FreePascal Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
FreePacal 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

FreePascal 팁&트릭
[19] fpc의 zip파일의 winrar등의 파일 이름 지원 패치.
김도완 [purplecofe2] 5258 읽음    2014-12-12 18:59
질문에서 winrar등에서 만들어진 zip파일에서 안되는 것을 보고 패치를 했습니다.
FPC의 packages의 paszlib의 zipper.pp의 내용을 고친 것입니다.

(수정) 파일명으로 할당하는 부분에 대한 추가적인 코드 추가.

Index: packages/paszlib/src/zipper.pp
===================================================================
--- packages/paszlib/src/zipper.pp	(revision 29277)
+++ packages/paszlib/src/zipper.pp	(working copy)
@@ -32,6 +32,8 @@
   LOCAL_FILE_HEADER_SIGNATURE                = $04034B50;
   CENTRAL_FILE_HEADER_SIGNATURE              = $02014B50;
   ZIP64_HEADER_ID                            = $0001;
+  // infozip unicode path
+  INFOZIP_UNICODE_PATH_ID                    = $7075;
 
 Type
    Local_File_Header_Type = Packed Record //1 per zipped file
@@ -757,6 +759,17 @@
       Result := Result or UNIX_FILE;
 end;
 
+function CRC32Str(const s:string):DWord;
+var
+  i:Integer;
+begin
+  Result:=$FFFFFFFF;
+  if Length(S)>0 then
+    for i:=1 to Length(s) do
+      Result:=Crc_32_Tab[Byte(Result XOR LongInt(s[i]))] XOR ((Result SHR 8) AND $00FFFFFF);
+  Result:=not Result;
+end;
+
 { ---------------------------------------------------------------------
     TDeCompressor
   ---------------------------------------------------------------------}
@@ -2031,6 +2044,9 @@
   D : TDateTime;
   ExtraFieldHdr: Extensible_Data_Field_Header_Type;
   SavePos: int64; //could be qword but limited by stream
+  // Infozip unicode path
+  Infozip_Unicode_Path_Ver:Byte;
+  Infozip_Unicode_Path_CRC32:DWord;
 Begin
   FZipStream.Seek(Item.HdrPos,soBeginning);
   FZipStream.ReadBuffer(LocalHdr,SizeOf(LocalHdr));
@@ -2048,7 +2064,7 @@
       if Extra_Field_Length>0 then
         begin
         SavePos := FZipStream.Position;
-        if (LocalHdr.Extra_Field_Length>=SizeOf(ExtraFieldHdr)+SizeOf(LocalZip64Fld)) then
+        if (LocalHdr.Extra_Field_Length>=SizeOf(ExtraFieldHdr)) then
           while FZipStream.Position=20701}
+                    if DefaultSystemCodePage<>CP_UTF8 then
+                      Item.ArchiveFileName:=Utf8ToAnsi(S)
+                      else
+                        Item.ArchiveFileName:=S;
+                    if DefaultRTLFileSystemCodePage<>CP_UTF8 then
+                       Item.DiskFileName:=Utf8ToAnsi(S)
+                       else
+                         Item.DiskFileName:=S;
+                    {$ELSE}
+                    Item.ArchiveFileName:=Utf8ToAnsi(S);
+                    Item.DiskFileName:=Utf8ToAnsi(S);
+                    {$ENDIF}
+                  end else
+                    FZipStream.Seek(ExtraFieldHdr.Data_Size-5,soFromCurrent);
+                end else
+                  FZipStream.Seek(ExtraFieldHdr.Data_Size-1,soFromCurrent);
+              end else
+                FZipStream.Seek(ExtraFieldHdr.Data_Size,soFromCurrent);
             end;
         // Move past extra fields
         FZipStream.Seek(SavePos+Extra_Field_Length,soFromBeginning);
@@ -2229,6 +2276,9 @@
   NewNode   : TFullZipFileEntry;
   D : TDateTime;
   S : String;
+  // infozip unicode path
+  Infozip_unicode_path_ver : byte; // always 1
+  Infozip_unicode_path_crc32 : DWord;
 Begin
   FindEndHeaders(EndHdr, EndHdrPos,
     EndZip64Hdr, EndZip64HdrPos);
@@ -2319,6 +2369,31 @@
               NewNode.HdrPos := Zip64Field.Relative_Hdr_Offset;
               end;
             end
+            // infozip unicode path extra field
+          else if ExtraFieldHeader.Header_ID = INFOZIP_UNICODE_PATH_ID then
+            begin
+              FZipStream.ReadBuffer(Infozip_unicode_path_ver,1);
+              if Infozip_unicode_path_ver=1 then begin
+                FZipStream.ReadBuffer(Infozip_unicode_path_crc32,sizeof(Infozip_unicode_path_crc32));
+                {$IFDEF FPC_BIG_ENDIAN}
+                Infozip_unicode_path_crc32:=SwapEndian(Infozip_unicode_path_crc32);
+                {$ENDIF}
+                if CRC32Str(S)=Infozip_unicode_path_crc32 then begin
+                  SetLength(S,ExtraFieldHeader.Data_Size-5);
+                  FZipStream.ReadBuffer(S[1],Length(S));
+                  {$if FPC_FULLVERSION>=20701}
+                  if DefaultSystemCodePage<>CP_UTF8 then
+                    NewNode.ArchiveFileName:=Utf8ToAnsi(S)
+                    else
+                      NewNode.ArchiveFileName:=S;
+                  {$ELSE}
+                  NewNode.ArchiveFileName:=Utf8ToAnsi(S);
+                  {$ENDIF}
+                end else
+                  FZipStream.Seek(ExtraFieldHeader.Data_Size-5,soFromCurrent);
+              end else
+                FZipStream.Seek(ExtraFieldHeader.Data_Size-1,soFromCurrent);
+            end
           else
             begin
               // Read past non-Zip64 extra field




참고하시기를~

+ -

관련 글 리스트
19 fpc의 zip파일의 winrar등의 파일 이름 지원 패치. 김도완 5258 2014/12/12
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.