home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 19
/
CD_ASCQ_19_010295.iso
/
dos
/
prg
/
pas
/
ktools
/
source
/
ofzip.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-09-17
|
8KB
|
291 lines
Unit OFZip;
{ lecture du contenu d'un fichier ZIP }
{ Kostrzewa Bruno }
{ juin 1994 }
INTERFACE
Uses Dos,
OBinFile,
OTableau;
Const
EndDirSign=$06054B50 ; { fin du répertoire des fichiers }
FileDirSign=$02014B50 ; { entête des fichiers dans le répertoire }
tab_method:Array[0..6] of string[8] =
('Stored','Shrunk','Reduc.1','Reduc.2','Reduc.3','Reduc.4','Imploded');
mois:Array[1..12] of string[3] =
('Jan','Fev','Mar','Avr','Mai','Jun','Jul','Aou','Sep','Oct','Nov','Dec');
erFile = $100;
erNotZip = $101;
erDisks = $102;
erFatale = $103;
Type
TEndDirDesc=record
sign :longint; { signature fin rép }
nmr_disk :word; { numéro du disque }
nmr_disk_dir:word; { disque contenant début rép }
nb_file_disk:word; { nbre de fichier sur ce disque }
total_file :word; { nbre total de fichiers dans rép }
size_dir :longint; { taille du rép }
start_dir :longint; { offset début rép sur son disque }
comment_len :word; { longueur du commentaire }
end;
TFileDirDesc=record
sign :longint; { signature entête des fichiers }
version :word; { version du logiciel de compression }
version_extract:word; { version pour extraire le fichier }
bit_flag :word; { drapeaux }
method :word; { méthode de compression }
time_date :longint; { date et heure de modification }
crc_32 :longint; { cyclic redundancy check 32 bits du fichier }
comp_size :longint; { taille fichier compressé }
uncomp_size :longint; { taille fichier décompressé }
filenamelen :word; { longueur du nom de fichier }
extrafieldlen:word; { longueur extra_field }
filecomlen :word; { longueur du commentaire du fichier }
disk_nmr :word; { numéro du disque contenant le fichier }
int_attr :word; { attribut fichier interne }
ext_attr :longint; { attribut fichier externe }
start_header:longint; { offset début entête du fichier sur son disque }
end;
PString=^String;
PFileZipDatas=^TFileZipDatas;
TFileZipDatas=record
FileDir:TFileDirDesc;
FName:PString;
FComment:PString;
End;
PZipTab=^TZipTab;
TZipTab=object(TTabPtr)
TailleDecomp:Real;
Constructor Init(NomFichier:PathStr);
Function GetErrorMsg:String; virtual;
Procedure Effacer(P: Pointer); virtual;
Function GetRec(n:Integer):PFileZipDatas;
end;
{ fonctions utilitaires }
Function Longueur(R:TFileZipDatas):String;
Function Methode(R:TFileZipDatas):String;
Function Taille(R:TFileZipDatas):String;
Function Ratio(R:TFileZipDatas):String;
Function ZDate(R:TFileZipDatas):String;
Function ZHeure(R:TFileZipDatas):String;
Function CRC32(R:TFileZipDatas):String;
Function ZNom(R:TFileZipDatas):String;
IMPLEMENTATION
Function hexa(nbr:longint;long:integer):string;
{ conversion d'un nombre en hexadécimal }
Const hexa_tab:array[0..15] of char =
('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
Var i:byte;
Begin
if long=0 then long:=trunc(ln(nbr)/ln(16))+1;
hexa[0]:=char(long);
for i:=0 to long-1 do
hexa[long-i]:=hexa_tab[(nbr shr (4*i)) and $000F];
End;
Function deci(nbr:longint;long:byte;with0:boolean):string;
{ écriture d'un entier sur long chiffres }
Var i:byte;
d:string;
Begin
if long=0 then long:=trunc(ln(nbr)/ln(10))+1;
d[0]:=char(long);
str(nbr:long,d);
for i:=1 to long do
if (d[i]=' ') and with0 then d[i]:='0';
deci:=d;
End;
Procedure DisposeStr(P:PString);
Var l:Byte;
Begin
l:=ord(P^[0]);
freemem(P,l+1);
End;
Function NewStr(S:String):PString;
Var P:PString;
Begin
GetMem(P,length(S)+1);
P^:=S;
NewStr:=P;
End;
{ Objet TZipTab }
Constructor TZipTab.Init(NomFichier:PathStr);
Var f:PBinFile;
i,p:LongInt;
S:String;
EndDir:TEndDirDesc;
fdatas:PFileZipDatas;
Begin
TTabPtr.Init(20,20);
TailleDecomp:=0;
f:=New(PBinFile,Init(NomFichier,8*1024));
if not f^.IsValid
then begin
ErrorFlag:=erFile;
exit;
end;
{ Recherche fin du répertoire des fichiers à partir de la fin }
p:=f^.datafilesize+1;
repeat
dec(p);
with f^ do
begin
setfileposit(p-sizeof(EndDir));
readvar(EndDir,sizeof(EndDir));
end;
until (EndDir.sign=EndDirSign) or (p=sizeof(EndDir));
if p=sizeof(EndDir)
then begin
ErrorFlag:=erNotZip;
exit;
end;
if EndDir.nmr_disk<>0
then begin
ErrorFlag:=erDisks;
exit;
end;
{ lecture des données }
f^.setfileposit(EndDir.start_dir);
for i:=1 to EndDir.total_file do
begin
new(fdatas);
fdatas^.fname:=nil;
fdatas^.fcomment:=nil;
f^.readvar(fdatas^.FileDir,sizeof(TFileDirDesc));
Ajouter(fdatas);
with fdatas^ do
begin
{ vérification signature }
if FileDir.sign<>FileDirSign
then begin
ErrorFlag:=erFatale;
exit;
end
else begin
{ mise à jour taille totale }
TailleDecomp:=TailleDecomp+FileDir.uncomp_size;
{ nom du fichier }
f^.readvar(s[1],FileDir.filenamelen);
s[0]:=chr(FileDir.filenamelen);
fname:=newstr(s);
{ commentaire fichier }
f^.setfileposit(f^.getfileposit+FileDir.extrafieldlen);
if FileDir.filecomlen<>0
then begin
f^.readvar(s[1],FileDir.filecomlen);
s[0]:=chr(FileDir.filecomlen);
fcomment:=newstr(s);
end;
end;
end; {with}
end; {for}
dispose(f,done);
End;
Function TZipTab.GetErrorMsg:String;
Begin
case ErrorFlag of
erFile : GetErrorMsg:='Ouverture du fichier impossible.';
erNotZip : GetErrorMsg:='Format du fichier non reconnu.';
erDisks : GetErrorMsg:='Les fichiers sont sur plusieurs disques.';
erFatale : GetErrorMsg:='Erreur fatale dans le fichier ZIP.';
else GetErrorMsg:=TTabPtr.GetErrorMsg;
end;
End;
Procedure TZipTab.Effacer(P:Pointer);
Var w:PFileZipDatas;
Begin
w:=PFileZipDatas(p);
with w^ do
begin
if fname<>nil then disposestr(fname);
if fcomment<>nil then disposestr(fcomment);
end;
Dispose(w);
End;
Function TZipTab.GetRec(n:Integer):PFileZipDatas;
Var P:PFileZipDatas;
Begin
if (n<1) or (n>NombreItems)
then P:=nil
else Lire(P,n);
GetRec:=P;
End;
Function Longueur(R:TFileZipDatas):String;
Begin
Longueur:=deci(R.FileDir.uncomp_size,8,false);
End;
Function Methode(R:TFileZipDatas):String;
Begin
Methode:=Tab_Method[R.FileDir.method];
End;
Function Taille(R:TFileZipDatas):String;
Begin
Taille:=deci(R.FileDir.comp_size,9,false);
End;
Function Ratio(R:TFileZipDatas):String;
Begin
Ratio:=deci(100-R.FileDir.comp_size*100 div R.FileDir.uncomp_size,
4,false)+'%';
End;
Function ZDate(R:TFileZipDatas):String;
Var t:DateTime;
Begin
UnPackTime(R.FileDir.time_date,t);
ZDate:=deci(t.day,2,true)+' '+mois[t.month]+' '+deci(t.year,4,true);
End;
Function ZHeure(R:TFileZipDatas):String;
Var t:DateTime;
Begin
UnPackTime(R.FileDir.time_date,t);
ZHeure:=deci(t.hour,2,true)+':'+deci(t.min,2,true)+':'+deci(t.sec,2,true);
End;
Function CRC32(R:TFileZipDatas):String;
Begin
CRC32:=hexa(R.FileDir.crc_32,8);
End;
Function ZNom(R:TFileZipDatas):String;
Var fd:DirStr;
fn:NameStr;
fe:ExtStr;
Begin
fsplit(R.fname^,fd,fn,fe);
fd:=fn+fe;
while length(fd)<12 do fd:=fd+' ';
ZNom:=fd;
End;
END.
{ Fin du fichier OFZip.Pas }