archive_string_default_conversion_for_read(struct archive *a)
{
const char *cur_charset = get_current_charset(a);
-
- if (a->current_codepage == CP_C_LOCALE ||
- a->current_codepage == a->current_oemcp)
+ char oemcp[16];
+
+ /* NOTE: a check of cur_charset is unneeded but we need
+ * that get_current_charset() has been surely called at
+ * this time whatever C compiler optimized. */
+ if (cur_charset != NULL &&
+ (a->current_codepage == CP_C_LOCALE ||
+ a->current_codepage == a->current_oemcp))
return (NULL);/* no conversion. */
- return (get_sconv_object(a, "CP_OEMCP", cur_charset,
+
+ _snprintf(oemcp, sizeof(oemcp)-1, "CP%d", a->current_oemcp);
+ /* Make sure a null termination must be set. */
+ oemcp[sizeof(oemcp)-1] = '\0';
+ return (get_sconv_object(a, oemcp, cur_charset,
SCONV_FROM_CHARSET));
}
archive_string_default_conversion_for_write(struct archive *a)
{
const char *cur_charset = get_current_charset(a);
-
- if (a->current_codepage == CP_C_LOCALE ||
- a->current_codepage == a->current_oemcp)
+ char oemcp[16];
+
+ /* NOTE: a check of cur_charset is unneeded but we need
+ * that get_current_charset() has been surely called at
+ * this time whatever C compiler optimized. */
+ if (cur_charset != NULL &&
+ (a->current_codepage == CP_C_LOCALE ||
+ a->current_codepage == a->current_oemcp))
return (NULL);/* no conversion. */
- return (get_sconv_object(a, "CP_OEMCP", cur_charset,
+
+ _snprintf(oemcp, sizeof(oemcp)-1, "CP%d", a->current_oemcp);
+ /* Make sure a null termination must be set. */
+ oemcp[sizeof(oemcp)-1] = '\0';
+ return (get_sconv_object(a, cur_charset, oemcp,
SCONV_TO_CHARSET));
}
#else
size_t used;
if (NULL == setlocale(LC_ALL, "ru_RU.UTF-8")) {
- skipping("KOI8-R locale not available on this system.");
+ skipping("ru_RU.UTF-8 locale not available on this system.");
return;
}
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set a UTF-8 filename. */
archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
/* A bit 11 of general purpos flag should be 0x08,
* which indicates the filename charset is UTF-8. */
assertEqualInt(0x08, buff[7]);
- /* Above three characters in KOI8-R should translate to the following
- * three characters (two bytes each) in UTF-8. */
assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6);
/*
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set a UTF-8 filename. */
archive_entry_set_pathname(entry, "\xD0\xBF\xD1\x80\xD0\xB8");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
/* A bit 11 of general purpos flag should be 0x08,
* which indicates the filename charset is UTF-8. */
assertEqualInt(0x08, buff[7]);
- /* Above three characters in KOI8-R should translate to the following
- * three characters (two bytes each) in UTF-8. */
assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6);
/*
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set an ASCII filename. */
archive_entry_set_pathname(entry, "abcABC");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set a KOI8-R filename. */
archive_entry_set_pathname(entry, "\xD0\xD2\xC9");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set a KOI8-R filename. */
archive_entry_set_pathname(entry, "\xD0\xD2\xC9");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set an ASCII filename. */
archive_entry_set_pathname(entry, "abcABC");
archive_entry_set_filetype(entry, AE_IFREG);
archive_entry_set_size(entry, 0);
assertEqualMem(buff + 30, "abcABC", 6);
}
+/*
+ * Other archiver applications on Windows translate CP1251 filenames
+ * into CP866 filenames and store it in the zip file.
+ * Test above behavior works well.
+ */
+static void
+test_zip_filename_encoding_Russian_Russia()
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ char buff[4096];
+ size_t used;
+
+ if (NULL == setlocale(LC_ALL, "Russian_Russia")) {
+ skipping("Russian_Russia locale not available on this system.");
+ return;
+ }
+
+ /*
+ * Verify that Russian_Russia(CP1251) filenames are correctly translated
+ * to UTF-8.
+ */
+ a = archive_write_new();
+ assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a));
+ if (archive_write_set_options(a, "hdrcharset=UTF-8") != ARCHIVE_OK) {
+ skipping("This system cannot convert character-set"
+ " from Russian_Russia.CP1251 to UTF-8.");
+ archive_write_free(a);
+ return;
+ }
+ assertEqualInt(ARCHIVE_OK,
+ archive_write_open_memory(a, buff, sizeof(buff), &used));
+
+ entry = archive_entry_new2(a);
+ /* Set a CP1251 filename. */
+ archive_entry_set_pathname(entry, "\xEF\xF0\xE8");
+ archive_entry_set_filetype(entry, AE_IFREG);
+ archive_entry_set_size(entry, 0);
+ assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
+ archive_entry_free(entry);
+ assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+ /* A bit 11 of general purpos flag should be 0x08,
+ * which indicates the filename charset is UTF-8. */
+ assertEqualInt(0x08, buff[7]);
+ /* Above three characters in CP1251 should translate to the following
+ * three characters (two bytes each) in UTF-8. */
+ assertEqualMem(buff + 30, "\xD0\xBF\xD1\x80\xD0\xB8", 6);
+
+ /*
+ * Verify that Russian_Russia(CP1251) filenames are correctly translated
+ * to CP866.
+ */
+ a = archive_write_new();
+ assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a));
+ assertEqualInt(ARCHIVE_OK,
+ archive_write_open_memory(a, buff, sizeof(buff), &used));
+
+ entry = archive_entry_new2(a);
+ /* Set a CP1251 filename. */
+ archive_entry_set_pathname(entry, "\xEF\xF0\xE8");
+ archive_entry_set_filetype(entry, AE_IFREG);
+ archive_entry_set_size(entry, 0);
+ assertEqualInt(ARCHIVE_OK, archive_write_header(a, entry));
+ archive_entry_free(entry);
+ assertEqualInt(ARCHIVE_OK, archive_write_free(a));
+
+ /* A bit 11 of general purpos flag should be 0,
+ * which indicates the filename charset is unkown. */
+ assertEqualInt(0, buff[7]);
+ /* Above three characters in CP1251 should translate to the following
+ * three characters in CP866. */
+ assertEqualMem(buff + 30, "\xAF\xE0\xA8", 3);
+}
+
static void
test_zip_filename_encoding_EUCJP()
{
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set an EUC-JP filename. */
archive_entry_set_pathname(entry, "\xC9\xBD.txt");
/* Check the Unicode version. */
archive_entry_set_filetype(entry, AE_IFREG);
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set an EUC-JP filename. */
archive_entry_set_pathname(entry, "\xC9\xBD.txt");
/* Check the Unicode version. */
archive_entry_set_filetype(entry, AE_IFREG);
archive_write_open_memory(a, buff, sizeof(buff), &used));
entry = archive_entry_new2(a);
+ /* Set an ASCII filename. */
archive_entry_set_pathname(entry, "abcABC");
/* Check the Unicode version. */
archive_entry_set_filetype(entry, AE_IFREG);
{
test_zip_filename_encoding_UTF8();
test_zip_filename_encoding_KOI8R();
+ test_zip_filename_encoding_Russian_Russia();
test_zip_filename_encoding_EUCJP();
}