Ключевые слова:patch, ftp, charset, decode, (найти похожие документы)
From: Александр Ямшанов <kukazuka mail.ru>
Newsgroups: email
Date: Mon, 9 Mar 2005 14:31:37 +0000 (UTC)
Subject: Патч для изменения кодировки на лету ftp-сервером vsftpd
Изменение кодировки на лету ftp-сервером.
Думаю, что часто возникает проблема, что когда windows-пользователи закачивают
на unix-сервер файлы через ftp, т.к. в консоли они тогда отображаются
иероглифами. Так допустим, если отправить файл "Привет всем.txt", то в
файловой системе создастся файл "оПХБЕР БЯЕЛ.txt". Хотя, если смотреть через
ftp-сервер, то все отображается нормально. На примере одного-двух файлов на
подобные мелочи можно и не обращать внимания, но в масштабах большого
файлового сервера на это рано или поздно придется обратить внимания.
До последнего времени в качестве ftp-сервера использовался proftpd. В качестве
временного решения проблемы можно использовать Far, он умеет своими силами
менять кодировку. Для proftpd существует патч, чтобы его научить менять
кодировку (см. http://home.h01.itscom.net/para/software/misc/proftpd-iconv/index-e.html),
но даже после пропатчивания сервера остается проблема буквы "я". Допустим,
если залить на сервер файл "Кляп.txt", то запишется файл "Кл.txt", т.е.
пропадет сама буква "я" и буква, которая шла следом.
В ftp-сервере vsftpd проблемы буквы "я", как оказалось, не существует. Но
никакого патча найти не удалось. Пришлось написать самому (патч см. ниже).
Проблем с ним пока не заметил. Работает так, как и хотелось бы. Он не такой
универсальный, как для proftpd, но для меня в данном случае не это было
главным. Буду рад комментариям.
Альтернативное решение - патч от Andrey V. Elsukov для перекодировки имен файлов
FTP клиентом Midnight Commander: ftp://ftp.opennet.ru/pub/sys/shell/mc-rus-vfs/
# cat vsftpd-2.0.1-koi2win.patch
diff -urN vsftpd-2.0.1.old/ftpcmdio.c vsftpd-2.0.1/ftpcmdio.c
--- vsftpd-2.0.1/ftpcmdio.c.orig Fri Jul 2 18:23:02 2004
+++ vsftpd-2.0.1/ftpcmdio.c Sun Feb 27 21:42:08 2005
@@ -198,6 +198,7 @@
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);
+ str_win2koi(p_str);
/* As mandated by the FTP specifications.. */
str_replace_char(p_str, '\0', '\n');
/* If the last character is a \r, strip it */
diff -urN vsftpd-2.0.1/ls.c.orig vsftpd-2.0.1/ls.c
--- vsftpd-2.0.1.old/ls.c Fri Jul 2 18:23:34 2004
+++ vsftpd-2.0.1/ls.c Sun Feb 27 21:42:08 2005
@@ -432,6 +432,7 @@
tunable_use_localtime));
str_append_char(p_str, ' ');
/* Filename */
+ str_koi2win(p_filename_str);
str_append_str(p_str, p_filename_str);
str_append_text(p_str, "\r\n");
}
diff -urN vsftpd-2.0.1.old/str.c vsftpd-2.0.1/str.c
--- vsftpd-2.0.1/str.c.orig Fri Jul 2 18:25:43 2004
+++ vsftpd-2.0.1/str.c Sun Feb 27 21:42:08 2005
@@ -660,3 +660,46 @@
}
}
+void
+str_win2koi(struct mystr* p_str)
+{
+ int i;
+ char wk[] = {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,179,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,163,185,186,187,188,189,190,191,
+ 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240,
+ 242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241,
+ 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208,
+ 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209};
+
+ for(i = 0; i < p_str->len; i++)
+ {
+ if(p_str->p_buf[i] & 0200)
+ {
+ p_str->p_buf[i] = wk[p_str->p_buf[i] & 0177];
+ }
+ }
+}
+
+void
+str_koi2win(struct mystr* p_str)
+{
+ int i;
+ char kw[] = {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,184,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,168,180,181,182,183,184,185,186,187,188,189,190,191,
+ 254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238,
+ 239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250,
+ 222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206,
+ 207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218};
+
+ for(i = 0; i < p_str->len; i++)
+ {
+ if(p_str->p_buf[i] & 0200)
+ {
+ p_str->p_buf[i] = kw[p_str->p_buf[i] & 0177];
+ }
+ }
+}
diff -urN vsftpd-2.0.1.old/str.h vsftpd-2.0.1/str.h
--- vsftpd-2.0.1/str.h.orig Fri Jun 4 23:35:00 2004
+++ vsftpd-2.0.1/str.h Sun Feb 27 21:42:08 2005
@@ -120,5 +120,8 @@
int str_contains_line(const struct mystr* p_str,
const struct mystr* p_line_str);
+void win2koi(struct mystr* p_str); // Recode WIN to KOI;
+void koi2win(struct mystr* p_str); // Recode KOI to WIN;
+
#endif /* VSFTP_STR_H */
есть допутим 2 ситуации: на линух заходит линух и на линух заходит мастдай, то в перврмслучае будет правильно выдана koi8-r->koi8-r а во втором koi8-r->cp1251 ? тоесть для линух клиентов ничё не изменится? всё и будет ок?
>я сделал по другому - vsftpd в параметрах командной строки принимает входящую,
>исходящую кодировки (используется iconv), и порт, на котором слушать.
>
>если интесно - могу запостить.
насколько я помню в случае с перекодировкой с использованием iconv наблюдается тоже ряд глюков, в частности с символом номера в русской расскладке и рядом украинских литер.
RandoMan, какие действия необходимо проделать, чтобы я у себя на компьютере смог получить подобный результати и убедиться, что перекодировка не осуществляется? Возможно я что-то пропустил, когда правил. ;-)
---
Так, допустим, если создать через Windows Explorer создать папку "Новая папка", а в ней ещё одну "Новая папка", то затем их не удается удалить, Explorer говорит: "550 Failed to change directory.". Как показал tcpdump от Windows Explorer приходит команда для каталога "Новаяя папка", так что, как мне кажется, здесь виноват не сервер, а клиент. FAR в данном случае справляется без проблем.
Так как видимо подобная проблема не только меня беспокоит, то думаю в скором времени немного перепишу патч, сделав так, что перекодировка будет осуществляться средствами iconv, а названия кодировок будут помещаться в конфиг. Соответсвенно это будет более универсально, а во-вторых, можно будет запуская несколько ftp-серверов на разных портах обеспечить нормальную работу для различных клиентов, таких как dos, unix, windows, mac...
Так что, если замечены ещё какие-нибудь глюки, прошу сообщать, пока не поздно. ;-)
>RandoMan, какие действия необходимо проделать, чтобы я у себя на компьютере смог
>получить подобный результати и убедиться, что перекодировка не осуществляется? Возможно я
>что-то пропустил, когда правил. ;-)
Ну фар может быть не использует pwd. А totalcmd использует.
попробуй консольным ftp-клиентом
Там видно...
ЗЫ: тупо взял сорсы vsftpd, твой патч, и получил указанный мной результат :)
c proftpd вроде как тоже можно, по крайней мере у мена все прекрасно работает.
1) Чтоб побороть "Я" в кодиpовке 1251?
netio.c ищем код вида:
switch (mode) {
case IAC:
вырезаем этот switch целиком.
и готово
У меня так работает, причем уже давно.
точно. Без всяких патчей, здорово!
Если сервер юниксовый, а пользователи только виндовозные - лучший вариант помоему.
Такая вырезка кода безопасности не вредит?
Добавлена поддержка полной перекодировки для Кириллицы между UTF-8, Win-1251, Koi8-R, IBM866 и ISO-8859-5 (необходимо определить VSFTP_CHARCONV_SUPPORT_CYRILLIC в charconv.h).
Исправлены ответы на команды похожие на PWD (проблема перекодировки).
Добавлена поддержка перекодирования русских символов между UTF-8, Win-1251, Koi8-R без использования модуля iconv для каждой сессии. Для использования данной функции необходимо в файл настройки vsftpd.conf добавить строки: convert_charset_enable=1,local_charset=CP, remote_charset=CP. CP может принимать следующие значения: UTF8, WIN1251 or KOI8R.
Добавлена поддержка команда OPTS с аргументами UTF8 (значения ON или OFF) и CP (значения UTF8, WIN1251 или KOI8R).
Добавлена информация о режиме работы конвертора символов в ответе на команду STAT.