r13622: Allow to rename machine accounts in a Samba Domain. This still uses the
[jra/samba/.git] / source / lib / util_str.c
index 1401d6d85349de0f8e17f34451c89e1bfa30f28b..e799556cd1ebb6ad87208561b429f38979331b7b 100644 (file)
@@ -183,7 +183,7 @@ char **toktocliplist(int *ctok, const char *sep)
 int StrCaseCmp(const char *s, const char *t)
 {
 
-       const char * ps, * pt;
+       const char *ps, *pt;
        size_t size;
        smb_ucs2_t *buffer_s, *buffer_t;
        int ret;
@@ -201,8 +201,8 @@ int StrCaseCmp(const char *s, const char *t)
                        /* not ascii anymore, do it the hard way from here on in */
                        break;
 
-               us = toupper(*ps);
-               ut = toupper(*pt);
+               us = toupper_ascii(*ps);
+               ut = toupper_ascii(*pt);
                if (us == ut)
                        continue;
                else if (us < ut)
@@ -211,17 +211,17 @@ int StrCaseCmp(const char *s, const char *t)
                        return +1;
        }
 
-       size = push_ucs2_allocate(&buffer_s, s);
+       size = push_ucs2_allocate(&buffer_s, ps);
        if (size == (size_t)-1) {
-               return strcmp(s, t); 
+               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 */
        }
        
-       size = push_ucs2_allocate(&buffer_t, t);
+       size = push_ucs2_allocate(&buffer_t, pt);
        if (size == (size_t)-1) {
                SAFE_FREE(buffer_s);
-               return strcmp(s, t); 
+               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 */
        }
@@ -266,12 +266,12 @@ BOOL strequal(const char *s1, const char *s2)
  **/
 BOOL strnequal(const char *s1,const char *s2,size_t n)
 {
-  if (s1 == s2)
-         return(True);
-  if (!s1 || !s2 || !n)
-         return(False);
+       if (s1 == s2)
+               return(True);
+       if (!s1 || !s2 || !n)
+               return(False);
   
-  return(StrnCaseCmp(s1,s2,n)==0);
+       return(StrnCaseCmp(s1,s2,n)==0);
 }
 
 /**
@@ -280,12 +280,12 @@ BOOL strnequal(const char *s1,const char *s2,size_t n)
 
 BOOL strcsequal(const char *s1,const char *s2)
 {
-  if (s1 == s2)
-         return(True);
-  if (!s1 || !s2)
-         return(False);
+       if (s1 == s2)
+               return(True);
+       if (!s1 || !s2)
+               return(False);
   
-  return(strcmp(s1,s2)==0);
+       return(strcmp(s1,s2)==0);
 }
 
 /**
@@ -309,7 +309,7 @@ int strwicmp(const char *psz1, const char *psz2)
                        psz1++;
                while (isspace((int)*psz2))
                        psz2++;
-               if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
+               if (toupper_ascii(*psz1) != toupper_ascii(*psz2) || *psz1 == '\0'
                    || *psz2 == '\0')
                        break;
                psz1++;
@@ -680,7 +680,7 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con
 
        for(i = 0; i < len; i++) {
                int val = (src[i] & 0xff);
-               if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
+               if (isupper_ascii(val) || islower_ascii(val) || isdigit(val) || strchr_m(other_safe_chars, val))
                        dest[i] = src[i];
                else
                        dest[i] = '_';
@@ -774,12 +774,12 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex)
                        continue;
                }
 
-               if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
+               if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
                        break;
 
                i++; /* next hex digit */
 
-               if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
+               if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
                        break;
 
                /* get the two nybbles */
@@ -795,9 +795,14 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex)
        return num_chars;
 }
 
-DATA_BLOB strhex_to_data_blob(const char *strhex) 
+DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) 
 {
-       DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1);
+       DATA_BLOB ret_blob;
+
+       if (mem_ctx != NULL)
+               ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
+       else
+               ret_blob = data_blob(NULL, strlen(strhex)/2+1);
 
        ret_blob.length = strhex_to_str((char*)ret_blob.data,   
                                        strlen(strhex), 
@@ -810,16 +815,17 @@ DATA_BLOB strhex_to_data_blob(const char *strhex)
  * Routine to print a buffer as HEX digits, into an allocated string.
  */
 
-void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
+char *hex_encode(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
 {
        int i;
        char *hex_buffer;
 
-       *out_hex_buffer = SMB_XMALLOC_ARRAY(char, (len*2)+1);
-       hex_buffer = *out_hex_buffer;
+       hex_buffer = TALLOC_ARRAY(mem_ctx, char, (len*2)+1);
 
        for (i = 0; i < len; i++)
                slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
+
+       return hex_buffer;
 }
 
 /**
@@ -917,7 +923,7 @@ BOOL string_set(char **dest,const char *src)
 **/
 
 void string_sub2(char *s,const char *pattern, const char *insert, size_t len, 
-                BOOL remove_unsafe_characters, BOOL replace_once)
+                BOOL remove_unsafe_characters, BOOL replace_once, BOOL allow_trailing_dollar)
 {
        char *p;
        ssize_t ls,lp,li, i;
@@ -949,6 +955,11 @@ void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
                        case '\'':
                        case ';':
                        case '$':
+                               /* allow a trailing $ (as in machine accounts) */
+                               if (allow_trailing_dollar && (i == li - 1 )) {
+                                       p[i] = insert[i];
+                                       break;
+                               }
                        case '%':
                        case '\r':
                        case '\n':
@@ -972,12 +983,12 @@ void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
 
 void string_sub_once(char *s, const char *pattern, const char *insert, size_t len)
 {
-       string_sub2( s, pattern, insert, len, True, True );
+       string_sub2( s, pattern, insert, len, True, True, False );
 }
 
 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
 {
-       string_sub2( s, pattern, insert, len, True, False );
+       string_sub2( s, pattern, insert, len, True, False, False );
 }
 
 void fstring_sub(char *s,const char *pattern,const char *insert)
@@ -997,7 +1008,8 @@ void pstring_sub(char *s,const char *pattern,const char *insert)
  as string.
 **/
 
-char *realloc_string_sub(char *string, const char *pattern, const char *insert)
+char *realloc_string_sub(char *string, const char *pattern,
+                        const char *insert)
 {
        char *p, *in;
        char *s;
@@ -1057,6 +1069,77 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert)
        return string;
 }
 
+/* Same as string_sub, but returns a talloc'ed string */
+
+char *talloc_string_sub(TALLOC_CTX *mem_ctx, const char *src,
+                       const char *pattern, const char *insert)
+{
+       char *p, *in;
+       char *s;
+       char *string;
+       ssize_t ls,lp,li,ld, i;
+
+       if (!insert || !pattern || !*pattern || !src || !*src)
+               return NULL;
+
+       string = talloc_strdup(mem_ctx, src);
+       if (string == NULL) {
+               DEBUG(0, ("talloc_strdup failed\n"));
+               return NULL;
+       }
+
+       s = string;
+
+       in = SMB_STRDUP(insert);
+       if (!in) {
+               DEBUG(0, ("talloc_string_sub: out of memory!\n"));
+               return NULL;
+       }
+       ls = (ssize_t)strlen(s);
+       lp = (ssize_t)strlen(pattern);
+       li = (ssize_t)strlen(insert);
+       ld = li - lp;
+       for (i=0;i<li;i++) {
+               switch (in[i]) {
+                       case '`':
+                       case '"':
+                       case '\'':
+                       case ';':
+                       case '$':
+                       case '%':
+                       case '\r':
+                       case '\n':
+                               in[i] = '_';
+                       default:
+                               /* ok */
+                               break;
+               }
+       }
+       
+       while ((p = strstr_m(s,pattern))) {
+               if (ld > 0) {
+                       int offset = PTR_DIFF(s,string);
+                       char *t = TALLOC_REALLOC(mem_ctx, string, ls + ld + 1);
+                       if (!t) {
+                               DEBUG(0, ("talloc_string_sub: out of "
+                                         "memory!\n"));
+                               SAFE_FREE(in);
+                               return NULL;
+                       }
+                       string = t;
+                       p = t + offset + (p - s);
+               }
+               if (li != lp) {
+                       memmove(p+li,p+lp,strlen(p+lp)+1);
+               }
+               memcpy(p, in, li);
+               s = p + li;
+               ls += ld;
+       }
+       SAFE_FREE(in);
+       return string;
+}
+
 /**
  Similar to string_sub() but allows for any character to be substituted. 
  Use with caution!
@@ -1432,7 +1515,7 @@ void strlower_m(char *s)
           (ie. they match for the first 128 chars) */
 
        while (*s && !(((unsigned char)s[0]) & 0x80)) {
-               *s = tolower((unsigned char)*s);
+               *s = tolower_ascii((unsigned char)*s);
                s++;
        }
 
@@ -1466,7 +1549,7 @@ void strupper_m(char *s)
           (ie. they match for the first 128 chars) */
 
        while (*s && !(((unsigned char)s[0]) & 0x80)) {
-               *s = toupper((unsigned char)*s);
+               *s = toupper_ascii((unsigned char)*s);
                s++;
        }
 
@@ -1589,7 +1672,7 @@ int fstr_sprintf(fstring s, const char *fmt, ...)
 
 #define S_LIST_ABS 16 /* List Allocation Block Size */
 
-char **str_list_make(const char *string, const char *sep)
+static char **str_list_make_internal(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
 {
        char **list, **rlist;
        const char *str;
@@ -1599,7 +1682,11 @@ char **str_list_make(const char *string, const char *sep)
        
        if (!string || !*string)
                return NULL;
-       s = SMB_STRDUP(string);
+       if (mem_ctx) {
+               s = talloc_strdup(mem_ctx, string);
+       } else {
+               s = SMB_STRDUP(string);
+       }
        if (!s) {
                DEBUG(0,("str_list_make: Unable to allocate memory"));
                return NULL;
@@ -1613,32 +1700,64 @@ char **str_list_make(const char *string, const char *sep)
        while (next_token(&str, tok, sep, sizeof(tok))) {               
                if (num == lsize) {
                        lsize += S_LIST_ABS;
-                       rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1);
+                       if (mem_ctx) {
+                               rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, lsize +1);
+                       } else {
+                               rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1);
+                       }
                        if (!rlist) {
                                DEBUG(0,("str_list_make: Unable to allocate memory"));
                                str_list_free(&list);
-                               SAFE_FREE(s);
+                               if (mem_ctx) {
+                                       TALLOC_FREE(s);
+                               } else {
+                                       SAFE_FREE(s);
+                               }
                                return NULL;
                        } else
                                list = rlist;
                        memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
                }
+
+               if (mem_ctx) {
+                       list[num] = talloc_strdup(mem_ctx, tok);
+               } else {
+                       list[num] = SMB_STRDUP(tok);
+               }
                
-               list[num] = SMB_STRDUP(tok);
                if (!list[num]) {
                        DEBUG(0,("str_list_make: Unable to allocate memory"));
                        str_list_free(&list);
-                       SAFE_FREE(s);
+                       if (mem_ctx) {
+                               TALLOC_FREE(s);
+                       } else {
+                               SAFE_FREE(s);
+                       }
                        return NULL;
                }
        
                num++;  
        }
-       
-       SAFE_FREE(s);
+
+       if (mem_ctx) {
+               TALLOC_FREE(s);
+       } else {
+               SAFE_FREE(s);
+       }
+
        return list;
 }
 
+char **str_list_make_talloc(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
+{
+       return str_list_make_internal(mem_ctx, string, sep);
+}
+
+char **str_list_make(const char *string, const char *sep)
+{
+       return str_list_make_internal(NULL, string, sep);
+}
+
 BOOL str_list_copy(char ***dest, const char **src)
 {
        char **list, **rlist;
@@ -1700,16 +1819,35 @@ BOOL str_list_compare(char **list1, char **list2)
        return True;
 }
 
-void str_list_free(char ***list)
+static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
 {
        char **tlist;
        
        if (!list || !*list)
                return;
        tlist = *list;
-       for(; *tlist; tlist++)
-               SAFE_FREE(*tlist);
-       SAFE_FREE(*list);
+       for(; *tlist; tlist++) {
+               if (mem_ctx) {
+                       TALLOC_FREE(*tlist);
+               } else {
+                       SAFE_FREE(*tlist);
+               }
+       }
+       if (mem_ctx) {
+               TALLOC_FREE(*tlist);
+       } else {
+               SAFE_FREE(*list);
+       }
+}
+
+void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
+{
+       str_list_free_internal(mem_ctx, list);
+}
+
+void str_list_free(char ***list)
+{
+       str_list_free_internal(NULL, list);
 }
 
 /******************************************************************************
@@ -1719,6 +1857,9 @@ int str_list_count( const char **list )
 {
        int i = 0;
 
+       if ( ! list )
+               return 0;
+
        /* count the number of list members */
        
        for ( i=0; *list; i++, list++ );
@@ -2239,3 +2380,23 @@ char *sstring_sub(const char *src, char front, char back)
        temp3[len-1] = '\0';
        return temp3;
 }
+
+/********************************************************************
+ Check a string for any occurrences of a specified list of invalid
+ characters.
+********************************************************************/
+
+BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
+{
+       int i;
+
+       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] ) ) {
+                       return False;
+               }
+       }
+
+       return True;
+}
+