* 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
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);
"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;
}
--- /dev/null
- 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));
+ }