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