r25014: Use talloc for allocating values as well.
[kai/samba.git] / source4 / lib / util / util_str.c
index 11a95731debbcd527a0034aeeb342e64ef656c01..4bec469f872191ad54ccbdbe935e783ab46d31af 100644 (file)
@@ -9,7 +9,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "system/iconv.h"
-#include "smb.h"
-#include "pstring.h"
-#include "lib/ldb/include/ldb.h"
+#include "libcli/raw/smb.h"
+#include "system/locale.h"
 
 /**
  * @file
  * @brief String utilities.
  **/
 
-/**
- * Get the next token from a string, return False if none found.
- * Handles double-quotes.
- * 
- * Based on a routine by GJC@VILLAGE.COM. 
- * Extensively modified by Andrew.Tridgell@anu.edu.au
- **/
-BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
-{
-       const char *s;
-       BOOL quoted;
-       size_t len=1;
-
-       if (!ptr)
-               return(False);
-
-       s = *ptr;
-
-       /* default to simple separators */
-       if (!sep)
-               sep = " \t\n\r";
-
-       /* find the first non sep char */
-       while (*s && strchr_m(sep,*s))
-               s++;
-       
-       /* nothing left? */
-       if (! *s)
-               return(False);
-       
-       /* copy over the token */
-       for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
-               if (*s == '\"') {
-                       quoted = !quoted;
-               } else {
-                       len++;
-                       *buff++ = *s;
-               }
-       }
-       
-       *ptr = (*s) ? s+1 : s;  
-       *buff = 0;
-       
-       return(True);
-}
-
-/**
- Case insensitive string compararison
-**/
-int strcasecmp_m(const char *s1, const char *s2)
-{
-       codepoint_t c1=0, c2=0;
-       size_t size1, size2;
-
-       while (*s1 && *s2) {
-               c1 = next_codepoint(s1, &size1);
-               c2 = next_codepoint(s2, &size2);
-
-               s1 += size1;
-               s2 += size2;
-
-               if (c1 == c2) {
-                       continue;
-               }
-
-               if (c1 == INVALID_CODEPOINT ||
-                   c2 == INVALID_CODEPOINT) {
-                       /* what else can we do?? */
-                       return c1 - c2;
-               }
-
-               if (toupper_w(c1) != toupper_w(c2)) {
-                       return c1 - c2;
-               }
-       }
-
-       return *s1 - *s2;
-}
-
-/**
- * Compare 2 strings.
- *
- * @note The comparison is case-insensitive.
- **/
-BOOL strequal(const char *s1, const char *s2)
-{
-       if (s1 == s2)
-               return(True);
-       if (!s1 || !s2)
-               return(False);
-  
-       return strcasecmp_m(s1,s2) == 0;
-}
-
-/**
- Compare 2 strings (case sensitive).
-**/
-BOOL strcsequal(const char *s1,const char *s2)
-{
-       if (s1 == s2)
-               return(True);
-       if (!s1 || !s2)
-               return(False);
-       
-       return strcmp(s1,s2) == 0;
-}
-
-
-/**
-Do a case-insensitive, whitespace-ignoring string compare.
-**/
-int strwicmp(const char *psz1, const 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((int)*psz1))
-                       psz1++;
-               while (isspace((int)*psz2))
-                       psz2++;
-               if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2) 
-                   || *psz1 == '\0'
-                   || *psz2 == '\0')
-                       break;
-               psz1++;
-               psz2++;
-       }
-       return (*psz1 - *psz2);
-}
-
-/**
- String replace.
- NOTE: oldc and newc must be 7 bit characters
-**/
-void string_replace(char *s, char oldc, char newc)
-{
-       while (*s) {
-               size_t size;
-               codepoint_t c = next_codepoint(s, &size);
-               if (c == oldc) {
-                       *s = newc;
-               }
-               s += size;
-       }
-}
 
 /**
  Trim the specified elements off the front and back of a string.
 **/
-BOOL trim_string(char *s,const char *front,const char *back)
+_PUBLIC_ bool trim_string(char *s, const char *front, const char *back)
 {
-       BOOL ret = False;
+       bool ret = false;
        size_t front_len;
        size_t back_len;
        size_t len;
 
        /* Ignore null or empty strings. */
        if (!s || (s[0] == '\0'))
-               return False;
+               return false;
 
        front_len       = front? strlen(front) : 0;
        back_len        = back? strlen(back) : 0;
@@ -212,7 +56,7 @@ BOOL trim_string(char *s,const char *front,const char *back)
                         * easily overlap. Found by valgrind. JRA. */
                        memmove(s, s+front_len, (len-front_len)+1);
                        len -= front_len;
-                       ret=True;
+                       ret=true;
                }
        }
        
@@ -220,7 +64,7 @@ BOOL trim_string(char *s,const char *front,const char *back)
                while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
                        s[len-back_len]='\0';
                        len -= back_len;
-                       ret=True;
+                       ret=true;
                }
        }
        return ret;
@@ -229,25 +73,25 @@ BOOL trim_string(char *s,const char *front,const char *back)
 /**
  Find the number of 'c' chars in a string
 **/
-size_t count_chars(const char *s, char c)
+_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c)
 {
        size_t count = 0;
 
        while (*s) {
-               size_t size;
-               codepoint_t c2 = next_codepoint(s, &size);
-               if (c2 == c) count++;
-               s += size;
+               if (*s == c) count++;
+               s ++;
        }
 
        return count;
 }
 
+
+
 /**
  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)
+_PUBLIC_ char *safe_strcpy(char *dest,const char *src, size_t maxlength)
 {
        size_t len;
 
@@ -289,7 +133,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)
+_PUBLIC_ char *safe_strcat(char *dest, const char *src, size_t maxlength)
 {
        size_t src_len, dest_len;
 
@@ -324,73 +168,6 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength)
        return dest;
 }
 
-/**
- 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 !
-**/
-
-char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
-{
-       size_t len, i;
-
-       if (maxlength == 0) {
-               /* can't fit any bytes at all! */
-               return NULL;
-       }
-
-       if (!dest) {
-               DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
-               return NULL;
-       }
-
-       if (!src) {
-               *dest = 0;
-               return dest;
-       }  
-
-       len = strlen(src);
-       if (len >= maxlength)
-               len = maxlength - 1;
-
-       if (!other_safe_chars)
-               other_safe_chars = "";
-
-       for(i = 0; i < len; i++) {
-               int val = (src[i] & 0xff);
-               if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
-                       dest[i] = src[i];
-               else
-                       dest[i] = '_';
-       }
-
-       dest[i] = '\0';
-
-       return dest;
-}
-
-/**
- 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;
-       if (!dest)
-               return(NULL);
-       if (!src) {
-               *dest = 0;
-               return(dest);
-       }
-       while (n-- && (*d++ = *src++))
-               ;
-       *d = 0;
-       return(dest);
-}
-
-
 /**
  Routine to get hex characters and turn them into a 16 byte array.
  the array can be variable length, and any non-hex-numeric
@@ -401,7 +178,7 @@ char *StrnCpy(char *dest,const char *src,size_t n)
 
 
 **/
-size_t strhex_to_str(char *p, size_t len, const char *strhex)
+_PUBLIC_ size_t strhex_to_str(char *p, size_t len, const char *strhex)
 {
        size_t i;
        size_t num_chars = 0;
@@ -415,12 +192,12 @@ size_t strhex_to_str(char *p, size_t len, const char *strhex)
                        continue;
                }
 
-               if (!(p1 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
+               if (!(p1 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
                        break;
 
                i++; /* next hex digit */
 
-               if (!(p2 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
+               if (!(p2 = strchr(hexchars, toupper((unsigned char)strhex[i]))))
                        break;
 
                /* get the two nybbles */
@@ -436,7 +213,10 @@ 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) 
+/** 
+ * Parse a hex string and return a data blob. 
+ */
+_PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(const char *strhex) 
 {
        DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1);
 
@@ -451,12 +231,12 @@ 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)
+_PUBLIC_ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
 {
        int i;
        char *hex_buffer;
 
-       *out_hex_buffer = smb_xmalloc((len*2)+1);
+       *out_hex_buffer = malloc_array_p(char, (len*2)+1);
        hex_buffer = *out_hex_buffer;
 
        for (i = 0; i < len; i++)
@@ -464,59 +244,39 @@ void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
 }
 
 /**
- Check if a string is part of a list.
-**/
-BOOL in_list(const char *s, const char *list, BOOL casesensitive)
+ * talloc version of hex_encode()
+ */
+_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
 {
-       pstring tok;
-       const char *p=list;
+       int i;
+       char *hex_buffer;
 
-       if (!list)
-               return(False);
+       hex_buffer = talloc_array(mem_ctx, char, (len*2)+1);
 
-       while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
-               if (casesensitive) {
-                       if (strcmp(tok,s) == 0)
-                               return(True);
-               } else {
-                       if (strcasecmp_m(tok,s) == 0)
-                               return(True);
-               }
-       }
-       return(False);
+       for (i = 0; i < len; i++)
+               slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
+
+       return hex_buffer;
 }
 
 /**
- Set a string value, allocing the space for the string
+ Set a string value, deallocating any existing space, and allocing the space
+ for the string
 **/
-static BOOL string_init(char **dest,const char *src)
+_PUBLIC_ bool string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
 {
-       if (!src) src = "";
+       talloc_free(*dest);
+
+       if (src == NULL) 
+               src = "";
 
-       (*dest) = strdup(src);
+       *dest = talloc_strdup(mem_ctx, src);
        if ((*dest) == NULL) {
                DEBUG(0,("Out of memory in string_init\n"));
-               return False;
+               return false;
        }
-       return True;
-}
-
-/**
- Free a string value.
-**/
-void string_free(char **s)
-{
-       if (s) SAFE_FREE(*s);
-}
 
-/**
- Set a string value, deallocating any existing space, and allocing the space
- for the string
-**/
-BOOL string_set(char **dest, const char *src)
-{
-       string_free(dest);
-       return string_init(dest,src);
+       return true;
 }
 
 /**
@@ -531,7 +291,7 @@ BOOL string_set(char **dest, const char *src)
  use of len==0 which was for no length checks to be done.
 **/
 
-void string_sub(char *s,const char *pattern, const char *insert, size_t len)
+_PUBLIC_ void string_sub(char *s, const char *pattern, const char *insert, size_t len)
 {
        char *p;
        ssize_t ls,lp,li, i;
@@ -585,7 +345,7 @@ void string_sub(char *s,const char *pattern, const char *insert, size_t len)
  use of len==0 which was for no length checks to be done.
 **/
 
-void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
+_PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
 {
        char *p;
        ssize_t ls,lp,li;
@@ -620,306 +380,21 @@ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
 }
 
 
-/**
- Strchr and strrchr_m are a bit complex on general multi-byte strings. 
-**/
-char *strchr_m(const char *s, char c)
-{
-       /* characters below 0x3F are guaranteed to not appear in
-          non-initial position in multi-byte charsets */
-       if ((c & 0xC0) == 0) {
-               return strchr(s, c);
-       }
-
-       while (*s) {
-               size_t size;
-               codepoint_t c2 = next_codepoint(s, &size);
-               if (c2 == c) {
-                       return discard_const(s);
-               }
-               s += size;
-       }
-
-       return NULL;
-}
-
-char *strrchr_m(const char *s, char c)
-{
-       char *ret = NULL;
-
-       /* characters below 0x3F are guaranteed to not appear in
-          non-initial position in multi-byte charsets */
-       if ((c & 0xC0) == 0) {
-               return strrchr(s, c);
-       }
-
-       while (*s) {
-               size_t size;
-               codepoint_t c2 = next_codepoint(s, &size);
-               if (c2 == c) {
-                       ret = discard_const(s);
-               }
-               s += size;
-       }
-
-       return ret;
-}
-
-/*
-  return True if any (multi-byte) character is lower case
-*/
-BOOL strhaslower(const char *string)
-{
-       while (*string) {
-               size_t c_size;
-               codepoint_t s;
-               codepoint_t t;
-
-               s = next_codepoint(string, &c_size);
-               string += c_size;
-
-               t = toupper_w(s);
-
-               if (s != t) {
-                       return True; /* that means it has lower case chars */
-               }
-       }
-
-       return False;
-} 
-
-/*
-  return True if any (multi-byte) character is upper case
-*/
-BOOL strhasupper(const char *string)
-{
-       while (*string) {
-               size_t c_size;
-               codepoint_t s;
-               codepoint_t t;
-
-               s = next_codepoint(string, &c_size);
-               string += c_size;
-
-               t = tolower_w(s);
-
-               if (s != t) {
-                       return True; /* that means it has upper case chars */
-               }
-       }
-
-       return False;
-} 
-
-/**
- Convert a string to lower case, allocated with talloc
-**/
-char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
-{
-       size_t size=0;
-       char *dest;
-
-       /* this takes advantage of the fact that upper/lower can't
-          change the length of a character by more than 1 byte */
-       dest = talloc_size(ctx, 2*(strlen(src))+1);
-       if (dest == NULL) {
-               return NULL;
-       }
-
-       while (*src) {
-               size_t c_size;
-               codepoint_t c = next_codepoint(src, &c_size);
-               src += c_size;
-
-               c = tolower_w(c);
-
-               c_size = push_codepoint(dest+size, c);
-               if (c_size == -1) {
-                       talloc_free(dest);
-                       return NULL;
-               }
-               size += c_size;
-       }
-
-       dest[size] = 0;
-
-       return dest;
-}
-
-/**
- Convert a string to UPPER case, allocated with talloc
-**/
-char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
-{
-       size_t size=0;
-       char *dest;
-       
-       if (!src) {
-               return NULL;
-       }
-
-       /* this takes advantage of the fact that upper/lower can't
-          change the length of a character by more than 1 byte */
-       dest = talloc_size(ctx, 2*(strlen(src))+1);
-       if (dest == NULL) {
-               return NULL;
-       }
-
-       while (*src) {
-               size_t c_size;
-               codepoint_t c = next_codepoint(src, &c_size);
-               src += c_size;
-
-               c = toupper_w(c);
-
-               c_size = push_codepoint(dest+size, c);
-               if (c_size == -1) {
-                       talloc_free(dest);
-                       return NULL;
-               }
-               size += c_size;
-       }
-
-       dest[size] = 0;
-
-       return dest;
-}
-
-/**
- Convert a string to lower case.
-**/
-void strlower_m(char *s)
-{
-       char *d;
-
-       /* this is quite a common operation, so we want it to be
-          fast. We optimise for the ascii case, knowing that all our
-          supported multi-byte character sets are ascii-compatible
-          (ie. they match for the first 128 chars) */
-       while (*s && !(((uint8_t)*s) & 0x80)) {
-               *s = tolower((uint8_t)*s);
-               s++;
-       }
-
-       if (!*s)
-               return;
-
-       d = s;
-
-       while (*s) {
-               size_t c_size, c_size2;
-               codepoint_t c = next_codepoint(s, &c_size);
-               c_size2 = push_codepoint(d, tolower_w(c));
-               if (c_size2 > c_size) {
-                       DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
-                                c, tolower_w(c), (int)c_size, (int)c_size2));
-                       smb_panic("codepoint expansion in strlower_m\n");
-               }
-               s += c_size;
-               d += c_size2;
-       }
-       *d = 0;
-}
-
-/**
- Convert a string to UPPER case.
-**/
-void strupper_m(char *s)
-{
-       char *d;
-
-       /* this is quite a common operation, so we want it to be
-          fast. We optimise for the ascii case, knowing that all our
-          supported multi-byte character sets are ascii-compatible
-          (ie. they match for the first 128 chars) */
-       while (*s && !(((uint8_t)*s) & 0x80)) {
-               *s = toupper((uint8_t)*s);
-               s++;
-       }
-
-       if (!*s)
-               return;
-
-       d = s;
-
-       while (*s) {
-               size_t c_size, c_size2;
-               codepoint_t c = next_codepoint(s, &c_size);
-               c_size2 = push_codepoint(d, toupper_w(c));
-               if (c_size2 > c_size) {
-                       DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
-                                c, toupper_w(c), (int)c_size, (int)c_size2));
-                       smb_panic("codepoint expansion in strupper_m\n");
-               }
-               s += c_size;
-               d += c_size2;
-       }
-       *d = 0;
-}
-
-/**
- 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)
-{
-       size_t count = 0;
-
-       if (!s) {
-               return 0;
-       }
-
-       while (*s && !(((uint8_t)*s) & 0x80)) {
-               s++;
-               count++;
-       }
-
-       if (!*s) {
-               return count;
-       }
-
-       while (*s) {
-               size_t c_size;
-               codepoint_t c = next_codepoint(s, &c_size);
-               if (c < 0x10000) {
-                       count += 1;
-               } else {
-                       count += 2;
-               }
-               s += c_size;
-       }
-
-       return count;
-}
-
-/**
-   Work out the number of multibyte chars in a string, including the NULL
-   terminator.
-**/
-size_t strlen_m_term(const char *s)
-{
-       if (!s) {
-               return 0;
-       }
-
-       return strlen_m(s) + 1;
-}
 
 /**
  Unescape a URL encoded string, in place.
 **/
 
-void rfc1738_unescape(char *buf)
+_PUBLIC_ void rfc1738_unescape(char *buf)
 {
        char *p=buf;
 
-       while ((p=strchr_m(p,'+')))
+       while ((p=strchr(p,'+')))
                *p = ' ';
 
        p = buf;
 
-       while (p && *p && (p=strchr_m(p,'%'))) {
+       while (p && *p && (p=strchr(p,'%'))) {
                int c1 = p[1];
                int c2 = p[2];
 
@@ -946,32 +421,6 @@ void rfc1738_unescape(char *buf)
        }
 }
 
-/**
- * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
- **/
-DATA_BLOB base64_decode_data_blob(TALLOC_CTX *mem_ctx, const char *s)
-{
-       DATA_BLOB ret = data_blob_talloc(mem_ctx, s, strlen(s)+1);
-       ret.length = ldb_base64_decode((char *)ret.data);
-       return ret;
-}
-
-/**
- * Decode a base64 string in-place - wrapper for the above
- **/
-void base64_decode_inplace(char *s)
-{
-       ldb_base64_decode(s);
-}
-
-/**
- * Encode a base64 string into a talloc()ed string caller to free.
- **/
-char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
-{
-       return ldb_base64_encode(mem_ctx, (const char *)data.data, data.length);
-}
-
 #ifdef VALGRIND
 size_t valgrind_strlen(const char *s)
 {
@@ -987,14 +436,14 @@ size_t valgrind_strlen(const char *s)
   format a string into length-prefixed dotted domain format, as used in NBT
   and in some ADS structures
 **/
-const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s)
+_PUBLIC_ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s)
 {
        char *ret;
        int i;
        if (!s || !*s) {
                return talloc_strdup(mem_ctx, "");
        }
-       ret = talloc_size(mem_ctx, strlen(s)+2);
+       ret = talloc_array(mem_ctx, char, strlen(s)+2);
        if (!ret) {
                return ret;
        }
@@ -1016,7 +465,13 @@ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s)
        return ret;
 }
 
-BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
+/**
+ * Add a string to an array of strings.
+ *
+ * num should be a pointer to an integer that holds the current 
+ * number of elements in strings. It will be updated by this function.
+ */
+_PUBLIC_ bool add_string_to_array(TALLOC_CTX *mem_ctx,
                         const char *str, const char ***strings, int *num)
 {
        char *dup_str = talloc_strdup(mem_ctx, str);
@@ -1026,12 +481,12 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
                                    const char *, ((*num)+1));
 
        if ((*strings == NULL) || (dup_str == NULL))
-               return False;
+               return false;
 
        (*strings)[*num] = dup_str;
        *num += 1;
 
-       return True;
+       return true;
 }
 
 
@@ -1039,7 +494,7 @@ BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
 /**
   varient of strcmp() that handles NULL ptrs
 **/
-int strcmp_safe(const char *s1, const char *s2)
+_PUBLIC_ int strcmp_safe(const char *s1, const char *s2)
 {
        if (s1 == s2) {
                return 0;
@@ -1056,7 +511,7 @@ return the number of bytes occupied by a buffer in ASCII format
 the result includes the null termination
 limited by 'n' bytes
 **/
-size_t ascii_len_n(const char *src, size_t n)
+_PUBLIC_ size_t ascii_len_n(const char *src, size_t n)
 {
        size_t len;
 
@@ -1072,7 +527,7 @@ size_t ascii_len_n(const char *src, size_t n)
 /**
  Return a string representing a CIFS attribute for a file.
 **/
-char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib)
+_PUBLIC_ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib)
 {
        int i, len;
        const struct {
@@ -1097,7 +552,7 @@ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib)
        };
        char *ret;
 
-       ret = talloc_size(mem_ctx, ARRAY_SIZE(attr_strs)+1);
+       ret = talloc_array(mem_ctx, char, ARRAY_SIZE(attr_strs)+1);
        if (!ret) {
                return NULL;
        }
@@ -1115,35 +570,42 @@ char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib)
 
 /**
  Set a boolean variable from the text value stored in the passed string.
- Returns True in success, False if the passed string does not correctly 
+ Returns true in success, false if the passed string does not correctly 
  represent a boolean.
 **/
 
-BOOL set_boolean(const char *boolean_string, BOOL *boolean)
+_PUBLIC_ bool set_boolean(const char *boolean_string, bool *boolean)
 {
        if (strwicmp(boolean_string, "yes") == 0 ||
            strwicmp(boolean_string, "true") == 0 ||
            strwicmp(boolean_string, "on") == 0 ||
            strwicmp(boolean_string, "1") == 0) {
-               *boolean = True;
-               return True;
+               *boolean = true;
+               return true;
        } else if (strwicmp(boolean_string, "no") == 0 ||
                   strwicmp(boolean_string, "false") == 0 ||
                   strwicmp(boolean_string, "off") == 0 ||
                   strwicmp(boolean_string, "0") == 0) {
-               *boolean = False;
-               return True;
+               *boolean = false;
+               return true;
        }
-       return False;
+       return false;
 }
 
-BOOL conv_str_bool(const char * str, BOOL * val)
+/**
+ * Parse a string containing a boolean value.
+ *
+ * val will be set to the read value.
+ *
+ * @retval true if a boolean value was parsed, false otherwise.
+ */
+_PUBLIC_ bool conv_str_bool(const char * str, bool * val)
 {
        char *  end = NULL;
        long    lval;
 
        if (str == NULL || *str == '\0') {
-               return False;
+               return false;
        }
 
        lval = strtol(str, &end, 10 /* base */);
@@ -1151,25 +613,25 @@ BOOL conv_str_bool(const char * str, BOOL * val)
                return set_boolean(str, val);
        }
 
-       *val = (lval) ? True : False;
-       return True;
+       *val = (lval) ? true : false;
+       return true;
 }
 
 /**
  * Convert a size specification like 16K into an integral number of bytes. 
  **/
-BOOL conv_str_size(const char * str, uint64_t * val)
+_PUBLIC_ bool conv_str_size(const char * str, uint64_t * val)
 {
        char *              end = NULL;
        unsigned long long  lval;
 
        if (str == NULL || *str == '\0') {
-               return False;
+               return false;
        }
 
        lval = strtoull(str, &end, 10 /* base */);
        if (end == NULL || end == str) {
-               return False;
+               return false;
        }
 
        if (*end) {
@@ -1184,28 +646,129 @@ BOOL conv_str_size(const char * str, uint64_t * val)
                } else if (strwicmp(end, "P") == 0) {
                        lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL);
                } else {
-                       return False;
+                       return false;
                }
        }
 
        *val = (uint64_t)lval;
-       return True;
+       return true;
 }
 
-BOOL conv_str_u64(const char * str, uint64_t * val)
+/**
+ * Parse a uint64_t value from a string
+ *
+ * val will be set to the value read.
+ *
+ * @retval true if parsing was successful, false otherwise
+ */
+_PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val)
 {
        char *              end = NULL;
        unsigned long long  lval;
 
        if (str == NULL || *str == '\0') {
-               return False;
+               return false;
        }
 
        lval = strtoull(str, &end, 10 /* base */);
        if (end == NULL || *end != '\0' || end == str) {
-               return False;
+               return false;
        }
 
        *val = (uint64_t)lval;
-       return True;
+       return true;
+}
+
+/**
+return the number of bytes occupied by a buffer in CH_UTF16 format
+the result includes the null termination
+**/
+_PUBLIC_ size_t utf16_len(const void *buf)
+{
+       size_t len;
+
+       for (len = 0; SVAL(buf,len); len += 2) ;
+
+       return len + 2;
+}
+
+/**
+return the number of bytes occupied by a buffer in CH_UTF16 format
+the result includes the null termination
+limited by 'n' bytes
+**/
+_PUBLIC_ size_t utf16_len_n(const void *src, size_t n)
+{
+       size_t len;
+
+       for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
+
+       if (len+2 <= n) {
+               len += 2;
+       }
+
+       return len;
+}
+
+_PUBLIC_ size_t ucs2_align(const void *base_ptr, const void *p, int flags)
+{
+       if (flags & (STR_NOALIGN|STR_ASCII))
+               return 0;
+       return PTR_DIFF(p, base_ptr) & 1;
+}
+
+/**
+Do a case-insensitive, whitespace-ignoring string compare.
+**/
+_PUBLIC_ int strwicmp(const char *psz1, const 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((int)*psz1))
+                       psz1++;
+               while (isspace((int)*psz2))
+                       psz2++;
+               if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2) 
+                   || *psz1 == '\0'
+                   || *psz2 == '\0')
+                       break;
+               psz1++;
+               psz2++;
+       }
+       return (*psz1 - *psz2);
+}
+
+/**
+ String replace.
+**/
+_PUBLIC_ void string_replace(char *s, char oldc, char newc)
+{
+       while (*s) {
+               if (*s == oldc) *s = newc;
+               s++;
+       }
+}
+
+/**
+ * Compare 2 strings.
+ *
+ * @note The comparison is case-insensitive.
+ **/
+_PUBLIC_ bool strequal(const char *s1, const char *s2)
+{
+       if (s1 == s2)
+               return true;
+       if (!s1 || !s2)
+               return false;
+  
+       return strcasecmp(s1,s2) == 0;
 }