chinson 寫:剛測試了一下, SmarfFTP支援 Unicode 檔名 "顯示" ,但是 Unicode 中文目錄進不去,換成 big5 檔名就沒問題.....
aadia 寫:ProFTPD - iconv() charset conversion patch
http://home.h01.itscom.net/para/softwar ... dex-e.html
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
enable_iconv=YES
local_charset=UTF-8
remote_charset=BIG5
twu2 寫:修改幾個會出問題的指令. 如: rmdir, dele, rename, size, chmod.
新的 patch 可以到這兒抓
http://www.teatime.com.tw/~tommy/linux/ ... conv.patch
如果是使用 Debian Sarge, 也可以直接用這個:
http://www.teatime.com.tw/~tommy/debian ... 0_i386.deb
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);
twu2 寫:gftp 的修改很簡單.
而且, 修改這個後, 就可以不用我之前加上的那個非標準的 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/ ... sets.patch
給 sarge 用的 deb 在這兒:
http://www.teatime.com.tw/~tommy/debian ... -1_all.deb
http://www.teatime.com.tw/~tommy/debian ... 1_i386.deb
http://www.teatime.com.tw/~tommy/debian ... 1_i386.deb
http://www.teatime.com.tw/~tommy/debian ... 1_i386.deb
正在瀏覽這個版面的使用者:沒有註冊會員 和 1 位訪客