summaryrefslogtreecommitdiff
path: root/source3/lib/util_unistr.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib/util_unistr.c')
-rw-r--r--source3/lib/util_unistr.c912
1 files changed, 875 insertions, 37 deletions
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c
index ddcea26e38..5e7076d5df 100644
--- a/source3/lib/util_unistr.c
+++ b/source3/lib/util_unistr.c
@@ -23,6 +23,9 @@
extern int DEBUGLEVEL;
+ smb_ucs2_t wchar_list_sep[] = { (smb_ucs2_t)' ', (smb_ucs2_t)'\t', (smb_ucs2_t)',',
+ (smb_ucs2_t)';', (smb_ucs2_t)':', (smb_ucs2_t)'\n',
+ (smb_ucs2_t)'\r', 0 };
/*
* The following are the codepage to ucs2 and vica versa maps.
* These are dynamically loaded from a unicode translation file.
@@ -689,7 +692,7 @@ smb_ucs2_t *dos_to_unicode(smb_ucs2_t *dst, const char *src, size_t dst_len)
Count the number of characters in a smb_ucs2_t string.
********************************************************************/
-size_t wstrlen(const smb_ucs2_t *src)
+size_t strlen_w(const smb_ucs2_t *src)
{
size_t len;
@@ -704,12 +707,12 @@ size_t wstrlen(const smb_ucs2_t *src)
the terminating zero. maxlength is in bytes.
********************************************************************/
-smb_ucs2_t *safe_wstrcpy(smb_ucs2_t *dest,const smb_ucs2_t *src, size_t maxlength)
+smb_ucs2_t *safe_strcpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src, size_t maxlength)
{
size_t ucs2_len;
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in safe_wstrcpy\n"));
+ DEBUG(0,("ERROR: NULL dest in safe_strcpy_w\n"));
return NULL;
}
@@ -718,14 +721,20 @@ smb_ucs2_t *safe_wstrcpy(smb_ucs2_t *dest,const smb_ucs2_t *src, size_t maxlengt
return dest;
}
- ucs2_len = wstrlen(src);
+ /*
+ * Convert maxlength to smb_ucs2_t units.
+ */
- if (ucs2_len >= (maxlength/sizeof(smb_ucs2_t))) {
+ maxlength /= sizeof(smb_ucs2_t);
+
+ ucs2_len = strlen_w(src);
+
+ if (ucs2_len >= maxlength) {
fstring out;
- DEBUG(0,("ERROR: string overflow by %u bytes in safe_wstrcpy [%.50s]\n",
- (unsigned int)((ucs2_len*sizeof(smb_ucs2_t))-maxlength),
+ DEBUG(0,("ERROR: string overflow by %u bytes in safe_strcpy_w [%.50s]\n",
+ (unsigned int)((ucs2_len-maxlength)*sizeof(smb_ucs2_t)),
unicode_to_unix(out,src,sizeof(out))) );
- ucs2_len = (maxlength/sizeof(smb_ucs2_t)) - 1;
+ ucs2_len = maxlength - 1;
}
memcpy(dest, src, ucs2_len*sizeof(smb_ucs2_t));
@@ -738,27 +747,32 @@ smb_ucs2_t *safe_wstrcpy(smb_ucs2_t *dest,const smb_ucs2_t *src, size_t maxlengt
maxlength is in bytes.
********************************************************************/
-smb_ucs2_t *safe_wstrcat(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
+smb_ucs2_t *safe_strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
{
size_t ucs2_src_len, ucs2_dest_len;
if (!dest) {
- DEBUG(0,("ERROR: NULL dest in safe_wstrcat\n"));
+ DEBUG(0,("ERROR: NULL dest in safe_strcat_w\n"));
return NULL;
}
- if (!src) {
+ if (!src)
return dest;
- }
- ucs2_src_len = wstrlen(src);
- ucs2_dest_len = wstrlen(dest);
+ /*
+ * Convert maxlength to smb_ucs2_t units.
+ */
+
+ maxlength /= sizeof(smb_ucs2_t);
- if (ucs2_src_len + ucs2_dest_len >= (maxlength/sizeof(smb_ucs2_t))) {
+ ucs2_src_len = strlen_w(src);
+ ucs2_dest_len = strlen_w(dest);
+
+ if (ucs2_src_len + ucs2_dest_len >= maxlength) {
fstring out;
- int new_len = (maxlength/sizeof(smb_ucs2_t)) - ucs2_dest_len - 1;
- DEBUG(0,("ERROR: string overflow by %u characters in safe_wstrcat [%.50s]\n",
- (unsigned int)((sizeof(smb_ucs2_t)*(ucs2_src_len + ucs2_dest_len)) - maxlength),
+ int new_len = maxlength - ucs2_dest_len - 1;
+ DEBUG(0,("ERROR: string overflow by %u characters in safe_strcat_w [%.50s]\n",
+ (unsigned int)(sizeof(smb_ucs2_t)*(ucs2_src_len + ucs2_dest_len - maxlength)),
unicode_to_unix(out,src,sizeof(out))) );
ucs2_src_len = (size_t)(new_len > 0 ? new_len : 0);
}
@@ -772,7 +786,7 @@ smb_ucs2_t *safe_wstrcat(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxleng
Compare the two strings s1 and s2. len is in ucs2 units.
********************************************************************/
-int wstrcmp(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
+int strcmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
smb_ucs2_t c1, c2;
@@ -793,7 +807,7 @@ int wstrcmp(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
Compare the first n characters of s1 to s2. len is in ucs2 units.
********************************************************************/
-int wstrncmp(const smb_ucs2_t *s1, const smb_ucs2_t *s2, size_t len)
+int strncmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2, size_t len)
{
smb_ucs2_t c1, c2;
@@ -815,16 +829,16 @@ int wstrncmp(const smb_ucs2_t *s1, const smb_ucs2_t *s2, size_t len)
Search string s2 from s1.
********************************************************************/
-smb_ucs2_t *wstrstr(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
+smb_ucs2_t *strstr_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
- size_t len = wstrlen(s2);
+ size_t len = strlen_w(s2);
if (!*s2)
return (smb_ucs2_t *)s1;
for(;*s1; s1++) {
if (*s1 == *s2) {
- if (wstrncmp(s1, s2, len) == 0)
+ if (strncmp_w(s1, s2, len) == 0)
return (smb_ucs2_t *)s1;
}
}
@@ -835,7 +849,7 @@ smb_ucs2_t *wstrstr(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
Search for ucs2 char c from the beginning of s.
********************************************************************/
-smb_ucs2_t *wstrchr(const smb_ucs2_t *s, smb_ucs2_t c)
+smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
{
do {
if (*s == c)
@@ -849,7 +863,7 @@ smb_ucs2_t *wstrchr(const smb_ucs2_t *s, smb_ucs2_t c)
Search for ucs2 char c from the end of s.
********************************************************************/
-smb_ucs2_t *wstrrchr(const smb_ucs2_t *s, smb_ucs2_t c)
+smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
{
smb_ucs2_t *retval = 0;
@@ -865,7 +879,7 @@ smb_ucs2_t *wstrrchr(const smb_ucs2_t *s, smb_ucs2_t c)
Search token from s1 separated by any ucs2 char of s2.
********************************************************************/
-smb_ucs2_t *wstrtok(smb_ucs2_t *s1, const smb_ucs2_t *s2)
+smb_ucs2_t *strtok_w(smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
static smb_ucs2_t *s = NULL;
smb_ucs2_t *q;
@@ -877,7 +891,7 @@ smb_ucs2_t *wstrtok(smb_ucs2_t *s1, const smb_ucs2_t *s2)
}
for (q = s1; *s1; s1++) {
- smb_ucs2_t *p = wstrchr(s2, *s1);
+ smb_ucs2_t *p = strchr_w(s2, *s1);
if (p) {
if (s1 != q) {
s = s1 + 1;
@@ -899,13 +913,13 @@ smb_ucs2_t *wstrtok(smb_ucs2_t *s1, const smb_ucs2_t *s2)
Duplicate a ucs2 string.
********************************************************************/
-smb_ucs2_t *wstrdup(const smb_ucs2_t *s)
+smb_ucs2_t *strdup_w(const smb_ucs2_t *s)
{
- size_t newlen = (wstrlen(s)+1)*sizeof(smb_ucs2_t);
+ size_t newlen = (strlen_w(s)+1)*sizeof(smb_ucs2_t);
smb_ucs2_t *newstr = (smb_ucs2_t *)malloc(newlen);
if (newstr == NULL)
return NULL;
- safe_wstrcpy(newstr, s, newlen);
+ safe_strcpy_w(newstr, s, newlen);
return newstr;
}
@@ -928,7 +942,7 @@ static smb_unicode_table_t map_table[] = {
Is an upper case wchar.
********************************************************************/
-int wisupper( smb_ucs2_t val)
+int isupper_w( smb_ucs2_t val)
{
return (map_table[val].flags & UNI_UPPER);
}
@@ -937,7 +951,7 @@ int wisupper( smb_ucs2_t val)
Is a lower case wchar.
********************************************************************/
-int wislower( smb_ucs2_t val)
+int islower_w( smb_ucs2_t val)
{
return (map_table[val].flags & UNI_LOWER);
}
@@ -946,7 +960,7 @@ int wislower( smb_ucs2_t val)
Is a digit wchar.
********************************************************************/
-int wisdigit( smb_ucs2_t val)
+int isdigit_w( smb_ucs2_t val)
{
return (map_table[val].flags & UNI_DIGIT);
}
@@ -955,7 +969,7 @@ int wisdigit( smb_ucs2_t val)
Is a hex digit wchar.
********************************************************************/
-int wisxdigit( smb_ucs2_t val)
+int isxdigit_w( smb_ucs2_t val)
{
return (map_table[val].flags & UNI_XDIGIT);
}
@@ -964,7 +978,7 @@ int wisxdigit( smb_ucs2_t val)
Is a space wchar.
********************************************************************/
-int wisspace( smb_ucs2_t val)
+int isspace_w( smb_ucs2_t val)
{
return (map_table[val].flags & UNI_SPACE);
}
@@ -973,7 +987,7 @@ int wisspace( smb_ucs2_t val)
Convert a wchar to upper case.
********************************************************************/
-smb_ucs2_t wtoupper( smb_ucs2_t val )
+smb_ucs2_t toupper_w( smb_ucs2_t val )
{
return map_table[val].upper;
}
@@ -982,7 +996,831 @@ smb_ucs2_t wtoupper( smb_ucs2_t val )
Convert a wchar to lower case.
********************************************************************/
-smb_ucs2_t wtolowerr( smb_ucs2_t val )
+smb_ucs2_t tolower_w( smb_ucs2_t val )
{
return map_table[val].lower;
}
+
+static smb_ucs2_t *last_ptr = NULL;
+
+void set_first_token_w(smb_ucs2_t *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
+ bufsize is in bytes.
+****************************************************************************/
+
+static smb_ucs2_t sep_list[] = { (smb_ucs2_t)' ', (smb_ucs2_t)'\t', (smb_ucs2_t)'\n', (smb_ucs2_t)'\r', 0};
+static smb_ucs2_t quotechar = (smb_ucs2_t)'\"';
+
+BOOL next_token_w(smb_ucs2_t **ptr, smb_ucs2_t *buff, smb_ucs2_t *sep, size_t bufsize)
+{
+ smb_ucs2_t *s;
+ BOOL quoted;
+ size_t len=1;
+
+ /*
+ * Convert bufsize to smb_ucs2_t units.
+ */
+
+ bufsize /= sizeof(smb_ucs2_t);
+
+ if (!ptr)
+ ptr = &last_ptr;
+ if (!ptr)
+ return(False);
+
+ s = *ptr;
+
+ /*
+ * Default to simple separators.
+ */
+
+ if (!sep)
+ sep = sep_list;
+
+ /*
+ * Find the first non sep char.
+ */
+
+ while(*s && strchr_w(sep,*s))
+ s++;
+
+ /*
+ * Nothing left ?
+ */
+
+ if (!*s)
+ return(False);
+
+ /*
+ * Copy over the token.
+ */
+
+ for (quoted = False; len < bufsize && *s && (quoted || !strchr_w(sep,*s)); s++) {
+ if (*s == quotechar) {
+ 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.
+****************************************************************************/
+
+smb_ucs2_t **toktocliplist_w(int *ctok, smb_ucs2_t *sep)
+{
+ smb_ucs2_t *s=last_ptr;
+ int ictok=0;
+ smb_ucs2_t **ret, **iret;
+
+ if (!sep)
+ sep = sep_list;
+
+ while(*s && strchr_w(sep,*s))
+ s++;
+
+ /*
+ * Nothing left ?
+ */
+
+ if (!*s)
+ return(NULL);
+
+ do {
+ ictok++;
+ while(*s && (!strchr_w(sep,*s)))
+ s++;
+ while(*s && strchr_w(sep,*s))
+ *s++=0;
+ } while(*s);
+
+ *ctok = ictok;
+ s = last_ptr;
+
+ if (!(ret=iret=malloc(ictok*sizeof(smb_ucs2_t *))))
+ return NULL;
+
+ while(ictok--) {
+ *iret++=s;
+ while(*s++)
+ ;
+ while(!*s)
+ s++;
+ }
+
+ return ret;
+}
+
+/*******************************************************************
+ Case insensitive string compararison.
+********************************************************************/
+
+int StrCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t)
+{
+ /*
+ * Compare until we run out of string, either t or s, or find a difference.
+ */
+
+ while (*s && *t && toupper_w(*s) == toupper_w(*t)) {
+ s++;
+ t++;
+ }
+
+ return(toupper_w(*s) - toupper_w(*t));
+}
+
+/*******************************************************************
+ Case insensitive string compararison, length limited.
+********************************************************************/
+
+int StrnCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t, size_t n)
+{
+ /*
+ * Compare until we run out of string, either t or s, or chars.
+ */
+
+ while (n && *s && *t && toupper_w(*s) == toupper_w(*t)) {
+ s++;
+ t++;
+ n--;
+ }
+
+ /*
+ * Not run out of chars - strings are different lengths.
+ */
+
+ if (n)
+ return(toupper_w(*s) - toupper_w(*t));
+
+ /*
+ * Identical up to where we run out of chars,
+ * and strings are same length.
+ */
+
+ return(0);
+}
+
+/*******************************************************************
+ Compare 2 strings.
+********************************************************************/
+
+BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
+{
+ if (s1 == s2)
+ return(True);
+ if (!s1 || !s2)
+ return(False);
+
+ return(StrCaseCmp_w(s1,s2)==0);
+}
+
+/*******************************************************************
+ Compare 2 strings up to and including the nth char.
+******************************************************************/
+
+BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
+{
+ if (s1 == s2)
+ return(True);
+ if (!s1 || !s2 || !n)
+ return(False);
+
+ return(StrnCaseCmp_w(s1,s2,n)==0);
+}
+
+/*******************************************************************
+ Compare 2 strings (case sensitive).
+********************************************************************/
+
+BOOL strcsequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2)
+{
+ if (s1 == s2)
+ return(True);
+ if (!s1 || !s2)
+ return(False);
+
+ return(strcmp_w(s1,s2)==0);
+}
+
+/*******************************************************************
+ Convert a string to lower case.
+********************************************************************/
+
+void strlower_w(smb_ucs2_t *s)
+{
+ while (*s) {
+ if (isupper_w(*s))
+ *s = tolower_w(*s);
+ s++;
+ }
+}
+
+/*******************************************************************
+ Convert a string to upper case.
+********************************************************************/
+
+void strupper_w(smb_ucs2_t *s)
+{
+ while (*s) {
+ if (islower_w(*s))
+ *s = toupper_w(*s);
+ s++;
+ }
+}
+
+/*******************************************************************
+ Convert a string to "normal" form.
+********************************************************************/
+
+void strnorm_w(smb_ucs2_t *s)
+{
+ extern int case_default;
+ if (case_default == CASE_UPPER)
+ strupper_w(s);
+ else
+ strlower_w(s);
+}
+
+/*******************************************************************
+ Check if a string is in "normal" case.
+********************************************************************/
+
+BOOL strisnormal_w(smb_ucs2_t *s)
+{
+ extern int case_default;
+ if (case_default == CASE_UPPER)
+ return(!strhaslower_w(s));
+
+ return(!strhasupper_w(s));
+}
+
+/****************************************************************************
+ String replace.
+****************************************************************************/
+
+void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
+{
+ while (*s) {
+ if (oldc == *s)
+ *s = newc;
+ s++;
+ }
+}
+
+/*******************************************************************
+ Skip past some strings in a buffer. n is in bytes.
+********************************************************************/
+
+smb_ucs2_t *skip_string_w(smb_ucs2_t *buf,size_t n)
+{
+ while (n--)
+ buf += (strlen_w(buf)*sizeof(smb_ucs2_t)) + 1;
+ return(buf);
+}
+
+/*******************************************************************
+ Count the number of characters in a string. Same as strlen_w in
+ smb_ucs2_t string units.
+********************************************************************/
+
+size_t str_charnum_w(const smb_ucs2_t *s)
+{
+ return strlen_w(s);
+}
+
+/*******************************************************************
+ Trim the specified elements off the front and back of a string.
+********************************************************************/
+
+BOOL trim_string_w(smb_ucs2_t *s,const smb_ucs2_t *front,const smb_ucs2_t *back)
+{
+ BOOL ret = False;
+ size_t front_len = (front && *front) ? strlen_w(front) : 0;
+ size_t back_len = (back && *back) ? strlen_w(back) : 0;
+ size_t s_len;
+
+ while (front_len && strncmp_w(s, front, front_len) == 0) {
+ smb_ucs2_t *p = s;
+ ret = True;
+
+ while (1) {
+ if (!(*p = p[front_len]))
+ break;
+ p++;
+ }
+ }
+
+ if(back_len) {
+ s_len = strlen_w(s);
+ while ((s_len >= back_len) &&
+ (strncmp_w(s + s_len - back_len, back, back_len)==0)) {
+ ret = True;
+ s[s_len - back_len] = 0;
+ s_len = strlen_w(s);
+ }
+ }
+
+ return(ret);
+}
+
+/****************************************************************************
+ Does a string have any uppercase chars in it ?
+****************************************************************************/
+
+BOOL strhasupper_w(const smb_ucs2_t *s)
+{
+ while (*s) {
+ if (isupper_w(*s))
+ return(True);
+ s++;
+ }
+ return(False);
+}
+
+/****************************************************************************
+ Does a string have any lowercase chars in it ?
+****************************************************************************/
+
+BOOL strhaslower_w(const smb_ucs2_t *s)
+{
+ while (*s) {
+ if (islower(*s))
+ return(True);
+ s++;
+ }
+ return(False);
+}
+
+/****************************************************************************
+ Find the number of 'c' chars in a string.
+****************************************************************************/
+
+size_t count_chars_w(const smb_ucs2_t *s,smb_ucs2_t c)
+{
+ size_t count=0;
+
+ while (*s) {
+ if (*s == c)
+ count++;
+ s++;
+ }
+ return(count);
+}
+
+/*******************************************************************
+ Return True if a string consists only of one particular character.
+********************************************************************/
+
+BOOL str_is_all_w(const smb_ucs2_t *s,smb_ucs2_t c)
+{
+ if(s == NULL)
+ return False;
+ if(!*s)
+ return False;
+
+ while (*s) {
+ if (*s != c)
+ return False;
+ s++;
+ }
+ return True;
+}
+
+/*******************************************************************
+ 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 !
+ maxlength is in bytes.
+********************************************************************/
+
+smb_ucs2_t *alpha_strcpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
+{
+ size_t len, i;
+
+ /*
+ * Convert to smb_ucs2_t units.
+ */
+
+ maxlength /= sizeof(smb_ucs2_t);
+
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in alpha_strcpy_w\n"));
+ return NULL;
+ }
+
+ if (!src) {
+ *dest = 0;
+ return dest;
+ }
+
+ len = strlen_w(src);
+ if (len >= maxlength)
+ len = maxlength - 1;
+
+ for(i = 0; i < len; i++) {
+ smb_ucs2_t val = src[i];
+ if(isupper_w(val) ||islower_w(val) || isdigit_w(val))
+ dest[i] = src[i];
+ else
+ dest[i] = (smb_ucs2_t)'_';
+ }
+
+ 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 and is in bytes.
+****************************************************************************/
+
+smb_ucs2_t *StrnCpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src,size_t n)
+{
+ smb_ucs2_t *d = dest;
+ if (!dest)
+ return(NULL);
+ if (!src) {
+ *dest = 0;
+ return(dest);
+ }
+
+ /*
+ * Convert to smb_ucs2_t units.
+ */
+
+ n /= sizeof(smb_ucs2_t);
+
+ 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).
+ n is in bytes.
+****************************************************************************/
+
+smb_ucs2_t *strncpyn_w(smb_ucs2_t *dest, const smb_ucs2_t *src,size_t n, smb_ucs2_t c)
+{
+ smb_ucs2_t *p;
+ size_t str_len;
+
+ p = strchr_w(src, c);
+ if (p == NULL) {
+ fstring cval;
+ smb_ucs2_t mbcval[2];
+ mbcval[0] = c;
+ mbcval[1] = 0;
+ DEBUG(5, ("strncpyn_w: separator character (%s) not found\n",
+ unicode_to_unix(cval,mbcval,sizeof(cval)) ));
+ return NULL;
+ }
+
+ str_len = PTR_DIFF(p, src) + sizeof(smb_ucs2_t);
+ safe_strcpy_w(dest, src, MIN(n, str_len));
+
+ return p;
+}
+
+/*************************************************************
+ Routine to get hex characters and turn them into a 16 byte array.
+ The array can be variable length, and any non-hex-numeric
+ characters are skipped. "0xnn" or "0Xnn" is specially catered
+ for. len is in bytes.
+ Valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
+**************************************************************/
+
+static smb_ucs2_t hexprefix[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'x', 0 };
+static smb_ucs2_t hexchars[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'1', (smb_ucs2_t)'2', (smb_ucs2_t)'3',
+ (smb_ucs2_t)'4', (smb_ucs2_t)'5', (smb_ucs2_t)'6', (smb_ucs2_t)'7',
+ (smb_ucs2_t)'8', (smb_ucs2_t)'9', (smb_ucs2_t)'A', (smb_ucs2_t)'B',
+ (smb_ucs2_t)'C', (smb_ucs2_t)'D', (smb_ucs2_t)'E', (smb_ucs2_t)'F', 0 };
+
+size_t strhex_to_str_w(char *p, size_t len, const smb_ucs2_t *strhex)
+{
+ size_t i;
+ size_t num_chars = 0;
+ unsigned char lonybble, hinybble;
+ smb_ucs2_t *p1 = NULL, *p2 = NULL;
+
+ /*
+ * Convert to smb_ucs2_t units.
+ */
+
+ len /= sizeof(smb_ucs2_t);
+
+ for (i = 0; i < len && strhex[i] != 0; i++) {
+ if (strnequal_w(hexchars, hexprefix, 2)) {
+ i++; /* skip two chars */
+ continue;
+ }
+
+ if (!(p1 = strchr_w(hexchars, toupper_w(strhex[i]))))
+ break;
+
+ i++; /* next hex digit */
+
+ if (!(p2 = strchr_w(hexchars, toupper_w(strhex[i]))))
+ break;
+
+ /* get the two nybbles */
+ hinybble = (PTR_DIFF(p1, hexchars)/sizeof(smb_ucs2_t));
+ lonybble = (PTR_DIFF(p2, hexchars)/sizeof(smb_ucs2_t));
+
+ p[num_chars] = (hinybble << 4) | lonybble;
+ num_chars++;
+
+ p1 = NULL;
+ p2 = NULL;
+ }
+ return num_chars;
+}
+
+/****************************************************************************
+ Check if a string is part of a list.
+****************************************************************************/
+
+BOOL in_list_w(smb_ucs2_t *s,smb_ucs2_t *list,BOOL casesensitive)
+{
+ wpstring tok;
+ smb_ucs2_t *p=list;
+
+ if (!list)
+ return(False);
+
+ while (next_token_w(&p,tok,LIST_SEP_W,sizeof(tok))) {
+ if (casesensitive) {
+ if (strcmp_w(tok,s) == 0)
+ return(True);
+ } else {
+ if (StrCaseCmp_w(tok,s) == 0)
+ return(True);
+ }
+ }
+ return(False);
+}
+
+/* This is used to prevent lots of mallocs of size 2 */
+static smb_ucs2_t *null_string = NULL;
+
+/****************************************************************************
+ Set a string value, allocing the space for the string.
+****************************************************************************/
+
+BOOL string_init_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
+{
+ size_t l;
+
+ if (!null_string) {
+ if((null_string = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t))) == NULL) {
+ DEBUG(0,("string_init_w: malloc fail for null_string.\n"));
+ return False;
+ }
+ *null_string = 0;
+ }
+
+ if (!src)
+ src = null_string;
+
+ l = strlen_w(src);
+
+ if (l == 0)
+ *dest = null_string;
+ else {
+ (*dest) = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t)*(l+1));
+ if ((*dest) == NULL) {
+ DEBUG(0,("Out of memory in string_init_w\n"));
+ return False;
+ }
+
+ wpstrcpy(*dest,src);
+ }
+ return(True);
+}
+
+/****************************************************************************
+ Free a string value.
+****************************************************************************/
+
+void string_free_w(smb_ucs2_t **s)
+{
+ if (!s || !(*s))
+ return;
+ if (*s == null_string)
+ *s = NULL;
+ if (*s)
+ free((char *)*s);
+ *s = NULL;
+}
+
+/****************************************************************************
+ Set a string value, allocing the space for the string, and deallocating any
+ existing space.
+****************************************************************************/
+
+BOOL string_set_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
+{
+ string_free_w(dest);
+
+ return(string_init_w(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.
+
+ Any of " ; ' $ or ` in the insert string are replaced with _
+ if len==0 then no length check is performed
+ len is in bytes.
+****************************************************************************/
+
+void string_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
+{
+ smb_ucs2_t *p;
+ ssize_t ls,lp,li, i;
+
+ /*
+ * Convert to smb_ucs2_t units.
+ */
+
+ len /= sizeof(smb_ucs2_t);
+
+ if (!insert || !pattern || !s)
+ return;
+
+ ls = (ssize_t)strlen_w(s);
+ lp = (ssize_t)strlen_w(pattern);
+ li = (ssize_t)strlen_w(insert);
+
+ if (!*pattern)
+ return;
+
+ while (lp <= ls && (p = strstr_w(s,pattern))) {
+ if (len && (ls + (li-lp) >= len)) {
+ fstring out;
+ DEBUG(0,("ERROR: string overflow by %d in string_sub_w(%.50s, %d)\n",
+ (int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
+ unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
+ break;
+ }
+ if (li != lp)
+ memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
+
+ for (i=0;i<li;i++) {
+ switch (insert[i]) {
+ case (smb_ucs2_t)'`':
+ case (smb_ucs2_t)'"':
+ case (smb_ucs2_t)'\'':
+ case (smb_ucs2_t)';':
+ case (smb_ucs2_t)'$':
+ case (smb_ucs2_t)'%':
+ case (smb_ucs2_t)'\r':
+ case (smb_ucs2_t)'\n':
+ p[i] = (smb_ucs2_t)'_';
+ break;
+ default:
+ p[i] = insert[i];
+ }
+ }
+ s = p + li;
+ ls += (li-lp);
+ }
+}
+
+void fstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert)
+{
+ string_sub_w(s, pattern, insert, sizeof(wfstring));
+}
+
+void pstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,smb_ucs2_t *insert)
+{
+ string_sub_w(s, pattern, insert, sizeof(wpstring));
+}
+
+/****************************************************************************
+ 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_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
+{
+ smb_ucs2_t *p;
+ ssize_t ls,lp,li;
+
+ /*
+ * Convert to smb_ucs2_t units.
+ */
+
+ len /= sizeof(smb_ucs2_t);
+
+ if (!insert || !pattern || !s)
+ return;
+
+ ls = (ssize_t)strlen_w(s);
+ lp = (ssize_t)strlen_w(pattern);
+ li = (ssize_t)strlen_w(insert);
+
+ if (!*pattern)
+ return;
+
+ while (lp <= ls && (p = strstr_w(s,pattern))) {
+ if (len && (ls + (li-lp) >= len)) {
+ fstring out;
+ DEBUG(0,("ERROR: string overflow by %d in all_string_sub_w(%.50s, %d)\n",
+ (int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
+ unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
+ break;
+ }
+ if (li != lp)
+ memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
+
+ memcpy(p, insert, li*sizeof(smb_ucs2_t));
+ s = p + li;
+ ls += (li-lp);
+ }
+}
+
+/****************************************************************************
+ Splits out the front and back at a separator.
+****************************************************************************/
+
+void split_at_last_component_w(smb_ucs2_t *path, smb_ucs2_t *front, smb_ucs2_t sep, smb_ucs2_t *back)
+{
+ smb_ucs2_t *p = strrchr_w(path, sep);
+
+ if (p != NULL)
+ *p = 0;
+
+ if (front != NULL)
+ wpstrcpy(front, path);
+
+ if (p != NULL) {
+ if (back != NULL)
+ wpstrcpy(back, p+1);
+ *p = (smb_ucs2_t)'\\';
+ } else {
+ if (back != NULL)
+ back[0] = 0;
+ }
+}
+
+
+/****************************************************************************
+ Write an octal as a string.
+****************************************************************************/
+
+smb_ucs2_t *octal_string_w(int i)
+{
+ static smb_ucs2_t wret[64];
+ char ret[64];
+
+ if (i == -1)
+ slprintf(ret, sizeof(ret), "-1");
+ else
+ slprintf(ret, sizeof(ret), "0%o", i);
+ return unix_to_unicode(wret, ret, sizeof(wret));
+}
+
+
+/****************************************************************************
+ Truncate a string at a specified length.
+ length is in bytes.
+****************************************************************************/
+
+smb_ucs2_t *string_truncate_w(smb_ucs2_t *s, size_t length)
+{
+ /*
+ * Convert to smb_ucs2_t units.
+ */
+
+ length /= sizeof(smb_ucs2_t);
+
+ if (s && strlen_w(s) > length)
+ s[length] = 0;
+
+ return s;
+}