mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-03 13:30:55 +02:00
* Added possibility to set filename in archive, and added possibility to use streams
git-svn-id: trunk@11833 -
This commit is contained in:
parent
50012c2357
commit
7e5340c07c
@ -119,14 +119,6 @@ Const
|
||||
|
||||
Type
|
||||
|
||||
TZipItem = Class(TObject)
|
||||
Path : String;
|
||||
Name : String;
|
||||
Size : LongInt;
|
||||
DateTime : TDateTime;
|
||||
HdrPos : Longint;
|
||||
end;
|
||||
|
||||
TProgressEvent = Procedure(Sender : TObject; Const Pct : Double) of object;
|
||||
TOnEndOfFileEvent = Procedure(Sender : TObject; Const Ratio : Double) of object;
|
||||
TOnStartFileEvent = Procedure(Sender : TObject; Const AFileName : String) of object;
|
||||
@ -260,17 +252,54 @@ Type
|
||||
Class Function ZipID : Word; override;
|
||||
end;
|
||||
|
||||
{ TZipFileEntry }
|
||||
|
||||
TZipFileEntry = Class(TCollectionItem)
|
||||
private
|
||||
FArchiveFileName: String;
|
||||
FDateTime: TDateTime;
|
||||
FDiskFileName: String;
|
||||
FHeaderPos: Longint;
|
||||
FSize: Integer;
|
||||
FStream: TStream;
|
||||
function GetArchiveFileName: String;
|
||||
Protected
|
||||
Property HdrPos : Longint Read FHeaderPos Write FheaderPos;
|
||||
Public
|
||||
Property Stream : TStream Read FStream Write FStream;
|
||||
Published
|
||||
Property ArchiveFileName : String Read GetArchiveFileName Write FArchiveFileName;
|
||||
Property DiskFileName : String Read FDiskFileName Write FDiskFileName;
|
||||
Property Size : Integer Read FSize Write FSize;
|
||||
Property DateTime : TDateTime Read FDateTime Write FDateTime;
|
||||
end;
|
||||
|
||||
{ TZipFileEntries }
|
||||
|
||||
TZipFileEntries = Class(TCollection)
|
||||
private
|
||||
function GetZ(AIndex : Integer): TZipFileEntry;
|
||||
procedure SetZ(AIndex : Integer; const AValue: TZipFileEntry);
|
||||
Public
|
||||
Function AddFileEntry(Const ADiskFileName : String): TZipFileEntry;
|
||||
Function AddFileEntry(Const ADiskFileName, AArchiveFileName : String): TZipFileEntry;
|
||||
Function AddFileEntry(Const AStream : TSTream; Const AArchiveFileName : String): TZipFileEntry;
|
||||
Property Entries[AIndex : Integer] : TZipFileEntry Read GetZ Write SetZ; default;
|
||||
end;
|
||||
|
||||
|
||||
{ TZipper }
|
||||
|
||||
TZipper = Class(TObject)
|
||||
Private
|
||||
FEntries: TZipFileEntries;
|
||||
FZipping : Boolean;
|
||||
FBufSize : LongWord;
|
||||
FFileName : String; { Name of resulting Zip file }
|
||||
FFiles : TStrings;
|
||||
FInMemSize : Integer;
|
||||
FOutFile : TFileStream;
|
||||
FInFile : TFileStream; { I/O file variables }
|
||||
FInFile : TStream; { I/O file variables }
|
||||
LocalHdr : Local_File_Header_Type;
|
||||
CentralHdr : Central_File_Header_Type;
|
||||
EndHdr : End_of_Central_Dir_Type;
|
||||
@ -278,25 +307,28 @@ Type
|
||||
FOnProgress : TProgressEvent;
|
||||
FOnEndOfFile : TOnEndOfFileEvent;
|
||||
FOnStartFile : TOnStartFileEvent;
|
||||
function CheckEntries: Integer;
|
||||
procedure SetEntries(const AValue: TZipFileEntries);
|
||||
Protected
|
||||
Procedure OpenOutput;
|
||||
Procedure CloseOutput;
|
||||
Procedure CloseInput;
|
||||
Procedure StartZipFile(Item : TZipItem);
|
||||
Function UpdateZipHeader(Item : TZipItem; FZip : TStream; ACRC : LongWord;AMethod : Word) : Boolean;
|
||||
Procedure CloseInput(Item : TZipFileEntry);
|
||||
Procedure StartZipFile(Item : TZipFileEntry);
|
||||
Function UpdateZipHeader(Item : TZipFileEntry; FZip : TStream; ACRC : LongWord;AMethod : Word) : Boolean;
|
||||
Procedure BuildZipDirectory;
|
||||
Procedure DoEndOfFile;
|
||||
Procedure ZipOneFile(Item : TZipItem); virtual;
|
||||
Function OpenInput(InFileName : String) : Boolean;
|
||||
Procedure ZipOneFile(Item : TZipFileEntry); virtual;
|
||||
Function OpenInput(Item : TZipFileEntry) : Boolean;
|
||||
Procedure GetFileInfo;
|
||||
Procedure SetBufSize(Value : LongWord);
|
||||
Procedure SetFileName(Value : String);
|
||||
Function CreateCompressor(Item : TZipItem; AinFile,AZipStream : TStream) : TCompressor; virtual;
|
||||
Function CreateCompressor(Item : TZipFileEntry; AinFile,AZipStream : TStream) : TCompressor; virtual;
|
||||
Public
|
||||
Constructor Create;
|
||||
Destructor Destroy;override;
|
||||
Procedure ZipAllFiles; virtual;
|
||||
Procedure ZipFiles(AFileName : String; FileList : TStrings);
|
||||
Procedure ZipFiles(AFileName : String; Entries : TZipFileEntries);
|
||||
Procedure Clear;
|
||||
Public
|
||||
Property BufferSize : LongWord Read FBufSize Write SetBufSize;
|
||||
@ -307,6 +339,7 @@ Type
|
||||
Property FileName : String Read FFileName Write SetFileName;
|
||||
Property Files : TStrings Read FFiles;
|
||||
Property InMemSize : Integer Read FInMemSize Write FInMemSize;
|
||||
Property Entries : TZipFileEntries Read FEntries Write SetEntries;
|
||||
end;
|
||||
|
||||
{ TYbZipper }
|
||||
@ -319,8 +352,8 @@ Type
|
||||
FBufSize : LongWord;
|
||||
FFileName : String; { Name of resulting Zip file }
|
||||
FOutputPath : String;
|
||||
FEntries : TZipFileEntries;
|
||||
FFiles : TStrings;
|
||||
FZipEntries : TFPList; { don't use TFPObjectList, becuase of Contnrs dependency }
|
||||
FOutFile : TFileStream;
|
||||
FZipFile : TFileStream; { I/O file variables }
|
||||
LocalHdr : Local_File_Header_Type;
|
||||
@ -335,15 +368,15 @@ Type
|
||||
Procedure OpenInput;
|
||||
Procedure CloseOutput;
|
||||
Procedure CloseInput;
|
||||
Procedure ReadZipHeader(Item : TZipItem; out ACRC : LongWord;out AMethod : Word);
|
||||
Procedure ReadZipHeader(Item : TZipFileEntry; out ACRC : LongWord;out AMethod : Word);
|
||||
Procedure ReadZipDirectory;
|
||||
Procedure DoEndOfFile;
|
||||
Procedure UnZipOneFile(Item : TZipItem); virtual;
|
||||
Procedure UnZipOneFile(Item : TZipFileEntry); virtual;
|
||||
Function OpenOutput(OutFileName : String) : Boolean;
|
||||
Procedure SetBufSize(Value : LongWord);
|
||||
Procedure SetFileName(Value : String);
|
||||
Procedure SetOutputPath(Value:String);
|
||||
Function CreateDeCompressor(Item : TZipItem; AMethod : Word;AZipFile,AOutFile : TStream) : TDeCompressor; virtual;
|
||||
Function CreateDeCompressor(Item : TZipFileEntry; AMethod : Word;AZipFile,AOutFile : TStream) : TDeCompressor; virtual;
|
||||
Public
|
||||
Constructor Create;
|
||||
Destructor Destroy;override;
|
||||
@ -360,6 +393,7 @@ Type
|
||||
Property FileName : String Read FFileName Write SetFileName;
|
||||
Property OutputPath : String Read FOutputPath Write SetOutputPath;
|
||||
Property Files : TStrings Read FFiles;
|
||||
Property Entries : TZipFileEntries Read FEntries Write FEntries;
|
||||
end;
|
||||
|
||||
EZipError = Class(Exception);
|
||||
@ -372,6 +406,9 @@ ResourceString
|
||||
SErrInvalidCRC = 'Invalid CRC checksum while unzipping %s';
|
||||
SErrCorruptZIP = 'Corrupt ZIP file %s';
|
||||
SErrUnsupportedCompressionFormat = 'Unsupported compression format %d';
|
||||
SErrMissingFileName = 'Missing filename in entry %d';
|
||||
SErrMissingArchiveName = 'Missing archive filename in streamed entry %d';
|
||||
SErrFileDoesNotExist = 'File "%s" does not exist.';
|
||||
|
||||
{ ---------------------------------------------------------------------
|
||||
Auxiliary
|
||||
@ -907,26 +944,42 @@ end;
|
||||
Procedure TZipper.GetFileInfo;
|
||||
|
||||
Var
|
||||
Info : TSearchRec;
|
||||
I : Longint;
|
||||
NewNode : TZipItem;
|
||||
|
||||
F : TZipFileEntry;
|
||||
Info : TSearchRec;
|
||||
I : Longint;
|
||||
|
||||
Begin
|
||||
For I := 0 to FFiles.Count-1 do
|
||||
For I := 0 to FEntries.Count-1 do
|
||||
begin
|
||||
If FindFirst(FFiles[I], STDATTR, Info)=0 then
|
||||
try
|
||||
NewNode:=TZipItem.Create;
|
||||
NewNode.Path := ExtractFilePath(FFiles[i]);
|
||||
NewNode.Name := Info.Name;
|
||||
NewNode.Size := Info.Size;
|
||||
NewNode.DateTime:=FileDateToDateTime(Info.Time);
|
||||
FFiles.Objects[i]:=NewNode;
|
||||
finally
|
||||
FindClose(Info);
|
||||
end;
|
||||
end;
|
||||
F:=FEntries[i];
|
||||
If F.Stream=Nil then
|
||||
begin
|
||||
If (F.DiskFileName='') then
|
||||
Raise EZipError.CreateFmt(SErrMissingFileName,[I]);
|
||||
If FindFirst(F.DiskFileName, STDATTR, Info)=0 then
|
||||
try
|
||||
F.Size:=Info.Size;
|
||||
F.DateTime:=FileDateToDateTime(Info.Time);
|
||||
finally
|
||||
FindClose(Info);
|
||||
end
|
||||
else
|
||||
Raise EZipError.CreateFmt(SErrFileDoesNotExist,[F.DiskFileName]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
If (F.ArchiveFileName='') then
|
||||
Raise EZipError.CreateFmt(SErrMissingArchiveName,[I]);
|
||||
F.Size:=F.Stream.Size;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TZipper.SetEntries(const AValue: TZipFileEntries);
|
||||
begin
|
||||
if FEntries=AValue then exit;
|
||||
FEntries.Assign(AValue);
|
||||
end;
|
||||
|
||||
Procedure TZipper.OpenOutput;
|
||||
@ -936,13 +989,16 @@ Begin
|
||||
End;
|
||||
|
||||
|
||||
Function TZipper.OpenInput(InFileName : String) : Boolean;
|
||||
Function TZipper.OpenInput(Item : TZipFileEntry) : Boolean;
|
||||
|
||||
Begin
|
||||
FInFile:=TFileStream.Create(InFileName,fmOpenRead);
|
||||
If (Item.Stream<>nil) then
|
||||
FInFile:=Item.Stream
|
||||
else
|
||||
FInFile:=TFileStream.Create(Item.DiskFileName,fmOpenRead);
|
||||
Result:=True;
|
||||
If Assigned(FOnStartFile) then
|
||||
FOnStartFile(Self,InFileName);
|
||||
FOnStartFile(Self,Item.ArchiveFileName);
|
||||
End;
|
||||
|
||||
|
||||
@ -953,14 +1009,17 @@ Begin
|
||||
end;
|
||||
|
||||
|
||||
Procedure TZipper.CloseInput;
|
||||
Procedure TZipper.CloseInput(Item : TZipFileEntry);
|
||||
|
||||
Begin
|
||||
FreeAndNil(FInFile);
|
||||
If (FInFile<>Item.Stream) then
|
||||
FreeAndNil(FInFile)
|
||||
else
|
||||
FinFile:=Nil;
|
||||
end;
|
||||
|
||||
|
||||
Procedure TZipper.StartZipFile(Item : TZipItem);
|
||||
Procedure TZipper.StartZipFile(Item : TZipFileEntry);
|
||||
|
||||
Begin
|
||||
FillChar(LocalHdr,SizeOf(LocalHdr),0);
|
||||
@ -980,11 +1039,11 @@ Begin
|
||||
End;
|
||||
|
||||
|
||||
Function TZipper.UpdateZipHeader(Item : TZipItem; FZip : TStream; ACRC : LongWord; AMethod : Word) : Boolean;
|
||||
Function TZipper.UpdateZipHeader(Item : TZipFileEntry; FZip : TStream; ACRC : LongWord; AMethod : Word) : Boolean;
|
||||
var
|
||||
ZFileName : ShortString;
|
||||
Begin
|
||||
ZFileName:=Item.Path+Item.Name;
|
||||
ZFileName:=Item.ArchiveFileName;
|
||||
With LocalHdr do
|
||||
begin
|
||||
FileName_Length := Length(ZFileName);
|
||||
@ -1009,11 +1068,11 @@ Var
|
||||
SavePos : LongInt;
|
||||
HdrPos : LongInt;
|
||||
CenDirPos : LongInt;
|
||||
Entries : Word;
|
||||
ACount : Word;
|
||||
ZFileName : ShortString;
|
||||
|
||||
Begin
|
||||
Entries := 0;
|
||||
ACount := 0;
|
||||
CenDirPos := FOutFile.Position;
|
||||
FOutFile.Seek(0,soFrombeginning); { Rewind output file }
|
||||
HdrPos := FOutFile.Position;
|
||||
@ -1039,7 +1098,7 @@ Begin
|
||||
FOutFile.Seek(0,soFromEnd);
|
||||
FOutFile.WriteBuffer(CentralHdr,SizeOf(CentralHdr));
|
||||
FOutFile.WriteBuffer(ZFileName[1],Length(ZFileName));
|
||||
Inc(Entries);
|
||||
Inc(ACount);
|
||||
FOutFile.Seek(SavePos + LocalHdr.Compressed_Size,soFromBeginning);
|
||||
HdrPos:=FOutFile.Position;
|
||||
FOutFile.ReadBuffer(LocalHdr, SizeOf(LocalHdr));
|
||||
@ -1051,8 +1110,8 @@ Begin
|
||||
Signature := END_OF_CENTRAL_DIR_SIGNATURE;
|
||||
Disk_Number := 0;
|
||||
Central_Dir_Start_Disk := 0;
|
||||
Entries_This_Disk := Entries;
|
||||
Total_Entries := Entries;
|
||||
Entries_This_Disk := ACount;
|
||||
Total_Entries := ACount;
|
||||
Central_Dir_Size := FOutFile.Size-CenDirPos;
|
||||
Start_Disk_Offset := CenDirPos;
|
||||
ZipFile_Comment_Length := 0;
|
||||
@ -1060,13 +1119,13 @@ Begin
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TZipper.CreateCompressor(Item : TZipItem; AInFile,AZipStream : TStream) : TCompressor;
|
||||
Function TZipper.CreateCompressor(Item : TZipFileEntry; AInFile,AZipStream : TStream) : TCompressor;
|
||||
|
||||
begin
|
||||
Result:=TDeflater.Create(AinFile,AZipStream,FBufSize);
|
||||
end;
|
||||
|
||||
Procedure TZipper.ZipOneFile(Item : TZipItem);
|
||||
Procedure TZipper.ZipOneFile(Item : TZipFileEntry);
|
||||
|
||||
Var
|
||||
CRC : LongWord;
|
||||
@ -1075,7 +1134,7 @@ Var
|
||||
TmpFileName : String;
|
||||
|
||||
Begin
|
||||
OpenInput(Item.Path+Item.Name);
|
||||
OpenInput(Item);
|
||||
Try
|
||||
StartZipFile(Item);
|
||||
If (FInfile.Size<=FInMemSize) then
|
||||
@ -1111,32 +1170,28 @@ Begin
|
||||
DeleteFile(TmpFileName);
|
||||
end;
|
||||
Finally
|
||||
CloseInput;
|
||||
CloseInput(Item);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TZipper.ZipAllFiles;
|
||||
|
||||
Var
|
||||
Item : TZipItem;
|
||||
I : Integer;
|
||||
filecnt : integer;
|
||||
Begin
|
||||
if FFiles.Count=0 then
|
||||
exit;
|
||||
If CheckEntries=0 then
|
||||
Exit;
|
||||
FZipping:=True;
|
||||
Try
|
||||
GetFileInfo;
|
||||
OpenOutput;
|
||||
Try
|
||||
filecnt:=0;
|
||||
For I:=0 to FFiles.Count-1 do
|
||||
For I:=0 to FEntries.Count-1 do
|
||||
begin
|
||||
Item:=FFiles.Objects[i] as TZipItem;
|
||||
if assigned(Item) then
|
||||
begin
|
||||
ZipOneFile(Item);
|
||||
inc(filecnt);
|
||||
end;
|
||||
ZipOneFile(FEntries[i]);
|
||||
inc(filecnt);
|
||||
end;
|
||||
if filecnt>0 then
|
||||
BuildZipDirectory;
|
||||
@ -1174,6 +1229,13 @@ begin
|
||||
ZipAllFiles;
|
||||
end;
|
||||
|
||||
procedure TZipper.ZipFiles(AFileName: String; Entries: TZipFileEntries);
|
||||
begin
|
||||
FFileName:=AFileName;
|
||||
FEntries.Assign(Entries);
|
||||
ZipAllFiles;
|
||||
end;
|
||||
|
||||
Procedure TZipper.DoEndOfFile;
|
||||
|
||||
Var
|
||||
@ -1194,18 +1256,32 @@ begin
|
||||
FBufSize:=DefaultBufSize;
|
||||
FInMemSize:=DefaultInMemSize;
|
||||
FFiles:=TStringList.Create;
|
||||
TStringlist(FFiles).Sorted:=True;
|
||||
FEntries:=TZipFileEntries.Create(TZipFileEntry);
|
||||
FOnPercent:=1;
|
||||
end;
|
||||
|
||||
Procedure TZipper.Clear;
|
||||
Function TZipper.CheckEntries : Integer;
|
||||
|
||||
Var
|
||||
I : Integer;
|
||||
|
||||
begin
|
||||
For I:=0 to FFiles.Count-1 do
|
||||
FFiles.Objects[i].Free;
|
||||
If (FFiles.Count>0) and (FEntries.Count=0) then
|
||||
begin
|
||||
FEntries.Clear;
|
||||
For I:=0 to FFiles.Count-1 do
|
||||
begin
|
||||
FEntries.AddFileEntry(FFiles[i]);
|
||||
end;
|
||||
end;
|
||||
Result:=FEntries.Count;
|
||||
end;
|
||||
|
||||
|
||||
Procedure TZipper.Clear;
|
||||
|
||||
begin
|
||||
FEntries.Clear;
|
||||
FFiles.Clear;
|
||||
end;
|
||||
|
||||
@ -1213,6 +1289,7 @@ Destructor TZipper.Destroy;
|
||||
|
||||
begin
|
||||
Clear;
|
||||
FreeAndNil(FEntries);
|
||||
FreeAndNil(FFiles);
|
||||
Inherited;
|
||||
end;
|
||||
@ -1254,20 +1331,27 @@ Begin
|
||||
end;
|
||||
|
||||
|
||||
Procedure TUnZipper.ReadZipHeader(Item : TZipItem; out ACRC : LongWord; out AMethod : Word);
|
||||
Procedure TUnZipper.ReadZipHeader(Item : TZipFileEntry; out ACRC : LongWord; out AMethod : Word);
|
||||
|
||||
Var
|
||||
S : String;
|
||||
D : TDateTime;
|
||||
|
||||
Begin
|
||||
FZipFile.Seek(Item.HdrPos,soFromBeginning);
|
||||
FZipFile.ReadBuffer(LocalHdr,SizeOf(LocalHdr));
|
||||
With LocalHdr do
|
||||
begin
|
||||
SetLength(Item.Name,Filename_Length);
|
||||
FZipFile.ReadBuffer(Item.Name[1],Filename_Length);
|
||||
FZipFile.Seek(Extra_Field_Length,soCurrent);
|
||||
Item.Size:=Uncompressed_Size;
|
||||
ZipDateTimeToDateTime(Last_Mod_Date,Last_Mod_Time,Item.DateTime);
|
||||
ACrc:=Crc32;
|
||||
AMethod:=Compress_method;
|
||||
SetLength(S,Filename_Length);
|
||||
FZipFile.ReadBuffer(S[1],Filename_Length);
|
||||
FZipFile.Seek(Extra_Field_Length,soCurrent);
|
||||
Item.ArchiveFileName:=S;
|
||||
Item.DiskFileName:=S;
|
||||
Item.Size:=Uncompressed_Size;
|
||||
ZipDateTimeToDateTime(Last_Mod_Date,Last_Mod_Time,D);
|
||||
Item.DateTime:=D;
|
||||
ACrc:=Crc32;
|
||||
AMethod:=Compress_method;
|
||||
end;
|
||||
End;
|
||||
|
||||
@ -1275,41 +1359,43 @@ End;
|
||||
Procedure TUnZipper.ReadZipDirectory;
|
||||
|
||||
Var
|
||||
i,
|
||||
EndHdrPos,
|
||||
CenDirPos : LongInt;
|
||||
NewNode : TZipItem;
|
||||
i,
|
||||
EndHdrPos,
|
||||
CenDirPos : LongInt;
|
||||
NewNode : TZipFileEntry;
|
||||
S : String;
|
||||
|
||||
Begin
|
||||
EndHdrPos:=FZipFile.Size-SizeOf(EndHdr);
|
||||
if EndHdrPos < 0 then
|
||||
raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
|
||||
FZipFile.Seek(EndHdrPos,soFromBeginning);
|
||||
FZipFile.ReadBuffer(EndHdr, SizeOf(EndHdr));
|
||||
With EndHdr do
|
||||
begin
|
||||
if Signature <> END_OF_CENTRAL_DIR_SIGNATURE then
|
||||
raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
|
||||
CenDirPos:=Start_Disk_Offset;
|
||||
end;
|
||||
FZipFile.Seek(CenDirPos,soFrombeginning);
|
||||
for i:=0 to EndHdr.Entries_This_Disk-1 do
|
||||
begin
|
||||
FZipFile.ReadBuffer(CentralHdr, SizeOf(CentralHdr));
|
||||
With CentralHdr do
|
||||
begin
|
||||
if Signature<>CENTRAL_FILE_HEADER_SIGNATURE then
|
||||
raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
|
||||
NewNode:=TZipItem.Create;
|
||||
NewNode.HdrPos := Local_Header_Offset;
|
||||
SetLength(NewNode.Name,Filename_Length);
|
||||
FZipFile.ReadBuffer(NewNode.Name[1],Filename_Length);
|
||||
FZipFile.Seek(Extra_Field_Length+File_Comment_Length,soCurrent);
|
||||
FZipEntries.Add(NewNode);
|
||||
end;
|
||||
end;
|
||||
EndHdrPos:=FZipFile.Size-SizeOf(EndHdr);
|
||||
if EndHdrPos < 0 then
|
||||
raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
|
||||
FZipFile.Seek(EndHdrPos,soFromBeginning);
|
||||
FZipFile.ReadBuffer(EndHdr, SizeOf(EndHdr));
|
||||
With EndHdr do
|
||||
begin
|
||||
if Signature <> END_OF_CENTRAL_DIR_SIGNATURE then
|
||||
raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
|
||||
CenDirPos:=Start_Disk_Offset;
|
||||
end;
|
||||
FZipFile.Seek(CenDirPos,soFrombeginning);
|
||||
for i:=0 to EndHdr.Entries_This_Disk-1 do
|
||||
begin
|
||||
FZipFile.ReadBuffer(CentralHdr, SizeOf(CentralHdr));
|
||||
With CentralHdr do
|
||||
begin
|
||||
if Signature<>CENTRAL_FILE_HEADER_SIGNATURE then
|
||||
raise EZipError.CreateFmt(SErrCorruptZIP,[FZipFile.FileName]);
|
||||
NewNode:=FEntries.Add as TZipFileEntry;
|
||||
NewNode.HdrPos := Local_Header_Offset;
|
||||
SetLength(S,Filename_Length);
|
||||
FZipFile.ReadBuffer(S[1],Filename_Length);
|
||||
NewNode.ArchiveFileName:=S;
|
||||
FZipFile.Seek(Extra_Field_Length+File_Comment_Length,soCurrent);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TUnZipper.CreateDeCompressor(Item : TZipItem; AMethod : Word;AZipFile,AOutFile : TStream) : TDeCompressor;
|
||||
Function TUnZipper.CreateDeCompressor(Item : TZipFileEntry; AMethod : Word;AZipFile,AOutFile : TStream) : TDeCompressor;
|
||||
begin
|
||||
case AMethod of
|
||||
8 :
|
||||
@ -1319,7 +1405,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TUnZipper.UnZipOneFile(Item : TZipItem);
|
||||
Procedure TUnZipper.UnZipOneFile(Item : TZipFileEntry);
|
||||
|
||||
Var
|
||||
Count : Longint;
|
||||
@ -1329,7 +1415,7 @@ Var
|
||||
Begin
|
||||
Try
|
||||
ReadZipHeader(Item,CRC,ZMethod);
|
||||
OutputFileName:=Item.Name;
|
||||
OutputFileName:=Item.DiskFileName;
|
||||
if FOutputPath<>'' then
|
||||
OutputFileName:=IncludeTrailingPathDelimiter(FOutputPath)+OutputFileName;
|
||||
OpenOutput(OutputFileName);
|
||||
@ -1345,7 +1431,7 @@ Begin
|
||||
OnPercent:=Self.OnPercent;
|
||||
DeCompress;
|
||||
if CRC<>Crc32Val then
|
||||
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.Name]);
|
||||
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]);
|
||||
Finally
|
||||
Free;
|
||||
end;
|
||||
@ -1357,9 +1443,10 @@ end;
|
||||
|
||||
Procedure TUnZipper.UnZipAllFiles;
|
||||
Var
|
||||
Item : TZipItem;
|
||||
Item : TZipFileEntry;
|
||||
I : Integer;
|
||||
AllFiles : Boolean;
|
||||
|
||||
Begin
|
||||
FUnZipping:=True;
|
||||
Try
|
||||
@ -1367,15 +1454,14 @@ Begin
|
||||
OpenInput;
|
||||
Try
|
||||
ReadZipDirectory;
|
||||
For I:=0 to FZipEntries.Count-1 do
|
||||
For I:=0 to FEntries.Count-1 do
|
||||
begin
|
||||
Item:=TZipItem(FZipEntries[i]);
|
||||
if AllFiles or
|
||||
(FFiles.IndexOf(Item.Name)<>-1) then
|
||||
UnZipOneFile(Item);
|
||||
Item:=FEntries[i];
|
||||
if AllFiles or (FFiles.IndexOf(Item.ArchiveFileName)<>-1) then
|
||||
UnZipOneFile(Item);
|
||||
end;
|
||||
Finally
|
||||
CloseInput;
|
||||
CloseInput;
|
||||
end;
|
||||
finally
|
||||
FUnZipping:=False;
|
||||
@ -1441,23 +1527,16 @@ Constructor TUnZipper.Create;
|
||||
begin
|
||||
FBufSize:=DefaultBufSize;
|
||||
FFiles:=TStringList.Create;
|
||||
FZipEntries:=TFPList.Create;
|
||||
TStringlist(FFiles).Sorted:=True;
|
||||
FEntries:=TZipFileEntries.Create(TZipFileEntry);
|
||||
FOnPercent:=1;
|
||||
end;
|
||||
|
||||
Procedure TUnZipper.Clear;
|
||||
|
||||
Var
|
||||
I : Integer;
|
||||
|
||||
begin
|
||||
For I:=0 to FFiles.Count-1 do
|
||||
FFiles.Objects[i].Free;
|
||||
FFiles.Clear;
|
||||
For I:=0 to FZipEntries.Count-1 do
|
||||
TZipItem(FZipEntries[i]).Free;
|
||||
FZipEntries.Clear;
|
||||
FEntries.Clear;
|
||||
end;
|
||||
|
||||
Destructor TUnZipper.Destroy;
|
||||
@ -1465,8 +1544,51 @@ Destructor TUnZipper.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
FreeAndNil(FFiles);
|
||||
FreeAndNil(FZipEntries);
|
||||
FreeAndNil(FEntries);
|
||||
Inherited;
|
||||
end;
|
||||
|
||||
{ TZipFileEntry }
|
||||
|
||||
function TZipFileEntry.GetArchiveFileName: String;
|
||||
begin
|
||||
Result:=FArchiveFileName;
|
||||
If (Result='') then
|
||||
Result:=FDiskFileName;
|
||||
end;
|
||||
|
||||
{ TZipFileEntries }
|
||||
|
||||
function TZipFileEntries.GetZ(AIndex : Integer): TZipFileEntry;
|
||||
begin
|
||||
Result:=TZipFileEntry(Items[AIndex]);
|
||||
end;
|
||||
|
||||
procedure TZipFileEntries.SetZ(AIndex : Integer; const AValue: TZipFileEntry);
|
||||
begin
|
||||
Items[AIndex]:=AValue;
|
||||
end;
|
||||
|
||||
function TZipFileEntries.AddFileEntry(const ADiskFileName: String
|
||||
): TZipFileEntry;
|
||||
begin
|
||||
Result:=Add as TZipFileEntry;
|
||||
Result.DiskFileName:=ADiskFileName;
|
||||
end;
|
||||
|
||||
function TZipFileEntries.AddFileEntry(const ADiskFileName,
|
||||
AArchiveFileName: String): TZipFileEntry;
|
||||
begin
|
||||
Result:=AddFileEntry(ADiskFileName);
|
||||
Result.ArchiveFileName:=AArchiveFileName;
|
||||
end;
|
||||
|
||||
function TZipFileEntries.AddFileEntry(const AStream: TSTream;
|
||||
const AArchiveFileName: String): TZipFileEntry;
|
||||
begin
|
||||
Result:=Add as TZipFileEntry;
|
||||
Result.Stream:=AStream;
|
||||
Result.ArchiveFileName:=AArchiveFileName;
|
||||
end;
|
||||
|
||||
End.
|
||||
|
Loading…
Reference in New Issue
Block a user