Changes from APPLIANCE_HEAD:
[ira/wip.git] / source3 / lib / util_str.c
index 142f0af4c8717b4bfa87ebf8773f0e6f73e6762a..e07e5ef6ada681263221cc51d1e0f64b6a6626a0 100644 (file)
@@ -302,6 +302,36 @@ BOOL strcsequal(const char *s1,const char *s2)
   return(strcmp(s1,s2)==0);
 }
 
+/***************************************************************************
+Do a case-insensitive, whitespace-ignoring string compare.
+***************************************************************************/
+int strwicmp(char *psz1, char *psz2)
+{
+       /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
+       /* appropriate value. */
+       if (psz1 == psz2)
+               return (0);
+       else if (psz1 == NULL)
+               return (-1);
+       else if (psz2 == NULL)
+               return (1);
+
+       /* sync the strings on first non-whitespace */
+       while (1)
+       {
+               while (isspace(*psz1))
+                       psz1++;
+               while (isspace(*psz2))
+                       psz2++;
+               if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
+                   || *psz2 == '\0')
+                       break;
+               psz1++;
+               psz2++;
+       }
+       return (*psz1 - *psz2);
+}
+
 
 /*******************************************************************
   convert a string to lower case
@@ -343,7 +373,7 @@ void strlower(char *s)
     else
 #endif /* KANJI_WIN95_COMPATIBILITY */
     {
-      size_t skip = skip_multibyte_char( *s );
+      size_t skip = get_character_len( *s );
       if( skip != 0 )
         s += skip;
       else
@@ -396,7 +426,7 @@ void strupper(char *s)
     else
 #endif /* KANJI_WIN95_COMPATIBILITY */
     {
-      size_t skip = skip_multibyte_char( *s );
+      size_t skip = get_character_len( *s );
       if( skip != 0 )
         s += skip;
       else
@@ -440,17 +470,29 @@ BOOL strisnormal(char *s)
 void string_replace(char *s,char oldc,char newc)
 {
   size_t skip;
-  while (*s)
-  {
-    skip = skip_multibyte_char( *s );
-    if( skip != 0 )
-      s += skip;
-    else
-    {
+
+  /*
+   * sbcs optimization.
+   */
+  if(!global_is_multibyte_codepage) {
+    while (*s) {
       if (oldc == *s)
         *s = newc;
       s++;
     }
+  } else {
+    while (*s)
+    {
+      skip = get_character_len( *s );
+      if( skip != 0 )
+        s += skip;
+      else
+      {
+        if (oldc == *s)
+          *s = newc;
+        s++;
+      }
+    }
   }
 }
 
@@ -476,10 +518,17 @@ size_t str_charnum(const char *s)
 {
   size_t len = 0;
   
-  while (*s != '\0') {
-    int skip = skip_multibyte_char(*s);
-    s += (skip ? skip : 1);
-    len++;
+  /*
+   * sbcs optimization.
+   */
+  if(!global_is_multibyte_codepage) {
+    return strlen(s);
+  } else {
+    while (*s != '\0') {
+      int skip = get_character_len(*s);
+      s += (skip ? skip : 1);
+      len++;
+    }
   }
   return len;
 }
@@ -518,7 +567,7 @@ BOOL trim_string(char *s,const char *front,const char *back)
 
   if(back_len)
   {
-    if(!is_multibyte_codepage())
+    if(!global_is_multibyte_codepage)
     {
       s_len = strlen(s);
       while ((s_len >= back_len) && 
@@ -552,11 +601,20 @@ BOOL trim_string(char *s,const char *front,const char *back)
         size_t charcount = 0;
         char *mbp = s;
 
-        while(charcount < (mb_s_len - mb_back_len))
-        {
-          size_t skip = skip_multibyte_char(*mbp);
-          mbp += (skip ? skip : 1);
-          charcount++;
+        /*
+         * sbcs optimization.
+         */
+        if(!global_is_multibyte_codepage) {
+          while(charcount < (mb_s_len - mb_back_len)) {
+            mbp += 1;
+            charcount++;
+          }
+        } else {
+          while(charcount < (mb_s_len - mb_back_len)) {
+            size_t skip = skip_multibyte_char(*mbp);
+            mbp += (skip ? skip : 1);
+            charcount++;
+          }
         }
 
         /*
@@ -615,7 +673,7 @@ BOOL strhasupper(const char *s)
     else
 #endif /* KANJI_WIN95_COMPATIBILITY */
     {
-      size_t skip = skip_multibyte_char( *s );
+      size_t skip = get_character_len( *s );
       if( skip != 0 )
         s += skip;
       else {
@@ -670,7 +728,7 @@ BOOL strhaslower(const char *s)
     else
 #endif /* KANJI_WIN95_COMPATIBILITY */
     {
-      size_t skip = skip_multibyte_char( *s );
+      size_t skip = get_character_len( *s );
       if( skip != 0 )
         s += skip;
       else {
@@ -720,7 +778,7 @@ size_t count_chars(const char *s,char c)
   {
     while (*s) 
     {
-      size_t skip = skip_multibyte_char( *s );
+      size_t skip = get_character_len( *s );
       if( skip != 0 )
         s += skip;
       else {
@@ -733,12 +791,65 @@ size_t count_chars(const char *s,char c)
   return(count);
 }
 
+/*******************************************************************
+Return True if a string consists only of one particular character.
+********************************************************************/
+
+BOOL str_is_all(const char *s,char c)
+{
+  if(s == NULL)
+    return False;
+  if(!*s)
+    return False;
 
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+  /*
+   * For completeness we should put in equivalent code for code pages
+   * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+   * doubt anyone wants Samba to behave differently from Win95 and WinNT
+   * here. They both treat full width ascii characters as case senstive
+   * filenames (ie. they don't do the work we do here).
+   * JRA.
+   */
+
+  if(lp_client_code_page() == KANJI_CODEPAGE)
+  {
+    /* Win95 treats full width ascii characters as case sensitive. */
+    while (*s)
+    {
+      if (is_shift_jis (*s))
+        s += 2;
+      else
+      {
+        if (*s != c)
+          return False;
+        s++;
+      }
+    }
+  }
+  else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+  {
+    while (*s)
+    {
+      size_t skip = get_character_len( *s );
+      if( skip != 0 )
+        s += skip;
+      else {
+        if (*s != c)
+          return False;
+        s++;
+      }
+    }
+  }
+  return True;
+}
 
 /*******************************************************************
 safe string copy into a known length string. maxlength does not
 include the terminating zero.
 ********************************************************************/
+
 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
 {
     size_t len;
@@ -757,7 +868,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength)
 
     if (len > maxlength) {
            DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
-                    len-maxlength, src));
+                    (int)(len-maxlength), src));
            len = maxlength;
     }
       
@@ -770,6 +881,7 @@ char *safe_strcpy(char *dest,const char *src, size_t maxlength)
 safe string cat into a string. maxlength does not
 include the terminating zero.
 ********************************************************************/
+
 char *safe_strcat(char *dest, const char *src, size_t maxlength)
 {
     size_t src_len, dest_len;
@@ -788,7 +900,7 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength)
 
     if (src_len + dest_len > maxlength) {
            DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
-                    src_len + dest_len - maxlength, src));
+                    (int)(src_len + dest_len - maxlength), src));
            src_len = maxlength - dest_len;
     }
       
@@ -797,28 +909,48 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength)
     return dest;
 }
 
-/****************************************************************************
-this is a safer strcpy(), meant to prevent core dumps when nasty things happen
-****************************************************************************/
-char *StrCpy(char *dest,const char *src)
+/*******************************************************************
+ Paranoid strcpy into a buffer of given length (includes terminating
+ zero. Strips out all but 'a-Z0-9' and replaces with '_'. Deliberately
+ does *NOT* check for multibyte characters. Don't change it !
+********************************************************************/
+
+char *alpha_strcpy(char *dest, const char *src, size_t maxlength)
 {
-  char *d = dest;
+       size_t len, i;
 
-  /* I don't want to get lazy with these ... */
-  SMB_ASSERT(dest && src);
+       if (!dest) {
+               DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
+               return NULL;
+       }
 
-  if (!dest) return(NULL);
-  if (!src) {
-    *dest = 0;
-    return(dest);
-  }
-  while ((*d++ = *src++)) ;
-  return(dest);
+       if (!src) {
+               *dest = 0;
+               return dest;
+       }  
+
+       len = strlen(src);
+       if (len >= maxlength)
+               len = maxlength - 1;
+
+       for(i = 0; i < len; i++) {
+               int val = (src[i] & 0xff);
+               if(isupper(val) ||islower(val) || isdigit(val))
+                       dest[i] = src[i];
+               else
+                       dest[i] = '_';
+       }
+
+       dest[i] = '\0';
+
+       return dest;
 }
 
 /****************************************************************************
-like strncpy but always null terminates. Make sure there is room!
+ Like strncpy but always null terminates. Make sure there is room!
+ The variable n should always be one less than the available size.
 ****************************************************************************/
+
 char *StrnCpy(char *dest,const char *src,size_t n)
 {
   char *d = dest;
@@ -832,7 +964,6 @@ char *StrnCpy(char *dest,const char *src,size_t n)
   return(dest);
 }
 
-
 /****************************************************************************
 like strncpy but copies up to the character marker.  always null terminates.
 returns a pointer to the character marker in the source string (src).
@@ -935,7 +1066,7 @@ static char *null_string = NULL;
 /****************************************************************************
 set a string value, allocing the space for the string
 ****************************************************************************/
-BOOL string_init(char **dest,const char *src)
+static BOOL string_init(char **dest,const char *src)
 {
   size_t l;
   if (!src)     
@@ -998,29 +1129,42 @@ enough room!
 This routine looks for pattern in s and replaces it with 
 insert. It may do multiple replacements.
 
-any of " ; ' or ` in the insert string are replaced with _
+any of " ; ' $ or ` in the insert string are replaced with _
+if len==0 then no length check is performed
 ****************************************************************************/
-void string_sub(char *s,const char *pattern,const char *insert)
+void string_sub(char *s,const char *pattern,const char *insert, size_t len)
 {
        char *p;
-       size_t ls,lp,li, i;
+       ssize_t ls,lp,li, i;
 
        if (!insert || !pattern || !s) return;
 
-       ls = strlen(s);
-       lp = strlen(pattern);
-       li = strlen(insert);
+       ls = (ssize_t)strlen(s);
+       lp = (ssize_t)strlen(pattern);
+       li = (ssize_t)strlen(insert);
 
        if (!*pattern) return;
        
        while (lp <= ls && (p = strstr(s,pattern))) {
-               memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
+               if (len && (ls + (li-lp) >= len)) {
+                       DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
+                                (int)(ls + (li-lp) - len),
+                                pattern, (int)len));
+                       break;
+               }
+               if (li != lp) {
+                       memmove(p+li,p+lp,strlen(p+lp)+1);
+               }
                for (i=0;i<li;i++) {
                        switch (insert[i]) {
                        case '`':
                        case '"':
                        case '\'':
                        case ';':
+                       case '$':
+                       case '%':
+                       case '\r':
+                       case '\n':
                                p[i] = '_';
                                break;
                        default:
@@ -1032,26 +1176,44 @@ void string_sub(char *s,const char *pattern,const char *insert)
        }
 }
 
+void fstring_sub(char *s,const char *pattern,const char *insert)
+{
+       string_sub(s, pattern, insert, sizeof(fstring));
+}
+
+void pstring_sub(char *s,const char *pattern,const char *insert)
+{
+       string_sub(s, pattern, insert, sizeof(pstring));
+}
 
 /****************************************************************************
 similar to string_sub() but allows for any character to be substituted. 
 Use with caution!
+if len==0 then no length check is performed
 ****************************************************************************/
-void all_string_sub(char *s,const char *pattern,const char *insert)
+void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
 {
        char *p;
-       size_t ls,lp,li;
+       ssize_t ls,lp,li;
 
        if (!insert || !pattern || !s) return;
 
-       ls = strlen(s);
-       lp = strlen(pattern);
-       li = strlen(insert);
+       ls = (ssize_t)strlen(s);
+       lp = (ssize_t)strlen(pattern);
+       li = (ssize_t)strlen(insert);
 
        if (!*pattern) return;
        
        while (lp <= ls && (p = strstr(s,pattern))) {
-               memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
+               if (len && (ls + (li-lp) >= len)) {
+                       DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
+                                (int)(ls + (li-lp) - len),
+                                pattern, (int)len));
+                       break;
+               }
+               if (li != lp) {
+                       memmove(p+li,p+lp,strlen(p+lp)+1);
+               }
                memcpy(p, insert, li);
                s = p + li;
                ls += (li-lp);
@@ -1090,72 +1252,49 @@ void split_at_last_component(char *path, char *front, char sep, char *back)
        }
 }
 
-/****************************************************************************
-convert a bit field to a string.  if you want multiple bits to be detected
-set them first, e.g SV_TYPE_ALL to be "All" or "Full Control" for ACB_INFOs.
-
-strings are expected to contain their own separators, although the code
-below only assumes that separators are spaces.
 
+/****************************************************************************
+write an octal as a string
 ****************************************************************************/
-char *bit_field_to_str(uint32 type, struct field_info *bs)
+char *octal_string(int i)
 {
-       static fstring typestr;
-       int i = 0;
-
-       typestr[0] = 0;
-
-       if (type == 0 || bs == NULL)
-       {
-               return NULL;
-       }
-
-       while (bs[i].str != NULL && type != 0)
-       {
-               if (IS_BITS_SET_ALL(bs[i].bits, type))
-               {
-                       fstrcat(typestr, bs[i].str);
-                       type &= ~bs[i].bits;
-               }
-               i++;
-       }
-       
-       i = strlen(typestr)-1;
-       if (i > 0 && typestr[i] == ' ')
-       {
-               typestr[i] = 0;
+       static char ret[64];
+       if (i == -1) {
+               return "-1";
        }
-
-       return typestr;
+       slprintf(ret, sizeof(ret), "0%o", i);
+       return ret;
 }
 
+
 /****************************************************************************
-convert an enumeration to a string.  first item is the default.
+truncate a string at a specified length
 ****************************************************************************/
-char *enum_field_to_str(uint32 type, struct field_info *bs, BOOL first_default)
+char *string_truncate(char *s, int length)
 {
-       int i = 0;
-
-       if (bs == NULL)
-       {
-               return NULL;
-       }
-
-       while (bs[i].str != NULL && type != 0)
-       {
-               if (bs[i].bits == type)
-               {
-                       return bs[i].str;
-               }
-               i++;
+       if (s && strlen(s) > length) {
+               s[length] = 0;
        }
+       return s;
+}
 
-       /* oops - none found */
+/* Parse a string of the form DOMAIN/user into a domain and a user */
 
-       if (first_default)
-       {
-               return bs[0].str;
+void parse_domain_user(char *domuser, fstring domain, fstring user)
+{
+       char *p;
+       char *sep = lp_winbind_separator();
+       if (!sep) sep = "\\";
+       p = strchr(domuser,*sep);
+       if (!p) p = strchr(domuser,'\\');
+       if (!p) {
+               fstrcpy(domain,"");
+               fstrcpy(user, domuser);
+               return;
        }
-
-       return NULL;
+       
+       fstrcpy(user, p+1);
+       fstrcpy(domain, domuser);
+       domain[PTR_DIFF(p, domuser)] = 0;
+       strupper(domain);
 }