mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-11 21:29:42 +02:00
* Make sure UTF8 is supported for all filenames when unzipping (bug ID 25982)
git-svn-id: trunk@33360 -
This commit is contained in:
parent
7cda2d237f
commit
b000a31abd
@ -403,7 +403,7 @@ Type
|
|||||||
FEntries : TZipFileEntries;
|
FEntries : TZipFileEntries;
|
||||||
FZipping : Boolean;
|
FZipping : Boolean;
|
||||||
FBufSize : LongWord;
|
FBufSize : LongWord;
|
||||||
FFileName : String; { Name of resulting Zip file }
|
FFileName : RawByteString; { Name of resulting Zip file }
|
||||||
FFileComment : String;
|
FFileComment : String;
|
||||||
FFiles : TStrings;
|
FFiles : TStrings;
|
||||||
FInMemSize : Int64;
|
FInMemSize : Int64;
|
||||||
@ -431,7 +431,7 @@ Type
|
|||||||
Function OpenInput(Item : TZipFileEntry) : Boolean;
|
Function OpenInput(Item : TZipFileEntry) : Boolean;
|
||||||
Procedure GetFileInfo;
|
Procedure GetFileInfo;
|
||||||
Procedure SetBufSize(Value : LongWord);
|
Procedure SetBufSize(Value : LongWord);
|
||||||
Procedure SetFileName(Value : String);
|
Procedure SetFileName(Value : RawByteString);
|
||||||
Function CreateCompressor(Item : TZipFileEntry; AinFile,AZipStream : TStream) : TCompressor; virtual;
|
Function CreateCompressor(Item : TZipFileEntry; AinFile,AZipStream : TStream) : TCompressor; virtual;
|
||||||
Property NeedsZip64 : boolean Read FZipFileNeedsZip64 Write FZipFileNeedsZip64;
|
Property NeedsZip64 : boolean Read FZipFileNeedsZip64 Write FZipFileNeedsZip64;
|
||||||
Public
|
Public
|
||||||
@ -439,14 +439,14 @@ Type
|
|||||||
Destructor Destroy;override;
|
Destructor Destroy;override;
|
||||||
Procedure ZipAllFiles; virtual;
|
Procedure ZipAllFiles; virtual;
|
||||||
// Saves zip to file and changes FileName
|
// Saves zip to file and changes FileName
|
||||||
Procedure SaveToFile(AFileName: string);
|
Procedure SaveToFile(AFileName: RawByteString);
|
||||||
// Saves zip to stream
|
// Saves zip to stream
|
||||||
Procedure SaveToStream(AStream: TStream);
|
Procedure SaveToStream(AStream: TStream);
|
||||||
// Zips specified files into a zip with name AFileName
|
// Zips specified files into a zip with name AFileName
|
||||||
Procedure ZipFiles(AFileName : String; FileList : TStrings);
|
Procedure ZipFiles(AFileName : RawByteString; FileList : TStrings);
|
||||||
Procedure ZipFiles(FileList : TStrings);
|
Procedure ZipFiles(FileList : TStrings);
|
||||||
// Zips specified entries into a zip with name AFileName
|
// Zips specified entries into a zip with name AFileName
|
||||||
Procedure ZipFiles(AFileName : String; Entries : TZipFileEntries);
|
Procedure ZipFiles(AFileName : RawByteString; Entries : TZipFileEntries);
|
||||||
Procedure ZipFiles(Entries : TZipFileEntries);
|
Procedure ZipFiles(Entries : TZipFileEntries);
|
||||||
Procedure Clear;
|
Procedure Clear;
|
||||||
Public
|
Public
|
||||||
@ -455,7 +455,7 @@ Type
|
|||||||
Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
|
Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
|
||||||
Property OnStartFile : TOnStartFileEvent Read FOnStartFile Write FOnStartFile;
|
Property OnStartFile : TOnStartFileEvent Read FOnStartFile Write FOnStartFile;
|
||||||
Property OnEndFile : TOnEndOfFileEvent Read FOnEndOfFile Write FOnEndOfFile;
|
Property OnEndFile : TOnEndOfFileEvent Read FOnEndOfFile Write FOnEndOfFile;
|
||||||
Property FileName : String Read FFileName Write SetFileName;
|
Property FileName : RawByteString Read FFileName Write SetFileName;
|
||||||
Property FileComment: String Read FFileComment Write FFileComment;
|
Property FileComment: String Read FFileComment Write FFileComment;
|
||||||
// Deprecated. Use Entries.AddFileEntry(FileName) or Entries.AddFileEntries(List) instead.
|
// Deprecated. Use Entries.AddFileEntry(FileName) or Entries.AddFileEntries(List) instead.
|
||||||
Property Files : TStrings Read FFiles; deprecated;
|
Property Files : TStrings Read FFiles; deprecated;
|
||||||
@ -501,8 +501,8 @@ Type
|
|||||||
FOnOpenInputStream: TCustomInputStreamEvent;
|
FOnOpenInputStream: TCustomInputStreamEvent;
|
||||||
FUnZipping : Boolean;
|
FUnZipping : Boolean;
|
||||||
FBufSize : LongWord;
|
FBufSize : LongWord;
|
||||||
FFileName : String; { Name of resulting Zip file }
|
FFileName : RawByteString; { Name of resulting Zip file }
|
||||||
FOutputPath : String;
|
FOutputPath : RawByteString;
|
||||||
FFileComment: String;
|
FFileComment: String;
|
||||||
FEntries : TFullZipFileEntries;
|
FEntries : TFullZipFileEntries;
|
||||||
FFiles : TStrings;
|
FFiles : TStrings;
|
||||||
@ -529,18 +529,18 @@ Type
|
|||||||
Procedure ReadZipHeader(Item : TFullZipFileEntry; out AMethod : Word);
|
Procedure ReadZipHeader(Item : TFullZipFileEntry; out AMethod : Word);
|
||||||
Procedure DoEndOfFile;
|
Procedure DoEndOfFile;
|
||||||
Procedure UnZipOneFile(Item : TFullZipFileEntry); virtual;
|
Procedure UnZipOneFile(Item : TFullZipFileEntry); virtual;
|
||||||
Function OpenOutput(OutFileName : RawByteString; var OutStream: TStream; Item : TFullZipFileEntry) : Boolean;
|
Function OpenOutput(OutFileName : RawByteString; Out OutStream: TStream; Item : TFullZipFileEntry) : Boolean;
|
||||||
Procedure SetBufSize(Value : LongWord);
|
Procedure SetBufSize(Value : LongWord);
|
||||||
Procedure SetFileName(Value : String);
|
Procedure SetFileName(Value : RawByteString);
|
||||||
Procedure SetOutputPath(Value:String);
|
Procedure SetOutputPath(Value: RawByteString);
|
||||||
Function CreateDeCompressor(Item : TZipFileEntry; AMethod : Word;AZipFile,AOutFile : TStream) : TDeCompressor; virtual;
|
Function CreateDeCompressor(Item : TZipFileEntry; AMethod : Word;AZipFile,AOutFile : TStream) : TDeCompressor; virtual;
|
||||||
Public
|
Public
|
||||||
Constructor Create;
|
Constructor Create;
|
||||||
Destructor Destroy;override;
|
Destructor Destroy;override;
|
||||||
Procedure UnZipAllFiles; virtual;
|
Procedure UnZipAllFiles; virtual;
|
||||||
Procedure UnZipFiles(AFileName : String; FileList : TStrings);
|
Procedure UnZipFiles(AFileName : RawByteString; FileList : TStrings);
|
||||||
Procedure UnZipFiles(FileList : TStrings);
|
Procedure UnZipFiles(FileList : TStrings);
|
||||||
Procedure UnZipAllFiles(AFileName : String);
|
Procedure UnZipAllFiles(AFileName : RawByteString);
|
||||||
Procedure Clear;
|
Procedure Clear;
|
||||||
Procedure Examine;
|
Procedure Examine;
|
||||||
Public
|
Public
|
||||||
@ -553,8 +553,8 @@ Type
|
|||||||
Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
|
Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
|
||||||
Property OnStartFile : TOnStartFileEvent Read FOnStartFile Write FOnStartFile;
|
Property OnStartFile : TOnStartFileEvent Read FOnStartFile Write FOnStartFile;
|
||||||
Property OnEndFile : TOnEndOfFileEvent Read FOnEndOfFile Write FOnEndOfFile;
|
Property OnEndFile : TOnEndOfFileEvent Read FOnEndOfFile Write FOnEndOfFile;
|
||||||
Property FileName : String Read FFileName Write SetFileName;
|
Property FileName : RawByteString Read FFileName Write SetFileName;
|
||||||
Property OutputPath : String Read FOutputPath Write SetOutputPath;
|
Property OutputPath : RawByteString Read FOutputPath Write SetOutputPath;
|
||||||
Property FileComment: String Read FFileComment;
|
Property FileComment: String Read FFileComment;
|
||||||
Property Files : TStrings Read FFiles;
|
Property Files : TStrings Read FFiles;
|
||||||
Property Entries : TFullZipFileEntries Read FEntries;
|
Property Entries : TFullZipFileEntries Read FEntries;
|
||||||
@ -565,6 +565,8 @@ Type
|
|||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
|
||||||
|
uses rtlconsts;
|
||||||
|
|
||||||
ResourceString
|
ResourceString
|
||||||
SErrBufsizeChange = 'Changing buffer size is not allowed while (un)zipping.';
|
SErrBufsizeChange = 'Changing buffer size is not allowed while (un)zipping.';
|
||||||
SErrFileChange = 'Changing output file name is not allowed while (un)zipping.';
|
SErrFileChange = 'Changing output file name is not allowed while (un)zipping.';
|
||||||
@ -576,7 +578,6 @@ ResourceString
|
|||||||
SErrMissingFileName = 'Missing filename in entry %d.';
|
SErrMissingFileName = 'Missing filename in entry %d.';
|
||||||
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.';
|
||||||
SErrFileTooLarge = 'File size %d is larger than maximum supported size %d.';
|
|
||||||
SErrPosTooLarge = 'Position/offset %d is larger than maximum supported %d.';
|
SErrPosTooLarge = 'Position/offset %d is larger than maximum supported %d.';
|
||||||
SErrNoFileName = 'No archive filename for examine operation.';
|
SErrNoFileName = 'No archive filename for examine operation.';
|
||||||
SErrNoStream = 'No stream is opened.';
|
SErrNoStream = 'No stream is opened.';
|
||||||
@ -586,6 +587,50 @@ ResourceString
|
|||||||
{ ---------------------------------------------------------------------
|
{ ---------------------------------------------------------------------
|
||||||
Auxiliary
|
Auxiliary
|
||||||
---------------------------------------------------------------------}
|
---------------------------------------------------------------------}
|
||||||
|
Type
|
||||||
|
// A local version of TFileStream which uses rawbytestring. It
|
||||||
|
TFileStream = class(THandleStream)
|
||||||
|
Private
|
||||||
|
FFileName : RawBytestring;
|
||||||
|
public
|
||||||
|
constructor Create(const AFileName: RawBytestring; Mode: Word);
|
||||||
|
constructor Create(const AFileName: RawBytestring; Mode: Word; Rights: Cardinal);
|
||||||
|
destructor Destroy; override;
|
||||||
|
property FileName : RawBytestring Read FFilename;
|
||||||
|
end;
|
||||||
|
constructor TFileStream.Create(const AFileName: rawbytestring; Mode: Word);
|
||||||
|
|
||||||
|
begin
|
||||||
|
Create(AFileName,Mode,438);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
constructor TFileStream.Create(const AFileName: rawbytestring; Mode: Word; Rights: Cardinal);
|
||||||
|
|
||||||
|
Var
|
||||||
|
H : Thandle;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FFileName:=AFileName;
|
||||||
|
If (Mode and fmCreate) > 0 then
|
||||||
|
H:=FileCreate(AFileName,Mode,Rights)
|
||||||
|
else
|
||||||
|
H:=FileOpen(AFileName,Mode);
|
||||||
|
|
||||||
|
If (THandle(H)=feInvalidHandle) then
|
||||||
|
If Mode=fmcreate then
|
||||||
|
raise EFCreateError.createfmt(SFCreateError,[AFileName])
|
||||||
|
else
|
||||||
|
raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
|
||||||
|
Inherited Create(H);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
destructor TFileStream.Destroy;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FileClose(Handle);
|
||||||
|
end;
|
||||||
|
|
||||||
{$IFDEF FPC_BIG_ENDIAN}
|
{$IFDEF FPC_BIG_ENDIAN}
|
||||||
function SwapLFH(const Values: Local_File_Header_Type): Local_File_Header_Type;
|
function SwapLFH(const Values: Local_File_Header_Type): Local_File_Header_Type;
|
||||||
@ -1815,7 +1860,7 @@ begin
|
|||||||
SaveToFile(FileName);
|
SaveToFile(FileName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TZipper.SaveToFile(AFileName: string);
|
procedure TZipper.SaveToFile(AFileName: RawByteString);
|
||||||
var
|
var
|
||||||
lStream: TFileStream;
|
lStream: TFileStream;
|
||||||
begin
|
begin
|
||||||
@ -1860,7 +1905,7 @@ begin
|
|||||||
FBufSize:=Value;
|
FBufSize:=Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Procedure TZipper.SetFileName(Value : String);
|
Procedure TZipper.SetFileName(Value : RawByteString);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
If FZipping then
|
If FZipping then
|
||||||
@ -1868,7 +1913,7 @@ begin
|
|||||||
FFileName:=Value;
|
FFileName:=Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Procedure TZipper.ZipFiles(AFileName : String; FileList : TStrings);
|
Procedure TZipper.ZipFiles(AFileName : RawByteString; FileList : TStrings);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FFileName:=AFileName;
|
FFileName:=AFileName;
|
||||||
@ -1881,7 +1926,7 @@ begin
|
|||||||
ZipAllFiles;
|
ZipAllFiles;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TZipper.ZipFiles(AFileName: String; Entries: TZipFileEntries);
|
procedure TZipper.ZipFiles(AFileName: RawByteString; Entries: TZipFileEntries);
|
||||||
begin
|
begin
|
||||||
FFileName:=AFileName;
|
FFileName:=AFileName;
|
||||||
ZipFiles(Entries);
|
ZipFiles(Entries);
|
||||||
@ -1969,7 +2014,6 @@ begin
|
|||||||
Inherited;
|
Inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ ---------------------------------------------------------------------
|
{ ---------------------------------------------------------------------
|
||||||
TUnZipper
|
TUnZipper
|
||||||
---------------------------------------------------------------------}
|
---------------------------------------------------------------------}
|
||||||
@ -1985,10 +2029,11 @@ End;
|
|||||||
|
|
||||||
|
|
||||||
function TUnZipper.OpenOutput(OutFileName: RawByteString;
|
function TUnZipper.OpenOutput(OutFileName: RawByteString;
|
||||||
var OutStream: TStream; Item: TFullZipFileEntry): Boolean;
|
out OutStream: TStream; Item: TFullZipFileEntry): Boolean;
|
||||||
Var
|
Var
|
||||||
Path: String;
|
Path: RawByteString;
|
||||||
OldDirectorySeparators: set of char;
|
OldDirectorySeparators: set of char;
|
||||||
|
|
||||||
Begin
|
Begin
|
||||||
{ the default RTL behavior is broken on Unix platforms
|
{ the default RTL behavior is broken on Unix platforms
|
||||||
for Windows compatibility: it allows both '/' and '\'
|
for Windows compatibility: it allows both '/' and '\'
|
||||||
@ -2023,6 +2068,7 @@ Begin
|
|||||||
ForceDirectories(Path);
|
ForceDirectories(Path);
|
||||||
AllowDirectorySeparators:=OldDirectorySeparators;
|
AllowDirectorySeparators:=OldDirectorySeparators;
|
||||||
OutStream:=TFileStream.Create(OutFileName,fmCreate);
|
OutStream:=TFileStream.Create(OutFileName,fmCreate);
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
AllowDirectorySeparators:=OldDirectorySeparators;
|
AllowDirectorySeparators:=OldDirectorySeparators;
|
||||||
@ -2398,7 +2444,7 @@ Begin
|
|||||||
if CRC32Str(S)=Infozip_unicode_path_crc32 then
|
if CRC32Str(S)=Infozip_unicode_path_crc32 then
|
||||||
begin
|
begin
|
||||||
SetLength(U,ExtraFieldHeader.Data_Size-5);
|
SetLength(U,ExtraFieldHeader.Data_Size-5);
|
||||||
FZipStream.ReadBuffer(U[1],Length(U));
|
FZipStream.ReadBuffer(U[1],Length(U));
|
||||||
NewNode.UTF8ArchiveFileName:=U;
|
NewNode.UTF8ArchiveFileName:=U;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -2434,42 +2480,99 @@ end;
|
|||||||
procedure TUnZipper.UnZipOneFile(Item: TFullZipFileEntry);
|
procedure TUnZipper.UnZipOneFile(Item: TFullZipFileEntry);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
Count: int64;
|
|
||||||
Attrs: Longint;
|
|
||||||
ZMethod : Word;
|
ZMethod : Word;
|
||||||
|
{$ifdef unix}
|
||||||
LinkTargetStream: TStringStream;
|
LinkTargetStream: TStringStream;
|
||||||
|
{$endif}
|
||||||
OutputFileName: RawByteString;
|
OutputFileName: RawByteString;
|
||||||
FOutStream: TStream;
|
FOutStream: TStream;
|
||||||
IsLink: Boolean;
|
IsLink: Boolean;
|
||||||
IsCustomStream: Boolean;
|
IsCustomStream: Boolean;
|
||||||
|
U : UnicodeString;
|
||||||
|
|
||||||
procedure DoUnzip(const Dest: TStream);
|
Procedure SetAttributes;
|
||||||
|
Var
|
||||||
|
Attrs : Longint;
|
||||||
begin
|
begin
|
||||||
if ZMethod=0 then
|
// set attributes
|
||||||
begin
|
FileSetDate(OutputFileName, DateTimeToFileDate(Item.DateTime));
|
||||||
if (LocalHdr.Compressed_Size<>0) then
|
if (Item.Attributes <> 0) then
|
||||||
|
begin
|
||||||
|
Attrs := 0;
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
if (Item.OS in [OS_UNIX,OS_OSX]) then Attrs := Item.Attributes;
|
||||||
|
if (Item.OS in [OS_FAT,OS_NTFS,OS_OS2,OS_VFAT]) then
|
||||||
|
Attrs := ZipFatAttrsToUnixAttrs(Item.Attributes);
|
||||||
|
{$ELSE}
|
||||||
|
if (Item.OS in [OS_FAT,OS_NTFS,OS_OS2,OS_VFAT]) then Attrs := Item.Attributes;
|
||||||
|
if (Item.OS in [OS_UNIX,OS_OSX]) then
|
||||||
|
Attrs := ZipUnixAttrsToFatAttrs(ExtractFileName(Item.ArchiveFileName), Item.Attributes);
|
||||||
|
{$ENDIF}
|
||||||
|
if Attrs <> 0 then
|
||||||
begin
|
begin
|
||||||
if LocalZip64Fld.Compressed_Size>0 then
|
{$IFDEF UNIX}
|
||||||
Count:=Dest.CopyFrom(FZipStream,LocalZip64Fld.Compressed_Size)
|
FpChmod(OutputFileName, Attrs);
|
||||||
else
|
{$ELSE}
|
||||||
Count:=Dest.CopyFrom(FZipStream,LocalHdr.Compressed_Size);
|
FileSetAttr(OutputFileName, Attrs);
|
||||||
{$warning TODO: Implement CRC Check}
|
{$ENDIF}
|
||||||
end
|
end;
|
||||||
else
|
|
||||||
Count:=0;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
With CreateDecompressor(Item, ZMethod, FZipStream, Dest) do
|
|
||||||
Try
|
|
||||||
OnProgress:=Self.OnProgress;
|
|
||||||
OnPercent:=Self.OnPercent;
|
|
||||||
DeCompress;
|
|
||||||
if Item.CRC32 <> Crc32Val then
|
|
||||||
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]);
|
|
||||||
Finally
|
|
||||||
Free;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure DoUnzip(const Dest: TStream);
|
||||||
|
|
||||||
|
begin
|
||||||
|
if ZMethod=0 then
|
||||||
|
begin
|
||||||
|
if (LocalHdr.Compressed_Size<>0) then
|
||||||
|
begin
|
||||||
|
if LocalZip64Fld.Compressed_Size>0 then
|
||||||
|
Dest.CopyFrom(FZipStream,LocalZip64Fld.Compressed_Size)
|
||||||
|
else
|
||||||
|
Dest.CopyFrom(FZipStream,LocalHdr.Compressed_Size);
|
||||||
|
{$warning TODO: Implement CRC Check}
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
With CreateDecompressor(Item, ZMethod, FZipStream, Dest) do
|
||||||
|
Try
|
||||||
|
OnProgress:=Self.OnProgress;
|
||||||
|
OnPercent:=Self.OnPercent;
|
||||||
|
DeCompress;
|
||||||
|
if Item.CRC32 <> Crc32Val then
|
||||||
|
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]);
|
||||||
|
Finally
|
||||||
|
Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure GetOutputFileName;
|
||||||
|
|
||||||
|
Var
|
||||||
|
I : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if Not UseUTF8 then
|
||||||
|
OutputFileName:=StringReplace(Item.DiskFileName,'/',DirectorySeparator,[rfReplaceAll])
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// Sets codepage.
|
||||||
|
OutputFileName:=Item.UTF8DiskFileName;
|
||||||
|
U:=UTF8Decode(OutputFileName);
|
||||||
|
// Do not use stringreplace, it will mess up the codepage.
|
||||||
|
if '/'<>DirectorySeparator then
|
||||||
|
For I:=1 to Length(U) do
|
||||||
|
if U[i]='/' then
|
||||||
|
U[i]:=DirectorySeparator;
|
||||||
|
OutputFileName:=UTF8Encode(U);
|
||||||
|
end;
|
||||||
|
if (Not IsCustomStream) and (FOutputPath<>'') then
|
||||||
|
begin
|
||||||
|
// Do not use IncludeTrailingPathdelimiter
|
||||||
|
OutputFileName:=FOutputPath+OutputFileName;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
Begin
|
Begin
|
||||||
ReadZipHeader(Item, ZMethod);
|
ReadZipHeader(Item, ZMethod);
|
||||||
if (Item.BitFlags and 1)<>0 then
|
if (Item.BitFlags and 1)<>0 then
|
||||||
@ -2478,30 +2581,19 @@ Begin
|
|||||||
Raise EZipError.CreateFmt(SErrPatchSetNotSupported,[Item.ArchiveFileName]);
|
Raise EZipError.CreateFmt(SErrPatchSetNotSupported,[Item.ArchiveFileName]);
|
||||||
// Normalize output filename to conventions of target platform.
|
// Normalize output filename to conventions of target platform.
|
||||||
// Zip file always has / path separators
|
// Zip file always has / path separators
|
||||||
|
|
||||||
if UseUTF8 then
|
|
||||||
OutputFileName:=StringReplace(Item.UTF8DiskFileName,'/',DirectorySeparator,[rfReplaceAll])
|
|
||||||
else
|
|
||||||
OutputFileName:=StringReplace(Item.DiskFileName,'/',DirectorySeparator,[rfReplaceAll]);
|
|
||||||
|
|
||||||
IsCustomStream := Assigned(FOnCreateStream);
|
IsCustomStream := Assigned(FOnCreateStream);
|
||||||
|
GetOutputFileName;
|
||||||
if (IsCustomStream = False) and (FOutputPath<>'') then
|
|
||||||
OutputFileName:=IncludeTrailingPathDelimiter(FOutputPath)+OutputFileName;
|
|
||||||
|
|
||||||
IsLink := Item.IsLink;
|
IsLink := Item.IsLink;
|
||||||
|
|
||||||
{$IFNDEF UNIX}
|
{$IFNDEF UNIX}
|
||||||
if IsLink and Not IsCustomStream then
|
if IsLink and Not IsCustomStream then
|
||||||
begin
|
begin
|
||||||
{$warning TODO: Implement symbolic link creation for non-unix, e.g.
|
{$warning TODO: Implement symbolic link creation for non-unix, e.g.
|
||||||
Windows NTFS}
|
Windows NTFS}
|
||||||
IsLink := False;
|
IsLink := False;
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
if IsCustomStream then
|
if IsCustomStream then
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
OpenOutput(OutputFileName, FOutStream, Item);
|
OpenOutput(OutputFileName, FOutStream, Item);
|
||||||
if (IsLink = False) and (Item.IsDirectory = False) then
|
if (IsLink = False) and (Item.IsDirectory = False) then
|
||||||
@ -2509,65 +2601,34 @@ Begin
|
|||||||
Finally
|
Finally
|
||||||
CloseOutput(Item, FOutStream);
|
CloseOutput(Item, FOutStream);
|
||||||
end;
|
end;
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if IsLink then
|
|
||||||
begin
|
|
||||||
{$IFDEF UNIX}
|
|
||||||
LinkTargetStream := TStringStream.Create('');
|
|
||||||
try
|
|
||||||
DoUnzip(LinkTargetStream);
|
|
||||||
fpSymlink(PChar(LinkTargetStream.DataString), PChar(OutputFileName));
|
|
||||||
finally
|
|
||||||
LinkTargetStream.Free;
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if Item.IsDirectory then
|
if IsLink then
|
||||||
CreateDir(OutputFileName)
|
|
||||||
else
|
|
||||||
begin
|
begin
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
LinkTargetStream := TStringStream.Create('');
|
||||||
try
|
try
|
||||||
OpenOutput(OutputFileName, FOutStream, Item);
|
DoUnzip(LinkTargetStream);
|
||||||
DoUnzip(FOutStream);
|
fpSymlink(PChar(LinkTargetStream.DataString), PChar(OutputFileName));
|
||||||
Finally
|
finally
|
||||||
CloseOutput(Item, FOutStream);
|
LinkTargetStream.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
{$ENDIF}
|
||||||
end;
|
end
|
||||||
end;
|
else if Item.IsDirectory then
|
||||||
|
CreateDir(OutputFileName)
|
||||||
if Not IsCustomStream then
|
else
|
||||||
begin
|
|
||||||
// set attributes
|
|
||||||
FileSetDate(OutputFileName, DateTimeToFileDate(Item.DateTime));
|
|
||||||
|
|
||||||
if (Item.Attributes <> 0) then
|
|
||||||
begin
|
|
||||||
Attrs := 0;
|
|
||||||
{$IFDEF UNIX}
|
|
||||||
if (Item.OS in [OS_UNIX,OS_OSX]) then Attrs := Item.Attributes;
|
|
||||||
if (Item.OS in [OS_FAT,OS_NTFS,OS_OS2,OS_VFAT]) then
|
|
||||||
Attrs := ZipFatAttrsToUnixAttrs(Item.Attributes);
|
|
||||||
{$ELSE}
|
|
||||||
if (Item.OS in [OS_FAT,OS_NTFS,OS_OS2,OS_VFAT]) then Attrs := Item.Attributes;
|
|
||||||
if (Item.OS in [OS_UNIX,OS_OSX]) then
|
|
||||||
Attrs := ZipUnixAttrsToFatAttrs(ExtractFileName(Item.ArchiveFileName), Item.Attributes);
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
if Attrs <> 0 then
|
|
||||||
begin
|
begin
|
||||||
{$IFDEF UNIX}
|
try
|
||||||
FpChmod(OutputFileName, Attrs);
|
OpenOutput(OutputFileName, FOutStream, Item);
|
||||||
{$ELSE}
|
DoUnzip(FOutStream);
|
||||||
FileSetAttr(OutputFileName, Attrs);
|
Finally
|
||||||
{$ENDIF}
|
CloseOutput(Item, FOutStream);
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
SetAttributes;
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -2618,7 +2679,7 @@ begin
|
|||||||
FBufSize:=Value;
|
FBufSize:=Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TUnZipper.SetFileName(Value: String);
|
procedure TUnZipper.SetFileName(Value: RawByteString);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
If FUnZipping then
|
If FUnZipping then
|
||||||
@ -2626,14 +2687,25 @@ begin
|
|||||||
FFileName:=Value;
|
FFileName:=Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TUnZipper.SetOutputPath(Value: String);
|
procedure TUnZipper.SetOutputPath(Value: RawByteString);
|
||||||
|
|
||||||
|
Var
|
||||||
|
DS : RawByteString;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
If FUnZipping then
|
If FUnZipping then
|
||||||
Raise EZipError.Create(SErrFileChange);
|
Raise EZipError.Create(SErrFileChange);
|
||||||
FOutputPath:=Value;
|
FOutputPath:=Value;
|
||||||
|
If (FOutputPath<>'') and (FoutputPath[Length(FoutputPath)]<>DirectorySeparator) then
|
||||||
|
begin
|
||||||
|
// Preserve codepage of outputpath
|
||||||
|
DS:=DirectorySeparator;
|
||||||
|
SetCodePage(DS,StringCodePage(FoutputPath),False);
|
||||||
|
FOutputPath:=FoutputPath+DS;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TUnZipper.UnZipFiles(AFileName: String; FileList: TStrings);
|
procedure TUnZipper.UnZipFiles(AFileName: RawByteString; FileList: TStrings);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FFileName:=AFileName;
|
FFileName:=AFileName;
|
||||||
@ -2646,7 +2718,7 @@ begin
|
|||||||
UnZipAllFiles;
|
UnZipAllFiles;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TUnZipper.UnZipAllFiles(AFileName: String);
|
procedure TUnZipper.UnZipAllFiles(AFileName: RawByteString);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FFileName:=AFileName;
|
FFileName:=AFileName;
|
||||||
|
Loading…
Reference in New Issue
Block a user