diff -urbB unzip-5.52.orig/fileio.c unzip-5.52/fileio.c
--- unzip-5.52.orig/fileio.c	2006-12-22 12:47:47.000000000 +0900
+++ unzip-5.52/fileio.c	2006-12-23 15:53:38.000000000 +0900
@@ -2463,6 +2463,66 @@
 #endif /* REGULUS */
 
 
+#ifdef NLS
+char*
+strdup_iconv (const char	*to_enc,
+	      const char	*from_enc,
+	      char		*str)
+{
+  iconv_t cd;
+  char *outbuf, *outbufp, *inbufp;
+  size_t outbufsize, inbytesleft, outbytesleft, ret;
+
+  inbufp = str;
+  inbytesleft = strlen (str);
+  outbytesleft = outbufsize = 8192;
+  outbufp = outbuf = malloc (outbufsize);
+  if (! outbuf)
+    return NULL;
+
+  cd = iconv_open (to_enc, from_enc);
+  if (cd == (iconv_t) -1)
+    return NULL;
+
+  while (inbytesleft) {
+    ret = iconv (cd, &inbufp, &inbytesleft, &outbufp, &outbytesleft);
+    if (ret == (size_t) -1) {
+      if (errno == E2BIG) {
+	size_t offset = (size_t) outbufp - (size_t) outbuf;
+	char *newbuf;
+	/* grow size of memory */
+	outbufsize += 8192;
+	outbytesleft += 8192;
+	newbuf = realloc (outbuf, outbufsize);
+	if (! newbuf) {
+	  iconv_close (cd);
+	  free (outbuf);
+	  return NULL;
+	}
+	outbuf = newbuf;
+	outbufp = outbuf + offset;
+      } else if (outbytesleft > 0 && inbytesleft > 0) {
+	/* error but force to go forward */
+	*outbufp ++ = *inbufp ++;
+	inbytesleft --;
+	outbytesleft --;
+      } else break;
+    }
+  }
+  iconv_close (cd);
+
+  outbufsize -= outbytesleft;
+  if (outbufsize < 1) {
+    free (outbuf);
+    return NULL;
+  }
+
+  outbuf = realloc (outbuf, outbufsize + 1);
+  outbuf[outbufsize] = '\0';
+
+  return outbuf;
+}
+#endif
 
 
 #ifdef _MBCS
@@ -2492,6 +2552,13 @@
 }
 
 
+int uzmblen (ZCONST char *ptr) {
+  int i = mblen (ptr, MB_CUR_MAX);
+  if (i >= 0) return i;
+  return 1; /* keep to go forward */
+}
+
+
 #ifdef NEED_UZMBSCHR
 /***********************/
 /* Function uzmbschr() */
diff -urbB unzip-5.52.orig/unix/unix.c unzip-5.52/unix/unix.c
--- unzip-5.52.orig/unix/unix.c	2006-12-22 12:47:47.000000000 +0900
+++ unzip-5.52/unix/unix.c	2006-12-23 14:21:01.000000000 +0900
@@ -196,7 +196,7 @@
         }
 
         /* break the wildspec into a directory part and a wildcard filename */
-        if ((G.wildname = (ZCONST char *)strrchr(wildspec, '/')) == NULL) {
+        if ((G.wildname = (ZCONST char *)MBSRCHR(wildspec, '/')) == NULL) {
             G.dirname = ".";
             G.dirnamelen = 1;
             G.have_dirname = FALSE;
@@ -431,7 +431,11 @@
              */
             if ((tmp & 0x10) == 0) {
                 extent fnlen = strlen(G.filename);
+#ifdef _MBCS
+		if (lastchar(G.filename, fnlen) == '/')
+#else
                 if (fnlen > 0 && G.filename[fnlen-1] == '/')
+#endif
                     tmp |= 0x10;
             }
             /* read-only bit --> write perms; subdir bit --> dir exec bit */
@@ -508,7 +512,7 @@
     *pathcomp = '\0';           /* initialize translation buffer */
     pp = pathcomp;              /* point to translation buffer */
     if (uO.jflag)               /* junking directories */
-        cp = (char *)strrchr(G.filename, '/');
+        cp = (char *)MBSRCHR(G.filename, '/');
     if (cp == (char *)NULL)     /* no '/' or not junking dirs */
         cp = G.filename;        /* point to internal zipfile-member pathname */
     else
@@ -594,7 +598,11 @@
     fore exiting.
   ---------------------------------------------------------------------------*/
 
+#ifdef _MBCS
+    if (lastchar(G.filename, strlen(G.filename)) == '/') {
+#else
     if (G.filename[strlen(G.filename) - 1] == '/') {
+#endif
         checkdir(__G__ G.filename, GETPATH);
         if (G.created_dir) {
             if (QCOND2) {
@@ -883,7 +891,11 @@
                 return MPN_NOMEM;
             }
             strcpy(tmproot, pathcomp);
+#ifdef _MBCS
+	    if (lastchar(tmproot, G.rootlen) == '/') {
+#else
             if (tmproot[G.rootlen-1] == '/') {
+#endif
                 tmproot[--G.rootlen] = '\0';
             }
             if (G.rootlen > 0 && (SSTAT(tmproot, &G.statbuf) ||
diff -urbB unzip-5.52.orig/unzip.c unzip-5.52/unzip.c
--- unzip-5.52.orig/unzip.c	2005-02-27 13:37:14.000000000 +0900
+++ unzip-5.52/unzip.c	2006-12-23 15:46:09.000000000 +0900
@@ -667,6 +667,9 @@
 #endif /* NO_EXCEPT_SIGNALS */
 
     SETLOCALE(LC_CTYPE,"");
+#ifdef NLS /* needs locale support */
+    uO.charenc_sys = nl_langinfo (CODESET);
+#endif
 
 #if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
     extern void DebugMalloc(void);
@@ -1217,6 +1220,29 @@
 #endif /* !SFX || SFX_EXDIR */
                 case ('e'):    /* just ignore -e, -x options (extract) */
                     break;
+#ifdef NLS
+		case 'E':  /* -E:  character encoding for archive */
+		  if (negative) {
+		    uO.charenc_arch = NULL;
+		  } else {
+		    uO.charenc_arch = s;
+		    if (*uO.charenc_arch == '\0') {
+		      if (! (-- argc)) {
+			Info(slide, 0x401, ((char *)slide,
+			     "error:  must give character encording name\n"));
+			return PK_PARAM;
+		      }
+		      uO.charenc_arch = *(++ argv);
+		      if (*uO.charenc_arch == '-') {
+			Info(slide, 0x401, ((char *)slide,
+			     "error:  must give character encording name\n"));
+			return PK_PARAM;
+		      }
+		    }
+		    else while (*(++ s));
+		  }
+		  break;
+#endif /* NLS */
 #ifdef MACOS
                 case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
                     if( negative ) {
diff -urbB unzip-5.52.orig/unzip.h unzip-5.52/unzip.h
--- unzip-5.52.orig/unzip.h	2006-12-22 12:47:47.000000000 +0900
+++ unzip-5.52/unzip.h	2006-12-23 14:21:01.000000000 +0900
@@ -427,6 +427,10 @@
 #ifndef FUNZIP
     char *exdir;        /* pointer to extraction root directory (-d option) */
     char *pwdarg;       /* pointer to command-line password (-P option) */
+#ifdef NLS
+    char *charenc_sys;  /* character encoding for the system. */
+    char *charenc_arch; /* character encoding for an archive. */
+#endif
     int zipinfo_mode;   /* behave like ZipInfo or like normal UnZip? */
     int aflag;          /* -a: do ASCII-EBCDIC and/or end-of-line translation */
 #ifdef VMS
diff -urbB unzip-5.52.orig/unzpriv.h unzip-5.52/unzpriv.h
--- unzip-5.52.orig/unzpriv.h	2006-12-22 12:47:47.000000000 +0900
+++ unzip-5.52/unzpriv.h	2006-12-23 15:55:21.000000000 +0900
@@ -1159,6 +1159,19 @@
 
 #define FILNAMSIZ  PATH_MAX
 
+#ifdef NLS
+#  ifndef _MBCS
+#    define _MBCS
+#  endif
+#  include <langinfo.h>
+#  include <iconv.h>
+char* strdup_iconv (const char *to_name, const char *from_name, char *str);
+#  if (OUTBUFSIZ < FILNAMSIZ)
+#    undef OUTBUFSIZ
+#    define OUTBUFSIZ FILNAMSIZ
+#  endif
+#endif
+
 /* DBCS support for Info-ZIP  (mainly for japanese (-: )
  * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
  */
@@ -1167,7 +1180,8 @@
    /* Multi Byte Character Set */
 #  define ___MBS_TMP_DEF  char *___tmp_ptr;
 #  define ___TMP_PTR      ___tmp_ptr
-#  define CLEN(ptr) mblen((ZCONST char *)(ptr), MB_CUR_MAX)
+#  define CLEN(ptr) uzmblen(ptr)
+   int  uzmblen (ZCONST char *ptr);
 #  ifndef PREINCSTR
 #    define PREINCSTR(ptr) (ptr += CLEN(ptr))
 #  endif
@@ -2469,6 +2483,15 @@
  *  code page.  As with A_TO_N(), conversion is done in place.
  */
 #ifndef _ISO_INTERN
+#  ifdef NLS
+#    define _ISO_INTERN(str1) { \
+    char *tmp = strdup_iconv (uO.charenc_sys, "CP1252", str1); \
+    if (tmp) { \
+      strncpy (str1, tmp, FILNAMSIZ); \
+      free (tmp); \
+    } \
+  }
+#  else
 #  ifdef CRTL_CP_IS_OEM
 #    ifndef IZ_ISO2OEM_ARRAY
 #      define IZ_ISO2OEM_ARRAY
@@ -2479,9 +2502,19 @@
 #  else
 #    define _ISO_INTERN(str1)   A_TO_N(str1)
 #  endif
+#  endif /* NLS */
 #endif
 
 #ifndef _OEM_INTERN
+#  ifdef NLS
+#    define _OEM_INTERN(str1) { \
+    char *tmp = strdup_iconv (uO.charenc_sys, "CP437", str1); \
+    if (tmp) { \
+      strncpy (str1, tmp, FILNAMSIZ); \
+      free (tmp); \
+    } \
+  }
+#  else
 #  ifdef CRTL_CP_IS_OEM
 #    define _OEM_INTERN(str1)   A_TO_N(str1)
 #  else
@@ -2492,6 +2525,7 @@
        for (p=(uch *)(str1); *p; p++)\
          *p = native((*p & 0x80) ? oem2iso[*p & 0x7f] : *p);}
 #  endif
+#  endif /* NSL */
 #endif
 
 #ifndef STR_TO_ISO
@@ -2576,6 +2610,26 @@
  * All other ports are assumed to code zip entry filenames in ISO 8859-1.
  */
 #ifndef Ext_ASCII_TO_Native
+#  ifdef NLS
+#   define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \
+    if (uO.charenc_arch) { \
+      char *tmp = strdup_iconv (uO.charenc_sys, uO.charenc_arch, string); \
+      if (tmp) { \
+	strncpy (string, tmp, FILNAMSIZ); \
+	free (tmp); \
+      } \
+    } else { \
+    if (((hostnum) == FS_FAT_ && \
+         !(((islochdr) || (isuxatt)) && \
+           ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \
+        (hostnum) == FS_HPFS_ || \
+        ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
+        _OEM_INTERN((string)); \
+    } else { \
+        _ISO_INTERN((string)); \
+    } \
+    }
+#  else
 #  define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \
     if (((hostnum) == FS_FAT_ && \
          !(((islochdr) || (isuxatt)) && \
@@ -2586,6 +2640,7 @@
     } else { \
         _ISO_INTERN((string)); \
     }
+#  endif /* NLS */
 #endif
 
 
diff -urbB unzip-5.52.orig/zipinfo.c unzip-5.52/zipinfo.c
--- unzip-5.52.orig/zipinfo.c	2005-01-27 10:02:16.000000000 +0900
+++ unzip-5.52/zipinfo.c	2006-12-23 15:47:42.000000000 +0900
@@ -482,6 +482,27 @@
                         uO.C_flag = TRUE;
                     break;
 #endif /* !CMS_MVS */
+#ifdef NLS
+		case 'E': /* -E:  character encoding for archive */
+		  if (negative) {
+		    uO.charenc_arch = NULL;
+		  } else {
+		    uO.charenc_arch = s;
+		    if (*uO.charenc_arch == '\0') {
+		      if (! (-- argc)) {
+			error = TRUE;
+			break;
+		      }
+		      uO.charenc_arch = *(++ argv);
+		      if (*uO.charenc_arch == '-') {
+			error = TRUE;
+			break;
+		      }
+		    }
+		    else while (*(++ s));
+		  }
+		  break;
+#endif /* NLS */
                 case 'h':      /* header line */
                     if (negative)
                         hflag_2 = hflag_slmv = FALSE, negative = 0;
