Index: charconv.c
===================================================================
--- charconv.c (revision 0)
+++ charconv.c (revision 140)
@@ -0,0 +1,460 @@
+/*
+ * Part of Very Secure FTPd
+ * Licence: GPL v2
+ * Author: Dmitriy Balashov
+ * charconv.c
+ */
+
+#include "charconv.h"
+#include "tunables.h"
+#include "session.h"
+#include "str.h"
+#include "sysutil.h"
+
+#include "char_maps/utf8.map"
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+#include "char_maps/cyrillic.map"
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+#include "char_maps/western.map"
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+#include "char_maps/central.map"
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+#include "char_maps/soutern.map"
+#endif
+
+/* Tables mapping supported codepage names to runtime variables */
+static struct available_charsets
+{
+ const char* p_charset_name;
+ int p_variable;
+}
+available_charsets_array[] =
+{
+ { VSFTP_CP_NONE , VSFTP_C_NONE },
+ // Cyrillic
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+ { VSFTP_CP_UTF_8 , VSFTP_C_UTF8 },
+ { VSFTP_CP_UTF8 , VSFTP_C_UTF8 },
+ { VSFTP_CP_WIN_1251 , VSFTP_C_1251 },
+ { VSFTP_CP_WIN1251 , VSFTP_C_1251 },
+ { VSFTP_CP_CP1251 , VSFTP_C_1251 },
+ { VSFTP_CP_1251 , VSFTP_C_1251 },
+ { VSFTP_CP_KOI8_R , VSFTP_C_878R },
+ { VSFTP_CP_KOI8R , VSFTP_C_878R },
+ { VSFTP_CP_CP878 , VSFTP_C_878R },
+ { VSFTP_CP_878 , VSFTP_C_878R },
+ { VSFTP_CP_CP878R , VSFTP_C_878R },
+ { VSFTP_CP_878R , VSFTP_C_878R },
+ { VSFTP_CP_KOI8_U , VSFTP_C_878U },
+ { VSFTP_CP_KOI8U , VSFTP_C_878U },
+ { VSFTP_CP_CP878U , VSFTP_C_878U },
+ { VSFTP_CP_878U , VSFTP_C_878U },
+ { VSFTP_CP_IBM866 , VSFTP_C_866 },
+ { VSFTP_CP_CP866 , VSFTP_C_866 },
+ { VSFTP_CP_866 , VSFTP_C_866 },
+ { VSFTP_CP_ISO8859_5 , VSFTP_C_ISO5 },
+ { VSFTP_CP_ISO5 , VSFTP_C_ISO5 },
+#endif
+ // Western European
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+ { VSFTP_CP_ISO8859_1 , VSFTP_C_ISO1 },
+ { VSFTP_CP_ISO1 , VSFTP_C_ISO1 },
+ { VSFTP_CP_LATIN1 , VSFTP_C_ISO1 },
+ { VSFTP_CP_ISO8859_15, VSFTP_C_ISO15 },
+ { VSFTP_CP_ISO15 , VSFTP_C_ISO15 },
+ { VSFTP_CP_LATIN9 , VSFTP_C_ISO15 },
+ { VSFTP_CP_WIN_1252 , VSFTP_C_1252 },
+ { VSFTP_CP_WIN1252 , VSFTP_C_1252 },
+ { VSFTP_CP_CP1252 , VSFTP_C_1252 },
+ { VSFTP_CP_1252 , VSFTP_C_1252 },
+#endif
+ // Central European
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+ { VSFTP_CP_ISO8859_2 , VSFTP_C_ISO2 },
+ { VSFTP_CP_ISO2 , VSFTP_C_ISO2 },
+ { VSFTP_CP_LATIN2 , VSFTP_C_ISO2 },
+ { VSFTP_CP_ISO8859_16, VSFTP_C_ISO16 },
+ { VSFTP_CP_ISO16 , VSFTP_C_ISO16 },
+ { VSFTP_CP_WIN_1250 , VSFTP_C_1250 },
+ { VSFTP_CP_WIN1250 , VSFTP_C_1250 },
+ { VSFTP_CP_CP1250 , VSFTP_C_1250 },
+ { VSFTP_CP_1250 , VSFTP_C_1250 },
+#endif
+ // Soutern European
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+ { VSFTP_CP_ISO8859_3 , VSFTP_C_ISO3 },
+ { VSFTP_CP_ISO3 , VSFTP_C_ISO3 },
+ { VSFTP_CP_LATIN3 , VSFTP_C_ISO3 },
+#endif
+ { 0, 0 }
+};
+
+/* Available convertions */
+static struct available_convertions
+{
+ int local;
+ int remote;
+ int localCharset;
+ int remoteCharset;
+}
+available_convertions_array[] =
+{ // Cyrillic
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+ { VSFTP_C_UTF8 , VSFTP_C_1251 , VSFTP_CS_UTF8CYR , VSFTP_CS_1251 },
+ { VSFTP_C_UTF8 , VSFTP_C_878R , VSFTP_CS_UTF8CYR , VSFTP_CS_878R },
+ { VSFTP_C_UTF8 , VSFTP_C_878U , VSFTP_CS_UTF8CYR , VSFTP_CS_878U },
+ { VSFTP_C_UTF8 , VSFTP_C_866 , VSFTP_CS_UTF8CYR , VSFTP_CS_866 },
+ { VSFTP_C_UTF8 , VSFTP_C_ISO5 , VSFTP_CS_UTF8CYR , VSFTP_CS_ISO5 },
+ { VSFTP_C_1251 , VSFTP_C_UTF8 , VSFTP_CS_1251 , VSFTP_CS_UTF8CYR },
+ { VSFTP_C_1251 , VSFTP_C_878R , VSFTP_CS_1251 , VSFTP_CS_878R },
+ { VSFTP_C_1251 , VSFTP_C_878U , VSFTP_CS_1251 , VSFTP_CS_878U },
+ { VSFTP_C_1251 , VSFTP_C_866 , VSFTP_CS_1251 , VSFTP_CS_866 },
+ { VSFTP_C_1251 , VSFTP_C_ISO5 , VSFTP_CS_1251 , VSFTP_CS_ISO5 },
+ { VSFTP_C_878R , VSFTP_C_UTF8 , VSFTP_CS_878R , VSFTP_CS_UTF8CYR },
+ { VSFTP_C_878R , VSFTP_C_1251 , VSFTP_CS_878R , VSFTP_CS_1251 },
+ { VSFTP_C_878R , VSFTP_C_878U , VSFTP_CS_878R , VSFTP_CS_878U },
+ { VSFTP_C_878R , VSFTP_C_866 , VSFTP_CS_878R , VSFTP_CS_866 },
+ { VSFTP_C_878R , VSFTP_C_ISO5 , VSFTP_CS_878R , VSFTP_CS_ISO5 },
+ { VSFTP_C_866 , VSFTP_C_UTF8 , VSFTP_CS_866 , VSFTP_CS_UTF8CYR },
+ { VSFTP_C_866 , VSFTP_C_1251 , VSFTP_CS_866 , VSFTP_CS_1251 },
+ { VSFTP_C_866 , VSFTP_C_878R , VSFTP_CS_866 , VSFTP_CS_878R },
+ { VSFTP_C_866 , VSFTP_C_878U , VSFTP_CS_866 , VSFTP_CS_878U },
+ { VSFTP_C_866 , VSFTP_C_ISO5 , VSFTP_CS_866 , VSFTP_CS_ISO5 },
+ { VSFTP_C_ISO5 , VSFTP_C_UTF8 , VSFTP_CS_ISO5 , VSFTP_CS_UTF8CYR },
+ { VSFTP_C_ISO5 , VSFTP_C_1251 , VSFTP_CS_ISO5 , VSFTP_CS_1251 },
+ { VSFTP_C_ISO5 , VSFTP_C_878R , VSFTP_CS_ISO5 , VSFTP_CS_878R },
+ { VSFTP_C_ISO5 , VSFTP_C_878U , VSFTP_CS_ISO5 , VSFTP_CS_878U },
+ { VSFTP_C_ISO5 , VSFTP_C_866 , VSFTP_CS_ISO5 , VSFTP_CS_866 },
+#endif
+ // Western European
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+ { VSFTP_C_UTF8 , VSFTP_C_ISO1 , VSFTP_CS_UTF8WEST , VSFTP_CS_ISO1 },
+ { VSFTP_C_UTF8 , VSFTP_C_ISO15 , VSFTP_CS_UTF8WEST , VSFTP_CS_ISO15 },
+ { VSFTP_C_UTF8 , VSFTP_C_1252 , VSFTP_CS_UTF8WEST , VSFTP_CS_1252 },
+ { VSFTP_C_ISO1 , VSFTP_C_UTF8 , VSFTP_CS_ISO1 , VSFTP_CS_UTF8WEST },
+ { VSFTP_C_ISO1 , VSFTP_C_ISO15 , VSFTP_CS_ISO1 , VSFTP_CS_ISO15 },
+ { VSFTP_C_ISO1 , VSFTP_C_1252 , VSFTP_CS_ISO1 , VSFTP_CS_1252 },
+ { VSFTP_C_ISO15 , VSFTP_C_UTF8 , VSFTP_CS_ISO15 , VSFTP_CS_UTF8WEST },
+ { VSFTP_C_ISO15 , VSFTP_C_ISO1 , VSFTP_CS_ISO15 , VSFTP_CS_ISO1 },
+ { VSFTP_C_ISO15 , VSFTP_C_1252 , VSFTP_CS_ISO15 , VSFTP_CS_1252 },
+ { VSFTP_C_1252 , VSFTP_C_UTF8 , VSFTP_CS_1252 , VSFTP_CS_UTF8WEST },
+ { VSFTP_C_1252 , VSFTP_C_ISO1 , VSFTP_CS_1252 , VSFTP_CS_ISO1 },
+ { VSFTP_C_1252 , VSFTP_C_ISO15 , VSFTP_CS_1252 , VSFTP_CS_ISO15 },
+#endif
+ // Central European
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+ { VSFTP_C_UTF8 , VSFTP_C_ISO2 , VSFTP_CS_UTF8CENT , VSFTP_CS_ISO2 },
+ { VSFTP_C_UTF8 , VSFTP_C_ISO16 , VSFTP_CS_UTF8CENT , VSFTP_CS_ISO16 },
+ { VSFTP_C_UTF8 , VSFTP_C_1250 , VSFTP_CS_UTF8CENT , VSFTP_CS_1250 },
+ { VSFTP_C_ISO2 , VSFTP_C_UTF8 , VSFTP_CS_ISO2 , VSFTP_CS_UTF8CENT },
+ { VSFTP_C_ISO2 , VSFTP_C_ISO16 , VSFTP_CS_ISO2 , VSFTP_CS_ISO16 },
+ { VSFTP_C_ISO2 , VSFTP_C_1250 , VSFTP_CS_ISO2 , VSFTP_CS_1250 },
+ { VSFTP_C_ISO16 , VSFTP_C_UTF8 , VSFTP_CS_ISO16 , VSFTP_CS_UTF8CENT },
+ { VSFTP_C_ISO16 , VSFTP_C_ISO2 , VSFTP_CS_ISO16 , VSFTP_CS_ISO2 },
+ { VSFTP_C_ISO16 , VSFTP_C_1250 , VSFTP_CS_ISO16 , VSFTP_CS_1250 },
+ { VSFTP_C_1250 , VSFTP_C_UTF8 , VSFTP_CS_1250 , VSFTP_CS_UTF8CENT },
+ { VSFTP_C_1250 , VSFTP_C_ISO2 , VSFTP_CS_1250 , VSFTP_CS_ISO2 },
+ { VSFTP_C_1250 , VSFTP_C_ISO16 , VSFTP_CS_1250 , VSFTP_CS_ISO16 },
+#endif
+ // Soutern European
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+ { VSFTP_C_UTF8 , VSFTP_C_ISO3 , VSFTP_CS_UTF8SOUT , VSFTP_CS_ISO3 },
+ { VSFTP_C_ISO3 , VSFTP_C_UTF8 , VSFTP_CS_ISO3 , VSFTP_CS_UTF8SOUT },
+#endif
+
+ { 0, 0, 0, 0 }
+};
+
+map_ptr map_array[] =
+{
+ 0,
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+ codepage_utf8cyr_array, codepage_win1251_array, codepage_koi8r_array,
+ codepage_ibm866_array, codepage_iso5_array, codepage_koi8u_array,
+#else
+ 0, 0, 0, 0, 0,
+#endif
+
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+ codepage_utf8west_array, codepage_iso1_array, codepage_iso15_array,
+ codepage_win1252_array,
+#else
+ 0, 0, 0, 0,
+#endif
+
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+ codepage_utf8cent_array, codepage_iso2_array, codepage_iso16_array,
+ codepage_win1250_array,
+#else
+ 0, 0, 0, 0,
+#endif
+
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+ codepage_utf8sout_array, codepage_iso3_array,
+#else
+ 0, 0,
+#endif
+
+ 0
+};
+
+/* Initial table for work with unprintable chars */
+map_ptr init_array[] =
+{
+ 0,
+ codepage_utf8_array,
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+ codepage_win1251_array, codepage_koi8r_array, codepage_ibm866_array,
+ codepage_iso5_array, codepage_koi8u_array,
+#else
+ 0, 0, 0, 0,
+#endif
+
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+ codepage_iso1_array, codepage_iso15_array, codepage_win1252_array,
+#else
+ 0, 0, 0,
+#endif
+
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+ codepage_iso2_array, codepage_iso16_array, codepage_win1250_array,
+#else
+ 0, 0, 0,
+#endif
+
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+ codepage_iso3_array,
+#else
+ 0,
+#endif
+
+ 0
+};
+
+map_ptr localMap = 0, remoteMap = 0;
+map_ptr localTbl = 0, remoteTbl = 0;
+
+void char_convertion(struct mystr* p_str, int direction, char unprintable);
+void InitTables(map_ptr* map, map_ptr* table, int indexx);
+static int char_len(unsigned int s);
+static unsigned int bsearch_index(map_ptr map, unsigned int low, unsigned int high, unsigned int char_code);
+
+const char* vsf_charconv_charset_name(int code)
+{
+ int i = 0;
+ while (available_charsets_array [i].p_charset_name && available_charsets_array [i].p_variable != code) i++;
+ return available_charsets_array [i].p_charset_name;
+}
+
+int vsf_charconv_codepage(const char* p_str)
+{
+ const struct available_charsets* charsets = available_charsets_array;
+
+ while (charsets->p_charset_name != 0)
+ {
+ if (str_equal_str (charsets->p_charset_name, p_str))
+ {
+ return charsets->p_variable;
+ }
+ charsets++;
+ }
+
+ return 0;
+}
+
+int vsf_charconv_avail_convertion(int localCode, int remoteCode)
+{
+ const struct available_convertions* aconv = available_convertions_array;
+
+ while (aconv->local != 0)
+ {
+ if (localCode == aconv->local && remoteCode == aconv->remote)
+ {
+ InitTables(&localMap, &localTbl, aconv->localCharset);
+ InitTables(&remoteMap, &remoteTbl, aconv->remoteCharset);
+ return 1;
+ }
+ aconv++;
+ }
+
+ return 0;
+}
+
+void vsf_charconv_init_local_codepage(int localCode)
+{
+ if (!localCode)
+ {
+ return;
+ }
+
+ localTbl = init_array [localCode];
+ localMap = vsf_sysutil_malloc((localTbl [0].order + 1) * sizeof(_codepage_map));
+ localMap [0].char_code = localTbl [0].char_code;
+ localMap [0].order = localTbl [0].order;
+
+ int indexx = 1;
+ while (localTbl [indexx].char_code)
+ {
+ if (localTbl [indexx].order)
+ {
+ localMap [localTbl [indexx].order].char_code = localTbl [indexx].char_code;
+ localMap [localTbl [indexx].order].order = indexx;
+ }
+ indexx++;
+ }
+
+ return;
+}
+
+void vsf_charconv_convert(struct vsf_session* p_sess, struct mystr* p_str, int direction)
+{
+ if (!p_sess->enable_convertion || !p_sess->remote_charset || !tunable_local_codepage) return;
+
+ char_convertion(p_str, direction, '?');
+}
+
+void vsf_charconv_replace_unprintable(struct mystr* p_str, char new_char)
+{
+ if (localMap) char_convertion(p_str, VSFTP_CONVDIRECT_UNPRINTABLE, new_char);
+}
+
+void InitTables(map_ptr* map, map_ptr* table, int indexx)
+{
+ *table = map_array [indexx];
+
+ if (*map) vsf_sysutil_free(*map);
+
+ *map = vsf_sysutil_malloc(((*table) [0].order + 1) * sizeof(_codepage_map));
+ (*map) [0].char_code = (*table) [0].char_code;
+ (*map) [0].order = (*table) [0].order;
+
+ indexx = 1;
+ while ((*table) [indexx].char_code)
+ {
+ if ((*table) [indexx].order)
+ {
+ (*map) [(*table) [indexx].order].char_code = (*table) [indexx].char_code;
+ (*map) [(*table) [indexx].order].order = indexx;
+ }
+ indexx++;
+ }
+
+ return;
+}
+
+static int char_len(unsigned int s)
+{
+ int len = 1;
+ if ((s & 0x80) == 0x00) len = 1;
+ else if ((s & 0xe0) == 0xc0) len = 2;
+ else if ((s & 0xf0) == 0xe0) len = 3;
+ else if ((s & 0xf8) == 0xf0) len = 4;
+// else if ((s & 0xfc) == 0xf8) len = 5;
+// else if ((s & 0xfe) == 0xce) len = 6;
+ return (len);
+}
+
+static unsigned int bsearch_index(map_ptr map, unsigned int low, unsigned int high, unsigned int char_code)
+{
+ unsigned int m, l = low, r = high;
+
+ m = (l + r) >> 1;
+ while ((m != 0) && (map [m].char_code != char_code))
+ {
+ if (map [m].char_code < char_code) l = m + 1;
+ else
+ if (map [m].char_code > char_code) r = m - 1;
+ if (l > r)
+ return 0;
+ else
+ m = (l + r) >> 1;
+ }
+
+ if (m) m = map [m].order;
+ return m;
+}
+
+void char_convertion(struct mystr* p_str, int direction, char unprintable)
+{
+ const char* srcbuf;
+ unsigned int srclen;
+ char* dstbuf;
+ map_ptr src, dst;
+ unsigned int sl;
+ unsigned int srcpos = 0, dstpos = 0;
+ unsigned int char_code = 0;
+
+ srclen = str_getlen(p_str); // Len of source string
+ srcbuf = str_getbuf(p_str);
+
+ if (direction == VSFTP_CONVDIRECT_FORWARD)
+ {
+ src = localMap;
+ dst = remoteTbl;
+ }
+ else
+ if (direction == VSFTP_CONVDIRECT_BACKWARD)
+ {
+ src = remoteMap;
+ dst = localTbl;
+ }
+ else
+ {
+ src = localMap;
+ dst = localTbl;
+ }
+
+ if (!src || !dst)
+ {
+ return;
+ }
+
+ dstbuf = vsf_sysutil_malloc(srclen * dst [0].char_code + dst [0].char_code);
+
+ while (srcpos < srclen)
+ {
+ char_code = (unsigned char)srcbuf [srcpos++];
+ if (src [0].char_code > 1)
+ {
+ sl = char_len (char_code);
+ while (sl-- > 1)
+ {
+ char_code = (char_code << 8) | (unsigned char)srcbuf [srcpos++];
+ }
+ }
+
+ if (char_code > 127)
+ {
+ sl = bsearch_index (src, 1, src [0].order, char_code);
+ char_code = 0;
+ if (sl) char_code = dst [sl].char_code;
+ }
+
+ if (char_code == 13 || char_code == 10)
+ {
+ char_code = 0;
+ }
+ else
+ if (char_code < 32 && char_code != 9)
+ {
+ char_code = (unsigned int)unprintable;
+ }
+
+ if (char_code > 0 || direction != VSFTP_CONVDIRECT_UNPRINTABLE)
+ {
+ if (char_code & 0xff000000) dstbuf [dstpos++] = (char)((char_code >> 24) & 0xff);
+ if (char_code & 0x00ff0000) dstbuf [dstpos++] = (char)((char_code >> 16) & 0xff);
+ if (char_code & 0x0000ff00) dstbuf [dstpos++] = (char)((char_code >> 8) & 0xff);
+ if (char_code & 0x000000ff) dstbuf [dstpos++] = (char)((char_code ) & 0xff);
+ }
+ }
+
+ dstbuf [dstpos] = '\0';
+
+ str_alloc_text(p_str, dstbuf);
+ vsf_sysutil_free(dstbuf);
+}
+
Index: twoprocess.c
===================================================================
--- twoprocess.c (revision 132)
+++ twoprocess.c (revision 140)
@@ -439,7 +439,7 @@
/* Guard against the config error of having the anonymous ftp tree owned
* by the user we are running as
*/
- if (was_anon && vsf_sysutil_write_access("/"))
+ if (!tunable_tpm_allow_anon_root_access && was_anon && vsf_sysutil_write_access("/"))
{
die("vsftpd: refusing to run with writable anonymous root");
}
Index: charconv.h
===================================================================
--- charconv.h (revision 0)
+++ charconv.h (revision 140)
@@ -0,0 +1,182 @@
+#ifndef VSF_CHARCONV_H
+#define VSF_CHARCONV_H
+
+struct mystr;
+struct vsf_session;
+
+#define VSFTP_CHARCONV_SUPPORT_CYRILLIC
+#define VSFTP_CHARCONV_SUPPORT_WESTERN
+#define VSFTP_CHARCONV_SUPPORT_CENTRAL
+#define VSFTP_CHARCONV_SUPPORT_SOUTERN
+
+#define VSFTP_CONVDIRECT_FORWARD 1
+#define VSFTP_CONVDIRECT_UNPRINTABLE 0
+#define VSFTP_CONVDIRECT_BACKWARD -1
+
+/* Supported charset for convertion */
+#define VSFTP_CP_NONE "NONE"
+#define VSFTP_CP_UTF_8 "UTF-8"
+#define VSFTP_CP_UTF8 "UTF8"
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+#define VSFTP_CP_WIN_1251 "Win-1251"
+#define VSFTP_CP_WIN1251 "WIN1251"
+#define VSFTP_CP_CP1251 "CP1251"
+#define VSFTP_CP_1251 "1251"
+#define VSFTP_CP_KOI8_R "Koi8-R"
+#define VSFTP_CP_KOI8R "KOI8R"
+#define VSFTP_CP_KOI8_U "Koi8-U"
+#define VSFTP_CP_KOI8U "KOI8U"
+#define VSFTP_CP_CP878 "CP878"
+#define VSFTP_CP_878 "878"
+#define VSFTP_CP_CP878R "CP878R"
+#define VSFTP_CP_878R "878R"
+#define VSFTP_CP_CP878U "CP878U"
+#define VSFTP_CP_878U "878U"
+#define VSFTP_CP_IBM866 "IBM866"
+#define VSFTP_CP_CP866 "CP866"
+#define VSFTP_CP_866 "866"
+#define VSFTP_CP_ISO8859_5 "ISO-8859-5"
+#define VSFTP_CP_ISO5 "ISO5"
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+#define VSFTP_CP_ISO8859_1 "ISO-8859-1"
+#define VSFTP_CP_ISO1 "ISO1"
+#define VSFTP_CP_LATIN1 "LATIN1"
+#define VSFTP_CP_ISO8859_15 "ISO-8859-15"
+#define VSFTP_CP_ISO15 "ISO15"
+#define VSFTP_CP_LATIN9 "LATIN9"
+#define VSFTP_CP_WIN_1252 "Win-1252"
+#define VSFTP_CP_WIN1252 "WIN1252"
+#define VSFTP_CP_CP1252 "CP1252"
+#define VSFTP_CP_1252 "1252"
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+#define VSFTP_CP_ISO8859_2 "ISO-8859-2"
+#define VSFTP_CP_ISO2 "ISO2"
+#define VSFTP_CP_LATIN2 "LATIN2"
+#define VSFTP_CP_ISO8859_16 "ISO-8859-16"
+#define VSFTP_CP_ISO16 "ISO16"
+#define VSFTP_CP_WIN_1250 "Win-1250"
+#define VSFTP_CP_WIN1250 "WIN1250"
+#define VSFTP_CP_CP1250 "CP1250"
+#define VSFTP_CP_1250 "1250"
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+#define VSFTP_CP_ISO8859_3 "ISO-8859-3"
+#define VSFTP_CP_ISO3 "ISO3"
+#define VSFTP_CP_LATIN3 "LATIN3"
+#endif
+
+#define VSFTP_C_NONE 0
+#define VSFTP_C_UTF8 1
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+#define VSFTP_C_1251 2
+#define VSFTP_C_878R 3
+#define VSFTP_C_866 4
+#define VSFTP_C_ISO5 5
+#define VSFTP_C_878U 6
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+#define VSFTP_C_ISO1 7
+#define VSFTP_C_ISO15 8
+#define VSFTP_C_1252 9
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+#define VSFTP_C_ISO2 10
+#define VSFTP_C_ISO16 11
+#define VSFTP_C_1250 12
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+#define VSFTP_C_ISO3 13
+#endif
+
+#define VSFTP_CS_NONE 0
+#ifdef VSFTP_CHARCONV_SUPPORT_CYRILLIC
+#define VSFTP_CS_UTF8CYR 1
+#define VSFTP_CS_1251 2
+#define VSFTP_CS_878R 3
+#define VSFTP_CS_866 4
+#define VSFTP_CS_ISO5 5
+#define VSFTP_CS_878U 6
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_WESTERN
+#define VSFTP_CS_UTF8WEST 7
+#define VSFTP_CS_ISO1 8
+#define VSFTP_CS_ISO15 9
+#define VSFTP_CS_1252 10
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_CENTRAL
+#define VSFTP_CS_UTF8CENT 11
+#define VSFTP_CS_ISO2 12
+#define VSFTP_CS_ISO16 13
+#define VSFTP_CS_1250 14
+#endif
+#ifdef VSFTP_CHARCONV_SUPPORT_SOUTERN
+#define VSFTP_CS_UTF8SOUT 15
+#define VSFTP_CS_ISO3 16
+#endif
+
+struct codepage_map
+{
+ unsigned int char_code; // The first element is count bytes of char.
+ unsigned int order;
+} _codepage_map;
+
+typedef struct codepage_map * map_ptr;
+
+extern map_ptr localMap;
+
+/* vsf_charconv_charset_name()
+ * PURPOSE
+ * Get charset name by code;
+ * PARAMETERS
+ * code - Internal charset code
+ * RETURNS
+ * Charset name
+ */
+const char* vsf_charconv_charset_name(int code);
+
+/* vsf_charconv_codepage()
+ * PURPOSE
+ * Get internal charset code
+ * PARAMETERS
+ * p_str - String value with code page
+ * RETURNS
+ * Internal charset code
+ */
+int vsf_charconv_codepage(const char* p_str);
+
+/* vsf_charconv_init_local_codepage(int localCode)
+ * PURPOSE
+ * Init local codepage for work with unprintable chars
+ * PARAMETERS
+ * localCode - source internal code page
+ */
+void vsf_charconv_init_local_codepage(int localCode);
+
+/* vsf_charconv_avail_convertion()
+ * PURPOS
+ * Checking for available convertion characters
+ * PARAMETERS
+ * localCode - source internal code page
+ * remoteCode - destination internal code page
+ * RETURNS
+ * Available ot not converion
+ */
+int vsf_charconv_avail_convertion(int localCode, int remoteCode);
+
+/* vsf_charconv_convert()
+ * PURPOSE
+ * Converting string via charsets
+ * PARAMETERS
+ * p_sess - the current session object
+ * p_str - string for convertin
+ * direction - converting from host to remoute charsetr or otherwise
+ */
+void vsf_charconv_convert(struct vsf_session* p_sess, struct mystr* p_str, int direction);
+
+/* vsf_charconv_replace_unprintable
+ */
+void vsf_charconv_replace_unprintable(struct mystr* p_str, char new_char);
+
+#endif
Index: sysutil.c
===================================================================
--- sysutil.c (revision 132)
+++ sysutil.c (revision 140)
@@ -201,6 +201,9 @@
case kVSFSysUtilSigHUP:
realsig = SIGHUP;
break;
+ case kVSFSysUtilSigUSR1:
+ realsig = SIGUSR1;
+ break;
default:
bug("unknown signal in vsf_sysutil_translate_sig");
break;
@@ -496,6 +499,22 @@
}
}
+void
+vsf_sysutil_fillbuff(void* buff, unsigned int size, char chr)
+{
+ if (size == 0 || size > INT_MAX || buff == NULL)
+ {
+ return;
+ }
+ while (size != 0)
+ {
+ *(char*)buff = chr;
+ buff++;
+ size--;
+ }
+ return;
+}
+
void*
vsf_sysutil_malloc(unsigned int size)
{
@@ -514,6 +533,15 @@
}
void*
+vsf_sysutil_malloc_zero(unsigned int size)
+{
+ void* p_ret;
+ p_ret = vsf_sysutil_malloc(size);
+ vsf_sysutil_fillbuff(p_ret, size, 0);
+ return p_ret;
+}
+
+void*
vsf_sysutil_realloc(void* p_ptr, unsigned int size)
{
void* p_ret;
@@ -549,10 +577,24 @@
return (unsigned int) s_current_pid;
}
+unsigned int
+vsf_sysutil_getppid(void)
+{
+ return (unsigned int)getppid();
+}
+
int
vsf_sysutil_fork(void)
{
- int retval = vsf_sysutil_fork_failok();
+ /* Child does NOT inherit exit function */
+ exitfunc_t curr_func = s_exit_func;
+ int retval;
+ s_exit_func = 0;
+ retval = vsf_sysutil_fork_failok();
+ if (retval != 0)
+ {
+ s_exit_func = curr_func;
+ }
if (retval < 0)
{
die("fork");
@@ -839,6 +881,14 @@
}
const char*
+vsf_sysutil_ulong_to_hex(unsigned long the_ulong)
+{
+ static char ulong_buf[32];
+ (void) snprintf(ulong_buf, sizeof(ulong_buf), "%.8lx", the_ulong);
+ return ulong_buf;
+}
+
+const char*
vsf_sysutil_filesize_t_to_str(filesize_t the_filesize)
{
static char filesize_buf[32];
@@ -1035,6 +1085,18 @@
return strdup(p_str);
}
+char*
+vsf_sysutil_strndup(const char* p_str, unsigned int p_len)
+{
+ char *new = (char *)malloc(p_len+1);
+
+ if (new == NULL)
+ return NULL;
+
+ new[p_len]='\0';
+ return (char *)memcpy(new, p_str, p_len);
+}
+
void
vsf_sysutil_memclr(void* p_dest, unsigned int size)
{
@@ -1357,6 +1419,13 @@
return perms;
}
+long
+vsf_sysutil_statbuf_get_filedate(const struct vsf_sysutil_statbuf* p_statbuf)
+{
+ const struct stat* p_stat = (const struct stat*) p_statbuf;
+ return p_stat->st_mtime;
+}
+
const char*
vsf_sysutil_statbuf_get_date(const struct vsf_sysutil_statbuf* p_statbuf,
int use_localtime, long curr_time)
@@ -1569,7 +1638,7 @@
int
vsf_sysutil_retval_is_error(int retval)
{
- if (retval < 0)
+ if (retval == -1)
{
return 1;
}
@@ -2275,6 +2344,15 @@
}
}
+int
+vsf_sysutil_inet_addr_to_int(struct vsf_sysutil_sockaddr* p_addr)
+{
+ struct in_addr sin_addr;
+ vsf_sysutil_memcpy(&sin_addr, &p_addr->u.u_sockaddr_in.sin_addr,
+ sizeof(p_addr->u.u_sockaddr_in.sin_addr));
+ return (int)sin_addr.s_addr;
+}
+
struct vsf_sysutil_user*
vsf_sysutil_getpwuid(const int uid)
{
@@ -2587,14 +2665,18 @@
}
const char*
-vsf_sysutil_get_current_date(void)
+vsf_sysutil_get_current_date(int use_localtime)
{
static char datebuf[64];
time_t curr_time;
const struct tm* p_tm;
int i = 0;
curr_time = vsf_sysutil_get_time_sec();
- p_tm = localtime(&curr_time);
+ if (!use_localtime) {
+ p_tm = gmtime(&curr_time);
+ } else {
+ p_tm = localtime(&curr_time);
+ }
if (strftime(datebuf, sizeof(datebuf), "%a %b!%d %H:%M:%S %Y", p_tm) == 0)
{
die("strftime");
@@ -2616,6 +2698,70 @@
return datebuf;
}
+const char*
+vsf_sysutil_get_datetimefmt(int use_localtime, long curr_time, const char* fmt)
+{
+ static char datebuf[64];
+ const struct tm* p_tm;
+ int i = 0;
+ if (!use_localtime) {
+ p_tm = gmtime(&curr_time);
+ } else {
+ p_tm = localtime(&curr_time);
+ }
+ if (strftime(datebuf, sizeof(datebuf), fmt, p_tm) == 0)
+ {
+ die("strftime");
+ }
+ datebuf[sizeof(datebuf) - 1] = '\0';
+ /* This hack is because %e in strftime() isn't so portable */
+ while (datebuf[i] != '!' && datebuf[i] != '\0')
+ {
+ ++i;
+ }
+ if (datebuf[i] == '!')
+ {
+ datebuf[i] = ' ';
+ if (datebuf[i+1] == '0')
+ {
+ datebuf[i+1] = ' ';
+ }
+ }
+ return datebuf;
+}
+
+const char*
+vsf_sysutil_get_datetime(int use_localtime, long curr_time)
+{
+ if (!use_localtime) {
+ return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%a,!%d %b %H:%M:%S %Y %Z");
+ } else {
+ return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%a,!%d %b %H:%M:%S %Y");
+ }
+}
+
+const char*
+vsf_sysutil_get_date(int use_localtime, long curr_time)
+{
+ return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%a,!%d %b %Y");
+}
+
+const char*
+vsf_sysutil_get_sdate(int use_localtime, long curr_time)
+{
+ return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%d.%m.%Y");
+}
+
+const char*
+vsf_sysutil_get_time(int use_localtime, long curr_time)
+{
+ if (!use_localtime) {
+ return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%H:%M:%S %Z");
+ } else {
+ return vsf_sysutil_get_datetimefmt(use_localtime, curr_time, "%H:%M:%S");
+ }
+}
+
long
vsf_sysutil_get_time_sec(void)
{
@@ -2830,3 +2976,54 @@
s_sig_details[i].pending = 0;
}
}
+
+static struct sigaction sigalr, sigusr1;
+
+void
+vsf_sysutil_sigaction(const enum EVSFSysUtilSignal sig, void (*p_handlefunc)(int))
+{
+ int realsig = vsf_sysutil_translate_sig(sig);
+ int retval;
+ struct sigaction sigact, *origsigact=NULL;
+ if (realsig==SIGALRM)
+ {
+ origsigact = &sigalr;
+ }
+ else if (realsig==SIGUSR1)
+ {
+ origsigact = &sigusr1;
+ }
+ vsf_sysutil_memclr(&sigact, sizeof(sigact));
+ if (p_handlefunc != NULL)
+ {
+ sigact.sa_handler = p_handlefunc;
+ retval = sigfillset(&sigact.sa_mask);
+ if (retval != 0)
+ {
+ die("sigfillset");
+ }
+ retval = sigaction(realsig, &sigact, origsigact);
+ }
+ else
+ {
+ retval = sigaction(realsig, origsigact, NULL);
+ }
+ if (retval != 0)
+ {
+ die("sigaction");
+ }
+}
+
+int
+vsf_sysutil_kill(int pid, int sig)
+{
+ int realsig = vsf_sysutil_translate_sig(sig);
+ return kill(pid, realsig);
+}
+
+int
+vsf_sysutil_pause()
+{
+ return pause();
+}
+
Index: tunables.c
===================================================================
--- tunables.c (revision 132)
+++ tunables.c (revision 140)
@@ -7,6 +7,7 @@
#include "tunables.h"
#include "sysutil.h"
+#include "builddefs.h"
int tunable_anonymous_enable;
int tunable_local_enable;
@@ -72,6 +73,7 @@
int tunable_mdtm_write;
int tunable_lock_upload_files;
int tunable_pasv_addr_resolve;
+int tunable_userlist_log;
int tunable_debug_ssl;
int tunable_require_cert;
int tunable_validate_cert;
@@ -86,6 +88,19 @@
int tunable_isolate_network;
int tunable_ftp_enable;
int tunable_http_enable;
+int tunable_http_browse;
+int tunable_convert_charset_enable;
+int tunable_local_codepage;
+int tunable_remote_codepage;
+int tunable_anon_delete_enable;
+int tunable_add_default_rule;
+int tunable_chown_by_ip;
+int tunable_tpm_allow_anon_root_access;
+int tunable_double_377;
+int tunable_anon_rxtx_rate;
+int tunable_local_rxtx_rate;
+int tunable_chown_group;
+int tunable_anti_bruteforce;
unsigned int tunable_accept_timeout;
unsigned int tunable_connect_timeout;
@@ -97,7 +112,11 @@
unsigned int tunable_pasv_min_port;
unsigned int tunable_pasv_max_port;
unsigned int tunable_anon_max_rate;
+unsigned int tunable_anon_max_rate_rx;
+unsigned int tunable_anon_max_rate_tx;
unsigned int tunable_local_max_rate;
+unsigned int tunable_local_max_rate_rx;
+unsigned int tunable_local_max_rate_tx;
unsigned int tunable_listen_port;
unsigned int tunable_max_clients;
unsigned int tunable_file_open_mode;
@@ -140,6 +159,16 @@
const char* tunable_rsa_private_key_file;
const char* tunable_dsa_private_key_file;
const char* tunable_ca_certs_file;
+const char* tunable_local_charset;
+const char* tunable_remote_charset;
+const char* tunable_pasv_addr_rules;
+const char* tunable_users_access_ip;
+const char* tunable_anti_bruteforce_banner;
+const char* tunable_http_error_403_server_tpl;
+const char* tunable_http_error_403_tpl;
+const char* tunable_http_error_404_tpl;
+const char* tunable_http_browse_tpl;
+const char* tunable_http_browse_line_tpl;
static void install_str_setting(const char* p_value, const char** p_storage);
@@ -178,7 +207,7 @@
tunable_use_localtime = 0;
tunable_check_shell = 1;
tunable_hide_ids = 0;
- tunable_listen = 0;
+ tunable_listen = 1;
tunable_port_promiscuous = 0;
tunable_passwd_chroot_enable = 0;
tunable_no_anon_password = 0;
@@ -188,7 +217,7 @@
tunable_listen_ipv6 = 0;
tunable_dual_log_enable = 0;
tunable_syslog_enable = 0;
- tunable_background = 0;
+ tunable_background = 1;
tunable_virtual_use_local_privs = 0;
tunable_session_support = 0;
tunable_download_enable = 1;
@@ -210,6 +239,7 @@
tunable_mdtm_write = 1;
tunable_lock_upload_files = 1;
tunable_pasv_addr_resolve = 0;
+ tunable_userlist_log = 0;
tunable_debug_ssl = 0;
tunable_require_cert = 0;
tunable_validate_cert = 0;
@@ -224,6 +254,19 @@
tunable_isolate_network = 1;
tunable_ftp_enable = 1;
tunable_http_enable = 0;
+ tunable_http_browse = 0;
+ tunable_convert_charset_enable = 0;
+ tunable_local_codepage = 0;
+ tunable_remote_codepage = 0;
+ tunable_anon_delete_enable = 1;
+ tunable_add_default_rule = 0;
+ tunable_chown_by_ip = 0;
+ tunable_tpm_allow_anon_root_access = 0;
+ tunable_double_377 = 1;
+ tunable_anon_rxtx_rate = 0;
+ tunable_local_rxtx_rate = 0;
+ tunable_chown_group = 0;
+ tunable_anti_bruteforce = 0;
tunable_accept_timeout = 60;
tunable_connect_timeout = 60;
@@ -236,7 +279,11 @@
tunable_pasv_min_port = 5001;
tunable_pasv_max_port = 0;
tunable_anon_max_rate = 0;
+ tunable_anon_max_rate_rx = 0;
+ tunable_anon_max_rate_tx = 0;
tunable_local_max_rate = 0;
+ tunable_local_max_rate_rx = 0;
+ tunable_local_max_rate_tx = 0;
/* IPPORT_FTP */
tunable_listen_port = 21;
tunable_max_clients = 2000;
@@ -248,7 +295,7 @@
tunable_delay_successful_login = 0;
tunable_max_login_fails = 3;
/* -rw------- */
- tunable_chown_upload_mode = 0600;
+ tunable_chown_upload_mode = 0666;
install_str_setting("/usr/share/empty", &tunable_secure_chroot_dir);
install_str_setting("ftp", &tunable_ftp_username);
@@ -258,11 +305,11 @@
install_str_setting(".message", &tunable_message_file);
install_str_setting("nobody", &tunable_nopriv_user);
install_str_setting(0, &tunable_ftpd_banner);
- install_str_setting("/etc/vsftpd.banned_emails", &tunable_banned_email_file);
- install_str_setting("/etc/vsftpd.chroot_list", &tunable_chroot_list_file);
+ install_str_setting(VSF_CONFIG_PATH VSF_CONFIG_PREFIX "banned_emails", &tunable_banned_email_file);
+ install_str_setting(VSF_CONFIG_PATH VSF_CONFIG_PREFIX "chroot_list", &tunable_chroot_list_file);
install_str_setting("ftp", &tunable_pam_service_name);
install_str_setting("ftp", &tunable_guest_username);
- install_str_setting("/etc/vsftpd.user_list", &tunable_userlist_file);
+ install_str_setting(VSF_CONFIG_PATH VSF_CONFIG_PREFIX "user_list", &tunable_userlist_file);
install_str_setting(0, &tunable_anon_root);
install_str_setting(0, &tunable_local_root);
install_str_setting(0, &tunable_banner_file);
@@ -275,7 +322,7 @@
install_str_setting(0, &tunable_hide_file);
install_str_setting(0, &tunable_deny_file);
install_str_setting(0, &tunable_user_sub_token);
- install_str_setting("/etc/vsftpd.email_passwords",
+ install_str_setting(VSF_CONFIG_PATH VSF_CONFIG_PREFIX "email_passwords",
&tunable_email_password_file);
install_str_setting("/usr/share/ssl/certs/vsftpd.pem",
&tunable_rsa_cert_file);
@@ -284,6 +331,16 @@
install_str_setting(0, &tunable_rsa_private_key_file);
install_str_setting(0, &tunable_dsa_private_key_file);
install_str_setting(0, &tunable_ca_certs_file);
+ install_str_setting("NONE", &tunable_local_charset);
+ install_str_setting("NONE", &tunable_remote_charset);
+ install_str_setting(VSF_CONFIG_PATH VSF_CONFIG_PREFIX "pasv_rules", &tunable_pasv_addr_rules);
+ install_str_setting(VSF_CONFIG_PATH VSF_CONFIG_PREFIX "users_ip", &tunable_users_access_ip);
+ install_str_setting(0, &tunable_anti_bruteforce_banner);
+ install_str_setting(0, &tunable_http_error_403_server_tpl);
+ install_str_setting(0, &tunable_http_error_403_tpl);
+ install_str_setting(0, &tunable_http_error_404_tpl);
+ install_str_setting(0, &tunable_http_browse_tpl);
+ install_str_setting(0, &tunable_http_browse_line_tpl);
}
void
Index: features.c
===================================================================
--- features.c (revision 132)
+++ features.c (revision 140)
@@ -18,31 +18,34 @@
vsf_cmdio_write_hyphen(p_sess, FTP_FEAT, "Features:");
if (tunable_ssl_enable)
{
- vsf_cmdio_write_raw(p_sess, " AUTH SSL\r\n");
- vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " AUTH SSL\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " AUTH TLS\r\n");
}
if (tunable_port_enable)
{
- vsf_cmdio_write_raw(p_sess, " EPRT\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " EPRT\r\n");
}
if (tunable_pasv_enable)
{
- vsf_cmdio_write_raw(p_sess, " EPSV\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " EPSV\r\n");
}
- vsf_cmdio_write_raw(p_sess, " MDTM\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " MDTM\r\n");
if (tunable_pasv_enable)
{
- vsf_cmdio_write_raw(p_sess, " PASV\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " PASV\r\n");
}
if (tunable_ssl_enable)
{
- vsf_cmdio_write_raw(p_sess, " PBSZ\r\n");
- vsf_cmdio_write_raw(p_sess, " PROT\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " PBSZ\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " PROT\r\n");
}
- vsf_cmdio_write_raw(p_sess, " REST STREAM\r\n");
- vsf_cmdio_write_raw(p_sess, " SIZE\r\n");
- vsf_cmdio_write_raw(p_sess, " TVFS\r\n");
- vsf_cmdio_write_raw(p_sess, " UTF8\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " REST STREAM\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " SIZE\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " TVFS\r\n");
+ if (tunable_convert_charset_enable)
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, " UTF8\r\n");
+ }
vsf_cmdio_write(p_sess, FTP_FEAT, "End");
}
Index: http.c
===================================================================
--- http.c (revision 0)
+++ http.c (revision 140)
@@ -0,0 +1,331 @@
+/*
+ * Part of Very Secure FTPd
+ * Licence: GPL v2
+ * Author: Dmitriy Balashov
+ * http.c
+ *
+ * Routines to handle HTTP.
+ */
+
+#include "session.h"
+#include "access.h"
+#include "tunables.h"
+#include "charconv.h"
+#include "filestr.h"
+#include "str.h"
+#include "strlist.h"
+#include "ftpcmdio.h"
+#include "ls.h"
+#include "sysutil.h"
+#include "sysstr.h"
+#include "logging.h"
+#include "defs.h"
+#include "utility.h"
+#include "postlogin.h"
+#include "http_msg.h"
+#include "http_str.h"
+
+enum EResourceType
+{
+ ResTypeNotFound = -1,
+ ResTypeFile,
+ ResType_Dir,
+ ResTypeDir
+};
+
+static void http_error(struct vsf_session* p_sess, const enum EVSFHttpMsgType p_type);
+static void http_html_content(struct vsf_session* p_sess, const char* response, const struct mystr* body);
+static void http_header_print(struct vsf_session* p_sess, const char* response);
+static enum EResourceType http_check_resource(struct vsf_session* p_sess, filesize_t* p_size);
+static enum EResourceType http_request_resource_type(struct vsf_session* p_sess, filesize_t* p_size);
+static void http_handle_send(struct vsf_session* p_sess, filesize_t p_size);
+static void http_handle_browse(struct vsf_session* p_sess);
+
+static char* err_403_forbidden = "403 Forbidden";
+static char* err_404_not_found = "404 Not Found";
+static char* err_200_ok = "200 OK";
+
+void
+handle_http(struct vsf_session* p_sess)
+{
+ /* Warning: Doesn't respect cmds_allowed etc. because there is currently only
+ * one command (GET)!
+ * HTTP likely doesn't respect other important FTP options. I don't think
+ * logging works.
+ */
+ if (!tunable_download_enable)
+ {
+ bug("HTTP needs download - fix your config");
+ }
+ /* Eat the HTTP headers, which we don't care about. */
+
+ do
+ {
+ vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
+ &p_sess->ftp_arg_str, 1, 1);
+ }
+ while (!str_isempty(&p_sess->ftp_cmd_str) ||
+ !str_isempty(&p_sess->ftp_arg_str));
+
+ if (!p_sess->is_anonymous)
+ {
+ http_error(p_sess, kVSFHttpMsgType403Serv);
+ }
+
+ /* Split the path from the HTTP/1.x */
+ str_split_char(&p_sess->http_get_arg, &p_sess->ftp_arg_str, ' ');
+ str_unescape(&p_sess->http_get_arg);
+
+ static filesize_t p_size;
+ enum EResourceType p_res_type = http_check_resource(p_sess, &p_size);
+
+ switch (p_res_type)
+ {
+ case ResTypeDir:
+ if (!tunable_http_browse || str_chdir(&p_sess->http_get_arg) != 0)
+ {
+ http_error(p_sess, kVSFHttpMsgType403);
+ }
+ break;
+ case ResTypeNotFound:
+ http_error(p_sess, kVSFHttpMsgType404);
+ break;
+ default:
+ break;
+ }
+
+ if (p_res_type == ResTypeDir)
+ {
+ http_handle_browse(p_sess);
+ }
+ else
+ {
+ http_handle_send(p_sess, p_size);
+ }
+
+ if (vsf_log_entry_pending(p_sess))
+ {
+ vsf_log_do_log(p_sess, 0);
+ }
+ vsf_sysutil_exit(0);
+}
+
+static void
+http_error(struct vsf_session* p_sess, const enum EVSFHttpMsgType p_type)
+{
+ static char* response;
+ static struct mystr p_tpl = INIT_MYSTR;
+ static struct mystr p_res = INIT_MYSTR;
+
+ switch (p_type)
+ {
+ case kVSFHttpMsgType403Serv:
+ response = err_403_forbidden;
+ break;
+ case kVSFHttpMsgType403:
+ response = err_403_forbidden;
+ break;
+ case kVSFHttpMsgType404:
+ response = err_404_not_found;
+ break;
+ default:
+ bug("Bad HTTP error code");
+ break;
+ }
+
+ str_alloc_text(&p_tpl, vsf_http_messages_get(p_type));
+ str_process_template(p_sess, &p_res, &p_tpl, 0, 0, vsf_sysutil_get_time_sec(), 0);
+ http_html_content(p_sess, response, &p_res);
+}
+
+static void
+http_html_content(struct vsf_session* p_sess,
+ const char* response,
+ const struct mystr* body)
+{
+ http_header_print(p_sess, response);
+ vsf_cmdio_write_raw_quiet(p_sess, "Content-Type: text/html\r\n");
+
+ vsf_cmdio_write_raw_quiet(p_sess, "Content-Length: ");
+ vsf_cmdio_write_raw_quiet(p_sess, vsf_sysutil_filesize_t_to_str(str_getlen(body)));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, str_getbuf(body));
+
+ vsf_sysutil_exit(0);
+}
+
+
+static void
+http_header_print(struct vsf_session* p_sess, const char* response)
+{
+ static const char* hdr = "\r\n"
+ "Server: vsftpd\r\n"
+ "Connection: close\r\n"
+ "X-Frame-Options: SAMEORIGIN\r\n"
+ "X-Content-Type-Options: nosniff\r\n";
+
+ vsf_cmdio_write_raw_quiet(p_sess, "HTTP/1.0 ");
+ vsf_cmdio_write_raw_quiet(p_sess, response);
+ vsf_cmdio_write_raw_quiet(p_sess, hdr);
+}
+
+static enum EResourceType
+http_check_resource(struct vsf_session* p_sess, filesize_t* p_size)
+{
+ enum EResourceType ret = http_request_resource_type(p_sess, p_size);
+
+ if (ret == ResType_Dir)
+ {
+ str_chdir(&p_sess->http_get_arg);
+ str_getcwd(&p_sess->http_get_arg);
+ http_header_print(p_sess, "302 Found");
+ vsf_cmdio_write_raw_quiet(p_sess, "Location: ");
+ vsf_cmdio_write_raw_quiet(p_sess, str_getbuf(&p_sess->http_get_arg));
+ vsf_cmdio_write_raw_quiet(p_sess, "/\r\n\r\n");
+
+ vsf_sysutil_exit(0);
+ }
+
+ return ret;
+}
+
+static enum EResourceType
+http_request_resource_type(struct vsf_session* p_sess, filesize_t* p_size)
+{
+ static struct vsf_sysutil_statbuf* p_statbuf;
+ static struct mystr path = INIT_MYSTR;
+ int retval = 0;
+ enum EResourceType ret = ResTypeFile;
+
+ if (str_equal_text(&p_sess->http_get_arg, "/"))
+ {
+ ret = ResTypeDir;
+ }
+ else
+ {
+ if (str_get_char_at(&p_sess->http_get_arg, str_getlen(&p_sess->http_get_arg) - 1) == '/')
+ {
+ ret++; // _Dir
+ str_left(&p_sess->http_get_arg, &path, str_getlen(&p_sess->http_get_arg) - 1);
+ }
+ else
+ {
+ str_copy(&path, &p_sess->http_get_arg);
+ }
+
+ retval = str_stat(&path, &p_statbuf);
+ if (retval == 0)
+ {
+ if (vsf_sysutil_statbuf_is_dir(p_statbuf))
+ {
+ ret++;
+ struct str_locate_result locate = str_locate_text(&path, "..");
+ if (locate.found && ret == ResTypeDir)
+ {
+ ret--;
+ }
+ }
+ else
+ {
+ if (ret != ResTypeFile)
+ {
+ ret = ResTypeNotFound;
+ }
+ else
+ {
+ *p_size = vsf_sysutil_statbuf_get_size(p_statbuf);
+ }
+ }
+ }
+ else
+ {
+ ret = ResTypeNotFound;
+ }
+ }
+
+ if ((ret == ResTypeDir || ret == ResTypeFile) &&
+ !vsf_access_check_file(&p_sess->http_get_arg))
+ {
+ http_error(p_sess, kVSFHttpMsgType403);
+ }
+ if (ret == ResTypeFile)
+ {
+ int opened_file;
+ opened_file = str_open(&p_sess->http_get_arg, kVSFSysStrOpenReadOnly);
+ if (vsf_sysutil_retval_is_error(opened_file))
+ {
+ http_error(p_sess, kVSFHttpMsgType403);
+ }
+ vsf_sysutil_close(opened_file);
+ }
+
+ return ret;
+}
+
+static void
+http_handle_send(struct vsf_session* p_sess, filesize_t p_size)
+{
+ http_header_print(p_sess, err_200_ok);
+ str_copy(&p_sess->ftp_arg_str, &p_sess->http_get_arg);
+ str_split_char(&p_sess->http_get_arg, &p_sess->ftp_cmd_str, '.');
+ str_upper(&p_sess->ftp_cmd_str);
+ if (str_equal_text(&p_sess->ftp_cmd_str, "HTML") ||
+ str_equal_text(&p_sess->ftp_cmd_str, "HTM"))
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, "Content-Type: text/html\r\n");
+ }
+ else
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, "Content-Type: dunno\r\n");
+ }
+ vsf_cmdio_write_raw_quiet(p_sess, "Content-Length: ");
+ vsf_cmdio_write_raw_quiet(p_sess, vsf_sysutil_filesize_t_to_str(p_size));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n\r\n");
+ p_sess->is_ascii = 0;
+ p_sess->restart_pos = 0;
+ process_http_retr(p_sess);
+}
+
+static void http_handle_browse(struct vsf_session* p_sess)
+{
+ struct vsf_sysutil_dir* p_dir = 0;
+ static struct vsf_sysutil_statbuf* s_p_dirstat;
+ int dir_allow_read = 1;
+ struct mystr_list dir_list = INIT_STRLIST;
+
+ p_dir = str_opendir(&p_sess->http_get_arg);
+ if (p_dir && tunable_anon_world_readable_only)
+ {
+ vsf_sysutil_dir_stat(p_dir, &s_p_dirstat);
+ if (!vsf_sysutil_statbuf_is_readable_other(s_p_dirstat))
+ {
+ dir_allow_read = 0;
+ }
+ }
+ if (p_dir != 0 && dir_allow_read)
+ {
+ static struct mystr s_option_str = INIT_MYSTR;
+ static struct mystr s_filter_str = INIT_MYSTR;
+
+ vsf_ls_populate_dir_list(p_sess, &dir_list, 0, p_dir, &p_sess->http_get_arg,
+ &s_option_str, &s_filter_str, 1, 1);
+ }
+ if (p_dir)
+ {
+ vsf_sysutil_closedir(p_dir);
+ }
+ if (!dir_allow_read)
+ {
+ http_error(p_sess, kVSFHttpMsgType403);
+ }
+ else
+ {
+ static struct mystr p_tpl = INIT_MYSTR;
+ static struct mystr p_res = INIT_MYSTR;
+
+ str_alloc_text(&p_tpl, vsf_http_messages_get(kVSFHttpMsgType200Browse));
+ str_process_template(p_sess, &p_res, &p_tpl, 0, 0, vsf_sysutil_get_time_sec(), &dir_list);
+ str_list_free(&dir_list);
+ http_html_content(p_sess, err_200_ok, &p_res);
+ }
+}
Index: oneprocess.c
===================================================================
--- oneprocess.c (revision 132)
+++ oneprocess.c (revision 140)
@@ -115,6 +115,10 @@
case kVSFLoginFail:
return;
break;
+ case kVSFLoginHTTPFail:
+ p_sess->is_anonymous = 0;
+ process_post_login(p_sess);
+ break;
case kVSFLoginAnon:
p_sess->is_anonymous = 1;
process_post_login(p_sess);
Index: sysutil.h
===================================================================
--- sysutil.h (revision 132)
+++ sysutil.h (revision 140)
@@ -30,7 +30,8 @@
kVSFSysUtilSigCHLD,
kVSFSysUtilSigPIPE,
kVSFSysUtilSigURG,
- kVSFSysUtilSigHUP
+ kVSFSysUtilSigHUP,
+ kVSFSysUtilSigUSR1
};
enum EVSFSysUtilInterruptContext
{
@@ -122,6 +123,7 @@
const struct vsf_sysutil_statbuf* p_stat);
const char* vsf_sysutil_statbuf_get_perms(
const struct vsf_sysutil_statbuf* p_stat);
+long vsf_sysutil_statbuf_get_filedate(const struct vsf_sysutil_statbuf* p_statbuf);
const char* vsf_sysutil_statbuf_get_date(
const struct vsf_sysutil_statbuf* p_stat, int use_localtime, long curr_time);
const char* vsf_sysutil_statbuf_get_numeric_date(
@@ -160,11 +162,13 @@
/* Memory allocating/freeing */
void* vsf_sysutil_malloc(unsigned int size);
+void* vsf_sysutil_malloc_zero(unsigned int size);
void* vsf_sysutil_realloc(void* p_ptr, unsigned int size);
void vsf_sysutil_free(void* p_ptr);
/* Process creation/exit/process handling */
unsigned int vsf_sysutil_getpid(void);
+unsigned int vsf_sysutil_getppid(void);
void vsf_sysutil_post_fork(void);
int vsf_sysutil_fork(void);
int vsf_sysutil_fork_failok(void);
@@ -182,10 +186,14 @@
const struct vsf_sysutil_wait_retval* p_waitret);
int vsf_sysutil_wait_get_exitcode(
const struct vsf_sysutil_wait_retval* p_waitret);
+void vsf_sysutil_sigaction(const enum EVSFSysUtilSignal sig, void (*p_handlefunc)(int));
+int vsf_sysutil_kill(int pid, int sig);
+int vsf_sysutil_pause();
/* Various string functions */
unsigned int vsf_sysutil_strlen(const char* p_text);
char* vsf_sysutil_strdup(const char* p_str);
+char* vsf_sysutil_strndup(const char* p_str, unsigned int p_len);
void vsf_sysutil_memclr(void* p_dest, unsigned int size);
void vsf_sysutil_memcpy(void* p_dest, const void* p_src,
const unsigned int size);
@@ -196,6 +204,7 @@
int vsf_sysutil_atoi(const char* p_str);
filesize_t vsf_sysutil_a_to_filesize_t(const char* p_str);
const char* vsf_sysutil_ulong_to_str(unsigned long the_ulong);
+const char* vsf_sysutil_ulong_to_hex(unsigned long the_ulong);
const char* vsf_sysutil_filesize_t_to_str(filesize_t the_filesize);
const char* vsf_sysutil_double_to_str(double the_double);
const char* vsf_sysutil_uint_to_octal(unsigned int the_uint);
@@ -205,6 +214,7 @@
int vsf_sysutil_isprint(int the_char);
int vsf_sysutil_isalnum(int the_char);
int vsf_sysutil_isdigit(int the_char);
+void vsf_sysutil_fillbuff(void* buff, unsigned int size, char chr);
/* Socket handling */
struct vsf_sysutil_sockaddr;
@@ -257,6 +267,7 @@
unsigned int wait_seconds);
void vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr,
const char* p_name);
+int vsf_sysutil_inet_addr_to_int(struct vsf_sysutil_sockaddr* p_addr);
/* Option setting on sockets */
void vsf_sysutil_activate_keepalive(int fd);
void vsf_sysutil_set_iptos_throughput(int fd);
@@ -303,7 +314,12 @@
void vsf_sysutil_make_session_leader(void);
void vsf_sysutil_reopen_standard_fds(void);
void vsf_sysutil_tzset(void);
-const char* vsf_sysutil_get_current_date(void);
+const char* vsf_sysutil_get_current_date(int use_localtime);
+const char* vsf_sysutil_get_datetimefmt(int use_localtime, long curr_time, const char* fmt);
+const char* vsf_sysutil_get_datetime(int use_localtime, long curr_time);
+const char* vsf_sysutil_get_date(int use_localtime, long curr_time);
+const char* vsf_sysutil_get_sdate(int use_localtime, long curr_time);
+const char* vsf_sysutil_get_time(int use_localtime, long curr_time);
void vsf_sysutil_qsort(void* p_base, unsigned int num_elem,
unsigned int elem_size,
int (*p_compar)(const void *, const void *));
Index: tunables.h
===================================================================
--- tunables.h (revision 132)
+++ tunables.h (revision 140)
@@ -73,6 +73,7 @@
extern int tunable_mdtm_write; /* Allow MDTM to set timestamps */
extern int tunable_lock_upload_files; /* Lock uploading files */
extern int tunable_pasv_addr_resolve; /* DNS resolve pasv_addr */
+extern int tunable_userlist_log; /* Log every failed login attempt */
extern int tunable_debug_ssl; /* Verbose SSL logging */
extern int tunable_require_cert; /* SSL client cert required */
extern int tunable_validate_cert; /* SSL certs must be valid */
@@ -87,6 +88,19 @@
extern int tunable_isolate_network; /* Use CLONE_NEWNET */
extern int tunable_ftp_enable; /* Allow FTP protocol */
extern int tunable_http_enable; /* Allow HTTP protocol */
+extern int tunable_http_browse; /* Allow browse directory when HTTP protocol enabled */
+extern int tunable_convert_charset_enable; /* Allow converting charsets for file names */
+extern int tunable_local_codepage; /* Code of local charset */
+extern int tunable_remote_codepage; /* Code of remote charset */
+extern int tunable_anon_delete_enable; /* Allow command DELE for anonymous */
+extern int tunable_add_default_rule; /* Add default rule if defined rules file */
+extern int tunable_chown_by_ip; /* Chown by IP */
+extern int tunable_tpm_allow_anon_root_access;/* Allow access to root by anonymous in two process model */
+extern int tunable_double_377; /* On/off double char \377 */
+extern int tunable_anon_rxtx_rate; /* On/off rx and tx rates for anon */
+extern int tunable_local_rxtx_rate; /* On/off rx and tx rates for local */
+extern int tunable_chown_group; /* Chown group */
+extern int tunable_anti_bruteforce; /* On/off anti bruteforce algoritm */
/* Integer/numeric defines */
extern unsigned int tunable_accept_timeout;
@@ -99,7 +113,11 @@
extern unsigned int tunable_pasv_min_port;
extern unsigned int tunable_pasv_max_port;
extern unsigned int tunable_anon_max_rate;
+extern unsigned int tunable_anon_max_rate_rx;
+extern unsigned int tunable_anon_max_rate_tx;
extern unsigned int tunable_local_max_rate;
+extern unsigned int tunable_local_max_rate_rx;
+extern unsigned int tunable_local_max_rate_tx;
extern unsigned int tunable_listen_port;
extern unsigned int tunable_max_clients;
extern unsigned int tunable_file_open_mode;
@@ -143,6 +161,16 @@
extern const char* tunable_dsa_private_key_file;
extern const char* tunable_ca_certs_file;
extern const char* tunable_cmds_denied;
+extern const char* tunable_local_charset;
+extern const char* tunable_remote_charset;
+extern const char* tunable_pasv_addr_rules;
+extern const char* tunable_users_access_ip;
+extern const char* tunable_anti_bruteforce_banner;
+extern const char* tunable_http_error_403_server_tpl;
+extern const char* tunable_http_error_403_tpl;
+extern const char* tunable_http_error_404_tpl;
+extern const char* tunable_http_browse_tpl;
+extern const char* tunable_http_browse_line_tpl;
#endif /* VSF_TUNABLES_H */
Index: http.h
===================================================================
--- http.h (revision 0)
+++ http.h (revision 140)
@@ -0,0 +1,10 @@
+#ifndef VSF_HTTP_H
+#define VSF_HTTP_H
+
+struct vsf_session;
+
+void handle_http(struct vsf_session* p_sess);
+void http_browse(struct vsf_session* p_sess, long curr_time);
+
+#endif /* VSF_HTTP_H */
+
Index: COPYRIGHT
===================================================================
--- COPYRIGHT (revision 132)
+++ COPYRIGHT (revision 140)
@@ -1,3 +1,3 @@
Everything within this tar archive is Copyright (c) Chris Evans, except
where otherwise noted in individual files.
-
+Additional fetures is Copyright (c) Dmitriy Balashov.
Index: Makefile
===================================================================
--- Makefile (revision 132)
+++ Makefile (revision 140)
@@ -5,7 +5,7 @@
#CFLAGS = -g
CFLAGS = -O2 -Wall -W -Wshadow #-pedantic -Werror -Wconversion
-LIBS = `./vsf_findlibs.sh`
+LIBS = -lwrap -lnsl -lpam -lcap -ldl -lcrypto
LINK = -Wl,-s
OBJS = main.o utility.o prelogin.o ftpcmdio.o postlogin.o privsock.o \
@@ -14,7 +14,8 @@
banner.o filestr.o parseconf.o secutil.o \
ascii.o oneprocess.o twoprocess.o privops.o standalone.o hash.o \
tcpwrap.o ipaddrparse.o access.o features.o readwrite.o opts.o \
- ssl.o sslslave.o ptracesandbox.o ftppolicy.o sysutil.o sysdeputil.o
+ ssl.o sslslave.o ptracesandbox.o ftppolicy.o sysutil.o sysdeputil.o \
+ charconv.o pasvrules.o usersip.o http.o http_msg.o http_str.o
.c.o:
Index: builddefs.h
===================================================================
--- builddefs.h (revision 132)
+++ builddefs.h (revision 140)
@@ -5,5 +5,10 @@
#define VSF_BUILD_PAM
#undef VSF_BUILD_SSL
+#define VSF_CONFIG_PATH "/etc/vsftpd/"
+#define VSF_CONFIG_PREFIX ""
+//#define VSF_CONFIG_PATH "/etc/"
+//#define VSF_CONFIG_PREFIX "vsftpd."
+
#endif /* VSF_BUILDDEFS_H */
Index: http_str.c
===================================================================
--- http_str.c (revision 0)
+++ http_str.c (revision 140)
@@ -0,0 +1,367 @@
+/*
+ * Part of Very Secure FTPd
+ * Licence: GPL v2
+ * Author: Dmitriy Balashov
+ * http_str.c
+ *
+ * HTTP messages.
+ */
+
+#include "defs.h"
+#include "http_str.h"
+#include "str.h"
+#include "strlist.h"
+#include "sysutil.h"
+#include "tunables.h"
+#include "charconv.h"
+#include "vsftpver.h"
+#include "session.h"
+#include "utility.h"
+
+#define digit_to_int(code) ((code < 'A') ? (code - '0') : ((code & ~0x20) - 'A' + 10))
+#define digits_to_int(code1, code2) ((digit_to_int(code1) << 4) | digit_to_int(code2))
+#define is_digit(code) ((code >= '0' && code <= '9') || ((code & ~0x20) >= 'A' && (code & ~0x20) <= 'F'))
+
+#define int_to_digit(code) ("0123456789abcdef"[code] + 0)
+
+static const unsigned char urlchr_table[256] =
+{
+ 1, 1, 1, 1, 1, 1, 1, 1, /* NUL SOH STX ETX EOT ENQ ACK BEL */
+ 1, 1, 1, 1, 1, 1, 1, 1, /* BS HT LF VT FF CR SO SI */
+ 1, 1, 1, 1, 1, 1, 1, 1, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
+ 1, 1, 1, 1, 1, 1, 1, 1, /* CAN EM SUB ESC FS GS RS US */
+ 1, 0, 1, 1, 0, 1, 0, 0, /* SP ! " # $ % & ' */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* ( ) * + , - . / */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
+ 0, 0, 1, 0, 1, 0, 1, 0, /* 8 9 : ; < = > ? */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
+ 0, 0, 0, 1, 1, 1, 1, 0, /* X Y Z [ \ ] ^ _ */
+ 1, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
+ 0, 0, 0, 1, 1, 1, 0, 1, /* x y z { | } ~ DEL */
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+void
+str_escape(struct mystr* p_str)
+{
+ const char* srcbuf;
+ unsigned int srclen;
+ char* dstbuf;
+ unsigned int srcpos = 0, dstpos = 0;
+ unsigned int char_code;
+
+ srclen = str_getlen(p_str); // Len of source string
+ srcbuf = str_getbuf(p_str);
+ dstbuf = vsf_sysutil_malloc(srclen * 3);
+
+ while (srcpos < srclen)
+ {
+ char_code = (unsigned char)srcbuf [srcpos++];
+
+ if (urlchr_table[char_code])
+ {
+ dstbuf [dstpos++] = '%';
+ dstbuf [dstpos++] = int_to_digit(char_code >> 4);
+ dstbuf [dstpos++] = int_to_digit(char_code & 0x0f);
+ }
+ else
+ {
+ dstbuf [dstpos++] = char_code;
+ }
+ }
+
+ dstbuf [dstpos] = '\0';
+
+ str_alloc_text(p_str, dstbuf);
+ vsf_sysutil_free(dstbuf);
+}
+
+void
+str_unescape(struct mystr* p_str)
+{
+ const char* srcbuf;
+ unsigned int srclen;
+ char* dstbuf;
+ unsigned int srcpos = 0, dstpos = 0;
+ unsigned int char_code, char2_code;
+
+ srclen = str_getlen(p_str); // Len of source string
+ srcbuf = str_getbuf(p_str);
+ dstbuf = vsf_sysutil_malloc(srclen+1);
+
+ while (srcpos < srclen)
+ {
+ char_code = (unsigned char)srcbuf [srcpos++];
+ if (char_code == '%' && srcpos < (srclen - 2) &&
+ is_digit(srcbuf [srcpos]) && is_digit(srcbuf [srcpos+1]))
+ {
+ char_code = srcbuf [srcpos++];
+ char2_code = srcbuf [srcpos++];
+ dstbuf [dstpos++] = digits_to_int (char_code, char2_code);
+ }
+ else
+ {
+ dstbuf [dstpos++] = char_code;
+ }
+ }
+
+ dstbuf [dstpos] = '\0';
+
+ str_alloc_text(p_str, dstbuf);
+ vsf_sysutil_free(dstbuf);
+}
+
+void
+str_process_template(struct vsf_session* p_sess,
+ struct mystr* p_str,
+ struct mystr* p_tpl,
+ const struct mystr* p_filename,
+ const struct vsf_sysutil_statbuf* p_stat,
+ long curr_time,
+ struct mystr_list* p_dir)
+{
+ static struct mystr s_lhs_chunk_str;
+ static struct mystr s_rhs_chunk_str;
+ char cmd;
+ filesize_t size;
+ long f_time;
+
+ if (p_stat)
+ {
+ f_time = vsf_sysutil_statbuf_get_filedate(p_stat);
+ size = vsf_sysutil_statbuf_get_size(p_stat);
+ }
+ else
+ {
+ f_time = curr_time;
+ size = 0;
+ }
+
+ str_free(p_str);
+ str_reserve(p_str, VSFTP_DIR_BUFSIZE);
+ str_copy(&s_lhs_chunk_str, p_tpl);
+
+ while (str_getlen(&s_lhs_chunk_str) > 0)
+ {
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, '%');
+ str_append_str(p_str, &s_lhs_chunk_str);
+ if (str_getlen(&s_rhs_chunk_str) > 0)
+ {
+ cmd = str_del_char_at(&s_rhs_chunk_str, 0);
+
+ if (p_filename && str_getlen(p_filename) > 0)
+ {
+ static struct mystr p_tmp_str = INIT_MYSTR;
+ switch (cmd)
+ {
+ case 'i':
+ case 'I':
+ str_append_str(p_str, p_filename);
+ break;
+ case 'd': // Date
+ str_append_text(p_str, vsf_sysutil_get_sdate(tunable_use_localtime, f_time));
+ break;
+ case 'D': // Full date time in format
+ str_append_text(p_str, vsf_sysutil_get_datetime(tunable_use_localtime, f_time));
+ break;
+ case 't': // Time
+ str_append_text(p_str, vsf_sysutil_get_time(tunable_use_localtime, f_time));
+ break;
+ case 'T': // Date time if FTP format
+ str_append_text(p_str, vsf_sysutil_statbuf_get_date(p_stat,
+ tunable_use_localtime,
+ curr_time));
+ break;
+ case 'p':
+ case 'P': // Permissions as in FTP
+ str_append_text(p_str, vsf_sysutil_statbuf_get_perms(p_stat));
+ break;
+ case 'f':
+ case 'F': // File/Dir/Link
+ if (vsf_sysutil_statbuf_is_dir(p_stat))
+ {
+ str_append_text(p_str, "dir");
+ }
+ else
+ if (vsf_sysutil_statbuf_is_symlink(p_stat))
+ {
+ str_append_text(p_str, "link");
+ }
+ else
+ if (vsf_sysutil_statbuf_is_regfile(p_stat))
+ {
+ str_append_text(p_str, "file");
+ }
+ else
+ if (vsf_sysutil_statbuf_is_socket(p_stat))
+ {
+ str_append_text(p_str, "sock");
+ }
+ else
+ {
+ str_append_text(p_str, "unk");
+ }
+ break;
+ case 'l':
+ case 'L': // Link?
+ str_copy(&p_tmp_str, p_filename);
+ str_escape(&p_tmp_str);
+ str_append_str(p_str, &p_tmp_str);
+ if (vsf_sysutil_statbuf_is_dir(p_stat))
+ {
+ str_append_text(p_str, "/");
+ }
+ break;
+ case 's': // File size in bytes
+ if (vsf_sysutil_statbuf_is_regfile(p_stat))
+ {
+ str_append_filesize_t(p_str, size);
+ }
+ else
+ {
+ str_append_text(p_str, " ");
+ }
+ break;
+ case 'S': // File size in Kbytes
+ if (vsf_sysutil_statbuf_is_regfile(p_stat))
+ {
+ str_append_filesize_t(p_str, (size+512)/1024);
+ str_append_char(p_str, 'K');
+ }
+ else
+ {
+ str_append_text(p_str, " ");
+ }
+ break;
+ case 'u':
+ case 'U': // User
+ str_getuser(&p_tmp_str, p_stat);
+ str_append_str(p_str, &p_tmp_str);
+ break;
+ case 'g':
+ case 'G': // Group
+ str_getgroup(&p_tmp_str, p_stat);
+ str_append_str(p_str, &p_tmp_str);
+ break;
+ default:
+ str_append_char(p_str, '%');
+ str_append_char(p_str, cmd);
+ break;
+ }
+ }
+ else
+ {
+ switch (cmd)
+ {
+ case 'b':
+ case 'B':
+ if (p_dir)
+ {
+ unsigned int dir_index_max = str_list_get_length(p_dir);
+ unsigned int dir_index;
+
+ for (dir_index = 0; dir_index < dir_index_max; dir_index++)
+ {
+ str_append_str(p_str, str_list_get_pstr(p_dir, dir_index));
+ }
+ }
+ /// Browse directory
+ break;
+ case 'r':
+ case 'R':
+ str_append_str(p_str, &p_sess->http_get_arg);
+ break;
+ case 'd':
+ str_append_text(p_str, vsf_sysutil_get_sdate(tunable_use_localtime, curr_time));
+ break;
+ case 'D':
+ str_append_text(p_str, vsf_sysutil_get_date(tunable_use_localtime, curr_time));
+ break;
+ case 't':
+ str_append_text(p_str, vsf_sysutil_get_time(tunable_use_localtime, curr_time));
+ break;
+ case 'T':
+ str_append_text(p_str, vsf_sysutil_get_datetime(tunable_use_localtime, curr_time));
+ break;
+ case 'v':
+ str_append_text(p_str, "vsFTPd");
+ break;
+ case 'V':
+ str_append_text(p_str, "vsFTPd " VSF_VERSION);
+ break;
+ default:
+ str_append_char(p_str, '%');
+ str_append_char(p_str, cmd);
+ break;
+ }
+ }
+ }
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ }
+}
+
+void
+str_getuser(struct mystr* p_str, const struct vsf_sysutil_statbuf* p_stat)
+{
+ if (tunable_hide_ids)
+ {
+ str_alloc_text(p_str, "ftp");
+ }
+ else
+ {
+ int uid = vsf_sysutil_statbuf_get_uid(p_stat);
+ struct vsf_sysutil_user* p_user = 0;
+ if (tunable_text_userdb_names)
+ {
+ p_user = vsf_sysutil_getpwuid(uid);
+ }
+ if (p_user == 0)
+ {
+ str_alloc_ulong(p_str, (unsigned long) uid);
+ }
+ else
+ {
+ str_alloc_text(p_str, vsf_sysutil_user_getname(p_user));
+ }
+ }
+}
+
+void
+str_getgroup(struct mystr* p_str, const struct vsf_sysutil_statbuf* p_stat)
+{
+ if (tunable_hide_ids)
+ {
+ str_alloc_text(p_str, "ftp");
+ }
+ else
+ {
+ int gid = vsf_sysutil_statbuf_get_gid(p_stat);
+ struct vsf_sysutil_group* p_group = 0;
+ if (tunable_text_userdb_names)
+ {
+ p_group = vsf_sysutil_getgrgid(gid);
+ }
+ if (p_group == 0)
+ {
+ str_alloc_ulong(p_str, (unsigned long) gid);
+ }
+ else
+ {
+ str_alloc_text(p_str, vsf_sysutil_group_getname(p_group));
+ }
+ }
+}
+
Index: str.c
===================================================================
--- str.c (revision 132)
+++ str.c (revision 140)
@@ -19,6 +19,7 @@
/* Ick. Its for die() */
#include "utility.h"
#include "sysutil.h"
+#include "charconv.h"
/* File local functions */
static void str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
@@ -89,6 +90,18 @@
return vsf_sysutil_strdup(str_getbuf(p_str));
}
+const char*
+str_strdup_trimmed(const struct mystr* p_str)
+{
+ const char* p_trimmed = str_getbuf(p_str);
+ int h, t, newlen;
+
+ for (h = 0; h < (int)str_getlen(p_str) && vsf_sysutil_isspace(p_trimmed[h]); h++);
+ for (t = str_getlen(p_str) - 1; t >= 0 && vsf_sysutil_isspace(p_trimmed[t]); t--);
+ newlen = t - h + 1;
+ return newlen ? vsf_sysutil_strndup(p_trimmed+h, (unsigned int)newlen) : 0L;
+}
+
void
str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term)
{
@@ -109,6 +122,12 @@
}
void
+str_alloc_ulong_hex(struct mystr* p_str, unsigned long the_long)
+{
+ str_alloc_text(p_str, vsf_sysutil_ulong_to_hex(the_long));
+}
+
+void
str_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize)
{
str_alloc_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
@@ -223,6 +242,35 @@
return (str_equal_internal(p_str->p_buf, p_str->len, p_text, cmplen) == 0);
}
+int
+str_equal_str(const char* p_str1, const char* p_str2)
+{
+ unsigned int strlen1 = vsf_sysutil_strlen(p_str1);
+ unsigned int strlen2 = vsf_sysutil_strlen(p_str2);
+ return (str_equal_internal(p_str1, strlen1, p_str2, strlen2) == 0);
+}
+
+int
+str_equal_bool(struct mystr* p_str)
+{
+ str_upper(p_str);
+ if (str_equal_text(p_str, "YES") ||
+ str_equal_text(p_str, "TRUE") ||
+ str_equal_text(p_str, "1"))
+ {
+ return 1;
+ }
+ else
+ if (str_equal_text(p_str, "NO") ||
+ str_equal_text(p_str, "FALSE") ||
+ str_equal_text(p_str, "0"))
+ {
+ return 0;
+ }
+ else
+ return -1;
+}
+
void
str_append_str(struct mystr* p_str, const struct mystr* p_other)
{
@@ -249,6 +297,12 @@
}
void
+str_append_ulong_hex(struct mystr* p_str, unsigned long the_ulong)
+{
+ str_append_text(p_str, vsf_sysutil_ulong_to_hex(the_ulong));
+}
+
+void
str_append_filesize_t(struct mystr* p_str, filesize_t the_filesize)
{
str_append_text(p_str, vsf_sysutil_filesize_t_to_str(the_filesize));
@@ -342,6 +396,40 @@
}
void
+str_trim_char(struct mystr* p_str, char chr)
+{
+ const char* srcbuf;
+ unsigned int srclen;
+ char* dstbuf;
+ unsigned int srcpos = 0, dstpos = 0;
+ char oldchr = '\0';
+
+ srclen = str_getlen(p_str); // Len of source string
+ srcbuf = str_getbuf(p_str);
+
+ dstbuf = vsf_sysutil_malloc(srclen);
+
+ while (srcpos < srclen)
+ {
+ if (srcbuf[srcpos] == chr && oldchr == srcbuf[srcpos]) {
+ srcpos++;
+ continue;
+ }
+
+ dstbuf[dstpos] = oldchr = srcbuf[srcpos];
+ srcpos++;
+ dstpos++;
+ }
+
+ dstbuf [dstpos] = '\0';
+
+ str_empty(p_str);
+ str_append_text(p_str, dstbuf);
+
+ vsf_sysutil_free(dstbuf);
+}
+
+void
str_split_char(struct mystr* p_src, struct mystr* p_rhs, char c)
{
/* Just use str_split_text */
@@ -399,7 +487,7 @@
if (indexx + search_len > p_src->len)
{
bug("indexx invalid in str_split_text");
- }
+ }
/* Build rhs */
private_str_alloc_memchunk(p_rhs, p_src->p_buf + indexx + search_len,
p_src->len - indexx - search_len);
@@ -559,6 +647,32 @@
return p_str->p_buf[indexx];
}
+char
+str_del_char_at(struct mystr* p_str, const unsigned int indexx)
+{
+ static struct mystr buf = INIT_MYSTR;
+ char del_char;
+
+ if (indexx >= p_str->len)
+ {
+ bug("bad indexx in str_del_char_at");
+ }
+
+ del_char = p_str->p_buf[indexx];
+ private_str_alloc_memchunk(&buf, "\0", 0);
+ if (indexx > 0)
+ {
+ private_str_append_memchunk(&buf, p_str->p_buf, indexx);
+ }
+ if (indexx < p_str->len)
+ {
+ private_str_append_memchunk(&buf, p_str->p_buf + indexx + 1, p_str->len - indexx - 1);
+ }
+ str_copy(p_str, &buf);
+ str_free(&buf);
+ return del_char;
+}
+
int
str_contains_space(const struct mystr* p_str)
{
@@ -601,6 +715,18 @@
return 0;
}
+void
+str_basename (struct mystr* d_str, const struct mystr* path)
+{
+ static struct mystr tmp = INIT_MYSTR;
+
+ str_copy (&tmp, path);
+ str_split_char_reverse(&tmp, d_str, '/');
+
+ if (str_isempty(d_str))
+ str_copy (d_str, path);
+}
+
int
str_atoi(const struct mystr* p_str)
{
@@ -670,12 +796,16 @@
void
str_replace_unprintable(struct mystr* p_str, char new_char)
{
- unsigned int i;
- for (i=0; i < p_str->len; i++)
+ if (localMap) vsf_charconv_replace_unprintable(p_str, new_char);
+ else
{
- if (!vsf_sysutil_isprint(p_str->p_buf[i]))
+ unsigned int i;
+ for (i=0; i < p_str->len; i++)
{
- p_str->p_buf[i] = new_char;
+ if (!vsf_sysutil_isprint(p_str->p_buf[i]))
+ {
+ p_str->p_buf[i] = new_char;
+ }
}
}
}
Index: EXAMPLE/HTTP_TEMPLATES/browse.html
===================================================================
--- EXAMPLE/HTTP_TEMPLATES/browse.html (revision 0)
+++ EXAMPLE/HTTP_TEMPLATES/browse.html (revision 140)
@@ -0,0 +1,84 @@
+
+
+
+ Index of %r
+
+
+
+
+
+
+
Index of %r
+
+
+
+ |
+ Name |
+ Size |
+ Last Modified |
+
+
+
+%b
+
+
+
+
Generated %T by %V
+
+
+
Index: EXAMPLE/HTTP_TEMPLATES/403-serv.html
===================================================================
--- EXAMPLE/HTTP_TEMPLATES/403-serv.html (revision 0)
+++ EXAMPLE/HTTP_TEMPLATES/403-serv.html (revision 140)
@@ -0,0 +1,55 @@
+
+
+
+ 403 Forbidden
+
+
+
+
+
+
+
Forbidden
+
You don't have permission to access this server.
+
+
Generated %T by %V
+
+
+
Index: EXAMPLE/HTTP_TEMPLATES/403.html
===================================================================
--- EXAMPLE/HTTP_TEMPLATES/403.html (revision 0)
+++ EXAMPLE/HTTP_TEMPLATES/403.html (revision 140)
@@ -0,0 +1,55 @@
+
+
+
+ 403 Forbidden
+
+
+
+
+
+
+
Forbidden
+
You don't have permission to access %r on this server.
+
+
Generated %T by %V
+
+
+
Index: EXAMPLE/HTTP_TEMPLATES/404.html
===================================================================
--- EXAMPLE/HTTP_TEMPLATES/404.html (revision 0)
+++ EXAMPLE/HTTP_TEMPLATES/404.html (revision 140)
@@ -0,0 +1,55 @@
+
+
+
+ 404 Not Found
+
+
+
+
+
+
+
Not Found
+
The requested URL %r was not found on this server.
+
+
Generated %T by %V
+
+
+
Index: EXAMPLE/HTTP_TEMPLATES/browse_line.html
===================================================================
--- EXAMPLE/HTTP_TEMPLATES/browse_line.html (revision 0)
+++ EXAMPLE/HTTP_TEMPLATES/browse_line.html (revision 140)
@@ -0,0 +1,7 @@
+
+ [%f] |
+ |
+ %S |
+ %d |
+ %t |
+
Index: http_str.h
===================================================================
--- http_str.h (revision 0)
+++ http_str.h (revision 140)
@@ -0,0 +1,22 @@
+#ifndef VSF_HTTP_STR_H
+#define VSF_HTTP_STR_H
+
+struct mystr;
+struct vsf_sysutil_statbuf;
+struct vsf_session;
+struct mystr_list;
+
+void str_escape(struct mystr* p_str);
+void str_unescape(struct mystr* p_str);
+void str_process_template(struct vsf_session* p_sess,
+ struct mystr* p_str,
+ struct mystr* p_tpl,
+ const struct mystr* p_filename,
+ const struct vsf_sysutil_statbuf* p_stat,
+ long curr_time,
+ struct mystr_list* p_dir);
+void str_getuser(struct mystr* p_str, const struct vsf_sysutil_statbuf* p_stat);
+void str_getgroup(struct mystr* p_str, const struct vsf_sysutil_statbuf* p_stat);
+
+#endif /* VSF_HTTP_STR_H */
+
Index: str.h
===================================================================
--- str.h (revision 132)
+++ str.h (revision 140)
@@ -28,9 +28,11 @@
/* NOTE: String buffer data does NOT include terminating character */
void str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term);
void str_alloc_ulong(struct mystr* p_str, unsigned long the_ulong);
+void str_alloc_ulong_hex(struct mystr* p_str, unsigned long the_ulong);
void str_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize);
void str_copy(struct mystr* p_dest, const struct mystr* p_src);
const char* str_strdup(const struct mystr* p_str);
+const char* str_strdup_trimmed(const struct mystr* p_str);
void str_empty(struct mystr* p_str);
void str_free(struct mystr* p_str);
void str_trunc(struct mystr* p_str, unsigned int trunc_len);
@@ -43,10 +45,13 @@
int str_strcmp(const struct mystr* p_str1, const struct mystr* p_str2);
int str_equal(const struct mystr* p_str1, const struct mystr* p_str2);
int str_equal_text(const struct mystr* p_str, const char* p_text);
+int str_equal_str(const char* p_str1, const char* p_str2);
+int str_equal_bool(struct mystr* p_str);
void str_append_str(struct mystr* p_str, const struct mystr* p_other);
void str_append_text(struct mystr* p_str, const char* p_src);
void str_append_ulong(struct mystr* p_str, unsigned long the_long);
+void str_append_ulong_hex(struct mystr* p_str, unsigned long the_long);
void str_append_filesize_t(struct mystr* p_str, filesize_t the_filesize);
void str_append_char(struct mystr* p_str, char the_char);
void str_append_double(struct mystr* p_str, double the_double);
@@ -58,6 +63,8 @@
void str_replace_text(struct mystr* p_str, const char* p_from,
const char* p_to);
+void str_trim_char(struct mystr* p_str, char chr);
+
void str_split_char(struct mystr* p_src, struct mystr* p_rhs, char c);
void str_split_char_reverse(struct mystr* p_src, struct mystr* p_rhs, char c);
void str_split_text(struct mystr* p_src, struct mystr* p_rhs,
@@ -93,10 +100,12 @@
unsigned int indexx);
char str_get_char_at(const struct mystr* p_str, const unsigned int indexx);
+char str_del_char_at(struct mystr* p_str, const unsigned int indexx);
int str_contains_space(const struct mystr* p_str);
int str_all_space(const struct mystr* p_str);
int str_contains_unprintable(const struct mystr* p_str);
void str_replace_unprintable(struct mystr* p_str, char new_char);
+void str_basename (struct mystr* d_str, const struct mystr* path);
int str_atoi(const struct mystr* p_str);
filesize_t str_a_to_filesize_t(const struct mystr* p_str);
unsigned int str_octal_to_uint(const struct mystr* p_str);
Index: parseconf.c
===================================================================
--- parseconf.c (revision 132)
+++ parseconf.c (revision 140)
@@ -91,6 +91,7 @@
{ "mdtm_write", &tunable_mdtm_write },
{ "lock_upload_files", &tunable_lock_upload_files },
{ "pasv_addr_resolve", &tunable_pasv_addr_resolve },
+ { "userlist_log", &tunable_userlist_log },
{ "debug_ssl", &tunable_debug_ssl },
{ "require_cert", &tunable_require_cert },
{ "validate_cert", &tunable_validate_cert },
@@ -105,6 +106,17 @@
{ "isolate_network", &tunable_isolate_network },
{ "ftp_enable", &tunable_ftp_enable },
{ "http_enable", &tunable_http_enable },
+ { "http_browse", &tunable_http_browse },
+ { "convert_charset_enable", &tunable_convert_charset_enable },
+ { "anon_delete_enable", &tunable_anon_delete_enable },
+ { "add_default_rule", &tunable_add_default_rule },
+ { "chown_by_ip", &tunable_chown_by_ip },
+ { "tpm_allow_anon_root_access", &tunable_tpm_allow_anon_root_access },
+ { "double_377", &tunable_double_377 },
+ { "anon_rxtx_rate", &tunable_anon_rxtx_rate },
+ { "local_rxtx_rate", &tunable_local_rxtx_rate },
+ { "chown_group", &tunable_chown_group },
+ { "anti_bruteforce", &tunable_anti_bruteforce },
{ 0, 0 }
};
@@ -135,6 +147,10 @@
{ "delay_successful_login", &tunable_delay_successful_login },
{ "max_login_fails", &tunable_max_login_fails },
{ "chown_upload_mode", &tunable_chown_upload_mode },
+ { "anon_max_rate_rx", &tunable_anon_max_rate_rx },
+ { "anon_max_rate_tx", &tunable_anon_max_rate_tx },
+ { "local_max_rate_rx", &tunable_local_max_rate_rx },
+ { "local_max_rate_tx", &tunable_local_max_rate_tx },
{ 0, 0 }
};
@@ -177,6 +193,16 @@
{ "dsa_private_key_file", &tunable_dsa_private_key_file },
{ "ca_certs_file", &tunable_ca_certs_file },
{ "cmds_denied", &tunable_cmds_denied },
+ { "local_charset", &tunable_local_charset },
+ { "remote_charset", &tunable_remote_charset },
+ { "pasv_addr_rules", &tunable_pasv_addr_rules },
+ { "users_access_ip", &tunable_users_access_ip },
+ { "anti_bruteforce_banner", &tunable_anti_bruteforce_banner },
+ { "http_error_403_server_tpl", &tunable_http_error_403_server_tpl },
+ { "http_error_403_tpl", &tunable_http_error_403_tpl },
+ { "http_error_404_tpl", &tunable_http_error_404_tpl },
+ { "http_browse_tpl", &tunable_http_browse_tpl },
+ { "http_browse_line_tpl", &tunable_http_browse_line_tpl },
{ 0, 0 }
};
@@ -277,7 +303,7 @@
}
else
{
- *p_curr_setting = str_strdup(&s_value_str);
+ *p_curr_setting = str_strdup_trimmed(&s_value_str);
}
return;
}
@@ -298,24 +324,17 @@
/* Is it a boolean value? */
{
const struct parseconf_bool_setting* p_bool_setting = parseconf_bool_array;
+ int res_bool;
while (p_bool_setting->p_setting_name != 0)
{
if (str_equal_text(&s_setting_str, p_bool_setting->p_setting_name))
{
/* Got it */
- str_upper(&s_value_str);
- if (str_equal_text(&s_value_str, "YES") ||
- str_equal_text(&s_value_str, "TRUE") ||
- str_equal_text(&s_value_str, "1"))
+ res_bool = str_equal_bool(&s_value_str);
+ if (res_bool >= 0)
{
- *(p_bool_setting->p_variable) = 1;
+ *(p_bool_setting->p_variable) = res_bool;
}
- else if (str_equal_text(&s_value_str, "NO") ||
- str_equal_text(&s_value_str, "FALSE") ||
- str_equal_text(&s_value_str, "0"))
- {
- *(p_bool_setting->p_variable) = 0;
- }
else if (errs_fatal)
{
die2("bad bool value in config file for: ",
Index: vsftpver.h
===================================================================
--- vsftpver.h (revision 132)
+++ vsftpver.h (revision 140)
@@ -1,7 +1,7 @@
#ifndef VSF_VERSION_H
#define VSF_VERSION_H
-#define VSF_VERSION "2.3.4"
+#define VSF_VERSION "2.3.4+ (ext.1)"
#endif /* VSF_VERSION_H */
Index: opts.c
===================================================================
--- opts.c (revision 132)
+++ opts.c (revision 140)
@@ -2,6 +2,7 @@
* Part of Very Secure FTPd
* Licence: GPL v2
* Author: Chris Evans
+ * Extended: Dmitriy Balashov
* opts.c
*
* Routines to handle OPTS.
@@ -10,11 +11,54 @@
#include "ftpcodes.h"
#include "ftpcmdio.h"
#include "session.h"
+#include "tunables.h"
+#include "charconv.h"
void
handle_opts(struct vsf_session* p_sess)
{
+ struct mystr opts = INIT_MYSTR;
+ struct mystr prm = INIT_MYSTR;
+
str_upper(&p_sess->ftp_arg_str);
+ str_copy(&opts, &p_sess->ftp_arg_str);
+ str_split_char(&opts, &prm, ' ');
+
+ if (tunable_convert_charset_enable && str_equal_text(&opts, "UTF8"))
+ {
+ if (str_equal_text(&prm, "ON"))
+ {
+ p_sess->remote_charset = vsf_charconv_codepage(VSFTP_CP_UTF8);
+ p_sess->enable_convertion = vsf_charconv_avail_convertion(tunable_local_codepage, p_sess->remote_charset);
+ vsf_cmdio_write(p_sess, FTP_OPTSOK, "UTF8 option is On.");
+ }
+ else
+ if (str_equal_text(&prm, "OFF"))
+ {
+ p_sess->remote_charset = tunable_remote_codepage;
+ p_sess->enable_convertion = vsf_charconv_avail_convertion(tunable_local_codepage, p_sess->remote_charset);
+ vsf_cmdio_write(p_sess, FTP_OPTSOK, "UTF8 option is Off.");
+ }
+ else
+ {
+ vsf_cmdio_write(p_sess, FTP_BADOPTS, "Invalid UTF8 option.");
+ }
+ }
+ else
+ if (str_equal_text(&opts, "CP"))
+ {
+ if (vsf_charconv_avail_convertion(tunable_local_codepage, vsf_charconv_codepage(str_getbuf(&prm))))
+ {
+ vsf_cmdio_write(p_sess, FTP_OPTSOK, "Codepage changed.");
+ p_sess->remote_charset = vsf_charconv_codepage(str_getbuf(&prm));
+ p_sess->enable_convertion = 1;
+ }
+ else
+ {
+ vsf_cmdio_write(p_sess, FTP_BADOPTS, "Bad codepage defined");
+ }
+ }
+ else
if (str_equal_text(&p_sess->ftp_arg_str, "UTF8 ON"))
{
vsf_cmdio_write(p_sess, FTP_OPTSOK, "Always in UTF8 mode.");
@@ -23,5 +67,7 @@
{
vsf_cmdio_write(p_sess, FTP_BADOPTS, "Option not understood.");
}
+
+ str_free(&opts);
+ str_free(&prm);
}
-
Index: vsf_findlibs.sh
===================================================================
--- vsf_findlibs.sh (revision 132)
+++ vsf_findlibs.sh (revision 140)
@@ -1,70 +1,72 @@
#!/bin/sh
# Cheesy hacky location of additional link libraries.
+if [ -d "/lib64" ]; then
+ lib="lib64"
+else
+ lib="lib"
+fi
+
locate_library() { [ ! "$1*" = "`echo $1*`" ]; }
find_func() { egrep $1 $2 >/dev/null; }
if find_func hosts_access tcpwrap.o; then
echo "-lwrap";
- locate_library /lib/libnsl.so && echo "-lnsl";
- locate_library /lib64/libnsl.so && echo "-lnsl";
+ locate_library /$lib/libnsl.so && echo "-lnsl";
fi
# Look for PAM (done weirdly due to distribution bugs (e.g. Debian) or the
# crypt library.
if find_func pam_start sysdeputil.o; then
- locate_library /lib/libpam.so.0 && echo "/lib/libpam.so.0";
- locate_library /usr/lib/libpam.so && echo "-lpam";
- locate_library /usr/lib64/libpam.so && echo "-lpam";
+ locate_library /$lib/libpam.so.0 && echo "/$lib/libpam.so.0";
+ locate_library /usr/$lib/libpam.so && echo "-lpam";
# HP-UX ends shared libraries with .sl
- locate_library /usr/lib/libpam.sl && echo "-lpam";
+ locate_library /usr/$lib/libpam.sl && echo "-lpam";
# AIX ends shared libraries with .a
- locate_library /usr/lib/libpam.a && echo "-lpam";
+ locate_library /usr/$lib/libpam.a && echo "-lpam";
else
- locate_library /lib/libcrypt.so && echo "-lcrypt";
- locate_library /usr/lib/libcrypt.so && echo "-lcrypt";
- locate_library /usr/lib64/libcrypt.so && echo "-lcrypt";
+ locate_library /$lib/libcrypt.so && echo "-lcrypt";
+ locate_library /usr/$lib/libcrypt.so && echo "-lcrypt";
fi
# Look for the dynamic linker library. Needed by older RedHat when
# you link in PAM
-locate_library /lib/libdl.so && echo "-ldl";
+locate_library /$lib/libdl.so && echo "-ldl";
# Look for libsocket. Solaris needs this.
-locate_library /lib/libsocket.so && echo "-lsocket";
+locate_library /$lib/libsocket.so && echo "-lsocket";
# Look for libnsl. Solaris needs this.
-locate_library /lib/libnsl.so && echo "-lnsl";
+locate_library /$lib/libnsl.so && echo "-lnsl";
# Look for libresolv. Solaris needs this.
-locate_library /lib/libresolv.so && echo "-lresolv";
+locate_library /$lib/libresolv.so && echo "-lresolv";
# Look for libutil. Older FreeBSD need this for setproctitle().
-locate_library /usr/lib/libutil.so && echo "-lutil";
+locate_library /usr/$lib/libutil.so && echo "-lutil";
# For older HP-UX...
-locate_library /usr/lib/libsec.sl && echo "-lsec";
+locate_library /usr/$lib/libsec.sl && echo "-lsec";
# Look for libcap (capabilities)
-if locate_library /lib/libcap.so.1; then
- echo "/lib/libcap.so.1";
-elif locate_library /lib/libcap.so.2; then
- echo "/lib/libcap.so.2";
+if locate_library /$lib/libcap.so.1; then
+ echo "/$lib/libcap.so.1";
+elif locate_library /$lib/libcap.so.2; then
+ echo "/$lib/libcap.so.2";
else
- locate_library /usr/lib/libcap.so && echo "-lcap";
- locate_library /lib/libcap.so && echo "-lcap";
- locate_library /lib64/libcap.so && echo "-lcap";
+ locate_library /usr/$lib/libcap.so && echo "-lcap";
+ locate_library /$lib/libcap.so && echo "-lcap";
fi
# Solaris needs this for nanosleep()..
-locate_library /lib/libposix4.so && echo "-lposix4";
-locate_library /usr/lib/libposix4.so && echo "-lposix4";
+locate_library /$lib/libposix4.so && echo "-lposix4";
+locate_library /usr/$lib/libposix4.so && echo "-lposix4";
# Tru64 (nanosleep)
locate_library /usr/shlib/librt.so && echo "-lrt";
# Solaris sendfile
-locate_library /usr/lib/libsendfile.so && echo "-lsendfile";
+locate_library /usr/$lib/libsendfile.so && echo "-lsendfile";
# OpenSSL
if find_func SSL_library_init ssl.o; then
Index: ssl.c
===================================================================
--- ssl.c (revision 132)
+++ ssl.c (revision 140)
@@ -552,7 +552,11 @@
if (tunable_debug_ssl)
{
const char* p_ssl_version = SSL_get_cipher_version(p_ssl);
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ const SSL_CIPHER* p_ssl_cipher = SSL_get_current_cipher(p_ssl);
+#else
SSL_CIPHER* p_ssl_cipher = SSL_get_current_cipher(p_ssl);
+#endif
const char* p_cipher_name = SSL_CIPHER_get_name(p_ssl_cipher);
X509* p_ssl_cert = SSL_get_peer_certificate(p_ssl);
int reused = SSL_session_reused(p_ssl);
Index: sysdeputil.c
===================================================================
--- sysdeputil.c (revision 132)
+++ sysdeputil.c (revision 140)
@@ -16,6 +16,10 @@
#include "tunables.h"
#include "builddefs.h"
+/* For gethostbyaddr, inet_addr */
+#include
+#include
+
/* For Linux, this adds nothing :-) */
#include "port/porting_junk.h"
@@ -65,8 +69,6 @@
/* BEGIN config */
#if defined(__linux__)
- #include
- #include
#define VSF_SYSDEP_HAVE_LINUX_CLONE
#include
#ifndef CLONE_NEWPID
@@ -181,7 +183,6 @@
#include
#if defined(VSF_SYSDEP_HAVE_CAPABILITIES) && !defined(VSF_SYSDEP_HAVE_LIBCAP)
-#include
#include
#include
#include
@@ -323,6 +324,10 @@
const struct mystr* p_remote_host)
{
int retval;
+#ifdef PAM_RHOST
+ struct sockaddr_in sin;
+ struct hostent *host;
+#endif
pam_item_t item;
const char* pam_user_name = 0;
struct pam_conv the_conv =
@@ -343,7 +348,12 @@
return 0;
}
#ifdef PAM_RHOST
- retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host));
+ sin.sin_addr.s_addr = inet_addr(str_getbuf(p_remote_host));
+ host = gethostbyaddr((char*)&sin.sin_addr.s_addr,sizeof(struct in_addr),AF_INET);
+ if (host != (struct hostent*)0)
+ retval = pam_set_item(s_pamh, PAM_RHOST, host->h_name);
+ else
+ retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host));
if (retval != PAM_SUCCESS)
{
(void) pam_end(s_pamh, retval);
Index: Changelog
===================================================================
--- Changelog (revision 132)
+++ Changelog (revision 140)
@@ -1259,3 +1259,33 @@
At this point: v2.3.4 released!
===============================
+Extended builds:
+- Added char convertion for Western, Central, Soutern and Cyrillic encoding.
+For use this feature added local_charset, remote_charset and
+convert_charset_enable.
+By default convert_charset_enable is undefined.
+- Added anonymous access rights. For use this feature added pasv_addr_rules.
+By default vsftpd uses /etc/vsftpd.pasv_rules. Used next file format:
+ [remote_charset] [anonymous_enable
+[anon_upload_enable [anon_mkdir_write_enable [anon_other_write_enable
+[anon_delete_enable]]]]]
+- Added local users access rights. For use this feature added users_access_ip.
+By default vsftpd uses /etc/vsftpd.users_ip. Used next file format:
+ [CodePage] [ ...]
+- To command STAT added information about char convertion.
+- Added command OPTS with arguments UTF8 (values ON or OFF) and CP.
+- Fixed writing to log unprintable chars. For this used char convertion
+mechanism.
+- Allow or disallow delete files by anonymous. This feature work if defined
+anon_delete_enable.
+- Added chowning anonymous uploaded files by user IP.
+- Changed authentication user id in xferlog to file owner uid.
+- Allow or disallow write to writeble root by anonimous when server work
+in two process mode. This feature work if defined tpm_allow_anon_root_access.
+- Added new parametr double_377 (by default 1). This paramert
+switch off telnet specific character \377.
+- Changed find libs in "vsf_findlibs.sh".
+- Different speed for upload and download transfer rates for anonymous and
+local users.
+- Don't add HTTP header string to log.
+
Index: vsftpd.conf.5
===================================================================
--- vsftpd.conf.5 (revision 132)
+++ vsftpd.conf.5 (revision 140)
@@ -1,10 +1,10 @@
.TH VSFTPD.CONF 5
.SH NAME
-vsftpd.conf \- config file for vsftpd
+vsftpd.conf \- config file for vsftpd with extended builds
.SH DESCRIPTION
vsftpd.conf may be used to control various aspects of vsftpd's behaviour. By
default, vsftpd looks for this file at the location
-.BR /etc/vsftpd.conf .
+.BR /etc/vsftpd/vsftpd.conf .
However, you may override this by specifying a command line argument to
vsftpd. The command line argument is the pathname of the configuration file
for vsftpd. This behaviour is useful because you may wish to use an advanced
@@ -26,6 +26,18 @@
Each setting has a compiled in default which may be modified in the
configuration file.
+.SH ADDITIONAL OPTIONS IN EXTENDED BUILD
+.BR "add_default_rule, anon_delete_enable, anon_max_rate_rx, "
+.BR "anon_max_rate_tx, anon_rxtx_rate, bind_retries, chown_by_ip, "
+.BR "chown_group, convert_charset_enable, double_377, "
+.BR "http_browse, http_browse_tpl, http_browse_line_tpl, http_error_403_server_tpl, "
+.BR "http_error_403_tpl, http_error_404_tpl, "
+.BR "local_charset, local_max_rate_rx, local_max_rate_tx, local_rxtx_rate, "
+.BR "pasv_addr_rules, remote_charset, tpm_allow_anon_root_access, users_access_ip"
+
+.SH CHANGED OPTIONS IN EXTENDED BUILD
+.BR pasv_addr_resolve
+
.SH BOOLEAN OPTIONS
Below is a list of boolean options. The value for a boolean option may be set
to
@@ -34,6 +46,19 @@
.BR NO .
.TP
+.B add_default_rule
+Only applies if loaded rules-file defined in option
+.BR pasv_addr_rules .
+If set to YES, added next rule:
+.RS
+.B "0.0.0.0 0.0.0.0/0 0.0.0.0"
+.BR "remote_charset anonymous_enable anon_upload_enable anon_mkdir_write_enable "
+.BR "anon_other_write_enable anon_delete_enable"
+.RE
+.TP
+.B " "
+Default: NO
+.TP
.B allow_anon_ssl
Only applies if
.BR ssl_enable
@@ -42,6 +67,14 @@
Default: NO
.TP
+.B anon_delete_enable
+If set to YES, anonymous users will be permitted to delete files. This
+option work with
+.BR anon_other_write_enable
+option.
+
+Default: YES
+.TP
.B anon_mkdir_write_enable
If set to YES, anonymous users will be permitted to create new directories
under certain conditions. For this to work, the option
@@ -58,6 +91,15 @@
Default: NO
.TP
+.B anon_rxtx_rate
+If set to YES, you can define speed for upload and download diferently by
+parameters
+.BR anon_max_rate_rx
+and
+.BR anon_max_rate_tx .
+
+Default: NO
+.TP
.B anon_upload_enable
If set to YES, anonymous users will be permitted to upload files under certain
conditions. For this to work, the option
@@ -110,7 +152,7 @@
the listener process. i.e. control will immediately be returned to the shell
which launched vsftpd.
-Default: NO
+Default: YES
.TP
.B check_shell
Note! This option only has an effect for non-PAM builds of vsftpd. If disabled,
@@ -124,6 +166,13 @@
Default: YES
.TP
+.B chown_by_ip
+If enabled, all anonymously uploaded files will have the ownership changed
+to the user IP. This options available if defined
+.BR chown_uploads .
+
+Default: NO
+.TP
.B chown_uploads
If enabled, all anonymously uploaded files will have the ownership changed
to the user specified in the setting
@@ -138,7 +187,7 @@
different if chroot_local_user is set to YES. In this case, the list becomes
a list of users which are NOT to be placed in a chroot() jail.
By default, the file containing this list is
-/etc/vsftpd.chroot_list, but you may override this with the
+/etc/vsftpd/chroot_list, but you may override this with the
.BR chroot_list_file
setting.
@@ -163,6 +212,16 @@
Default: NO (but the sample config file enables it)
.TP
+.B convert_charset_enable
+If set to YES, useds internal charset convertion tables for translate chars
+between local charset (
+.BR local_charset
+) and remote charset (
+.BR remote_charset
+).
+
+Default: NO
+.TP
.B debug_ssl
If true, OpenSSL connection diagnostics are dumped to the vsftpd log file.
(Added in v2.0.6).
@@ -177,7 +236,7 @@
.B deny_email_enable
If activated, you may provide a list of anonymous password e-mail responses
which cause login to be denied. By default, the file containing this list is
-/etc/vsftpd.banned_emails, but you may override this with the
+/etc/vsftpd/banned_emails, but you may override this with the
.BR banned_email_file
setting.
@@ -196,6 +255,11 @@
Default: NO (but the sample config file enables it)
.TP
+.B double_377
+If set to NO, switch off telnet specific character \377.
+
+Default: YES
+.TP
.B download_enable
If set to NO, all download requests will give permission denied.
@@ -250,6 +314,14 @@
Default: YES
.TP
+.B ftp_enable
+Work daemon as FTP server. You can't define to
+.BR YES
+this parameter and
+.BR http_enable .
+
+Default: YES
+.TP
.B guest_enable
If enabled, all non-anonymous logins are classed as "guest" logins. A guest
login is remapped to the user specified in the
@@ -264,6 +336,49 @@
Default: NO
.TP
+.B http_browse
+Allow to browse directory content for user.
+
+Default: NO
+.TP
+.B http_browse_tpl
+Path to file with template for browsing directory. If not defined, it will use
+the built-in template.
+
+Default: (none)
+.TP
+.B http_browse_line_tpl
+Path to file with row template for browsing directory. If not defined, it will
+use the built-in template.
+
+Default: (none)
+.TP
+.B http_enable
+Work daemon as HTTP server. You can't define to
+.BR YES
+this parameter and
+.BR ftp_enable .
+
+Default: NO
+.TP
+.B http_error_403_server_tpl
+Path to file with template "Server Forbidden". If not defined, it will use then
+built-in template.
+
+Default: (none)
+.TP
+.B http_error_403_tpl
+Path to file with template "file or dir forbidden". If not defined, it will use
+the built-in template.
+
+Default: (none)
+.TP
+.B http_error_404_tpl
+Path to file with template "file not found". If not defined, it will use the
+built-in template.
+
+Default: (none)
+.TP
.B implicit_ssl
If enabled, an SSL handshake is the first thing expect on all connections
(the FTPS protocol). To support explicit SSL and/or plain text too, a
@@ -277,7 +392,7 @@
run once directly. vsftpd itself will then take care of listening for and
handling incoming connections.
-Default: NO
+Default: YES
.TP
.B listen_ipv6
Like the listen parameter, except vsftpd will listen on an IPv6 socket instead
@@ -294,6 +409,15 @@
Default: NO
.TP
+.B local_rxtx_rate
+If set to YES, you can define speed for upload and download diferently by
+parameters
+.BR local_max_rate_rx
+and
+.BR local_max_rate_tx .
+
+Default: NO
+.TP
.B lock_upload_files
When enabled, all uploads proceed with a write lock on the upload file. All
downloads proceed with a shared read lock on the download file. WARNING!
@@ -357,7 +481,7 @@
.B pasv_addr_resolve
Set to YES if you want to use a hostname (as opposed to IP address) in the
.BR pasv_address
-option.
+option. The resolve IP address by hostname every for each session.
Default: NO
.TP
@@ -433,7 +557,7 @@
file specified by the
.BR email_password_file
setting. The file format is one password per line, no extra whitespace. The
-default filename is /etc/vsftpd.email_passwords.
+default filename is /etc/vsftpd/email_passwords.
Default: NO
.TP
@@ -548,6 +672,12 @@
Default: NO
.TP
+.B tpm_allow_anon_root_access
+If enabled, then anonymous user can write to writable root on server in two
+process model.
+
+Default: NO
+.TP
.B use_localtime
If enabled, vsftpd will display directory listings with the time in your
local time zone. The default is to display GMT. The times returned by the
@@ -588,6 +718,14 @@
Default: NO
.TP
+.B userlist_log
+This option is examined if
+.BR userlist_enable
+is activated. If enabled, every login denial based on the user list will be
+logged.
+
+Default: NO
+.TP
.B virtual_use_local_privs
If enabled, virtual users will use the same privileges as local users. By
default, virtual users will use the same privileges as anonymous users, which
@@ -637,6 +775,20 @@
Default: 0 (unlimited)
.TP
+.B anon_max_rate_rx
+The maximum upload data transfer rate permitted, in bytes per second, for anonymous
+clients if defined
+.BR anon_rxtx_rate .
+
+Default: 0 (unlimited)
+.TP
+.B anon_max_rate_tx
+The maximum download data transfer rate permitted, in bytes per second, for anonymous
+clients if defined
+.BR anon_rxtx_rate .
+
+Default: 0 (unlimited)
+.TP
.B anon_umask
The value that the umask for file creation is set to for anonymous users. NOTE! If you want to specify octal values, remember the "0" prefix otherwise the
value will be treated as a base 10 integer!
@@ -705,6 +857,20 @@
Default: 0 (unlimited)
.TP
+.B local_max_rate_rx
+The maximum upload data transfer rate permitted, in bytes per second, for local
+authenticated users if defined
+.BR local_rxtx_rate .
+
+Default: 0 (unlimited)
+.TP
+.B local_max_rate_tx
+The maximum download data transfer rate permitted, in bytes per second, for local
+authenticated users if defined
+.BR local_rxtx_rate .
+
+Default: 0 (unlimited)
+.TP
.B local_umask
The value that the umask for file creation is set to for local users. NOTE! If
you want to specify octal values, remember the "0" prefix otherwise the value
@@ -764,7 +930,7 @@
.BR deny_email_enable
is enabled.
-Default: /etc/vsftpd.banned_emails
+Default: /etc/vsftpd/banned_emails
.TP
.B banner_file
This option is the name of a file containing text to display when someone
@@ -803,7 +969,7 @@
is enabled, then the list file becomes a list of users to NOT place in a
chroot() jail.
-Default: /etc/vsftpd.chroot_list
+Default: /etc/vsftpd/chroot_list
.TP
.B cmds_allowed
This options specifies a comma separated list of allowed FTP commands (post
@@ -864,7 +1030,7 @@
.BR secure_email_list_enable
setting.
-Default: /etc/vsftpd.email_passwords
+Default: /etc/vsftpd/email_passwords
.TP
.B ftp_username
This is the name of the user we use for handling anonymous FTP. The home
@@ -914,6 +1080,16 @@
Default: (none)
.TP
+.B local_charset
+This option is defined local system charset. This option can be:
+.I "NONE, UTF8 (UTF-8), WIN1251 (1251 or CP1251), KOI8R (878 or CP878), "
+.I "KOI8U (878U or CP878U), "
+.I "IBM866 (866 or CP866), ISO-8859-5 (ISO5), ISO-8859-1 (LATIN1 or ISO1), "
+.I "ISO-8859-15 (LATIN9 or ISO15), WIN1252 (1252 or CP1252), "
+.I "ISO-8859-2 (LATIN2 or ISO2), ISO-8859-16 (ISO16) or WIN1250 (1250 or CP1250)"
+
+Default: NONE
+.TP
.B local_root
This option represents a directory which vsftpd will try to change into
after a local (i.e. non-anonymous) login. Failure is silently ignored.
@@ -951,6 +1127,30 @@
Default: (none - the address is taken from the incoming connected socket)
.TP
+.B pasv_addr_rules
+Use this option for load rules file. The file can be next format:
+.RS
+.B " "
+.BR "[remote_charset] [anonymous_enable [anon_upload_enable "
+.BR "[anon_mkdir_write_enable [anon_other_write_enable [anon_delete_enable]]]]]"
+.RE
+.TP
+.B " "
+If
+.B passive_address
+defined as
+.I 0.0.0.0
+then value getting from option
+.BR pasv_address .
+
+Default: /etc/vsftpd/pasv_rules
+.TP
+.B remote_charset
+This option is define remote client charset. Available values as for
+.BR local_charset.
+
+Default: NONE
+.TP
.B rsa_cert_file
This option specifies the location of the RSA certificate to use for SSL
encrypted connections.
@@ -981,6 +1181,21 @@
Default: DES-CBC3-SHA
.TP
+.B users_access_ip
+Use this option for load users access rules. The file can be next format:
+.RS
+.B ""
+.BR " [...]"
+.RE
+.TP
+.B " "
+If
+.B remote_address
+defined as
+.I 0.0.0.0
+then user can't access to ftp. If user not defined in this file it is
+considered, that it has rights to access.
+.TP
.B user_config_dir
This powerful option allows the override of any config option specified in
the manual page, on a per-user basis. Usage is simple, and is best illustrated
@@ -1026,7 +1241,7 @@
.BR userlist_enable
option is active.
-Default: /etc/vsftpd.user_list
+Default: /etc/vsftpd/user_list
.TP
.B vsftpd_log_file
This option is the name of the file to which we write the vsftpd style
@@ -1053,6 +1268,15 @@
Default: /var/log/xferlog
-.SH AUTHOR
-scarybeasts@gmail.com
+.SH AUTHORS
+Original sources by
+.BR Chris
+.BR Evans
+(scarybeasts@gmail.com)
+Extended builds by
+.BR Dmitriy
+.BR Balashov
+(vsftpd@devnet.ru)
+
+
Index: char_maps/utf8.map
===================================================================
--- char_maps/utf8.map (revision 0)
+++ char_maps/utf8.map (revision 140)
@@ -0,0 +1,393 @@
+/*
+ !!! WARNING !!!
+ DON'T CHANGE ORDER OF CHARS
+*/
+
+struct codepage_map codepage_utf8_array[] =
+ {
+ { 0x000003, 382 }, // max size , char count
+ { 0x00c280, 1 },
+ { 0x00c281, 2 },
+ { 0x00c282, 3 },
+ { 0x00c283, 4 },
+ { 0x00c284, 5 },
+ { 0x00c285, 6 },
+ { 0x00c286, 7 },
+ { 0x00c287, 8 },
+ { 0x00c288, 9 },
+ { 0x00c289, 10 },
+ { 0x00c28a, 11 },
+ { 0x00c28b, 12 },
+ { 0x00c28c, 13 },
+ { 0x00c28d, 14 },
+ { 0x00c28e, 15 },
+ { 0x00c28f, 16 },
+ { 0x00c290, 17 },
+ { 0x00c291, 18 },
+ { 0x00c292, 19 },
+ { 0x00c293, 20 },
+ { 0x00c294, 21 },
+ { 0x00c295, 22 },
+ { 0x00c296, 23 },
+ { 0x00c297, 24 },
+ { 0x00c298, 25 },
+ { 0x00c299, 26 },
+ { 0x00c29a, 27 },
+ { 0x00c29b, 28 },
+ { 0x00c29c, 29 },
+ { 0x00c29d, 30 },
+ { 0x00c29e, 31 },
+ { 0x00c29f, 32 },
+ { 0x00c2a0, 33 },
+ { 0x00c2a1, 34 },
+ { 0x00c2a2, 35 },
+ { 0x00c2a3, 36 },
+ { 0x00c2a4, 37 },
+ { 0x00c2a5, 38 },
+ { 0x00c2a6, 39 },
+ { 0x00c2a7, 40 },
+ { 0x00c2a8, 41 },
+ { 0x00c2a9, 42 },
+ { 0x00c2aa, 43 },
+ { 0x00c2ab, 44 },
+ { 0x00c2ac, 45 },
+ { 0x00c2ad, 46 },
+ { 0x00c2ae, 47 },
+ { 0x00c2af, 48 },
+ { 0x00c2b0, 49 },
+ { 0x00c2b1, 50 },
+ { 0x00c2b2, 51 },
+ { 0x00c2b3, 52 },
+ { 0x00c2b4, 53 },
+ { 0x00c2b5, 54 },
+ { 0x00c2b6, 55 },
+ { 0x00c2b7, 56 },
+ { 0x00c2b8, 57 },
+ { 0x00c2b9, 58 },
+ { 0x00c2ba, 59 },
+ { 0x00c2bb, 60 },
+ { 0x00c2bc, 61 },
+ { 0x00c2bd, 62 },
+ { 0x00c2be, 63 },
+ { 0x00c2bf, 64 },
+ { 0x00c380, 65 },
+ { 0x00c381, 66 },
+ { 0x00c382, 67 },
+ { 0x00c383, 68 },
+ { 0x00c384, 69 },
+ { 0x00c385, 70 },
+ { 0x00c386, 71 },
+ { 0x00c387, 72 },
+ { 0x00c388, 73 },
+ { 0x00c389, 74 },
+ { 0x00c38a, 75 },
+ { 0x00c38b, 76 },
+ { 0x00c38c, 77 },
+ { 0x00c38d, 78 },
+ { 0x00c38e, 79 },
+ { 0x00c38f, 80 },
+ { 0x00c390, 81 },
+ { 0x00c391, 82 },
+ { 0x00c392, 83 },
+ { 0x00c393, 84 },
+ { 0x00c394, 85 },
+ { 0x00c395, 86 },
+ { 0x00c396, 87 },
+ { 0x00c397, 88 },
+ { 0x00c398, 89 },
+ { 0x00c399, 90 },
+ { 0x00c39a, 91 },
+ { 0x00c39b, 92 },
+ { 0x00c39c, 93 },
+ { 0x00c39d, 94 },
+ { 0x00c39e, 95 },
+ { 0x00c39f, 96 },
+ { 0x00c3a0, 97 },
+ { 0x00c3a1, 98 },
+ { 0x00c3a2, 99 },
+ { 0x00c3a3, 100 },
+ { 0x00c3a4, 101 },
+ { 0x00c3a5, 102 },
+ { 0x00c3a6, 103 },
+ { 0x00c3a7, 104 },
+ { 0x00c3a8, 105 },
+ { 0x00c3a9, 106 },
+ { 0x00c3aa, 107 },
+ { 0x00c3ab, 108 },
+ { 0x00c3ac, 109 },
+ { 0x00c3ad, 110 },
+ { 0x00c3ae, 111 },
+ { 0x00c3af, 112 },
+ { 0x00c3b0, 113 },
+ { 0x00c3b1, 114 },
+ { 0x00c3b2, 115 },
+ { 0x00c3b3, 116 },
+ { 0x00c3b4, 117 },
+ { 0x00c3b5, 118 },
+ { 0x00c3b6, 119 },
+ { 0x00c3b7, 120 },
+ { 0x00c3b8, 121 },
+ { 0x00c3b9, 122 },
+ { 0x00c3ba, 123 },
+ { 0x00c3bb, 124 },
+ { 0x00c3bc, 125 },
+ { 0x00c3bd, 126 },
+ { 0x00c3be, 127 },
+ { 0x00c3bf, 128 },
+ { 0x00c482, 129 },
+ { 0x00c483, 130 },
+ { 0x00c484, 131 },
+ { 0x00c485, 132 },
+ { 0x00c486, 133 },
+ { 0x00c487, 134 },
+ { 0x00c488, 135 },
+ { 0x00c489, 136 },
+ { 0x00c48a, 137 },
+ { 0x00c48b, 138 },
+ { 0x00c48c, 139 },
+ { 0x00c48d, 140 },
+ { 0x00c48e, 141 },
+ { 0x00c48f, 142 },
+ { 0x00c490, 143 },
+ { 0x00c491, 144 },
+ { 0x00c498, 145 },
+ { 0x00c499, 146 },
+ { 0x00c49a, 147 },
+ { 0x00c49b, 148 },
+ { 0x00c49c, 149 },
+ { 0x00c49d, 150 },
+ { 0x00c49e, 151 },
+ { 0x00c49f, 152 },
+ { 0x00c4a0, 153 },
+ { 0x00c4a1, 154 },
+ { 0x00c4a4, 155 },
+ { 0x00c4a5, 156 },
+ { 0x00c4a6, 157 },
+ { 0x00c4a7, 158 },
+ { 0x00c4b0, 159 },
+ { 0x00c4b1, 160 },
+ { 0x00c4b4, 161 },
+ { 0x00c4b5, 162 },
+ { 0x00c4b9, 163 },
+ { 0x00c4ba, 164 },
+ { 0x00c4bd, 165 },
+ { 0x00c4be, 166 },
+ { 0x00c581, 167 },
+ { 0x00c582, 168 },
+ { 0x00c583, 169 },
+ { 0x00c584, 170 },
+ { 0x00c587, 171 },
+ { 0x00c588, 172 },
+ { 0x00c590, 173 },
+ { 0x00c591, 174 },
+ { 0x00c592, 175 },
+ { 0x00c593, 176 },
+ { 0x00c594, 177 },
+ { 0x00c595, 178 },
+ { 0x00c598, 179 },
+ { 0x00c599, 180 },
+ { 0x00c59a, 181 },
+ { 0x00c59b, 182 },
+ { 0x00c59c, 183 },
+ { 0x00c59d, 184 },
+ { 0x00c59e, 185 },
+ { 0x00c59f, 186 },
+ { 0x00c5a0, 187 },
+ { 0x00c5a1, 188 },
+ { 0x00c5a2, 189 },
+ { 0x00c5a3, 190 },
+ { 0x00c5a4, 191 },
+ { 0x00c5a5, 192 },
+ { 0x00c5ac, 193 },
+ { 0x00c5ad, 194 },
+ { 0x00c5ae, 195 },
+ { 0x00c5af, 196 },
+ { 0x00c5b0, 197 },
+ { 0x00c5b1, 198 },
+ { 0x00c5b8, 199 },
+ { 0x00c5b9, 200 },
+ { 0x00c5ba, 201 },
+ { 0x00c5bb, 202 },
+ { 0x00c5bc, 203 },
+ { 0x00c5bd, 204 },
+ { 0x00c5be, 205 },
+ { 0x00c692, 206 },
+ { 0x00c89a, 207 },
+ { 0x00cb86, 208 },
+ { 0x00cb87, 209 },
+ { 0x00cb98, 210 },
+ { 0x00cb99, 211 },
+ { 0x00cb9b, 212 },
+ { 0x00cb9c, 213 },
+ { 0x00cb9d, 214 },
+ { 0x00d081, 215 },
+ { 0x00d082, 216 },
+ { 0x00d083, 217 },
+ { 0x00d084, 218 },
+ { 0x00d085, 219 },
+ { 0x00d086, 220 },
+ { 0x00d087, 221 },
+ { 0x00d088, 222 },
+ { 0x00d089, 223 },
+ { 0x00d08a, 224 },
+ { 0x00d08b, 225 },
+ { 0x00d08c, 226 },
+ { 0x00d08e, 227 },
+ { 0x00d08f, 228 },
+ { 0x00d090, 229 },
+ { 0x00d091, 230 },
+ { 0x00d092, 231 },
+ { 0x00d093, 232 },
+ { 0x00d094, 233 },
+ { 0x00d095, 234 },
+ { 0x00d096, 235 },
+ { 0x00d097, 236 },
+ { 0x00d098, 237 },
+ { 0x00d099, 238 },
+ { 0x00d09a, 239 },
+ { 0x00d09b, 240 },
+ { 0x00d09c, 241 },
+ { 0x00d09d, 242 },
+ { 0x00d09e, 243 },
+ { 0x00d09f, 244 },
+ { 0x00d0a0, 245 },
+ { 0x00d0a1, 246 },
+ { 0x00d0a2, 247 },
+ { 0x00d0a3, 248 },
+ { 0x00d0a4, 249 },
+ { 0x00d0a5, 250 },
+ { 0x00d0a6, 251 },
+ { 0x00d0a7, 252 },
+ { 0x00d0a8, 253 },
+ { 0x00d0a9, 254 },
+ { 0x00d0aa, 255 },
+ { 0x00d0ab, 256 },
+ { 0x00d0ac, 257 },
+ { 0x00d0ad, 258 },
+ { 0x00d0ae, 259 },
+ { 0x00d0af, 260 },
+ { 0x00d0b0, 261 },
+ { 0x00d0b1, 262 },
+ { 0x00d0b2, 263 },
+ { 0x00d0b3, 264 },
+ { 0x00d0b4, 265 },
+ { 0x00d0b5, 266 },
+ { 0x00d0b6, 267 },
+ { 0x00d0b7, 268 },
+ { 0x00d0b8, 269 },
+ { 0x00d0b9, 270 },
+ { 0x00d0ba, 271 },
+ { 0x00d0bb, 272 },
+ { 0x00d0bc, 273 },
+ { 0x00d0bd, 274 },
+ { 0x00d0be, 275 },
+ { 0x00d0bf, 276 },
+ { 0x00d180, 277 },
+ { 0x00d181, 278 },
+ { 0x00d182, 279 },
+ { 0x00d183, 280 },
+ { 0x00d184, 281 },
+ { 0x00d185, 282 },
+ { 0x00d186, 283 },
+ { 0x00d187, 284 },
+ { 0x00d188, 285 },
+ { 0x00d189, 286 },
+ { 0x00d18a, 287 },
+ { 0x00d18b, 288 },
+ { 0x00d18c, 289 },
+ { 0x00d18d, 290 },
+ { 0x00d18e, 291 },
+ { 0x00d18f, 292 },
+ { 0x00d191, 293 },
+ { 0x00d192, 294 },
+ { 0x00d193, 295 },
+ { 0x00d194, 296 },
+ { 0x00d195, 297 },
+ { 0x00d196, 298 },
+ { 0x00d197, 299 },
+ { 0x00d198, 300 },
+ { 0x00d199, 301 },
+ { 0x00d19a, 302 },
+ { 0x00d19b, 303 },
+ { 0x00d19c, 304 },
+ { 0x00d19e, 305 },
+ { 0x00d19f, 306 },
+ { 0x00d290, 307 },
+ { 0x00d291, 308 },
+ { 0xe28093, 309 },
+ { 0xe28094, 310 },
+ { 0xe28098, 311 },
+ { 0xe28099, 312 },
+ { 0xe2809a, 313 },
+ { 0xe2809c, 314 },
+ { 0xe2809d, 315 },
+ { 0xe2809e, 316 },
+ { 0xe280a0, 317 },
+ { 0xe280a1, 318 },
+ { 0xe280a2, 319 },
+ { 0xe280a6, 320 },
+ { 0xe280b0, 321 },
+ { 0xe280b9, 322 },
+ { 0xe280ba, 323 },
+ { 0xe282ac, 324 },
+ { 0xe28496, 325 },
+ { 0xe284a2, 326 },
+ { 0xe28899, 327 },
+ { 0xe2889a, 328 },
+ { 0xe28988, 329 },
+ { 0xe289a4, 330 },
+ { 0xe289a5, 331 },
+ { 0xe28ca0, 332 },
+ { 0xe28ca1, 333 },
+ { 0xe29480, 334 },
+ { 0xe29482, 335 },
+ { 0xe2948c, 336 },
+ { 0xe29490, 337 },
+ { 0xe29494, 338 },
+ { 0xe29498, 339 },
+ { 0xe2949c, 340 },
+ { 0xe294a4, 341 },
+ { 0xe294ac, 342 },
+ { 0xe294b4, 343 },
+ { 0xe294bc, 344 },
+ { 0xe29590, 345 },
+ { 0xe29591, 346 },
+ { 0xe29592, 347 },
+ { 0xe29593, 348 },
+ { 0xe29594, 349 },
+ { 0xe29595, 350 },
+ { 0xe29596, 351 },
+ { 0xe29597, 352 },
+ { 0xe29598, 353 },
+ { 0xe29599, 354 },
+ { 0xe2959a, 355 },
+ { 0xe2959b, 356 },
+ { 0xe2959c, 357 },
+ { 0xe2959d, 358 },
+ { 0xe2959e, 359 },
+ { 0xe2959f, 360 },
+ { 0xe295a0, 361 },
+ { 0xe295a1, 362 },
+ { 0xe295a2, 363 },
+ { 0xe295a3, 364 },
+ { 0xe295a4, 365 },
+ { 0xe295a5, 366 },
+ { 0xe295a6, 367 },
+ { 0xe295a7, 368 },
+ { 0xe295a8, 369 },
+ { 0xe295a9, 370 },
+ { 0xe295aa, 371 },
+ { 0xe295ab, 372 },
+ { 0xe295ac, 373 },
+ { 0xe29680, 374 },
+ { 0xe29684, 375 },
+ { 0xe29688, 376 },
+ { 0xe2968c, 377 },
+ { 0xe29690, 378 },
+ { 0xe29691, 379 },
+ { 0xe29692, 380 },
+ { 0xe29693, 381 },
+ { 0xe296a0, 382 },
+ { 0x000000, 0 }
+ };
+
Index: char_maps/western.map
===================================================================
--- char_maps/western.map (revision 0)
+++ char_maps/western.map (revision 140)
@@ -0,0 +1,669 @@
+/*
+ !!! WARNING !!!
+ DON'T CHANGE ORDER OF CHARS
+*/
+
+struct codepage_map codepage_utf8west_array[] =
+ {
+ { 0x000003, 155 }, // max size , char count
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00c280, 1 },
+ { 0x00c281, 2 },
+ { 0x00c282, 3 },
+ { 0x00c283, 4 },
+ { 0x00c284, 5 },
+ { 0x00c285, 6 },
+ { 0x00c286, 7 },
+ { 0x00c287, 8 },
+ { 0x00c288, 9 },
+ { 0x00c289, 10 },
+ { 0x00c28a, 11 },
+ { 0x00c28b, 12 },
+ { 0x00c28c, 13 },
+ { 0x00c28d, 14 },
+ { 0x00c28e, 15 },
+ { 0x00c28f, 16 },
+ { 0x00c290, 17 },
+ { 0x00c291, 18 },
+ { 0x00c292, 19 },
+ { 0x00c293, 20 },
+ { 0x00c294, 21 },
+ { 0x00c295, 22 },
+ { 0x00c296, 23 },
+ { 0x00c297, 24 },
+ { 0x00c298, 25 },
+ { 0x00c299, 26 },
+ { 0x00c29a, 27 },
+ { 0x00c29b, 28 },
+ { 0x00c29c, 29 },
+ { 0x00c29d, 30 },
+ { 0x00c29e, 31 },
+ { 0x00c29f, 32 },
+ { 0x00c2a0, 33 },
+ { 0x00c2a1, 34 },
+ { 0x00c2a2, 35 },
+ { 0x00c2a3, 36 },
+ { 0x00c2a4, 37 },
+ { 0x00c2a5, 38 },
+ { 0x00c2a6, 39 },
+ { 0x00c2a7, 40 },
+ { 0x00c2a8, 41 },
+ { 0x00c2a9, 42 },
+ { 0x00c2aa, 43 },
+ { 0x00c2ab, 44 },
+ { 0x00c2ac, 45 },
+ { 0x00c2ad, 46 },
+ { 0x00c2ae, 47 },
+ { 0x00c2af, 48 },
+ { 0x00c2b0, 49 },
+ { 0x00c2b1, 50 },
+ { 0x00c2b2, 51 },
+ { 0x00c2b3, 52 },
+ { 0x00c2b4, 53 },
+ { 0x00c2b5, 54 },
+ { 0x00c2b6, 55 },
+ { 0x00c2b7, 56 },
+ { 0x00c2b8, 57 },
+ { 0x00c2b9, 58 },
+ { 0x00c2ba, 59 },
+ { 0x00c2bb, 60 },
+ { 0x00c2bc, 61 },
+ { 0x00c2bd, 62 },
+ { 0x00c2be, 63 },
+ { 0x00c2bf, 64 },
+ { 0x00c380, 65 },
+ { 0x00c381, 66 },
+ { 0x00c382, 67 },
+ { 0x00c383, 68 },
+ { 0x00c384, 69 },
+ { 0x00c385, 70 },
+ { 0x00c386, 71 },
+ { 0x00c387, 72 },
+ { 0x00c388, 73 },
+ { 0x00c389, 74 },
+ { 0x00c38a, 75 },
+ { 0x00c38b, 76 },
+ { 0x00c38c, 77 },
+ { 0x00c38d, 78 },
+ { 0x00c38e, 79 },
+ { 0x00c38f, 80 },
+ { 0x00c390, 81 },
+ { 0x00c391, 82 },
+ { 0x00c392, 83 },
+ { 0x00c393, 84 },
+ { 0x00c394, 85 },
+ { 0x00c395, 86 },
+ { 0x00c396, 87 },
+ { 0x00c397, 88 },
+ { 0x00c398, 89 },
+ { 0x00c399, 90 },
+ { 0x00c39a, 91 },
+ { 0x00c39b, 92 },
+ { 0x00c39c, 93 },
+ { 0x00c39d, 94 },
+ { 0x00c39e, 95 },
+ { 0x00c39f, 96 },
+ { 0x00c3a0, 97 },
+ { 0x00c3a1, 98 },
+ { 0x00c3a2, 99 },
+ { 0x00c3a3, 100 },
+ { 0x00c3a4, 101 },
+ { 0x00c3a5, 102 },
+ { 0x00c3a6, 103 },
+ { 0x00c3a7, 104 },
+ { 0x00c3a8, 105 },
+ { 0x00c3a9, 106 },
+ { 0x00c3aa, 107 },
+ { 0x00c3ab, 108 },
+ { 0x00c3ac, 109 },
+ { 0x00c3ad, 110 },
+ { 0x00c3ae, 111 },
+ { 0x00c3af, 112 },
+ { 0x00c3b0, 113 },
+ { 0x00c3b1, 114 },
+ { 0x00c3b2, 115 },
+ { 0x00c3b3, 116 },
+ { 0x00c3b4, 117 },
+ { 0x00c3b5, 118 },
+ { 0x00c3b6, 119 },
+ { 0x00c3b7, 120 },
+ { 0x00c3b8, 121 },
+ { 0x00c3b9, 122 },
+ { 0x00c3ba, 123 },
+ { 0x00c3bb, 124 },
+ { 0x00c3bc, 125 },
+ { 0x00c3bd, 126 },
+ { 0x00c3be, 127 },
+ { 0x00c3bf, 128 },
+ { 0x00c592, 129 },
+ { 0x00c593, 130 },
+ { 0x00c5a0, 131 },
+ { 0x00c5a1, 132 },
+ { 0x00c5b8, 133 },
+ { 0x00c5bd, 134 },
+ { 0x00c5be, 135 },
+ { 0x00c692, 136 },
+ { 0x00cb86, 137 },
+ { 0x00cb9c, 138 },
+ { 0xe28093, 139 },
+ { 0xe28094, 140 },
+ { 0xe28098, 141 },
+ { 0xe28099, 142 },
+ { 0xe2809a, 143 },
+ { 0xe2809c, 144 },
+ { 0xe2809d, 145 },
+ { 0xe2809e, 146 },
+ { 0xe280a0, 147 },
+ { 0xe280a1, 148 },
+ { 0xe280a2, 149 },
+ { 0xe280a6, 150 },
+ { 0xe280b0, 151 },
+ { 0xe280b9, 152 },
+ { 0xe280ba, 153 },
+ { 0xe282ac, 154 },
+ { 0xe284a2, 155 },
+ { 0x000000, 0 }
+ };
+
+struct codepage_map codepage_iso1_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x009a, 27 },
+ { 0x009b, 28 },
+ { 0x009c, 29 },
+ { 0x009d, 30 },
+ { 0x009e, 31 },
+ { 0x009f, 32 },
+ { 0x00a0, 33 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00a3, 36 },
+ { 0x00a4, 37 },
+ { 0x00a5, 38 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x00b3, 52 },
+ { 0x00b4, 53 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00b8, 57 },
+ { 0x00b9, 58 },
+ { 0x00ba, 59 },
+ { 0x00bb, 60 },
+ { 0x00bc, 61 },
+ { 0x00bd, 62 },
+ { 0x00be, 63 },
+ { 0x00bf, 64 },
+ { 0x00c0, 65 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c3, 68 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00c8, 73 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d1, 82 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00d6, 87 },
+ { 0x00d7, 88 },
+ { 0x00d8, 89 },
+ { 0x00d9, 90 },
+ { 0x00da, 91 },
+ { 0x00db, 92 },
+ { 0x00dc, 93 },
+ { 0x00dd, 94 },
+ { 0x00de, 95 },
+ { 0x00df, 96 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e3, 100 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f0, 113 },
+ { 0x00f1, 114 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00f6, 119 },
+ { 0x00f7, 120 },
+ { 0x00f8, 121 },
+ { 0x00f9, 122 },
+ { 0x00fa, 123 },
+ { 0x00fb, 124 },
+ { 0x00fc, 125 },
+ { 0x00fd, 126 },
+ { 0x00fe, 127 },
+ { 0x00ff, 128 },
+ { 0x0000, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_iso15_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x009a, 27 },
+ { 0x009b, 28 },
+ { 0x009c, 29 },
+ { 0x009d, 30 },
+ { 0x009e, 31 },
+ { 0x009f, 32 },
+ { 0x00a0, 33 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00a3, 36 },
+ { 0x003f, 0 },
+ { 0x00a5, 38 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x00b3, 52 },
+ { 0x00b4, 53 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00b8, 57 },
+ { 0x00b9, 58 },
+ { 0x00ba, 59 },
+ { 0x00bb, 60 },
+ { 0x00bc, 61 },
+ { 0x00bd, 62 },
+ { 0x00be, 63 },
+ { 0x00bf, 64 },
+ { 0x00c0, 65 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c3, 68 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00c8, 73 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d1, 82 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00d6, 87 },
+ { 0x00d7, 88 },
+ { 0x00d8, 89 },
+ { 0x00d9, 90 },
+ { 0x00da, 91 },
+ { 0x00db, 92 },
+ { 0x00dc, 93 },
+ { 0x00dd, 94 },
+ { 0x00de, 95 },
+ { 0x00df, 96 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e3, 100 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f0, 113 },
+ { 0x00f1, 114 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00f6, 119 },
+ { 0x00f7, 120 },
+ { 0x00f8, 121 },
+ { 0x00f9, 122 },
+ { 0x00fa, 123 },
+ { 0x00fb, 124 },
+ { 0x00fc, 125 },
+ { 0x00fd, 126 },
+ { 0x00fe, 127 },
+ { 0x00ff, 128 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a4, 37 },
+ { 0x003f, 0 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_win1252_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x0081, 2 },
+ { 0x008d, 14 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x009d, 30 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a0, 33 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00a3, 36 },
+ { 0x00a4, 37 },
+ { 0x00a5, 38 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x00b3, 52 },
+ { 0x00b4, 53 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00b8, 57 },
+ { 0x00b9, 58 },
+ { 0x00ba, 59 },
+ { 0x00bb, 60 },
+ { 0x00bc, 61 },
+ { 0x00bd, 62 },
+ { 0x00be, 63 },
+ { 0x00bf, 64 },
+ { 0x00c0, 65 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c3, 68 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00c8, 73 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d1, 82 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00d6, 87 },
+ { 0x00d7, 88 },
+ { 0x00d8, 89 },
+ { 0x00d9, 90 },
+ { 0x00da, 91 },
+ { 0x00db, 92 },
+ { 0x00dc, 93 },
+ { 0x00dd, 94 },
+ { 0x00de, 95 },
+ { 0x00df, 96 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e3, 100 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f0, 113 },
+ { 0x00f1, 114 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00f6, 119 },
+ { 0x00f7, 120 },
+ { 0x00f8, 121 },
+ { 0x00f9, 122 },
+ { 0x00fa, 123 },
+ { 0x00fb, 124 },
+ { 0x00fc, 125 },
+ { 0x00fd, 126 },
+ { 0x00fe, 127 },
+ { 0x00ff, 128 },
+ { 0x008c, 13 },
+ { 0x009c, 29 },
+ { 0x008a, 11 },
+ { 0x009a, 27 },
+ { 0x009f, 32 },
+ { 0x008e, 15 },
+ { 0x009e, 31 },
+ { 0x0083, 4 },
+ { 0x0088, 9 },
+ { 0x0098, 25 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0082, 3 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0084, 5 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0095, 22 },
+ { 0x0085, 6 },
+ { 0x0089, 10 },
+ { 0x008b, 12 },
+ { 0x009b, 28 },
+ { 0x0080, 1 },
+ { 0x0099, 26 },
+ { 0x0000, 0 }
+ };
+
Index: char_maps/central.map
===================================================================
--- char_maps/central.map (revision 0)
+++ char_maps/central.map (revision 140)
@@ -0,0 +1,738 @@
+/*
+ !!! WARNING !!!
+ DON'T CHANGE ORDER OF CHARS
+*/
+
+struct codepage_map codepage_utf8cent_array[] =
+ {
+ { 0x000003, 178 }, // max size , char count
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00c280, 1 },
+ { 0x00c281, 2 },
+ { 0x00c282, 3 },
+ { 0x00c283, 4 },
+ { 0x00c284, 5 },
+ { 0x00c285, 6 },
+ { 0x00c286, 7 },
+ { 0x00c287, 8 },
+ { 0x00c288, 9 },
+ { 0x00c289, 10 },
+ { 0x00c28a, 11 },
+ { 0x00c28b, 12 },
+ { 0x00c28c, 13 },
+ { 0x00c28d, 14 },
+ { 0x00c28e, 15 },
+ { 0x00c28f, 16 },
+ { 0x00c290, 17 },
+ { 0x00c291, 18 },
+ { 0x00c292, 19 },
+ { 0x00c293, 20 },
+ { 0x00c294, 21 },
+ { 0x00c295, 22 },
+ { 0x00c296, 23 },
+ { 0x00c297, 24 },
+ { 0x00c298, 25 },
+ { 0x00c299, 26 },
+ { 0x00c29a, 27 },
+ { 0x00c29b, 28 },
+ { 0x00c29c, 29 },
+ { 0x00c29d, 30 },
+ { 0x00c29e, 31 },
+ { 0x00c29f, 32 },
+ { 0x00c2a0, 33 },
+ { 0x00c2a4, 34 },
+ { 0x00c2a6, 35 },
+ { 0x00c2a7, 36 },
+ { 0x00c2a8, 37 },
+ { 0x00c2a9, 38 },
+ { 0x00c2ab, 39 },
+ { 0x00c2ad, 40 },
+ { 0x00c2ad, 41 },
+ { 0x00c2ae, 42 },
+ { 0x00c2b0, 43 },
+ { 0x00c2b1, 44 },
+ { 0x00c2b4, 45 },
+ { 0x00c2b5, 46 },
+ { 0x00c2b6, 47 },
+ { 0x00c2b7, 48 },
+ { 0x00c2b8, 49 },
+ { 0x00c2bb, 50 },
+ { 0x00c380, 51 },
+ { 0x00c381, 52 },
+ { 0x00c382, 53 },
+ { 0x00c384, 54 },
+ { 0x00c386, 55 },
+ { 0x00c387, 56 },
+ { 0x00c388, 57 },
+ { 0x00c389, 58 },
+ { 0x00c38a, 59 },
+ { 0x00c38b, 60 },
+ { 0x00c38c, 61 },
+ { 0x00c38d, 62 },
+ { 0x00c38e, 63 },
+ { 0x00c38f, 64 },
+ { 0x00c392, 65 },
+ { 0x00c393, 66 },
+ { 0x00c394, 67 },
+ { 0x00c396, 68 },
+ { 0x00c397, 69 },
+ { 0x00c399, 70 },
+ { 0x00c39a, 71 },
+ { 0x00c39b, 72 },
+ { 0x00c39c, 73 },
+ { 0x00c39d, 74 },
+ { 0x00c39f, 75 },
+ { 0x00c3a0, 76 },
+ { 0x00c3a1, 77 },
+ { 0x00c3a2, 78 },
+ { 0x00c3a4, 79 },
+ { 0x00c3a6, 80 },
+ { 0x00c3a7, 81 },
+ { 0x00c3a8, 82 },
+ { 0x00c3a9, 83 },
+ { 0x00c3aa, 84 },
+ { 0x00c3ab, 85 },
+ { 0x00c3ac, 86 },
+ { 0x00c3ad, 87 },
+ { 0x00c3ae, 88 },
+ { 0x00c3af, 89 },
+ { 0x00c3b2, 90 },
+ { 0x00c3b3, 91 },
+ { 0x00c3b4, 92 },
+ { 0x00c3b6, 93 },
+ { 0x00c3b7, 94 },
+ { 0x00c3b9, 95 },
+ { 0x00c3ba, 96 },
+ { 0x00c3bb, 97 },
+ { 0x00c3bc, 98 },
+ { 0x00c3bd, 99 },
+ { 0x00c3bf, 100 },
+ { 0x00c482, 101 },
+ { 0x00c483, 102 },
+ { 0x00c484, 103 },
+ { 0x00c485, 104 },
+ { 0x00c486, 105 },
+ { 0x00c487, 106 },
+ { 0x00c48c, 107 },
+ { 0x00c48d, 108 },
+ { 0x00c48e, 109 },
+ { 0x00c48f, 110 },
+ { 0x00c490, 111 },
+ { 0x00c491, 112 },
+ { 0x00c498, 113 },
+ { 0x00c499, 114 },
+ { 0x00c49a, 115 },
+ { 0x00c49b, 116 },
+ { 0x00c4b9, 117 },
+ { 0x00c4ba, 118 },
+ { 0x00c4bd, 119 },
+ { 0x00c4be, 120 },
+ { 0x00c581, 121 },
+ { 0x00c582, 122 },
+ { 0x00c583, 123 },
+ { 0x00c584, 124 },
+ { 0x00c587, 125 },
+ { 0x00c588, 126 },
+ { 0x00c590, 127 },
+ { 0x00c591, 128 },
+ { 0x00c592, 129 },
+ { 0x00c593, 130 },
+ { 0x00c594, 131 },
+ { 0x00c595, 132 },
+ { 0x00c598, 133 },
+ { 0x00c599, 134 },
+ { 0x00c59a, 135 },
+ { 0x00c59b, 136 },
+ { 0x00c59e, 137 },
+ { 0x00c59f, 138 },
+ { 0x00c5a0, 139 },
+ { 0x00c5a1, 140 },
+ { 0x00c5a2, 141 },
+ { 0x00c5a3, 142 },
+ { 0x00c5a4, 143 },
+ { 0x00c5a5, 144 },
+ { 0x00c5ae, 145 },
+ { 0x00c5af, 146 },
+ { 0x00c5b0, 147 },
+ { 0x00c5b1, 148 },
+ { 0x00c5b8, 149 },
+ { 0x00c5b9, 150 },
+ { 0x00c5ba, 151 },
+ { 0x00c5bb, 152 },
+ { 0x00c5bc, 153 },
+ { 0x00c5bd, 154 },
+ { 0x00c5be, 155 },
+ { 0x00cb87, 156 },
+ { 0x00cb98, 157 },
+ { 0x00cb99, 158 },
+ { 0x00c89a, 159 },
+ { 0x00cb9b, 160 },
+ { 0x00cb9d, 161 },
+ { 0xe28093, 162 },
+ { 0xe28094, 163 },
+ { 0xe28098, 164 },
+ { 0xe28099, 165 },
+ { 0xe2809a, 166 },
+ { 0xe2809c, 167 },
+ { 0xe2809d, 168 },
+ { 0xe2809e, 169 },
+ { 0xe280a0, 170 },
+ { 0xe280a1, 171 },
+ { 0xe280a2, 172 },
+ { 0xe280a6, 173 },
+ { 0xe280b0, 174 },
+ { 0xe280b9, 175 },
+ { 0xe280ba, 176 },
+ { 0xe282ac, 177 },
+ { 0xe284a2, 178 },
+ { 0x000000, 0 }
+ };
+
+struct codepage_map codepage_iso2_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x009a, 27 },
+ { 0x009b, 28 },
+ { 0x009c, 29 },
+ { 0x009d, 30 },
+ { 0x009e, 31 },
+ { 0x009f, 32 },
+ { 0x00a0, 33 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00a3, 36 },
+ { 0x00a4, 37 },
+ { 0x00a5, 38 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x00b3, 52 },
+ { 0x00b4, 53 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00b8, 57 },
+ { 0x00b9, 58 },
+ { 0x00ba, 59 },
+ { 0x00bb, 60 },
+ { 0x00bc, 61 },
+ { 0x00bd, 62 },
+ { 0x00be, 63 },
+ { 0x00bf, 64 },
+ { 0x00c0, 65 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c3, 68 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00c8, 73 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d1, 82 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00d6, 87 },
+ { 0x00d7, 88 },
+ { 0x00d8, 89 },
+ { 0x00d9, 90 },
+ { 0x00da, 91 },
+ { 0x00db, 92 },
+ { 0x00dc, 93 },
+ { 0x00dd, 94 },
+ { 0x00de, 95 },
+ { 0x00df, 96 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e3, 100 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f0, 113 },
+ { 0x00f1, 114 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00f6, 119 },
+ { 0x00f7, 120 },
+ { 0x00f8, 121 },
+ { 0x00f9, 122 },
+ { 0x00fa, 123 },
+ { 0x00fb, 124 },
+ { 0x00fc, 125 },
+ { 0x00fd, 126 },
+ { 0x00fe, 127 },
+ { 0x00ff, 128 },
+ { 0x0000, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_iso16_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x009a, 27 },
+ { 0x009b, 28 },
+ { 0x009c, 29 },
+ { 0x009d, 30 },
+ { 0x009e, 31 },
+ { 0x009f, 32 },
+ { 0x00a0, 33 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a7, 40 },
+ { 0x003f, 0 },
+ { 0x00a9, 42 },
+ { 0x00ab, 44 },
+ { 0x00ad, 46 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x003f, 0 },
+ { 0x00bb, 60 },
+ { 0x00c0, 65 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c4, 69 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00c8, 73 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d6, 87 },
+ { 0x003f, 0 },
+ { 0x00d9, 90 },
+ { 0x00da, 91 },
+ { 0x00db, 92 },
+ { 0x00dc, 93 },
+ { 0x003f, 0 },
+ { 0x00df, 96 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e4, 101 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f6, 119 },
+ { 0x003f, 0 },
+ { 0x00f9, 122 },
+ { 0x00fa, 123 },
+ { 0x00fb, 124 },
+ { 0x00fc, 125 },
+ { 0x003f, 0 },
+ { 0x00ff, 128 },
+ { 0x00c3, 68 },
+ { 0x00e3, 100 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00c5, 70 },
+ { 0x00e5, 102 },
+ { 0x00b2, 51 },
+ { 0x00b9, 58 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00d0, 81 },
+ { 0x00f0, 113 },
+ { 0x00dd, 94 },
+ { 0x00fd, 126 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a3, 36 },
+ { 0x00b3, 52 },
+ { 0x00d1, 82 },
+ { 0x00f1, 114 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00d5, 86 },
+ { 0x00f5, 118 },
+ { 0x00bc, 61 },
+ { 0x00bd, 62 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00d7, 88 },
+ { 0x00f7, 120 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a6, 39 },
+ { 0x00a8, 41 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00d8, 89 },
+ { 0x00f8, 121 },
+ { 0x00be, 63 },
+ { 0x00ac, 45 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00bf, 64 },
+ { 0x00b4, 53 },
+ { 0x00b8, 57 },
+ { 0x003f, 0 },
+ { 0x00aa, 43 },
+ { 0x00ba, 59 },
+ { 0x00de, 95 },
+ { 0x00fe, 127 },
+ { 0x00b5, 54 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a5, 38 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a4, 37 },
+ { 0x003f, 0 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_win1250_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x0081, 2 },
+ { 0x0083, 4 },
+ { 0x0088, 9 },
+ { 0x0090, 17 },
+ { 0x0098, 25 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a0, 33 },
+ { 0x00a4, 37 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b4, 53 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00b8, 57 },
+ { 0x00bb, 60 },
+ { 0x003f, 0 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c4, 69 },
+ { 0x003f, 0 },
+ { 0x00c7, 72 },
+ { 0x003f, 0 },
+ { 0x00c9, 74 },
+ { 0x003f, 0 },
+ { 0x00cb, 76 },
+ { 0x003f, 0 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d6, 87 },
+ { 0x00d7, 88 },
+ { 0x003f, 0 },
+ { 0x00da, 91 },
+ { 0x003f, 0 },
+ { 0x00dc, 93 },
+ { 0x00dd, 94 },
+ { 0x00df, 96 },
+ { 0x003f, 0 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e4, 101 },
+ { 0x003f, 0 },
+ { 0x00e7, 104 },
+ { 0x003f, 0 },
+ { 0x00e9, 106 },
+ { 0x003f, 0 },
+ { 0x00eb, 108 },
+ { 0x003f, 0 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f6, 119 },
+ { 0x00f7, 120 },
+ { 0x003f, 0 },
+ { 0x00fa, 123 },
+ { 0x003f, 0 },
+ { 0x00fc, 125 },
+ { 0x00fd, 126 },
+ { 0x003f, 0 },
+ { 0x00c3, 68 },
+ { 0x00e3, 100 },
+ { 0x00a5, 38 },
+ { 0x00b9, 58 },
+ { 0x00c6, 71 },
+ { 0x00e6, 103 },
+ { 0x00c8, 73 },
+ { 0x00e8, 105 },
+ { 0x00cf, 80 },
+ { 0x00ef, 112 },
+ { 0x00d0, 81 },
+ { 0x00f0, 113 },
+ { 0x00ca, 75 },
+ { 0x00ea, 107 },
+ { 0x00cc, 77 },
+ { 0x00ec, 109 },
+ { 0x00c5, 70 },
+ { 0x00e5, 102 },
+ { 0x00bc, 61 },
+ { 0x00be, 63 },
+ { 0x00a3, 36 },
+ { 0x00b3, 52 },
+ { 0x00d1, 82 },
+ { 0x00f1, 114 },
+ { 0x00d2, 83 },
+ { 0x00f2, 115 },
+ { 0x00d5, 86 },
+ { 0x00f5, 118 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00c0, 65 },
+ { 0x00e0, 97 },
+ { 0x00d8, 89 },
+ { 0x00f8, 121 },
+ { 0x008c, 13 },
+ { 0x009c, 29 },
+ { 0x00aa, 43 },
+ { 0x00ba, 59 },
+ { 0x008a, 11 },
+ { 0x009a, 27 },
+ { 0x00de, 95 },
+ { 0x00fe, 127 },
+ { 0x008d, 14 },
+ { 0x009d, 30 },
+ { 0x00d9, 90 },
+ { 0x00f9, 122 },
+ { 0x00db, 92 },
+ { 0x00fb, 124 },
+ { 0x003f, 0 },
+ { 0x008f, 16 },
+ { 0x009f, 32 },
+ { 0x00af, 48 },
+ { 0x00bf, 64 },
+ { 0x008e, 15 },
+ { 0x009e, 31 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00ff, 128 },
+ { 0x003f, 0 },
+ { 0x00b2, 51 },
+ { 0x00bd, 62 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0082, 3 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0084, 5 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0095, 22 },
+ { 0x0085, 6 },
+ { 0x0089, 10 },
+ { 0x008b, 12 },
+ { 0x009b, 28 },
+ { 0x0080, 1 },
+ { 0x0099, 26 },
+ { 0x0000, 0 }
+ };
+
Index: char_maps/cyrillic.map
===================================================================
--- char_maps/cyrillic.map (revision 0)
+++ char_maps/cyrillic.map (revision 140)
@@ -0,0 +1,1349 @@
+/*
+ !!! WARNING !!!
+ DON'T CHANGE ORDER OF CHARS
+*/
+
+struct codepage_map codepage_utf8cyr_array[] =
+ {
+ { 0x000003, 216 }, // max size , char count
+ { 0x00003f, 0 },
+ { 0x00003f, 0 },
+ { 0x00c280, 1 },
+ { 0x00c281, 2 },
+ { 0x00c282, 3 },
+ { 0x00c283, 4 },
+ { 0x00c284, 5 },
+ { 0x00c285, 6 },
+ { 0x00c286, 7 },
+ { 0x00c287, 8 },
+ { 0x00c288, 9 },
+ { 0x00c289, 10 },
+ { 0x00c28a, 11 },
+ { 0x00c28b, 12 },
+ { 0x00c28c, 13 },
+ { 0x00c28d, 14 },
+ { 0x00c28e, 15 },
+ { 0x00c28f, 16 },
+ { 0x00c290, 17 },
+ { 0x00c291, 18 },
+ { 0x00c292, 19 },
+ { 0x00c293, 20 },
+ { 0x00c294, 21 },
+ { 0x00c295, 22 },
+ { 0x00c296, 23 },
+ { 0x00c297, 24 },
+ { 0x00c298, 25 },
+ { 0x00c299, 26 },
+ { 0x00c29a, 27 },
+ { 0x00c29b, 28 },
+ { 0x00c29c, 29 },
+ { 0x00c29d, 30 },
+ { 0x00c29e, 31 },
+ { 0x00c29f, 32 },
+ { 0x00c2a0, 33 },
+ { 0x00c2a4, 34 },
+ { 0x00c2a6, 35 },
+ { 0x00c2a7, 36 },
+ { 0x00c2a9, 37 },
+ { 0x00c2ab, 38 },
+ { 0x00c2ac, 39 },
+ { 0x00c2ad, 40 },
+ { 0x00c2ae, 41 },
+ { 0x00c2b0, 42 },
+ { 0x00c2b1, 43 },
+ { 0x00c2b2, 44 },
+ { 0x00c2b5, 45 },
+ { 0x00c2b6, 46 },
+ { 0x00c2b7, 47 },
+ { 0x00c2bb, 48 },
+ { 0x00c3b7, 49 },
+ { 0x00d081, 50 },
+ { 0x00d082, 51 },
+ { 0x00d083, 52 },
+ { 0x00d084, 53 },
+ { 0x00d085, 54 },
+ { 0x00d086, 55 },
+ { 0x00d087, 56 },
+ { 0x00d088, 57 },
+ { 0x00d089, 58 },
+ { 0x00d08a, 59 },
+ { 0x00d08b, 60 },
+ { 0x00d08c, 61 },
+ { 0x00d08e, 62 },
+ { 0x00d08f, 63 },
+ { 0x00d090, 64 },
+ { 0x00d091, 65 },
+ { 0x00d092, 66 },
+ { 0x00d093, 67 },
+ { 0x00d094, 68 },
+ { 0x00d095, 69 },
+ { 0x00d096, 70 },
+ { 0x00d097, 71 },
+ { 0x00d098, 72 },
+ { 0x00d099, 73 },
+ { 0x00d09a, 74 },
+ { 0x00d09b, 75 },
+ { 0x00d09c, 76 },
+ { 0x00d09d, 77 },
+ { 0x00d09e, 78 },
+ { 0x00d09f, 79 },
+ { 0x00d0a0, 80 },
+ { 0x00d0a1, 81 },
+ { 0x00d0a2, 82 },
+ { 0x00d0a3, 83 },
+ { 0x00d0a4, 84 },
+ { 0x00d0a5, 85 },
+ { 0x00d0a6, 86 },
+ { 0x00d0a7, 87 },
+ { 0x00d0a8, 88 },
+ { 0x00d0a9, 89 },
+ { 0x00d0aa, 90 },
+ { 0x00d0ab, 91 },
+ { 0x00d0ac, 92 },
+ { 0x00d0ad, 93 },
+ { 0x00d0ae, 94 },
+ { 0x00d0af, 95 },
+ { 0x00d0b0, 96 },
+ { 0x00d0b1, 97 },
+ { 0x00d0b2, 98 },
+ { 0x00d0b3, 99 },
+ { 0x00d0b4, 100 },
+ { 0x00d0b5, 101 },
+ { 0x00d0b6, 102 },
+ { 0x00d0b7, 103 },
+ { 0x00d0b8, 104 },
+ { 0x00d0b9, 105 },
+ { 0x00d0ba, 106 },
+ { 0x00d0bb, 107 },
+ { 0x00d0bc, 108 },
+ { 0x00d0bd, 109 },
+ { 0x00d0be, 110 },
+ { 0x00d0bf, 111 },
+ { 0x00d180, 112 },
+ { 0x00d181, 113 },
+ { 0x00d182, 114 },
+ { 0x00d183, 115 },
+ { 0x00d184, 116 },
+ { 0x00d185, 117 },
+ { 0x00d186, 118 },
+ { 0x00d187, 119 },
+ { 0x00d188, 120 },
+ { 0x00d189, 121 },
+ { 0x00d18a, 122 },
+ { 0x00d18b, 123 },
+ { 0x00d18c, 124 },
+ { 0x00d18d, 125 },
+ { 0x00d18e, 126 },
+ { 0x00d18f, 127 },
+ { 0x00d191, 128 },
+ { 0x00d192, 129 },
+ { 0x00d193, 130 },
+ { 0x00d194, 131 },
+ { 0x00d195, 132 },
+ { 0x00d196, 133 },
+ { 0x00d197, 134 },
+ { 0x00d198, 135 },
+ { 0x00d199, 136 },
+ { 0x00d19a, 137 },
+ { 0x00d19b, 138 },
+ { 0x00d19c, 139 },
+ { 0x00d19e, 140 },
+ { 0x00d19f, 141 },
+ { 0x00d290, 142 },
+ { 0x00d291, 143 },
+ { 0xe28093, 144 },
+ { 0xe28094, 145 },
+ { 0xe28098, 146 },
+ { 0xe28099, 147 },
+ { 0xe2809a, 148 },
+ { 0xe2809c, 149 },
+ { 0xe2809d, 150 },
+ { 0xe2809e, 151 },
+ { 0xe280a0, 152 },
+ { 0xe280a1, 153 },
+ { 0xe280a2, 154 },
+ { 0xe280a6, 155 },
+ { 0xe280b0, 156 },
+ { 0xe280b9, 157 },
+ { 0xe280ba, 158 },
+ { 0xe28496, 159 },
+ { 0xe284a2, 160 },
+ { 0xe28899, 161 },
+ { 0xe2889a, 162 },
+ { 0xe28988, 163 },
+ { 0xe289a4, 164 },
+ { 0xe289a5, 165 },
+ { 0xe28ca0, 166 },
+ { 0xe28ca1, 167 },
+ { 0xe29480, 168 },
+ { 0xe29482, 169 },
+ { 0xe2948c, 170 },
+ { 0xe29490, 171 },
+ { 0xe29494, 172 },
+ { 0xe29498, 173 },
+ { 0xe2949c, 174 },
+ { 0xe294a4, 175 },
+ { 0xe294ac, 176 },
+ { 0xe294b4, 177 },
+ { 0xe294bc, 178 },
+ { 0xe29590, 179 },
+ { 0xe29591, 180 },
+ { 0xe29592, 181 },
+ { 0xe29593, 182 },
+ { 0xe29594, 183 },
+ { 0xe29595, 184 },
+ { 0xe29596, 185 },
+ { 0xe29597, 186 },
+ { 0xe29598, 187 },
+ { 0xe29599, 188 },
+ { 0xe2959a, 189 },
+ { 0xe2959b, 190 },
+ { 0xe2959c, 191 },
+ { 0xe2959d, 192 },
+ { 0xe2959e, 193 },
+ { 0xe2959f, 194 },
+ { 0xe295a0, 195 },
+ { 0xe295a1, 196 },
+ { 0xe295a2, 197 },
+ { 0xe295a3, 198 },
+ { 0xe295a4, 199 },
+ { 0xe295a5, 200 },
+ { 0xe295a6, 201 },
+ { 0xe295a7, 202 },
+ { 0xe295a8, 203 },
+ { 0xe295a9, 204 },
+ { 0xe295aa, 205 },
+ { 0xe295ab, 206 },
+ { 0xe295ac, 207 },
+ { 0xe29680, 208 },
+ { 0xe29684, 209 },
+ { 0xe29688, 210 },
+ { 0xe2968c, 211 },
+ { 0xe29690, 212 },
+ { 0xe29691, 213 },
+ { 0xe29692, 214 },
+ { 0xe29693, 215 },
+ { 0xe296a0, 216 },
+ { 0x000000, 0 }
+ };
+
+struct codepage_map codepage_win1251_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x0088, 9 },
+ { 0x0098, 25 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a0, 33 },
+ { 0x00a4, 37 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a9, 42 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x003f, 0 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00bb, 60 },
+ { 0x003f, 0 },
+ { 0x00a8, 41 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x00aa, 43 },
+ { 0x00bd, 62 },
+ { 0x00b2, 51 },
+ { 0x00af, 48 },
+ { 0x00a3, 36 },
+ { 0x008a, 11 },
+ { 0x008c, 13 },
+ { 0x008e, 15 },
+ { 0x008d, 14 },
+ { 0x00a1, 34 },
+ { 0x008f, 16 },
+ { 0x00c0, 65 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c3, 68 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00c8, 73 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d1, 82 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00d6, 87 },
+ { 0x00d7, 88 },
+ { 0x00d8, 89 },
+ { 0x00d9, 90 },
+ { 0x00da, 91 },
+ { 0x00db, 92 },
+ { 0x00dc, 93 },
+ { 0x00dd, 94 },
+ { 0x00de, 95 },
+ { 0x00df, 96 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e3, 100 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f0, 113 },
+ { 0x00f1, 114 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00f6, 119 },
+ { 0x00f7, 120 },
+ { 0x00f8, 121 },
+ { 0x00f9, 122 },
+ { 0x00fa, 123 },
+ { 0x00fb, 124 },
+ { 0x00fc, 125 },
+ { 0x00fd, 126 },
+ { 0x00fe, 127 },
+ { 0x00ff, 128 },
+ { 0x00b8, 57 },
+ { 0x0090, 17 },
+ { 0x0083, 4 },
+ { 0x00ba, 59 },
+ { 0x00be, 63 },
+ { 0x00b3, 52 },
+ { 0x00bf, 64 },
+ { 0x00bc, 61 },
+ { 0x009a, 27 },
+ { 0x009c, 29 },
+ { 0x009e, 31 },
+ { 0x009d, 30 },
+ { 0x00a2, 35 },
+ { 0x009f, 32 },
+ { 0x00a5, 38 },
+ { 0x00b4, 53 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0082, 3 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0084, 5 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0095, 22 },
+ { 0x0085, 6 },
+ { 0x0089, 10 },
+ { 0x008b, 12 },
+ { 0x009b, 28 },
+ { 0x00b9, 58 },
+ { 0x0099, 26 },
+ { 0x0000, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_koi8u_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x009a, 27 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00bf, 64 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x009c, 29 },
+ { 0x003f, 0 },
+ { 0x009d, 30 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x009e, 31 },
+ { 0x003f, 0 },
+ { 0x009f, 32 },
+ { 0x00b3, 52 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00b4, 53 },
+ { 0x003f, 0 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00f7, 120 },
+ { 0x00e7, 104 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00f6, 119 },
+ { 0x00fa, 123 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f0, 113 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00e6, 103 },
+ { 0x00e8, 105 },
+ { 0x00e3, 100 },
+ { 0x00fe, 127 },
+ { 0x00fb, 124 },
+ { 0x00fd, 126 },
+ { 0x00ff, 128 },
+ { 0x00f9, 122 },
+ { 0x00f8, 121 },
+ { 0x00fc, 125 },
+ { 0x00e0, 97 },
+ { 0x00f1, 114 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00d7, 88 },
+ { 0x00c7, 72 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00d6, 87 },
+ { 0x00da, 91 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00c6, 71 },
+ { 0x00c8, 73 },
+ { 0x00c3, 68 },
+ { 0x00de, 95 },
+ { 0x00db, 92 },
+ { 0x00dd, 94 },
+ { 0x00df, 96 },
+ { 0x00d9, 90 },
+ { 0x00d8, 89 },
+ { 0x00dc, 93 },
+ { 0x00c0, 65 },
+ { 0x00d1, 82 },
+ { 0x00a3, 36 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a4, 37 },
+ { 0x003f, 0 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00bd, 62 },
+ { 0x00ad, 46 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x0093, 20 },
+ { 0x009b, 28 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x00a0, 33 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x003f, 0 },
+ { 0x00a5, 38 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x003f, 0 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x003f, 0 },
+ { 0x00b5, 54 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00b8, 57 },
+ { 0x00b9, 58 },
+ { 0x00ba, 59 },
+ { 0x00bb, 60 },
+ { 0x00bc, 61 },
+ { 0x003f, 0 },
+ { 0x00be, 63 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0094, 21 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_ibm866_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00ff, 128 },
+ { 0x00fd, 126 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f8, 121 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00fa, 123 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f0, 113 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f2, 115 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f4, 117 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f6, 119 },
+ { 0x003f, 0 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x009a, 27 },
+ { 0x009b, 28 },
+ { 0x009c, 29 },
+ { 0x009d, 30 },
+ { 0x009e, 31 },
+ { 0x009f, 32 },
+ { 0x00a0, 33 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00a3, 36 },
+ { 0x00a4, 37 },
+ { 0x00a5, 38 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e3, 100 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f1, 114 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f3, 116 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f5, 118 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f7, 120 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00fc, 125 },
+ { 0x003f, 0 },
+ { 0x00f9, 122 },
+ { 0x00fb, 124 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00c4, 69 },
+ { 0x00b3, 52 },
+ { 0x00da, 91 },
+ { 0x00bf, 64 },
+ { 0x00c0, 65 },
+ { 0x00d9, 90 },
+ { 0x00c3, 68 },
+ { 0x00b4, 53 },
+ { 0x00c2, 67 },
+ { 0x00c1, 66 },
+ { 0x00c5, 70 },
+ { 0x00cd, 78 },
+ { 0x00ba, 59 },
+ { 0x00d5, 86 },
+ { 0x00d6, 87 },
+ { 0x00c9, 74 },
+ { 0x00b8, 57 },
+ { 0x00b7, 56 },
+ { 0x00bb, 60 },
+ { 0x00d4, 85 },
+ { 0x00d3, 84 },
+ { 0x00c8, 73 },
+ { 0x00be, 63 },
+ { 0x00bd, 62 },
+ { 0x00bc, 61 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00cc, 77 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b9, 58 },
+ { 0x00d1, 82 },
+ { 0x00d2, 83 },
+ { 0x00cb, 76 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00ca, 75 },
+ { 0x00d8, 89 },
+ { 0x00d7, 88 },
+ { 0x00ce, 79 },
+ { 0x00df, 96 },
+ { 0x00dc, 93 },
+ { 0x00db, 92 },
+ { 0x00dd, 94 },
+ { 0x00de, 95 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x00fe, 127 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_iso5_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x009a, 27 },
+ { 0x009b, 28 },
+ { 0x009c, 29 },
+ { 0x009d, 30 },
+ { 0x009e, 31 },
+ { 0x009f, 32 },
+ { 0x00a0, 33 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00fd, 126 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00ad, 46 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00a3, 36 },
+ { 0x00a4, 37 },
+ { 0x00a5, 38 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x00b3, 52 },
+ { 0x00b4, 53 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00b8, 57 },
+ { 0x00b9, 58 },
+ { 0x00ba, 59 },
+ { 0x00bb, 60 },
+ { 0x00bc, 61 },
+ { 0x00bd, 62 },
+ { 0x00be, 63 },
+ { 0x00bf, 64 },
+ { 0x00c0, 65 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00c3, 68 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00c6, 71 },
+ { 0x00c7, 72 },
+ { 0x00c8, 73 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d1, 82 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00d6, 87 },
+ { 0x00d7, 88 },
+ { 0x00d8, 89 },
+ { 0x00d9, 90 },
+ { 0x00da, 91 },
+ { 0x00db, 92 },
+ { 0x00dc, 93 },
+ { 0x00dd, 94 },
+ { 0x00de, 95 },
+ { 0x00df, 96 },
+ { 0x00e0, 97 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00e3, 100 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00e6, 103 },
+ { 0x00e7, 104 },
+ { 0x00e8, 105 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f1, 114 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00f6, 119 },
+ { 0x00f7, 120 },
+ { 0x00f8, 121 },
+ { 0x00f9, 122 },
+ { 0x00fa, 123 },
+ { 0x00fb, 124 },
+ { 0x00fc, 125 },
+ { 0x00fe, 127 },
+ { 0x00ff, 128 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x00f0, 113 },
+ { 0x0000, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x003f, 0 },
+ { 0x0000, 0 }
+ };
+
+struct codepage_map codepage_koi8r_array[] =
+ {
+ { 0x0001, 128 }, // max size , char count for control
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x009a, 27 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x00bf, 64 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x009c, 29 },
+ { 0x005f, 0 },
+ { 0x009d, 30 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x009e, 31 },
+ { 0x005f, 0 },
+ { 0x009f, 32 },
+ { 0x00b3, 52 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x00e1, 98 },
+ { 0x00e2, 99 },
+ { 0x00f7, 120 },
+ { 0x00e7, 104 },
+ { 0x00e4, 101 },
+ { 0x00e5, 102 },
+ { 0x00f6, 119 },
+ { 0x00fa, 123 },
+ { 0x00e9, 106 },
+ { 0x00ea, 107 },
+ { 0x00eb, 108 },
+ { 0x00ec, 109 },
+ { 0x00ed, 110 },
+ { 0x00ee, 111 },
+ { 0x00ef, 112 },
+ { 0x00f0, 113 },
+ { 0x00f2, 115 },
+ { 0x00f3, 116 },
+ { 0x00f4, 117 },
+ { 0x00f5, 118 },
+ { 0x00e6, 103 },
+ { 0x00e8, 105 },
+ { 0x00e3, 100 },
+ { 0x00fe, 127 },
+ { 0x00fb, 124 },
+ { 0x00fd, 126 },
+ { 0x00ff, 128 },
+ { 0x00f9, 122 },
+ { 0x00f8, 121 },
+ { 0x00fc, 125 },
+ { 0x00e0, 97 },
+ { 0x00f1, 114 },
+ { 0x00c1, 66 },
+ { 0x00c2, 67 },
+ { 0x00d7, 88 },
+ { 0x00c7, 72 },
+ { 0x00c4, 69 },
+ { 0x00c5, 70 },
+ { 0x00d6, 87 },
+ { 0x00da, 91 },
+ { 0x00c9, 74 },
+ { 0x00ca, 75 },
+ { 0x00cb, 76 },
+ { 0x00cc, 77 },
+ { 0x00cd, 78 },
+ { 0x00ce, 79 },
+ { 0x00cf, 80 },
+ { 0x00d0, 81 },
+ { 0x00d2, 83 },
+ { 0x00d3, 84 },
+ { 0x00d4, 85 },
+ { 0x00d5, 86 },
+ { 0x00c6, 71 },
+ { 0x00c8, 73 },
+ { 0x00c3, 68 },
+ { 0x00de, 95 },
+ { 0x00db, 92 },
+ { 0x00dd, 94 },
+ { 0x00df, 96 },
+ { 0x00d9, 90 },
+ { 0x00d8, 89 },
+ { 0x00dc, 93 },
+ { 0x00c0, 65 },
+ { 0x00d1, 82 },
+ { 0x00a3, 36 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x005f, 0 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x0093, 20 },
+ { 0x009b, 28 },
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x00a0, 33 },
+ { 0x00a1, 34 },
+ { 0x00a2, 35 },
+ { 0x00a4, 37 },
+ { 0x00a5, 38 },
+ { 0x00a6, 39 },
+ { 0x00a7, 40 },
+ { 0x00a8, 41 },
+ { 0x00a9, 42 },
+ { 0x00aa, 43 },
+ { 0x00ab, 44 },
+ { 0x00ac, 45 },
+ { 0x00ad, 46 },
+ { 0x00ae, 47 },
+ { 0x00af, 48 },
+ { 0x00b0, 49 },
+ { 0x00b1, 50 },
+ { 0x00b2, 51 },
+ { 0x00b4, 53 },
+ { 0x00b5, 54 },
+ { 0x00b6, 55 },
+ { 0x00b7, 56 },
+ { 0x00b8, 57 },
+ { 0x00b9, 58 },
+ { 0x00ba, 59 },
+ { 0x00bb, 60 },
+ { 0x00bc, 61 },
+ { 0x00bd, 62 },
+ { 0x00be, 63 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0094, 21 },
+ { 0x0000, 0 }
+ };
+
Index: char_maps/soutern.map
===================================================================
--- char_maps/soutern.map (revision 0)
+++ char_maps/soutern.map (revision 140)
@@ -0,0 +1,259 @@
+/*
+ !!! WARNING !!!
+ DON'T CHANGE ORDER OF CHARS
+*/
+
+struct codepage_map codepage_utf8sout_array[] =
+ {
+ { 0x000003, 121 }, // max size , char count
+ { 0x00c280, 1 },
+ { 0x00c281, 2 },
+ { 0x00c282, 3 },
+ { 0x00c283, 4 },
+ { 0x00c284, 5 },
+ { 0x00c285, 6 },
+ { 0x00c286, 7 },
+ { 0x00c287, 8 },
+ { 0x00c288, 9 },
+ { 0x00c289, 10 },
+ { 0x00c28a, 11 },
+ { 0x00c28b, 12 },
+ { 0x00c28c, 13 },
+ { 0x00c28d, 14 },
+ { 0x00c28e, 15 },
+ { 0x00c28f, 16 },
+ { 0x00c290, 17 },
+ { 0x00c291, 18 },
+ { 0x00c292, 19 },
+ { 0x00c293, 20 },
+ { 0x00c294, 21 },
+ { 0x00c295, 22 },
+ { 0x00c296, 23 },
+ { 0x00c297, 24 },
+ { 0x00c298, 25 },
+ { 0x00c299, 26 },
+ { 0x00c29a, 27 },
+ { 0x00c29b, 28 },
+ { 0x00c29c, 29 },
+ { 0x00c29d, 30 },
+ { 0x00c29e, 31 },
+ { 0x00c29f, 32 },
+ { 0x00c2a0, 33 },
+ { 0x00c2a3, 34 },
+ { 0x00c2a4, 35 },
+ { 0x00c2a7, 36 },
+ { 0x00c2a8, 37 },
+ { 0x00c2ad, 38 },
+ { 0x00c2b0, 39 },
+ { 0x00c2b2, 40 },
+ { 0x00c2b3, 41 },
+ { 0x00c2b4, 42 },
+ { 0x00c2b5, 43 },
+ { 0x00c2b7, 44 },
+ { 0x00c2b8, 45 },
+ { 0x00c2bd, 46 },
+ { 0x00c380, 47 },
+ { 0x00c381, 48 },
+ { 0x00c382, 49 },
+ { 0x00c384, 50 },
+ { 0x00c387, 51 },
+ { 0x00c388, 52 },
+ { 0x00c389, 53 },
+ { 0x00c38a, 54 },
+ { 0x00c38b, 55 },
+ { 0x00c38c, 56 },
+ { 0x00c38d, 57 },
+ { 0x00c38e, 58 },
+ { 0x00c38f, 59 },
+ { 0x00c391, 60 },
+ { 0x00c392, 61 },
+ { 0x00c393, 62 },
+ { 0x00c394, 63 },
+ { 0x00c396, 64 },
+ { 0x00c397, 65 },
+ { 0x00c399, 66 },
+ { 0x00c39a, 67 },
+ { 0x00c39b, 68 },
+ { 0x00c39c, 69 },
+ { 0x00c39f, 70 },
+ { 0x00c3a0, 71 },
+ { 0x00c3a1, 72 },
+ { 0x00c3a2, 73 },
+ { 0x00c3a4, 74 },
+ { 0x00c3a7, 75 },
+ { 0x00c3a8, 76 },
+ { 0x00c3a9, 77 },
+ { 0x00c3aa, 78 },
+ { 0x00c3ab, 79 },
+ { 0x00c3ac, 80 },
+ { 0x00c3ad, 81 },
+ { 0x00c3ae, 82 },
+ { 0x00c3af, 83 },
+ { 0x00c3b1, 84 },
+ { 0x00c3b2, 85 },
+ { 0x00c3b3, 86 },
+ { 0x00c3b4, 87 },
+ { 0x00c3b6, 88 },
+ { 0x00c3b7, 89 },
+ { 0x00c3b9, 90 },
+ { 0x00c3ba, 91 },
+ { 0x00c3bb, 92 },
+ { 0x00c3bc, 93 },
+ { 0x00c488, 94 },
+ { 0x00c489, 95 },
+ { 0x00c48a, 96 },
+ { 0x00c48b, 97 },
+ { 0x00c49c, 98 },
+ { 0x00c49d, 99 },
+ { 0x00c49e, 100 },
+ { 0x00c49f, 101 },
+ { 0x00c4a0, 102 },
+ { 0x00c4a1, 103 },
+ { 0x00c4a4, 104 },
+ { 0x00c4a5, 105 },
+ { 0x00c4a6, 106 },
+ { 0x00c4a7, 107 },
+ { 0x00c4b0, 108 },
+ { 0x00c4b1, 109 },
+ { 0x00c4b4, 110 },
+ { 0x00c4b5, 111 },
+ { 0x00c59c, 112 },
+ { 0x00c59d, 113 },
+ { 0x00c59e, 114 },
+ { 0x00c59f, 115 },
+ { 0x00c5ac, 116 },
+ { 0x00c5ad, 117 },
+ { 0x00c5bb, 118 },
+ { 0x00c5bc, 119 },
+ { 0x00cb98, 120 },
+ { 0x00cb99, 121 },
+ { 0x000000, 0 }
+ };
+
+struct codepage_map codepage_iso3_array[] =
+ {
+ { 0x0001, 121 }, // max size , char count for control
+ { 0x0080, 1 },
+ { 0x0081, 2 },
+ { 0x0082, 3 },
+ { 0x0083, 4 },
+ { 0x0084, 5 },
+ { 0x0085, 6 },
+ { 0x0086, 7 },
+ { 0x0087, 8 },
+ { 0x0088, 9 },
+ { 0x0089, 10 },
+ { 0x008a, 11 },
+ { 0x008b, 12 },
+ { 0x008c, 13 },
+ { 0x008d, 14 },
+ { 0x008e, 15 },
+ { 0x008f, 16 },
+ { 0x0090, 17 },
+ { 0x0091, 18 },
+ { 0x0092, 19 },
+ { 0x0093, 20 },
+ { 0x0094, 21 },
+ { 0x0095, 22 },
+ { 0x0096, 23 },
+ { 0x0097, 24 },
+ { 0x0098, 25 },
+ { 0x0099, 26 },
+ { 0x009a, 27 },
+ { 0x009b, 28 },
+ { 0x009c, 29 },
+ { 0x009d, 30 },
+ { 0x009e, 31 },
+ { 0x009f, 32 },
+ { 0x00a0, 33 },
+ { 0x00a3, 36 },
+ { 0x00a4, 37 },
+ { 0x00a7, 39 },
+ { 0x00a8, 40 },
+ { 0x00ad, 45 },
+ { 0x00b0, 47 },
+ { 0x00b2, 49 },
+ { 0x00b3, 50 },
+ { 0x00b4, 51 },
+ { 0x00b5, 52 },
+ { 0x00b7, 54 },
+ { 0x00b8, 55 },
+ { 0x00bd, 60 },
+ { 0x00c0, 62 },
+ { 0x00c1, 63 },
+ { 0x00c2, 64 },
+ { 0x00c4, 65 },
+ { 0x00c7, 68 },
+ { 0x00c8, 69 },
+ { 0x00c9, 70 },
+ { 0x00ca, 71 },
+ { 0x00cb, 72 },
+ { 0x00cc, 73 },
+ { 0x00cd, 74 },
+ { 0x00ce, 75 },
+ { 0x00cf, 76 },
+ { 0x00d1, 77 },
+ { 0x00d2, 78 },
+ { 0x00d3, 79 },
+ { 0x00d4, 80 },
+ { 0x00d6, 82 },
+ { 0x00d7, 83 },
+ { 0x00d9, 85 },
+ { 0x00da, 86 },
+ { 0x00db, 87 },
+ { 0x00dc, 88 },
+ { 0x00df, 91 },
+ { 0x00e0, 92 },
+ { 0x00e1, 93 },
+ { 0x00e2, 94 },
+ { 0x00e4, 95 },
+ { 0x00e7, 98 },
+ { 0x00e8, 99 },
+ { 0x00e9, 100 },
+ { 0x00ea, 101 },
+ { 0x00eb, 102 },
+ { 0x00ec, 103 },
+ { 0x00ed, 104 },
+ { 0x00ee, 105 },
+ { 0x00ef, 106 },
+ { 0x00f1, 107 },
+ { 0x00f2, 108 },
+ { 0x00f3, 109 },
+ { 0x00f4, 110 },
+ { 0x00f6, 112 },
+ { 0x00f7, 113 },
+ { 0x00f9, 115 },
+ { 0x00fa, 116 },
+ { 0x00fb, 117 },
+ { 0x00fc, 118 },
+ { 0x00c6, 67 },
+ { 0x00e6, 97 },
+ { 0x00c5, 66 },
+ { 0x00e5, 96 },
+ { 0x00d8, 84 },
+ { 0x00f8, 114 },
+ { 0x00ab, 43 },
+ { 0x00bb, 58 },
+ { 0x00d5, 81 },
+ { 0x00f5, 111 },
+ { 0x00a6, 38 },
+ { 0x00b6, 53 },
+ { 0x00a1, 34 },
+ { 0x00b1, 48 },
+ { 0x00a9, 41 },
+ { 0x00b9, 56 },
+ { 0x00ac, 44 },
+ { 0x00bc, 59 },
+ { 0x00de, 90 },
+ { 0x00fe, 120 },
+ { 0x00aa, 42 },
+ { 0x00ba, 57 },
+ { 0x00dd, 89 },
+ { 0x00fd, 119 },
+ { 0x00af, 46 },
+ { 0x00bf, 61 },
+ { 0x00a2, 35 },
+ { 0x00ff, 121 },
+ { 0x0000, 0 }
+ };
+
Index: postlogin.c
===================================================================
--- postlogin.c (revision 132)
+++ postlogin.c (revision 140)
@@ -25,8 +25,10 @@
#include "access.h"
#include "features.h"
#include "ssl.h"
+#include "charconv.h"
#include "vsftpver.h"
#include "opts.h"
+#include "http.h"
/* Private local functions */
static void handle_pwd(struct vsf_session* p_sess);
@@ -60,7 +62,6 @@
static void handle_stat_file(struct vsf_session* p_sess);
static void handle_logged_in_user(struct vsf_session* p_sess);
static void handle_logged_in_pass(struct vsf_session* p_sess);
-static void handle_http(struct vsf_session* p_sess);
static int pasv_active(struct vsf_session* p_sess);
static int port_active(struct vsf_session* p_sess);
@@ -88,11 +89,31 @@
{
vsf_sysutil_set_umask(tunable_anon_umask);
p_sess->bw_rate_max = tunable_anon_max_rate;
+ if (tunable_anon_rxtx_rate)
+ {
+ p_sess->bw_rate_max_rx = tunable_anon_max_rate_rx;
+ p_sess->bw_rate_max_tx = tunable_anon_max_rate_tx;
+ }
+ else
+ {
+ p_sess->bw_rate_max_rx = tunable_anon_max_rate;
+ p_sess->bw_rate_max_tx = tunable_anon_max_rate;
+ }
}
else
{
vsf_sysutil_set_umask(tunable_local_umask);
p_sess->bw_rate_max = tunable_local_max_rate;
+ if (tunable_local_rxtx_rate)
+ {
+ p_sess->bw_rate_max_rx = tunable_local_max_rate_rx;
+ p_sess->bw_rate_max_tx = tunable_local_max_rate_tx;
+ }
+ else
+ {
+ p_sess->bw_rate_max_rx = tunable_local_max_rate;
+ p_sess->bw_rate_max_tx = tunable_local_max_rate;
+ }
}
if (p_sess->is_http)
{
@@ -108,7 +129,16 @@
/* Handle any login message */
vsf_banner_dir_changed(p_sess, FTP_LOGINOK);
vsf_cmdio_write(p_sess, FTP_LOGINOK, "Login successful.");
-
+ vsf_charconv_init_local_codepage(tunable_local_codepage);
+ tunable_remote_codepage = p_sess->remote_charset;
+ if (tunable_convert_charset_enable)
+ {
+ p_sess->enable_convertion = vsf_charconv_avail_convertion(tunable_local_codepage, p_sess->remote_charset);
+ }
+ else
+ {
+ p_sess->enable_convertion = 0;
+ }
while(1)
{
int cmd_ok = 1;
@@ -118,7 +148,7 @@
}
/* Blocks */
vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
- &p_sess->ftp_arg_str, 1);
+ &p_sess->ftp_arg_str, 1, 0);
if (tunable_setproctitle_enable)
{
struct mystr proctitle_str = INIT_MYSTR;
@@ -262,7 +292,7 @@
handle_rmd(p_sess);
}
else if (tunable_write_enable &&
- (tunable_anon_other_write_enable || !p_sess->is_anonymous) &&
+ ((tunable_anon_other_write_enable && tunable_anon_delete_enable) || !p_sess->is_anonymous) &&
str_equal_text(&p_sess->ftp_cmd_str, "DELE"))
{
handle_dele(p_sess);
@@ -446,6 +476,12 @@
}
}
+void
+process_http_retr(struct vsf_session* p_sess)
+{
+ handle_retr(p_sess, 1);
+}
+
static void
handle_pwd(struct vsf_session* p_sess)
{
@@ -670,6 +706,7 @@
vsf_sysutil_lock_file_read(opened_file);
}
vsf_sysutil_fstat(opened_file, &s_p_statbuf);
+ p_sess->retr_owner_uid = vsf_sysutil_statbuf_get_uid(s_p_statbuf);
/* No games please */
if (!vsf_sysutil_statbuf_is_regfile(s_p_statbuf))
{
@@ -716,6 +753,7 @@
str_append_filesize_t(&s_mark_str,
vsf_sysutil_statbuf_get_size(s_p_statbuf));
str_append_text(&s_mark_str, " bytes).");
+ p_sess->bw_rate_max = p_sess->bw_rate_max_tx;
if (is_http)
{
remote_fd = VSFTP_COMMAND_FD;
@@ -767,6 +805,7 @@
pasv_cleanup(p_sess);
file_close_out:
vsf_sysutil_close(opened_file);
+ p_sess->retr_owner_uid = 0;
}
static void
@@ -861,6 +900,7 @@
}
else
{
+ p_sess->bw_rate_max = p_sess->bw_rate_max_tx;
int remote_fd = get_remote_transfer_fd(
p_sess, "Here comes the directory listing.");
if (vsf_sysutil_retval_is_error(remote_fd))
@@ -1052,9 +1092,9 @@
vsf_sysutil_deactivate_noblock(new_file_fd);
}
/* Are we required to chown() this file for security? */
- if (p_sess->is_anonymous && tunable_chown_uploads)
+ if (p_sess->is_anonymous && tunable_chown_uploads && !is_append && offset == 0)
{
- vsf_sysutil_fchmod(new_file_fd, tunable_chown_upload_mode);
+ vsf_sysutil_fchmod(new_file_fd, (tunable_chown_upload_mode & ~tunable_anon_umask));
if (tunable_one_process_model)
{
vsf_one_process_chown_upload(p_sess, new_file_fd);
@@ -1084,6 +1124,7 @@
{
vsf_sysutil_lseek_end(new_file_fd);
}
+ p_sess->bw_rate_max = p_sess->bw_rate_max_rx;
if (is_unique)
{
struct mystr resp_str = INIT_MYSTR;
@@ -1115,6 +1156,8 @@
trans_ret.retval = -2;
}
p_sess->transfer_size = trans_ret.transferred;
+ vsf_sysutil_fstat(new_file_fd, &s_p_statbuf);
+ p_sess->retr_owner_uid = vsf_sysutil_statbuf_get_uid(s_p_statbuf);
if (trans_ret.retval == 0)
{
success = 1;
@@ -1141,6 +1184,7 @@
str_unlink(p_filename);
}
vsf_sysutil_close(new_file_fd);
+ p_sess->retr_owner_uid = 0;
}
static void
@@ -1366,7 +1410,7 @@
return;
}
/* Get the async command - blocks (use data timeout alarm) */
- vsf_cmdio_get_cmd_and_arg(p_sess, &async_cmd_str, &async_arg_str, 0);
+ vsf_cmdio_get_cmd_and_arg(p_sess, &async_cmd_str, &async_arg_str, 0, 0);
/* Chop off first four characters; they are telnet characters. The client
* should have sent the first two normally and the second two as urgent
* data.
@@ -1727,14 +1771,11 @@
{
vsf_cmdio_write_hyphen(p_sess, FTP_HELP,
"The following commands are recognized.");
- vsf_cmdio_write_raw(p_sess,
-" ABOR ACCT ALLO APPE CDUP CWD DELE EPRT EPSV FEAT HELP LIST MDTM MKD\r\n");
- vsf_cmdio_write_raw(p_sess,
-" MODE NLST NOOP OPTS PASS PASV PORT PWD QUIT REIN REST RETR RMD RNFR\r\n");
- 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");
+ vsf_cmdio_write_raw_quiet(p_sess,
+ " ABOR ACCT ALLO APPE CDUP CWD DELE EPRT EPSV FEAT HELP LIST MDTM MKD\r\n"
+ " MODE NLST NOOP OPTS PASS PASV PORT PWD QUIT REIN REST RETR RMD RNFR\r\n"
+ " RNTO SITE SIZE SMNT STAT STOR STOU STRU SYST TYPE USER XCUP XCWD XMKD\r\n"
+ " XPWD XRMD\r\n");
vsf_cmdio_write(p_sess, FTP_HELP, "Help OK.");
}
@@ -1777,65 +1818,95 @@
handle_stat(struct vsf_session* p_sess)
{
vsf_cmdio_write_hyphen(p_sess, FTP_STATOK, "FTP server status:");
- vsf_cmdio_write_raw(p_sess, " Connected to ");
- vsf_cmdio_write_raw(p_sess, str_getbuf(&p_sess->remote_ip_str));
- vsf_cmdio_write_raw(p_sess, "\r\n");
- vsf_cmdio_write_raw(p_sess, " Logged in as ");
- vsf_cmdio_write_raw(p_sess, str_getbuf(&p_sess->user_str));
- vsf_cmdio_write_raw(p_sess, "\r\n");
- vsf_cmdio_write_raw(p_sess, " TYPE: ");
+ vsf_cmdio_write_raw_quiet(p_sess, " Connected to ");
+ vsf_cmdio_write_raw_quiet(p_sess, str_getbuf(&p_sess->remote_ip_str));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Logged in as ");
+ vsf_cmdio_write_raw_quiet(p_sess, str_getbuf(&p_sess->user_str));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " TYPE: ");
if (p_sess->is_ascii)
{
- vsf_cmdio_write_raw(p_sess, "ASCII\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, "ASCII\r\n");
}
else
{
- vsf_cmdio_write_raw(p_sess, "BINARY\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, "BINARY\r\n");
}
- if (p_sess->bw_rate_max == 0)
+
+ if (p_sess->bw_rate_max_rx == 0)
{
- vsf_cmdio_write_raw(p_sess, " No session bandwidth limit\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " No session upload bandwidth limit\r\n");
}
else
{
- vsf_cmdio_write_raw(p_sess, " Session bandwidth limit in byte/s is ");
- vsf_cmdio_write_raw(p_sess, vsf_sysutil_ulong_to_str(p_sess->bw_rate_max));
- vsf_cmdio_write_raw(p_sess, "\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Session upload bandwidth limit in byte/s is ");
+ vsf_cmdio_write_raw_quiet(p_sess, vsf_sysutil_ulong_to_str(p_sess->bw_rate_max_rx));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
}
+ if (p_sess->bw_rate_max_tx == 0)
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, " No session download bandwidth limit\r\n");
+ }
+ else
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, " Session download bandwidth limit in byte/s is ");
+ vsf_cmdio_write_raw_quiet(p_sess, vsf_sysutil_ulong_to_str(p_sess->bw_rate_max_tx));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
+ }
if (tunable_idle_session_timeout == 0)
{
- vsf_cmdio_write_raw(p_sess, " No session timeout\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " No session timeout\r\n");
}
else
{
- vsf_cmdio_write_raw(p_sess, " Session timeout in seconds is ");
- vsf_cmdio_write_raw(p_sess,
+ vsf_cmdio_write_raw_quiet(p_sess, " Session timeout in seconds is ");
+ vsf_cmdio_write_raw_quiet(p_sess,
vsf_sysutil_ulong_to_str(tunable_idle_session_timeout));
- vsf_cmdio_write_raw(p_sess, "\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
}
if (p_sess->control_use_ssl)
{
- vsf_cmdio_write_raw(p_sess, " Control connection is encrypted\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Control connection is encrypted\r\n");
}
else
{
- vsf_cmdio_write_raw(p_sess, " Control connection is plain text\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Control connection is plain text\r\n");
}
if (p_sess->data_use_ssl)
{
- vsf_cmdio_write_raw(p_sess, " Data connections will be encrypted\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Data connections will be encrypted\r\n");
}
else
{
- vsf_cmdio_write_raw(p_sess, " Data connections will be plain text\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Data connections will be plain text\r\n");
}
if (p_sess->num_clients > 0)
{
- vsf_cmdio_write_raw(p_sess, " At session startup, client count was ");
- vsf_cmdio_write_raw(p_sess, vsf_sysutil_ulong_to_str(p_sess->num_clients));
- vsf_cmdio_write_raw(p_sess, "\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " At session startup, client count was ");
+ vsf_cmdio_write_raw_quiet(p_sess, vsf_sysutil_ulong_to_str(p_sess->num_clients));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
}
- vsf_cmdio_write_raw(p_sess,
+ if (tunable_convert_charset_enable)
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, " Server charset is ");
+ vsf_cmdio_write_raw_quiet(p_sess, vsf_charconv_charset_name(tunable_local_codepage));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Remote charset is ");
+ vsf_cmdio_write_raw_quiet(p_sess, vsf_charconv_charset_name(p_sess->remote_charset));
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
+ vsf_cmdio_write_raw_quiet(p_sess, " Char convertion is ");
+ if (p_sess->enable_convertion)
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, "on");
+ }
+ else
+ {
+ vsf_cmdio_write_raw_quiet(p_sess, "off");
+ }
+ vsf_cmdio_write_raw_quiet(p_sess, "\r\n");
+ }
+ vsf_cmdio_write_raw_quiet(p_sess,
" vsFTPd " VSF_VERSION " - secure, fast, stable\r\n");
vsf_cmdio_write(p_sess, FTP_STATOK, "End of status");
}
@@ -1919,53 +1990,3 @@
{
vsf_cmdio_write(p_sess, FTP_LOGINOK, "Already logged in.");
}
-
-static void
-handle_http(struct vsf_session* p_sess)
-{
- /* Warning: Doesn't respect cmds_allowed etc. because there is currently only
- * one command (GET)!
- * HTTP likely doesn't respect other important FTP options. I don't think
- * logging works.
- */
- if (!tunable_download_enable)
- {
- bug("HTTP needs download - fix your config");
- }
- /* Eat the HTTP headers, which we don't care about. */
- do
- {
- vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
- &p_sess->ftp_arg_str, 1);
- }
- while (!str_isempty(&p_sess->ftp_cmd_str) ||
- !str_isempty(&p_sess->ftp_arg_str));
- vsf_cmdio_write_raw(p_sess, "HTTP/1.1 200 OK\r\n");
- vsf_cmdio_write_raw(p_sess, "Server: vsftpd\r\n");
- vsf_cmdio_write_raw(p_sess, "Connection: close\r\n");
- vsf_cmdio_write_raw(p_sess, "X-Frame-Options: SAMEORIGIN\r\n");
- vsf_cmdio_write_raw(p_sess, "X-Content-Type-Options: nosniff\r\n");
- /* Split the path from the HTTP/1.x */
- str_split_char(&p_sess->http_get_arg, &p_sess->ftp_arg_str, ' ');
- str_copy(&p_sess->ftp_arg_str, &p_sess->http_get_arg);
- str_split_char(&p_sess->http_get_arg, &p_sess->ftp_cmd_str, '.');
- str_upper(&p_sess->ftp_cmd_str);
- if (str_equal_text(&p_sess->ftp_cmd_str, "HTML") ||
- str_equal_text(&p_sess->ftp_cmd_str, "HTM"))
- {
- vsf_cmdio_write_raw(p_sess, "Content-Type: text/html\r\n");
- }
- else
- {
- vsf_cmdio_write_raw(p_sess, "Content-Type: dunno\r\n");
- }
- vsf_cmdio_write_raw(p_sess, "\r\n");
- p_sess->is_ascii = 0;
- p_sess->restart_pos = 0;
- handle_retr(p_sess, 1);
- if (vsf_log_entry_pending(p_sess))
- {
- vsf_log_do_log(p_sess, 0);
- }
- vsf_sysutil_exit(0);
-}
Index: prelogin.c
===================================================================
--- prelogin.c (revision 132)
+++ prelogin.c (revision 140)
@@ -34,6 +34,7 @@
static void handle_get(struct vsf_session* p_sess);
static void check_login_delay();
static void check_login_fails(struct vsf_session* p_sess);
+static void anti_bruteforce(struct vsf_session* p_sess);
void
init_connection(struct vsf_session* p_sess)
@@ -105,8 +106,7 @@
}
else if (tunable_ftpd_banner == 0)
{
- vsf_cmdio_write(p_sess, FTP_GREET, "(vsFTPd " VSF_VERSION
- ")");
+ vsf_cmdio_write(p_sess, FTP_GREET, "vsFTPd " VSF_VERSION " ready...");
}
else
{
@@ -120,7 +120,7 @@
while (1)
{
vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
- &p_sess->ftp_arg_str, 1);
+ &p_sess->ftp_arg_str, 1, 0);
if (tunable_ftp_enable)
{
if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
@@ -202,22 +202,21 @@
* non-anonymous usernames in the hope we save passwords going plaintext
* over the network
*/
- int is_anon = 1;
str_copy(&p_sess->user_str, &p_sess->ftp_arg_str);
str_upper(&p_sess->ftp_arg_str);
if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") &&
!str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS"))
{
- is_anon = 0;
+ p_sess->is_anonymous = 0;
}
- if (!tunable_local_enable && !is_anon)
+ if (!tunable_local_enable && !p_sess->is_anonymous)
{
vsf_cmdio_write(
p_sess, FTP_LOGINERR, "This FTP server is anonymous only.");
str_empty(&p_sess->user_str);
return;
}
- if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl &&
+ if (p_sess->is_anonymous && p_sess->control_use_ssl && !tunable_allow_anon_ssl &&
!tunable_force_anon_logins_ssl)
{
vsf_cmdio_write(
@@ -225,14 +224,14 @@
str_empty(&p_sess->user_str);
return;
}
- if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl &&
+ if (tunable_ssl_enable && !p_sess->is_anonymous && !p_sess->control_use_ssl &&
tunable_force_local_logins_ssl)
{
vsf_cmdio_write(
p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption.");
vsf_sysutil_exit(0);
}
- if (tunable_ssl_enable && is_anon && !p_sess->control_use_ssl &&
+ if (tunable_ssl_enable && p_sess->is_anonymous && !p_sess->control_use_ssl &&
tunable_force_anon_logins_ssl)
{
vsf_cmdio_write(
@@ -246,13 +245,26 @@
(!located && !tunable_userlist_deny))
{
check_login_delay();
- vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied.");
check_login_fails(p_sess);
+ if (tunable_userlist_log)
+ {
+ struct mystr str_log_line = INIT_MYSTR;
+ if (tunable_userlist_deny)
+ {
+ str_alloc_text(&str_log_line, "User is in the deny user list.");
+ }
+ else
+ {
+ str_alloc_text(&str_log_line, "User is not in the allow user list.");
+ }
+ vsf_log_failed_line(p_sess, kVSFLogEntryLogin, &str_log_line);
+ str_free(&str_log_line);
+ }
str_empty(&p_sess->user_str);
return;
}
}
- if (is_anon && tunable_no_anon_password)
+ if (p_sess->is_anonymous && tunable_no_anon_password)
{
/* Fake a password */
str_alloc_text(&p_sess->ftp_arg_str, "");
@@ -272,17 +284,26 @@
vsf_cmdio_write(p_sess, FTP_NEEDUSER, "Login with USER first.");
return;
}
- /* These login calls never return if successful */
- if (tunable_one_process_model)
+
+ if (!p_sess->is_http && !tunable_anonymous_enable && p_sess->is_anonymous)
{
- vsf_one_process_login(p_sess, &p_sess->ftp_arg_str);
+ vsf_cmdio_write(
+ p_sess, FTP_LOGINERR, "This FTP server does not allow anonymous logins.");
}
else
{
- vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);
+ /* These login calls never return if successful */
+ if (tunable_one_process_model)
+ {
+ vsf_one_process_login(p_sess, &p_sess->ftp_arg_str);
+ }
+ else
+ {
+ vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);
+ }
+ check_login_delay();
+ check_login_fails(p_sess);
}
- vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect.");
- check_login_fails(p_sess);
str_empty(&p_sess->user_str);
/* FALLTHRU if login fails */
}
@@ -299,6 +320,69 @@
{
if (++p_sess->login_fails >= tunable_max_login_fails)
{
- vsf_sysutil_exit(0);
+ if (tunable_anti_bruteforce)
+ {
+ anti_bruteforce(p_sess);
+ }
+ else
+ {
+ vsf_cmdio_write_exit(p_sess, FTP_LOGINERR, "Too many login attempts.");
+ }
}
+ else
+ {
+ vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied.");
+ }
}
+
+static const char* cmds = "ABOR\nACCT\nALLO\nAPPE\nCDUP\nCWD\nDELE\nEPRT\nEPSV\nFEAT\nHELP\nLIST\nMDTM\nMKD\n"
+ "MODE\nNLST\nNOOP\nOPTS\nPASS\nPASV\nPORT\nPWD\nQUIT\nREIN\nREST\nRETR\nRMD\nRNFR\n"
+ "RNTO\nSITE\nSIZE\nSMNT\nSTAT\nSTOR\nSTOU\nSTRU\nSYST\nTYPE\nUSER\nXCUP\nXCWD\nXMKD\n"
+ "XPWD\nXRMD";
+
+static void
+anti_bruteforce(struct vsf_session* p_sess)
+{
+ static struct mystr str_cmds = INIT_MYSTR;
+ str_alloc_text(&str_cmds, cmds);
+
+ tunable_log_ftp_protocol = 0;
+
+ if (tunable_anti_bruteforce_banner)
+ {
+ vsf_cmdio_write_hyphen(p_sess, FTP_LOGINOK, tunable_anti_bruteforce_banner);
+ }
+ vsf_cmdio_write(p_sess, FTP_LOGINOK, "Login successful.");
+
+ while (1)
+ {
+ vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
+ &p_sess->ftp_arg_str, 1, 1);
+
+ if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
+ {
+ vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.");
+ }
+ else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
+ {
+ handle_feat(p_sess);
+ }
+ else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS"))
+ {
+ handle_opts(p_sess);
+ }
+ else if (str_contains_line(&str_cmds, &p_sess->ftp_cmd_str))
+ {
+ vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");
+ }
+ else if (str_isempty(&p_sess->ftp_cmd_str) &&
+ str_isempty(&p_sess->ftp_arg_str))
+ {
+ /* Deliberately ignore to avoid NAT device bugs. ProFTPd does the same. */
+ }
+ else
+ {
+ vsf_cmdio_write(p_sess, FTP_BADCMD, "Unknown command.");
+ }
+ }
+ }
Index: postlogin.h
===================================================================
--- postlogin.h (revision 132)
+++ postlogin.h (revision 140)
@@ -11,5 +11,13 @@
*/
void process_post_login(struct vsf_session* p_sess);
+/* process_http_retr()
+ * PURPOSE
+ * Called to retrive file for http reply.
+ * PARAMETERS
+ * p_sess - the current session object
+ */
+void process_http_retr(struct vsf_session* p_sess);
+
#endif /* VSF_POSTLOGIN_H */
Index: pasvrules.c
===================================================================
--- pasvrules.c (revision 0)
+++ pasvrules.c (revision 140)
@@ -0,0 +1,310 @@
+/*
+ * Part of Very Secure FTPd
+ * Licence: GPL v2
+ * Author: Dmitriy Balashov
+ * pasvrules.c
+ */
+
+#include "pasvrules.h"
+#include "tunables.h"
+#include "str.h"
+#include "session.h"
+#include "filestr.h"
+#include "defs.h"
+#include "sysutil.h"
+#include "logging.h"
+#include "ftpcodes.h"
+#include "ftpcmdio.h"
+#include "charconv.h"
+#include "utility.h"
+
+static int parse_rules(struct mystr* p_rule_str, pasv_rules rule);
+pasv_rules find_rule(struct vsf_session* p_sess);
+void dispose_rules();
+
+static pasv_rules rules_list = 0;
+
+void
+vsf_pasvrules_load(const char* p_filename)
+{
+ struct mystr rules_file_str = INIT_MYSTR;
+ struct mystr rule_setting_str = INIT_MYSTR;
+ unsigned int str_pos = 0;
+ int retval;
+ pasv_rules rule = 0, owner = 0;
+
+ retval = str_fileread(&rules_file_str, p_filename, VSFTP_CONF_FILE_MAX);
+ if (vsf_sysutil_retval_is_error(retval))
+ {
+ return;
+ }
+
+ while (str_getline(&rules_file_str, &rule_setting_str, &str_pos))
+ {
+ if (str_isempty(&rule_setting_str) ||
+ str_get_char_at(&rule_setting_str, 0) == '#')
+ {
+ continue;
+ }
+ if (!rules_list)
+ {
+ rule = vsf_sysutil_malloc_zero(sizeof(pasv_rule));
+ rules_list = rule;
+ }
+ else
+ {
+ owner = rule;
+ rule = vsf_sysutil_malloc_zero(sizeof(pasv_rule));
+ owner->next = rule;
+ }
+ if (parse_rules(&rule_setting_str, rule) == 0)
+ {
+ vsf_sysutil_free(rule);
+ if (owner)
+ {
+ owner->next = 0;
+ }
+ else
+ {
+ rules_list = 0;
+ }
+ }
+ }
+ str_free(&rules_file_str);
+ if (!str_isempty(&rule_setting_str))
+ {
+ str_free(&rule_setting_str);
+ }
+ if (rules_list && tunable_add_default_rule)
+ {
+ owner = rule;
+ rule = vsf_sysutil_malloc_zero(sizeof(pasv_rule));
+ owner->next = rule;
+
+ rule->remote_charset = vsf_charconv_codepage(tunable_remote_charset);
+ rule->allow_anonymous = tunable_anonymous_enable;
+ rule->anon_upl_enable = tunable_anon_upload_enable;
+ rule->anon_md_enable = tunable_anon_mkdir_write_enable;
+ rule->anon_oth_enable = tunable_anon_other_write_enable;
+ rule->anon_del_enable = tunable_anon_delete_enable;
+ }
+}
+
+void
+vsf_pasvrules_define(struct vsf_session* p_sess)
+{
+ static pasv_rules rules;
+ rules = find_rule(p_sess);
+
+ if (rules)
+ {
+ tunable_anonymous_enable = rules->allow_anonymous;
+ tunable_anon_upload_enable = rules->anon_upl_enable;
+ tunable_anon_mkdir_write_enable = rules->anon_md_enable;
+ tunable_anon_other_write_enable = rules->anon_oth_enable;
+ tunable_anon_delete_enable = rules->anon_del_enable;
+ if (tunable_pasv_address)
+ {
+ vsf_sysutil_free((char*) tunable_pasv_address);
+ }
+ tunable_pasv_address = str_strdup(&rules->pasv_address);
+
+ p_sess->remote_charset = rules->remote_charset;
+ dispose_rules();
+ }
+ else
+ {
+ p_sess->remote_charset = vsf_charconv_codepage(tunable_remote_charset);
+ }
+
+ /* Resolve pasv_address if required */
+ if (tunable_pasv_address && tunable_pasv_addr_resolve)
+ {
+ struct vsf_sysutil_sockaddr* p_addr = 0;
+ const char* p_numeric_addr;
+ vsf_sysutil_dns_resolve(&p_addr, tunable_pasv_address);
+ vsf_sysutil_free((char*) tunable_pasv_address);
+ p_numeric_addr = vsf_sysutil_inet_ntop(p_addr);
+ tunable_pasv_address = vsf_sysutil_strdup(p_numeric_addr);
+ vsf_sysutil_free(p_addr);
+ }
+}
+
+static int
+parse_rules(struct mystr* p_rule_str, pasv_rules rule)
+{
+ static struct mystr s_lhs_chunk_str;
+ static struct mystr s_rhs_chunk_str;
+ static struct vsf_sysutil_sockaddr *sockaddr;
+ int mask, calc_mask, res_bool;
+ int is_remote_charset = 0;
+
+ str_replace_char(p_rule_str, '\t', ' ');
+ str_trim_char(p_rule_str, ' ');
+
+ str_copy(&s_lhs_chunk_str, p_rule_str);
+ str_free(p_rule_str);
+
+ vsf_sysutil_sockaddr_alloc_ipv4(&sockaddr);
+
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' '); // Get local_ip
+ str_append_char(&s_lhs_chunk_str, '\0');
+ if (vsf_sysutil_inet_aton(str_getbuf(&s_lhs_chunk_str), sockaddr) == 0)
+ {
+ return 0;
+ }
+ rule->local_ip = *(int*)vsf_sysutil_sockaddr_get_raw_addr(sockaddr);
+
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str); // Get remote_mask1
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, '/');
+ str_append_char(&s_lhs_chunk_str, '\0');
+ if (vsf_sysutil_inet_aton(str_getbuf(&s_lhs_chunk_str), sockaddr) == 0)
+ {
+ return 0;
+ }
+ rule->remote_mask1 = *(unsigned int*)vsf_sysutil_sockaddr_get_raw_addr(sockaddr);
+
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str); // Get remote_mask2
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+ mask = str_atoi(&s_lhs_chunk_str);
+ if (mask <= 0)
+ {
+ rule->remote_mask2 = 0;
+ }
+ else
+ if (mask >= 32)
+ {
+ rule->remote_mask2 = 0xFFFFFFFF;
+ }
+ else
+ {
+ calc_mask = 1;
+ calc_mask <<= (32 - mask);
+ calc_mask--;
+ calc_mask ^= 0xFFFFFFFF;
+
+ rule->remote_mask2 = ((calc_mask & 0x000000FF) << 24) | ((calc_mask & 0x0000FF00) << 8) | ((calc_mask & 0x00FF0000) >> 8) | ((calc_mask & 0xFF000000) >> 24);
+ }
+ rule->remote_mask1 &= rule->remote_mask2;
+
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str); // Get pasv_address
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+
+ str_copy(&rule->pasv_address, &s_lhs_chunk_str);
+ str_append_char(&rule->pasv_address, '\0');
+
+ rule->remote_charset = vsf_charconv_codepage(tunable_remote_charset);
+ rule->allow_anonymous = tunable_anonymous_enable;
+ rule->anon_upl_enable = tunable_anon_upload_enable;
+ rule->anon_md_enable = tunable_anon_mkdir_write_enable;
+ rule->anon_oth_enable = tunable_anon_other_write_enable;
+ rule->anon_del_enable = tunable_anon_delete_enable;
+
+ if (!str_isempty(&s_rhs_chunk_str))
+ { // Get remote_charset
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+ str_upper(&s_lhs_chunk_str);
+ if (str_equal_bool(&s_lhs_chunk_str) >= 0)
+ {
+ is_remote_charset = 0;
+ }
+ else
+ {
+ str_append_char(&s_lhs_chunk_str, '\0');
+ rule->remote_charset = vsf_charconv_codepage(str_getbuf(&s_lhs_chunk_str));
+ is_remote_charset = 1;
+ }
+ }
+ if (!str_isempty(&s_rhs_chunk_str) || !is_remote_charset)
+ { // Get allow_anonymous
+ if (is_remote_charset)
+ {
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+ }
+ if ((res_bool = str_equal_bool(&s_lhs_chunk_str)) >= 0)
+ {
+ rule->allow_anonymous = res_bool;
+ }
+ }
+
+ if (!str_isempty(&s_rhs_chunk_str))
+ { // Get anon_upl_enable
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+ if ((res_bool = str_equal_bool(&s_lhs_chunk_str)) >= 0)
+ {
+ rule->anon_upl_enable = res_bool;
+ }
+ }
+
+ if (!str_isempty(&s_rhs_chunk_str))
+ { // Get anon_md_enable
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+ if ((res_bool = str_equal_bool(&s_lhs_chunk_str)) >= 0)
+ {
+ rule->anon_md_enable = res_bool;
+ }
+ }
+
+ if (!str_isempty(&s_rhs_chunk_str))
+ { // Get anon_oth_enable
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+ if ((res_bool = str_equal_bool(&s_lhs_chunk_str)) >= 0)
+ {
+ rule->anon_oth_enable = res_bool;
+ }
+ }
+
+ if (!str_isempty(&s_rhs_chunk_str))
+ { // Get anon_del_enable
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+ if ((res_bool = str_equal_bool(&s_lhs_chunk_str)) >= 0)
+ {
+ rule->anon_del_enable = res_bool;
+ }
+ }
+
+ vsf_sysutil_sockaddr_clear(&sockaddr);
+ return 1;
+}
+
+void
+dispose_rules()
+{
+ static pasv_rules rules;
+
+ while (rules_list)
+ {
+ rules = rules_list->next;
+ str_free(&rules_list->pasv_address);
+ vsf_sysutil_free(rules_list);
+ rules_list = rules;
+ }
+}
+
+pasv_rules
+find_rule(struct vsf_session* p_sess)
+{
+ static pasv_rules rules;
+ rules = rules_list;
+ unsigned int local_ip = *(unsigned int*)vsf_sysutil_sockaddr_get_raw_addr(p_sess->p_local_addr);
+ unsigned int remote_ip = *(unsigned int*)vsf_sysutil_sockaddr_get_raw_addr(p_sess->p_remote_addr);
+
+ while (rules)
+ {
+ if ((rules->local_ip == 0 ||
+ rules->local_ip == local_ip) &&
+ rules->remote_mask1 == (remote_ip & rules->remote_mask2))
+ {
+ break;
+ }
+ rules = rules->next;
+ }
+
+ return rules;
+}
Index: pasvrules.h
===================================================================
--- pasvrules.h (revision 0)
+++ pasvrules.h (revision 140)
@@ -0,0 +1,44 @@
+#ifndef VSF_PASVRULES_H
+#define VSF_PASVRULES_H
+
+#ifndef VSFTP_STR_H
+#include "str.h"
+#endif
+
+struct vsf_session;
+
+
+typedef struct pasv_rule
+{
+ unsigned int local_ip ;
+ unsigned int remote_mask1 ;
+ unsigned int remote_mask2 ;
+ struct mystr pasv_address ;
+ int remote_charset ; // default tunable_remaote_charset
+ int allow_anonymous ; // default tunable_anonymous_enable
+ int anon_upl_enable ; // default tunable_anon_upload_enable
+ int anon_md_enable ; // default tunable_anon_mkdir_write_enable
+ int anon_oth_enable ; // default tunable_anon_other_write_enable
+ int anon_del_enable ; // default tunable_allow_anon_delete
+ void * next ;
+} pasv_rule;
+
+typedef struct pasv_rule * pasv_rules;
+
+/* vsf_pasvrules_load()
+ * PURPOSE
+ * Load file with rules
+ * PARAMETERS
+ * p_filename - file name with rules
+ */
+void vsf_pasvrules_load(const char* p_filename);
+
+/* vsf_pasvrules_define()
+ * PURPOSE
+ * Find rule for IP in session
+ * PARAMETERS
+ * p_sess - session
+ */
+void vsf_pasvrules_define(struct vsf_session* p_sess);
+
+#endif /* VSF_PASVRULES_H */
Index: usersip.c
===================================================================
--- usersip.c (revision 0)
+++ usersip.c (revision 140)
@@ -0,0 +1,223 @@
+/*
+ * Part of Very Secure FTPd
+ * Licence: GPL v2
+ * Author: Dmitriy Balashov
+ * usersip.c
+ */
+
+#include "usersip.h"
+#include "tunables.h"
+#include "str.h"
+#include "filestr.h"
+#include "sysutil.h"
+#include "session.h"
+#include "defs.h"
+#include "logging.h"
+#include "utility.h"
+#include "charconv.h"
+
+static void parse_rules(struct mystr* p_rule_str);
+
+static ip_rules rules_list = 0;
+
+void
+vsf_userip_load(const char* p_filename)
+{
+ struct mystr rules_file_str = INIT_MYSTR;
+ struct mystr rule_setting_str = INIT_MYSTR;
+ int retval;
+ unsigned int str_pos = 0;
+
+ retval = str_fileread(&rules_file_str, p_filename, VSFTP_CONF_FILE_MAX);
+ if (vsf_sysutil_retval_is_error(retval))
+ {
+ return;
+ }
+
+ while (str_getline(&rules_file_str, &rule_setting_str, &str_pos))
+ {
+ if (str_isempty(&rule_setting_str) ||
+ str_get_char_at(&rule_setting_str, 0) == '#')
+ {
+ continue;
+ }
+ parse_rules(&rule_setting_str);
+ }
+
+ str_free(&rules_file_str);
+ if (!str_isempty(&rule_setting_str))
+ {
+ str_free(&rule_setting_str);
+ }
+
+ if (rules_list) {
+ while (rules_list->prev)
+ {
+ rules_list = rules_list->prev;
+ }
+ }
+}
+
+int
+vsf_userip_check(const struct mystr* p_user,
+ struct vsf_session* p_sess)
+{
+ unsigned int remote_ip = 0;
+ int accept_login = 1;
+ static ip_rules rules;
+
+ if (!rules_list)
+ {
+ return(1);
+ }
+
+ rules = rules_list;
+
+ remote_ip = *(unsigned int*)vsf_sysutil_sockaddr_get_raw_addr(p_sess->p_remote_addr);
+
+ do
+ {
+ if (str_equal(p_user, &rules->p_user))
+ {
+ accept_login = 0;
+ if ((remote_ip & rules->remote_mask) == rules->remote_ip)
+ {
+ p_sess->remote_charset = rules->codepage;
+ return (1);
+ }
+ }
+ rules = rules->next;
+ }
+ while (rules);
+
+ return (accept_login);
+}
+
+void
+vsf_userip_free()
+{
+ if (rules_list)
+ {
+ do
+ {
+ if (rules_list->next)
+ {
+ rules_list = rules_list->next;
+ vsf_sysutil_free (rules_list->prev);
+ } else
+ {
+ vsf_sysutil_free (rules_list);
+ rules_list = 0;
+ }
+ }
+ while (rules_list);
+ }
+}
+
+static void
+parse_rules(struct mystr* p_rule_str)
+{
+ static struct mystr s_lhs_chunk_str;
+ static struct mystr s_rhs_chunk_str;
+ static struct mystr login;
+ static struct str_locate_result locate;
+ static struct mystr s_ip;
+ static struct vsf_sysutil_sockaddr *sockaddr;
+ unsigned int ui_ip = 0;
+ unsigned int ui_mask = 0;
+ unsigned int mask = 0;
+ unsigned int calc_mask = 0;
+ int codepage = 0;
+
+ vsf_sysutil_sockaddr_alloc_ipv4(&sockaddr);
+
+ str_replace_char(p_rule_str, '\t', ' ');
+ str_trim_char(p_rule_str, ' ');
+
+ str_copy(&s_lhs_chunk_str, p_rule_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' '); // Get user login
+ str_copy(&login, &s_lhs_chunk_str);
+
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' '); // Get user codepage
+ codepage = vsf_charconv_codepage(str_getbuf(&s_lhs_chunk_str));
+ if (codepage == 0)
+ {
+ codepage = vsf_charconv_codepage(tunable_remote_charset);
+ str_append_char(&s_lhs_chunk_str, ' ');
+ str_append_str(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_copy(&s_rhs_chunk_str, &s_lhs_chunk_str);
+ }
+
+ do
+ {
+ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
+ str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
+
+ locate = str_locate_char(&s_lhs_chunk_str, '/');
+ if (locate.found == 1) {
+ str_copy(&s_ip, &s_lhs_chunk_str);
+ str_split_char(&s_ip, &s_lhs_chunk_str, '/');
+ str_append_char(&s_ip, '\0');
+ if (vsf_sysutil_inet_aton(str_getbuf(&s_ip), sockaddr) != 0)
+ {
+ ui_ip = *(unsigned int*)vsf_sysutil_sockaddr_get_raw_addr(sockaddr);
+ mask = str_atoi(&s_lhs_chunk_str);
+ if (mask <= 0)
+ {
+ ui_mask = 0;
+ }
+ else
+ if (mask >= 32)
+ {
+ ui_mask = 0xFFFFFFFF;
+ }
+ else
+ {
+ calc_mask = 1;
+ calc_mask <<= (32 - mask);
+ calc_mask--;
+ calc_mask ^= 0xFFFFFFFF;
+
+ ui_mask = ((calc_mask & 0x000000FF) << 24) | ((calc_mask & 0x0000FF00) << 8) | ((calc_mask & 0x00FF0000) >> 8) | ((calc_mask & 0xFF000000) >> 24);
+ }
+ ui_ip &= ui_mask;
+ } else
+ {
+ continue;
+ }
+ } else
+ {
+ str_append_char(&s_lhs_chunk_str, '\0');
+ if (vsf_sysutil_inet_aton(str_getbuf(&s_lhs_chunk_str), sockaddr) != 0)
+ {
+ ui_ip = *(unsigned int*)vsf_sysutil_sockaddr_get_raw_addr(sockaddr);
+ }
+ ui_mask = 0xFFFFFFFF;
+ }
+
+ if (!rules_list)
+ {
+ rules_list = vsf_sysutil_malloc(sizeof(ip_rule));
+ vsf_sysutil_fillbuff(rules_list, sizeof(ip_rule), 0);
+ } else
+ {
+ rules_list->next = vsf_sysutil_malloc(sizeof(ip_rule));
+ vsf_sysutil_fillbuff(rules_list->next, sizeof(ip_rule), 0);
+ rules_list->next->prev = rules_list;
+ rules_list = rules_list->next;
+ }
+ rules_list->remote_ip = ui_ip;
+ rules_list->remote_mask = ui_mask;
+ rules_list->codepage = codepage;
+ str_copy (&rules_list->p_user, &login);
+
+ }
+ while (!str_isempty(&s_rhs_chunk_str));
+
+ str_free(&s_lhs_chunk_str);
+ str_free(&s_rhs_chunk_str);
+ str_free(&login);
+ str_free(&s_ip);
+}
+
Index: usersip.h
===================================================================
--- usersip.h (revision 0)
+++ usersip.h (revision 140)
@@ -0,0 +1,28 @@
+#ifndef VSF_USERSIP_H
+#define VSF_USERSIP_H
+
+#ifndef VSFTP_STR_H
+#include "str.h"
+#endif
+struct vsf_session;
+
+typedef struct ip_rule * ip_rules;
+
+typedef struct ip_rule
+{
+ struct mystr p_user ;
+ int codepage ;
+ unsigned int remote_ip ;
+ unsigned int remote_mask;
+ ip_rules prev ;
+ ip_rules next ;
+} ip_rule;
+
+void vsf_userip_load(const char* p_filename);
+
+int vsf_userip_check(const struct mystr* p_user,
+ struct vsf_session* p_sess);
+
+void vsf_userip_free();
+
+#endif /* VSF_USERSIP_H */
Index: privops.c
===================================================================
--- privops.c (revision 132)
+++ privops.c (revision 140)
@@ -18,6 +18,7 @@
#include "tunables.h"
#include "defs.h"
#include "logging.h"
+#include "usersip.h"
/* File private functions */
static enum EVSFPrivopLoginResult handle_anonymous_login(
@@ -214,8 +215,8 @@
static struct vsf_sysutil_statbuf* s_p_statbuf;
vsf_sysutil_fstat(fd, &s_p_statbuf);
/* Do nothing if it is already owned by the desired user. */
- if (vsf_sysutil_statbuf_get_uid(s_p_statbuf) ==
- p_sess->anon_upload_chown_uid)
+ if (vsf_sysutil_statbuf_get_uid(s_p_statbuf) == p_sess->anon_upload_chown_uid &&
+ vsf_sysutil_statbuf_get_gid(s_p_statbuf) == p_sess->anon_upload_chown_gid)
{
return;
}
@@ -233,7 +234,7 @@
* otherwise a compromise of the FTP user will lead to compromise of
* the "anon_upload_chown_uid" user (think chmod +s).
*/
- vsf_sysutil_fchown(fd, p_sess->anon_upload_chown_uid, -1);
+ vsf_sysutil_fchown(fd, p_sess->anon_upload_chown_uid, p_sess->anon_upload_chown_gid);
}
enum EVSFPrivopLoginResult
@@ -243,7 +244,7 @@
enum EVSFPrivopLoginResult result =
handle_login(p_sess, &p_sess->user_str, p_pass_str);
vsf_log_start_entry(p_sess, kVSFLogEntryLogin);
- if (result == kVSFLoginFail)
+ if (result == kVSFLoginFail || result == kVSFLoginHTTPFail)
{
vsf_log_do_log(p_sess, 0);
if (tunable_delay_failed_login)
@@ -315,6 +316,10 @@
{
result = handle_anonymous_login(p_sess, p_pass_str);
}
+ else if (p_sess->is_http)
+ {
+ result = kVSFLoginHTTPFail;
+ }
else
{
if (!tunable_local_enable)
@@ -367,10 +372,12 @@
struct mystr* p_user_str,
const struct mystr* p_pass_str)
{
- if (!vsf_sysdep_check_auth(p_user_str, p_pass_str, &p_sess->remote_ip_str))
+ if (!vsf_userip_check(p_user_str, p_sess) ||
+ !vsf_sysdep_check_auth(p_user_str, p_pass_str, &p_sess->remote_ip_str))
{
return kVSFLoginFail;
}
+ vsf_userip_free();
setup_username_globals(p_sess, p_user_str);
return kVSFLoginReal;
}
Index: utility.c
===================================================================
--- utility.c (revision 132)
+++ utility.c (revision 140)
@@ -50,3 +50,9 @@
vsf_sysutil_exit(0);
}
+void
+vsf_print(const char* p_text)
+{
+ (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, p_text,
+ vsf_sysutil_strlen(p_text));
+}
Index: ftpcmdio.c
===================================================================
--- ftpcmdio.c (revision 132)
+++ ftpcmdio.c (revision 140)
@@ -19,6 +19,7 @@
#include "logging.h"
#include "session.h"
#include "readwrite.h"
+#include "charconv.h"
/* Internal functions */
static void control_getline(struct mystr* p_str, struct vsf_session* p_sess);
@@ -75,6 +76,19 @@
}
void
+vsf_cmdio_write_raw_quiet(struct vsf_session* p_sess, const char* p_text)
+{
+ static struct mystr s_the_str;
+ int retval;
+ str_alloc_text(&s_the_str, p_text);
+ retval = ftp_write_str(p_sess, &s_the_str, kVSFRWControl);
+ if (retval != 0)
+ {
+ die("ftp_write_str");
+ }
+}
+
+void
vsf_cmdio_write_exit(struct vsf_session* p_sess, int status, const char* p_text)
{
/* Unblock any readers on the dying control channel. This is needed for SSL
@@ -126,9 +140,13 @@
vsf_log_line(p_sess, kVSFLogEntryFTPOutput, &s_write_buf_str);
}
str_copy(&s_text_mangle_str, p_str);
+ vsf_charconv_convert(p_sess, &s_text_mangle_str, VSFTP_CONVDIRECT_FORWARD);
/* Process the output response according to the specifications.. */
/* Escape telnet characters properly */
- str_replace_text(&s_text_mangle_str, "\377", "\377\377");
+ if (tunable_double_377)
+ {
+ str_replace_text(&s_text_mangle_str, "\377", "\377\377");
+ }
/* Change \n for \0 in response */
str_replace_char(&s_text_mangle_str, '\n', '\0');
/* Build string to squirt down network */
@@ -166,7 +184,7 @@
void
vsf_cmdio_get_cmd_and_arg(struct vsf_session* p_sess, struct mystr* p_cmd_str,
- struct mystr* p_arg_str, int set_alarm)
+ struct mystr* p_arg_str, int set_alarm, int is_quiet)
{
/* Prepare an alarm to timeout the session.. */
if (set_alarm)
@@ -187,7 +205,7 @@
str_split_char(p_cmd_str, p_arg_str, ' ');
}
str_upper(p_cmd_str);
- if (tunable_log_ftp_protocol)
+ if (tunable_log_ftp_protocol && !is_quiet)
{
static struct mystr s_log_str;
if (str_equal_text(p_cmd_str, "PASS"))
@@ -231,5 +249,6 @@
--len;
}
}
+ vsf_charconv_convert(p_sess, p_str, VSFTP_CONVDIRECT_BACKWARD);
}
Index: privops.h
===================================================================
--- privops.h (revision 132)
+++ privops.h (revision 140)
@@ -76,6 +76,7 @@
{
kVSFLoginNull = 0,
kVSFLoginFail,
+ kVSFLoginHTTPFail,
kVSFLoginAnon,
kVSFLoginReal
};
Index: secutil.c
===================================================================
--- secutil.c (revision 132)
+++ secutil.c (revision 140)
@@ -69,22 +69,22 @@
if (retval != 0)
{
die2("cannot change directory:", str_getbuf(&dir_str));
+ }
+ if (p_ext_dir_str && !str_isempty(p_ext_dir_str))
+ {
+ retval = str_chdir(p_ext_dir_str);
+ /* Failure on the extra directory is OK as long as we're not in
+ * chroot() mode
+ */
+ if (retval != 0 && !(options & VSF_SECUTIL_OPTION_CHROOT))
+ {
+ retval = 0;
+ }
+ }
+ if (retval != 0)
+ {
+ die2("cannot change directory:", str_getbuf(p_ext_dir_str));
}
- if (p_ext_dir_str && !str_isempty(p_ext_dir_str))
- {
- retval = str_chdir(p_ext_dir_str);
- /* Failure on the extra directory is OK as long as we're not in
- * chroot() mode
- */
- if (retval != 0 && !(options & VSF_SECUTIL_OPTION_CHROOT))
- {
- retval = 0;
- }
- }
- if (retval != 0)
- {
- die2("cannot change directory:", str_getbuf(p_ext_dir_str));
- }
if (options & VSF_SECUTIL_OPTION_CHANGE_EUID)
{
vsf_sysutil_seteuid_numeric(saved_euid);
Index: utility.h
===================================================================
--- utility.h (revision 132)
+++ utility.h (revision 140)
@@ -40,5 +40,12 @@
*/
void vsf_exit(const char* p_text);
+/* vsf_print()
+ * PURPOSE
+ * Writing out the specified text string in the process.
+ * PARAMETERS
+ * p_text - text string describing why the process is exiting
+ */
+void vsf_print(const char* p_text);
+
#endif
-
Index: vsftpd.conf
===================================================================
--- vsftpd.conf (revision 132)
+++ vsftpd.conf (revision 140)
@@ -1,4 +1,4 @@
-# Example config file /etc/vsftpd.conf
+# Example config file /etc/vsftpd/vsftpd.conf
#
# The default compiled in settings are fairly paranoid. This sample file
# loosens things up a bit, to make the ftp daemon more usable.
@@ -87,7 +87,7 @@
# useful for combatting certain DoS attacks.
#deny_email_enable=YES
# (default follows)
-#banned_email_file=/etc/vsftpd.banned_emails
+#banned_email_file=/etc/vsftpd/banned_emails
#
# You may specify an explicit list of local users to chroot() to their home
# directory. If chroot_local_user is YES, then this list becomes a list of
@@ -95,7 +95,7 @@
#chroot_local_user=YES
#chroot_list_enable=YES
# (default follows)
-#chroot_list_file=/etc/vsftpd.chroot_list
+#chroot_list_file=/etc/vsftpd/chroot_list
#
# You may activate the "-R" option to the builtin ls. This is disabled by
# default to avoid remote users being able to cause excessive I/O on large
Index: ftpcmdio.h
===================================================================
--- ftpcmdio.h (revision 132)
+++ ftpcmdio.h (revision 140)
@@ -45,6 +45,17 @@
*/
void vsf_cmdio_write_raw(struct vsf_session* p_sess, const char* p_text);
+/* vsf_cmdio_write_raw_quiet()
+ * PURPOSE
+ * Write a raw response to the FTP control connection. A status code is
+ * not prepended, and it is also the client's responsibility to include
+ * newline characters if required. Response do not writen to log.
+ * PARAMETERS
+ * p_sess - the current session object
+ * p_text - the text to report
+ */
+void vsf_cmdio_write_raw_quiet(struct vsf_session* p_sess, const char* p_text);
+
/* vsf_cmdio_write_exit()
* PURPOSE
* The same as vsf_cmdio_write(), and then the calling process is exited. The
@@ -88,10 +99,13 @@
* p_cmd_str - Where to put the FTP command string (may be empty)
* p_arg_str - Where to put the FTP argument string (may be empty)
* set_alarm - If true, the control connection inactivity monitor is used
+ * is_quiet - Don't log processed command
*/
void vsf_cmdio_get_cmd_and_arg(struct vsf_session* p_sess,
- struct mystr* p_cmd_str,
- struct mystr* p_arg_str, int set_alarm);
+ struct mystr* p_cmd_str,
+ struct mystr* p_arg_str,
+ int set_alarm,
+ int is_quiet);
#endif /* VSF_FTPCMDIO_H */
Index: ftpdataio.c
===================================================================
--- ftpdataio.c (revision 132)
+++ ftpdataio.c (revision 140)
@@ -315,8 +315,8 @@
{
p_subdir_list = &subdir_list;
}
- vsf_ls_populate_dir_list(&dir_list, p_subdir_list, p_dir, p_base_dir_str,
- p_option_str, p_filter_str, is_verbose);
+ vsf_ls_populate_dir_list(p_sess, &dir_list, p_subdir_list, p_dir, p_base_dir_str,
+ p_option_str, p_filter_str, is_verbose, 0);
if (p_subdir_list)
{
int retval;
Index: ls.c
===================================================================
--- ls.c (revision 132)
+++ ls.c (revision 140)
@@ -15,20 +15,32 @@
#include "sysstr.h"
#include "sysutil.h"
#include "tunables.h"
+#include "charconv.h"
+#include "http_str.h"
+#include "http_msg.h"
-static void build_dir_line(struct mystr* p_str,
+static void build_dir_line(struct vsf_session* p_sess,
+ struct mystr* p_str,
const struct mystr* p_filename_str,
const struct vsf_sysutil_statbuf* p_stat,
long curr_time);
+static void build_http_dir_line(struct vsf_session* p_sess,
+ struct mystr* p_str,
+ const struct mystr* p_filename_str,
+ const struct vsf_sysutil_statbuf* p_stat,
+ long curr_time);
+
void
-vsf_ls_populate_dir_list(struct mystr_list* p_list,
+vsf_ls_populate_dir_list(struct vsf_session* p_sess,
+ struct mystr_list* p_list,
struct mystr_list* p_subdir_list,
struct vsf_sysutil_dir* p_dir,
const struct mystr* p_base_dir_str,
const struct mystr* p_option_str,
const struct mystr* p_filter_str,
- int is_verbose)
+ int is_verbose,
+ int is_http)
{
struct mystr dirline_str = INIT_MYSTR;
struct mystr normalised_base_dir_str = INIT_MYSTR;
@@ -39,6 +51,8 @@
int F_option;
int do_stat = 0;
long curr_time = 0;
+ int show_parent = (is_http == 1 && !str_equal_text(p_base_dir_str, "/")) ? 1 : 0;
+
loc_result = str_locate_char(p_option_str, 'a');
a_option = loc_result.found;
loc_result = str_locate_char(p_option_str, 'r');
@@ -98,7 +112,8 @@
break;
}
len = str_getlen(&s_next_filename_str);
- if (len > 0 && str_get_char_at(&s_next_filename_str, 0) == '.')
+ if (len > 0 && str_get_char_at(&s_next_filename_str, 0) == '.' &&
+ ((show_parent == 0) || (show_parent == 1 && !str_equal_text(&s_next_filename_str, ".."))))
{
if (!a_option && !tunable_force_dot_files)
{
@@ -148,7 +163,7 @@
static struct mystr s_final_file_str;
/* If it's a damn symlink, we need to append the target */
str_copy(&s_final_file_str, &s_next_filename_str);
- if (vsf_sysutil_statbuf_is_symlink(s_p_statbuf))
+ if (!is_http && vsf_sysutil_statbuf_is_symlink(s_p_statbuf))
{
static struct mystr s_temp_str;
int retval = str_readlink(&s_temp_str, &s_next_path_and_filename_str);
@@ -162,7 +177,14 @@
{
str_append_char(&s_final_file_str, '/');
}
- build_dir_line(&dirline_str, &s_final_file_str, s_p_statbuf, curr_time);
+ if (is_http)
+ {
+ build_http_dir_line(p_sess, &dirline_str, &s_final_file_str, s_p_statbuf, curr_time);
+ }
+ else
+ {
+ build_dir_line(p_sess, &dirline_str, &s_final_file_str, s_p_statbuf, curr_time);
+ }
}
else
{
@@ -181,6 +203,7 @@
str_append_char(&dirline_str, '@');
}
}
+ vsf_charconv_convert(p_sess, &dirline_str, VSFTP_CONVDIRECT_FORWARD);
str_append_text(&dirline_str, "\r\n");
}
/* Add filename into our sorted list - sorting by filename or time. Also,
@@ -246,8 +269,28 @@
char last_token = 0;
int must_match_at_current_pos = 1;
str_copy(&filter_remain_str, p_filter_str);
- str_copy(&name_remain_str, p_filename_str);
+ if (!str_isempty (&filter_remain_str) && !str_isempty(p_filename_str)) {
+ if (str_get_char_at(p_filter_str, 0) == '/') {
+ if (str_get_char_at(p_filename_str, 0) != '/') {
+ str_getcwd (&name_remain_str);
+
+ if (str_getlen(&name_remain_str) > 1) /* cwd != root dir */
+ str_append_char (&name_remain_str, '/');
+
+ str_append_str (&name_remain_str, p_filename_str);
+ }
+ else
+ str_copy(&name_remain_str, p_filename_str);
+ } else {
+ if (str_get_char_at(p_filter_str, 0) != '{')
+ str_basename (&name_remain_str, p_filename_str);
+ else
+ str_copy (&name_remain_str, p_filename_str);
+ }
+ } else
+ str_copy(&name_remain_str, p_filename_str);
+
while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX)
{
static struct mystr s_match_needed_str;
@@ -288,6 +331,25 @@
{
goto out;
}
+ if (!must_match_at_current_pos)
+ {
+ struct mystr scan_fwd = INIT_MYSTR;
+
+ str_mid_to_end(&name_remain_str, &scan_fwd,
+ indexx + str_getlen(&s_match_needed_str));
+ /* We're allowed to be greedy, test if it match further along
+ * keep advancing indexx while we can still match.
+ */
+ while( (locate_result = str_locate_str(&scan_fwd, &s_match_needed_str)),
+ locate_result.found )
+ {
+ indexx += locate_result.index + str_getlen(&s_match_needed_str);
+ str_mid_to_end(&scan_fwd, &temp_str,
+ locate_result.index + str_getlen(&s_match_needed_str));
+ str_copy(&scan_fwd, &temp_str);
+ }
+ str_free(&scan_fwd);
+ }
/* Chop matched string out of remainder */
str_mid_to_end(&name_remain_str, &temp_str,
indexx + str_getlen(&s_match_needed_str));
@@ -368,7 +430,7 @@
}
static void
-build_dir_line(struct mystr* p_str, const struct mystr* p_filename_str,
+build_dir_line(struct vsf_session* p_sess, struct mystr* p_str, const struct mystr* p_filename_str,
const struct vsf_sysutil_statbuf* p_stat, long curr_time)
{
static struct mystr s_tmp_str;
@@ -382,52 +444,12 @@
str_append_str(p_str, &s_tmp_str);
str_append_char(p_str, ' ');
/* User */
- if (tunable_hide_ids)
- {
- str_alloc_text(&s_tmp_str, "ftp");
- }
- else
- {
- int uid = vsf_sysutil_statbuf_get_uid(p_stat);
- struct vsf_sysutil_user* p_user = 0;
- if (tunable_text_userdb_names)
- {
- p_user = vsf_sysutil_getpwuid(uid);
- }
- if (p_user == 0)
- {
- str_alloc_ulong(&s_tmp_str, (unsigned long) uid);
- }
- else
- {
- str_alloc_text(&s_tmp_str, vsf_sysutil_user_getname(p_user));
- }
- }
+ str_getuser(&s_tmp_str, p_stat);
str_rpad(&s_tmp_str, 8);
str_append_str(p_str, &s_tmp_str);
str_append_char(p_str, ' ');
/* Group */
- if (tunable_hide_ids)
- {
- str_alloc_text(&s_tmp_str, "ftp");
- }
- else
- {
- int gid = vsf_sysutil_statbuf_get_gid(p_stat);
- struct vsf_sysutil_group* p_group = 0;
- if (tunable_text_userdb_names)
- {
- p_group = vsf_sysutil_getgrgid(gid);
- }
- if (p_group == 0)
- {
- str_alloc_ulong(&s_tmp_str, (unsigned long) gid);
- }
- else
- {
- str_alloc_text(&s_tmp_str, vsf_sysutil_group_getname(p_group));
- }
- }
+ str_getgroup(&s_tmp_str, p_stat);
str_rpad(&s_tmp_str, 8);
str_append_str(p_str, &s_tmp_str);
str_append_char(p_str, ' ');
@@ -443,6 +465,14 @@
str_append_char(p_str, ' ');
/* Filename */
str_append_str(p_str, p_filename_str);
+ vsf_charconv_convert(p_sess, p_str, VSFTP_CONVDIRECT_FORWARD);
str_append_text(p_str, "\r\n");
}
+static void
+build_http_dir_line(struct vsf_session* p_sess, struct mystr* p_str, const struct mystr* p_filename_str,
+ const struct vsf_sysutil_statbuf* p_stat, long curr_time)
+{
+ str_process_template(p_sess, p_str, &msg_browse_line, p_filename_str, p_stat, curr_time, 0);
+}
+
Index: ls.h
===================================================================
--- ls.h (revision 132)
+++ ls.h (revision 140)
@@ -4,12 +4,14 @@
struct mystr;
struct mystr_list;
struct vsf_sysutil_dir;
+struct vsf_session;
/* vsf_ls_populate_dir_list()
* PURPOSE
* Given a directory handle, populate a formatted directory entry list (/bin/ls
* format). Also optionally populate a list of subdirectories.
* PARAMETERS
+ * p_sess - the current FTP session object
* p_list - the string list object for the result list of entries
* p_subdir_list - the string list object for the result list of
* subdirectories. May be 0 if client is not interested.
@@ -18,14 +20,17 @@
* p_option_str - the string of options given to the LIST/NLST command
* p_filter_str - the filter string given to LIST/NLST - e.g. "*.mp3"
* is_verbose - set to 1 for LIST, 0 for NLST
+ * is_http - ...
*/
-void vsf_ls_populate_dir_list(struct mystr_list* p_list,
+void vsf_ls_populate_dir_list(struct vsf_session* p_sess,
+ struct mystr_list* p_list,
struct mystr_list* p_subdir_list,
struct vsf_sysutil_dir* p_dir,
const struct mystr* p_base_dir_str,
const struct mystr* p_option_str,
const struct mystr* p_filter_str,
- int is_verbose);
+ int is_verbose,
+ int is_http);
/* vsf_filename_passes_filter()
* PURPOSE
Index: main.c
===================================================================
--- main.c (revision 132)
+++ main.c (revision 140)
@@ -22,6 +22,10 @@
#include "tcpwrap.h"
#include "vsftpver.h"
#include "ssl.h"
+#include "charconv.h"
+#include "pasvrules.h"
+#include "usersip.h"
+#include "http_msg.h"
/*
* Forward decls of helper functions
@@ -40,17 +44,17 @@
/* Control connection */
0, 0, 0,
/* Data connection */
- -1, 0, -1, 0, 0, 0, 0,
+ -1, 0, -1, 0, 0, 0, 0, 0, 0,
/* Login */
1, 0, INIT_MYSTR, INIT_MYSTR,
/* Protocol state */
- 0, 1, INIT_MYSTR, 0, 0,
+ 0, 1, INIT_MYSTR, 0, 0, 0, 0,
/* HTTP hacks */
0, INIT_MYSTR,
/* Session state */
0,
/* Userids */
- -1, -1, -1,
+ -1, -1, -1, -1,
/* Pre-chroot() cache */
INIT_MYSTR, INIT_MYSTR, INIT_MYSTR, INIT_MYSTR, 1,
/* Logging */
@@ -66,6 +70,8 @@
/* Secure connection state */
0, 0, 0, 0, 0, INIT_MYSTR, 0, -1, -1,
/* Login fails */
+ 0,
+ /* Owner UID */
0
};
int config_loaded = 0;
@@ -96,9 +102,20 @@
}
else
{
+ if (p_arg[1] == '?')
+ {
+ vsf_print("vsFTPd version " VSF_VERSION "\n");
+ vsf_print("Type 'vsftpd -v' to see the program version\n");
+ vsf_print("Usage: vsftpd [options]\n");
+ vsf_print(" - full path to configuration file\n");
+ vsf_print("Options:\n");
+ vsf_print(" -o=\n");
+ vsf_print(" parameter and value you can look in vsftpd configuration file manual\n");
+ vsf_exit("");
+ }
if (p_arg[1] == 'v')
{
- vsf_exit("vsftpd: version " VSF_VERSION "\n");
+ vsf_exit("vsFTPd version " VSF_VERSION "\n");
}
else if (p_arg[1] == 'o')
{
@@ -120,16 +137,10 @@
}
vsf_sysutil_free(p_statbuf);
}
- /* Resolve pasv_address if required */
- if (tunable_pasv_address && tunable_pasv_addr_resolve)
+ if (tunable_convert_charset_enable)
{
- struct vsf_sysutil_sockaddr* p_addr = 0;
- const char* p_numeric_addr;
- vsf_sysutil_dns_resolve(&p_addr, tunable_pasv_address);
- vsf_sysutil_free((char*) tunable_pasv_address);
- p_numeric_addr = vsf_sysutil_inet_ntop(p_addr);
- tunable_pasv_address = vsf_sysutil_strdup(p_numeric_addr);
- vsf_sysutil_free(p_addr);
+ tunable_local_codepage = vsf_charconv_codepage(tunable_local_charset);
+ tunable_convert_charset_enable = (tunable_local_codepage) ? 1 : 0;
}
if (!tunable_run_as_launching_user)
{
@@ -235,6 +246,17 @@
tunable_chown_uploads = 0;
}
}
+ if (tunable_pasv_addr_rules) {
+ vsf_pasvrules_load(tunable_pasv_addr_rules);
+ }
+ vsf_pasvrules_define(&the_session);
+ if (tunable_users_access_ip) {
+ vsf_userip_load(tunable_users_access_ip);
+ }
+ if (tunable_http_enable)
+ {
+ vsf_http_messages_load();
+ }
if (tunable_one_process_model)
{
vsf_one_process_start(&the_session);
@@ -359,6 +381,10 @@
tunable_chown_username);
}
p_sess->anon_upload_chown_uid = vsf_sysutil_user_getuid(p_user);
+ if (tunable_chown_group)
+ {
+ p_sess->anon_upload_chown_gid = vsf_sysutil_user_getgid(p_user);
+ }
}
}
Index: http_msg.c
===================================================================
--- http_msg.c (revision 0)
+++ http_msg.c (revision 140)
@@ -0,0 +1,78 @@
+/*
+ * Part of Very Secure FTPd
+ * Licence: GPL v2
+ * Author: Dmitriy Balashov
+ * http_msg.c
+ *
+ * HTTP messages.
+ */
+
+#include "defs.h"
+#include "http_msg.h"
+#include "tunables.h"
+#include "str.h"
+#include "filestr.h"
+#include "utility.h"
+#include "sysutil.h"
+//#include "logging.h"
+
+static void http_message_set(struct mystr* p_str, const char* p_filename, const char* p_default);
+
+static struct mystr msg_forbidden_server = INIT_MYSTR;
+static struct mystr msg_forbidden_object = INIT_MYSTR;
+static struct mystr msg_not_found = INIT_MYSTR;
+static struct mystr msg_browse = INIT_MYSTR;
+struct mystr msg_browse_line = INIT_MYSTR;
+static char* forbidden = "Forbidden";
+static char* not_found = "Not Found";
+static char* browse = "Index of %r
";
+static char* browse_line = "%f | %i | %s | %T |
";
+
+void
+vsf_http_messages_load()
+{
+ http_message_set(&msg_forbidden_server, tunable_http_error_403_server_tpl, forbidden);
+ http_message_set(&msg_forbidden_object, tunable_http_error_403_tpl, forbidden);
+ http_message_set(&msg_not_found, tunable_http_error_404_tpl, not_found);
+ http_message_set(&msg_browse, tunable_http_browse_tpl, browse);
+ http_message_set(&msg_browse_line, tunable_http_browse_line_tpl, browse_line);
+}
+
+const char*
+vsf_http_messages_get(const enum EVSFHttpMsgType p_msg_type)
+{
+ switch (p_msg_type)
+ {
+ case kVSFHttpMsgType403Serv:
+ return str_getbuf(&msg_forbidden_server);
+ break;
+ case kVSFHttpMsgType403:
+ return str_getbuf(&msg_forbidden_object);
+ break;
+ case kVSFHttpMsgType404:
+ return str_getbuf(&msg_not_found);
+ break;
+ case kVSFHttpMsgType200Browse:
+ return str_getbuf(&msg_browse);
+ break;
+ default:
+ bug("unknown message type in vsf_http_messages_get");
+ break;
+ }
+ return 0;
+}
+
+static void
+http_message_set(struct mystr* p_str, const char* p_filename, const char* p_default)
+{
+ int retval = 0;
+ if (p_filename)
+ {
+ retval = str_fileread(p_str, p_filename, VSFTP_DATA_BUFSIZE);
+ }
+ if (!p_filename || vsf_sysutil_retval_is_error(retval))
+ {
+ str_alloc_text(p_str, p_default);
+ }
+}
+
Index: AUDIT
===================================================================
--- AUDIT (revision 132)
+++ AUDIT (revision 140)
@@ -8,34 +8,44 @@
access.c 2
ascii.c 3
banner.c 2
-dirchange.c 3
+charconv.c 1
+features.c 1
filestr.c 3
-ftpcmdio.c 3
-ftpdataio.c 2
+ftpcmdio.c 1
+ftpdataio.c 1
+ftppolicy.c 1
hash.c 1
+http.c 1
+http_msg.c 1
+http_str.c 1
ipaddrparse.c 1
-logging.c 3
-ls.c 2
-main.c 3
+logging.c 1
+ls.c 1
+main.c 1
netstr.c 3
-oneprocess.c 3
-parseconf.c 2
-postlogin.c 2
+oneprocess.c 1
+opts.c 1
+parseconf.c 1
+pasvrules.c 1
+postlogin.c 1
postprivparent.c 3
-prelogin.c 3
-privops.c 2
-privparent.c 3
+prelogin.c 1
+privops.c 1
privsock.c 3
+ptracesandbox.c 1
+readwrite.c 1
secbuf.c 3
-secutil.c 3
+secutil.c 1
ssl.c 1
+sslslave.c 1
standalone.c 1
-str.c 2
+str.c 1
strlist.c 2
-sysdeputil.c 2
+sysdeputil.c 1
sysstr.c 3
-sysutil.c 2
-tunables.c 3
-twoprocess.c 2
-utility.c 3
-
+sysutil.c 1
+tcpwrap.c 1
+tunables.c 1
+twoprocess.c 1
+userip.c 1
+utility.c 1
Index: logging.c
===================================================================
--- logging.c (revision 132)
+++ logging.c (revision 140)
@@ -95,6 +95,13 @@
vsf_log_common(p_sess, 1, what, p_str);
}
+void
+vsf_log_failed_line(struct vsf_session* p_sess, enum EVSFLogEntryType what,
+ struct mystr* p_str)
+{
+ vsf_log_common(p_sess, 0, what, p_str);
+}
+
int
vsf_log_entry_pending(struct vsf_session* p_sess)
{
@@ -178,7 +185,7 @@
long delta_sec;
enum EVSFLogEntryType what = (enum EVSFLogEntryType) p_sess->log_type;
/* Date - vsf_sysutil_get_current_date updates cached time */
- str_alloc_text(p_str, vsf_sysutil_get_current_date());
+ str_alloc_text(p_str, vsf_sysutil_get_current_date(tunable_use_localtime));
str_append_char(p_str, ' ');
/* Transfer time (in seconds) */
delta_sec = vsf_sysutil_get_time_sec() - p_sess->log_start_sec;
@@ -239,7 +246,9 @@
}
str_append_char(p_str, ' ');
/* Service name, authentication method, authentication user id */
- str_append_text(p_str, "ftp 0 * ");
+ str_append_text(p_str, "ftp 0 ");
+ str_append_ulong(p_str, p_sess->retr_owner_uid);
+ str_append_text(p_str, " ");
/* Completion status */
if (succeeded)
{
@@ -260,7 +269,7 @@
if (!tunable_syslog_enable)
{
/* Date - vsf_sysutil_get_current_date updates cached time */
- str_append_text(p_str, vsf_sysutil_get_current_date());
+ str_append_text(p_str, vsf_sysutil_get_current_date(tunable_use_localtime));
/* Pid */
str_append_text(p_str, " [pid ");
str_append_ulong(p_str, vsf_sysutil_getpid());
Index: defs.h
===================================================================
--- defs.h (revision 132)
+++ defs.h (revision 140)
@@ -1,8 +1,10 @@
#ifndef VSF_DEFS_H
#define VSF_DEFS_H
-#define VSFTP_DEFAULT_CONFIG "/etc/vsftpd.conf"
+#include "builddefs.h"
+#define VSFTP_DEFAULT_CONFIG VSF_CONFIG_PATH "vsftpd.conf"
+
#define VSFTP_COMMAND_FD 0
#define VSFTP_PASSWORD_MAX 128
Index: session.h
===================================================================
--- session.h (revision 132)
+++ session.h (revision 140)
@@ -28,6 +28,8 @@
int data_fd;
int data_progress;
unsigned int bw_rate_max;
+ unsigned int bw_rate_max_rx;
+ unsigned int bw_rate_max_tx;
long bw_send_start_sec;
long bw_send_start_usec;
@@ -43,6 +45,8 @@
struct mystr rnfr_filename_str;
int abor_received;
int epsv_all;
+ int enable_convertion;
+ int remote_charset;
/* HTTP hacks */
int is_http;
@@ -55,6 +59,7 @@
int anon_ftp_uid;
int guest_user_uid;
int anon_upload_chown_uid;
+ int anon_upload_chown_gid;
/* Things we need to cache before we chroot() */
struct mystr banned_email_str;
@@ -97,6 +102,7 @@
int ssl_slave_fd;
int ssl_consumer_fd;
unsigned int login_fails;
+ unsigned long retr_owner_uid;
};
#endif /* VSF_SESSION_H */
Index: standalone.c
===================================================================
--- standalone.c (revision 132)
+++ standalone.c (revision 140)
@@ -26,6 +26,8 @@
static void handle_sigchld(void* duff);
static void handle_sighup(void* duff);
+static void handle_sigusr1(int sig);
+static void handle_sigalrm(int sig);
static void prepare_child(int sockfd);
static unsigned int handle_ip_count(void* p_raw_addr);
static void drop_ip_count(void* p_raw_addr);
@@ -46,15 +48,31 @@
}
if (tunable_background)
{
+ vsf_sysutil_sigaction(kVSFSysUtilSigALRM, handle_sigalrm);
+ vsf_sysutil_sigaction(kVSFSysUtilSigUSR1, handle_sigusr1);
+
int forkret = vsf_sysutil_fork();
if (forkret > 0)
{
/* Parent, just exit */
- vsf_sysutil_exit(0);
+ vsf_sysutil_set_alarm(3);
+ vsf_sysutil_pause();
+
+ vsf_sysutil_exit(1);
}
+ else if (forkret == 0)
+ {
+ // Son, restore original signal handler
+ vsf_sysutil_sigaction(kVSFSysUtilSigALRM, 0L);
+ vsf_sysutil_sigaction(kVSFSysUtilSigUSR1, 0L);
+ }
/* Son, close standard FDs to avoid SSH hang-on-exit */
vsf_sysutil_reopen_standard_fds();
vsf_sysutil_make_session_leader();
+
+ vsf_sysutil_close(0);
+ vsf_sysutil_close(1);
+ vsf_sysutil_close(2);
}
if (tunable_listen)
{
@@ -98,6 +116,10 @@
{
die("could not bind listening IPv4 socket");
}
+ if (tunable_background)
+ {
+ vsf_sysutil_kill(vsf_sysutil_getppid(), kVSFSysUtilSigUSR1);
+ }
}
else
{
@@ -127,6 +149,10 @@
{
die("could not bind listening IPv6 socket");
}
+ if (tunable_background)
+ {
+ vsf_sysutil_kill(vsf_sysutil_getppid(), kVSFSysUtilSigUSR1);
+ }
}
retval = vsf_sysutil_listen(listen_sock, VSFTP_LISTEN_BACKLOG);
if (vsf_sysutil_retval_is_error(retval))
@@ -263,6 +289,20 @@
vsf_parseconf_load_file(0, 0);
}
+static void
+handle_sigalrm(int sig)
+{
+ (void)sig; // avoid unused parameter error
+ vsf_sysutil_exit(1);
+}
+
+static void
+handle_sigusr1(int sig)
+{
+ (void)sig; // avoid unused parameter error
+ vsf_sysutil_exit(0);
+}
+
static unsigned int
hash_ip(unsigned int buckets, void* p_key)
{
Index: http_msg.h
===================================================================
--- http_msg.h (revision 0)
+++ http_msg.h (revision 140)
@@ -0,0 +1,22 @@
+#ifndef VSF_HTTP_MSG_H
+#define VSF_HTTP_MSG_H
+
+struct mystr;
+
+void vsf_http_messages_load();
+
+enum EVSFHttpMsgType
+{
+ kVSFHttpMsgType403Serv = 1,
+ kVSFHttpMsgType403,
+ kVSFHttpMsgType404,
+ kVSFHttpMsgType200Browse
+};
+
+extern struct mystr msg_browse_line;
+
+const char* vsf_http_messages_get(const enum EVSFHttpMsgType p_msg_type);
+
+
+#endif /* VSF_HTTP_MSG_H */
+
Index: logging.h
===================================================================
--- logging.h (revision 132)
+++ logging.h (revision 140)
@@ -19,7 +19,7 @@
kVSFLogEntryRename,
kVSFLogEntryRmdir,
kVSFLogEntryChmod,
- kVSFLogEntryDebug,
+ kVSFLogEntryDebug
};
/* vsf_log_init()
@@ -80,5 +80,16 @@
void vsf_log_line(struct vsf_session* p_sess, enum EVSFLogEntryType what,
struct mystr* p_str);
+/* vsf_log_failed_line()
+ * PURPOSE
+ * Same as vsf_log_line(), except that it logs the line as failed operation.
+ * PARAMETERS
+ * p_sess - the current session object
+ * what - the type of operation to log
+ * p_str - the string to log
+ */
+void vsf_log_failed_line(struct vsf_session* p_sess, enum EVSFLogEntryType what,
+ struct mystr* p_str);
+
#endif /* VSF_LOGGING_H */
Index: vsftpd.8
===================================================================
--- vsftpd.8 (revision 132)
+++ vsftpd.8 (revision 140)
@@ -21,7 +21,7 @@
recommended. It is activated by setting
.Pa listen=YES
in
-.Pa /etc/vsftpd.conf .
+.Pa /etc/vsftpd/vsftpd.conf .
Direct execution of the
.Nm vsftpd
binary will then launch the FTP service ready for immediate client connections.
@@ -47,14 +47,14 @@
config files.
.El
.Sh EXAMPLES
-vsftpd -olisten=NO /etc/vsftpd.conf -oftpd_banner=blah
+vsftpd -olisten=NO /etc/vsftpd/vsftpd.conf -oftpd_banner=blah
.Pp
That example overrides vsftpd's built-in default for the "listen" option to be
NO, but then loads /etc/vsftpd.conf which may override that setting. Finally,
the "ftpd_banner" setting is set to "blah", which overrides any default vsftpd
setting and any identical setting that was in the config file.
.Sh FILES
-.Pa /etc/vsftpd.conf
+.Pa /etc/vsftpd/vsftpd.conf
.Sh SEE ALSO
.Xr vsftpd.conf 5
.end