OSDN Git Service

* src/header.c (ConvertEncodingByIconv): newly added.
[lha/lha.git] / src / header.c
index f392bfe..e71ed01 100644 (file)
@@ -653,8 +653,6 @@ get_header(fp, hdr)
                }
                while (extend_size-- > 0)
                        dmy = get_byte();
-               if (hdr->extend_type == EXTEND_UNIX)
-                       return TRUE;
        } else if (hdr->header_level == 1) {
                hdr->has_crc = TRUE;
                extend_size = header_size - name_length-25;
@@ -769,7 +767,8 @@ get_header(fp, hdr)
 
        switch (hdr->extend_type) {
        case EXTEND_MSDOS:
-        archive_delim = "\xff\\";
+        archive_delim = "\377\\";
+                          /* `\' is for level 0 header and broken archive. */
         system_delim = "//";
         filename_case = noconvertcase ? NONE : TO_LOWER;
 
@@ -787,15 +786,17 @@ get_header(fp, hdr)
        case EXTEND_XOSK:
 #endif
        case EXTEND_UNIX:
-        archive_delim = "\xff";
+        archive_delim = "\377\\";
+                          /* `\' is for level 0 header and broken archive. */
         system_delim = "//";
         filename_case = NONE;
 
                break;
 
        case EXTEND_MACOS:
-        archive_delim = "\xff/:";
-        system_delim = "/:/";
+        archive_delim = "\377/:\\";
+                          /* `\' is for level 0 header and broken archive. */
+        system_delim = "/://";
         filename_case = NONE;
 
                hdr->unix_last_modified_stamp =
@@ -803,7 +804,8 @@ get_header(fp, hdr)
                break;
 
        default:
-        archive_delim = "\xff\\";
+        archive_delim = "\377\\";
+                          /* `\' is for level 0 header and broken archive. */
         system_delim = "//";
         filename_case = noconvertcase ? NONE : TO_LOWER;
         /* FIXME: if small letter is included in filename,
@@ -852,16 +854,8 @@ init_header(name, v_stat, hdr)
 {
        int             len;
 
-    int system_kanji_code = default_system_kanji_code;
-    char *archive_delim = "";
-    char *system_delim = "";
-    int filename_case = NONE;
-
     memset(hdr, 0, sizeof(LzHeader));
 
-    if (optional_system_kanji_code)
-        system_kanji_code = optional_system_kanji_code;
-
        if (compress_method == LZHUFF5_METHOD_NUM)  /* Changed N.Watazaki */
                memcpy(hdr->method, LZHUFF5_METHOD, METHOD_TYPE_STRAGE);
        else if (compress_method)
@@ -934,16 +928,6 @@ init_header(name, v_stat, hdr)
             error("file name is too long (%s -> %.*s)", hdr->name, len, lkname);
        }
 #endif
-
-       if (generic_format) {
-        filename_case = TO_UPPER;
-        archive_delim = "\\";
-    }
-
-    convert_filename(hdr->name, len, sizeof(hdr->name),
-                     system_kanji_code,
-                     system_kanji_code, /* no change code */
-                     system_delim, archive_delim, filename_case);
 }
 
 /* ------------------------------------------------------------------------ */
@@ -958,9 +942,13 @@ write_header(nafp, hdr)
        char            data[LZHEADER_STRAGE];
        char           *p;
        char           *headercrc_ptr;
+
     int archive_kanji_code = CODE_SJIS;
     int system_kanji_code = default_system_kanji_code;
-       char            lzname[256];
+    char *archive_delim = "\377";
+    char *system_delim = "/";
+    int filename_case = NONE;
+       char lzname[256];
 
     if (optional_archive_kanji_code)
         archive_kanji_code = optional_archive_kanji_code;
@@ -990,19 +978,30 @@ write_header(nafp, hdr)
 
        put_byte(hdr->header_level);
 
+    if (generic_format)
+        filename_case = TO_UPPER;
+
+       if (hdr->header_level == HEADER_LEVEL0) {
+        archive_delim = "\\";
+    }
+
     strncpy(lzname, hdr->name, sizeof(lzname));
     convert_filename(lzname, strlen(lzname), sizeof(lzname),
                      system_kanji_code,
                      archive_kanji_code,
-                     "\xff\\/", "\xff\xff\xff", NONE);
+                     system_delim, archive_delim, filename_case);
 
        if (hdr->header_level != HEADER_LEVEL2) {
-               if (p = strrchr(lzname, LHA_PATHSEP))
-                       name_length = strlen(++p);
-               else
-                       name_length = strlen(lzname);
+        if (hdr->header_level == HEADER_LEVEL0 ||
+            (p = strchr(lzname, LHA_PATHSEP)) == 0)
+            p = lzname;
+        else
+            ++p;
+        /* level 0 header: write pathname (contain the directory part) */
+        /* level 1 header: write filename (basename only) */
+        name_length = strlen(p);
                put_byte(name_length);
-               memcpy(data + I_NAME, p ? p : lzname, name_length);
+               memcpy(data + I_NAME, p, name_length);
                setup_put(data + I_NAME + name_length);
        }
 
@@ -1123,7 +1122,13 @@ write_header(nafp, hdr)
                fatal_error("Cannot write to temporary file");
 }
 
-#ifdef __APPLE__
+#if MULTIBYTE_FILENAME
+
+#if defined(__APPLE__)
+
+#include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFStringEncodingExt.h>
+
 /* this is not need for Mac OS X v 10.2 later */
 enum {
   kCFStringEncodingAllowLossyConversion = 1,
@@ -1211,38 +1216,93 @@ ConvertUTF8ToEncoding(const char* inUTF8Buf,
 
     return cfResult;
 }
-#endif /* __APPLE__ */
+
+#elif HAVE_ICONV
+#include <iconv.h>
+
+static int
+ConvertEncodingByIconv(const char *src, char *dst, int dstsize,
+                       const char *srcEnc, const char *dstEnc)
+{
+    iconv_t ic;
+    static char szTmpBuf[2048];
+    char *src_p;
+    char *dst_p;
+    size_t sLen;
+    size_t iLen;
+
+    dst_p = &szTmpBuf[0];
+    iLen = (size_t)sizeof(szTmpBuf)-1;
+    src_p = (char *)src;
+    sLen = (size_t)strlen(src);
+    memset(szTmpBuf, 0, sizeof(szTmpBuf));
+    memset(dst, 0, dstsize);
+
+    ic = iconv_open(dstEnc, srcEnc);
+    if (ic == (iconv_t)-1) {
+        error("iconv_open() failure");
+        return -1;
+    }
+
+    if (iconv(ic, &src_p, &sLen, &dst_p, &iLen) == (size_t)-1) {
+        error("iconv() failure");
+        iconv_close(ic);
+        return -1;
+    }
+
+    strncpy(dst, szTmpBuf, dstsize);
+
+    iconv_close(ic);
+
+    return 0;
+}
+#endif /* defined(__APPLE__) */
 
 char *
 sjis_to_utf8(char *dst, const char *src, size_t dstsize)
 {
-#ifdef __APPLE__
+#if defined(__APPLE__)
   dst[0] = '\0';
-  ConvertEncodingToUTF8(src, dst, dstsize,
-                        kCFStringEncodingDOSJapanese,
-                        kCFStringEncodingUseHFSPlusCanonical);
-
+  if (ConvertEncodingToUTF8(src, dst, dstsize,
+                            kCFStringEncodingDOSJapanese,
+                            kCFStringEncodingUseHFSPlusCanonical) == 0)
+      return dst;
+#elif HAVE_ICONV
+  if (ConvertEncodingByIconv(src, dst, dstsize, "SJIS", "UTF-8") != -1)
+      return dst;
 #else
-  /* not supported */
+  error("not support utf-8 conversion");
 #endif
-  return dst;
+
+  /* not supported */
+  if (dstsize < 1) return dst;
+  dst[dstsize-1] = 0;
+  return strncpy(dst, src, dstsize-1);
 }
 
 char *
 utf8_to_sjis(char *dst, const char *src, size_t dstsize)
 {
-#ifdef __APPLE__
+#if defined(__APPLE__)
   int srclen;
 
   dst[0] = '\0';
   srclen = strlen(src);
-  ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
-                        kCFStringEncodingDOSJapanese,
-                        kCFStringEncodingUseHFSPlusCanonical);
+  if (ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
+                            kCFStringEncodingDOSJapanese,
+                            kCFStringEncodingUseHFSPlusCanonical) == 0)
+      return dst;
+#elif HAVE_ICONV
+  if (ConvertEncodingByIconv(src, dst, dstsize, "UTF-8", "SJIS") != -1)
+      return dst;
 #else
-  /* not supported */
+  error("not support utf-8 conversion");
 #endif
-  return dst;
+
+  /* not supported */
+  if (dstsize < 1) return dst;
+  dst[dstsize-1] = 0;
+  return strncpy(dst, src, dstsize-1);
 }
 
 /*
@@ -1275,6 +1335,7 @@ sjis2euc(int *p1, int *p2)
     *p1 |= 0x80;
     *p2 |= 0x80;
 }
+#endif /* MULTIBYTE_FILENAME */
 
 /* Local Variables: */
 /* mode:c */