From: Martin Matuska Date: Tue, 7 May 2019 10:35:48 +0000 (+0200) Subject: Merge pull request #1180 from vapier/master X-Git-Tag: v3.4.0~44 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f98621f25afac04160f3c49c2302cb601b1ecc1;p=thirdparty%2Flibarchive.git Merge pull request #1180 from vapier/master zip: add support for Info-ZIP Unicode Path Extra Field --- 8f98621f25afac04160f3c49c2302cb601b1ecc1 diff --cc libarchive/archive_read_support_format_zip.c index 05b73705b,1e65968a6..c6a3cf943 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@@ -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; @@@ -732,6 -734,35 +734,38 @@@ } break; } + case 0x7075: + { + /* Info-ZIP Unicode Path Extra Field. */ + if (datasize < 5 || entry == NULL) + break; + offset += 5; + datasize -= 5; + - /* The path name in this field is always encoded in UTF-8. */ ++ /* 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); - // If the converter from UTF-8 is not available, then the - // path name from the main field will more likely be correct. ++ /* 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) { - // Ignore the error, and fallback to the path name from the main - // field. ++ /* 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"); ++ 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; } diff --cc libarchive/test/test_read_format_zip_7075_utf8_paths.c index 000000000,bfc95b097..e09b87ea5 mode 000000,100644..100644 --- a/libarchive/test/test_read_format_zip_7075_utf8_paths.c +++ b/libarchive/test/test_read_format_zip_7075_utf8_paths.c @@@ -1,0 -1,88 +1,88 @@@ + /*- + * 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 + + static void + verify(struct archive *a) { + struct archive_entry *ae; - const wchar_t *wp; ++ 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 1.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 2 - ö.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 3 - ä.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((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 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)); + }