]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
According to IEEE Std 1003.1-2001, we can use following charset to pax writer.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sat, 2 Apr 2011 05:10:30 +0000 (01:10 -0400)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Sat, 2 Apr 2011 05:10:30 +0000 (01:10 -0400)
 UTF-8
 BINARY
 ISO-8859-1  ISO8859-1
 ISO-8859-2  ISO8859-2
 ISO-8859-3  ISO8859-3
 ISO-8859-4  ISO8859-4
 ISO-8859-5  ISO8859-5
 ISO-8859-6  ISO8859-6
 ISO-8859-7  ISO8859-7
 ISO-8859-8  ISO8859-8
 ISO-8859-9  ISO8859-9
 ISO-8859-10 ISO8859-10
 ISO-8859-13 ISO8859-13
 ISO-8859-14 ISO8859-14
 ISO-8859-15 ISO8859-15

We should not allow other charset to a charset option of pax writer.

SVN-Revision: 3148

libarchive/archive_write_set_format_pax.c

index 823b1602acca998f3549934ba052e91954823db9..8980dc27200515995a1bbabc7b9dcd3c754eb6a5 100644 (file)
@@ -66,6 +66,7 @@ struct pax {
        struct archive_string_conv *opt_sconv;
        struct archive_string_conv *sconv_utf8;
        int                      opt_binary;
+       const char      *hdrcharset;
 };
 
 static void             add_pax_attr(struct archive_string *, const char *key,
@@ -155,30 +156,121 @@ static int
 archive_write_pax_options(struct archive_write *a, const char *key,
     const char *val)
 {
+       static const char *iso_charset[] = {
+               NULL,
+               "ISO-IR 8859 1 1998",
+               "ISO-IR 8859 2 1999",
+               "ISO-IR 8859 3 1999",
+               "ISO-IR 8859 4 1998",
+               "ISO-IR 8859 5 1999",
+               "ISO-IR 8859 6 1999",
+               "ISO-IR 8859 7 1987",
+               "ISO-IR 8859 8 1999",
+               "ISO-IR 8859 9 1999",
+               "ISO-IR 8859 10 1998",
+               NULL,
+               NULL,
+               "ISO-IR 8859 13 1998",
+               "ISO-IR 8859 14 1998",
+               "ISO-IR 8859 15 1999",
+       };
        struct pax *pax = (struct pax *)a->format_data;
        int ret = ARCHIVE_FAILED;
 
        if (strcmp(key, "charset")  == 0) {
+               /*
+                * The character-set we can use are defined in
+                * IEEE Std 1003.1-2001
+                */
                if (val == NULL || val[0] == 0)
                        archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
                            "pax: charset option needs a character-set name");
-               else if (strcmp(val, "BINARY") == 0 ||
-                   strcmp(val, "binary") == 0) {
+               else {
+                       int try_conv = 0;
+                       const char *p;
+
+                       switch (val[0]) {
+                       case 'b':
+                       case 'B':
+                               /*
+                                * Specify binary mode. We will not convert
+                                * filenames, uname and gname to any charsets.
+                                */
+                               if (strcmp(val, "BINARY") == 0 ||
+                                   strcmp(val, "binary") == 0) {
+                                       pax->opt_binary = 1;
+                                       pax->opt_sconv = NULL;
+                                       pax->hdrcharset = "BINARY";
+                                       ret = ARCHIVE_OK;
+                               }
+                               break;
+                       case 'I':
+                               /*
+                                * ISO-8859-1  ISO8859-1
+                                * ISO-8859-2  ISO8859-2
+                                * ISO-8859-3  ISO8859-3
+                                * ISO-8859-4  ISO8859-4
+                                * ISO-8859-5  ISO8859-5
+                                * ISO-8859-6  ISO8859-6
+                                * ISO-8859-7  ISO8859-7
+                                * ISO-8859-8  ISO8859-8
+                                * ISO-8859-9  ISO8859-9
+                                * ISO-8859-10 ISO8859-10
+                                * ISO-8859-13 ISO8859-13
+                                * ISO-8859-14 ISO8859-14
+                                * ISO-8859-15 ISO8859-15
+                                */
+                               if (strncmp(val, "ISO-8859-", 9) == 0 ||
+                                   strncmp(val, "ISO8859-", 8) == 0) {
+                                       int d;
+                                       if (val[3] == '-')
+                                               p = val + 9;
+                                       else
+                                               p = val + 8;
+                                       if (p[0] >= '1' && p[0] <= '9') {
+                                               d = p[0] - '0';
+                                               if (p[1] >= '0' && p[1] <= '5'
+                                                   && p[2] == '\0')
+                                                       d = d * 10 + (p[1] - '0');
+                                               else if (p[1] != '\0')
+                                                       d = -1;
+                                       } else
+                                               d = -1;
+                                       if (d >= 1 && d <= 15 &&
+                                           iso_charset[d] != NULL) {
+                                               try_conv = 1;
+                                               pax->hdrcharset =
+                                                   iso_charset[d];
+                                       }
+                               }
+                               break;
+                       case 'U':
+                               /* UTF-8 is default charset. */
+                               if (strcmp(val, "UTF-8") == 0) {
+                                       try_conv = 1;
+                                       pax->hdrcharset = NULL;
+                               }
+                               break;
+                       }
                        /*
-                        * Specify binary mode. We will not convert
-                        * filenames, uname and gname to UTF-8 or others.
+                        * Can this platform convert names to specified
+                        * charset ?
                         */
-                       pax->opt_binary = 1;
-                       pax->opt_sconv = NULL;
-                       ret = ARCHIVE_OK;
-               } else {
-                       pax->opt_sconv = archive_string_conversion_to_charset(
-                           &a->archive, val, 0);
-                       if (pax->opt_sconv != NULL) {
+                       if (try_conv) {
                                pax->opt_binary = 0;
-                               ret = ARCHIVE_OK;
-                       } else
-                               ret = ARCHIVE_FATAL;
+                               pax->opt_sconv =
+                                   archive_string_conversion_to_charset(
+                                       &a->archive, val, 0);
+                               if (pax->opt_sconv != NULL)
+                                       ret = ARCHIVE_OK;
+                               else {
+                                       pax->hdrcharset = NULL;
+                                       ret = ARCHIVE_FATAL;
+                               }
+                       } else if (ret != ARCHIVE_OK)
+                               archive_set_error(&a->archive,
+                                   ARCHIVE_ERRNO_MISC,
+                                   "pax: invalid charset name");
                }
        } else
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -397,9 +489,7 @@ archive_write_pax_header(struct archive_write *a,
         */
        if ((binary = pax->opt_binary) != 0)
                sconv = NULL;
-       else if (pax->opt_sconv != NULL &&
-           strcmp(archive_string_conversion_charset_name(pax->opt_sconv),
-               "UTF-8") != 0)
+       else if (pax->opt_sconv != NULL && pax->hdrcharset != NULL)
                sconv = pax->opt_sconv;
        else
                sconv = pax->sconv_utf8;
@@ -595,9 +685,8 @@ archive_write_pax_header(struct archive_write *a,
        /* Store the header encoding first, to be nice to readers. */
        if (binary)
                add_pax_attr(&(pax->pax_header), "hdrcharset", "BINARY");
-       else if (pax->opt_sconv != NULL && pax->sconv_utf8 != sconv)
-               add_pax_attr(&(pax->pax_header), "hdrcharset",
-                   archive_string_conversion_charset_name(sconv));
+       else if (pax->hdrcharset != NULL)
+               add_pax_attr(&(pax->pax_header), "hdrcharset", pax->hdrcharset);
 
 
        /*