Contributor: CAMERON CLARK
{
The following code is a cheezy way to read the structures that exist in a
zip file. it does not compress or decompress; it just reads the file
information included in the file. It is not finished and has a bug that has
been compensated for.
Enjoy -some code is not my own, i.e. the structures themselves.
}
USES dos; {Structure signatures}
CONST LOCAL = $04034B50; CENTRAL = $02014B50;END_OF = $06054B50;
{THE following three structures are found in the zip file }
{A signature WILL tell you WHICH follows the signature in the file}
TYPE ZLOCALtype = record { Zip File Header }
VerReqd : Word; { ..Version reqd to unzip }
BitFlag : Word; { ..Bit Flag }
Method : Word; { ..Compress Method }
LModTime: Word; { ..Last Mod Time }
LModDate: Word; { ..Last Mod Date }
CRC32 : LongInt; { ..File CRC }
CmpSize : LongInt; { ..Compressed Size }
UncmpSz : LongInt; { ..Uncompressed Size }
FNLen : Word; { ..File Name Length }
EFLen : Word; { ..Extra Field Length }
end;
TYPE ZCENTRALtype = record { Zip File Header }
MadeBy : Word;
VerReqd : Word; { ..Version reqd to unzip }
BitFlag : Word; { ..Bit Flag
}
Method : Word; { ..Compress Method
}
LModTime: Word; { ..Last Mod Time }
LModDate: Word; { ..Last Mod Date }
CRC32 : LongInt; { ..File CRC }
CmpSize : LongInt; { ..Compressed Size }
UncmpSz : LongInt; { ..Uncompressed Size }
FNLen : Word; { ..File Name Length
}
EFLen : Word; { ..Extra Field Length
}
end;
zCENTRAL2type=record
DiskNo : Word; { ..Starting Disk Number }
IFAttr : Word; { ..Internal File Attributes}
EFAttr : LongInt; { ..External File Attributes}
LHOff : LongInt; { ..Offset of local header }
end;
zENDType = Record { Directory End Record }
DiskNo : Word; { ..Number of this disk
}
ZDDisk : Word; { ..Disk w/ start of dir }
ZDETD : Word; { ..Dir ents this disk
}
ZDEnts : Word; { ..Total dir ents }
ZDSize : LongInt; { ..Dir size }
ZDStart : LongInt; { ..Offset to start of Dir }
CmtLen : Word; { ..Zip Comment Length
}
end;
VAR zLOCAL : zLOCALtype;
zCENTRAL : zCENTRALtype;
zCENTRAL2: zCENTRAL2type;
zEND : zENDtype;
Fi : File;
FIlename:String[12];
temp : array[1..16] of char;
zSignature: longInt;
I : integer;
{$I files.inc} {for opening files easy}
{$I buffer.inc} {Using a full buffer and fake disk reads}
{Nice when you don't know what structure follows}
{Fill the buffer and move the info to the structure
that fits}
Function num2Hex(L : LongInt) : String;
CONST HexChar : Array [0..15] of Char = '0123456789ABCDEF';
VAR hexs : string;
tByte, I,J : byte;
start : boolean;
Begin
HexS:='';
HexS := HexChar[(L AND $F0000000) SHR 28] +
HexChar[(L AND $0F000000) SHR 24] +
HexChar[(L AND $00F00000) SHR 20] +
HexChar[(L AND $000F0000) SHR 16] +
HexChar[(L AND $0000F000) SHR 12] +
HexChar[(L AND $00000F00) SHR 8] +
HexChar[(L AND $000000F0) SHR 4] +
HexChar[(L AND $0000000F) ];
Start:=False; {init}
j:=0;
FOR I:=1 to 8 DO BEGIN {rid of leading zeros}
IF hexS[i]<>'0' then Start:=true;
IF start then BEGIN
Inc(j,1);
HexS[j]:=HexS[i];
END;
END;
move(j,hexS[0],1); {reset string to new size}
num2Hex:=HexS;
end; {HexLInt}
BEGIN {-====-}
{Open the file if it exists; else OpenFile returns FALSE}
IF not OpenFile(fi, paramStr(1)) then BEGIN
Writeln('File ', paramStr(1) ,' not found. Check syntax');
halt;
END;
BRead(Fi, Zsignature, 4); {Fills the buffer}
{Moves 4 bytes into zSignature}
IF (Zsignature<>LOCAL) and (zSignature<>CENTRAL) THEN BEGIN
Writeln('File ',ParamStr(1),' does not appear to be a ZIP file.');
HALT
END;
WHILE 1<>0 DO BEGIN
{Read the structure that fits the zSignature}
IF zSignature= LOCAL THEN BEGIN
Bread(fi,Zlocal,SizeOf(Zlocal) );
Writeln('LOCAL');
END;
IF zSignature= CENTRAL THEN BEGIN
Bread(fi,ZCentral,SizeOf(Zlocal) );
WriteLN('CENTRAL');
END;
IF zSignature= END_OF THEN BEGIN
Bread(fi,zEnd,SizeOf(zEnd) );
WriteLN('END');
END;
{ALL three have a signature}
{ Writeln('long test ',num2hex(981347578));}
Write('Pksignature: ');
write( ((Zsignature and $F0000000) shr 28) );
write(' ', ((Zsignature and $0F000000) shr 24) );
write(' ', ((Zsignature and $00F00000) shr 20) );
write(' ', ((Zsignature and $000F0000) shr 16) );
write(' ', ((Zsignature and $0000F000) shr 12) );
write(' ', ((Zsignature and $00000F00) shr 8) );
write(' ', ((Zsignature and $000000F0) shr 4) );
write(' ', ((Zsignature and $0000000F) ) );
writeln;
IF (zSignature=Local) THEN BEGIN
WITH zLOCAL DO BEGIN
Write('Version Required: ',(verReqd div 10),'.' );
writeln(VerReqd mod 10);
writelN('BitFlag [?]: ',(bitflag) );
WriteLN('Method Used: ',(method) );
WriteLN('Last mod Time: ',num2hex(LmodTime));
WriteLN('Last mod Date: ',num2hex(LmodDate));
WriteLN('CRC32: ',num2hex(Crc32)); {Correct}
Writeln('Compressed Size: ',CmpSize); {correct}
WriteLn('Original Size: ',UnCmpSz); {correct}
Writeln('File name Length: ',FNlen); {correct}
Writeln('Extra field Length: ',EFlen);
BRead(Fi,Filename[1],FNlen);
move (FNlen,FileName[0],1); {init the string length}
WriteLN('FileName: ',FileName); {correct}
Bskip(fi,CmpSize); {skip the actual zipped part}
END;
END;
IF (zSignature=CENTRAL) THEN BEGIN
WITH zCENTRAL DO BEGIN
Writeln('MAde by version : ',madeBy);
Write('Version Required: ',(verReqd div 10),'.' );
writeln(VerReqd mod 10);
writelN('BitFlag [?]: ',(bitflag) );
WriteLN('Method Used: ',(method) );
WriteLN('Last mod Time: ',num2hex(LmodTime));
WriteLN('Last mod Date: ',num2hex(LmodDate));
WriteLN('CRC32: ',num2hex(Crc32));
Writeln('Compressed Size: ',CmpSize);
WriteLn('Original Size: ',UnCmpSz);
Writeln('File name Length: ',FNlen);
Writeln('Extra field Length: ',EFlen);
END;
WITH zCENTRAL2 DO BEGIN
BSkip(fi,4); {There's blanks?? why?}
Bread(Fi,zCentral2,SizeOf(zCentral2));
Writeln('Starting Disk #: ',DiskNo);
WriteLN('Internal File Attr: ',IFAttr);
WriteLN('External File Attr: ',EFAttr);
Writeln('Local header offset: ',LHoff);
BRead(Fi,Filename[1],zCENTRAL.FNlen);
move (zCENTRAL.FNlen,FileName[0],1);
WriteLN('FileName: ',FileName);
END;
END;
IF (zSignature=END_OF) THEN BEGIN
WITH zEND DO BEGIN
WriteLN('Disk Number: ',DiskNo);
WriteLN('Start of directory: ',ZDDisk);
WriteLN('Total entries, disk: ',ZDETD);
WriteLN('Total Entries: ',ZDEnts);
WriteLN('Directory Size: ',ZDSize);
WriteLN('Directory Offset: ',ZDStart);
WriteLN('Zip Comment Length: ',CmtLen);
halt;
END;
END;
ReadLN;
Bread(fi,zSignature,4); {read next Zsignature}
END; {WHILE NOT EOF}
Close(fi);
END.
{ FILES.INC}
FUNCTION FileExists(FileName: String): Boolean;
VAR F: file;
begin
{$I-}
Assign(F, FileName);
Reset(F);
Close(F);
{$I+}
FileExists:=(IOResult = 0) and (FileName <> '')
end; { FileExists }
FUNCTION OpenFile(VAR f: file; fileName:string): Boolean;
BEGIN
IF fileExists(FileName) then BEGIN
Assign(f,filename);
Reset(f,1);
Openfile:=True;
END
ELSE OpenFile:=False;
END;
FUNCTION FileExistsWild(FileName: String): Boolean;
VAR Fil: SearchRec;
begin
FindFirst(FileName,anyFile,Fil);
FileExistsWild:=(DosError=0) and (FileName <> '');
end; { FileExists }
{BUFFER.INC}
CONST zBufSize=8192;
TYPE zBufferType = array[1..zBufSize] of byte;
VAR zBuffer: zBufferType;
zCurrent: integer;
nSeen : Word;
PROCEDURE READBUFFER(Var f:file;nRead, Position: integer);
BEGIN
IF zCurrent=0 then zCurrent:=1;
BlockRead(f,zBuffer[Position],nRead,nSeen);
END;
PROCEDURe bREAD(var f: file;var userObj; nRead: integer);
VAR temp:integer; {^^^^^^^^^^^what ever the user is using!}
BEGIN
IF zCurrent=0 then ReadBUFFER(F, ZBufsize ,1); {init the buffer}
IF zcurrent+nRead>zBufSize THEN BEGIN {Part Missing??}
Temp:=ZbufSize+1-zCurrent; {Size of whats left in
buffer}
{ Writeln('What is left in the buffer ',temp);}
move(zBuffer[zCurrent], zBuffer[1], Temp); {move unread to start}
ReadBUFFER(F, ZBufsize-(Temp) ,Temp); {total minus what's left}
zCurrent:=1; {at position end of temp}
move(zBuffer[zCurrent],userOBJ,nREAD);
END
else BEGIN
move(ZBuffer[zCurrent],UserOBJ,nREad);
zCurrent:=zCurrent+nRead;
END;
END;
PROCEDURe bSkip(var f: file; nRead: integer);
VAR temp:integer; {SKIPS A PART OF THE BUFFER}
BEGIN
IF zCurrent=0 then ReadBUFFER(F, ZBufsize ,1); {init the buffer}
IF nRead>zBufSize then BEGIN
Seek(f,FilePos(f)+nRead-(ZbufSize+1-zCurrent));
{Remeber there may still be bytes ALREADY read in the buffer}
{You need not skip what's already there}
{Just seek to position - already read}
zCurrent:=0;
END
ELSE
IF zcurrent+nRead>zBufSize THEN BEGIN {Part Missing??}
Temp:=ZbufSize+1-zCurrent; {Size of whats left in
buffer}
move(zBuffer[zCurrent], zBuffer[1], Temp); {move unread to start}
ReadBUFFER(F, ZBufsize-(Temp) ,Temp);{refill} {total minus what's left}
zCurrent:=1+temp; {at position end of temp}
END
ELSE zCurrent:=zCurrent+nRead;
END;