作者 主題: FTP Server/Client 在 UTF-8 下的解決方案  (閱讀 69356 次)

0 會員 與 1 訪客 正在閱讀本文。

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
前幾天 "不小心" 把自己家裡的主機內的檔案名, 都改成 UTF-8 來處理, 在 samba 上頭是可以很正常的處理, 不過.... 發現在使用 ftp 時, 問題就不小了.

如果是支援 UTF-8 的 ftp client, 是可以正常運作, 如 gftp, smartftp....

不過, 在用了一天的 smartftp 之後, 實在發現和之前用 filezilla 的習慣大不相同, 用起來實在不習慣.

原本打算動手改 filezilla 的程式碼.... 只是, 在 windows 下頭, 似乎沒有 iconv 可以用... 又懶的去找 win32 可以用的函式... 所以, 就直接改 server 上的 vsftpd 來配合非 UTF-8 的 ftp client.

修改的構想主要來自 proftpd 的 iconv patch:
http://home.h01.itscom.net/para/software/misc/proftpd-iconv/index-e.html

我是修改 Debian 的 vsftpd 2.0.1 的版本.
patch 如下:

代碼: [選擇]
diff -Nur vsftpd-2.0.1/features.c vsftpd-2.0.1.patched/features.c
--- vsftpd-2.0.1/features.c 2004-07-02 19:22:45.000000000 +0800
+++ vsftpd-2.0.1.patched/features.c 2005-02-22 12:21:56.000000000 +0800
@@ -25,6 +25,7 @@
   vsf_cmdio_write_raw(p_sess, " EPSV\r\n");
   vsf_cmdio_write_raw(p_sess, " MDTM\r\n");
   vsf_cmdio_write_raw(p_sess, " PASV\r\n");
+  vsf_cmdio_write_raw(p_sess, " ICNV\r\n");
   if (tunable_ssl_enable)
   {
     vsf_cmdio_write_raw(p_sess, " PBSZ\r\n");
diff -Nur vsftpd-2.0.1/ftpcmdio.c vsftpd-2.0.1.patched/ftpcmdio.c
--- vsftpd-2.0.1/ftpcmdio.c 2004-07-02 19:23:02.000000000 +0800
+++ vsftpd-2.0.1.patched/ftpcmdio.c 2005-02-22 11:48:44.000000000 +0800
@@ -7,6 +7,9 @@
  * Routines applicable to reading and writing the FTP command stream.
  */
 
+#include <stdlib.h>
+#include <string.h>
+#include "utility.h"
 #include "ftpcmdio.h"
 #include "ftpcodes.h"
 #include "str.h"
@@ -170,6 +173,16 @@
   control_getline(p_cmd_str, p_sess);
   str_split_char(p_cmd_str, p_arg_str, ' ');
   str_upper(p_cmd_str);
+  if (!str_isempty(p_arg_str)) {
+      char *tmp_str;
+
+      tmp_str = remote2local(str_getbuf(p_arg_str));
+      if (tmp_str != NULL) {
+  str_empty(p_arg_str);
+          str_append_text(p_arg_str, tmp_str);
+  vsf_sysutil_free(tmp_str);
+      }
+  }
   if (tunable_log_ftp_protocol)
   {
     static struct mystr s_log_str;
diff -Nur vsftpd-2.0.1/ls.c vsftpd-2.0.1.patched/ls.c
--- vsftpd-2.0.1/ls.c 2004-07-02 19:23:34.000000000 +0800
+++ vsftpd-2.0.1.patched/ls.c 2005-02-22 11:48:56.000000000 +0800
@@ -7,6 +7,9 @@
  * Would you believe, code to handle directory listing.
  */
 
+#include <stdlib.h>
+#include <string.h>
+#include "utility.h"
 #include "ls.h"
 #include "access.h"
 #include "str.h"
@@ -363,6 +366,7 @@
                const struct vsf_sysutil_statbuf* p_stat)
 {
   static struct mystr s_tmp_str;
+  char *tmp_filename;
   filesize_t size = vsf_sysutil_statbuf_get_size(p_stat);
   /* Permissions */
   str_alloc_text(p_str, vsf_sysutil_statbuf_get_perms(p_stat));
@@ -432,7 +436,13 @@
                                                       tunable_use_localtime));
   str_append_char(p_str, ' ');
   /* Filename */
-  str_append_str(p_str, p_filename_str);
+  tmp_filename = local2remote(str_getbuf(p_filename_str));
+  if (tmp_filename == NULL)
+    str_append_str(p_str, p_filename_str);
+  else {
+    str_append_text(p_str, tmp_filename);
+    vsf_sysutil_free(tmp_filename);
+  }
   str_append_text(p_str, "\r\n");
 }
 
diff -Nur vsftpd-2.0.1/parseconf.c vsftpd-2.0.1.patched/parseconf.c
--- vsftpd-2.0.1/parseconf.c 2004-07-02 19:23:56.000000000 +0800
+++ vsftpd-2.0.1.patched/parseconf.c 2005-02-22 11:49:12.000000000 +0800
@@ -94,6 +94,7 @@
   { "ssl_sslv3", &tunable_sslv3 },
   { "ssl_tlsv1", &tunable_tlsv1 },
   { "tilde_user_enable", &tunable_tilde_user_enable },
+  { "enable_iconv", &tunable_enable_iconv },
   { 0, 0 }
 };
 
@@ -158,6 +159,8 @@
   { "rsa_cert_file", &tunable_rsa_cert_file },
   { "dsa_cert_file", &tunable_dsa_cert_file },
   { "ssl_ciphers", &tunable_ssl_ciphers },
+  { "local_charset", &tunable_local_charset },
+  { "remote_charset", &tunable_remote_charset },
   { 0, 0 }
 };
 
diff -Nur vsftpd-2.0.1/postlogin.c vsftpd-2.0.1.patched/postlogin.c
--- vsftpd-2.0.1/postlogin.c 2004-07-02 19:24:01.000000000 +0800
+++ vsftpd-2.0.1.patched/postlogin.c 2005-02-22 15:54:14.000000000 +0800
@@ -5,6 +5,9 @@
  * postlogin.c
  */
 
+#include <stdlib.h>
+#include <string.h>
+#include "utility.h"
 #include "postlogin.h"
 #include "session.h"
 #include "oneprocess.h"
@@ -157,6 +160,29 @@
     {
       handle_pwd(p_sess);
     }
+    else if (str_equal_text(&p_sess->ftp_cmd_str, "ICNV"))
+    {
+      str_upper(&p_sess->ftp_arg_str);
+      if (str_equal_text(&p_sess->ftp_arg_str, "ON"))
+      {
+        tunable_enable_iconv = 1;
+        vsf_cmdio_write(p_sess, FTP_CWDOK, "enable iconv().");
+      }
+      else if (str_equal_text(&p_sess->ftp_arg_str, "OFF"))
+      {
+        tunable_enable_iconv = 0;
+        vsf_cmdio_write(p_sess, FTP_CWDOK, "disable iconv().");
+      }
+      else {
+        if (tunable_enable_iconv) {
+          vsf_cmdio_write(p_sess, FTP_CWDOK, "iconv() enabled.");
+        }
+        else
+        {
+          vsf_cmdio_write(p_sess, FTP_CWDOK, "iconv() disabled.");
+        }
+      }
+    }
     else if (str_equal_text(&p_sess->ftp_cmd_str, "CWD") ||
              str_equal_text(&p_sess->ftp_cmd_str, "XCWD"))
     {
@@ -404,6 +430,7 @@
 static void
 handle_pwd(struct vsf_session* p_sess)
 {
+  char *tmp_str;
   static struct mystr s_cwd_buf_mangle_str;
   static struct mystr s_pwd_res_str;
   str_getcwd(&s_cwd_buf_mangle_str);
@@ -411,7 +438,13 @@
   str_replace_text(&s_cwd_buf_mangle_str, "\"", "\"\"");
   /* Enclose pathname in quotes */
   str_alloc_text(&s_pwd_res_str, "\"");
-  str_append_str(&s_pwd_res_str, &s_cwd_buf_mangle_str);
+  tmp_str = local2remote(str_getbuf(&s_cwd_buf_mangle_str));
+  if (tmp_str == NULL)
+    str_append_str(&s_pwd_res_str, &s_cwd_buf_mangle_str);
+  else {
+    str_append_text(&s_pwd_res_str, tmp_str);
+    vsf_sysutil_free(tmp_str);

+  }
   str_append_text(&s_pwd_res_str, "\"");
   vsf_cmdio_write_str(p_sess, FTP_PWDOK, &s_pwd_res_str);
 }
@@ -435,6 +468,24 @@
   }
   else
   {
+    if (tunable_enable_iconv) {
+      char *tmp_str;
+
+      tmp_str = local2remote(str_getbuf(&p_sess->ftp_arg_str));
+      if (tmp_str != NULL) {
+        str_empty(&p_sess->ftp_arg_str);
+        str_append_text(&p_sess->ftp_arg_str, tmp_str);
+        vsf_sysutil_free(tmp_str);
+        retval = str_chdir(&p_sess->ftp_arg_str);
+        if (retval == 0)
+        {
+          /* Handle any messages */
+          vsf_banner_dir_changed(p_sess, FTP_CWDOK);
+          vsf_cmdio_write(p_sess, FTP_CWDOK, "Directory successfully changed.");
+  return;
+        }
+      }
+    }
     vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to change directory.");
   }
 }
@@ -640,8 +691,29 @@
   opened_file = str_open(&p_sess->ftp_arg_str, kVSFSysStrOpenReadOnly);
   if (vsf_sysutil_retval_is_error(opened_file))
   {
-    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");
-    return;
+    if (tunable_enable_iconv) {
+      char *tmp_str;
+
+      tmp_str = local2remote(str_getbuf(&p_sess->ftp_arg_str));
+      if (tmp_str != NULL) {
+ str_empty(&p_sess->ftp_arg_str);
+ str_append_text(&p_sess->ftp_arg_str, tmp_str);
+ vsf_sysutil_free(tmp_str);
+ opened_file = str_open(&p_sess->ftp_arg_str, kVSFSysStrOpenReadOnly);
+ if (vsf_sysutil_retval_is_error(opened_file)) {
+          vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");
+          return;
+ }
+      }
+      else {
+        vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");
+        return;
+      }
+    }
+    else {
+      vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");
+      return;
+    }
   }
   vsf_sysutil_fstat(opened_file, &s_p_statbuf);
   /* No games please */
@@ -1623,7 +1695,7 @@
   vsf_cmdio_write_raw(p_sess,
 " RNTO SITE SIZE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD\r\n");
   vsf_cmdio_write_raw(p_sess,
-" XPWD XRMD\r\n");
+" XPWD XRMD ICNV\r\n");
   vsf_cmdio_write(p_sess, FTP_HELP, "Help OK.");
 }
 
diff -Nur vsftpd-2.0.1/tunables.c vsftpd-2.0.1.patched/tunables.c
--- vsftpd-2.0.1/tunables.c 2004-07-02 19:26:17.000000000 +0800
+++ vsftpd-2.0.1.patched/tunables.c 2005-02-22 12:17:52.000000000 +0800
@@ -66,6 +66,7 @@
 int tunable_sslv3 = 0;
 int tunable_tlsv1 = 1;
 int tunable_tilde_user_enable = 0;
+int tunable_enable_iconv = 0;
 
 unsigned int tunable_accept_timeout = 60;
 unsigned int tunable_connect_timeout = 60;
@@ -115,4 +116,7 @@
 const char* tunable_rsa_cert_file = "/usr/share/ssl/certs/vsftpd.pem";
 const char* tunable_dsa_cert_file = 0;
 const char* tunable_ssl_ciphers = "DES-CBC3-SHA";
+const char* tunable_local_charset = "UTF-8";
+const char* tunable_remote_charset = "BIG5";
+
 
diff -Nur vsftpd-2.0.1/tunables.h vsftpd-2.0.1.patched/tunables.h
--- vsftpd-2.0.1/tunables.h 2004-06-29 07:08:31.000000000 +0800
+++ vsftpd-2.0.1.patched/tunables.h 2005-02-22 11:50:27.000000000 +0800
@@ -62,6 +62,7 @@
 extern int tunable_sslv3;                     /* Allow SSLv3 */
 extern int tunable_tlsv1;                     /* Allow TLSv1 */
 extern int tunable_tilde_user_enable;         /* Support e.g. ~chris */
+extern int tunable_enable_iconv;      /* Convert filename use iconv */
 
 /* Integer/numeric defines */
 extern unsigned int tunable_accept_timeout;
@@ -110,6 +111,8 @@
 extern const char* tunable_rsa_cert_file;
 extern const char* tunable_dsa_cert_file;
 extern const char* tunable_ssl_ciphers;
+extern const char* tunable_local_charset;
+extern const char* tunable_remote_charset;
 
 #endif /* VSF_TUNABLES_H */
 
diff -Nur vsftpd-2.0.1/utility.c vsftpd-2.0.1.patched/utility.c
--- vsftpd-2.0.1/utility.c 2004-07-02 19:26:30.000000000 +0800
+++ vsftpd-2.0.1.patched/utility.c 2005-02-22 14:05:46.000000000 +0800
@@ -5,6 +5,13 @@

  * utility.c
  */
 
+#include <stdarg.h>
+#include <iconv.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include "tunables.h"
 #include "utility.h"
 #include "sysutil.h"
 #include "str.h"
@@ -50,3 +57,71 @@
   vsf_sysutil_exit(0);
 }
 
+char *
+local2remote(const char *buf)
+{
+  char *in_ptr;
+  char *out_ptr;
+  size_t inbytesleft, outbytesleft;
+  char *p;
+  iconv_t ic;
+
+  if (tunable_enable_iconv == 0) return NULL;
+  ic = iconv_open(tunable_remote_charset, tunable_local_charset);
+  if (ic == (iconv_t)(-1)) return NULL;
+  iconv(ic, NULL, NULL, NULL, NULL);
+
+  inbytesleft = strlen(buf);
+  outbytesleft = inbytesleft * 6;
+  p = vsf_sysutil_malloc(outbytesleft+1);
+
+  in_ptr = buf;
+  out_ptr = p;
+  while (inbytesleft) {
+    if (iconv(ic, &in_ptr, &inbytesleft, &out_ptr, &outbytesleft) == (size_t)(-1)) {
+      iconv_close(ic);
+      vsf_sysutil_free(p);
+      return NULL;
+    }
+  }
+
+  *out_ptr = 0;
+
+  iconv_close(ic);
+  return p;
+}
+
+char *
+remote2local(const char *buf)
+{
+  char *in_ptr;
+  char *out_ptr;
+  size_t inbytesleft, outbytesleft;
+  char *p;
+  iconv_t ic;
+
+  if (tunable_enable_iconv == 0) return NULL;
+  ic = iconv_open(tunable_local_charset, tunable_remote_charset);
+  if (ic == (iconv_t)(-1)) return NULL;
+  iconv(ic, NULL, NULL, NULL, NULL);
+
+  inbytesleft = strlen(buf);
+  outbytesleft = inbytesleft * 6;
+  p = vsf_sysutil_malloc(outbytesleft+1);
+
+  in_ptr = buf;
+  out_ptr = p;
+  while (inbytesleft) {
+    if (iconv(ic, &in_ptr, &inbytesleft, &out_ptr, &outbytesleft) == (size_t)(-1)) {
+      iconv_close(ic);
+      vsf_sysutil_free(p);
+      return NULL;
+    }
+  }
+
+  *out_ptr = 0;
+
+  iconv_close(ic);
+  return p;
+}
+
diff -Nur vsftpd-2.0.1/utility.h vsftpd-2.0.1.patched/utility.h
--- vsftpd-2.0.1/utility.h 2004-04-16 06:46:29.000000000 +0800
+++ vsftpd-2.0.1.patched/utility.h 2005-02-22 11:47:51.000000000 +0800
@@ -40,5 +40,7 @@
  */
 void vsf_exit(const char* p_text);
 
+char *local2remote(const char *buf);
+char *remote2local(const char *buf);
 #endif
 


可以到這兒抓
http://www.teatime.com.tw/~tommy/linux/vsftpd_iconv.patch

如果是使用 Debian Sarge, 也可以直接用這個:
http://www.teatime.com.tw/~tommy/debian/vsftpd_2.0.1-11_i386.deb

在使用這個 patch 之後, 你可以在 vsftpd.conf 中指定下面三個參數
代碼: [選擇]
enable_iconv=YES
local_charset=UTF-8
remote_charset=BIG5


local_charset 是主機檔案名稱使用的編碼. 內定為 UTF-8.
remote_charset 是 ftp client 的編碼. 內定為 BIG5.
enable_iconv 預設是關閉的, 也就是所有的動作應該都與沒加上這個 patch 時一樣. 如果設為 true/yes 時, 就會使用 iconv 來轉換檔名.

動作如下:
1. 所有的 client 送來的指令, 參數, 檔案或路徑名稱, 會使用 iconv 由 remote_charset 轉成 local_charset. 所以, 實際存取是使用 local_charset 的編碼.
2. 在 ls 指令時, 要送出檔名之前, 會用 iconv 由 local_charset 轉成 remote_charset 再送出.
3. 如果轉碼的動作是失敗的, 就不做轉碼的動作.
4. 加上一個 icnv on/off 指令 (非 ftp 標準), 可以讓 client 決定是否打開這個功能.
5. 主機上頭的檔案存取, 如果在轉成 local_charset 時, 存取失敗的話, 就假設該檔案或路徑為 remote_charset 的編碼格式, 再試一次.

以上述主機使用 UTF-8, client 使用 Big5 的情形下, 不管主機上頭的檔案路徑名稱是用 UTF-8 或 Big5, 都會轉成 Big5 送到 client 上頭, 所以當我們使用像 filezilla 之類不支援 UTF-8 的程式時, 所收到的都會是 Big5 編碼的資料.
如果我們使用支援 UTF-8 的 client 時, 如 gftp, 會發現, 反而原本在 UTF-8 的檔名, 在轉成 Big5 之後, 反而看不到正確的名稱. 此時, 可以使用上述的 icnv off 指令 (gftp 使用 site icnv off, 其他程式可能用 quote icnv off) 把轉碼的動作關閉, 就可以正常看到 UTF-8 編碼的檔案.

而在檔案抓取或更換目錄時, 會先用 UTF-8 試一次, 如果失敗, 再用 Big5 試一次. 以確定主機上頭的檔名無論是 Big5 或 UTF-8 都可以被存取.
而在檔案儲存或建立目錄時, 主機上只會使用 UTF-8 來編碼.

phantom

  • SA 苦力組
  • 俺是博士!
  • *****
  • 文章數: 2185
    • 檢視個人資料
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #1 於: 2005-02-22 16:57 »
了不起.
直接進精華區吧.
:)

改天也來玩玩.
Linux 非萬能, 沒 Linux 萬萬不能.
root = God
apt-get install ultimate-horsepower

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #2 於: 2005-02-25 10:59 »
修改幾個會出問題的指令. 如: rmdir, dele, rename, size, chmod.

新的 patch 可以到這兒抓
http://www.teatime.com.tw/~tommy/linux/vsftpd_iconv.patch

如果是使用 Debian Sarge, 也可以直接用這個:
http://www.teatime.com.tw/~tommy/debian/vsftpd_2.0.1-11_i386.deb

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #3 於: 2005-02-25 23:32 »
順便改一下 gftp 在處理 remote_charsets 的錯誤.

修改這個後, 就可以不用我之前加上的那個非標準的 icnv off 指令, 由 gftp 本身就可以處理 utf-8 (或支援 rfc-2640) 的 server, 加上 remote_charsets 設定, 也可以處理其它指定的編碼.

代碼: [選擇]
diff -Nur gftp-2.0.18/lib/protocols.c gftp-2.0.18.patched/lib/protocols.c

--- gftp-2.0.18/lib/protocols.c 2005-01-25 10:34:18.000000000 +0800
+++ gftp-2.0.18.patched/lib/protocols.c 2005-02-25 23:07:11.000000000 +0800
@@ -450,11 +450,16 @@
     {
       ret = g_convert_with_iconv (str, -1, request->iconv, &bread, &bwrite,
                                   &error);
-      if (ret == NULL)
-        printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
-                str, _("<unknown>"), "UTF-8", error->message);
-
-      return (ret);
+      if (ret == NULL) {
+//        printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
+//                str, _("<unknown>"), "UTF-8", error->message);
+        g_iconv_close (request->iconv);
+        request->iconv = NULL;
+        request->iconv_initialized = 0;
+      }
+      else {
+        return (ret);
+      }
     }

   gftp_lookup_request_option (request, "remote_charsets", &tempstr);
@@ -521,11 +526,16 @@
     {
       ret = g_convert_with_iconv (str, -1, request->iconv, &bread, &bwrite,
                                   &error);
-      if (ret == NULL)
-        printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
-                str, "UTF-8", _("<unknown>"), error->message);
-
-      return (ret);
+      if (ret == NULL) {
+//        printf (_("Error converting string '%s' from character set %s to character set %s: %s\n"),
+//                str, "UTF-8", _("<unknown>"), error->message);
+        g_iconv_close (request->iconv);
+        request->iconv = NULL;
+        request->iconv_initialized = 0;
+      }
+      else {
+        return (ret);
+      }
     }

   gftp_lookup_request_option (request, "remote_charsets", &tempstr);


patch 檔案在:
http://www.teatime.com.tw/~tommy/linux/gftp_remote_charsets.patch

給 sarge 用的 deb 在這兒:
http://www.teatime.com.tw/~tommy/debian/gftp_2.0.18-9_all.deb
http://www.teatime.com.tw/~tommy/debian/gftp-gtk_2.0.18-9_i386.deb
http://www.teatime.com.tw/~tommy/debian/gftp-common_2.0.18-9_i386.deb
http://www.teatime.com.tw/~tommy/debian/gftp-text_2.0.18-9_i386.deb

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #4 於: 2005-02-26 13:05 »
由於 gftp 內部在處理資料時, 似乎都轉成 utf-8 處理, 但是程式中這部份的邏輯似乎有點怪怪的, 除了在 remote_charsets 有設定時, 會把所有送出給 remote 的資料由 utf-8 再轉成所設定的編碼, 也會把由 remote 收到的資料由 remote_charsets 所設定的編碼轉成 utf-8 外, 對於 local (還有其他非 ftp 協定?), 也一直呼叫相同的函式來處理. (看不出有什麼判斷來決定那些要轉, 那些不用轉, 所以... 有些不該轉的也轉了... 有些該轉的, 又做了兩次轉換, 又轉回去原本的編碼)

原本打算把 gftp 修改成符合 rfc-2640.
1. 連線時送出 FEAT 指令, 判斷對方是否支援 rfc-2640. 也就是有 UTF8 feature.
2. 如果對於有支援 rfc-2640, 則不要使用 remote_charsets 的設定來轉碼. 應直接使用 utf-8.
3. 所有 local 端的檔名, 再由 utf-8 <-> local 之間互轉.

不過... 有些邏輯看了一上午, 實在看不太出來. 所以決定就用最簡單的改法. 就是假定 local 端一律使用 utf-8, 檔案儲存的時候, 如果檔名非 utf-8 就轉成 utf-8.

這個改法並非每個人都適用, 如果你的 locale 並沒設定為 utf-8, 應該會有問題.

至少, 這個改法, 符合我目前本身使用的需求. 可以正常看到中文檔名, 傳檔回來也是正常的 utf-8 中文檔名.

patch 與 deb 的檔名都沒改, 和上一篇的路徑相同, 直接抓就可以了.

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #5 於: 2005-02-26 18:02 »
修改一下 vsftpd, 以符合 rfc-2640 的需求. (如果我沒看錯的話)

新的 patch 可以到這兒抓
http://www.teatime.com.tw/~tommy/linux/vsftpd_iconv.patch

如果是使用 Debian Sarge, 也可以直接用這個:
http://www.teatime.com.tw/~tommy/debian/vsftpd_2.0.1-11_i386.deb

同之前的設定, 在把 enable_iconv 設為 yes, 且 remote_charset 設為 UTF-8 的時候, 會在 Clinet 使用 FEAT 指令時, 傳回 UTF8 表示支援檔名使用 UTF-8 編碼. (rfc-2640 好像就是要求 FEAT 有 UTF8, 且檔名都用 UTF-8 傳送)

另外, 我也改了一份 FileZilla 2.0.11 支援 rfc-2640 的版本. 麻煩測試一下.
http://www.teatime.com.tw/~tommy/FileZilla.zip

這個版本的 FileZilla 比較小, 因為沒支援 libidn.a (我還找不到 win32 的版本), 所以... domain name 不能用非英文的名字.
製造時, 我的 Visual Studio 2003 說無法載入 FzSFtp 的那個 project, 不過似乎還是可以使用 sftp.

與原本的版本差異除了上述 libidn.a 外, 就是在一開始連線時, 在送出 FEAT 指令後, 如果對方有回 UTF8, 在這之後, 就一律使用 UTF-8 來傳送檔名. 程式會將收到的檔名, 由 UTF-8 轉成 Windows 的 Unicode, 再轉成 ANSI CodePage (在繁體中文下就是 CP950), 在送出指令時, 會由 Windows 的 ANSI CodePage 轉成 Unicode 再轉成 UTF-8, 然後送出.
當然, 如果對方不支援 rfc-2640 的話, 也就應該不會有 UTF8 出現在 FEAT 中, 就不會做任何的轉換.

如果沒有問題的話, 這個 FileZilla 的相關 patch, 我整理一下再公開, 也會試著寄給 FileZilla 的作者.

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FileZilla 2.2.11 RFC-2640 Support
« 回覆 #6 於: 2005-02-27 22:07 »
昨天把 filezilla 的 patch 丟給作者去看, 結果, 因為我改的東西, 在 unicode 版本的編譯下頭會有問題... 我才發現... 原本 filezilla 有 unicode 版本?
那網站上頭抓到的執行檔是一般 ansi codepage 版本? 還是 unicode 版本呢?

我也不太清楚, 不過, 我發現我自己編的 unicode 版本, 就算沒有加上我的 patch, 也無法正常處理 big5 的中文. (由此看來, 似乎網站上頭那個執行檔不是 unicode 版本才對)

查了半天, 才發現原本作者在收到資料時, 是一個位元一個位元的方式, 由 ANSI 轉成  UNICODE, 這... 在沒有中文時, 當然是正常的, 有中文的話.... 一轉完... 中文也跟著完了, 反而變成亂碼.

所以改了比較大範圍的程式, 把這個轉換, 由一個位元改成一整行字串一起轉. 改了之後, 也的確可以看到中文了.

不過改好之後.... 發現我產生的 unicode 版本, 一執行..... 只要有中文出現, 隨時都可以 core dump.... 害我弄到今天下午才發現, 原本上頭顯示指令執行狀態的那個 list control 可能有問題, 因為... 後來發現不顯示就不會當. 才發現裡頭字串在顯示前又轉換一次, 但是 buffer 取得的大小有問題, 如果有中文可能就不夠大... 接著... 一複製就把 heap 給弄亂了. 造成後續整個程式變的很不穩定.

晚上測試了一下, 目前看來應該都沒有問題了. 剩下 unicode 版本... 到底能不能同時顯示多國文字, 我只有中文環境, 測不出來.
不過, 至少在中文下頭, 是沒有問題的.

這個壓縮檔案內有兩個執行檔. FileZillaA.exe 是 ansi codepage 版本, FileZilla.exe 是 unicode 版本.
兩個版本都有支援 RFC-2640. 在我的中文 XP 下頭使用, 都可以正常處理中文檔名.
http://www.teatime.com.tw/~tommy/FileZilla.zip

如果想自己編的, patch 在這兒:
http://www.teatime.com.tw/~tommy/filezilla_rfc2640.patch

這個 patch 剛剛有丟到 filezilla 的討論區給作者. 如果沒有問題, 希望下一個 2.2.x 的版本可以內建上去. (作者在開發 3.0 版.... 不知道會不會真的把這個功能放到 2.x 版上頭)

PS. 我還是沒做 IDN 的部份, 所以上頭那個執行檔, 都不能正常處理非英文的網域名.

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #7 於: 2005-02-28 15:24 »
今天再改了一下 gftp.

1. 如果 ftp server 使用 utf-8, 則不管 gftp 使用 big5 或 utf-8 都可以正常看到中文.
2. 如果 ftp server 使用 big5, 則在 remote_charsets 中有設定 big5 的話, 也可以正常看到中文.
3. 在指令的部份, dir 或 get 都可以輸入中文字當參數.
4. 不管 gftp 在什麼環境下執行, big5 or utf-8 or 其它, 所有 local 端的檔名, 都會使用 utf-8 處理.

也就是說, 如果你不是在 utf-8 的環境下頭的話, 最好不要用這個版本. 以免在 local 找不到 big5 的中文檔名, 抓回來的中文檔名也變成 utf-8 編碼.

我試過 gftp-text/gftp-gtk 兩個版本, 都可以正常使用. 只是有些傳送的訊息, 可能會出現 big5 碼, 會有轉碼失敗的錯誤訊息, 應該不會影響正常使用.

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #8 於: 2005-03-01 09:31 »
昨天 filezilla 的作者把我給他的 patch 放入 cvs 中了.
我今天早上抓 cvs 下來, 的確可以正常運作了.

還有一個小問題是在 unicode build 的版本上頭, 檔案列表還是會先由 utf-8 -> unicode -> ansi -> unicode. 可能有些多國語言的文字會轉失敗. 所以我今天早上給了作者另外一個小 patch 修正這個問題.

由於 patch 進入 cvs 了, 所以前頭那幾個 link 的檔案我就移除了, 有興趣的自己由 cvs 抓下來看.

我放了加上這些 patch 的執行檔如下, 如果你不在 unicode 的環境下頭, 可以使用 FileZillaA.exe 這一個, 如果在 unicode 下頭, 直接使用 FileZilla.exe 就可以.

這個 FileZilla.exe 應該可以正常處理多國語言. 也就是如果 server 支援 UTF-8, 上頭有多國的檔名, 應該都可以正常看到.

http://www.teatime.com.tw/~tommy/filezilla.zip

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #9 於: 2005-03-11 12:50 »
filezilla 2.2.12 released. 這個版本已經支援 RFC-2640 的 UTF8 功能.
官方網站的版本應該是 ansi 版本, 無法同時顯示多國文字.
如果需要 unicode 版本 (應該可以正常看到多國文字, 至少... 中文與日文是可以同時出現), 我編好一個放這兒:

http://www.teatime.com.tw/~tommy/filezilla.zip

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #10 於: 2005-03-12 11:02 »
update FileZilla to 2.2.12a.
這個版本應該和官方網站上的版本除了ansi 與 unicode 的差異外, 其它的都一樣.

http://www.teatime.com.tw/~tommy/filezilla.zip

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #11 於: 2005-03-12 23:22 »
修正 filezilla unicode 版本使用 sftp 時產生的 buffer overflow.

http://www.teatime.com.tw/~tommy/filezilla.zip

前面雖然有加上 winscp3 的 utf8 功能 (且 winscp3 的 sftp 速度的確遠快於 filezilla, 不過 fz 的作者卻說他自己試的速度都很快... :-(), 不過由於 winscp3 使用 bcb6 開發, 對於轉成 unicode 支援的版本有一定的困難度, 所以我打算直接修改 filezilla 的 sftp 部份, 讓它也能夠支援 utf-8 (其實是改好了, 不過... 還是無法做到多國文字同時支援), 這部份目前看起來會有比較大的異動, 留著有空再來慢慢測.

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #12 於: 2005-03-13 12:39 »
新增一個 use UTF-8 的選項. (在 site manager 的進階內)
如果這個選取這個選項, 則會認為所有遠端的檔案名稱都使用 UTF-8 編碼. (包含 ftp 與 sftp) 由於這個有異動到相關的語言檔, 所以如果你使用的語言的 .dll 沒有包含這個選項, 可能會無法開啟 "進階選項" 的對話視窗. 請使用有包含這個選項的語言檔, 或者切換到英文語言下面去設定.

我大略試了一下, 應該可以在 sftp 裡頭正常處理多國文字的檔案.

另外, 上頭的訊息列出現的檔案可能是 UTF-8 編碼, 看起來會像是亂碼, 不過運作上很正常.

這個 patch, 我整理一下再送給 fz 的作者看看, 不確定他是否會加上這個功能. (畢竟不是 RFC 內的東西...)

http://www.teatime.com.tw/~tommy/filezilla.zip

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #13 於: 2005-03-13 16:13 »
修正 ftp 下使用 utf-8 選項時, 若對方不支援 rfc-2640 時, 沒有正常轉換為 utf-8.
另外放上簡體與繁體中文的語言檔.

http://www.teatime.com.tw/~tommy/filezilla.zip

為了方便處理, patch 共有下面三個, 前兩個作者應該會接受. 至於 UTF-8 使用的那一個, 我就不清楚作者會怎麼處理了.
patch 都 submit 到 sourceforge 上頭了.

1. FileZilla 2.2.12a buffer overflow in unicode build
http://www.teatime.com.tw/~tommy/mypatch/filezilla_unicode.patch

2. FileZilla 2.2.12a FzSFtp.exe patch in unicode build
http://www.teatime.com.tw/~tommy/mypatch/filezilla_sftp_unicode.patch

3. FileZilla 2.2.12a Force UTF-8 encode for remote patch
http://www.teatime.com.tw/~tommy/mypatch/filezilla_utf8.patch

patch 的相關訊息可以參考 http://www.teatime.com.tw/~tommy/mypatch/

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #14 於: 2005-03-14 12:05 »
修改上狀態視窗顯示 utf-8 檔名的問題.
不過, 我發現這個視窗上頭不能顯示 unicode, 所以如果有其它國家的文字, 仍無法正常顯示

http://www.teatime.com.tw/~tommy/filezilla.zip

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #15 於: 2005-03-14 17:12 »
FileZilla 2.2.12a patch to enable unicode string display in status window:
http://www.teatime.com.tw/~tommy/mypatch/filezilla_unicode_status.patch

經過這個修正後, 可以在 Filezilla 上頭狀態視窗內正確的看到 unicode 的多國文字.
我想, 我對於 FileZilla 有關 UTF-8 與 unicode 的修正應該到此為止. 如果沒有什麼意外, 我應該不會再修改這個程式.

同樣, 執行檔放這兒:
http://www.teatime.com.tw/~tommy/filezilla.zip

如果要知道作者對這幾個 patch 有沒有興趣, 可以看一下 filezilla 討論區的這篇文章:
http://filezilla.sourceforge.net/forum/viewtopic.php?t=784

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #16 於: 2005-03-15 14:17 »
FileZilla 2.2.12b 出來了.
作者自己加上一個 force UTF8 的選項, 所以我的 patch 直接配合這個選項就可以了. 這個大幅縮小了 sftp 使用 UTF8 這個 patch 的大小.
前兩個 unicode 的 patch 應該已經進入 CVS 中了, 剩下下面三個:

修正 status window 無法顯示 unicode 的問題:
http://www.teatime.com.tw/~tommy/mypatch/filezilla_unicode_status.patch
http://sourceforge.net/tracker/index.php?func=detail&aid=1162835&group_id=21558&atid=372243

修正 2.2.12b 中, 如果使用 re-connect 連線, 並不會載入 UTF8 的選項:
http://www.teatime.com.tw/~tommy/mypatch/filezilla_utf8_reconnect.patch
http://sourceforge.net/tracker/index.php?func=detail&aid=1163450&group_id=21558&atid=372243

讓 sftp 也可以使用 UTF8:
http://www.teatime.com.tw/~tommy/mypatch/filezilla_sftp_utf8.patch
http://sourceforge.net/tracker/index.php?func=detail&aid=1163490&group_id=21558&atid=372243

這三個 patch 已經 submit 到 sourceforge.

至於加上上述 patch 的 unicode 版本為:
http://www.teatime.com.tw/~tommy/filezilla.zip

hyaloid

  • 可愛的小學生
  • *
  • 文章數: 2
    • 檢視個人資料
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #17 於: 2005-09-05 23:34 »
不好意思請問這個pacth如何使用呢
可以教我嗎 謝謝:)

hyaloid

  • 可愛的小學生
  • *
  • 文章數: 2
    • 檢視個人資料
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #18 於: 2005-09-05 23:37 »
引述: "hyaloid"
不好意思請問這個patch如何使用呢
可以教我嗎 謝謝:)


阿阿忘了說是vsftp的patch 不好意思^^:

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #19 於: 2005-09-07 09:11 »
引述: "hyaloid"
不好意思請問這個pacth如何使用呢
可以教我嗎 謝謝:)


man patch
到 google 打入 'how to apply patch' 找文章看.

cwinl

  • 可愛的小學生
  • *
  • 文章數: 12
    • 檢視個人資料
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #20 於: 2005-09-13 08:27 »
我的vsftpd的机器的locale为:
LANG=en_US
LC_CTYPE="en_US"
LC_NUMERIC="en_US"
LC_TIME="en_US"
LC_COLLATE="en_US"
LC_MONETARY="en_US"
LC_MESSAGES="en_US"
LC_PAPER="en_US"
LC_NAME="en_US"
LC_ADDRESS="en_US"
LC_TELEPHONE="en_US"
LC_MEASUREMENT="en_US"
LC_IDENTIFICATION="en_US"
LC_ALL=

我在看ps axf和/var/log/xferlog文件内容时
所有的中文的文件名字都是用??????表示的
我把locale改成zh_CN.GB2312后也还?????,不能显示中文

我想问一下
这个是不是您在这篇帖子里说的问题
解决的办法是不是打补丁就可以了呢?

另外,我从客户端看到的中文都没问题,是不是只让它能在xferlog中记录出中文就可以了呢?

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #21 於: 2006-07-06 12:56 »
由於 FileZilla 的作者對於某些 patch 有些堅持, 看起來似乎永遠不會接受該 patch, 所以我申請了一個新的 project, 把加上這一些在 FileZilla 與 FileZilla Server 的 patch 與所產生的執行檔, 放到這個專案上頭.

有需要的自己到這兒去找, 我會儘量在 FileZilla 有新版本的時候, 也順便更新上去.
http://sourceforge.net/projects/filezillapv

PS: 不知道這樣會不會違反或侵犯原有的授權 (因為我只是加上 patch 就 rebuild, 並沒有改名, 這部份有可能會侵犯 FileZilla 這個名稱...), 反正, 還沒被提出警告前,就先做了再說吧.

peter.c

  • 可愛的小學生
  • *
  • 文章數: 21
    • 檢視個人資料
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #22 於: 2006-08-01 15:13 »
請問

proftp該要怎麼修改呢??

謝謝

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5417
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #23 於: 2006-08-01 15:25 »
引述: "peter.c"
proftp該要怎麼修改呢??


第一篇有個 link 是 proftpd 的.
不過... 建議直接把 locale 改成 UTF-8, 然後 client 用支援 UTF-8 的軟體. 這樣子比較簡單.

huangjs

  • 可愛的小學生
  • *
  • 文章數: 1
    • 檢視個人資料
FTP Server/Client 在 UTF-8 下的解決方案
« 回覆 #24 於: 2007-01-10 21:16 »
引述: "twu2"
引述: "hyaloid"
不好意思請問這個pacth如何使用呢
可以教我嗎 謝謝:)


man patch
到 google 打入 'how to apply patch' 找文章看.


基本上就是patch -p0 < some.patch

-p數字 的選項是為了和patch內指定的檔名匹配之用

而patch是吃stdin的公用程式 所以要用導向符號

man一下應該不難嘍

 :D