Хм, где-то в декабре я тоже написал патч на vsftpd. Отличием является в основном то, что работает он через iconv, поэтому поддерживает все те перекодировки, что и iconv - и utf8 тоже.По поводу символа номера - надо иконву указывать не koi8 как локальную, а ISO-IR-111
Правда, в конфиг оно не смотрит... Кодировки задаются в builddefs.h при сборке
diff -Naurp vsftpd-2.0.1/Makefile vsftpd-2.0.1-iconv/Makefile
--- vsftpd-2.0.1/Makefile 2004-06-06 23:21:27.000000000 +0700
+++ vsftpd-2.0.1-iconv/Makefile 2004-12-03 14:30:57.000000000 +0600
@@ -14,7 +14,7 @@ OBJS = main.o utility.o prelogin.o ftpcm
banner.o filestr.o parseconf.o secutil.o \
ascii.o oneprocess.o twoprocess.o privops.o standalone.o hash.o \
tcpwrap.o ipv6parse.o access.o features.o readwrite.o \
- ssl.o sysutil.o sysdeputil.o
+ ssl.o sysutil.o sysdeputil.o recode.o
.c.o:
diff -Naurp vsftpd-2.0.1/builddefs.h vsftpd-2.0.1-iconv/builddefs.h
--- vsftpd-2.0.1/builddefs.h 2004-07-02 21:36:59.000000000 +0700
+++ vsftpd-2.0.1-iconv/builddefs.h 2004-12-03 14:39:34.000000000 +0600
@@ -4,6 +4,13 @@
#undef VSF_BUILD_TCPWRAPPERS
#define VSF_BUILD_PAM
#undef VSF_BUILD_SSL
+#define VSF_BUILD_ICONV
+
+#ifdef VSF_BUILD_ICONV
+/* Set up your codepages here */
+#define REMOTE_CODEPAGE "CP1251"
+#define LOCAL_CODEPAGE "KOI8R"
+#endif /* VSF_BUILD_ICONV */
#endif /* VSF_BUILDDEFS_H */
diff -Naurp vsftpd-2.0.1/ftpcmdio.c vsftpd-2.0.1-iconv/ftpcmdio.c
--- vsftpd-2.0.1/ftpcmdio.c 2004-07-02 18:23:02.000000000 +0700
+++ vsftpd-2.0.1-iconv/ftpcmdio.c 2004-12-03 14:30:57.000000000 +0600
@@ -198,6 +198,7 @@ control_getline(struct mystr* p_str, str
vsf_secbuf_alloc(&p_sess->p_control_line_buf, VSFTP_MAX_COMMAND_LINE);
}
ftp_getline(p_sess, p_str, p_sess->p_control_line_buf);
+
/* As mandated by the FTP specifications.. */
str_replace_char(p_str, '\0', '\n');
/* If the last character is a \r, strip it */
diff -Naurp vsftpd-2.0.1/ls.c vsftpd-2.0.1-iconv/ls.c
--- vsftpd-2.0.1/ls.c 2004-07-02 18:23:34.000000000 +0700
+++ vsftpd-2.0.1-iconv/ls.c 2004-12-03 14:30:57.000000000 +0600
@@ -197,9 +197,15 @@ vsf_ls_populate_dir_list(struct mystr_li
p_sort_str = &s_temp_str;
p_sort_subdir_str = &s_temp_str;
}
+#ifdef VSF_BUILD_ICONV
+ str_convert_out(&dirline_str);
+#endif /* VSF_BUILD_ICONV */
str_list_add(p_list, &dirline_str, p_sort_str);
if (p_subdir_list != 0 && vsf_sysutil_statbuf_is_dir(s_p_statbuf))
{
+#ifdef VSF_BUILD_ICONV
+ str_convert_out(&s_next_filename_str);
+#endif /* VSF_BUILD_ICONV */
str_list_add(p_subdir_list, &s_next_filename_str, p_sort_subdir_str);
}
}
diff -Naurp vsftpd-2.0.1/main.c vsftpd-2.0.1-iconv/main.c
--- vsftpd-2.0.1/main.c 2004-07-02 18:23:39.000000000 +0700
+++ vsftpd-2.0.1-iconv/main.c 2004-12-03 14:30:57.000000000 +0600
@@ -22,6 +22,7 @@
#include "tcpwrap.h"
#include "vsftpver.h"
#include "ssl.h"
+#include "postlogin.h"
/*
* Forward decls of helper functions
@@ -68,6 +69,20 @@ main(int argc, const char* argv[])
/* Zero or one argument supported. If one argument is passed, it is the
* path to the config file
*/
+
+#ifdef VSF_BUILD_ICONV
+ /* SETTING UP ICONV CONVERSIONS {By RandoMan}*/
+
+ iconv_out_d=iconv_open(REMOTE_CODEPAGE,LOCAL_CODEPAGE);
+ iconv_in_d=iconv_open(LOCAL_CODEPAGE,REMOTE_CODEPAGE);
+
+ if ((iconv_out_d == (iconv_t)-1) || (iconv_in_d == (iconv_t)-1))
+ {
+ die("Failed to set up iconv conversions");
+ }
+
+#endif /* VSF_BUILD_ICONV */
+
if (argc > 2)
{
die("vsftpd: too many arguments (I take an optional config file only)");
diff -Naurp vsftpd-2.0.1/postlogin.c vsftpd-2.0.1-iconv/postlogin.c
--- vsftpd-2.0.1/postlogin.c 2004-07-02 18:24:01.000000000 +0700
+++ vsftpd-2.0.1-iconv/postlogin.c 2004-12-03 14:30:57.000000000 +0600
@@ -26,6 +26,7 @@
#include "features.h"
#include "ssl.h"
#include "vsftpver.h"
+#include "builddefs.h"
/* Private local functions */
static void handle_pwd(struct vsf_session* p_sess);
@@ -79,6 +80,8 @@ static void resolve_tilde(struct mystr*
void
process_post_login(struct vsf_session* p_sess)
{
+
+
str_getcwd(&p_sess->home_str);
if (p_sess->is_anonymous)
{
@@ -95,6 +98,7 @@ process_post_login(struct vsf_session* p
vsf_sysutil_install_sighandler(kVSFSysUtilSigURG, handle_sigurg, p_sess);
vsf_sysutil_activate_sigurg(VSFTP_COMMAND_FD);
}
+
/* Handle any login message */
vsf_banner_dir_changed(p_sess, FTP_LOGINOK);
vsf_cmdio_write(p_sess, FTP_LOGINOK, "Login successful.");
@@ -108,6 +112,7 @@ process_post_login(struct vsf_session* p
/* Blocks */
vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
&p_sess->ftp_arg_str, 1);
+
if (tunable_setproctitle_enable)
{
struct mystr proctitle_str = INIT_MYSTR;
@@ -407,6 +412,11 @@ handle_pwd(struct vsf_session* p_sess)
static struct mystr s_cwd_buf_mangle_str;
static struct mystr s_pwd_res_str;
str_getcwd(&s_cwd_buf_mangle_str);
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_out(&s_cwd_buf_mangle_str);
+#endif /* VSF_BUILD_ICONV */
+
/* Double up any double-quotes in the pathname! */
str_replace_text(&s_cwd_buf_mangle_str, "\"", "\"\"");
/* Enclose pathname in quotes */
@@ -420,6 +430,11 @@ static void
handle_cwd(struct vsf_session* p_sess)
{
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
resolve_tilde(&p_sess->ftp_arg_str, p_sess);
if (!vsf_access_check_file(&p_sess->ftp_arg_str))
{
@@ -616,6 +631,11 @@ handle_retr(struct vsf_session* p_sess)
int remote_fd;
int opened_file;
int is_ascii = 0;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
filesize_t offset = p_sess->restart_pos;
p_sess->restart_pos = 0;
if (!data_transfer_checks_ok(p_sess))
@@ -719,6 +739,11 @@ handle_dir_common(struct vsf_session* p_
int use_control = 0;
str_empty(&s_option_str);
str_empty(&s_filter_str);
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
/* By default open the current directory */
str_alloc_text(&s_dir_name_str, ".");
if (!stat_cmd && !data_transfer_checks_ok(p_sess))
@@ -944,6 +969,11 @@ handle_upload_common(struct vsf_session*
int new_file_fd;
int remote_fd;
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
filesize_t offset = p_sess->restart_pos;
p_sess->restart_pos = 0;
if (!data_transfer_checks_ok(p_sess))
@@ -1053,6 +1083,11 @@ static void
handle_mkd(struct vsf_session* p_sess)
{
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
resolve_tilde(&p_sess->ftp_arg_str, p_sess);
vsf_log_start_entry(p_sess, kVSFLogEntryMkdir);
str_copy(&p_sess->log_str, &p_sess->ftp_arg_str);
@@ -1090,6 +1125,11 @@ static void
handle_rmd(struct vsf_session* p_sess)
{
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
resolve_tilde(&p_sess->ftp_arg_str, p_sess);
vsf_log_start_entry(p_sess, kVSFLogEntryRmdir);
str_copy(&p_sess->log_str, &p_sess->ftp_arg_str);
@@ -1117,6 +1157,11 @@ static void
handle_dele(struct vsf_session* p_sess)
{
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
resolve_tilde(&p_sess->ftp_arg_str, p_sess);
vsf_log_start_entry(p_sess, kVSFLogEntryDelete);
str_copy(&p_sess->log_str, &p_sess->ftp_arg_str);
@@ -1142,6 +1187,11 @@ static void
handle_rest(struct vsf_session* p_sess)
{
static struct mystr s_rest_str;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
filesize_t val = str_a_to_filesize_t(&p_sess->ftp_arg_str);
if (val < 0)
{
@@ -1159,6 +1209,11 @@ handle_rnfr(struct vsf_session* p_sess)
{
static struct vsf_sysutil_statbuf* p_statbuf;
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
/* Clear old value */
str_free(&p_sess->rnfr_filename_str);
resolve_tilde(&p_sess->ftp_arg_str, p_sess);
@@ -1192,6 +1247,11 @@ handle_rnto(struct vsf_session* p_sess)
{
static struct mystr s_tmp_str;
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
/* If we didn't get a RNFR, throw a wobbly */
if (str_isempty(&p_sess->rnfr_filename_str))
{
@@ -1351,6 +1411,11 @@ handle_size(struct vsf_session* p_sess)
*/
static struct vsf_sysutil_statbuf* s_p_statbuf;
int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
resolve_tilde(&p_sess->ftp_arg_str, p_sess);
if (!vsf_access_check_file(&p_sess->ftp_arg_str))
{
@@ -1375,6 +1440,11 @@ static void
handle_site(struct vsf_session* p_sess)
{
static struct mystr s_site_args_str;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
/* What SITE sub-command is it? */
str_split_char(&p_sess->ftp_arg_str, &s_site_args_str, ' ');
str_upper(&p_sess->ftp_arg_str);
@@ -1476,8 +1546,16 @@ handle_mdtm(struct vsf_session* p_sess)
static struct vsf_sysutil_statbuf* s_p_statbuf;
int do_write = 0;
long modtime = 0;
- struct str_locate_result loc = str_locate_char(&p_sess->ftp_arg_str, ' ');
- int retval = str_stat(&p_sess->ftp_arg_str, &s_p_statbuf);
+ struct str_locate_result loc;
+ int retval;
+
+#ifdef VSF_BUILD_ICONV
+ str_convert_in(&p_sess->ftp_arg_str);
+#endif /* VSF_BUILD_ICONV */
+
+ loc = str_locate_char(&p_sess->ftp_arg_str, ' ');
+ retval = str_stat(&p_sess->ftp_arg_str, &s_p_statbuf);
+
if (retval != 0 && loc.found &&
vsf_sysutil_isdigit(str_get_char_at(&p_sess->ftp_arg_str, 0)))
{
diff -Naurp vsftpd-2.0.1/postlogin.h vsftpd-2.0.1-iconv/postlogin.h
--- vsftpd-2.0.1/postlogin.h 2001-05-11 05:39:55.000000000 +0700
+++ vsftpd-2.0.1-iconv/postlogin.h 2004-12-03 14:30:57.000000000 +0600
@@ -12,4 +12,3 @@ struct vsf_session;
void process_post_login(struct vsf_session* p_sess);
#endif /* VSF_POSTLOGIN_H */
-
diff -Naurp vsftpd-2.0.1/recode.c vsftpd-2.0.1-iconv/recode.c
--- vsftpd-2.0.1/recode.c 1970-01-01 07:00:00.000000000 +0700
+++ vsftpd-2.0.1-iconv/recode.c 2004-12-03 14:41:36.000000000 +0600
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <errno.h>
+#include "recode.h"
+#include "sysutil.h"
+
+char *str_convert_encoding(const char *src, int src_len, iconv_t cd)
+{
+ char *result = NULL;
+ char *in_buf = src;
+ char *out_buf = NULL;
+ int res_len = 0;
+ int in_bytes_left = src_len;
+ int out_bytes_left = res_len;
+
+ int out_buf_pos;
+ iconv(cd,NULL,NULL,NULL,NULL);
+
+ while (in_bytes_left>0)
+ {
+ res_len+=ICONV_SIZE_INCREMENT_STEP;
+ out_bytes_left+=ICONV_SIZE_INCREMENT_STEP;
+
+ out_buf_pos=out_buf-result;
+ result=REALLOC(result,res_len);
+
+ if (result==NULL) { out_buf=NULL; break;}
+ out_buf=result+out_buf_pos;
+
+ if (iconv(cd,&in_buf,&in_bytes_left,&out_buf,&out_bytes_left) == (size_t)(-1))
+ {
+ if (errno!=E2BIG) break;
+ } else errno=0;
+
+ }
+ if (out_buf!=NULL) *out_buf=0;
+ return result;
+}
diff -Naurp vsftpd-2.0.1/recode.h vsftpd-2.0.1-iconv/recode.h
--- vsftpd-2.0.1/recode.h 1970-01-01 07:00:00.000000000 +0700
+++ vsftpd-2.0.1-iconv/recode.h 2004-12-03 14:35:41.000000000 +0600
@@ -0,0 +1,6 @@
+#include <iconv.h>
+
+#define ICONV_SIZE_INCREMENT_STEP 16
+#define REALLOC(x...) vsf_sysutil_realloc(x)
+
+char *str_convert_encoding(const char *src, int src_len, iconv_t cd);
diff -Naurp vsftpd-2.0.1/str.c vsftpd-2.0.1-iconv/str.c
--- vsftpd-2.0.1/str.c 2004-07-02 18:25:43.000000000 +0700
+++ vsftpd-2.0.1-iconv/str.c 2004-12-03 14:30:57.000000000 +0600
@@ -19,6 +19,55 @@
/* Ick. Its for die() */
#include "utility.h"
#include "sysutil.h"
+#include "builddefs.h"
+
+#ifdef VSF_BUILD_ICONV
+/* ICONV Conversions */
+
+#include "recode.h"
+#include <errno.h>
+#include <stdio.h>
+
+iconv_t iconv_out_d;
+iconv_t iconv_in_d;
+
+
+void str_convert(struct mystr* p_str, iconv_t conv_id)
+{
+ int src_len;
+ char *src;
+ char *dst;
+ struct mystr str_temp = INIT_MYSTR;
+
+ src_len = str_getlen(p_str);
+ if (src_len <= 0) return;
+
+ src=str_getbuf(p_str);
+
+ dst=str_convert_encoding(src,src_len,conv_id);
+ if (errno!=0)
+ {
+ if (dst!=NULL) vsf_sysutil_free(dst);
+ return;
+ }
+
+ str_alloc_text(&str_temp,dst);
+
+ str_copy(p_str,&str_temp);
+ str_free(&str_temp);
+ vsf_sysutil_free(dst);
+}
+
+void str_convert_out(struct mystr* p_str)
+{
+ str_convert(p_str,iconv_out_d);
+}
+void str_convert_in(struct mystr* p_str)
+{
+ str_convert(p_str,iconv_in_d);
+}
+
+#endif /* VSF_BUILD_ICONV */
/* File local functions */
static void str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
diff -Naurp vsftpd-2.0.1/str.h vsftpd-2.0.1-iconv/str.h
--- vsftpd-2.0.1/str.h 2004-06-04 23:35:00.000000000 +0700
+++ vsftpd-2.0.1-iconv/str.h 2004-12-03 14:30:57.000000000 +0600
@@ -7,6 +7,9 @@
#include "filesize.h"
#endif
+#include "builddefs.h"
+
+
struct mystr
{
char* PRIVATE_HANDS_OFF_p_buf;
@@ -15,6 +18,12 @@ struct mystr
unsigned int PRIVATE_HANDS_OFF_alloc_bytes;
};
+#ifdef VSF_BUILD_ICONV
+#include <iconv.h>
+extern iconv_t iconv_out_d;
+extern iconv_t iconv_in_d;
+#endif /* VSF_BUILD_ICONV */
+
#define INIT_MYSTR \
{ (void*)0, 0, 0 }
@@ -24,6 +33,9 @@ struct mystr
void private_str_alloc_memchunk(struct mystr* p_str, const char* p_src,
unsigned int len);
+void str_convert_out(struct mystr* p_str);
+void str_convert_in(struct mystr* p_str);
+
void str_alloc_text(struct mystr* p_str, const char* p_src);
/* NOTE: String buffer data does NOT include terminating character */
void str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term);