* Patch from Margérs to fix bug #32281 (zip/unzip files >4Gb)

git-svn-id: trunk@40215 -
This commit is contained in:
michael 2018-11-04 12:03:32 +00:00
parent cf4496aa1e
commit 79dc736a69

View File

@ -1609,6 +1609,8 @@ Begin
begin begin
Compressed_Size := FZip.Size; Compressed_Size := FZip.Size;
LocalZip64Fld.Compressed_Size := 0; LocalZip64Fld.Compressed_Size := 0;
if LocalZip64Fld.Original_Size > 0 then
IsZip64 := true;
end; end;
if AZipVersionReqd > Extract_Version_Reqd then if AZipVersionReqd > Extract_Version_Reqd then
Extract_Version_Reqd := AZipVersionReqd; Extract_Version_Reqd := AZipVersionReqd;
@ -1623,7 +1625,6 @@ Begin
FOutStream.WriteBuffer(ZFileName[1],Length(ZFileName)); FOutStream.WriteBuffer(ZFileName[1],Length(ZFileName));
if IsZip64 then if IsZip64 then
begin begin
LocalZip64ExtHdr.Header_ID:=ZIP64_HEADER_ID;
FOutStream.WriteBuffer({$IFDEF ENDIAN_BIG}SwapEDFH{$ENDIF}(LocalZip64ExtHdr),SizeOf(LocalZip64ExtHdr)); FOutStream.WriteBuffer({$IFDEF ENDIAN_BIG}SwapEDFH{$ENDIF}(LocalZip64ExtHdr),SizeOf(LocalZip64ExtHdr));
FOutStream.WriteBuffer({$IFDEF ENDIAN_BIG}SwapZ64EIF{$ENDIF}(LocalZip64Fld),SizeOf(LocalZip64Fld)); FOutStream.WriteBuffer({$IFDEF ENDIAN_BIG}SwapZ64EIF{$ENDIF}(LocalZip64Fld),SizeOf(LocalZip64Fld));
end; end;
@ -1682,7 +1683,7 @@ Begin
end; end;
end; end;
// Move past extra fields // Move past extra fields
FOutStream.Seek(SavePos+LocalHdr.Extra_Field_Length,soFromBeginning); //FOutStream.Seek(SavePos+LocalHdr.Extra_Field_Length,soFromBeginning);
end; end;
SavePos := FOutStream.Position; SavePos := FOutStream.Position;
FillChar(CentralHdr,SizeOf(CentralHdr),0); FillChar(CentralHdr,SizeOf(CentralHdr),0);
@ -1732,9 +1733,16 @@ Begin
else else
Local_Header_Offset := HdrPos; Local_Header_Offset := HdrPos;
end; end;
if IsZip64 then
begin
CentralHdr.Extra_Field_Length:=SizeOf(LocalZip64ExtHdr)+SizeOf(LocalZip64Fld);
end else CentralHdr.Extra_Field_Length :=0;
FOutStream.Seek(0,soEnd); FOutStream.Seek(0,soEnd);
FOutStream.WriteBuffer({$IFDEF FPC_BIG_ENDIAN}SwapCFH{$ENDIF}(CentralHdr),SizeOf(CentralHdr)); FOutStream.WriteBuffer({$IFDEF FPC_BIG_ENDIAN}SwapCFH{$ENDIF}(CentralHdr),SizeOf(CentralHdr));
FOutStream.WriteBuffer(ZFileName[1],Length(ZFileName)); FOutStream.WriteBuffer(ZFileName[1],Length(ZFileName));
if IsZip64 then if IsZip64 then
begin begin
FOutStream.Seek(0,soEnd); FOutStream.Seek(0,soEnd);
@ -1744,7 +1752,7 @@ Begin
Inc(ACount); Inc(ACount);
// Move past compressed file data to next header: // Move past compressed file data to next header:
if Iszip64 then if LocalZip64Fld.Compressed_Size > 0 then
FOutStream.Seek(SavePos + LocalZip64Fld.Compressed_Size,soBeginning) FOutStream.Seek(SavePos + LocalZip64Fld.Compressed_Size,soBeginning)
else else
FOutStream.Seek(SavePos + LocalHdr.Compressed_Size,soBeginning); FOutStream.Seek(SavePos + LocalHdr.Compressed_Size,soBeginning);
@ -2093,7 +2101,7 @@ function TUnZipper.OpenOutput(OutFileName: RawByteString;
Var Var
Path: RawByteString; 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 '\'
@ -2521,7 +2529,10 @@ Begin
end; end;
end; end;
// Move past extra fields and file comment to next header // Move past extra fields and file comment to next header
FZipStream.Seek(SavePos+Extra_Field_Length+File_Comment_Length,soFromBeginning); if File_Comment_Length > 0 then
FZipStream.Seek(File_Comment_Length,soFromCurrent);
// this doesn't work properly when zip file size is over 4Gb, so commented off
//FZipStream.Seek(SavePos+Extra_Field_Length+File_Comment_Length,soFromBeginning);
end; end;
end; end;
end; end;
@ -2605,7 +2616,7 @@ Var
OnProgress:=Self.OnProgress; OnProgress:=Self.OnProgress;
OnPercent:=Self.OnPercent; OnPercent:=Self.OnPercent;
DeCompress; DeCompress;
Self.FTotPos := FTotPos; Self.FTotPos := FTotPos;
if Item.CRC32 <> Crc32Val then if Item.CRC32 <> Crc32Val then
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]); raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]);
Finally Finally