home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2002 March
/
Chip_2002-03_cd1.bin
/
zkuste
/
delphi
/
kompon
/
d5
/
cak
/
CAKDIR.ZIP
/
CakExt.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
2001-10-28
|
16KB
|
457 lines
// Common Archiver Kit Experiment(CAKE)
// Common Interface for Compression/Decompression components.
//Copyright (C) Joseph Leung 2001 (lycj@yahoo.com)
//
//This library is free software; you can redistribute it and/or
//modify it under the terms of the GNU Lesser General Public
//License as published by the Free Software Foundation; either
//version 2.1 of the License, or (at your option) any later version.
//
//This library is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public
//License along with this library; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//////////////////////////////////////////////////////////////////////
//////////// CAKExtension ////////////
//////////////////////////////////////////////////////////////////////
// ___________________________________________
// ___________________________________________|
// CakExt |
// lastupdate 10.28.2001 |
// hIsToRy - Check CakDir.pas |
// ___________________________________________|
//
// INFO - Use CAKE to support more archive via Dos archiver using Scripts!!
// You are suggested to use CAKE to call this component.
// (Although you can compile this alone)
//
// To use it...
// 1. Put a cakdir in ur form (Called cakDir1 in this case)
// 2. Put this line in Form OnShow(not onCreate!),
// so it will check the path for extensions.
// CakDir1.CakExtScriptPath := Cakdir1.GrabProgramPath + 'Extension\';
// You can then read what's supported using
// Cakdir1.treatasExt
// 3. When user load an archiver that required to use extension,
// it will do autmatically! (no other changes required to support extension)
//
unit CakExt;
interface
uses
Windows, SysUtils, Classes, Shellapi;
const SCRIPTEXT = '.INI';
SCRIPTFILTER = '*' + SCRIPTEXT;
MACRO = '%';
SPACE = ' ';
DOT = '.';
INFO = 'Info';
FEATURES = 'Features';
PATHS = 'Paths';
STRINGS = 'Strings';
PARAM = 'Param';
COMMANDS = 'Commands';
LIST = 'List';
ERROR = 'Error!';
type
WorktypeEx = (Ex_None, //Donothing
Ex_LoadContents, //List Archive
Ex_Extract, //Extract Archive
Ex_Test, //Test Archive
Ex_Add, //Add file to archive
Ex_Delete, //Delete file from archive
Ex_SFX //Create Self extractables
);
ExtractOptionstypeEx = record
extr_to : string;
extract_files : string;
end;
AddOptionstypeEx = record
add_files : string;
end;
DeleteOptionstypeEx = record
del_files : string;
end;
ContenttypeEx = record
_Filename,_FileArchive : String;
_FileSize,_FilePackedSize : integer;
_FileRatio : integer;
end;
TCakExt = class(TComponent)
private { Private declarations }
Supporttype : string;
ScriptPath : string;
Log : string;
batfilename : string;
protected { Protected declarations }
procedure runandwait(programpath,Programparam : string);
public { Public declarations }
DosOutput : TStrings;
ExtractOptionsEx : ExtractOptionstypeEx;
AddOptionsEx : AddOptionstypeEx;
DeleteOptionsEx : DeleteOptionstypeEx;
Total_Contents : integer;
Archive_Contents : array of ContenttypeEx;
function Supportactions(Archivetype : string; Action : worktypeEx) : boolean;
procedure RePollScriptDirectory;
procedure Process(Archivename : string; Action : worktypeEx);
function TranslateString(Inifilename, Macroname, Archivename : string; var Executename : string) : string;
constructor Create( AOwner: TComponent ); override;
destructor Destroy; override;
published
property ScriptDirectory : string read ScriptPath write ScriptPath;
property Supportformats : string read Supporttype write Supporttype;
property Logfile : string read log write log;
property Batchfilename : string read batfilename;
{ Published declarations }
end;
procedure Register;
implementation
uses ConsoleApp, Inifiles;
/////////////////////////////////////////////////////////////////////////
//////////// CAKE's functions ////////////
/////////////////////////////////////////////////////////////////////////
function GetStringInIni(filename : string; section : string; key : string; default : string) : string;
var Ini : TInifile;
begin
Ini := TIniFile.Create(filename);
try
with Ini do
result := ReadString(section,key,'');
finally
Ini.Free;
end;
if result = '' then result := default;
end;
function GetIntegerInIni(filename : string; section : string; key : string; default : integer) : integer;
var Ini : TInifile;
begin
Ini := TIniFile.Create(filename);
try
with Ini do
result := ReadInteger(section,key,default);
finally
Ini.Free;
end;
//if result = then result := default;
end;
function AppendSlash(input : string) : string;
begin
if length(input) > 0 then
if input[Length(input)] = '\' then
result := input else
result := input + '\' else
result := input;
end;
function Removefileext(input : string) : string;
var
I: Integer;
begin
I := LastDelimiter('.\:', input);
if (I > 0) and (input[I] = '.') then
Result := Copy(input, 0, i-1) else
Result := input;
end;
procedure TCakExt.runandwait(programpath,Programparam : string);
Var
exInfo: TShellExecuteInfo;
exitcode: DWORD;
Begin
FillChar( exInfo, Sizeof(exInfo), 0 );
With exInfo Do Begin
cbSize:= Sizeof( exInfo ); // required!
fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
Wnd := 0;
lpVerb:= 'open';
lpFile:= Pchar( programpath );
lpParameters := Pchar( Programparam);
nShow := SW_NORMAL;
End;
If ShellExecuteEx( @exInfo ) Then Begin
While GetExitCodeProcess( exinfo.hProcess, exitcode )
and (exitcode = STILL_ACTIVE)
Do
Sleep( 500 );
CloseHandle( exinfo.hProcess );
End
end;
/////////////////////////////////////////////////////////////////////////
constructor TCakExt.Create( AOwner: TComponent );
begin
inherited Create( AOwner );
DosOutput := TStringList.create();
log := 'c:\Cake.log'; //if not specified...hungry?
batfilename := 'c:\run.bat';
end;
destructor TCakExt.Destroy;
begin
DosOutput.free;
inherited Destroy;
end;
/////////////////////////////////////////////////////////////////////////
procedure TCakExt.Process(Archivename : string; Action : worktypeEx);
var Archivetype : string;
File2Run, Param : string;
IniFilename : string;
ExitCode : integer;
mode : integer;
k : string;
function Calculatesize(sizestring : string) : integer;
var i : integer;
k,l : string;
begin
k := '';
l := TrimRight(TrimLeft(sizestring));
for i := 0 to length(l) do
if strtointdef(l[i],-1) <> -1 then
k := k + l[i];
result := strtointdef(k,0);
end;
procedure Loadfilelist;
var i : integer;
linestart,linestop : integer;
filenamestart, filenamestop : integer;
filesizestart, filesizestop : integer;
filepackedsizestart, filepackedsizestop : integer;
begin
linestart := GetIntegerInINI(Inifilename,LIST,'LINESTART',-1);
linestop := GetIntegerInINI(Inifilename,LIST,'LINESTOP',-1);
filenamestart := GetIntegerInINI(Inifilename,LIST,'FILENAME-START',-1);
filenamestop := GetIntegerInINI(Inifilename,LIST,'FILENAME-STOP',-1);
filesizestart := GetIntegerInINI(Inifilename,LIST,'FILESIZE-START',-1);
filesizestop := GetIntegerInINI(Inifilename,LIST,'FILESIZE-STOP',-1);
filepackedsizestart := GetIntegerInINI(Inifilename,LIST,'FILEPACKEDSIZE-START',-1);
filepackedsizestop := GetIntegerInINI(Inifilename,LIST,'FILEPACKEDSIZE-STOP',-1);
Total_Contents := Dosoutput.Count + linestop - linestart;
if Total_Contents > 0 then
begin
SetLength(Archive_Contents,Total_Contents);
for i := linestart to Dosoutput.Count + linestop - 1 do
with Archive_Contents[i - linestart] do
begin
if (filenamestart <> filenamestop) then
_Filename := TrimRight(TrimLeft(Copy(Dosoutput.strings[i],filenamestart,filenamestop-filenamestart)));
if (filesizestart <> filesizestop) then
_FileSize := calculatesize(Copy(Dosoutput.strings[i],filesizestart,filesizestop-filesizestart));
if (filepackedsizestart <> filepackedsizestop) then
_FilePackedSize := calculatesize(Copy(Dosoutput.strings[i],filepackedsizestart,filepackedsizestop-filepackedsizestart));
_FileRatio := 100;
if _FileSize > 0 then
_FileRatio := Trunc(_FilePackedSize / _FileSize * 100);
_FileArchive := Archivename;
end;
end;
end;
procedure MakeBatch(batfilename,file2run : string);
var tf : textfile;
begin
Assignfile(tf,batfilename);
Rewrite(tf);
Writeln(tf,'@'+file2run);
Writeln(tf,'@'+'Exit');
Closefile(tf);
end;
begin
Archivetype := Extractfileext(Archivename);
Archivetype := Copy(Archivetype,2,Length(Archivetype)-1);
Inifilename := Appendslash(ScriptPath) + Archivetype + SCRIPTEXT;
DosOutput.Clear;
if not SupportActions(Archivetype,Action) then exit;
Case Action of
Ex_LoadContents : Param := TranslateString(IniFilename,'LIST',Archivename,File2Run);
Ex_Extract : Param := TranslateString(IniFilename,'EXTRACT',Archivename,File2Run);
Ex_Test : Param := TranslateString(IniFilename,'TEST',Archivename,File2Run);
Ex_Add : Param := TranslateString(IniFilename,'ADD',Archivename,File2Run);
Ex_SFX : Param := TranslateString(IniFilename,'SFX',Archivename,File2Run);
Ex_Delete : Param := TranslateString(IniFilename,'DELETE',Archivename,File2Run);
end;
mode := GetIntegerInINI(IniFilename,COMMANDS,'MODE',0);
if fileexists(File2Run) and (File2Run <> '') then
begin
Case mode of
0 : ExitCode:= ExecConsoleApp(File2Run,Param,DosOutput,nil);
1 : begin
MakeBatch(Batfilename,File2run + SPACE + Param + ' >' + log);
RunAndWait(Batfilename,'');
if fileexists(log) then
DosOutput.LoadFromFile(log);
exitCode := 0;
end;
else
ExitCode := -1;
end;
Case Action of
Ex_LoadContents : Loadfilelist;
end;
end else
begin
ExitCode:= -1;
k := GetStringInINI(IniFilename,INFO,'DOWNLOAD','<none>');
MessageBox(0,
pchar('Cannot found executable specified in Extension script' + #13 + 'D/L Info > ' + k),
pchar('Not found!'),
0);
end;
DosOutput.Add('Exitcode = ' + Inttostr(Exitcode))
end;
function TCakExt.Supportactions(Archivetype : string; Action : worktypeEx) : boolean;
var IniFilename,atype : string;
begin
if Archivetype = '' then
begin
Result := false;
exit;
end;
if Archivetype[1] = '.' then
atype := copy(archivetype,2,length(archivetype)-1) else
atype := archivetype;
Inifilename := Appendslash(ScriptPath) + Atype + SCRIPTEXT;
Case Action of
Ex_None : Result := false;
Ex_LoadContents : result := (GetIntegerInIni(inifilename, FEATURES, 'LIST',0) = 1);
Ex_Extract : result := (GetIntegerInIni(inifilename, FEATURES, 'EXTRACT',0) = 1);
Ex_Test : result := (GetIntegerInIni(inifilename, FEATURES, 'TEST',0) = 1);
Ex_Add : result := (GetIntegerInIni(inifilename, FEATURES, 'ADD',0) = 1);
Ex_Delete : result := (GetIntegerInIni(inifilename, FEATURES, 'DELETE',0) = 1);
Ex_SFX : result := (GetIntegerInIni(inifilename, FEATURES, 'SFX',0) = 1);
else result := false;
end;
end;
function TCakExt.TranslateString(Inifilename, Macroname, Archivename : string; var Executename : string) : string;
var k,l : string;
i,j : integer;
Newmacro : string;
function Locatemacro(Macroname : string) : string;
var k : string;
begin
k := '';
if (Macroname = 'ADD') or (Macroname = 'EXTRACT') or
(Macroname = 'LIST') or (Macroname = 'TEST') or
(Macroname = 'DELETE') or (Macroname = 'SFX') then
k := GetStringInIni(Inifilename,COMMANDS,Macroname,'') else
if (Macroname = 'EXEPATH') or (Macroname = 'UNEXEPATH') then
k := GetStringInIni(Inifilename,PATHS,Macroname,'') else
if (Macroname = 'ARCHIVE-NAME') then
k := Removefileext(Archivename) else
if (Macroname = 'ARCHIVE-EXT') then
k := Extractfileext(Archivename) else
if (Macroname = 'ADDFILE') or (Macroname = 'FILE2ADD') then
k := AddOptionsEx.add_files else
if (Macroname = 'EXTRACTTO') then
k := ExtractOptionsEx.extr_to else
if (Macroname = 'FILE2EXTR') then
k := ExtractOptionsEx.extract_files else
if (Macroname = 'FILE2DEL') then
k := DeleteOptionsEx.del_files else
k := GetStringInIni(Inifilename,STRINGS,Macroname,'');
result := k;
end;
procedure Translate;
begin
NewMacro := Copy(k,i+1,j-i-1);
if (NewMacro = 'EXEPATH') or (NewMacro = 'UNEXEPATH') then
begin
Executename := LocateMacro(NewMacro);
l := '';
end else
l := LocateMacro(NewMacro);
k := Copy(k,0,i-1) + l + Copy(k,j+1,length(k) - j);
end;
procedure Looptranslate;
begin
i := pos(MACRO,k);
while i <> 0 do
begin
j := i + 1;
while (k[j] <> MACRO) and (j < length(k)) do
Inc(j);
if k[j] <> MACRO then
begin
result := ERROR;
exit;
end
else
Translate;
i := pos(MACRO,k);
end;
end;
begin
k := LocateMacro(Macroname);
looptranslate;
result := k;
end;
procedure TCakExt.RePollScriptDirectory;
var sr: TSearchRec;
k: string;
FileAttrs : integer;
begin
k := Appendslash(Scriptpath) + SCRIPTFILTER;
FileAttrs := 0;
FileAttrs := FileAttrs + faAnyFile;
supporttype := '';
if FindFirst(k , FileAttrs, sr) = 0 then
begin
supporttype := supporttype + SPACE + DOT + Removefileext(sr.name);
while (FindNext(sr) = 0) do
supporttype := supporttype + SPACE + DOT + Removefileext(sr.name);
end;
FindClose(sr);
end;
procedure Register;
begin
RegisterComponents('Qzip', [TCakExt]);
end;
end.