struct archive_string dirname;
struct archive_string filename;
+ struct archive_wstring dirname_w;
+ struct archive_wstring filename_w;
struct archive_wstring ws;
unsigned char dos_attr;
{
struct archive_string linkname;
struct archive_string pathname;
+ struct archive_wstring pathname_w;
struct lha *lha;
const unsigned char *p;
const char *signature;
lha->uid = 0;
lha->gid = 0;
archive_string_empty(&lha->dirname);
+ archive_wstring_empty(&lha->dirname_w);
archive_string_empty(&lha->filename);
+ archive_wstring_empty(&lha->filename_w);
lha->dos_attr = 0;
if (lha->opt_sconv != NULL)
lha->sconv = lha->opt_sconv;
/*
* Make a pathname from a dirname and a filename.
*/
+ if (archive_strlen(&lha->filename_w) > 0 || archive_strlen(&lha->dirname_w) > 0) {
+ /* This archive has some unicode contents */
+ if (archive_strlen(&lha->filename_w) == 0)
+ if (-1 == archive_wstring_append_from_mbs(&lha->filename_w, lha->filename.s, archive_strlen(&lha->filename))) {
+ if (errno == ENOMEM)
+ archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
+ else
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't convert a path to a wchar_t string");
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return ARCHIVE_FATAL;
+ }
+ if (archive_strlen(&lha->dirname_w) == 0)
+ if (-1 == archive_wstring_append_from_mbs(&lha->dirname_w, lha->dirname.s, archive_strlen(&lha->dirname))) {
+ if (errno == ENOMEM)
+ archive_set_error(&a->archive, ENOMEM, "Can't allocate memory");
+ else
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't convert a path to a wchar_t string");
+ a->archive.state = ARCHIVE_STATE_FATAL;
+ return ARCHIVE_FATAL;
+ }
+ }
+
archive_string_concat(&lha->dirname, &lha->filename);
+ archive_wstring_concat(&lha->dirname_w, &lha->filename_w);
archive_string_init(&pathname);
+ archive_string_init(&pathname_w);
archive_string_init(&linkname);
archive_string_copy(&pathname, &lha->dirname);
+ archive_wstring_copy(&pathname_w, &lha->dirname_w);
if ((lha->mode & AE_IFMT) == AE_IFLNK) {
/*
* Extract the symlink-name if it's included in the pathname.
+ * Symlink-name is assumed not to exist in UNICODE filename, because UNICODE archives are created only on Windows(unlha32.dll)
*/
if (!lha_parse_linkname(&linkname, &pathname)) {
/* We couldn't get the symlink-name. */
ARCHIVE_ERRNO_FILE_FORMAT,
"Unknown symlink-name");
archive_string_free(&pathname);
+ archive_wstring_free(&pathname_w);
archive_string_free(&linkname);
return (ARCHIVE_FAILED);
}
/*
* Set basic file parameters.
*/
- if (archive_entry_copy_pathname_l(entry, pathname.s,
+ if (archive_strlen(&pathname_w) > 0 ) {
+ archive_entry_copy_pathname_w(entry, pathname_w.s);
+ }else if (archive_entry_copy_pathname_l(entry, pathname.s,
pathname.length, lha->sconv) != 0) {
if (errno == ENOMEM) {
archive_set_error(&a->archive, ENOMEM,
err = ARCHIVE_WARN;
}
archive_string_free(&pathname);
+ archive_wstring_free(&pathname_w);
if (archive_strlen(&linkname) > 0) {
if (archive_entry_copy_symlink_l(entry, linkname.s,
linkname.length, lha->sconv) != 0) {
archive_strncpy(&lha->filename,
(const char *)extdheader, datasize);
break;
+ case EXT_UTF16_FILENAME:
+ if (datasize == 0) {
+ /* maybe directory header */
+ archive_wstring_empty(&lha->filename_w);
+ break;
+ }
+ if (extdheader[0] == '\0')
+ goto invalid;
+ archive_wstrncpy(&lha->filename_w,
+ (const wchar_t *)extdheader, datasize / 2);
+ break;
+
case EXT_DIRECTORY:
if (datasize == 0 || extdheader[0] == '\0')
/* no directory name data. exit this case. */
/* invalid directory data */
goto invalid;
break;
+ case EXT_UTF16_DIRECTORY:
+ if (datasize == 0 || extdheader[0] == '\0')
+ /* no directory name data. exit this case. */
+ goto invalid;
+
+ archive_wstrncpy(&lha->dirname_w,
+ (const wchar_t *)extdheader, datasize / 2);
+ /*
+ * Convert directory delimiter from 0xFF
+ * to '/' for local system.
+ */
+ for (i = 0; i < lha->dirname_w.length; i++) {
+ if (lha->dirname_w.s[i] == 0xFFFF)
+ lha->dirname_w.s[i] = L'/';
+ }
+ /* Is last character directory separator? */
+ if (lha->dirname_w.s[lha->dirname_w.length - 1] != L'/')
+ /* invalid directory data */
+ goto invalid;
+ break;
case EXT_DOS_ATTR:
if (datasize == 2)
lha->dos_attr = (unsigned char)
}
break;
case EXT_TIMEZONE: /* Not supported */
- case EXT_UTF16_FILENAME: /* Not supported */
- case EXT_UTF16_DIRECTORY: /* Not supported */
+ break;
default:
break;
}