first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[kai/samba.git] / source3 / lib / util_str.c
index dad0e854770f7d52298cbd353d187bf877660b16..58718f395a3e97d4f4f68be0f5261b34ad7cdf1a 100644 (file)
@@ -458,11 +458,11 @@ void string_replace(char *s,char oldc,char newc)
 /*******************************************************************
 skip past some strings in a buffer
 ********************************************************************/
-char *skip_string(const char *buf,size_t n)
+char *skip_string(char *buf,size_t n)
 {
   while (n--)
     buf += strlen(buf) + 1;
-  return((char *)buf);
+  return(buf);
 }
 
 /*******************************************************************
@@ -733,12 +733,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 = skip_multibyte_char( *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 +810,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 +823,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 +842,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 +851,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 +906,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).
@@ -882,16 +955,16 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex)
                        continue;
                }
 
-               while (!(p1 = strchr(hexchars, toupper(strhex[i]))))
+               if (!(p1 = strchr(hexchars, toupper(strhex[i]))))
                {
-                       continue;
+                       break;
                }
 
                i++; /* next hex digit */
 
-               while (!(p2 = strchr(hexchars, toupper(strhex[i]))))
+               if (!(p2 = strchr(hexchars, toupper(strhex[i]))))
                {
-                       continue;
+                       break;
                }
 
                /* get the two nybbles */
@@ -998,28 +1071,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:
@@ -1031,26 +1118,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, i;
+       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);
@@ -1088,3 +1193,29 @@ void split_at_last_component(char *path, char *front, char sep, char *back)
                }
        }
 }
+
+
+/****************************************************************************
+write an octal as a string
+****************************************************************************/
+char *octal_string(int i)
+{
+       static char ret[64];
+       if (i == -1) {
+               return "-1";
+       }
+       slprintf(ret, sizeof(ret), "0%o", i);
+       return ret;
+}
+
+
+/****************************************************************************
+truncate a string at a specified length
+****************************************************************************/
+char *string_truncate(char *s, int length)
+{
+       if (s && strlen(s) > length) {
+               s[length] = 0;
+       }
+       return s;
+}