diff --git a/lib/replace/replace.c b/lib/replace/replace.c index 12716ea..0197b10 100644 --- a/lib/replace/replace.c +++ b/lib/replace/replace.c @@ -30,6 +30,7 @@ #include "system/syslog.h" #include "system/locale.h" #include "system/wait.h" +#include "../util/safe_string.h" #ifdef _WIN32 #define mkdir(d,m) _mkdir(d) @@ -466,7 +467,7 @@ char *rep_strcasestr(const char *haystack, const char *needle) const char *s; size_t nlen = strlen(needle); for (s=haystack;*s;s++) { - if (toupper(*needle) == toupper(*s) && + if (ascii_toupper(*needle) == ascii_toupper(*s) && strncasecmp(s, needle, nlen) == 0) { return (char *)((uintptr_t)s); } diff --git a/lib/util/charset/charcnv.c b/lib/util/charset/charcnv.c index e9f6ab0..4e46cfc 100644 --- a/lib/util/charset/charcnv.c +++ b/lib/util/charset/charcnv.c @@ -135,21 +135,6 @@ static smb_iconv_t get_conv_handle(struct smb_iconv_convenience *ic, charset_t from, charset_t to) { const char *n1, *n2; - static bool initialised; - - if (initialised == false) { - initialised = true; - -#ifdef LC_ALL - /* we set back the locale to C to get ASCII-compatible - toupper/lower functions. For now we do not need - any other POSIX localisations anyway. When we - should really need localized string functions one - day we need to write our own ascii_tolower etc. - */ - setlocale(LC_ALL, "C"); -#endif - } if (ic->conv_handles[from][to]) { return ic->conv_handles[from][to]; diff --git a/lib/util/charset/codepoints.c b/lib/util/charset/codepoints.c index 8be2051..95e7e77 100644 --- a/lib/util/charset/codepoints.c +++ b/lib/util/charset/codepoints.c @@ -21,6 +21,7 @@ #include "includes.h" #include "system/locale.h" #include "dynconfig/dynconfig.h" +#include "lib/util/safe_string.h" /** * @file @@ -69,7 +70,7 @@ void load_case_tables(void) _PUBLIC_ codepoint_t toupper_m(codepoint_t val) { if (val < 128) { - return toupper(val); + return ascii_toupper(val); } if (upcase_table == NULL) { load_case_tables(); @@ -89,7 +90,7 @@ _PUBLIC_ codepoint_t toupper_m(codepoint_t val) _PUBLIC_ codepoint_t tolower_m(codepoint_t val) { if (val < 128) { - return tolower(val); + return ascii_tolower(val); } if (lowcase_table == NULL) { load_case_tables(); diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c index 520ce05..d445116 100644 --- a/lib/util/charset/util_unistr.c +++ b/lib/util/charset/util_unistr.c @@ -542,7 +542,7 @@ _PUBLIC_ void strlower_m(char *s) supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ while (*s && !(((uint8_t)*s) & 0x80)) { - *s = tolower((uint8_t)*s); + *s = ascii_tolower((uint8_t)*s); s++; } @@ -581,7 +581,7 @@ _PUBLIC_ void strupper_m(char *s) supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ while (*s && !(((uint8_t)*s) & 0x80)) { - *s = toupper((uint8_t)*s); + *s = ascii_toupper((uint8_t)*s); s++; } diff --git a/lib/util/safe_string.h b/lib/util/safe_string.h index a6c052f..283a0ab 100644 --- a/lib/util/safe_string.h +++ b/lib/util/safe_string.h @@ -41,4 +41,7 @@ #endif /* !_SPLINT_ */ +char ascii_tolower (char c); +char ascii_toupper (char c); + #endif diff --git a/lib/util/util.c b/lib/util/util.c index d645f7e..0582d35 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -602,12 +602,12 @@ _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t } for (; i < strhex_len && strhex[i] != 0; i++) { - if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i])))) + if (!(p1 = strchr(hexchars, ascii_toupper((unsigned char)strhex[i])))) break; i++; /* next hex digit */ - if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i])))) + if (!(p2 = strchr(hexchars, ascii_toupper((unsigned char)strhex[i])))) break; /* get the two nybbles */ diff --git a/lib/util/util_str.c b/lib/util/util_str.c index 0ea71a8..90dac6c 100644 --- a/lib/util/util_str.c +++ b/lib/util/util_str.c @@ -289,7 +289,7 @@ _PUBLIC_ int strwicmp(const char *psz1, const char *psz2) psz1++; while (isspace((int)*psz2)) psz2++; - if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2) + if (ascii_toupper((unsigned char)*psz1) != ascii_toupper((unsigned char)*psz2) || *psz1 == '\0' || *psz2 == '\0') break; @@ -332,4 +332,22 @@ _PUBLIC_ void string_replace(char *s, char oldc, char newc) } } +/** + like tolower(), but only for ascii letters, to not depend on C locale +**/ +char ascii_tolower (char c) +{ + if (c >= 'A' && c <= 'Z') + c = c + 32; + return c; +} +/** + like toupper(), but only for ascii letters, to not depend on C locale +**/ +char ascii_toupper (char c) +{ + if (c >= 'a' && c <= 'z') + c = c - 32; + return c; +} diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index b9bff91..c3e0538 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -42,6 +42,7 @@ #include "dsdb/common/util.h" #include "lib/socket/socket.h" #include "dsdb/samdb/ldb_modules/util.h" +#include "lib/util/safe_string.h" /* search the sam for the specified attributes in a specific domain, filter on @@ -2815,10 +2816,10 @@ const char *samdb_cn_to_lDAPDisplayName(TALLOC_CTX *mem_ctx, const char *cn) if (tokens == NULL) return NULL; - /* "tolower()" and "toupper()" should also work properly on 0x00 */ - tokens[0][0] = tolower(tokens[0][0]); + /* "ascii_tolower()" and "ascii_toupper()" should also work properly on 0x00 */ + tokens[0][0] = ascii_tolower(tokens[0][0]); for (i = 1; i < str_list_length((const char **)tokens); i++) - tokens[i][0] = toupper(tokens[i][0]); + tokens[i][0] = ascii_toupper(tokens[i][0]); ret = talloc_strdup(mem_ctx, tokens[0]); for (i = 1; i < str_list_length((const char **)tokens); i++) diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c index 2f4454c..a929e41 100644 --- a/source4/lib/ldb/common/attrib_handlers.c +++ b/source4/lib/ldb/common/attrib_handlers.c @@ -29,6 +29,7 @@ #include "ldb_private.h" #include "system/locale.h" #include "ldb_handlers.h" +#include "lib/util/safe_string.h" /* default handler that just copies a ldb_val. @@ -227,7 +228,7 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, * never appear in multibyte sequences */ if (((unsigned char)s1[0]) & 0x80) goto utf8str; if (((unsigned char)s2[0]) & 0x80) goto utf8str; - if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2)) + if (ascii_toupper((unsigned char)*s1) != ascii_toupper((unsigned char)*s2)) break; if (*s1 == ' ') { while (n1 && s1[0] == s1[1]) { s1++; n1--; } @@ -249,15 +250,15 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx, while (n2 && *s2 == ' ') { s2++; n2--; } } if (n1 == 0 && n2 != 0) { - return -(int)toupper(*s2); + return -(int)ascii_toupper(*s2); } if (n2 == 0 && n1 != 0) { - return (int)toupper(*s1); + return (int)ascii_toupper(*s1); } if (n2 == 0 && n2 == 0) { return 0; } - return (int)toupper(*s1) - (int)toupper(*s2); + return (int)ascii_toupper(*s1) - (int)ascii_toupper(*s2); utf8str: /* no need to recheck from the start, just from the first utf8 char found */ @@ -273,9 +274,9 @@ utf8str: if (ret == 0) { if (n1 == n2) return 0; if (n1 > n2) { - return (int)toupper(s1[n2]); + return (int)ascii_toupper(s1[n2]); } else { - return -(int)toupper(s2[n1]); + return -(int)ascii_toupper(s2[n1]); } } return ret; diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c index 73ae71b..cc98464 100644 --- a/source4/lib/ldb/common/ldb_utf8.c +++ b/source4/lib/ldb/common/ldb_utf8.c @@ -33,7 +33,7 @@ #include "ldb_private.h" #include "system/locale.h" - +#include "lib/util/safe_string.h" /* this allow the user to pass in a caseless comparison @@ -62,7 +62,7 @@ char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n return NULL; } for (i=0;ret[i];i++) { - ret[i] = toupper((unsigned char)ret[i]); + ret[i] = ascii_toupper((unsigned char)ret[i]); } return ret; } @@ -118,7 +118,7 @@ char *ldb_attr_casefold(void *mem_ctx, const char *s) return NULL; } for (i = 0; ret[i]; i++) { - ret[i] = toupper((unsigned char)ret[i]); + ret[i] = ascii_toupper((unsigned char)ret[i]); } return ret; } diff --git a/source4/lib/samba3/smbpasswd.c b/source4/lib/samba3/smbpasswd.c index 502f13f..1163748 100644 --- a/source4/lib/samba3/smbpasswd.c +++ b/source4/lib/samba3/smbpasswd.c @@ -55,6 +55,7 @@ #include "includes.h" #include "system/locale.h" #include "lib/samba3/samba3.h" +#include "lib/util/safe_string.h" /*! Convert 32 hex characters into a 16 byte array. */ @@ -70,8 +71,8 @@ struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, const char *p) for (i = 0; i < (sizeof(pwd->hash) * 2); i += 2) { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); + hinybble = ascii_toupper(p[i]); + lonybble = ascii_toupper(p[i + 1]); p1 = strchr_m(hexchars, hinybble); p2 = strchr_m(hexchars, lonybble); diff --git a/source4/ntvfs/posix/pvfs_shortname.c b/source4/ntvfs/posix/pvfs_shortname.c index 530def9..ea2dd82 100644 --- a/source4/ntvfs/posix/pvfs_shortname.c +++ b/source4/ntvfs/posix/pvfs_shortname.c @@ -23,6 +23,7 @@ #include "system/locale.h" #include "vfs_posix.h" #include "param/param.h" +#include "lib/util/safe_string.h" /* this mangling scheme uses the following format @@ -471,7 +472,7 @@ static char *name_map(struct pvfs_mangle_context *ctx, if (! FLAG_CHECK(lead_chars[i], FLAG_ASCII)) { lead_chars[i] = '_'; } - lead_chars[i] = toupper((unsigned char)lead_chars[i]); + lead_chars[i] = ascii_toupper((unsigned char)lead_chars[i]); } for (;imangle_prefix;i++) { lead_chars[i] = '_'; @@ -491,7 +492,7 @@ static char *name_map(struct pvfs_mangle_context *ctx, for (i=1; extension_length < 3 && dot_p[i]; i++) { unsigned char c = dot_p[i]; if (FLAG_CHECK(c, FLAG_ASCII)) { - extension[extension_length++] = toupper(c); + extension[extension_length++] = ascii_toupper(c); } } } @@ -589,10 +590,10 @@ static void init_tables(struct pvfs_mangle_context *ctx) ctx->char_flags[c2] |= FLAG_POSSIBLE2; ctx->char_flags[c3] |= FLAG_POSSIBLE3; ctx->char_flags[c4] |= FLAG_POSSIBLE4; - ctx->char_flags[tolower(c1)] |= FLAG_POSSIBLE1; - ctx->char_flags[tolower(c2)] |= FLAG_POSSIBLE2; - ctx->char_flags[tolower(c3)] |= FLAG_POSSIBLE3; - ctx->char_flags[tolower(c4)] |= FLAG_POSSIBLE4; + ctx->char_flags[ascii_tolower(c1)] |= FLAG_POSSIBLE1; + ctx->char_flags[ascii_tolower(c2)] |= FLAG_POSSIBLE2; + ctx->char_flags[ascii_tolower(c3)] |= FLAG_POSSIBLE3; + ctx->char_flags[ascii_tolower(c4)] |= FLAG_POSSIBLE4; ctx->char_flags[(unsigned char)'.'] |= FLAG_POSSIBLE4; }