};
#define ZIP_LENGTH_AT_END 8
+#define ZIP_UTF8_NAME (1<<11)
struct zip_file_header {
char signature[4];
{
const struct zip_file_header *p;
const void *h;
+ int ret = ARCHIVE_OK;
if ((p = __archive_read_ahead(a, sizeof *p, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP file header");
return (ARCHIVE_FATAL);
}
- archive_strncpy_from_locale(&a->archive, &zip->pathname,
- h, zip->filename_length, zip->charset);
+ if (zip->charset == NULL && (zip->flags & ZIP_UTF8_NAME) != 0) {
+ /* The filename is stored to be UTF-8. */
+ if (archive_strncpy_from_locale(&a->archive, &zip->pathname,
+ h, zip->filename_length, "UTF-8") != 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Pathname cannot be converted "
+ "from UTF-8 to current locale.");
+ ret = ARCHIVE_WARN;
+ }
+ } else {
+ if (archive_strncpy_from_locale(&a->archive, &zip->pathname,
+ h, zip->filename_length, zip->charset) != 0) {
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Pathname cannot be converted "
+ "from %s to current locale.", zip->charset);
+ ret = ARCHIVE_WARN;
+ }
+ }
__archive_read_consume(a, zip->filename_length);
archive_entry_set_pathname(entry, zip->pathname.s);
zip->compression_name);
a->archive.archive_format_name = zip->format_name;
- return (ARCHIVE_OK);
+ return (ret);
}
/* Convert an MSDOS-style date/time into Unix-style time. */
assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
/* Close the archive. */
-cleanup:
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+cleanup:
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
/* Close the archive. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+cleanup:
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+static void
+test_read_format_zip_filename_UTF8_eucJP(const char *refname)
+{
+ struct archive *a;
+ struct archive_entry *ae;
+
+ /*
+ * Read ZIP filename in ja_JP.eucJP without charset option
+ * because the file name in the sample file is UTF-8 and
+ * Bit 11 of its general purpose bit flag is set.
+ */
+ if (NULL == setlocale(LC_ALL, "ja_JP.eucJP")) {
+ skipping("ja_JP.eucJP locale not available on this system.");
+ return;
+ }
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
+ if (ARCHIVE_OK != archive_read_set_options(a, "charset=UTF-8")) {
+ skipping("This system cannot convert character-set"
+ " from UTF-8 to eucJP.");
+ goto cleanup;
+ }
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ /* Verify directory file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualString("\xc9\xbd\xa4\xc0\xa4\xe8\x2f",
+ archive_entry_pathname(ae));
+ assertEqualInt(0, archive_entry_size(ae));
+
+ /* Verify regular file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertEqualString(
+ "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb0\xec\xcd\xf7\xc9\xbd\x2e\x74\x78\x74",
+ archive_entry_pathname(ae));
+ assertEqualInt(5, archive_entry_size(ae));
+
+ /* Verify regular file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertEqualString(
+ "\xc9\xbd\xa4\xc0\xa4\xe8\x2f\xb4\xc1\xbb\xfa\x2e\x74\x78\x74",
+ archive_entry_pathname(ae));
+ assertEqualInt(5, archive_entry_size(ae));
+
+
+ /* End of archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify archive format. */
+ assertEqualIntA(a, ARCHIVE_COMPRESSION_NONE, archive_compression(a));
+ assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
+
+ /* Close the archive. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
cleanup:
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
+static void
+test_read_format_zip_filename_UTF8_UTF8(const char *refname)
+{
+ struct archive *a;
+ struct archive_entry *ae;
+
+ /*
+ * Read ZIP filename in ja_JP.UTF-8 without charset option
+ * because the file name in the sample file is UTF-8 and
+ * Bit 11 of its general purpose bit flag is set.
+ */
+ if (NULL == setlocale(LC_ALL, "ja_JP.UTF-8")) {
+ skipping("ja_JP.UTF-8 locale not available on this system.");
+ return;
+ }
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ /* Verify directory file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualString("\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f",
+ archive_entry_pathname(ae));
+ assertEqualInt(0, archive_entry_size(ae));
+
+ /* Verify regular file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertEqualString("\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f"
+ "\xe4\xb8\x80\xe8\xa6\xa7\xe8\xa1\xa8\x2e\x74\x78\x74",
+ archive_entry_pathname(ae));
+ assertEqualInt(5, archive_entry_size(ae));
+
+ /* Verify regular file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertEqualString("\xe8\xa1\xa8\xe3\x81\xa0\xe3\x82\x88\x2f"
+ "\xe6\xbc\xa2\xe5\xad\x97\x2e\x74\x78\x74",
+ archive_entry_pathname(ae));
+ assertEqualInt(5, archive_entry_size(ae));
+
+
+ /* End of archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify archive format. */
+ assertEqualIntA(a, ARCHIVE_COMPRESSION_NONE, archive_compression(a));
+ assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a));
+
+ /* Close the archive. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_zip_filename)
{
const char *refname = "test_read_format_zip_cp932.zip";
+ const char *refname2 = "test_read_format_zip_utf8.zip";
extract_reference_file(refname);
test_read_format_zip_filename_CP932_eucJP(refname);
test_read_format_zip_filename_CP932_UTF8(refname);
+ extract_reference_file(refname2);
+ test_read_format_zip_filename_UTF8_eucJP(refname2);
+ test_read_format_zip_filename_UTF8_UTF8(refname2);
}