]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Merge pull request #1180 from vapier/master
authorMartin Matuska <martin.matuska@axelspringer.de>
Tue, 7 May 2019 10:35:48 +0000 (12:35 +0200)
committerMartin Matuska <martin.matuska@axelspringer.de>
Tue, 7 May 2019 12:28:41 +0000 (14:28 +0200)
zip: add support for Info-ZIP Unicode Path Extra Field

1  2 
libarchive/archive_read_support_format_zip.c
libarchive/test/test_read_format_zip_7075_utf8_paths.c

index 05b73705bec67ae3c3ccecd3555195709ecf58ac,1e65968a6640a0910dee4cd43b33405faf689998..c6a3cf94329a19606cf93ee7c98242cb7be5e23d
@@@ -472,9 -472,11 +472,11 @@@ zip_time(const char *p
   *  triplets.  id and size are 2 bytes each.
   */
  static int
- process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry)
+ process_extra(struct archive_read *a, struct archive_entry *entry,
 -              const char *p, size_t extra_length, struct zip_entry* zip_entry)
++     const char *p, size_t extra_length, struct zip_entry* zip_entry)
  {
        unsigned offset = 0;
+       struct zip *zip = (struct zip *)(a->format->data);
  
        if (extra_length == 0) {
                return ARCHIVE_OK;
                        }
                        break;
                }
 -                      /* The path name in this field is always encoded in UTF-8. */
+               case 0x7075:
+               {
+                       /* Info-ZIP Unicode Path Extra Field. */
+                       if (datasize < 5 || entry == NULL)
+                               break;
+                       offset += 5;
+                       datasize -= 5;
 -                              // If the converter from UTF-8 is not available, then the
 -                              // path name from the main field will more likely be correct.
++                      /* The path name in this field is always encoded
++                       * in UTF-8. */
+                       if (zip->sconv_utf8 == NULL) {
+                               zip->sconv_utf8 =
+                                       archive_string_conversion_from_charset(
+                                       &a->archive, "UTF-8", 1);
 -                              // Ignore the error, and fallback to the path name from the main
 -                              // field.
++                              /* If the converter from UTF-8 is not
++                               * available, then the path name from the main
++                               * field will more likely be correct. */
+                               if (zip->sconv_utf8 == NULL)
+                                       break;
+                       }
+                       if (archive_entry_copy_pathname_l(entry,
+                           p + offset, datasize, zip->sconv_utf8) != 0) {
 -                              fprintf(stderr, "Failed to read the ZIP 0x7075 extra field path.\n");
++                              /* Ignore the error, and fallback to the path
++                               * name from the main field. */
+ #ifdef DEBUG
++                              fprintf(stderr, "Failed to read the ZIP "
++                                  "0x7075 extra field path.\n");
+ #endif
+                       }
+                       break;
+               }
                case 0x7855:
                        /* Info-ZIP Unix Extra Field (type 2) "Ux". */
  #ifdef DEBUG
@@@ -928,7 -959,7 +962,8 @@@ zip_read_local_file_header(struct archi
                return (ARCHIVE_FATAL);
        }
  
-       if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) {
 -      if (ARCHIVE_OK != process_extra(a, entry, h, extra_length, zip_entry)) {
++      if (ARCHIVE_OK != process_extra(a, entry, h, extra_length,
++          zip_entry)) {
                return ARCHIVE_FATAL;
        }
        __archive_read_consume(a, extra_length);
@@@ -3543,7 -3570,7 +3579,8 @@@ slurp_central_directory(struct archive_
                            "Truncated ZIP file header");
                        return ARCHIVE_FATAL;
                }
-               if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) {
 -              if (ARCHIVE_OK != process_extra(a, entry, p + filename_length, extra_length, zip_entry)) {
++              if (ARCHIVE_OK != process_extra(a, entry, p + filename_length,
++                  extra_length, zip_entry)) {
                        return ARCHIVE_FATAL;
                }
  
index 0000000000000000000000000000000000000000,bfc95b097d90749a7268221d882040da973e14ad..e09b87ea59af917e077bbbe4de7a6be3e470a085
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,88 +1,88 @@@
 -      const wchar_t *wp;
+ /*-
+  * Copyright (c) 2003-2007 Tim Kientzle
+  * Copyright (c) 2011 Michihiro NAKAJIMA
+  * Copyright (c) 2019 Mike Frysinger
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  */
+ #include "test.h"
+ __FBSDID("$FreeBSD$");
+ #include <locale.h>
+ static void
+ verify(struct archive *a) {
+       struct archive_entry *ae;
 -      assert((wp = archive_entry_pathname_w(ae)) != NULL);
 -      assertEqualInt(0, wcscmp(wp, L"File 1.txt"));
++      const char *p;
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
 -      assert((wp = archive_entry_pathname_w(ae)) != NULL);
 -      assertEqualInt(0, wcscmp(wp, L"File 2 - ö.txt"));
++      assert((p = archive_entry_pathname_utf8(ae)) != NULL);
++      assertEqualUTF8String(p, "File 1.txt");
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
 -      assert((wp = archive_entry_pathname_w(ae)) != NULL);
 -      assertEqualInt(0, wcscmp(wp, L"File 3 - ä.txt"));
++      assert((p = archive_entry_pathname_utf8(ae)) != NULL);
++      assertEqualUTF8String(p, "File 2 - o\xCC\x88.txt");
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
 -      assert((wp = archive_entry_pathname_w(ae)) != NULL);
 -      assertEqualInt(0, wcscmp(wp, L"File 4 - å.txt"));
++      assert((p = archive_entry_pathname_utf8(ae)) != NULL);
++      assertEqualUTF8String(p, "File 3 - a\xCC\x88.txt");
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
++      assert((p = archive_entry_pathname_utf8(ae)) != NULL);
++      assertEqualUTF8String(p, "File 4 - a\xCC\x8A.txt");
+       assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+ }
+ DEFINE_TEST(test_read_format_zip_utf8_paths)
+ {
+       const char *refname = "test_read_format_zip_7075_utf8_paths.zip";
+       struct archive *a;
+       char *p;
+       size_t s;
+       extract_reference_file(refname);
+       if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) {
+               skipping("en_US.UTF-8 locale not available on this system.");
+               return;
+       }
+       /* Verify with seeking reader. */
+       assert((a = archive_read_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240));
+       verify(a);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
+       /* Verify with streaming reader. */
+       p = slurpfile(&s, refname);
+       assert((a = archive_read_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+       assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31));
+       verify(a);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+       assertEqualIntA(a, ARCHIVE_OK, archive_free(a));
+ }