Browse Source

* TUnzipper now instrumentable with events to be usable with custom streams
Patch from Andrew, Mantis 15151

git-svn-id: trunk@14256 -

marco 15 years ago
parent
commit
51d5d1ea3b
1 changed files with 34 additions and 21 deletions
  1. 34 21
      packages/paszlib/src/zipper.pp

+ 34 - 21
packages/paszlib/src/zipper.pp

@@ -362,6 +362,7 @@ Type
   end;
   end;
 
 
   TOnCustomStreamEvent = Procedure(Sender : TObject; var AStream : TStream; AItem : TFullZipFileEntry) of object;
   TOnCustomStreamEvent = Procedure(Sender : TObject; var AStream : TStream; AItem : TFullZipFileEntry) of object;
+  TCustomInputStreamEvent = Procedure(Sender: TObject; var AStream: TStream) of object;
 
 
   { TFullZipFileEntries }
   { TFullZipFileEntries }
 
 
@@ -377,15 +378,17 @@ Type
 
 
   TUnZipper = Class(TObject)
   TUnZipper = Class(TObject)
   Private
   Private
+    FOnCloseInputStream: TCustomInputStreamEvent;
     FOnCreateStream: TOnCustomStreamEvent;
     FOnCreateStream: TOnCustomStreamEvent;
     FOnDoneStream: TOnCustomStreamEvent;
     FOnDoneStream: TOnCustomStreamEvent;
+    FOnOpenInputStream: TCustomInputStreamEvent;
     FUnZipping  : Boolean;
     FUnZipping  : Boolean;
     FBufSize    : LongWord;
     FBufSize    : LongWord;
     FFileName   :  String;         { Name of resulting Zip file                 }
     FFileName   :  String;         { Name of resulting Zip file                 }
     FOutputPath : String;
     FOutputPath : String;
     FEntries    : TFullZipFileEntries;
     FEntries    : TFullZipFileEntries;
     FFiles      : TStrings;
     FFiles      : TStrings;
-    FZipFile     : TFileStream;     { I/O file variables                         }
+    FZipStream  : TStream;     { I/O file variables                         }
     LocalHdr    : Local_File_Header_Type;
     LocalHdr    : Local_File_Header_Type;
     CentralHdr  : Central_File_Header_Type;
     CentralHdr  : Central_File_Header_Type;
     EndHdr      : End_of_Central_Dir_Type;
     EndHdr      : End_of_Central_Dir_Type;
@@ -418,6 +421,8 @@ Type
     Procedure Examine;
     Procedure Examine;
   Public
   Public
     Property BufferSize : LongWord Read FBufSize Write SetBufSize;
     Property BufferSize : LongWord Read FBufSize Write SetBufSize;
+    Property OnOpenInputStream: TCustomInputStreamEvent read FOnOpenInputStream write FOnOpenInputStream;
+    Property OnCloseInputStream: TCustomInputStreamEvent read FOnCloseInputStream write FOnCloseInputStream;
     Property OnCreateStream : TOnCustomStreamEvent Read FOnCreateStream Write FOnCreateStream;
     Property OnCreateStream : TOnCustomStreamEvent Read FOnCreateStream Write FOnCreateStream;
     Property OnDoneStream : TOnCustomStreamEvent Read FOnDoneStream Write FOnDoneStream;
     Property OnDoneStream : TOnCustomStreamEvent Read FOnDoneStream Write FOnDoneStream;
     Property OnPercent : Integer Read FOnPercent Write FOnPercent;
     Property OnPercent : Integer Read FOnPercent Write FOnPercent;
@@ -444,6 +449,7 @@ ResourceString
   SErrMissingArchiveName = 'Missing archive filename in streamed entry %d';
   SErrMissingArchiveName = 'Missing archive filename in streamed entry %d';
   SErrFileDoesNotExist = 'File "%s" does not exist.';
   SErrFileDoesNotExist = 'File "%s" does not exist.';
   SErrNoFileName = 'No archive filename for examine operation.';
   SErrNoFileName = 'No archive filename for examine operation.';
+  SErrNoStream = 'No stream is opened.';
 
 
 { ---------------------------------------------------------------------
 { ---------------------------------------------------------------------
     Auxiliary
     Auxiliary
@@ -1498,7 +1504,10 @@ end;
 Procedure TUnZipper.OpenInput;
 Procedure TUnZipper.OpenInput;
 
 
 Begin
 Begin
-  FZipFile:=TFileStream.Create(FFileName,fmOpenRead);
+  if Assigned(FOnOpenInputStream) then
+    FOnOpenInputStream(Self, FZipStream);
+  if FZipStream = nil then
+    FZipStream:=TFileStream.Create(FFileName,fmOpenRead);
 End;
 End;
 
 
 
 
@@ -1549,7 +1558,9 @@ end;
 Procedure TUnZipper.CloseInput;
 Procedure TUnZipper.CloseInput;
 
 
 Begin
 Begin
-  FreeAndNil(FZipFile);
+  if Assigned(FOnCloseInputStream) then
+    FOnCloseInputStream(Self, FZipStream);
+  FreeAndNil(FZipStream);
 end;
 end;
 
 
 
 
@@ -1558,18 +1569,18 @@ Var
   S : String;
   S : String;
   D : TDateTime;
   D : TDateTime;
 Begin
 Begin
-  FZipFile.Seek(Item.HdrPos,soFromBeginning);
-  FZipFile.ReadBuffer(LocalHdr,SizeOf(LocalHdr));
+  FZipStream.Seek(Item.HdrPos,soFromBeginning);
+  FZipStream.ReadBuffer(LocalHdr,SizeOf(LocalHdr));
 {$IFDEF FPC_BIG_ENDIAN}
 {$IFDEF FPC_BIG_ENDIAN}
   LocalHdr := SwapLFH(LocalHdr);
   LocalHdr := SwapLFH(LocalHdr);
 {$ENDIF}
 {$ENDIF}
   With LocalHdr do
   With LocalHdr do
     begin
     begin
       SetLength(S,Filename_Length);
       SetLength(S,Filename_Length);
-      FZipFile.ReadBuffer(S[1],Filename_Length);
+      FZipStream.ReadBuffer(S[1],Filename_Length);
       //SetLength(E,Extra_Field_Length);
       //SetLength(E,Extra_Field_Length);
-      //FZipFile.ReadBuffer(E[1],Extra_Field_Length);
-      FZipFile.Seek(Extra_Field_Length,soCurrent);
+      //FZipStream.ReadBuffer(E[1],Extra_Field_Length);
+      FZipStream.Seek(Extra_Field_Length,soCurrent);
       Item.ArchiveFileName:=S;
       Item.ArchiveFileName:=S;
       Item.DiskFileName:=S;
       Item.DiskFileName:=S;
       Item.Size:=Uncompressed_Size;
       Item.Size:=Uncompressed_Size;
@@ -1592,36 +1603,36 @@ Var
   D : TDateTime;
   D : TDateTime;
   S : String;
   S : String;
 Begin
 Begin
-  EndHdrPos:=FZipFile.Size-SizeOf(EndHdr);
+  EndHdrPos:=FZipStream.Size-SizeOf(EndHdr);
   if EndHdrPos < 0 then
   if EndHdrPos < 0 then
-    raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
-  FZipFile.Seek(EndHdrPos,soFromBeginning);
-  FZipFile.ReadBuffer(EndHdr, SizeOf(EndHdr));
+    raise EZipError.CreateFmt(SErrCorruptZIP,[FileName]);
+  FZipStream.Seek(EndHdrPos,soFromBeginning);
+  FZipStream.ReadBuffer(EndHdr, SizeOf(EndHdr));
 {$IFDEF FPC_BIG_ENDIAN}
 {$IFDEF FPC_BIG_ENDIAN}
   EndHdr := SwapECD(EndHdr);
   EndHdr := SwapECD(EndHdr);
 {$ENDIF}
 {$ENDIF}
   With EndHdr do
   With EndHdr do
     begin
     begin
     if Signature <> END_OF_CENTRAL_DIR_SIGNATURE then
     if Signature <> END_OF_CENTRAL_DIR_SIGNATURE then
-      raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
+      raise EZipError.CreateFmt(SErrCorruptZIP,[FileName]);
     CenDirPos:=Start_Disk_Offset;
     CenDirPos:=Start_Disk_Offset;
     end;
     end;
-  FZipFile.Seek(CenDirPos,soFrombeginning);
+  FZipStream.Seek(CenDirPos,soFrombeginning);
   FEntries.Clear;
   FEntries.Clear;
   for i:=0 to EndHdr.Entries_This_Disk-1 do
   for i:=0 to EndHdr.Entries_This_Disk-1 do
     begin
     begin
-    FZipFile.ReadBuffer(CentralHdr, SizeOf(CentralHdr));
+    FZipStream.ReadBuffer(CentralHdr, SizeOf(CentralHdr));
 {$IFDEF FPC_BIG_ENDIAN}
 {$IFDEF FPC_BIG_ENDIAN}
     CentralHdr := SwapCFH(CentralHdr);
     CentralHdr := SwapCFH(CentralHdr);
 {$ENDIF}
 {$ENDIF}
     With CentralHdr do
     With CentralHdr do
       begin
       begin
       if Signature<>CENTRAL_FILE_HEADER_SIGNATURE then
       if Signature<>CENTRAL_FILE_HEADER_SIGNATURE then
-        raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
+        raise EZipError.CreateFmt(SErrCorruptZIP,[FileName]);
       NewNode:=FEntries.Add as TFullZipFileEntry;
       NewNode:=FEntries.Add as TFullZipFileEntry;
       NewNode.HdrPos := Local_Header_Offset;
       NewNode.HdrPos := Local_Header_Offset;
       SetLength(S,Filename_Length);
       SetLength(S,Filename_Length);
-      FZipFile.ReadBuffer(S[1],Filename_Length);
+      FZipStream.ReadBuffer(S[1],Filename_Length);
       NewNode.ArchiveFileName:=S;
       NewNode.ArchiveFileName:=S;
       NewNode.Size:=Uncompressed_Size;
       NewNode.Size:=Uncompressed_Size;
       NewNode.FCompressedSize:=Compressed_Size;
       NewNode.FCompressedSize:=Compressed_Size;
@@ -1634,7 +1645,7 @@ Begin
         NewNode.Attributes := External_Attributes;
         NewNode.Attributes := External_Attributes;
       ZipDateTimeToDateTime(Last_Mod_Date,Last_Mod_Time,D);
       ZipDateTimeToDateTime(Last_Mod_Date,Last_Mod_Time,D);
       NewNode.DateTime:=D;
       NewNode.DateTime:=D;
-      FZipFile.Seek(Extra_Field_Length+File_Comment_Length,soCurrent);
+      FZipStream.Seek(Extra_Field_Length+File_Comment_Length,soCurrent);
       end;
       end;
    end;
    end;
 end;
 end;
@@ -1667,14 +1678,14 @@ Var
     begin
     begin
       if (LocalHdr.Compressed_Size<>0) then
       if (LocalHdr.Compressed_Size<>0) then
         begin
         begin
-          Count:=Dest.CopyFrom(FZipFile,LocalHdr.Compressed_Size)
+          Count:=Dest.CopyFrom(FZipStream,LocalHdr.Compressed_Size)
          {$warning TODO: Implement CRC Check}
          {$warning TODO: Implement CRC Check}
         end
         end
       else
       else
         Count:=0;
         Count:=0;
     end
     end
     else
     else
-    With CreateDecompressor(Item, ZMethod, FZipFile, Dest) do
+    With CreateDecompressor(Item, ZMethod, FZipStream, Dest) do
       Try
       Try
         OnProgress:=Self.OnProgress;
         OnProgress:=Self.OnProgress;
         OnPercent:=Self.OnPercent;
         OnPercent:=Self.OnPercent;
@@ -1883,9 +1894,11 @@ end;
 
 
 procedure TUnZipper.Examine;
 procedure TUnZipper.Examine;
 begin
 begin
-  If (FFileName='') then
+  if (FOnOpenInputStream = nil) and (FFileName='') then
     Raise EZipError.Create(SErrNoFileName);
     Raise EZipError.Create(SErrNoFileName);
   OpenInput;
   OpenInput;
+  If (FZipStream=nil) then
+    Raise EZipError.Create(SErrNoStream);
   Try
   Try
     ReadZipDirectory;
     ReadZipDirectory;
   Finally
   Finally