mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
FIX: Zip - determine encoding when GetACP = GetOEMCP (Windows)
This commit is contained in:
parent
5cc27c528a
commit
7fc2f7db91
2 changed files with 130 additions and 59 deletions
|
|
@ -1499,25 +1499,14 @@ begin
|
|||
SetString(UnicodeName, XceedField.UnicodeName, XceedField.Length);
|
||||
FFileName := Utf16ToUtf8(UnicodeName);
|
||||
end
|
||||
else
|
||||
begin
|
||||
else begin
|
||||
SystemCode := HostOS;
|
||||
{$IF DEFINED(MSWINDOWS)}
|
||||
if (GetACP <> GetOEMCP) and (SystemCode = hosDOS) then
|
||||
FFileName := CeOemToUtf8(FItemInfo.FileName)
|
||||
else if (GetACP <> GetOEMCP) and CeTryDecode(FItemInfo.FileName, CP_OEMCP, UnicodeName) then
|
||||
FFileName := Utf16ToUtf8(UnicodeName)
|
||||
else if (SystemCode = hosNTFS) or (SystemCode = hosWinNT) then
|
||||
FFileName := CeAnsiToUtf8(FItemInfo.FileName)
|
||||
else
|
||||
{$ELSEIF DEFINED(UNIX)}
|
||||
if (SystemCode = hosDOS) then
|
||||
FFileName := CeOemToUtf8(FItemInfo.FileName)
|
||||
else if (SystemCode = hosNTFS) or (SystemCode = hosWinNT) then
|
||||
FFileName := CeAnsiToUtf8(FItemInfo.FileName)
|
||||
else
|
||||
{$ENDIF}
|
||||
FFileName := FItemInfo.FileName;
|
||||
FFileName := CeSysToUtf8(FItemInfo.FileName);
|
||||
end;
|
||||
|
||||
{ read ZIP64 extended header }
|
||||
|
|
@ -1684,6 +1673,7 @@ procedure TAbZipItem.SetFileName(const Value : string );
|
|||
var
|
||||
{$IFDEF MSWINDOWS}
|
||||
AnsiName : AnsiString;
|
||||
UnicName : UnicodeString;
|
||||
{$ENDIF}
|
||||
UTF8Name : AnsiString;
|
||||
FieldSize : Word;
|
||||
|
|
@ -1695,9 +1685,10 @@ begin
|
|||
{$IFDEF MSWINDOWS}
|
||||
FItemInfo.IsUTF8 := False;
|
||||
HostOS := hosDOS;
|
||||
if CeTryEncode(UTF8Decode(Value), CP_OEMCP, False, AnsiName) then
|
||||
UnicName := UTF8Decode(Value);
|
||||
if CeTryEncode(UnicName, CP_OEMCP, False, AnsiName) then
|
||||
{no-op}
|
||||
else if (GetACP <> GetOEMCP) and CeTryEncode(UTF8Decode(Value), CP_ACP, False, AnsiName) then
|
||||
else if (GetACP <> GetOEMCP) and CeTryEncode(UnicName, CP_ACP, False, AnsiName) then
|
||||
HostOS := hosWinNT
|
||||
else
|
||||
FItemInfo.IsUTF8 := True;
|
||||
|
|
|
|||
|
|
@ -2766,9 +2766,18 @@ Index: AbZipPrc.pas
|
|||
Item.ExternalFileAttributes := LongWord(AttrEx.Mode) shl 16 + LongWord(AttrEx.Attr);
|
||||
Index: AbZipTyp.pas
|
||||
===================================================================
|
||||
--- AbZipTyp.pas (revision 512)
|
||||
--- AbZipTyp.pas (revision 539)
|
||||
+++ AbZipTyp.pas (working copy)
|
||||
@@ -169,7 +169,7 @@
|
||||
@@ -67,6 +67,8 @@
|
||||
AbLanguageEncodingFlag = $0800;
|
||||
|
||||
Ab_Zip64SubfieldID : Word = $0001;
|
||||
+ Ab_NTFSSubfieldID : Word = $000A;
|
||||
+ Ab_InfoZipTimestampSubfieldID : Word = $5455;
|
||||
Ab_InfoZipUnicodePathSubfieldID : Word = $7075;
|
||||
Ab_XceedUnicodePathSubfieldID : Word = $554E;
|
||||
Ab_XceedUnicodePathSignature : LongWord= $5843554E;
|
||||
@@ -169,7 +171,7 @@
|
||||
(cmStored, cmShrunk, cmReduced1, cmReduced2, cmReduced3,
|
||||
cmReduced4, cmImploded, cmTokenized, cmDeflated,
|
||||
cmEnhancedDeflated, cmDCLImploded, cmBzip2 = 12, cmLZMA = 14,
|
||||
|
|
@ -2777,7 +2786,7 @@ Index: AbZipTyp.pas
|
|||
|
||||
TAbZipSupportedMethod =
|
||||
(smStored, smDeflated, smBestMethod);
|
||||
@@ -206,6 +206,7 @@
|
||||
@@ -206,6 +208,7 @@
|
||||
FCompressedSize : Int64;
|
||||
FUncompressedSize : Int64;
|
||||
public {methods}
|
||||
|
|
@ -2785,7 +2794,15 @@ Index: AbZipTyp.pas
|
|||
procedure SaveToStream( Stream : TStream );
|
||||
public {properties}
|
||||
property CRC32 : Longint
|
||||
@@ -407,6 +408,7 @@
|
||||
@@ -369,6 +372,7 @@
|
||||
FDiskNumberStart : LongWord;
|
||||
FLFHExtraField : TAbExtraField;
|
||||
FRelativeOffset : Int64;
|
||||
+ FDateTime : TDateTime;
|
||||
|
||||
protected {methods}
|
||||
function GetCompressionMethod : TAbZipCompressionMethod;
|
||||
@@ -407,6 +411,7 @@
|
||||
function GetLastModFileDate : Word; override;
|
||||
function GetLastModFileTime : Word; override;
|
||||
function GetNativeFileAttributes : LongInt; override;
|
||||
|
|
@ -2793,7 +2810,7 @@ Index: AbZipTyp.pas
|
|||
procedure SetCompressedSize( const Value : Int64 ); override;
|
||||
procedure SetCRC32( const Value : Longint ); override;
|
||||
procedure SetExternalFileAttributes( Value : LongWord ); override;
|
||||
@@ -530,8 +532,8 @@
|
||||
@@ -530,8 +535,8 @@
|
||||
override;
|
||||
destructor Destroy;
|
||||
override;
|
||||
|
|
@ -2804,7 +2821,7 @@ Index: AbZipTyp.pas
|
|||
|
||||
public {properties}
|
||||
property CompressionMethodToUse : TAbZipSupportedMethod
|
||||
@@ -620,11 +622,14 @@
|
||||
@@ -620,11 +625,16 @@
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
Math,
|
||||
|
|
@ -2816,12 +2833,14 @@ Index: AbZipTyp.pas
|
|||
+ SysUtils,
|
||||
+ LazUTF8,
|
||||
+ DCOSUtils,
|
||||
+ DCBasicTypes,
|
||||
+ DCClassesUtf8,
|
||||
+ DCDateTimeUtils,
|
||||
+ DCConvertEncoding;
|
||||
|
||||
function VerifyZip(Strm : TStream) : TAbArchiveType;
|
||||
{ determine if stream appears to be in PkZip format }
|
||||
@@ -638,20 +643,31 @@
|
||||
@@ -638,20 +648,31 @@
|
||||
Result := atUnknown;
|
||||
try
|
||||
Strm.Position := 0;
|
||||
|
|
@ -2867,7 +2886,7 @@ Index: AbZipTyp.pas
|
|||
end;
|
||||
end;
|
||||
except
|
||||
@@ -733,8 +749,7 @@
|
||||
@@ -733,8 +754,7 @@
|
||||
leaves stream positioned at start of structure or at original
|
||||
position if not found }
|
||||
const
|
||||
|
|
@ -2877,7 +2896,7 @@ Index: AbZipTyp.pas
|
|||
var
|
||||
StartPos : Int64;
|
||||
TailRec : TAbZipEndOfCentralDirectoryRecord;
|
||||
@@ -741,7 +756,6 @@
|
||||
@@ -741,7 +761,6 @@
|
||||
Buffer : PAnsiChar;
|
||||
Offset : Int64;
|
||||
TestPos : PAnsiChar;
|
||||
|
|
@ -2885,7 +2904,7 @@ Index: AbZipTyp.pas
|
|||
BytesRead : Int64;
|
||||
BufSize : Int64;
|
||||
CommentLen: integer;
|
||||
@@ -767,7 +781,7 @@
|
||||
@@ -767,7 +786,7 @@
|
||||
stream; we need to search for the tail signature}
|
||||
|
||||
{get a buffer}
|
||||
|
|
@ -2894,7 +2913,7 @@ Index: AbZipTyp.pas
|
|||
GetMem(Buffer, BufSize);
|
||||
try
|
||||
|
||||
@@ -774,57 +788,41 @@
|
||||
@@ -774,57 +793,41 @@
|
||||
{start out searching backwards}
|
||||
Offset := -BufSize;
|
||||
|
||||
|
|
@ -2979,7 +2998,7 @@ Index: AbZipTyp.pas
|
|||
end;
|
||||
|
||||
{if we reach this point, the CD tail is not present}
|
||||
@@ -914,6 +912,17 @@
|
||||
@@ -914,6 +917,17 @@
|
||||
end;
|
||||
{============================================================================}
|
||||
{ TAbZipDataDescriptor implementation ====================================== }
|
||||
|
|
@ -2997,7 +3016,7 @@ Index: AbZipTyp.pas
|
|||
procedure TAbZipDataDescriptor.SaveToStream( Stream : TStream );
|
||||
begin
|
||||
Stream.Write( Ab_ZipDataDescriptorSignature, sizeof( Ab_ZipDataDescriptorSignature ) );
|
||||
@@ -1195,12 +1204,13 @@
|
||||
@@ -1195,12 +1209,13 @@
|
||||
{ TAbZipDirectoryFileFooter implementation ================================= }
|
||||
function TAbZipDirectoryFileFooter.GetIsZip64: Boolean;
|
||||
begin
|
||||
|
|
@ -3017,7 +3036,7 @@ Index: AbZipTyp.pas
|
|||
end;
|
||||
{ -------------------------------------------------------------------------- }
|
||||
procedure TAbZipDirectoryFileFooter.LoadFromStream( Stream : TStream );
|
||||
@@ -1395,10 +1405,17 @@
|
||||
@@ -1395,10 +1410,17 @@
|
||||
Result := Byte(ExternalFileAttributes);
|
||||
{$ENDIF}
|
||||
{$IFDEF UNIX}
|
||||
|
|
@ -3037,7 +3056,7 @@ Index: AbZipTyp.pas
|
|||
{$ENDIF}
|
||||
end;
|
||||
{ -------------------------------------------------------------------------- }
|
||||
@@ -1407,6 +1424,22 @@
|
||||
@@ -1407,6 +1429,30 @@
|
||||
Result := FItemInfo.FileName;
|
||||
end;
|
||||
{ -------------------------------------------------------------------------- }
|
||||
|
|
@ -3049,18 +3068,34 @@ Index: AbZipTyp.pas
|
|||
+begin
|
||||
+ // Zip stores MS-DOS date/time.
|
||||
+{$IFDEF UNIX}
|
||||
+ DateTime := AbDosFileDateToDateTime(LastModFileDate, LastModFileTime);
|
||||
+ Result := AbLocalDateTimeToUnixTime(DateTime);
|
||||
+ if (FDateTime <> 0) then
|
||||
+ DateTime := FDateTime
|
||||
+ else begin
|
||||
+ DateTime := AbDosFileDateToDateTime(LastModFileDate, LastModFileTime);
|
||||
+ end;
|
||||
+ Result := DateTimeToUnixFileTime(DateTime);
|
||||
+{$ELSE}
|
||||
+ LongRec(Result).Hi := LastModFileDate;
|
||||
+ LongRec(Result).Lo := LastModFileTime;
|
||||
+ if (FDateTime <> 0) then
|
||||
+ Result := DateTimeToDosFileTime(FDateTime)
|
||||
+ else begin
|
||||
+ LongRec(Result).Hi := LastModFileDate;
|
||||
+ LongRec(Result).Lo := LastModFileTime;
|
||||
+ end;
|
||||
+{$ENDIF}
|
||||
+end;
|
||||
+{ -------------------------------------------------------------------------- }
|
||||
function TAbZipItem.GetShannonFanoTreeCount : Byte;
|
||||
begin
|
||||
Result := FItemInfo.ShannonFanoTreeCount;
|
||||
@@ -1430,12 +1463,13 @@
|
||||
@@ -1424,6 +1470,7 @@
|
||||
{ -------------------------------------------------------------------------- }
|
||||
procedure TAbZipItem.LoadFromStream( Stream : TStream );
|
||||
var
|
||||
+ Tag, TagSize,
|
||||
FieldSize: Word;
|
||||
FieldStream: TStream;
|
||||
InfoZipField: PInfoZipUnicodePathRec;
|
||||
@@ -1430,12 +1477,13 @@
|
||||
UnicodeName: UnicodeString;
|
||||
UTF8Name: AnsiString;
|
||||
XceedField: PXceedUnicodePathRec;
|
||||
|
|
@ -3076,7 +3111,7 @@ Index: AbZipTyp.pas
|
|||
else if FItemInfo.ExtraField.Get(Ab_InfoZipUnicodePathSubfieldID, Pointer(InfoZipField), FieldSize) and
|
||||
(FieldSize > SizeOf(TInfoZipUnicodePathRec)) and
|
||||
(InfoZipField.Version = 1) and
|
||||
@@ -1442,7 +1476,7 @@
|
||||
@@ -1442,7 +1490,7 @@
|
||||
(InfoZipField.NameCRC32 = AbCRC32Of(FItemInfo.FileName)) then begin
|
||||
SetString(UTF8Name, InfoZipField.UnicodeName,
|
||||
FieldSize - SizeOf(TInfoZipUnicodePathRec) + 1);
|
||||
|
|
@ -3085,7 +3120,7 @@ Index: AbZipTyp.pas
|
|||
end
|
||||
else if FItemInfo.ExtraField.Get(Ab_XceedUnicodePathSubfieldID, Pointer(XceedField), FieldSize) and
|
||||
(FieldSize > SizeOf(TXceedUnicodePathRec)) and
|
||||
@@ -1449,16 +1483,28 @@
|
||||
@@ -1449,16 +1497,17 @@
|
||||
(XceedField.Signature = Ab_XceedUnicodePathSignature) and
|
||||
(XceedField.Length * SizeOf(WideChar) = FieldSize - SizeOf(TXceedUnicodePathRec) + SizeOf(WideChar)) then begin
|
||||
SetString(UnicodeName, XceedField.UnicodeName, XceedField.Length);
|
||||
|
|
@ -3098,39 +3133,84 @@ Index: AbZipTyp.pas
|
|||
- OemToCharBuff(PAnsiChar(FItemInfo.FileName), PChar(FFileName), Length(FFileName));
|
||||
- end
|
||||
- {$ENDIF}
|
||||
else
|
||||
- else
|
||||
- FFileName := string(FItemInfo.FileName);
|
||||
+ begin
|
||||
+ else begin
|
||||
+ SystemCode := HostOS;
|
||||
+ {$IF DEFINED(MSWINDOWS)}
|
||||
+ if (GetACP <> GetOEMCP) and (SystemCode = hosDOS) then
|
||||
+ FFileName := CeOemToUtf8(FItemInfo.FileName)
|
||||
+ else if (GetACP <> GetOEMCP) and CeTryDecode(FItemInfo.FileName, CP_OEMCP, UnicodeName) then
|
||||
+ FFileName := Utf16ToUtf8(UnicodeName)
|
||||
+ else if (SystemCode = hosNTFS) or (SystemCode = hosWinNT) then
|
||||
+ FFileName := CeAnsiToUtf8(FItemInfo.FileName)
|
||||
+ else
|
||||
+ {$ELSEIF DEFINED(UNIX)}
|
||||
+ if (SystemCode = hosDOS) then
|
||||
+ FFileName := CeOemToUtf8(FItemInfo.FileName)
|
||||
+ else if (SystemCode = hosNTFS) or (SystemCode = hosWinNT) then
|
||||
+ FFileName := CeAnsiToUtf8(FItemInfo.FileName)
|
||||
+ else
|
||||
+ {$ENDIF}
|
||||
+ FFileName := FItemInfo.FileName;
|
||||
+ FFileName := CeSysToUtf8(FItemInfo.FileName);
|
||||
+ end;
|
||||
|
||||
{ read ZIP64 extended header }
|
||||
FUncompressedSize := FItemInfo.UncompressedSize;
|
||||
@@ -1596,24 +1642,20 @@
|
||||
@@ -1481,6 +1530,45 @@
|
||||
|
||||
LastModFileTime := FItemInfo.LastModFileTime;
|
||||
LastModFileDate := FItemInfo.LastModFileDate;
|
||||
+ // NTFS Extra Field
|
||||
+ if FItemInfo.ExtraField.GetStream(Ab_NTFSSubfieldID, FieldStream) then
|
||||
+ try
|
||||
+ FieldSize:= FieldStream.Size;
|
||||
+ if (FieldSize >= 32) then
|
||||
+ begin
|
||||
+ // Skip Reserved
|
||||
+ Dec(FieldSize, 4);
|
||||
+ FieldStream.Seek(4, soBeginning);
|
||||
+ while (FieldSize > 4) do
|
||||
+ begin
|
||||
+ Dec(FieldSize, 4);
|
||||
+ Tag:= FieldStream.ReadWord;
|
||||
+ TagSize:= FieldStream.ReadWord;
|
||||
+ TagSize:= Min(TagSize, FieldSize);
|
||||
+ if (Tag = $0001) and (TagSize >= 24) then
|
||||
+ begin
|
||||
+ FDateTime:= WinFileTimeToDateTime(TWinFileTime(FieldStream.ReadQWord));
|
||||
+ Break;
|
||||
+ end;
|
||||
+ Dec(FieldSize, TagSize);
|
||||
+ end;
|
||||
+ end;
|
||||
+ finally
|
||||
+ FieldStream.Free;
|
||||
+ end
|
||||
+ // Extended Timestamp Extra Field
|
||||
+ else if FItemInfo.ExtraField.GetStream(Ab_InfoZipTimestampSubfieldID, FieldStream) then
|
||||
+ try
|
||||
+ FieldSize:= FieldStream.Size;
|
||||
+ if (FieldSize >= 5) then
|
||||
+ begin
|
||||
+ Tag:= FieldStream.ReadByte;
|
||||
+ if (Tag and $01 <> 0) then
|
||||
+ FDateTime:= UnixFileTimeToDateTime(TUnixFileTime(FieldStream.ReadDWord));
|
||||
+ end;
|
||||
+ finally
|
||||
+ FieldStream.Free;
|
||||
+ end;
|
||||
FDiskFileName := FileName;
|
||||
AbUnfixName( FDiskFileName );
|
||||
Action := aaNone;
|
||||
@@ -1585,6 +1673,7 @@
|
||||
var
|
||||
{$IFDEF MSWINDOWS}
|
||||
AnsiName : AnsiString;
|
||||
+ UnicName : UnicodeString;
|
||||
{$ENDIF}
|
||||
UTF8Name : AnsiString;
|
||||
FieldSize : Word;
|
||||
@@ -1596,24 +1685,21 @@
|
||||
{$IFDEF MSWINDOWS}
|
||||
FItemInfo.IsUTF8 := False;
|
||||
HostOS := hosDOS;
|
||||
- if AbTryEncode(Value, CP_OEMCP, False, AnsiName) then
|
||||
+ if CeTryEncode(UTF8Decode(Value), CP_OEMCP, False, AnsiName) then
|
||||
+ UnicName := UTF8Decode(Value);
|
||||
+ if CeTryEncode(UnicName, CP_OEMCP, False, AnsiName) then
|
||||
{no-op}
|
||||
- else if (GetACP <> GetOEMCP) and AbTryEncode(Value, CP_ACP, False, AnsiName) then
|
||||
+ else if (GetACP <> GetOEMCP) and CeTryEncode(UTF8Decode(Value), CP_ACP, False, AnsiName) then
|
||||
+ else if (GetACP <> GetOEMCP) and CeTryEncode(UnicName, CP_ACP, False, AnsiName) then
|
||||
HostOS := hosWinNT
|
||||
- else if AbTryEncode(Value, CP_OEMCP, True, AnsiName) then
|
||||
- {no-op}
|
||||
|
|
@ -3152,7 +3232,7 @@ Index: AbZipTyp.pas
|
|||
{$ENDIF}
|
||||
|
||||
UseExtraField := False;
|
||||
@@ -1626,7 +1668,7 @@
|
||||
@@ -1626,7 +1712,7 @@
|
||||
end;
|
||||
|
||||
if UseExtraField then begin
|
||||
|
|
@ -3161,7 +3241,7 @@ Index: AbZipTyp.pas
|
|||
FieldSize := SizeOf(TInfoZipUnicodePathRec) + Length(UTF8Name) - 1;
|
||||
GetMem(InfoZipField, FieldSize);
|
||||
try
|
||||
@@ -1762,11 +1804,11 @@
|
||||
@@ -1762,11 +1848,11 @@
|
||||
inherited Destroy;
|
||||
end;
|
||||
{ -------------------------------------------------------------------------- }
|
||||
|
|
@ -3176,7 +3256,7 @@ Index: AbZipTyp.pas
|
|||
Result := TAbZipItem.Create;
|
||||
with TAbZipItem( Result ) do begin
|
||||
CompressionMethod := cmDeflated;
|
||||
@@ -1773,9 +1815,17 @@
|
||||
@@ -1773,9 +1859,17 @@
|
||||
GeneralPurposeBitFlag := 0;
|
||||
CompressedSize := 0;
|
||||
CRC32 := 0;
|
||||
|
|
@ -3196,7 +3276,7 @@ Index: AbZipTyp.pas
|
|||
end;
|
||||
end;
|
||||
{ -------------------------------------------------------------------------- }
|
||||
@@ -1930,8 +1980,8 @@
|
||||
@@ -1930,8 +2024,8 @@
|
||||
AbStripDots( lValue );
|
||||
|
||||
for i := 1 to Length( lValue ) do
|
||||
|
|
@ -3207,7 +3287,7 @@ Index: AbZipTyp.pas
|
|||
Result := lValue;
|
||||
end;
|
||||
{ -------------------------------------------------------------------------- }
|
||||
@@ -1983,7 +2033,7 @@
|
||||
@@ -1983,7 +2077,7 @@
|
||||
FStatus := asInvalid; //TODO: Status updates are extremely inconsistent
|
||||
raise EAbUserAbort.Create;
|
||||
end;
|
||||
|
|
@ -3216,7 +3296,7 @@ Index: AbZipTyp.pas
|
|||
TailPosition := FindCentralDirectoryTail( FStream );
|
||||
end;
|
||||
end;
|
||||
@@ -2302,7 +2352,7 @@
|
||||
@@ -2302,7 +2396,7 @@
|
||||
if FOwnsStream then begin
|
||||
{need new stream to write}
|
||||
FreeAndNil(FStream);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue