split string and unicode string routines into these files.
authorLuke Leighton <lkcl@samba.org>
Thu, 5 Nov 1998 16:48:35 +0000 (16:48 +0000)
committerLuke Leighton <lkcl@samba.org>
Thu, 5 Nov 1998 16:48:35 +0000 (16:48 +0000)
these are *not* going to be added into the Makefile.in yet
so they still also exist in util.c.
(This used to be commit 3f5feda6749dace6bc51fb0e02b16d2b72a930b8)

source3/lib/util_str.c [new file with mode: 0644]
source3/lib/util_unistr.c [new file with mode: 0644]

diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
new file mode 100644 (file)
index 0000000..7eb1494
--- /dev/null
@@ -0,0 +1,976 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   Samba utility functions
+   Copyright (C) Andrew Tridgell 1992-1998
+   
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+static char *last_ptr=NULL;
+
+void set_first_token(char *ptr)
+{
+       last_ptr = ptr;
+}
+
+/****************************************************************************
+  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(char **ptr,char *buff,char *sep, int bufsize)
+{
+  char *s;
+  BOOL quoted;
+  int len=1;
+
+  if (!ptr) ptr = &last_ptr;
+  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(sep,*s)) s++;
+
+  /* nothing left? */
+  if (! *s) return(False);
+
+  /* copy over the token */
+  for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++)
+    {
+           if (*s == '\"') {
+                   quoted = !quoted;
+           } else {
+                   len++;
+                   *buff++ = *s;
+           }
+    }
+
+  *ptr = (*s) ? s+1 : s;  
+  *buff = 0;
+  last_ptr = *ptr;
+
+  return(True);
+}
+
+/****************************************************************************
+Convert list of tokens to array; dependent on above routine.
+Uses last_ptr from above - bit of a hack.
+****************************************************************************/
+char **toktocliplist(int *ctok, char *sep)
+{
+  char *s=last_ptr;
+  int ictok=0;
+  char **ret, **iret;
+
+  if (!sep) sep = " \t\n\r";
+
+  while(*s && strchr(sep,*s)) s++;
+
+  /* nothing left? */
+  if (!*s) return(NULL);
+
+  do {
+    ictok++;
+    while(*s && (!strchr(sep,*s))) s++;
+    while(*s && strchr(sep,*s)) *s++=0;
+  } while(*s);
+
+  *ctok=ictok;
+  s=last_ptr;
+
+  if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL;
+  
+  while(ictok--) {    
+    *iret++=s;
+    while(*s++);
+    while(!*s) s++;
+  }
+
+  return ret;
+}
+
+
+/*******************************************************************
+  case insensitive string compararison
+********************************************************************/
+int StrCaseCmp(char *s, char *t)
+{
+  /* compare until we run out of string, either t or s, or find a difference */
+  /* We *must* use toupper rather than tolower here due to the
+     asynchronous upper to lower mapping.
+   */
+#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. */
+    int diff;
+    for (;;)
+    {
+      if (!*s || !*t)
+           return toupper (*s) - toupper (*t);
+      else if (is_sj_alph (*s) && is_sj_alph (*t))
+      {
+        diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+        if (diff)
+          return diff;
+        s += 2;
+        t += 2;
+      }
+      else if (is_shift_jis (*s) && is_shift_jis (*t))
+      {
+        diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+        if (diff)
+          return diff;
+        diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+        if (diff)
+          return diff;
+        s += 2;
+        t += 2;
+      }
+      else if (is_shift_jis (*s))
+        return 1;
+      else if (is_shift_jis (*t))
+        return -1;
+      else 
+      {
+        diff = toupper (*s) - toupper (*t);
+        if (diff)
+          return diff;
+        s++;
+        t++;
+      }
+    }
+  }
+  else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+  {
+    while (*s && *t && toupper(*s) == toupper(*t))
+    {
+      s++;
+      t++;
+    }
+
+    return(toupper(*s) - toupper(*t));
+  }
+}
+
+/*******************************************************************
+  case insensitive string compararison, length limited
+********************************************************************/
+int StrnCaseCmp(char *s, char *t, int n)
+{
+  /* compare until we run out of string, either t or s, or chars */
+  /* We *must* use toupper rather than tolower here due to the
+     asynchronous upper to lower mapping.
+   */
+#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. */
+    int diff;
+    for (;n > 0;)
+    {
+      if (!*s || !*t)
+        return toupper (*s) - toupper (*t);
+      else if (is_sj_alph (*s) && is_sj_alph (*t))
+      {
+        diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+        if (diff)
+          return diff;
+        s += 2;
+        t += 2;
+        n -= 2;
+      }
+      else if (is_shift_jis (*s) && is_shift_jis (*t))
+      {
+        diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+        if (diff)
+          return diff;
+        diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+        if (diff)
+          return diff;
+        s += 2;
+        t += 2;
+        n -= 2;
+      }
+      else if (is_shift_jis (*s))
+        return 1;
+      else if (is_shift_jis (*t))
+        return -1;
+      else 
+      {
+        diff = toupper (*s) - toupper (*t);
+        if (diff)
+          return diff;
+        s++;
+        t++;
+        n--;
+      }
+    }
+    return 0;
+  }
+  else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+  {
+    while (n && *s && *t && toupper(*s) == toupper(*t))
+    {
+      s++;
+      t++;
+      n--;
+    }
+
+    /* not run out of chars - strings are different lengths */
+    if (n) 
+      return(toupper(*s) - toupper(*t));
+
+    /* identical up to where we run out of chars, 
+       and strings are same length */
+    return(0);
+  }
+}
+
+/*******************************************************************
+  compare 2 strings 
+********************************************************************/
+BOOL strequal(char *s1, char *s2)
+{
+  if (s1 == s2) return(True);
+  if (!s1 || !s2) return(False);
+  
+  return(StrCaseCmp(s1,s2)==0);
+}
+
+/*******************************************************************
+  compare 2 strings up to and including the nth char.
+  ******************************************************************/
+BOOL strnequal(char *s1,char *s2,int n)
+{
+  if (s1 == s2) return(True);
+  if (!s1 || !s2 || !n) return(False);
+  
+  return(StrnCaseCmp(s1,s2,n)==0);
+}
+
+/*******************************************************************
+  compare 2 strings (case sensitive)
+********************************************************************/
+BOOL strcsequal(char *s1,char *s2)
+{
+  if (s1 == s2) return(True);
+  if (!s1 || !s2) return(False);
+  
+  return(strcmp(s1,s2)==0);
+}
+
+
+/*******************************************************************
+  convert a string to lower case
+********************************************************************/
+void strlower(char *s)
+{
+  while (*s)
+  {
+#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. */
+      if (is_shift_jis (*s))
+      {
+        if (is_sj_upper (s[0], s[1]))
+          s[1] = sj_tolower2 (s[1]);
+        s += 2;
+      }
+      else if (is_kana (*s))
+      {
+        s++;
+      }
+      else
+      {
+        if (isupper(*s))
+          *s = tolower(*s);
+        s++;
+      }
+    }
+    else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+    {
+      int skip = skip_multibyte_char( *s );
+      if( skip != 0 )
+        s += skip;
+      else
+      {
+        if (isupper(*s))
+          *s = tolower(*s);
+        s++;
+      }
+    }
+  }
+}
+
+/*******************************************************************
+  convert a string to upper case
+********************************************************************/
+void strupper(char *s)
+{
+  while (*s)
+  {
+#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. */
+      if (is_shift_jis (*s))
+      {
+        if (is_sj_lower (s[0], s[1]))
+          s[1] = sj_toupper2 (s[1]);
+        s += 2;
+      }
+      else if (is_kana (*s))
+      {
+        s++;
+      }
+      else
+      {
+        if (islower(*s))
+          *s = toupper(*s);
+        s++;
+      }
+    }
+    else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+    {
+      int skip = skip_multibyte_char( *s );
+      if( skip != 0 )
+        s += skip;
+      else
+      {
+        if (islower(*s))
+          *s = toupper(*s);
+        s++;
+      }
+    }
+  }
+}
+
+/*******************************************************************
+  convert a string to "normal" form
+********************************************************************/
+void strnorm(char *s)
+{
+  extern int case_default;
+  if (case_default == CASE_UPPER)
+    strupper(s);
+  else
+    strlower(s);
+}
+
+/*******************************************************************
+check if a string is in "normal" case
+********************************************************************/
+BOOL strisnormal(char *s)
+{
+  extern int case_default;
+  if (case_default == CASE_UPPER)
+    return(!strhaslower(s));
+
+  return(!strhasupper(s));
+}
+
+
+/****************************************************************************
+  string replace
+****************************************************************************/
+void string_replace(char *s,char oldc,char newc)
+{
+  int skip;
+  while (*s)
+  {
+    skip = skip_multibyte_char( *s );
+    if( skip != 0 )
+      s += skip;
+    else
+    {
+      if (oldc == *s)
+        *s = newc;
+      s++;
+    }
+  }
+}
+
+
+/*******************************************************************
+skip past some strings in a buffer
+********************************************************************/
+char *skip_string(char *buf,int n)
+{
+  while (n--)
+    buf += strlen(buf) + 1;
+  return(buf);
+}
+
+/*******************************************************************
+ Count the number of 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.
+ 16.oct.98, jdblair@cobaltnet.com.
+********************************************************************/
+
+size_t str_charnum(char *s)
+{
+  size_t len = 0;
+  
+  while (*s != '\0') {
+    int skip = skip_multibyte_char(*s);
+    s += (skip ? skip : 1);
+    len++;
+  }
+  return len;
+}
+
+/*******************************************************************
+trim the specified elements off the front and back of a string
+********************************************************************/
+
+BOOL trim_string(char *s,char *front,char *back)
+{
+  BOOL ret = False;
+  size_t front_len = (front && *front) ? strlen(front) : 0;
+  size_t back_len = (back && *back) ? strlen(back) : 0;
+  size_t s_len;
+
+  while (front_len && strncmp(s, front, front_len) == 0)
+  {
+    char *p = s;
+    ret = True;
+    while (1)
+    {
+      if (!(*p = p[front_len]))
+        break;
+      p++;
+    }
+  }
+
+  /*
+   * We split out the multibyte code page
+   * case here for speed purposes. Under a
+   * multibyte code page we need to walk the
+   * string forwards only and multiple times.
+   * Thanks to John Blair for finding this
+   * one. JRA.
+   */
+
+  if(back_len)
+  {
+    if(!is_multibyte_codepage())
+    {
+      s_len = strlen(s);
+      while ((s_len >= back_len) && 
+             (strncmp(s + s_len - back_len, back, back_len)==0))  
+      {
+        ret = True;
+        s[s_len - back_len] = '\0';
+        s_len = strlen(s);
+      }
+    }
+    else
+    {
+
+      /*
+       * Multibyte code page case.
+       * Keep going through the string, trying
+       * to match the 'back' string with the end
+       * of the string. If we get a match, truncate
+       * 'back' off the end of the string and
+       * go through the string again from the
+       * start. Keep doing this until we have
+       * gone through the string with no match
+       * at the string end.
+       */
+
+      size_t mb_back_len = str_charnum(back);
+      size_t mb_s_len = str_charnum(s);
+
+      while(mb_s_len >= mb_back_len)
+      {
+        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++;
+        }
+
+        /*
+         * mbp now points at mb_back_len multibyte
+         * characters from the end of s.
+         */
+
+        if(strcmp(mbp, back) == 0)
+        {
+          ret = True;
+          *mbp = '\0';
+          mb_s_len = str_charnum(s);
+          mbp = s;
+        }
+        else
+          break;
+      } /* end while mb_s_len... */
+    } /* end else .. */
+  } /* end if back_len .. */
+
+  return(ret);
+}
+
+
+/****************************************************************************
+does a string have any uppercase chars in it?
+****************************************************************************/
+BOOL strhasupper(char *s)
+{
+  while (*s) 
+  {
+#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. */
+      if (is_shift_jis (*s))
+        s += 2;
+      else if (is_kana (*s))
+        s++;
+      else
+      {
+        if (isupper(*s))
+          return(True);
+        s++;
+      }
+    }
+    else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+    {
+      int skip = skip_multibyte_char( *s );
+      if( skip != 0 )
+        s += skip;
+      else {
+        if (isupper(*s))
+          return(True);
+        s++;
+      }
+    }
+  }
+  return(False);
+}
+
+/****************************************************************************
+does a string have any lowercase chars in it?
+****************************************************************************/
+BOOL strhaslower(char *s)
+{
+  while (*s) 
+  {
+#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. */
+      if (is_shift_jis (*s))
+      {
+        if (is_sj_upper (s[0], s[1]))
+          return(True);
+        if (is_sj_lower (s[0], s[1]))
+          return (True);
+        s += 2;
+      }
+      else if (is_kana (*s))
+      {
+        s++;
+      }
+      else
+      {
+        if (islower(*s))
+          return(True);
+        s++;
+      }
+    }
+    else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+    {
+      int skip = skip_multibyte_char( *s );
+      if( skip != 0 )
+        s += skip;
+      else {
+        if (islower(*s))
+          return(True);
+        s++;
+      }
+    }
+  }
+  return(False);
+}
+
+/****************************************************************************
+find the number of chars in a string
+****************************************************************************/
+int count_chars(char *s,char c)
+{
+  int count=0;
+
+#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)
+          count++;
+        s++;
+      }
+    }
+  }
+  else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+  {
+    while (*s) 
+    {
+      int skip = skip_multibyte_char( *s );
+      if( skip != 0 )
+        s += skip;
+      else {
+        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, int maxlength)
+{
+    int len;
+
+    if (!dest) {
+        DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
+        return NULL;
+    }
+
+    if (!src) {
+        *dest = 0;
+        return dest;
+    }  
+
+    len = strlen(src);
+
+    if (len > maxlength) {
+           DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
+                    len-maxlength, src));
+           len = maxlength;
+    }
+      
+    memcpy(dest, src, len);
+    dest[len] = 0;
+    return dest;
+}  
+
+/*******************************************************************
+safe string cat into a string. maxlength does not
+include the terminating zero.
+********************************************************************/
+char *safe_strcat(char *dest, char *src, int maxlength)
+{
+    int src_len, dest_len;
+
+    if (!dest) {
+        DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
+        return NULL;
+    }
+
+    if (!src) {
+        return dest;
+    }  
+
+    src_len = strlen(src);
+    dest_len = strlen(dest);
+
+    if (src_len + dest_len > maxlength) {
+           DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
+                    src_len + dest_len - maxlength, src));
+           src_len = maxlength - dest_len;
+    }
+      
+    memcpy(&dest[dest_len], src, src_len);
+    dest[dest_len + src_len] = 0;
+    return dest;
+}
+
+/****************************************************************************
+this is a safer strcpy(), meant to prevent core dumps when nasty things happen
+****************************************************************************/
+char *StrCpy(char *dest,char *src)
+{
+  char *d = dest;
+
+  /* I don't want to get lazy with these ... */
+  SMB_ASSERT(dest && src);
+
+  if (!dest) return(NULL);
+  if (!src) {
+    *dest = 0;
+    return(dest);
+  }
+  while ((*d++ = *src++)) ;
+  return(dest);
+}
+
+/****************************************************************************
+like strncpy but always null terminates. Make sure there is room!
+****************************************************************************/
+char *StrnCpy(char *dest,char *src,int n)
+{
+  char *d = dest;
+  if (!dest) return(NULL);
+  if (!src) {
+    *dest = 0;
+    return(dest);
+  }
+  while (n-- && (*d++ = *src++)) ;
+  *d = 0;
+  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).
+****************************************************************************/
+char *strncpyn(char *dest, char *src,int n, char c)
+{
+       char *p;
+       int str_len;
+
+       p = strchr(src, c);
+       if (p == NULL)
+       {
+               DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
+               return NULL;
+       }
+
+       str_len = PTR_DIFF(p, src);
+       strncpy(dest, src, MIN(n, str_len));
+       dest[str_len] = '\0';
+
+       return p;
+}
+
+
+/****************************************************************************
+check if a string is part of a list
+****************************************************************************/
+BOOL in_list(char *s,char *list,BOOL casesensitive)
+{
+  pstring tok;
+  char *p=list;
+
+  if (!list) return(False);
+
+  while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
+    if (casesensitive) {
+      if (strcmp(tok,s) == 0)
+        return(True);
+    } else {
+      if (StrCaseCmp(tok,s) == 0)
+        return(True);
+    }
+  }
+  return(False);
+}
+
+/* this is used to prevent lots of mallocs of size 1 */
+static char *null_string = NULL;
+
+/****************************************************************************
+set a string value, allocing the space for the string
+****************************************************************************/
+BOOL string_init(char **dest,char *src)
+{
+  int l;
+  if (!src)     
+    src = "";
+
+  l = strlen(src);
+
+  if (l == 0)
+    {
+      if (!null_string) {
+        if((null_string = (char *)malloc(1)) == NULL) {
+          DEBUG(0,("string_init: malloc fail for null_string.\n"));
+          return False;
+        }
+        *null_string = 0;
+      }
+      *dest = null_string;
+    }
+  else
+    {
+      (*dest) = (char *)malloc(l+1);
+      if ((*dest) == NULL) {
+             DEBUG(0,("Out of memory in string_init\n"));
+             return False;
+      }
+
+      pstrcpy(*dest,src);
+    }
+  return(True);
+}
+
+/****************************************************************************
+free a string value
+****************************************************************************/
+void string_free(char **s)
+{
+  if (!s || !(*s)) return;
+  if (*s == null_string)
+    *s = NULL;
+  if (*s) free(*s);
+  *s = NULL;
+}
+
+/****************************************************************************
+set a string value, allocing the space for the string, and deallocating any 
+existing space
+****************************************************************************/
+BOOL string_set(char **dest,char *src)
+{
+  string_free(dest);
+
+  return(string_init(dest,src));
+}
+
+/****************************************************************************
+substitute a string for a pattern in another string. Make sure there is 
+enough room!
+
+This routine looks for pattern in s and replaces it with 
+insert. It may do multiple replacements.
+
+return True if a substitution was done.
+****************************************************************************/
+BOOL string_sub(char *s,char *pattern,char *insert)
+{
+  BOOL ret = False;
+  char *p;
+  int ls,lp,li;
+
+  if (!insert || !pattern || !s) return(False);
+
+  ls = strlen(s);
+  lp = strlen(pattern);
+  li = strlen(insert);
+
+  if (!*pattern) return(False);
+
+  while (lp <= ls && (p = strstr(s,pattern)))
+    {
+      ret = True;
+      memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
+      memcpy(p,insert,li);
+      s = p + li;
+      ls = strlen(s);
+    }
+  return(ret);
+}
+
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c
new file mode 100644 (file)
index 0000000..2365090
--- /dev/null
@@ -0,0 +1,186 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   Samba utility functions
+   Copyright (C) Andrew Tridgell 1992-1998
+   
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+*/
+
+#include "includes.h"
+
+/*******************************************************************
+write a string in unicoode format
+********************************************************************/
+int PutUniCode(char *dst,char *src)
+{
+  int ret = 0;
+  while (*src) {
+    dst[ret++] = src[0];
+    dst[ret++] = 0;    
+    src++;
+  }
+  dst[ret++]=0;
+  dst[ret++]=0;
+  return(ret);
+}
+
+/*******************************************************************
+skip past some unicode strings in a buffer
+********************************************************************/
+char *skip_unicode_string(char *buf,int n)
+{
+  while (n--)
+  {
+    while (*buf)
+      buf += 2;
+    buf += 2;
+  }
+  return(buf);
+}
+
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistrn2(uint16 *buf, int len)
+{
+       static char lbufs[8][MAXUNI];
+       static int nexti;
+       char *lbuf = lbufs[nexti];
+       char *p;
+
+       nexti = (nexti+1)%8;
+
+       for (p = lbuf; *buf && p-lbuf < MAXUNI-2 && len > 0; len--, p++, buf++)
+       {
+               *p = *buf;
+       }
+
+       *p = 0;
+       return lbuf;
+}
+
+static char lbufs[8][MAXUNI];
+static int nexti;
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistr2(uint16 *buf)
+{
+       char *lbuf = lbufs[nexti];
+       char *p;
+
+       nexti = (nexti+1)%8;
+
+       for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++)
+       {
+               *p = *buf;
+       }
+
+       *p = 0;
+       return lbuf;
+}
+
+/*******************************************************************
+Return a ascii version of a unicode string
+********************************************************************/
+char *unistr2_to_str(UNISTR2 *str)
+{
+       char *lbuf = lbufs[nexti];
+       char *p;
+       uint16 *buf = str->buffer;
+       int max_size = MIN(sizeof(str->buffer)-2, str->uni_str_len);
+
+       nexti = (nexti+1)%8;
+
+       for (p = lbuf; *buf && p-lbuf < max_size; p++, buf++)
+       {
+               *p = *buf;
+       }
+
+       *p = 0;
+       return lbuf;
+}
+
+/*******************************************************************
+create a null-terminated unicode string from a null-terminated ascii string.
+return number of unicode chars copied, excluding the null character.
+
+only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+int struni2(uint16 *p, char *buf)
+{
+       int len = 0;
+
+       if (p == NULL) return 0;
+
+       if (buf != NULL)
+       {
+               for (; *buf && len < MAXUNI-2; len++, p++, buf++)
+               {
+                       *p = *buf;
+               }
+       }
+
+       *p = 0;
+
+       return len;
+}
+
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistr(char *buf)
+{
+       char *lbuf = lbufs[nexti];
+       char *p;
+
+       nexti = (nexti+1)%8;
+
+       for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2)
+       {
+               *p = *buf;
+       }
+       *p = 0;
+       return lbuf;
+}
+
+
+/*******************************************************************
+strcpy for unicode strings.  returns length (in num of wide chars)
+********************************************************************/
+int unistrcpy(char *dst, char *src)
+{
+       int num_wchars = 0;
+
+       while (*src)
+       {
+               *dst++ = *src++;
+               *dst++ = *src++;
+               num_wchars++;
+       }
+       *dst++ = 0;
+       *dst++ = 0;
+
+       return num_wchars;
+}
+