diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h index 82396e14985..16bb9c62fbf 100644 --- a/lib/util/charset/charset.h +++ b/lib/util/charset/charset.h @@ -130,17 +130,29 @@ void string_replace_m(char *s, char oldc, char newc); bool strcsequal(const char *s1,const char *s2); bool strequal_m(const char *s1, const char *s2); int strncasecmp_m(const char *s1, const char *s2, size_t n); +int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2, size_t n); bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize); +int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2); int strcasecmp_m(const char *s1, const char *s2); size_t count_chars_m(const char *s, char c); void strupper_m(char *s); void strlower_m(char *s); char *strupper_talloc(TALLOC_CTX *ctx, const char *src); char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *src); +char *strupper_talloc_n_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src, size_t n); char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n); + char *strlower_talloc_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src); char *strlower_talloc(TALLOC_CTX *ctx, const char *src); bool strhasupper(const char *string); +bool strhaslower_handle(struct smb_iconv_handle *ic, + const char *string); bool strhaslower(const char *string); +bool strhasupper_handle(struct smb_iconv_handle *ic, + const char *string); char *strrchr_m(const char *s, char c); char *strchr_m(const char *s, char c); diff --git a/lib/util/charset/tests/convert_string.c b/lib/util/charset/tests/convert_string.c index 5c7bdcb1da5..a634e84e9cb 100644 --- a/lib/util/charset/tests/convert_string.c +++ b/lib/util/charset/tests/convert_string.c @@ -490,6 +490,166 @@ static bool test_plato_latin_cp850_utf8(struct torture_context *tctx) return true; } +static bool test_gd_case_utf8(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB gd_utf8 = base64_decode_data_blob(gd_utf8_base64); + char *gd_lower, *gd_upper; + talloc_steal(tctx, gd_utf8.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8", "UTF8"); + torture_assert(tctx, iconv_handle, "getting utf8 iconv handle"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, (const char *)gd_utf8.data), + "GD's name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, (const char *)gd_utf8.data), + "GD's name has an lower case character"); + gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_utf8.data); + torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case"); + gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_utf8.data, gd_utf8.length); + torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_upper), + "upper case name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_lower), + "lower case name has an lower case character"); + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_lower) == false, + "lower case name has no upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_upper) == false, + "upper case name has no lower case character"); + + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper, + gd_lower) == 0, + "case insensitive comparison upper/lower"); + + /* This string isn't different in length upper/lower */ + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_upper, gd_utf8.length) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_utf8.data, + gd_lower, gd_utf8.length) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper, + gd_lower, gd_utf8.length) == 0, + "case insensitive comparison upper/lower"); + return true; +} + +static bool test_gd_case_cp850(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB gd_cp850 = base64_decode_data_blob(gd_cp850_base64); + char *gd_lower, *gd_upper; + talloc_steal(tctx, gd_cp850.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "CP850", "CP850"); + torture_assert(tctx, iconv_handle, "getting cp850 iconv handle"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, (const char *)gd_cp850.data), + "GD's name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, (const char *)gd_cp850.data), + "GD's name has an lower case character"); + gd_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)gd_cp850.data); + torture_assert(tctx, gd_lower, "failed to convert GD's name into lower case"); + gd_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)gd_cp850.data, gd_cp850.length); + torture_assert(tctx, gd_lower, "failed to convert GD's name into upper case"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_upper), + "upper case name has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_lower), + "lower case name has an lower case character"); + torture_assert(tctx, + strhasupper_handle(iconv_handle, gd_lower) == false, + "lower case name has no upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, gd_upper) == false, + "upper case name has no lower case character"); + + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, gd_upper, + gd_lower) == 0, + "case insensitive comparison upper/lower"); + + /* This string isn't different in length upper/lower */ + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_upper, gd_cp850.length) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, (const char *)gd_cp850.data, + gd_lower, gd_cp850.length) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strncasecmp_m_handle(iconv_handle, gd_upper, + gd_lower, gd_cp850.length) == 0, + "case insensitive comparison upper/lower"); + return true; +} + +static bool test_plato_case_utf8(struct torture_context *tctx) +{ + struct smb_iconv_handle *iconv_handle; + DATA_BLOB plato_utf8 = base64_decode_data_blob(plato_utf8_base64); + char *plato_lower, *plato_upper; + talloc_steal(tctx, plato_utf8.data); + + iconv_handle = get_iconv_testing_handle(tctx, "ASCII", "UTF8", "UTF8"); + torture_assert(tctx, iconv_handle, "getting utf8 iconv handle"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, (const char *)plato_utf8.data), + "PLATO's apology has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, (const char *)plato_utf8.data), + "PLATO's apology has an lower case character"); + plato_lower = strlower_talloc_handle(iconv_handle, tctx, (const char *)plato_utf8.data); + torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into lower case"); + plato_upper = strupper_talloc_n_handle(iconv_handle, tctx, (const char *)plato_utf8.data, plato_utf8.length); + torture_assert(tctx, plato_lower, "failed to convert PLATO's apology into upper case"); + + torture_assert(tctx, + strhasupper_handle(iconv_handle, plato_upper), + "upper case string has an upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, plato_lower), + "lower case string has an lower case character"); + torture_assert(tctx, + strhasupper_handle(iconv_handle, plato_lower) == false, + "lower case string has no upper case character"); + torture_assert(tctx, + strhaslower_handle(iconv_handle, plato_upper) == false, + "upper case string has no lower case character"); + + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data, + plato_upper) == 0, + "case insensitive comparison orig/upper"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, (const char *)plato_utf8.data, + plato_lower) == 0, + "case insensitive comparison orig/lower"); + torture_assert(tctx, strcasecmp_m_handle(iconv_handle, plato_upper, + plato_lower) == 0, + "case insensitive comparison upper/lower"); + return true; +} + struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx) { struct torture_suite *suite = torture_suite_create(mem_ctx, "convert_string_talloc"); @@ -501,3 +661,13 @@ struct torture_suite *torture_local_convert_string(TALLOC_CTX *mem_ctx) torture_suite_add_simple_test(suite, "plato_ascii_cp850_utf8", test_plato_latin_cp850_utf8); return suite; } + +struct torture_suite *torture_local_string_case(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "string_case"); + + torture_suite_add_simple_test(suite, "gd_case_utf8", test_gd_case_utf8); + torture_suite_add_simple_test(suite, "gd_case_cp850", test_gd_case_cp850); + torture_suite_add_simple_test(suite, "plato_case_utf8", test_plato_case_utf8); + return suite; +} diff --git a/lib/util/charset/util_str.c b/lib/util/charset/util_str.c index f36c91eef35..e8f0b788b1c 100644 --- a/lib/util/charset/util_str.c +++ b/lib/util/charset/util_str.c @@ -28,13 +28,13 @@ #endif /** - Case insensitive string compararison + Case insensitive string compararison, handle specified for testing **/ -_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2) +_PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2) { codepoint_t c1=0, c2=0; size_t size1, size2; - struct smb_iconv_handle *iconv_handle = get_iconv_handle(); /* handle null ptr comparisons to simplify the use in qsort */ if (s1 == s2) return 0; @@ -67,13 +67,22 @@ _PUBLIC_ int strcasecmp_m(const char *s1, const char *s2) } /** - Case insensitive string compararison, length limited + Case insensitive string compararison **/ -_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n) +_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strcasecmp_m_handle(iconv_handle, s1, s2); +} + +/** + Case insensitive string compararison, length limited, handle specified for testing +**/ +_PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle, + const char *s1, const char *s2, size_t n) { codepoint_t c1=0, c2=0; size_t size1, size2; - struct smb_iconv_handle *iconv_handle = get_iconv_handle(); /* handle null ptr comparisons to simplify the use in qsort */ if (s1 == s2) return 0; @@ -111,6 +120,15 @@ _PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n) return *s1 - *s2; } +/** + Case insensitive string compararison, length limited +**/ +_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strncasecmp_m_handle(iconv_handle, s1, s2, n); +} + /** * Compare 2 strings. * @@ -399,9 +417,9 @@ _PUBLIC_ char *strrchr_m(const char *s, char c) /** return True if any (multi-byte) character is lower case */ -_PUBLIC_ bool strhaslower(const char *string) +_PUBLIC_ bool strhaslower_handle(struct smb_iconv_handle *ic, + const char *string) { - struct smb_iconv_handle *ic = get_iconv_handle(); while (*string) { size_t c_size; codepoint_t s; @@ -420,12 +438,18 @@ _PUBLIC_ bool strhaslower(const char *string) return false; } +_PUBLIC_ bool strhaslower(const char *string) +{ + struct smb_iconv_handle *ic = get_iconv_handle(); + return strhaslower_handle(ic, string); +} + /** return True if any (multi-byte) character is upper case */ -_PUBLIC_ bool strhasupper(const char *string) +_PUBLIC_ bool strhasupper_handle(struct smb_iconv_handle *ic, + const char *string) { - struct smb_iconv_handle *ic = get_iconv_handle(); while (*string) { size_t c_size; codepoint_t s; @@ -444,3 +468,8 @@ _PUBLIC_ bool strhasupper(const char *string) return false; } +_PUBLIC_ bool strhasupper(const char *string) +{ + struct smb_iconv_handle *ic = get_iconv_handle(); + return strhasupper_handle(ic, string); +} diff --git a/lib/util/charset/util_unistr.c b/lib/util/charset/util_unistr.c index 284863a71c1..41549bff879 100644 --- a/lib/util/charset/util_unistr.c +++ b/lib/util/charset/util_unistr.c @@ -134,11 +134,11 @@ _PUBLIC_ char *alpha_strcpy(char *dest, const char *src, const char *other_safe_ /** Convert a string to lower case, allocated with talloc **/ -_PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src) +_PUBLIC_ char *strlower_talloc_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src) { size_t size=0; char *dest; - struct smb_iconv_handle *iconv_handle = get_iconv_handle(); if(src == NULL) { return NULL; @@ -176,15 +176,21 @@ _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src) return dest; } +_PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strlower_talloc_handle(iconv_handle, ctx, src); +} + /** Convert a string to UPPER case, allocated with talloc - source length limited to n bytes + source length limited to n bytes, iconv handle supplied **/ -_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n) +_PUBLIC_ char *strupper_talloc_n_handle(struct smb_iconv_handle *iconv_handle, + TALLOC_CTX *ctx, const char *src, size_t n) { size_t size=0; char *dest; - struct smb_iconv_handle *iconv_handle = get_iconv_handle(); if (!src) { return NULL; @@ -222,6 +228,15 @@ _PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n) return dest; } +/** + Convert a string to UPPER case, allocated with talloc + source length limited to n bytes +**/ +_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n) +{ + struct smb_iconv_handle *iconv_handle = get_iconv_handle(); + return strupper_talloc_n_handle(iconv_handle, ctx, src, n); +} /** Convert a string to UPPER case, allocated with talloc **/ diff --git a/source4/torture/local/local.c b/source4/torture/local/local.c index d542bfec59a..53fab6636c7 100644 --- a/source4/torture/local/local.c +++ b/source4/torture/local/local.c @@ -61,6 +61,7 @@ torture_local_loadparm, torture_local_charset, torture_local_convert_string, + torture_local_string_case, torture_local_compression, torture_local_event, torture_local_torture,