Fix bug #7781 (Samba transforms "ShareName" to lowercase when adding new share via...
[samba.git] / source3 / lib / util_str.c
index cdd7d0a300e118768653191e62ba3dff7cb3f1a9..17a4a8f2c4e9727f56a0c559d70de14ac4c14c57 100644 (file)
@@ -96,14 +96,14 @@ int StrCaseCmp(const char *s, const char *t)
                        return +1;
        }
 
-       if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
                return strcmp(ps, pt);
                /* Not quite the right answer, but finding the right one
                   under this failure case is expensive, and it's pretty
                   close */
        }
 
-       if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
                TALLOC_FREE(buffer_s);
                return strcmp(ps, pt);
                /* Not quite the right answer, but finding the right one
@@ -157,14 +157,14 @@ int StrnCaseCmp(const char *s, const char *t, size_t len)
                return 0;
        }
 
-       if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
                return strncmp(ps, pt, len-n);
                /* Not quite the right answer, but finding the right one
                   under this failure case is expensive,
                   and it's pretty close */
        }
 
-       if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
                TALLOC_FREE(buffer_s);
                return strncmp(ps, pt, len-n);
                /* Not quite the right answer, but finding the right one
@@ -366,7 +366,7 @@ size_t str_charnum(const char *s)
 {
        size_t ret, converted_size;
        smb_ucs2_t *tmpbuf2 = NULL;
-       if (!push_ucs2_talloc(NULL, &tmpbuf2, s, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
                return 0;
        }
        ret = strlen_w(tmpbuf2);
@@ -384,7 +384,7 @@ size_t str_ascii_charnum(const char *s)
 {
        size_t ret, converted_size;
        char *tmpbuf2 = NULL;
-       if (!push_ascii_talloc(NULL, &tmpbuf2, s, &converted_size)) {
+       if (!push_ascii_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
                return 0;
        }
        ret = strlen(tmpbuf2);
@@ -455,7 +455,7 @@ bool strhasupper(const char *s)
        bool ret;
        size_t converted_size;
 
-       if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) {
                return false;
        }
 
@@ -480,7 +480,7 @@ bool strhaslower(const char *s)
        bool ret;
        size_t converted_size;
 
-       if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) {
                return false;
        }
 
@@ -586,7 +586,9 @@ char *safe_strcat_fn(const char *fn,
  Paranoid strcpy into a buffer of given length (includes terminating
  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
  and replaces with '_'. Deliberately does *NOT* check for multibyte
- characters. Don't change it !
+ characters. Treats src as an array of bytes, not as a multibyte
+ string. Any byte >0x7f is automatically converted to '_'.
+ other_safe_chars must also contain an ascii string (bytes<0x7f).
 **/
 
 char *alpha_strcpy_fn(const char *fn,
@@ -622,8 +624,12 @@ char *alpha_strcpy_fn(const char *fn,
 
        for(i = 0; i < len; i++) {
                int val = (src[i] & 0xff);
-               if (isupper_ascii(val) || islower_ascii(val) ||
-                               isdigit(val) || strchr_m(other_safe_chars, val))
+               if (val > 0x7f) {
+                       dest[i] = '_';
+                       continue;
+               }
+               if (isupper(val) || islower(val) ||
+                               isdigit(val) || strchr(other_safe_chars, val))
                        dest[i] = src[i];
                else
                        dest[i] = '_';
@@ -1177,7 +1183,7 @@ char *strchr_m(const char *src, char c)
        s = src;
 #endif
 
-       if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
                /* Wrong answer, but what can we do... */
                return strchr(src, c);
        }
@@ -1187,7 +1193,7 @@ char *strchr_m(const char *src, char c)
                return NULL;
        }
        *p = 0;
-       if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) {
+       if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
                SAFE_FREE(ws);
                /* Wrong answer, but what can we do... */
                return strchr(src, c);
@@ -1248,7 +1254,7 @@ char *strrchr_m(const char *s, char c)
                char *ret;
                size_t converted_size;
 
-               if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) {
+               if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
                        /* Wrong answer, but what can we do. */
                        return strrchr(s, c);
                }
@@ -1258,7 +1264,7 @@ char *strrchr_m(const char *s, char c)
                        return NULL;
                }
                *p = 0;
-               if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) {
+               if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
                        TALLOC_FREE(ws);
                        /* Wrong answer, but what can we do. */
                        return strrchr(s, c);
@@ -1283,7 +1289,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n)
        char *ret;
        size_t converted_size;
 
-       if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
                /* Too hard to try and get right. */
                return NULL;
        }
@@ -1293,7 +1299,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n)
                return NULL;
        }
        *p = 0;
-       if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) {
+       if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
                TALLOC_FREE(ws);
                /* Too hard to try and get right. */
                return NULL;
@@ -1352,12 +1358,12 @@ char *strstr_m(const char *src, const char *findstr)
        s = src;
 #endif
 
-       if (!push_ucs2_talloc(NULL, &src_w, src, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &src_w, src, &converted_size)) {
                DEBUG(0,("strstr_m: src malloc fail\n"));
                return NULL;
        }
 
-       if (!push_ucs2_talloc(NULL, &find_w, findstr, &converted_size)) {
+       if (!push_ucs2_talloc(talloc_tos(), &find_w, findstr, &converted_size)) {
                TALLOC_FREE(src_w);
                DEBUG(0,("strstr_m: find malloc fail\n"));
                return NULL;
@@ -1372,7 +1378,7 @@ char *strstr_m(const char *src, const char *findstr)
        }
 
        *p = 0;
-       if (!pull_ucs2_talloc(NULL, &s2, src_w, &converted_size)) {
+       if (!pull_ucs2_talloc(talloc_tos(), &s2, src_w, &converted_size)) {
                TALLOC_FREE(src_w);
                TALLOC_FREE(find_w);
                DEBUG(0,("strstr_m: dest malloc fail\n"));
@@ -1454,12 +1460,12 @@ void strupper_m(char *s)
 }
 
 /**
- Count the number of UCS2 characters in a string. Normally this will
- be the same as the number of bytes in a string for single byte strings,
- but will be different for multibyte.
-**/
-
-size_t strlen_m(const char *s)
+ * Calculate the number of units (8 or 16-bit, depending on the
+ * destination charset), that would be needed to convert the input
+ * string which is expected to be in in CH_UNIX encoding to the
+ * destination charset (which should be a unicode charset).
+ */
+size_t strlen_m_ext(const char *s, const charset_t dst_charset)
 {
        size_t count = 0;
 
@@ -1479,19 +1485,67 @@ size_t strlen_m(const char *s)
        while (*s) {
                size_t c_size;
                codepoint_t c = next_codepoint(s, &c_size);
-               if (c < 0x10000) {
-                       /* Unicode char fits into 16 bits. */
+               s += c_size;
+
+               switch(dst_charset) {
+               case CH_UTF16LE:
+               case CH_UTF16BE:
+               case CH_UTF16MUNGED:
+                       if (c < 0x10000) {
+                               /* Unicode char fits into 16 bits. */
+                               count += 1;
+                       } else {
+                               /* Double-width unicode char - 32 bits. */
+                               count += 2;
+                       }
+                       break;
+               case CH_UTF8:
+                       /*
+                        * this only checks ranges, and does not
+                        * check for invalid codepoints
+                        */
+                       if (c < 0x80) {
+                               count += 1;
+                       } else if (c < 0x800) {
+                               count += 2;
+                       } else if (c < 0x1000) {
+                               count += 3;
+                       } else {
+                               count += 4;
+                       }
+                       break;
+               default:
+                       /*
+                        * non-unicode encoding:
+                        * assume that each codepoint fits into
+                        * one unit in the destination encoding.
+                        */
                        count += 1;
-               } else {
-                       /* Double-width unicode char - 32 bits. */
-                       count += 2;
                }
-               s += c_size;
        }
 
        return count;
 }
 
+size_t strlen_m_ext_term(const char *s, const charset_t dst_charset)
+{
+       if (!s) {
+               return 0;
+       }
+       return strlen_m_ext(s, dst_charset) + 1;
+}
+
+/**
+ Count the number of UCS2 characters in a string. Normally this will
+ be the same as the number of bytes in a string for single byte strings,
+ but will be different for multibyte.
+**/
+
+size_t strlen_m(const char *s)
+{
+       return strlen_m_ext(s, CH_UTF16LE);
+}
+
 /**
  Count the number of UCS2 characters in a string including the null
  terminator.
@@ -1616,7 +1670,7 @@ bool str_list_sub_basic( char **list, const char *smb_name,
 }
 
 /******************************************************************************
- substritute a specific pattern in a string list
+ substitute a specific pattern in a string list
  *****************************************************************************/
 
 bool str_list_substitute(char **list, const char *pattern, const char *insert)
@@ -1932,7 +1986,7 @@ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
        result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */
        SMB_ASSERT(result != NULL);
 
-       while (len-- && out_cnt < (data.length * 2) - 5) {
+       while (len--) {
                int c = (unsigned char) *(data.data++);
                bits += c;
                char_count++;
@@ -2247,6 +2301,10 @@ bool validate_net_name( const char *name,
 {
        int i;
 
+       if (!name) {
+               return false;
+       }
+
        for ( i=0; i<max_len && name[i]; i++ ) {
                /* fail if strchr_m() finds one of the invalid characters */
                if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
@@ -2430,13 +2488,13 @@ char *escape_shell_string(const char *src)
 
 #define S_LIST_ABS 16 /* List Allocation Block Size */
 
-char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
+char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
+       const char *sep)
 {
        char **list;
        const char *str;
-       char *s;
+       char *s, *tok;
        int num, lsize;
-       char *tok;
 
        if (!string || !*string)
                return NULL;