index c73811a3c447bd639755ddd8587c52804610428a..f9e54ad57f88f597a6a56fdf8e0fac7b8b1f4136 100644 (file)
// - File must start with LFH or EOCD signature
// - EOCD must be located strictly at the end of file
// - Multi-disk ZIP files are not supported
-// - UTF-8 not supported yet, expected WIN1251 encoding
+// - Expect UTF-8 or CP1251 encoded names
// - ZIP64 not supported
// - Encryption not supported
// - Zero-length file names not supported
ZIP_ENCRYPTION_MASK = (1 << 0) or (1 << 6) or (1 << 13);
ZIP_UTF8_MASK = (1 << 11);
+ function IsASCII(const s: AnsiString): Boolean;
+ var i: Integer;
+ begin
+ for i := 1 to Length(s) do
+ begin
+ if s[i] >= #$80 then
+ begin
+ Result := False;
+ exit;
+ end;
+ end;
+ Result := True;
+ end;
+
+ function IsUTF8(const s: AnsiString): Boolean;
+ var i, j, len: Integer;
+ begin
+ Result := False;
+ i := 1; len := Length(s);
+ while i <= len do
+ begin
+ case Ord(s[i]) of
+ $00..$7F: j := 0;
+ $80..$BF: exit; // invalid encoding
+ $C0..$DF: j := 1;
+ $E0..$EF: j := 2;
+ $F0..$F7: j := 3;
+ otherwise exit; // invalid encoding
+ end;
+ Inc(i);
+ while j > 0 do
+ begin
+ if i > len then exit; // invlid length
+ case Ord(s[i]) of
+ $80..$BF: ; // ok
+ else exit; // invalid encoding
+ end;
+ Inc(i);
+ Dec(j);
+ end;
+ end;
+ Result := True;
+ end;
+
procedure ToSectionFile(fname: AnsiString; out section, name: AnsiString); inline;
var i: SizeInt;
begin
var mypos, next: UInt64;
var name: PChar;
var aname: AnsiString;
+ var cvtbug, utf8: Boolean;
begin
mypos := s.Position;
s.ReadBuffer(sig[0], 4);
e_WriteLog('CDR#' + IntToStr(cdrid) + ' @' + IntToHex(mypos, 8) + ': External Attrib : $' + IntToHex(eattr, 8), MSG_NOTIFY);
e_WriteLog('CDR#' + IntToStr(cdrid) + ' @' + IntToHex(mypos, 8) + ': LFH Offset : $' + IntToHex(offset, 8), MSG_NOTIFY);
end;
+ cvtbug := False;
+ if (vva = $10) and (vvb = $0A) and (va = $10) and (vb = $00) and (flags = (1 << 10)) and (mtime = 0) and (iattr = 0) and (eattr = 0) then
+ begin
+ // HACK: Editor and wadcvt for long time sets incorrent flag for UTF-8
+ flags := ZIP_UTF8_MASK;
+ cvtbug := True;
+ end;
+ if gWADEditorLogLevel >= DFWAD_LOG_DEBUG then
+ e_WriteLog('CDR#' + IntToStr(cdrid) + ' @' + IntToHex(mypos, 8) + ': WADCVT BUG : ' + BoolToStr(cvtbug, True), MSG_NOTIFY);
if (va >= 10) and (va <= ZIP_MAXVERSION) then
begin
if (flags and ZIP_ENCRYPTION_MASK) = 0 then
try
s.ReadBuffer(name[0], fnlen);
name[fnlen] := #0;
- // TODO: when packer version < 63 detect utf8 by hands?
- if flags and ZIP_UTF8_MASK = 0 then
- aname := win2utf(name)
- else
- aname := name;
+ aname := name;
+ utf8 := True;
+ if (flags and ZIP_UTF8_MASK = 0) and (IsUTF8(name) = False) then
+ begin
+ aname := win2utf(aname);
+ utf8 := False;
+ end;
if gWADEditorLogLevel >= DFWAD_LOG_DEBUG then
+ begin
+ e_WriteLog('CDR#' + IntToStr(cdrid) + ' @' + IntToHex(mypos, 8) + ': UTF-8 Comatible : ' + BoolToStr(utf8, True), MSG_NOTIFY);
e_WriteLog('CDR#' + IntToStr(cdrid) + ' @' + IntToHex(mypos, 8) + ': Name : "' + aname + '"', MSG_NOTIFY);
+ end;
s.Seek(offset, TSeekOrigin.soBeginning);
ReadLFH(s, aname, csize, usize, comp, crc);
finally
end;
end;
- function IsASCII(const s: AnsiString): Boolean;
- var i: Integer;
- begin
- for i := 1 to Length(s) do
- begin
- if s[i] >= #$80 then
- begin
- Result := False;
- exit;
- end;
- end;
- Result := True;
- end;
-
function GetZIPVersion(const afname: AnsiString; flags, comp: UInt16): UInt8;
var version: UInt8;
begin