summaryrefslogtreecommitdiff
path: root/libarchive/archive_read_support_format_cab.c
diff options
context:
space:
mode:
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>2011-03-28 06:59:20 -0400
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>2011-03-28 06:59:20 -0400
commit15cf835cc555018bed865071cb9f5bcdb6b75060 (patch)
tree69c3312f104e2ff1a60255b63fc7f6ae34cae494 /libarchive/archive_read_support_format_cab.c
parentf74c5f05faccec9b0946faa3f3fbe41fab276a26 (diff)
downloadlibarchive-15cf835cc555018bed865071cb9f5bcdb6b75060.tar.gz
Improve character-set conversion functions.
- Change the interface in order to reduece the comparison of charset names. Previous version always did it when the functions were called; it was very inefficient. So I have made a conversion object, struct archive_string_conv, to resolve that issue. - Integrate *_from_charset and *_to_charset into *_in_locale because of above. - Integrate *_from_utf16be and *_to_utf16be into *in_locale. - On Windows, Make a codepage from a charset name to know whether current codepage and specified charset are the same or not. SVN-Revision: 3108
Diffstat (limited to 'libarchive/archive_read_support_format_cab.c')
-rw-r--r--libarchive/archive_read_support_format_cab.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c
index f1f80de6..5628b9db 100644
--- a/libarchive/archive_read_support_format_cab.c
+++ b/libarchive/archive_read_support_format_cab.c
@@ -290,7 +290,8 @@ struct cab {
unsigned char *uncompressed_buffer;
size_t uncompressed_buffer_size;
- char *charset;
+ struct archive_string_conv *sconv;
+ struct archive_string_conv *sconv_utf8;
char format_name[64];
#ifdef HAVE_ZLIB_H
@@ -458,12 +459,14 @@ archive_read_format_cab_options(struct archive_read *a,
if (val == NULL || val[0] == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"cab: charset option needs a character-set name");
- else if (archive_string_conversion_from_charset(
- &a->archive, val) == 0) {
- cab->charset = strdup(val);
- ret = ARCHIVE_OK;
- } else
- ret = ARCHIVE_FATAL;
+ else {
+ cab->sconv = archive_string_conversion_from_charset(
+ &a->archive, val, 0);
+ if (cab->sconv != NULL)
+ ret = ARCHIVE_OK;
+ else
+ ret = ARCHIVE_FATAL;
+ }
} else
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"cab: unknown keyword ``%s''", key);
@@ -792,12 +795,16 @@ cab_read_header(struct archive_read *a)
if ((len = cab_strnlen(p, avail-1)) <= 0)
goto invalid;
archive_string_init(&(file->pathname));
- if ((file->attr & ATTR_NAME_IS_UTF) && cab->charset == NULL)
- archive_strncpy_from_locale(&a->archive,
- &(file->pathname), p, len, "UTF-8");
- else
- archive_strncpy_from_locale(&a->archive,
- &(file->pathname), p, len, cab->charset);
+ if ((file->attr & ATTR_NAME_IS_UTF) && cab->sconv == NULL) {
+ if (cab->sconv_utf8 == NULL)
+ cab->sconv_utf8 =
+ archive_string_conversion_from_charset(
+ &(a->archive), "UTF-8", 1);
+ archive_strncpy_in_locale(&(file->pathname), p, len,
+ cab->sconv_utf8);
+ } else
+ archive_strncpy_in_locale(&(file->pathname), p,
+ len, cab->sconv);
__archive_read_consume(a, len + 1);
cab->cab_offset += len + 1;
/* Convert a path separator '\' -> '/' */
@@ -1970,7 +1977,6 @@ archive_read_format_cab_cleanup(struct archive_read *a)
archive_wstring_free(&cab->ws);
archive_string_free(&cab->mbs);
free(cab->uncompressed_buffer);
- free(cab->charset);
free(cab);
(a->format->data) = NULL;
return (ARCHIVE_OK);