diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/smb.h | 1 | ||||
-rw-r--r-- | source3/lib/charcnv.c | 13 | ||||
-rw-r--r-- | source3/lib/iconv.c | 8 | ||||
-rw-r--r-- | source3/lib/util_unistr.c | 50 |
4 files changed, 63 insertions, 9 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index ae2727268d..8c0491a004 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1654,6 +1654,7 @@ typedef struct { size_t (*push)(void *cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); void *cd_direct, *cd_pull, *cd_push; + char *from_name, *to_name; } *smb_iconv_t; /* The maximum length of a trust account password. diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 2e5413c5c0..256bd7e88c 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -51,6 +51,7 @@ static char *charset_name(charset_t ch) void init_iconv(void) { int c1, c2; + BOOL did_reload = False; /* so that charset_name() works we need to get the UNIX<->UCS2 going first */ @@ -66,6 +67,12 @@ void init_iconv(void) for (c2=0;c2<NUM_CHARSETS;c2++) { char *n1 = charset_name((charset_t)c1); char *n2 = charset_name((charset_t)c2); + if (conv_handles[c1][c2] && + strcmp(n1, conv_handles[c1][c2]->from_name) == 0 && + strcmp(n2, conv_handles[c1][c2]->to_name) == 0) continue; + + did_reload = True; + if (conv_handles[c1][c2]) { smb_iconv_close(conv_handles[c1][c2]); } @@ -77,6 +84,10 @@ void init_iconv(void) } } } + + if (did_reload) { + init_valid_table(); + } } /** @@ -105,6 +116,7 @@ size_t convert_string(charset_t from, charset_t to, initialized = 1; load_case_tables(); init_iconv(); + init_valid_table(); } descriptor = conv_handles[from][to]; @@ -136,7 +148,6 @@ size_t convert_string(charset_t from, charset_t to, break; case EILSEQ: reason="Illegal myltibyte sequence"; break; } - DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); /* smb_panic(reason); */ } return destlen-o_len; diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index 8bcd92d72a..c08524eaa0 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -125,6 +125,9 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) } memset(ret, 0, sizeof(*ret)); + ret->from_name = strdup(fromcode); + ret->to_name = strdup(tocode); + /* check for the simplest null conversion */ if (strcmp(fromcode, tocode) == 0) { ret->direct = iconv_copy; @@ -202,6 +205,9 @@ int smb_iconv_close (smb_iconv_t cd) if (cd->cd_push) iconv_close((iconv_t)cd->cd_push); #endif + SAFE_FREE(cd->from_name); + SAFE_FREE(cd->to_name); + memset(cd, 0, sizeof(*cd)); SAFE_FREE(cd); return 0; @@ -240,7 +246,7 @@ static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft, int ir_count=0; while (*inbytesleft >= 2 && *outbytesleft >= 1) { - (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[0] = (*inbuf)[0] & 0x7F; if ((*inbuf)[1]) ir_count++; (*inbytesleft) -= 2; (*outbytesleft) -= 1; diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 6034a715d3..08fc1760ae 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -32,6 +32,7 @@ static smb_ucs2_t *upcase_table; static smb_ucs2_t *lowcase_table; static uint8 *valid_table; + /******************************************************************* load the case handling tables ********************************************************************/ @@ -45,7 +46,6 @@ void load_case_tables(void) upcase_table = map_file(lib_path("upcase.dat"), 0x20000); lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000); - valid_table = map_file(lib_path("valid.dat"), 0x10000); /* we would like Samba to limp along even if these tables are not available */ @@ -62,14 +62,50 @@ void load_case_tables(void) for (i=0;i<0x10000;i++) lowcase_table[i] = i; for (i=0;i<256;i++) lowcase_table[UCS2_CHAR(i)] = UCS2_CHAR(isupper(i)?tolower(i):i); } +} + +/* + see if a ucs2 character can be mapped correctly to a dos character + and mapped back to the same character in ucs2 +*/ +static int check_dos_char(smb_ucs2_t c) +{ + char buf[10]; + smb_ucs2_t c2 = 0; + int len1, len2; + len1 = convert_string(CH_UCS2, CH_DOS, &c, 2, buf, sizeof(buf)); + if (len1 == 0) return 0; + len2 = convert_string(CH_DOS, CH_UCS2, buf, len1, &c2, 2); + if (len2 != 2) return 0; + return (c == c2); +} + +/******************************************************************* +load the valid character map table +********************************************************************/ +void init_valid_table(void) +{ + static int initialised; + static int mapped_file; + int i; + const char *allowed = ".!#$%&'()_-@^`~"; + + if (initialised && mapped_file) return; + initialised = 1; - if (!valid_table) { - const char *allowed = ".!#$%&'()_-@^`~"; - DEBUG(1,("creating lame valid table\n")); - valid_table = malloc(0x10000); - for (i=0;i<0x10000;i++) valid_table[i] = 0; - for (i=0;i<256;i++) valid_table[UCS2_CHAR(i)] = isalnum(i) || strchr(allowed,i); + valid_table = map_file(lib_path("valid.dat"), 0x10000); + if (valid_table) { + mapped_file = 1; + return; } + + if (valid_table) free(valid_table); + + DEBUG(2,("creating default valid table\n")); + valid_table = malloc(0x10000); + for (i=0;i<128;i++) valid_table[UCS2_CHAR(i)] = isalnum(i) || + strchr(allowed,i); + for (;i<0x10000;i++) valid_table[UCS2_CHAR(i)] = check_dos_char(i); } |