[Back to ARCHIVES SWAG index] [Back to Main SWAG index] [Original]

    {
    > Does anyone know where I can obtain source for reading a ZIP
    > file.  I know I could just shell and execute PKUNZIP, but the
    > looks horrible. 8-) I would like to do it as transparently as
    > possible (and without shelling :)  TIA!
    }
    Type      ZFHeader=Record
                         Signature                         :longint;
                         Version,GPBFlag,Compress,Date,Time:word;
                         CRC32,CSize,USize                 :longint;
                         FNameLen,ExtraField               :word;
                       end;

    type      PZipArchive=^TZipArchive;
              TZipArchive=object(TGeneralArchive)
                            constructor Init;
                            procedure FindFirst(var sr:SearchRec);virtual;
                            procedure FindNext(var sr:SearchRec);virtual;
                          private
                            Hdr:ZFHeader;
                            function  GetHeader(var sr:SearchRec):string;
                          end;

    implementation

    uses      Objects,OOAVUtil;

    Const     SIG = $04034B50;                  { Signature }

    constructor TZipArchive.Init;
    begin
      FillChar(Hdr,sizeof(Hdr),0);
    end;

    function  TZipArchive.GetHeader(var sr:SearchRec):string;
    var       b:byte;
              FName:string;
    begin
      fillchar(sr,sizeof(sr),0);
      if _FArchive^.GetPos=_FArchive^.GetSize then
        exit;
      _Farchive^.Read(Hdr,SizeOf(Hdr));
      if _FArchive^.Status<>stOk then
        exit;
    { Why checking for Hdr.FNamelen=0?
      Because the comments inserted in a ZIP-file are at the last field }
      if Hdr.FNameLen=0 then
        exit;
      FName:='';
      Repeat
        _FArchive^.Read(b,1);
        If b<>0 Then
          FName:=FName+Chr(b);
      Until (length(FName)=Hdr.FNameLen) or (b=0);
      if b=0 then
      begin
        GetHeader:='';
        exit;
      end;
      _FArchive^.Seek(_FArchive^.GetPos+Hdr.CSize+Hdr.ExtraField);
      sr.Size:=Hdr.USize;
      sr.Time:=Hdr.Date+Hdr.Time*longint(256*256);
      GetHeader:=FName;
    end;

    procedure TZipArchive.FindFirst(var sr:SearchRec);
    var       FName:string;
              found:boolean;
    begin
      found:=false;
      repeat
        FName:=GetHeader(sr);
        if FName='' then
        begin
          found:=true;
          sr.Name:='';
        end;
        while pos('/',FName)<>0 do
          FName[pos('/',FName)]:='\';
        if Fits(FName,_SearchDir+_SearchFile) then
        begin
          sr.Name:=copy(FName,length(_SearchDir)+1,12);
          found:=true;
        end;
      until found;
    end;

    procedure TZipArchive.FindNext(var sr:SearchRec);
    var       FName:string;
              found:boolean;
    begin
      found:=false;
      repeat
        FName:=GetHeader(sr);
        if FName='' then
        begin
          found:=true;
          sr.Name:='';
        end;
        while pos('/',FName)<>0 do
          FName[pos('/',FName)]:='\';
        if Fits(FName,_SearchDir+_SearchFile) then
        begin
          sr.Name:=copy(FName,length(_SearchDir)+1,12);
          found:=true;
        end;
      until found;
    end;

[Back to ARCHIVES SWAG index] [Back to Main SWAG index] [Original]