summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/lib/charcnv.c13
-rw-r--r--source3/lib/iconv.c8
-rw-r--r--source3/lib/util_unistr.c50
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);
}