diff -urN proftpd-1.3.4.orig/configure proftpd-1.3.4/configure
--- proftpd-1.3.4.orig/configure	2012-11-20 19:56:45.434081354 +0900
+++ proftpd-1.3.4/configure	2012-11-20 20:00:43.433971966 +0900
@@ -32536,7 +32536,7 @@
 
 
 
-LIBS="-lsupp $LIBS"
+LIBS="-lsupp -luchardet $LIBS"
 
 ac_shared_module_dirs=
 ac_static_module_dirs=
diff -urN proftpd-1.3.4.orig/include/universalchardet.h proftpd-1.3.4/include/universalchardet.h
--- proftpd-1.3.4.orig/include/universalchardet.h	1970-01-01 09:00:00.000000000 +0900
+++ proftpd-1.3.4/include/universalchardet.h	2012-11-20 20:00:43.404574033 +0900
@@ -0,0 +1,160 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Universal charset detector code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *          Kohei TAKETA <k-tak@void.in>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef ___UNIVERSALCHARDET_H___
+#define ___UNIVERSALCHARDET_H___
+
+#ifdef _WIN32
+#   ifdef DLL_EXPORTS
+#	define CHARDET_IMEXPORT extern _declspec(dllexport)
+#   else
+#	define CHARDET_IMEXPORT extern _declspec(dllimport)
+#   endif
+#else
+#   define CHARDET_IMEXPORT extern
+#endif
+
+#include <stddef.h>
+
+#define CHARDET_RESULT_OK		    0
+#define CHARDET_RESULT_NOMEMORY		    (-1)
+#define CHARDET_RESULT_INVALID_DETECTOR	    (-2)
+
+#define CHARDET_MAX_ENCODING_NAME	    64
+
+#define CHARDET_ENCODING_ISO_2022_JP    "ISO-2022-JP"
+#define CHARDET_ENCODING_ISO_2022_CN    "ISO-2022-CN"
+#define CHARDET_ENCODING_ISO_2022_KR    "ISO-2022-KR"
+#define CHARDET_ENCODING_ISO_8859_5     "ISO-8859-5"
+#define CHARDET_ENCODING_ISO_8859_7     "ISO-8859-7"
+#define CHARDET_ENCODING_ISO_8859_8     "ISO-8859-8"
+#define CHARDET_ENCODING_BIG5           "BIG5"
+#define CHARDET_ENCODING_GB18030        "GB18030"
+#define CHARDET_ENCODING_EUC_JP         "EUC-JP"
+#define CHARDET_ENCODING_EUC_KR         "EUC-KR"
+#define CHARDET_ENCODING_EUC_TW         "EUC-TW"
+#define CHARDET_ENCODING_SHIFT_JIS      "SHIFT_JIS"
+#define CHARDET_ENCODING_IBM855         "IBM855"
+#define CHARDET_ENCODING_IBM866         "IBM866"
+#define CHARDET_ENCODING_KOI8_R         "KOI8-R"
+#define CHARDET_ENCODING_MACCYRILLIC    "MACCYRILLIC"
+#define CHARDET_ENCODING_WINDOWS_1251   "WINDOWS-1251"
+#define CHARDET_ENCODING_WINDOWS_1252   "WINDOWS-1252"
+#define CHARDET_ENCODING_WINDOWS_1253   "WINDOWS-1253"
+#define CHARDET_ENCODING_WINDOWS_1255   "WINDOWS-1255"
+#define CHARDET_ENCODING_UTF_8          "UTF-8"
+#define CHARDET_ENCODING_UTF_16BE       "UTF-16BE"
+#define CHARDET_ENCODING_UTF_16LE       "UTF-16LE"
+#define CHARDET_ENCODING_UTF_32BE       "UTF-32BE"
+#define CHARDET_ENCODING_UTF_32LE       "UTF-32LE"
+#define CHARDET_ENCODING_HZ_GB_2312     "HZ-GB-2312"
+#define CHARDET_ENCODING_X_ISO_10646_UCS_4_3412 "X-ISO-10646-UCS-4-3412"
+#define CHARDET_ENCODING_X_ISO_10646_UCS_4_2143 "X-ISO-10646-UCS-4-2143"
+
+/* Unused */
+#define CHARDET_ENCODING_ISO_8859_2     "ISO-8859-2"
+#define CHARDET_ENCODING_WINDOWS_1250   "WINDOWS-1250"
+#define CHARDET_ENCODING_TIS_620        "TIS-620"
+
+typedef void* chardet_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Create an encoding detector.
+ * @param pdet [out] pointer to a chardet_t variable that receives
+ *             the encoding detector handle.
+ * @return CHARDET_RESULT_OK if succeeded. CHARDET_RESULT_NOMEMORY otherwise.
+ */
+CHARDET_IMEXPORT int chardet_create(chardet_t* pdet);
+
+/**
+ * Destroy an encoding detector.
+ * @param det [in] the encoding detector handle to be destroyed.
+ */
+CHARDET_IMEXPORT void chardet_destroy(chardet_t det);
+
+/**
+ * Feed data to an encoding detector.
+ * @param det [in] the encoding detector handle
+ * @param data [in] data
+ * @param len [in] length of data in bytes.
+ * @return CHARDET_RESULT_OK if succeeded.
+ *         CHARSET_RESULT_NOMEMORY if running out of memory.
+ *         CHARDET_RESULT_INVALID_DETECTOR if det was invalid.
+ */
+CHARDET_IMEXPORT int chardet_handle_data(chardet_t det, const char* data, unsigned int len);
+
+/**
+ * Notify an end of data to an encoding detctor.
+ * @param det [in] the encoding detector handle
+ * @return CHARDET_RESULT_OK if succeeded.
+ *         CHARDET_RESULT_INVALID_DETECTOR if det was invalid.
+ */
+CHARDET_IMEXPORT int chardet_data_end(chardet_t det);
+
+/**
+ * Reset an encoding detector.
+ * @param det [in] the encoding detector handle
+ * @return CHARDET_RESULT_OK if succeeded.
+ *         CHARDET_RESULT_INVALID_DETECTOR if det was invalid.
+ */
+CHARDET_IMEXPORT int chardet_reset(chardet_t det);
+
+/**
+ * Get the name of encoding that was detected.
+ * @param det [in] the encoding detector handle
+ * @param namebuf [in/out] pointer to a buffer that receives the name of
+ *                detected encoding. A valid encoding name or an empty string
+ *                will be written to namebuf. If an empty strng was written,
+ *                the detector could not detect any encoding.
+ *                Written strings will always be NULL-terminated.
+ * @param buflen [in] length of namebuf
+ * @return CHARDET_RESULT_OK if succeeded.
+ *         CHARDET_RESULT_NOMEMORY if namebuf was too small to store
+ *         the entire encoding name.
+ *         CHARDET_RESULT_INVALID_DETECTOR if det was invalid.
+ */
+CHARDET_IMEXPORT int chardet_get_charset(chardet_t det, char* namebuf, unsigned int buflen);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff -urN proftpd-1.3.4.orig/modules/mod_codeconv.c proftpd-1.3.4/modules/mod_codeconv.c
--- proftpd-1.3.4.orig/modules/mod_codeconv.c	1970-01-01 09:00:00.000000000 +0900
+++ proftpd-1.3.4/modules/mod_codeconv.c	2012-11-20 20:00:43.444150442 +0900
@@ -0,0 +1,267 @@
+/*
+ * ProFTPD: mod_codeconv -- local <-> remote charset conversion
+ *
+ * Copyright (c) 2004 by TSUJIKAWA Tohru <tsujikawa@tsg.ne.jp> / All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+
+#include        "conf.h"
+#include        <iconv.h>
+#include        "universalchardet.h"
+
+//
+// directive
+//
+#define DIRECTIVE_CHARSETLOCAL          "CharsetLocal"
+#define DIRECTIVE_CHARSETREMOTE         "CharsetRemote"
+#define DIRECTIVE_CHARAUTOUTF8          "CharautoUTF8Remote2Local"
+
+//
+// initialization
+//
+static int codeconv_init(void)
+{
+  return 0;
+}
+
+static int codeconv_sess_init(void)
+{
+  return 0;
+}
+
+
+char* remote2local(struct pool* pool, char* remote)
+{
+  iconv_t ic;
+  char*   local;
+  char*   in_ptr;
+  char*   out_ptr;
+  size_t  inbytesleft, outbytesleft;
+
+  config_rec*     conf_l = NULL;
+  config_rec*     conf_r = NULL;
+  config_rec*     conf_a = NULL;
+
+  conf_l = find_config(main_server->conf, CONF_PARAM, DIRECTIVE_CHARSETLOCAL, FALSE);
+  conf_r = find_config(main_server->conf, CONF_PARAM, DIRECTIVE_CHARSETREMOTE, FALSE);
+  conf_a = find_config(main_server->conf, CONF_PARAM, DIRECTIVE_CHARAUTOUTF8, FALSE);
+
+  if (!conf_l || !conf_r) return NULL;
+  if (conf_a) {
+    char encoding[32];
+    chardet_t det = NULL;
+    char* autochar = conf_r->argv[0];
+
+    chardet_create(&det);
+    chardet_handle_data(det, remote, (unsigned int)strlen(remote));
+    chardet_data_end(det);
+    chardet_get_charset(det, encoding, sizeof(encoding));
+    if (strcmp(encoding,"UTF-8")==0) {
+      autochar = "UTF-8";
+    }
+    chardet_destroy(det);
+
+    ic = iconv_open(conf_l->argv[0], autochar );
+  } else {
+    ic = iconv_open(conf_l->argv[0], conf_r->argv[0]);
+  }
+  if (ic == (iconv_t)(-1)) return NULL;
+
+  iconv(ic, NULL, NULL, NULL, NULL);
+
+  inbytesleft = strlen(remote);
+  outbytesleft = inbytesleft*3;
+  local = palloc(pool, outbytesleft+1);
+
+  in_ptr = remote; out_ptr = local;
+  while (inbytesleft) {
+    if (iconv(ic, &in_ptr, &inbytesleft, &out_ptr, &outbytesleft) == -1) {
+      *out_ptr = '?'; out_ptr++; outbytesleft--;
+      in_ptr++; inbytesleft--;
+      break;
+    }
+  }
+  *out_ptr = 0;
+
+  iconv_close(ic);
+
+  return local;
+}
+
+
+char* local2remote(char* local)
+{
+  iconv_t ic;
+  char*   remote;
+  char*   in_ptr;
+  char*   out_ptr;
+  size_t  inbytesleft, outbytesleft;
+
+  config_rec*     conf_l = NULL;
+  config_rec*     conf_r = NULL;
+
+  conf_l = find_config(main_server->conf, CONF_PARAM, DIRECTIVE_CHARSETLOCAL, FALSE);
+  conf_r = find_config(main_server->conf, CONF_PARAM, DIRECTIVE_CHARSETREMOTE, FALSE);
+  if (!conf_l || !conf_r) return NULL;
+
+  ic = iconv_open(conf_r->argv[0], conf_l->argv[0]);
+  if (ic == (iconv_t)(-1)) return NULL;
+
+  iconv(ic, NULL, NULL, NULL, NULL);
+
+  inbytesleft = strlen(local);
+  outbytesleft = inbytesleft*3;
+  remote = malloc(outbytesleft+1);
+
+  in_ptr = local; out_ptr = remote;
+  while (inbytesleft) {
+    if (iconv(ic, &in_ptr, &inbytesleft, &out_ptr, &outbytesleft) == -1) {
+      *out_ptr = '?'; out_ptr++; outbytesleft--;
+      in_ptr++; inbytesleft--;
+      break;
+    }
+  }
+  *out_ptr = 0;
+
+  iconv_close(ic);
+
+  return remote;
+}
+
+
+//
+// module handler
+//
+MODRET codeconv_pre_any(cmd_rec* cmd)
+{
+  char*   p;
+  int             i;
+
+  p = remote2local(cmd->pool, cmd->arg);
+  if (p) cmd->arg = p;
+
+  for (i = 0; i < cmd->argc; i++) {
+    p = remote2local(cmd->pool, cmd->argv[i]);
+    if (p) cmd->argv[i] = p;
+  }
+
+  return DECLINED(cmd);
+}
+
+
+//
+// local charset directive "CharsetLocal"
+//
+MODRET set_charsetlocal(cmd_rec *cmd) {
+  config_rec *c = NULL;
+
+  /* Syntax: CharsetLocal iconv-charset-name */
+
+  CHECK_ARGS(cmd, 1);
+  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
+
+  c = add_config_param_str(DIRECTIVE_CHARSETLOCAL, 1, cmd->argv[1]);
+
+  return HANDLED(cmd);
+}
+
+//
+// remote charset directive "CharsetRemote"
+//
+MODRET set_charsetremote(cmd_rec *cmd) {
+  config_rec *c = NULL;
+
+  /* Syntax: CharsetRemote iconv-charset-name */
+
+  CHECK_ARGS(cmd, 1);
+  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
+
+  c = add_config_param_str(DIRECTIVE_CHARSETREMOTE, 1, cmd->argv[1]);
+
+  return HANDLED(cmd);
+}
+
+
+// local charset directive "CharsetUTF8Remote2Local"
+//
+MODRET set_charsetutf8remote2local(cmd_rec *cmd) {
+  config_rec *c = NULL;
+
+  /* Syntax: CharsetUTF8Remote2Local auto-charset-name */
+
+  CHECK_ARGS(cmd, 1);
+  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
+
+  c = add_config_param_str(DIRECTIVE_CHARAUTOUTF8, 1, cmd->argv[1]);
+
+  return HANDLED(cmd);
+}
+
+
+
+//
+// module 用 directive
+//
+static conftable codeconv_conftab[] = {
+  { DIRECTIVE_CHARSETLOCAL,               set_charsetlocal,               NULL },
+  { DIRECTIVE_CHARSETREMOTE,              set_charsetremote,              NULL },
+  { DIRECTIVE_CHARAUTOUTF8,       set_charsetutf8remote2local, NULL },
+  { NULL, NULL, NULL }
+};
+
+
+//
+// trap するコマンド一覧
+//
+static cmdtable codeconv_cmdtab[] = {
+  { PRE_CMD,              C_ANY,  G_NONE, codeconv_pre_any,       FALSE, FALSE },
+  { 0,                    NULL }
+};
+
+
+//
+// module 情報
+//
+module codeconv_module = {
+
+  /* Always NULL */
+  NULL, NULL,
+
+  /* Module API version (2.0) */
+  0x20,
+
+  /* Module name */
+  "codeconv",
+
+  /* Module configuration directive handlers */
+  codeconv_conftab,
+
+  /* Module command handlers */
+  codeconv_cmdtab,
+
+  /* Module authentication handlers (none in this case) */
+  NULL,
+
+  /* Module initialization */
+  codeconv_init,
+
+  /* Session initialization */
+        codeconv_sess_init
+
+};
+
diff -urN proftpd-1.3.4.orig/modules/mod_ls.c proftpd-1.3.4/modules/mod_ls.c
--- proftpd-1.3.4.orig/modules/mod_ls.c	2012-11-20 19:56:45.454176878 +0900
+++ proftpd-1.3.4/modules/mod_ls.c	2012-11-20 20:00:43.444150442 +0900
@@ -264,10 +264,13 @@
 static char *listbuf = NULL;
 static size_t listbufsz = 0;
 
+extern char* local2remote(char*);
+
 static int sendline(int flags, char *fmt, ...) {
   va_list msg;
   char buf[PR_TUNABLE_BUFFER_SIZE+1] = {'\0'};
   int res = 0;
+  char* buf2;
   size_t listbuflen;
 
   if (listbuf == NULL) {
@@ -308,6 +311,13 @@
 
   buf[sizeof(buf)-1] = '\0';
 
+  if (buf[0]) {
+    buf2 = local2remote(buf);
+    if (buf2) {
+      strcpy(buf,buf2); free(buf2);
+    }
+  }
+
   /* If buf won't fit completely into listbuf, flush listbuf */
   listbuflen = strlen(listbuf);
 
diff -urN proftpd-1.3.4.orig/src/netio.c proftpd-1.3.4/src/netio.c
--- proftpd-1.3.4.orig/src/netio.c	2012-11-20 19:56:45.404194421 +0900
+++ proftpd-1.3.4/src/netio.c	2012-11-20 20:00:43.404574033 +0900
@@ -622,9 +622,12 @@
   return -1;
 }
 
+extern char* local2remote(char* local);
+
 int pr_netio_printf(pr_netio_stream_t *nstrm, const char *fmt, ...) {
   va_list msg;
   char buf[PR_RESPONSE_BUFFER_SIZE] = {'\0'};
+  char* p;
 
   if (!nstrm) {
     errno = EINVAL;
@@ -636,6 +639,13 @@
   va_end(msg);
   buf[sizeof(buf)-1] = '\0';
 
+  if (buf[0]) {
+    p = local2remote(buf);
+    if (p) {
+      strcpy(buf, p); free(p);
+    }
+  }
+
   return pr_netio_write(nstrm, buf, strlen(buf));
 }
 
