029ah Posted November 16, 2004 Posted November 16, 2004 все файлы у нас на серваке в UTF-8, а хотелось получить в FTP-клиенте CP1251. Пропатчил vsftpd-2.0.1, использовав iconv. в main.c строки #define INSIDE_CHARSET "UTF-8" #define OUTSIDE_CHARSET "CP1251" задают внутреннюю и внешнюю кодировки. Патч: vsftpd-2.0.1-convertable.diff diff -uNr vsftpd-2.0.1/ftpcmdio.c vsftpd-2.0.1-convertable/ftpcmdio.c --- vsftpd-2.0.1/ftpcmdio.c 2004-07-02 15:23:02.000000000 +0400 +++ vsftpd-2.0.1-convertable/ftpcmdio.c 2004-11-16 15:47:19.000000000 +0300 @@ -200,6 +200,7 @@ 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'); + str_iconv(p_str, 1); /* If the last character is a r, strip it */ { unsigned int len = str_getlen(p_str); diff -uNr vsftpd-2.0.1/main.c vsftpd-2.0.1-convertable/main.c --- vsftpd-2.0.1/main.c 2004-07-02 15:23:39.000000000 +0400 +++ vsftpd-2.0.1-convertable/main.c 2004-11-16 15:33:14.000000000 +0300 @@ -5,6 +5,10 @@ * main.c */ +#include <iconv.h> +#include <string.h> +#include <errno.h> + #include "session.h" #include "utility.h" #include "tunables.h" @@ -31,6 +35,10 @@ static void session_init(struct vsf_session* p_sess); static void env_init(void); +#define INSIDE_CHARSET "UTF-8" +#define OUTSIDE_CHARSET "CP1251" +iconv_t cd_inside, cd_outside; + int main(int argc, const char* argv[]) { @@ -68,6 +76,12 @@ /* Zero or one argument supported. If one argument is passed, it is the * path to the config file */ + + cd_inside = iconv_open(INSIDE_CHARSET, OUTSIDE_CHARSET); + if (cd_inside == (iconv_t)(-1)) die(strerror(errno)); + cd_outside = iconv_open(OUTSIDE_CHARSET, INSIDE_CHARSET); + if (cd_outside == (iconv_t)(-1)) die(strerror(errno)); + if (argc > 2) { die("vsftpd: too many arguments (I take an optional config file only)"); diff -uNr vsftpd-2.0.1/str.c vsftpd-2.0.1-convertable/str.c --- vsftpd-2.0.1/str.c 2004-07-02 15:25:43.000000000 +0400 +++ vsftpd-2.0.1-convertable/str.c 2004-11-16 15:56:33.000000000 +0300 @@ -660,3 +660,24 @@ } } +void +str_iconv(struct mystr* p_str, int direction) +{ + char tmp[MAX_ICONV_STRING+1], *to_buf, *from_buf; + size_t sz_from, sz_to, nconv; + + from_buf = (char*)str_strdup(p_str); + to_buf = tmp; + sz_from = str_getlen(p_str)+1; + if (sz_from>MAX_ICONV_STRING) return; + sz_to = MAX_ICONV_STRING; + if (direction) { + nconv = iconv(cd_inside, &from_buf, &sz_from, &to_buf, &sz_to); + nconv = iconv(cd_inside, NULL, NULL, NULL, NULL); + } else { + nconv = iconv(cd_outside, &from_buf, &sz_from, &to_buf, &sz_to); + nconv = iconv(cd_inside, NULL, NULL, NULL, NULL); + } + str_empty(p_str); + str_append_text(p_str, tmp); +} diff -uNr vsftpd-2.0.1/str.h vsftpd-2.0.1-convertable/str.h --- vsftpd-2.0.1/str.h 2004-06-04 20:35:00.000000000 +0400 +++ vsftpd-2.0.1-convertable/str.h 2004-11-16 15:52:48.000000000 +0300 @@ -1,12 +1,19 @@ #ifndef VSFTP_STR_H #define VSFTP_STR_H +#include <iconv.h> +#include <string.h> +#include "sysstr.h" +#define MAX_ICONV_STRING 2048 + /* TODO - document these functions;-) */ #ifndef VSF_FILESIZE_H #include "filesize.h" #endif +extern iconv_t cd_inside, cd_outside; + struct mystr { char* PRIVATE_HANDS_OFF_p_buf; @@ -120,5 +127,7 @@ int str_contains_line(const struct mystr* p_str, const struct mystr* p_line_str); +void str_iconv(struct mystr* p_str, int direction); // direction: 1 - inside, 0 - outside + #endif /* VSFTP_STR_H */ diff -uNr vsftpd-2.0.1/strlist.c vsftpd-2.0.1-convertable/strlist.c --- vsftpd-2.0.1/strlist.c 2004-07-02 15:25:48.000000000 +0400 +++ vsftpd-2.0.1-convertable/strlist.c 2004-11-16 15:39:25.000000000 +0300 @@ -92,6 +92,7 @@ p_node = &p_list->p_nodes[p_list->list_len]; p_node->str = s_null_str; p_node->sort_key_str = s_null_str; + str_iconv(p_str, 0); str_copy(&p_node->str, p_str); if (p_sort_key_str) { патч применяется как всегда: cd vsftpd-2.0.1 patch -p1 < ../vsftpd-2.0.1-convertable.diff [/code] Вставить ник Quote
029ah Posted March 13, 2005 Author Posted March 13, 2005 я его немного проапгрейдил - в командной строке можно указывать внутреннюю, внешнюю кодировки, и порт, на котором слушать. плюс, видимо, вышел новый релиз под версией 2.0.1, и предыдущий патч на ней не срабатывал. новый патч: diff -rc vsftpd-2.0.1/ftpcmdio.c vsftpd-2.0.1-convertable-r2/ftpcmdio.c *** vsftpd-2.0.1/ftpcmdio.c 2004-07-02 15:23:02.000000000 +0400 --- vsftpd-2.0.1-convertable-r2/ftpcmdio.c 2005-02-01 01:17:17.000000000 +0300 *************** *** 200,205 **** --- 200,206 ---- 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 (iconv_enabled) str_iconv(p_str, 1); /* If the last character is a r, strip it */ { unsigned int len = str_getlen(p_str); diff -rc vsftpd-2.0.1/ftpcmdio.h vsftpd-2.0.1-convertable-r2/ftpcmdio.h *** vsftpd-2.0.1/ftpcmdio.h 2003-09-10 03:11:01.000000000 +0400 --- vsftpd-2.0.1-convertable-r2/ftpcmdio.h 2005-02-01 01:17:00.000000000 +0300 *************** *** 1,6 **** --- 1,8 ---- #ifndef VSF_FTPCMDIO_H #define VSF_FTPCMDIO_H + extern int iconv_enabled; + struct mystr; struct vsf_session; diff -rc vsftpd-2.0.1/main.c vsftpd-2.0.1-convertable-r2/main.c *** vsftpd-2.0.1/main.c 2004-07-02 15:23:39.000000000 +0400 --- vsftpd-2.0.1-convertable-r2/main.c 2005-02-01 01:33:46.000000000 +0300 *************** *** 5,10 **** --- 5,15 ---- * main.c */ + #include <iconv.h> + #include <stdlib.h> + #include <string.h> + #include <errno.h> + #include "session.h" #include "utility.h" #include "tunables.h" *************** *** 31,36 **** --- 36,46 ---- static void session_init(struct vsf_session* p_sess); static void env_init(void); + #define INSIDE_CHARSET "UTF-8" + #define OUTSIDE_CHARSET "WINDOWS-1251" + iconv_t cd_inside, cd_outside; + int iconv_enabled=0; + int main(int argc, const char* argv[]) { *************** *** 68,82 **** /* Zero or one argument supported. If one argument is passed, it is the * path to the config file */ ! if (argc > 2) { ! die("vsftpd: too many arguments (I take an optional config file only)"); } else if (argc == 0) { die("vsftpd: missing argv[0]"); } ! if (argc == 2) { if (!vsf_sysutil_strcmp(argv[1], "-v")) { --- 78,93 ---- /* Zero or one argument supported. If one argument is passed, it is the * path to the config file */ ! ! if (argc > 5 || argc == 3) { ! die("vsftpd: incorrect arguments (usage: vsftpd /path/to/config [inside_charset outside_charset [listen_port]]"); } else if (argc == 0) { die("vsftpd: missing argv[0]"); } ! if (argc >= 2) { if (!vsf_sysutil_strcmp(argv[1], "-v")) { *************** *** 85,90 **** --- 96,112 ---- p_config_name = argv[1]; config_specified = 1; } + if (argc >= 4) { + cd_inside = iconv_open(argv[2], argv[3]); + if (cd_inside == (iconv_t)(-1)) die(strerror(errno)); + cd_outside = iconv_open(argv[3], argv[2]); + if (cd_outside == (iconv_t)(-1)) die(strerror(errno)); + iconv_enabled = 1; + } + if (argc == 5) { + tunable_listen_port = atoi(argv[4]); + } + /* This might need to open /dev/zero on systems lacking MAP_ANON. Needs * to be done early (i.e. before config file parse, which may use * anonymous pages diff -rc vsftpd-2.0.1/str.c vsftpd-2.0.1-convertable-r2/str.c *** vsftpd-2.0.1/str.c 2004-07-02 15:25:43.000000000 +0400 --- vsftpd-2.0.1-convertable-r2/str.c 2005-02-01 01:09:16.000000000 +0300 *************** *** 660,662 **** --- 660,683 ---- } } + void + str_iconv(struct mystr* p_str, int direction) + { + char tmp[MAX_ICONV_STRING+1], *to_buf, *from_buf; + size_t sz_from, sz_to, nconv; + + from_buf = (char*)str_strdup(p_str); + to_buf = tmp; + sz_from = str_getlen(p_str)+1; + if (sz_from>MAX_ICONV_STRING) return; + sz_to = MAX_ICONV_STRING; + if (direction) { + nconv = iconv(cd_inside, &from_buf, &sz_from, &to_buf, &sz_to); + nconv = iconv(cd_inside, NULL, NULL, NULL, NULL); + } else { + nconv = iconv(cd_outside, &from_buf, &sz_from, &to_buf, &sz_to); + nconv = iconv(cd_inside, NULL, NULL, NULL, NULL); + } + str_empty(p_str); + str_append_text(p_str, tmp); + } diff -rc vsftpd-2.0.1/str.h vsftpd-2.0.1-convertable-r2/str.h *** vsftpd-2.0.1/str.h 2004-06-04 20:35:00.000000000 +0400 --- vsftpd-2.0.1-convertable-r2/str.h 2005-02-01 01:09:16.000000000 +0300 *************** *** 1,12 **** --- 1,19 ---- #ifndef VSFTP_STR_H #define VSFTP_STR_H + #include <iconv.h> + #include <string.h> + #include "sysstr.h" + #define MAX_ICONV_STRING 2048 + /* TODO - document these functions;-) */ #ifndef VSF_FILESIZE_H #include "filesize.h" #endif + extern iconv_t cd_inside, cd_outside; + struct mystr { char* PRIVATE_HANDS_OFF_p_buf; *************** *** 120,124 **** --- 127,133 ---- int str_contains_line(const struct mystr* p_str, const struct mystr* p_line_str); + void str_iconv(struct mystr* p_str, int direction); // direction: 1 - inside, 0 - outside + #endif /* VSFTP_STR_H */ diff -rc vsftpd-2.0.1/strlist.c vsftpd-2.0.1-convertable-r2/strlist.c *** vsftpd-2.0.1/strlist.c 2004-07-02 15:25:48.000000000 +0400 --- vsftpd-2.0.1-convertable-r2/strlist.c 2005-02-01 01:21:12.000000000 +0300 *************** *** 92,97 **** --- 92,98 ---- p_node = &p_list->p_nodes[p_list->list_len]; p_node->str = s_null_str; p_node->sort_key_str = s_null_str; + if (iconv_enabled) str_iconv((struct mystr*)p_str, 0); str_copy(&p_node->str, p_str); if (p_sort_key_str) { diff -rc vsftpd-2.0.1/strlist.h vsftpd-2.0.1-convertable-r2/strlist.h *** vsftpd-2.0.1/strlist.h 2002-07-14 22:27:03.000000000 +0400 --- vsftpd-2.0.1-convertable-r2/strlist.h 2005-02-01 01:17:58.000000000 +0300 *************** *** 1,6 **** --- 1,8 ---- #ifndef VSF_STRLIST_H #define VSF_STRLIST_H + extern int iconv_enabled; + /* Forward declarations */ struct mystr; struct mystr_list_node; запускать можно так: # /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf UTF-8 WINDOWS-1251 # /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf UTF-8 UTF-8 2121 # /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf UTF-8 KOI8-R 2122 Вставить ник Quote
Guest Posted March 14, 2005 Posted March 14, 2005 # /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf UTF-8 WINDOWS-1251# /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf UTF-8 UTF-8 2121 # /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf UTF-8 KOI8-R 2122 всё это конечно хорошо, но не у всех локально utf-8. лучше вынести это дело в конфиг. ну и конечно добится добавления патча на официальном уровне. Вставить ник Quote
029ah Posted March 15, 2005 Author Posted March 15, 2005 мой патч основан на iconv, так что можно перекодировать хоть из WINDOWS-1251 в CP866, UTF-8 я привел для примера. в конфиг выносить не хочу - хочется запускать несколько vsftpd с указанием одного конфига и разных кодировок и портов. официально думаю не получится - решение не очень красивое, и с безопасностью теоретически могут возникнуть проблемы. у них для работы со строками только свои функции используются, а тут какая-то внешняя библиотека.. Вставить ник Quote
sirmax Posted March 15, 2005 Posted March 15, 2005 замечательно нужная вещь спасибо но ИМХО дейстаительно лучше в конфиг... как у самбы Вставить ник Quote
Guest Posted March 16, 2005 Posted March 16, 2005 официально думаю не получится - решение не очень красивое, и с безопасностью теоретически могут возникнуть проблемы. у них для работы со строками только свои функции используются, а тут какая-то внешняя библиотека.. а как быть с другими версиями (у меня 1.2.2) ? ну и раз уже взялся делать патчи выкладывай их гденибудь. а то на форуме както несеръёзно. Вставить ник Quote
029ah Posted March 17, 2005 Author Posted March 17, 2005 с другими версиями - нет времени, тем более на предыдущие... +( с патчем - подумаю, пока нет стабильного места, где выложить... Вставить ник Quote
Guest Posted March 17, 2005 Posted March 17, 2005 с другими версиями - нет времени, тем более на предыдущие... +(с патчем - подумаю, пока нет стабильного места, где выложить... 1.2.2 это не предидущая а стабильная ветка. Вставить ник Quote
Guest Posted November 30, 2005 Posted November 30, 2005 Есть патчик для 2.0.3 не использующий iconv. Поддержка перекодирования в разрезе сессий. Вставить ник Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.