Skip to content

Instantly share code, notes, and snippets.

@takeutch-kemeco
Last active January 26, 2021 02:50
Show Gist options
  • Save takeutch-kemeco/8753733 to your computer and use it in GitHub Desktop.
Save takeutch-kemeco/8753733 to your computer and use it in GitHub Desktop.
UnZip-6.0 で文字コードが CP932 or ISO-2022-JP の zip をデコードした場合に、ファイル名が文字化けする問題を修正するパッチ
diff --git a/extract.c b/extract.c
index 1acd769..9f18940 100644
--- a/extract.c
+++ b/extract.c
@@ -2554,6 +2554,10 @@ char *fnfilter(raw, space, size) /* convert name to safely printable form */
uch *space;
extent size;
{
+#ifdef LINUX
+ return (char *)raw;
+#endif /* LINUX */
+
#ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
ZCONST uch *r=(ZCONST uch *)raw;
uch *s=space;
diff --git a/fileio.c b/fileio.c
index ba0a1d0..317211e 100644
--- a/fileio.c
+++ b/fileio.c
@@ -83,7 +83,6 @@
#endif
#include "ebcdic.h" /* definition/initialization of ebcdic[] */
-
/*
Note: Under Windows, the maximum size of the buffer that can be used
with any of the *printf calls is 16,384, so win_fprintf was used to
@@ -2238,6 +2237,11 @@ int do_string(__G__ length, option) /* return PK-type error code */
G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */
#endif /* ?UNICODE_SUPPORT */
+#ifdef LINUX
+ iconv_to_utf8(G.filename, FILNAMSIZ);
+ break;
+#endif /* LINUX */
+
/* translate the Zip entry filename coded in host-dependent "extended
ASCII" into the compiler's (system's) internal text code page */
Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver,
@@ -2853,3 +2857,108 @@ int Far zfstrcmp(const char Far *s1, const char Far *s2)
#endif /* !_MSC_VER || (_MSC_VER < 600) */
#endif /* SMALL_MEM */
+
+
+
+
+
+/***********************/
+/* Function iconvstr() */
+/***********************/
+
+void iconvstr(char *target_code, char *dstbuf, size_t dstlen,
+ char *from_code, char *srcbuf, size_t srclen)
+{
+#ifdef LINUX
+ iconv_t ct = iconv_open(target_code, from_code);
+ if (ct == (iconv_t)-1) {
+ memcpy(dstbuf, srcbuf, srclen);
+ return;
+ }
+
+ char *s = srcbuf;
+ char *d = dstbuf;
+ while (*s != '\0' && dstlen > 0 && srclen > 0) {
+ size_t err = iconv(ct, &s, &srclen, &d, &dstlen);
+ if (err == (size_t)-1)
+ break;
+ }
+
+ *d = '\0';
+
+ iconv_close(ct);
+#endif /* LINUX */
+}
+
+
+
+/************************/
+/* Function is_encode() */
+/************************/
+
+int is_encode(char *code, char *buf, const size_t buflen)
+{
+#ifdef LINUX
+ char *bufA = calloc(buflen, sizeof(*bufA));
+ iconvstr("UTF8", bufA, buflen, code, buf, buflen);
+
+ char *bufB = calloc(buflen, sizeof(*bufB));
+ iconvstr(code, bufB, buflen, "UTF8", bufA, buflen);
+
+ int ret = TRUE;
+ char *s = buf;
+ char *d = bufB;
+ while (*s != '\0') {
+ if (*s++ != *d++) {
+ ret = FALSE;
+ break;
+ }
+ }
+
+ free(bufA);
+ free(bufB);
+
+ return ret;
+#endif /* LINUX */
+
+ return 0;
+}
+
+
+
+#ifdef LINUX
+/* used iconv_to_tf8(), iconv try list. */
+static char iconvlist[][0x100] = {
+ "ISO-2022-JP", "CP932", "EUC-JP",
+ "",
+};
+#endif /* LINUX */
+
+
+
+/****************************/
+/* Function iconv_to_utr8() */
+/****************************/
+
+void iconv_to_utf8(char *buf, const size_t buflen)
+{
+#ifdef LINUX
+ if (is_encode("UTF8", buf, buflen))
+ return;
+
+ char *bufA = calloc(buflen, sizeof(*bufA));
+ memcpy(bufA, buf, buflen);
+
+ int i = 0;
+ while (strcmp(iconvlist[i], "") != 0) {
+ if (is_encode(iconvlist[i], bufA, buflen)) {
+ iconvstr("UTF8", buf, buflen, iconvlist[i], bufA, buflen);
+ break;
+ }
+
+ i++;
+ }
+
+ free(bufA);
+#endif /* LINUX */
+}
diff --git a/unzpriv.h b/unzpriv.h
index dc9eff5..accc860 100644
--- a/unzpriv.h
+++ b/unzpriv.h
@@ -670,6 +670,10 @@
#endif /* ?MODERN */
+#ifdef LINUX
+#include <iconv.h>
+#endif /* LINUX */
+
/*************/
@@ -3120,4 +3124,30 @@ char *GetLoadPath OF((__GPRO)); /* local */
#endif /* UNICODE_SUPPORT && UNICODE_WCHAR */
+
+/*****************/
+/* iconv support */
+/*****************/
+
+/* Regarded as "from_code" character code of srcbuf, to replicate to dstbuf
+ * by converting to a character code "target_code".
+ */
+void iconvstr(char *target_code, char *dstbuf, size_t dstlen,
+ char *from_code, char *srcbuf, size_t srclen);
+
+/* Check whether there may be a "buf" character code "code", and returns a
+ * "True(non-zero)" if it is possible.
+ * (Will return "False(zero)" if there is no possibility)
+ */
+int is_encode(char *code, char *buf, const size_t buflen);
+
+/* Convert character code to a string of UTF8, the contents of the "buf".
+ * However attempt to transform, only the character codes listed in "iconvlist".
+ * It does not consider measures when the buffer is full, to be secured sufficient
+ * buffer size in advance in the "buf".
+ */
+void iconv_to_utf8(char *buf, const size_t buflen);
+
+
+
#endif /* !__unzpriv_h */
これは UnZip-6.0 で文字コードが CP932 or ISO-2022-JP の zip をデコードした場合に、
ファイル名が文字化けする問題を修正するパッチです。
文字コードは CP932, ISO-2022-JP, EUC-JP, UTF8 のみを想定してます。(それ以外はアウトオブ眼中です)
UnZip-6.0 のソースコードは以下のアドレスからダウンロードできます:
http://downloads.sourceforge.net/infozip/unzip60.tar.gz
UnZip-6.0 の通常のビルド方法は以下のアドレスが参考になります:
http://www.linuxfromscratch.org/blfs/view/svn/general/unzip.html
パッチ適用からビルドまでの手順:
1. UnZip-6.0のソースファイルをダウンロードし、ファイルを展開します:
wget -c http://downloads.sourceforge.net/infozip/unzip60.tar.gz
gzip -dc unzip60.tar.gz | tar xvf -
2. 今展開したUnZip-6.0ディレクトリー内へ移動し、unzip60-linux-cp932.patch パッチを同ディレクトリ内へ置きます:
cd unzip60
3. パッチを適用します:
patch -p1 < unzip60-linux-cp932.patch
4. コンパイルします:
make -f unix/Makefile linux_noasm
これで、ディレクトリ内に実行ファイル unzip が作成されます。
この状態でも ./unzip とすることで使用できますが、
これをシステムへインストールしたい場合は sudo make prefix=/usr install とするか、または手動で sudo cp unzip /usr/bin とします。
@tkhm
Copy link

tkhm commented Jun 24, 2016

とても助かりました。完全に上記の手順通りでうまくいきました。(On RHEL 6.7) どうもありがとうございます!

@Hukanzen
Copy link

Debian 9.8でもできました.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment