mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 03:46:10 +02:00
* patch by Tom Gregorovic (with some fixes by Alexander Grau) to
* support creating directories and symbolic links while unzipping * preserve access rights and date of unzipped files * fix the CRC32 control when the local header field is zero -> fixes mantis #14106 * fixed unzipping stored files of zero bytes git-svn-id: trunk@13378 -
This commit is contained in:
parent
d09b2d91a9
commit
292e4200c8
@ -18,6 +18,9 @@ unit zipper;
|
|||||||
Interface
|
Interface
|
||||||
|
|
||||||
Uses
|
Uses
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
BaseUnix,
|
||||||
|
{$ENDIF}
|
||||||
SysUtils,Classes,ZStream;
|
SysUtils,Classes,ZStream;
|
||||||
|
|
||||||
|
|
||||||
@ -251,15 +254,21 @@ Type
|
|||||||
TZipFileEntry = Class(TCollectionItem)
|
TZipFileEntry = Class(TCollectionItem)
|
||||||
private
|
private
|
||||||
FArchiveFileName: String;
|
FArchiveFileName: String;
|
||||||
|
FAttributes: LongInt;
|
||||||
|
FCRC32: LongWord;
|
||||||
FDateTime: TDateTime;
|
FDateTime: TDateTime;
|
||||||
FDiskFileName: String;
|
FDiskFileName: String;
|
||||||
FHeaderPos: Longint;
|
FHeaderPos: Longint;
|
||||||
|
FOS: Byte;
|
||||||
FSize: Integer;
|
FSize: Integer;
|
||||||
FStream: TStream;
|
FStream: TStream;
|
||||||
function GetArchiveFileName: String;
|
function GetArchiveFileName: String;
|
||||||
Protected
|
Protected
|
||||||
Property HdrPos : Longint Read FHeaderPos Write FheaderPos;
|
Property HdrPos : Longint Read FHeaderPos Write FheaderPos;
|
||||||
Public
|
Public
|
||||||
|
constructor Create;
|
||||||
|
function IsDirectory: Boolean;
|
||||||
|
function IsLink: Boolean;
|
||||||
Procedure Assign(Source : TPersistent); override;
|
Procedure Assign(Source : TPersistent); override;
|
||||||
Property Stream : TStream Read FStream Write FStream;
|
Property Stream : TStream Read FStream Write FStream;
|
||||||
Published
|
Published
|
||||||
@ -267,6 +276,9 @@ Type
|
|||||||
Property DiskFileName : String Read FDiskFileName Write FDiskFileName;
|
Property DiskFileName : String Read FDiskFileName Write FDiskFileName;
|
||||||
Property Size : Integer Read FSize Write FSize;
|
Property Size : Integer Read FSize Write FSize;
|
||||||
Property DateTime : TDateTime Read FDateTime Write FDateTime;
|
Property DateTime : TDateTime Read FDateTime Write FDateTime;
|
||||||
|
property OS: Byte read FOS write FOS;
|
||||||
|
property Attributes: LongInt read FAttributes write FAttributes;
|
||||||
|
property CRC32: LongWord read FCRC32 write FCRC32;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TZipFileEntries }
|
{ TZipFileEntries }
|
||||||
@ -337,8 +349,6 @@ Type
|
|||||||
Property Entries : TZipFileEntries Read FEntries Write SetEntries;
|
Property Entries : TZipFileEntries Read FEntries Write SetEntries;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TYbZipper }
|
|
||||||
|
|
||||||
{ TUnZipper }
|
{ TUnZipper }
|
||||||
|
|
||||||
TUnZipper = Class(TObject)
|
TUnZipper = Class(TObject)
|
||||||
@ -363,7 +373,7 @@ Type
|
|||||||
Procedure OpenInput;
|
Procedure OpenInput;
|
||||||
Procedure CloseOutput;
|
Procedure CloseOutput;
|
||||||
Procedure CloseInput;
|
Procedure CloseInput;
|
||||||
Procedure ReadZipHeader(Item : TZipFileEntry; out ACRC : LongWord;out AMethod : Word);
|
Procedure ReadZipHeader(Item : TZipFileEntry; out AMethod : Word);
|
||||||
Procedure ReadZipDirectory;
|
Procedure ReadZipDirectory;
|
||||||
Procedure DoEndOfFile;
|
Procedure DoEndOfFile;
|
||||||
Procedure UnZipOneFile(Item : TZipFileEntry); virtual;
|
Procedure UnZipOneFile(Item : TZipFileEntry); virtual;
|
||||||
@ -497,6 +507,67 @@ begin
|
|||||||
DT:=ComposeDateTime(EncodeDate(Y,M,D),EncodeTime(H,N,S,MS));
|
DT:=ComposeDateTime(EncodeDate(Y,M,D),EncodeTime(H,N,S,MS));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
OS_FAT = 0;
|
||||||
|
OS_UNIX = 3;
|
||||||
|
|
||||||
|
UNIX_MASK = $F000;
|
||||||
|
UNIX_FIFO = $1000;
|
||||||
|
UNIX_CHAR = $2000;
|
||||||
|
UNIX_DIR = $4000;
|
||||||
|
UNIX_BLK = $6000;
|
||||||
|
UNIX_FILE = $8000;
|
||||||
|
UNIX_LINK = $A000;
|
||||||
|
UNIX_SOCK = $C000;
|
||||||
|
|
||||||
|
|
||||||
|
UNIX_RUSR = $0100;
|
||||||
|
UNIX_WUSR = $0080;
|
||||||
|
UNIX_XUSR = $0040;
|
||||||
|
|
||||||
|
UNIX_RGRP = $0020;
|
||||||
|
UNIX_WGRP = $0010;
|
||||||
|
UNIX_XGRP = $0008;
|
||||||
|
|
||||||
|
UNIX_ROTH = $0004;
|
||||||
|
UNIX_WOTH = $0002;
|
||||||
|
UNIX_XOTH = $0001;
|
||||||
|
|
||||||
|
UNIX_DEFAULT = UNIX_RUSR or UNIX_WUSR or UNIX_XUSR or UNIX_RGRP or UNIX_ROTH;
|
||||||
|
|
||||||
|
|
||||||
|
function ZipUnixAttrsToFatAttrs(const Name: String; Attrs: Longint): Longint;
|
||||||
|
begin
|
||||||
|
Result := faArchive;
|
||||||
|
|
||||||
|
if (Pos('.', Name) = 1) and (Name <> '.') and (Name <> '..') then
|
||||||
|
Result := Result + faHidden;
|
||||||
|
case (Attrs and UNIX_MASK) of
|
||||||
|
UNIX_DIR: Result := Result + faDirectory;
|
||||||
|
UNIX_LINK: Result := Result + faSymLink;
|
||||||
|
UNIX_FIFO, UNIX_CHAR, UNIX_BLK, UNIX_SOCK:
|
||||||
|
Result := Result + faSysFile;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (Attrs and UNIX_WUSR) = 0 then
|
||||||
|
Result := Result + faReadOnly;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ZipFatAttrsToUnixAttrs(Attrs: Longint): Longint;
|
||||||
|
begin
|
||||||
|
Result := UNIX_DEFAULT;
|
||||||
|
if (faReadOnly and Attrs) > 0 then
|
||||||
|
Result := Result and not (UNIX_WUSR);
|
||||||
|
|
||||||
|
if (faSymLink and Attrs) > 0 then
|
||||||
|
Result := Result or UNIX_LINK
|
||||||
|
else
|
||||||
|
if (faDirectory and Attrs) > 0 then
|
||||||
|
Result := Result or UNIX_DIR
|
||||||
|
else
|
||||||
|
Result := Result or UNIX_FILE;
|
||||||
|
end;
|
||||||
|
|
||||||
{ ---------------------------------------------------------------------
|
{ ---------------------------------------------------------------------
|
||||||
TDeCompressor
|
TDeCompressor
|
||||||
---------------------------------------------------------------------}
|
---------------------------------------------------------------------}
|
||||||
@ -639,7 +710,7 @@ Const
|
|||||||
SPECIAL = 256; { Special function code }
|
SPECIAL = 256; { Special function code }
|
||||||
INCSIZE = 1; { Code indicating a jump in code size }
|
INCSIZE = 1; { Code indicating a jump in code size }
|
||||||
CLEARCODE = 2; { Code indicating code table has been cleared }
|
CLEARCODE = 2; { Code indicating code table has been cleared }
|
||||||
STDATTR = $23; { Standard file attribute for DOS Find First/Next }
|
STDATTR = faAnyFile; { Standard file attribute for DOS Find First/Next }
|
||||||
|
|
||||||
constructor TShrinker.Create(AInFile, AOutFile : TStream; ABufSize : LongWord);
|
constructor TShrinker.Create(AInFile, AOutFile : TStream; ABufSize : LongWord);
|
||||||
begin
|
begin
|
||||||
@ -1001,7 +1072,9 @@ Var
|
|||||||
F : TZipFileEntry;
|
F : TZipFileEntry;
|
||||||
Info : TSearchRec;
|
Info : TSearchRec;
|
||||||
I : Longint;
|
I : Longint;
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
UnixInfo: Stat;
|
||||||
|
{$ENDIF}
|
||||||
Begin
|
Begin
|
||||||
For I := 0 to FEntries.Count-1 do
|
For I := 0 to FEntries.Count-1 do
|
||||||
begin
|
begin
|
||||||
@ -1014,6 +1087,12 @@ Begin
|
|||||||
try
|
try
|
||||||
F.Size:=Info.Size;
|
F.Size:=Info.Size;
|
||||||
F.DateTime:=FileDateToDateTime(Info.Time);
|
F.DateTime:=FileDateToDateTime(Info.Time);
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
if fplstat(F.DiskFileName, @UnixInfo) = 0 then
|
||||||
|
F.Attributes := UnixInfo.st_mode;
|
||||||
|
{$ELSE}
|
||||||
|
F.Attributes := Info.Attr;
|
||||||
|
{$ENDIF}
|
||||||
finally
|
finally
|
||||||
FindClose(Info);
|
FindClose(Info);
|
||||||
end
|
end
|
||||||
@ -1025,6 +1104,11 @@ Begin
|
|||||||
If (F.ArchiveFileName='') then
|
If (F.ArchiveFileName='') then
|
||||||
Raise EZipError.CreateFmt(SErrMissingArchiveName,[I]);
|
Raise EZipError.CreateFmt(SErrMissingArchiveName,[I]);
|
||||||
F.Size:=F.Stream.Size;
|
F.Size:=F.Stream.Size;
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
F.Attributes := UNIX_FILE or UNIX_DEFAULT;
|
||||||
|
{$ELSE}
|
||||||
|
F.Attributes := faArchive;
|
||||||
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1049,7 +1133,10 @@ Begin
|
|||||||
If (Item.Stream<>nil) then
|
If (Item.Stream<>nil) then
|
||||||
FInFile:=Item.Stream
|
FInFile:=Item.Stream
|
||||||
else
|
else
|
||||||
FInFile:=TFileStream.Create(Item.DiskFileName,fmOpenRead);
|
if Item.IsDirectory then
|
||||||
|
FInFile := TStringStream.Create('')
|
||||||
|
else
|
||||||
|
FInFile:=TFileStream.Create(Item.DiskFileName,fmOpenRead);
|
||||||
Result:=True;
|
Result:=True;
|
||||||
If Assigned(FOnStartFile) then
|
If Assigned(FOnStartFile) then
|
||||||
FOnStartFile(Self,Item.ArchiveFileName);
|
FOnStartFile(Self,Item.ArchiveFileName);
|
||||||
@ -1143,13 +1230,20 @@ Begin
|
|||||||
begin
|
begin
|
||||||
Signature := CENTRAL_FILE_HEADER_SIGNATURE;
|
Signature := CENTRAL_FILE_HEADER_SIGNATURE;
|
||||||
MadeBy_Version := LocalHdr.Extract_Version_Reqd;
|
MadeBy_Version := LocalHdr.Extract_Version_Reqd;
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
MadeBy_Version := MadeBy_Version or (OS_UNIX shl 8);
|
||||||
|
{$ENDIF}
|
||||||
Move(LocalHdr.Extract_Version_Reqd, Extract_Version_Reqd, 26);
|
Move(LocalHdr.Extract_Version_Reqd, Extract_Version_Reqd, 26);
|
||||||
Last_Mod_Time:=localHdr.Last_Mod_Time;
|
Last_Mod_Time:=localHdr.Last_Mod_Time;
|
||||||
Last_Mod_Date:=localHdr.Last_Mod_Date;
|
Last_Mod_Date:=localHdr.Last_Mod_Date;
|
||||||
File_Comment_Length := 0;
|
File_Comment_Length := 0;
|
||||||
Starting_Disk_Num := 0;
|
Starting_Disk_Num := 0;
|
||||||
Internal_Attributes := 0;
|
Internal_Attributes := 0;
|
||||||
External_Attributes := faARCHIVE;
|
{$IFDEF UNIX}
|
||||||
|
External_Attributes := Entries[ACount].Attributes shl 16;
|
||||||
|
{$ELSE}
|
||||||
|
External_Attributes := Entries[ACount].Attributes;
|
||||||
|
{$ENDIF}
|
||||||
Local_Header_Offset := HdrPos;
|
Local_Header_Offset := HdrPos;
|
||||||
end;
|
end;
|
||||||
FOutFile.Seek(0,soFromEnd);
|
FOutFile.Seek(0,soFromEnd);
|
||||||
@ -1367,9 +1461,21 @@ End;
|
|||||||
|
|
||||||
|
|
||||||
Function TUnZipper.OpenOutput(OutFileName : String) : Boolean;
|
Function TUnZipper.OpenOutput(OutFileName : String) : Boolean;
|
||||||
|
Var
|
||||||
|
Path: String;
|
||||||
|
OldDirectorySeparators: set of char;
|
||||||
Begin
|
Begin
|
||||||
ForceDirectories(ExtractFilePath(OutFileName));
|
{ the default RTL behaviour is broken on Unix platforms
|
||||||
|
for Windows compatibility: it allows both '/' and '\'
|
||||||
|
as directory separator. We don't want that behaviour
|
||||||
|
here, since 'abc\' is a valid file name under Unix.
|
||||||
|
}
|
||||||
|
OldDirectorySeparators:=AllowDirectorySeparators;
|
||||||
|
AllowDirectorySeparators:=[DirectorySeparator];
|
||||||
|
Path:=ExtractFilePath(OutFileName);
|
||||||
|
if (Path<>'') then
|
||||||
|
ForceDirectories(Path);
|
||||||
|
AllowDirectorySeparators:=OldDirectorySeparators;
|
||||||
FOutFile:=TFileStream.Create(OutFileName,fmCreate);
|
FOutFile:=TFileStream.Create(OutFileName,fmCreate);
|
||||||
Result:=True;
|
Result:=True;
|
||||||
If Assigned(FOnStartFile) then
|
If Assigned(FOnStartFile) then
|
||||||
@ -1391,12 +1497,10 @@ Begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
Procedure TUnZipper.ReadZipHeader(Item : TZipFileEntry; out ACRC : LongWord; out AMethod : Word);
|
Procedure TUnZipper.ReadZipHeader(Item : TZipFileEntry; out AMethod : Word);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
S : String;
|
S : String;
|
||||||
D : TDateTime;
|
D : TDateTime;
|
||||||
|
|
||||||
Begin
|
Begin
|
||||||
FZipFile.Seek(Item.HdrPos,soFromBeginning);
|
FZipFile.Seek(Item.HdrPos,soFromBeginning);
|
||||||
FZipFile.ReadBuffer(LocalHdr,SizeOf(LocalHdr));
|
FZipFile.ReadBuffer(LocalHdr,SizeOf(LocalHdr));
|
||||||
@ -1405,16 +1509,19 @@ Begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
With LocalHdr do
|
With LocalHdr do
|
||||||
begin
|
begin
|
||||||
SetLength(S,Filename_Length);
|
SetLength(S,Filename_Length);
|
||||||
FZipFile.ReadBuffer(S[1],Filename_Length);
|
FZipFile.ReadBuffer(S[1],Filename_Length);
|
||||||
FZipFile.Seek(Extra_Field_Length,soCurrent);
|
//SetLength(E,Extra_Field_Length);
|
||||||
Item.ArchiveFileName:=S;
|
//FZipFile.ReadBuffer(E[1],Extra_Field_Length);
|
||||||
Item.DiskFileName:=S;
|
FZipFile.Seek(Extra_Field_Length,soCurrent);
|
||||||
Item.Size:=Uncompressed_Size;
|
Item.ArchiveFileName:=S;
|
||||||
ZipDateTimeToDateTime(Last_Mod_Date,Last_Mod_Time,D);
|
Item.DiskFileName:=S;
|
||||||
Item.DateTime:=D;
|
Item.Size:=Uncompressed_Size;
|
||||||
ACrc:=Crc32;
|
ZipDateTimeToDateTime(Last_Mod_Date,Last_Mod_Time,D);
|
||||||
AMethod:=Compress_method;
|
Item.DateTime:=D;
|
||||||
|
if Crc32 <> 0 then
|
||||||
|
Item.CRC32 := Crc32;
|
||||||
|
AMethod:=Compress_method;
|
||||||
end;
|
end;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
@ -1427,7 +1534,6 @@ Var
|
|||||||
CenDirPos : LongInt;
|
CenDirPos : LongInt;
|
||||||
NewNode : TZipFileEntry;
|
NewNode : TZipFileEntry;
|
||||||
S : String;
|
S : String;
|
||||||
|
|
||||||
Begin
|
Begin
|
||||||
EndHdrPos:=FZipFile.Size-SizeOf(EndHdr);
|
EndHdrPos:=FZipFile.Size-SizeOf(EndHdr);
|
||||||
if EndHdrPos < 0 then
|
if EndHdrPos < 0 then
|
||||||
@ -1452,14 +1558,23 @@ Begin
|
|||||||
{$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,[FZipFile.FileName]);
|
||||||
NewNode:=FEntries.Add as TZipFileEntry;
|
NewNode:=FEntries.Add as TZipFileEntry;
|
||||||
NewNode.HdrPos := Local_Header_Offset;
|
NewNode.HdrPos := Local_Header_Offset;
|
||||||
SetLength(S,Filename_Length);
|
SetLength(S,Filename_Length);
|
||||||
FZipFile.ReadBuffer(S[1],Filename_Length);
|
FZipFile.ReadBuffer(S[1],Filename_Length);
|
||||||
NewNode.ArchiveFileName:=S;
|
NewNode.ArchiveFileName:=S;
|
||||||
FZipFile.Seek(Extra_Field_Length+File_Comment_Length,soCurrent);
|
NewNode.OS := MadeBy_Version shr 8;
|
||||||
|
|
||||||
|
if NewNode.OS = OS_UNIX then
|
||||||
|
NewNode.Attributes := External_Attributes shr 16
|
||||||
|
else
|
||||||
|
NewNode.Attributes := External_Attributes;
|
||||||
|
|
||||||
|
NewNode.CRC32 := Crc32;
|
||||||
|
|
||||||
|
FZipFile.Seek(Extra_Field_Length + File_Comment_Length,soCurrent);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1477,35 +1592,104 @@ end;
|
|||||||
Procedure TUnZipper.UnZipOneFile(Item : TZipFileEntry);
|
Procedure TUnZipper.UnZipOneFile(Item : TZipFileEntry);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
Count : Longint;
|
Count, Attrs: Longint;
|
||||||
CRC : LongWord;
|
|
||||||
ZMethod : Word;
|
ZMethod : Word;
|
||||||
OutputFileName : string;
|
LinkTargetStream: TStringStream;
|
||||||
Begin
|
OutputFileName: string;
|
||||||
Try
|
IsLink: Boolean;
|
||||||
ReadZipHeader(Item,CRC,ZMethod);
|
|
||||||
OutputFileName:=Item.DiskFileName;
|
procedure DoUnzip(const Dest: TStream);
|
||||||
if FOutputPath<>'' then
|
begin
|
||||||
OutputFileName:=IncludeTrailingPathDelimiter(FOutputPath)+OutputFileName;
|
|
||||||
OpenOutput(OutputFileName);
|
|
||||||
if ZMethod=0 then
|
if ZMethod=0 then
|
||||||
begin
|
begin
|
||||||
Count:=FOutFile.CopyFrom(FZipFile,LocalHdr.Compressed_Size);
|
if (LocalHdr.Compressed_Size<>0) then
|
||||||
{$warning TODO: Implement CRC Check}
|
begin
|
||||||
end
|
Count:=Dest.CopyFrom(FZipFile,LocalHdr.Compressed_Size)
|
||||||
|
{$warning TODO: Implement CRC Check}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Count:=0;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
With CreateDecompressor(Item, ZMethod, FZipFile, FOutFile) do
|
With CreateDecompressor(Item, ZMethod, FZipFile, Dest) do
|
||||||
Try
|
Try
|
||||||
OnProgress:=Self.OnProgress;
|
OnProgress:=Self.OnProgress;
|
||||||
OnPercent:=Self.OnPercent;
|
OnPercent:=Self.OnPercent;
|
||||||
DeCompress;
|
DeCompress;
|
||||||
if CRC<>Crc32Val then
|
if Item.CRC32 <> Crc32Val then
|
||||||
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]);
|
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]);
|
||||||
Finally
|
Finally
|
||||||
Free;
|
Free;
|
||||||
end;
|
end;
|
||||||
Finally
|
end;
|
||||||
CloseOutput;
|
Begin
|
||||||
|
ReadZipHeader(Item, ZMethod);
|
||||||
|
OutputFileName:=Item.DiskFileName;
|
||||||
|
if FOutputPath<>'' then
|
||||||
|
OutputFileName:=IncludeTrailingPathDelimiter(FOutputPath)+OutputFileName;
|
||||||
|
|
||||||
|
IsLink := Item.IsLink;
|
||||||
|
|
||||||
|
{$IFNDEF UNIX}
|
||||||
|
if IsLink then
|
||||||
|
begin
|
||||||
|
{$warning TODO: Implement symbolic link creation for non-unix}
|
||||||
|
IsLink := False;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
|
||||||
|
if IsLink then
|
||||||
|
begin
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
LinkTargetStream := TStringStream.Create('');
|
||||||
|
try
|
||||||
|
DoUnzip(LinkTargetStream);
|
||||||
|
fpSymlink(PChar(LinkTargetStream.DataString), PChar(OutputFileName));
|
||||||
|
finally
|
||||||
|
LinkTargetStream.Free;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if Item.IsDirectory then
|
||||||
|
CreateDir(OutputFileName)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
try
|
||||||
|
OpenOutput(OutputFileName);
|
||||||
|
DoUnzip(FOutFile);
|
||||||
|
Finally
|
||||||
|
CloseOutput;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// set attributes
|
||||||
|
FileSetDate(OutputFileName, DateTimeToFileDate(Item.DateTime));
|
||||||
|
|
||||||
|
if (Item.Attributes <> 0) then
|
||||||
|
begin
|
||||||
|
Attrs := 0;
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
if Item.OS = OS_UNIX then Attrs := Item.Attributes;
|
||||||
|
if Item.OS = OS_FAT then
|
||||||
|
Attrs := ZipFatAttrsToUnixAttrs(Item.Attributes);
|
||||||
|
{$ELSE}
|
||||||
|
if Item.OS = OS_FAT then Attrs := Item.Attributes;
|
||||||
|
if Item.OS = OS_UNIX then
|
||||||
|
Attrs := ZipUnixAttrsToFatAttrs(ExtractFileName(Item.ArchiveFileName), Item.Attributes);
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
if Attrs <> 0 then
|
||||||
|
begin
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
FpChmod(OutputFileName, Attrs);
|
||||||
|
{$ELSE}
|
||||||
|
FileSetAttr(OutputFileName, Attrs);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1626,6 +1810,39 @@ begin
|
|||||||
Result:=FDiskFileName;
|
Result:=FDiskFileName;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor TZipFileEntry.Create;
|
||||||
|
begin
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
FOS := OS_UNIX;
|
||||||
|
{$ELSE}
|
||||||
|
FOS := OS_FAT;
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TZipFileEntry.IsDirectory: Boolean;
|
||||||
|
begin
|
||||||
|
Result := (DiskFileName <> '') and (DiskFileName[Length(DiskFileName)] in ['/', '\']);
|
||||||
|
if Attributes <> 0 then
|
||||||
|
begin
|
||||||
|
case OS of
|
||||||
|
OS_FAT: Result := (faDirectory and Attributes) > 0;
|
||||||
|
OS_UNIX: Result := (Attributes and UNIX_MASK) = UNIX_DIR;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TZipFileEntry.IsLink: Boolean;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
if Attributes <> 0 then
|
||||||
|
begin
|
||||||
|
case OS of
|
||||||
|
OS_FAT: Result := (faSymLink and Attributes) > 0;
|
||||||
|
OS_UNIX: Result := (Attributes and UNIX_MASK) = UNIX_LINK;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TZipFileEntry.Assign(Source: TPersistent);
|
procedure TZipFileEntry.Assign(Source: TPersistent);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
@ -1657,8 +1874,7 @@ begin
|
|||||||
Items[AIndex]:=AValue;
|
Items[AIndex]:=AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TZipFileEntries.AddFileEntry(const ADiskFileName: String
|
function TZipFileEntries.AddFileEntry(const ADiskFileName: String): TZipFileEntry;
|
||||||
): TZipFileEntry;
|
|
||||||
begin
|
begin
|
||||||
Result:=Add as TZipFileEntry;
|
Result:=Add as TZipFileEntry;
|
||||||
Result.DiskFileName:=ADiskFileName;
|
Result.DiskFileName:=ADiskFileName;
|
||||||
|
Loading…
Reference in New Issue
Block a user