/*
Unix SMB/CIFS implementation.
Samba utility functions
+
Copyright (C) Andrew Tridgell 1992-2001
Copyright (C) Simo Sorce 2001-2002
+ Copyright (C) Martin Pool 2003
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
*/
#include "includes.h"
+#include "system/iconv.h"
+#include "pstring.h"
+#include "lib/ldb/include/ldb.h"
+
+/**
+ * @file
+ * @brief String utilities.
+ **/
/**
* Get the next token from a string, return False if none found.
}
/**
-This is like next_token but is not re-entrant and "remembers" the first
-parameter so you can pass NULL. This is useful for user interface code
-but beware the fact that it is not re-entrant!
+ Case insensitive string compararison
**/
-
-static char *last_ptr=NULL;
-
-BOOL next_token_nr(const char **ptr, char *buff, const char *sep, size_t bufsize)
-{
- BOOL ret;
- if (!ptr)
- ptr = (const char **)&last_ptr;
-
- ret = next_token(ptr, buff, sep, bufsize);
- last_ptr = *ptr;
- return ret;
-}
-
-static uint16 tmpbuf[sizeof(pstring)];
-
-void set_first_token(char *ptr)
+int strcasecmp_m(const char *s1, const char *s2)
{
- last_ptr = ptr;
-}
-
-/**
- Convert list of tokens to array; dependent on above routine.
- Uses last_ptr from above - bit of a hack.
-**/
+ codepoint_t c1=0, c2=0;
+ size_t size1, size2;
-char **toktocliplist(int *ctok, const char *sep)
-{
- char *s=last_ptr;
- int ictok=0;
- char **ret, **iret;
+ while (*s1 && *s2) {
+ c1 = next_codepoint(s1, &size1);
+ c2 = next_codepoint(s2, &size2);
- if (!sep)
- sep = " \t\n\r";
+ s1 += size1;
+ s2 += size2;
- while(*s && strchr_m(sep,*s))
- s++;
+ if (c1 == c2) {
+ continue;
+ }
- /* nothing left? */
- if (!*s)
- return(NULL);
+ if (c1 == INVALID_CODEPOINT ||
+ c2 == INVALID_CODEPOINT) {
+ /* what else can we do?? */
+ return c1 - c2;
+ }
- do {
- ictok++;
- while(*s && (!strchr_m(sep,*s)))
- s++;
- while(*s && strchr_m(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++;
+ if (toupper_w(c1) != toupper_w(c2)) {
+ return c1 - c2;
+ }
}
- return ret;
-}
-
-/**
- Case insensitive string compararison.
-**/
-
-int StrCaseCmp(const char *s, const char *t)
-{
- pstring buf1, buf2;
- unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
- unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
- return strcmp(buf1,buf2);
-}
-
-/**
- Case insensitive string compararison, length limited.
-**/
-
-int StrnCaseCmp(const char *s, const char *t, size_t n)
-{
- pstring buf1, buf2;
- unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
- unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
- return strncmp(buf1,buf2,n);
+ return *s1 - *s2;
}
/**
if (!s1 || !s2)
return(False);
- return(StrCaseCmp(s1,s2)==0);
-}
-
-/**
- * Compare 2 strings up to and including the nth char.
- *
- * @note The comparison is case-insensitive.
- **/
-BOOL strnequal(const char *s1,const char *s2,size_t n)
-{
- if (s1 == s2)
- return(True);
- if (!s1 || !s2 || !n)
- return(False);
-
- return(StrnCaseCmp(s1,s2,n)==0);
+ 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);
+ 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 */
psz1++;
while (isspace((int)*psz2))
psz2++;
- if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
+ if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2)
+ || *psz1 == '\0'
|| *psz2 == '\0')
break;
psz1++;
return (*psz1 - *psz2);
}
-/**
- Convert a string to upper case, but don't modify it.
-**/
-
-char *strupper_talloc(TALLOC_CTX *mem_ctx, const char *s)
-{
- char *str;
-
- str = talloc_strdup(mem_ctx, s);
- strupper(str);
-
- return str;
-}
-
-
/**
String replace.
NOTE: oldc and newc must be 7 bit characters
**/
-
-void string_replace(char *s,char oldc,char newc)
+void string_replace(char *s, char oldc, char newc)
{
- if (strchr(s, oldc)) {
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
- pull_ucs2(NULL, s, tmpbuf, strlen(s)+1, sizeof(tmpbuf), STR_TERMINATE);
+ while (*s) {
+ size_t size;
+ codepoint_t c = next_codepoint(s, &size);
+ if (c == oldc) {
+ *s = newc;
+ }
+ s += size;
}
}
-/**
- Skip past some strings in a buffer.
-**/
-
-char *skip_string(char *buf,size_t 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.
-**/
-
-size_t str_charnum(const char *s)
-{
- uint16 tmpbuf2[sizeof(pstring)];
- push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
- return strlen_w(tmpbuf2);
-}
-
-/**
- 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.
-**/
-
-size_t str_ascii_charnum(const char *s)
-{
- pstring tmpbuf2;
- push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
- return strlen(tmpbuf2);
-}
-
/**
Trim the specified elements off the front and back of a string.
**/
-
BOOL trim_string(char *s,const char *front,const char *back)
{
BOOL ret = False;
if (front_len) {
while (len && strncmp(s, front, front_len)==0) {
- memcpy(s, s+front_len, (len-front_len)+1);
+ /* Must use memmove here as src & dest can
+ * easily overlap. Found by valgrind. JRA. */
+ memmove(s, s+front_len, (len-front_len)+1);
len -= front_len;
ret=True;
}
return ret;
}
-/**
- Does a string have any uppercase chars in it?
-**/
-
-BOOL strhasupper(const char *s)
-{
- smb_ucs2_t *ptr;
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- for(ptr=tmpbuf;*ptr;ptr++)
- if(isupper_w(*ptr))
- return True;
- return(False);
-}
-
-/**
- Does a string have any lowercase chars in it?
-**/
-
-BOOL strhaslower(const char *s)
-{
- smb_ucs2_t *ptr;
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- for(ptr=tmpbuf;*ptr;ptr++)
- if(islower_w(*ptr))
- return True;
- return(False);
-}
-
/**
Find the number of 'c' chars in a string
**/
-
-size_t count_chars(const char *s,char c)
-{
- smb_ucs2_t *ptr;
- int count;
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- for(count=0,ptr=tmpbuf;*ptr;ptr++)
- if(*ptr==UCS2_CHAR(c))
- count++;
- return(count);
-}
-
-/**
-Return True if a string consists only of one particular character.
-**/
-
-BOOL str_is_all(const char *s,char c)
+size_t count_chars(const char *s, char c)
{
- smb_ucs2_t *ptr;
+ size_t count = 0;
- if(s == NULL)
- return False;
- if(!*s)
- return False;
-
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- for(ptr=tmpbuf;*ptr;ptr++)
- if(*ptr!=UCS2_CHAR(c))
- return False;
+ while (*s) {
+ size_t size;
+ codepoint_t c2 = next_codepoint(s, &size);
+ if (c2 == c) count++;
+ s += size;
+ }
- return True;
+ 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)
{
size_t len;
if (len > maxlength) {
DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
- (unsigned int)(len-maxlength), len, maxlength, src));
+ (uint_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src));
len = 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;
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, const char *src, size_t n, char c)
-{
- char *p;
- size_t str_len;
-
- p = strchr_m(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;
-}
/**
Routine to get hex characters and turn them into a 16 byte array.
valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
-**/
+**/
size_t strhex_to_str(char *p, size_t len, const char *strhex)
{
size_t i;
size_t num_chars = 0;
- unsigned char lonybble, hinybble;
+ uint8_t lonybble, hinybble;
const char *hexchars = "0123456789ABCDEF";
char *p1 = NULL, *p2 = NULL;
for (i = 0; i < len && strhex[i] != 0; i++) {
- if (strnequal(hexchars, "0x", 2)) {
+ if (strncasecmp(hexchars, "0x", 2) == 0) {
i++; /* skip two chars */
continue;
}
- if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
+ if (!(p1 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
break;
i++; /* next hex digit */
- if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
+ if (!(p2 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
break;
/* get the two nybbles */
return num_chars;
}
+DATA_BLOB strhex_to_data_blob(const char *strhex)
+{
+ DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1);
+
+ ret_blob.length = strhex_to_str(ret_blob.data,
+ strlen(strhex),
+ strhex);
+
+ return ret_blob;
+}
+
+
+/**
+ * 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)
+{
+ int i;
+ char *hex_buffer;
+
+ *out_hex_buffer = smb_xmalloc((len*2)+1);
+ hex_buffer = *out_hex_buffer;
+
+ for (i = 0; i < len; i++)
+ slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
+}
+
/**
Check if a string is part of a list.
**/
-
BOOL in_list(const char *s, const char *list, BOOL casesensitive)
{
pstring tok;
if (strcmp(tok,s) == 0)
return(True);
} else {
- if (StrCaseCmp(tok,s) == 0)
+ if (strcasecmp_m(tok,s) == 0)
return(True);
}
}
}
}
-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 it will accept only allocated strings
- and may realloc them so pay attention at what you pass on no
- pointers inside strings, no pstrings or const may be passed
- as string.
-**/
-
-char *realloc_string_sub(char *string, const char *pattern, const char *insert)
-{
- char *p, *in;
- char *s;
- ssize_t ls,lp,li,ld, i;
-
- if (!insert || !pattern || !*pattern || !string || !*string)
- return NULL;
-
- s = string;
-
- in = strdup(insert);
- if (!in) {
- DEBUG(0, ("realloc_string_sub: out of memory!\n"));
- return NULL;
- }
- ls = (ssize_t)strlen(s);
- lp = (ssize_t)strlen(pattern);
- li = (ssize_t)strlen(insert);
- ld = li - lp;
- for (i=0;i<li;i++) {
- switch (in[i]) {
- case '`':
- case '"':
- case '\'':
- case ';':
- case '$':
- case '%':
- case '\r':
- case '\n':
- in[i] = '_';
- default:
- /* ok */
- break;
- }
- }
-
- while ((p = strstr(s,pattern))) {
- if (ld > 0) {
- char *t = Realloc(string, ls + ld + 1);
- if (!t) {
- DEBUG(0, ("realloc_string_sub: out of memory!\n"));
- SAFE_FREE(in);
- return NULL;
- }
- string = t;
- p = t + (p - s);
- }
- if (li != lp) {
- memmove(p+li,p+lp,strlen(p+lp)+1);
- }
- memcpy(p, in, li);
- s = p + li;
- ls += ld;
- }
- SAFE_FREE(in);
- return string;
-}
/**
Similar to string_sub() but allows for any character to be substituted.
}
}
+
/**
- Similar to all_string_sub but for unicode strings.
- Return a new allocated unicode string.
- similar to string_sub() but allows for any character to be substituted.
- Use with caution!
+ Strchr and strrchr_m are a bit complex on general multi-byte strings.
**/
-
-smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
- const smb_ucs2_t *insert)
+char *strchr_m(const char *s, char c)
{
- smb_ucs2_t *r, *rp;
- const smb_ucs2_t *sp;
- size_t lr, lp, li, lt;
-
- if (!insert || !pattern || !*pattern || !s)
- return NULL;
-
- lt = (size_t)strlen_w(s);
- lp = (size_t)strlen_w(pattern);
- li = (size_t)strlen_w(insert);
+ /* characters below 0x3F are guaranteed to not appear in
+ non-initial position in multi-byte charsets */
+ if ((c & 0xC0) == 0) {
+ return strchr(s, c);
+ }
- if (li > lp) {
- const smb_ucs2_t *st = s;
- int ld = li - lp;
- while ((sp = strstr_w(st, pattern))) {
- st = sp + lp;
- lt += ld;
+ while (*s) {
+ size_t size;
+ codepoint_t c2 = next_codepoint(s, &size);
+ if (c2 == c) {
+ return discard_const(s);
}
+ s += size;
}
- r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
- if (!r) {
- DEBUG(0, ("all_string_sub_w: out of memory!\n"));
- return NULL;
- }
+ return NULL;
+}
- while ((sp = strstr_w(s, pattern))) {
- memcpy(rp, s, (sp - s));
- rp += ((sp - s) / sizeof(smb_ucs2_t));
- memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
- s = sp + lp;
- rp += li;
+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);
}
- lr = ((rp - r) / sizeof(smb_ucs2_t));
- if (lr < lt) {
- memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
- rp += (lt - lr);
+
+ while (*s) {
+ size_t size;
+ codepoint_t c2 = next_codepoint(s, &size);
+ if (c2 == c) {
+ ret = discard_const(s);
+ }
+ s += size;
}
- *rp = 0;
- return r;
+ return ret;
}
-smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
- const char *insert)
+/*
+ return True if any (multi-byte) character is lower case
+*/
+BOOL strhaslower(const char *string)
{
- wpstring p, i;
+ while (*string) {
+ size_t c_size;
+ codepoint_t s;
+ codepoint_t t;
- if (!insert || !pattern || !s)
- return NULL;
- push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
- push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
- return all_string_sub_w(s, p, i);
-}
+ s = next_codepoint(string, &c_size);
+ string += c_size;
-/**
- Splits out the front and back at a separator.
-**/
+ t = toupper_w(s);
-void split_at_last_component(char *path, char *front, char sep, char *back)
+ 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)
{
- char *p = strrchr_m(path, sep);
+ while (*string) {
+ size_t c_size;
+ codepoint_t s;
+ codepoint_t t;
- if (p != NULL)
- *p = 0;
+ s = next_codepoint(string, &c_size);
+ string += c_size;
- if (front != NULL)
- pstrcpy(front, path);
+ t = tolower_w(s);
- if (p != NULL) {
- if (back != NULL)
- pstrcpy(back, p+1);
- *p = '\\';
- } else {
- if (back != NULL)
- back[0] = 0;
+ if (s != t) {
+ return True; /* that means it has upper case chars */
+ }
}
-}
+
+ return False;
+}
/**
- Write an octal as a string.
+ Convert a string to lower case, allocated with talloc
**/
-
-const char *octal_string(int i)
+char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
{
- static char ret[64];
- if (i == -1)
- return "-1";
- slprintf(ret, sizeof(ret)-1, "0%o", i);
- return ret;
-}
+ 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;
+ }
-/**
- Truncate a string at a specified length.
-**/
+ while (*src) {
+ size_t c_size;
+ codepoint_t c = next_codepoint(src, &c_size);
+ src += c_size;
-char *string_truncate(char *s, int length)
-{
- if (s && strlen(s) > length)
- s[length] = 0;
- return s;
+ 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;
}
/**
- Strchr and strrchr_m are very hard to do on general multi-byte strings.
- We convert via ucs2 for now.
+ Convert a string to UPPER case, allocated with talloc
**/
-
-char *strchr_m(const char *s, char c)
+char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
{
- wpstring ws;
- pstring s2;
- smb_ucs2_t *p;
+ size_t size=0;
+ char *dest;
+
+ if (!src) {
+ return NULL;
+ }
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
- p = strchr_w(ws, UCS2_CHAR(c));
- if (!p)
+ /* 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;
- *p = 0;
- pull_ucs2_pstring(s2, ws);
- return (char *)(s+strlen(s2));
-}
+ }
-char *strrchr_m(const char *s, char c)
-{
- wpstring ws;
- pstring s2;
- smb_ucs2_t *p;
+ while (*src) {
+ size_t c_size;
+ codepoint_t c = next_codepoint(src, &c_size);
+ src += c_size;
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
- p = strrchr_w(ws, UCS2_CHAR(c));
- if (!p)
- return NULL;
- *p = 0;
- pull_ucs2_pstring(s2, ws);
- return (char *)(s+strlen(s2));
+ 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 && !(((unsigned char)s[0]) & 0x7F)) {
- *s = tolower((unsigned char)*s);
+ while (*s && !(((uint8_t)s[0]) & 0x7F)) {
+ *s = tolower((uint8_t)*s);
s++;
}
if (!*s)
return;
- /* I assume that lowercased string takes the same number of bytes
- * as source string even in UTF-8 encoding. (VIV) */
- unix_strlower(s,strlen(s)+1,s,strlen(s)+1);
-}
-
-/**
- Duplicate convert a string to lower case.
-**/
+ d = s;
-char *strdup_lower(const char *s)
-{
- char *t = strdup(s);
- if (t == NULL) {
- DEBUG(0, ("strdup_lower: Out of memory!\n"));
- return NULL;
+ 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;
}
- strlower_m(t);
- return t;
+ *d = 0;
}
/**
- Convert a string to upper case.
+ 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 && !(((unsigned char)s[0]) & 0x7F)) {
- *s = toupper((unsigned char)*s);
+ while (*s && !(((uint8_t)s[0]) & 0x7F)) {
+ *s = toupper((uint8_t)*s);
s++;
}
if (!*s)
return;
- /* I assume that lowercased string takes the same number of bytes
- * as source string even in multibyte encoding. (VIV) */
- unix_strupper(s,strlen(s)+1,s,strlen(s)+1);
-}
+ 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;
+}
/**
- work out the number of multibyte chars in a string
+ 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)
{
return 0;
}
- while (*s && !(((unsigned char)s[0]) & 0x7F)) {
+ while (*s && !(((uint8_t)s[0]) & 0x7F)) {
s++;
count++;
}
return count;
}
- push_ucs2(NULL,tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- return count + strlen_w(tmpbuf);
+ 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;
}
/**
return strlen_m(s) + 1;
}
-/**
- Convert a string to upper case.
-**/
-
-char *strdup_upper(const char *s)
-{
- char *t = strdup(s);
- if (t == NULL) {
- DEBUG(0, ("strdup_upper: Out of memory!\n"));
- return NULL;
- }
- strupper_m(t);
- return t;
-}
-
-/**
- Return a RFC2254 binary string representation of a buffer.
- Used in LDAP filters.
- Caller must free.
-**/
-
-char *binary_string(char *buf, int len)
-{
- char *s;
- int i, j;
- const char *hex = "0123456789ABCDEF";
- s = malloc(len * 3 + 1);
- if (!s)
- return NULL;
- for (j=i=0;i<len;i++) {
- s[j] = '\\';
- s[j+1] = hex[((unsigned char)buf[i]) >> 4];
- s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
- j += 3;
- }
- s[j] = 0;
- return s;
-}
-
-/**
- Just a typesafety wrapper for snprintf into a pstring.
-**/
-
- int pstr_sprintf(pstring s, const char *fmt, ...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, fmt);
- ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-/**
- Just a typesafety wrapper for snprintf into a fstring.
-**/
-
- int fstr_sprintf(fstring s, const char *fmt, ...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, fmt);
- ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-#ifndef HAVE_STRNDUP
-/**
- Some platforms don't have strndup.
-**/
-
- char *strndup(const char *s, size_t n)
-{
- char *ret;
-
- n = strnlen(s, n);
- ret = malloc(n+1);
- if (!ret)
- return NULL;
- memcpy(ret, s, n);
- ret[n] = 0;
-
- return ret;
-}
-#endif
-
-#ifndef HAVE_STRNLEN
-/**
- Some platforms don't have strnlen
-**/
-
- size_t strnlen(const char *s, size_t n)
-{
- int i;
- for (i=0; s[i] && i<n; i++)
- /* noop */ ;
- return i;
-}
-#endif
-
-/**
- List of Strings manipulation functions
-**/
-
-#define S_LIST_ABS 16 /* List Allocation Block Size */
-
-char **str_list_make(const char *string, const char *sep)
-{
- char **list, **rlist;
- const char *str;
- char *s;
- int num, lsize;
- pstring tok;
-
- if (!string || !*string)
- return NULL;
- s = strdup(string);
- if (!s) {
- DEBUG(0,("str_list_make: Unable to allocate memory"));
- return NULL;
- }
- if (!sep) sep = LIST_SEP;
-
- num = lsize = 0;
- list = NULL;
-
- str = s;
- while (next_token(&str, tok, sep, sizeof(tok))) {
- if (num == lsize) {
- lsize += S_LIST_ABS;
- rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
- if (!rlist) {
- DEBUG(0,("str_list_make: Unable to allocate memory"));
- str_list_free(&list);
- SAFE_FREE(s);
- return NULL;
- } else
- list = rlist;
- memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
- }
-
- list[num] = strdup(tok);
- if (!list[num]) {
- DEBUG(0,("str_list_make: Unable to allocate memory"));
- str_list_free(&list);
- SAFE_FREE(s);
- return NULL;
- }
-
- num++;
- }
-
- SAFE_FREE(s);
- return list;
-}
-
-BOOL str_list_copy(char ***dest, const char **src)
-{
- char **list, **rlist;
- int num, lsize;
-
- *dest = NULL;
- if (!src)
- return False;
-
- num = lsize = 0;
- list = NULL;
-
- while (src[num]) {
- if (num == lsize) {
- lsize += S_LIST_ABS;
- rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
- if (!rlist) {
- DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
- str_list_free(&list);
- return False;
- } else
- list = rlist;
- memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
- }
-
- list[num] = strdup(src[num]);
- if (!list[num]) {
- DEBUG(0,("str_list_copy: Unable to allocate memory"));
- str_list_free(&list);
- return False;
- }
-
- num++;
- }
-
- *dest = list;
- return True;
-}
-
-/**
- * Return true if all the elements of the list match exactly.
- **/
-BOOL str_list_compare(char **list1, char **list2)
-{
- int num;
-
- if (!list1 || !list2)
- return (list1 == list2);
-
- for (num = 0; list1[num]; num++) {
- if (!list2[num])
- return False;
- if (!strcsequal(list1[num], list2[num]))
- return False;
- }
- if (list2[num])
- return False; /* if list2 has more elements than list1 fail */
-
- return True;
-}
-
-void str_list_free(char ***list)
-{
- char **tlist;
-
- if (!list || !*list)
- return;
- tlist = *list;
- for(; *tlist; tlist++)
- SAFE_FREE(*tlist);
- SAFE_FREE(*list);
-}
-
-BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
-{
- char *p, *s, *t;
- ssize_t ls, lp, li, ld, i, d;
-
- if (!list)
- return False;
- if (!pattern)
- return False;
- if (!insert)
- return False;
-
- lp = (ssize_t)strlen(pattern);
- li = (ssize_t)strlen(insert);
- ld = li -lp;
-
- while (*list) {
- s = *list;
- ls = (ssize_t)strlen(s);
-
- while ((p = strstr(s, pattern))) {
- t = *list;
- d = p -t;
- if (ld) {
- t = (char *) malloc(ls +ld +1);
- if (!t) {
- DEBUG(0,("str_list_substitute: Unable to allocate memory"));
- return False;
- }
- memcpy(t, *list, d);
- memcpy(t +d +li, p +lp, ls -d -lp +1);
- SAFE_FREE(*list);
- *list = t;
- ls += ld;
- s = t +d +li;
- }
-
- for (i = 0; i < li; i++) {
- switch (insert[i]) {
- case '`':
- case '"':
- case '\'':
- case ';':
- case '$':
- case '%':
- case '\r':
- case '\n':
- t[d +i] = '_';
- break;
- default:
- t[d +i] = insert[i];
- }
- }
- }
-
- list++;
- }
-
- return True;
-}
-
-
-#define IPSTR_LIST_SEP ","
-
-/**
- * Add ip string representation to ipstr list. Used also
- * as part of @function ipstr_list_make
- *
- * @param ipstr_list pointer to string containing ip list;
- * MUST BE already allocated and IS reallocated if necessary
- * @param ipstr_size pointer to current size of ipstr_list (might be changed
- * as a result of reallocation)
- * @param ip IP address which is to be added to list
- * @return pointer to string appended with new ip and possibly
- * reallocated to new length
- **/
-
-char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip)
-{
- char* new_ipstr = NULL;
-
- /* arguments checking */
- if (!ipstr_list || !ip) return NULL;
-
- /* attempt to convert ip to a string and append colon separator to it */
- if (*ipstr_list) {
- asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip));
- SAFE_FREE(*ipstr_list);
- } else {
- asprintf(&new_ipstr, "%s", inet_ntoa(*ip));
- }
- *ipstr_list = new_ipstr;
- return *ipstr_list;
-}
-
-
-/**
- * Allocate and initialise an ipstr list using ip adresses
- * passed as arguments.
- *
- * @param ipstr_list pointer to string meant to be allocated and set
- * @param ip_list array of ip addresses to place in the list
- * @param ip_count number of addresses stored in ip_list
- * @return pointer to allocated ip string
- **/
-
-char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count)
-{
- int i;
-
- /* arguments checking */
- if (!ip_list && !ipstr_list) return 0;
-
- *ipstr_list = NULL;
-
- /* process ip addresses given as arguments */
- for (i = 0; i < ip_count; i++)
- *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
-
- return (*ipstr_list);
-}
-
-
-/**
- * Parse given ip string list into array of ip addresses
- * (as in_addr structures)
- *
- * @param ipstr ip string list to be parsed
- * @param ip_list pointer to array of ip addresses which is
- * allocated by this function and must be freed by caller
- * @return number of succesfully parsed addresses
- **/
-
-int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list)
-{
- fstring token_str;
- int count;
-
- if (!ipstr_list || !ip_list) return 0;
-
- for (*ip_list = NULL, count = 0;
- next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
- count++) {
-
- struct in_addr addr;
-
- /* convert single token to ip address */
- if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
- break;
-
- /* prepare place for another in_addr structure */
- *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr));
- if (!*ip_list) return -1;
-
- (*ip_list)[count] = addr;
- }
-
- return count;
-}
-
-
-/**
- * Safely free ip string list
- *
- * @param ipstr_list ip string list to be freed
- **/
-
-void ipstr_list_free(char* ipstr_list)
-{
- SAFE_FREE(ipstr_list);
-}
-
-
/**
Unescape a URL encoded string, in place.
**/
}
}
-static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
/**
* Decode a base64 string into a DATA_BLOB - simple and slow algorithm
**/
-DATA_BLOB base64_decode_data_blob(const char *s)
+DATA_BLOB base64_decode_data_blob(TALLOC_CTX *mem_ctx, const char *s)
{
- int bit_offset, byte_offset, idx, i, n;
- DATA_BLOB decoded = data_blob(s, strlen(s)+1);
- unsigned char *d = decoded.data;
- char *p;
-
- n=i=0;
-
- while (*s && (p=strchr_m(b64,*s))) {
- idx = (int)(p - b64);
- byte_offset = (i*6)/8;
- bit_offset = (i*6)%8;
- d[byte_offset] &= ~((1<<(8-bit_offset))-1);
- if (bit_offset < 3) {
- d[byte_offset] |= (idx << (2-bit_offset));
- n = byte_offset+1;
- } else {
- d[byte_offset] |= (idx >> (bit_offset-2));
- d[byte_offset+1] = 0;
- d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
- n = byte_offset+2;
- }
- s++; i++;
- }
-
- /* fix up length */
- decoded.length = n;
- return decoded;
+ DATA_BLOB ret = data_blob_talloc(mem_ctx, s, strlen(s)+1);
+ ret.length = ldb_base64_decode(ret.data);
+ return ret;
}
/**
**/
void base64_decode_inplace(char *s)
{
- DATA_BLOB decoded = base64_decode_data_blob(s);
- memcpy(s, decoded.data, decoded.length);
- data_blob_free(&decoded);
-
- /* null terminate */
- s[decoded.length] = '\0';
+ ldb_base64_decode(s);
}
/**
- * Encode a base64 string into a malloc()ed string caller to free.
- *
- *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
+ * Encode a base64 string into a talloc()ed string caller to free.
**/
-char * base64_encode_data_blob(DATA_BLOB data)
+char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
{
- int bits = 0;
- int char_count = 0;
- size_t out_cnt = 0;
- size_t len = data.length;
- size_t output_len = data.length * 2;
- char *result = malloc(output_len); /* get us plenty of space */
-
- while (len-- && out_cnt < (data.length * 2) - 5) {
- int c = (unsigned char) *(data.data++);
- bits += c;
- char_count++;
- if (char_count == 3) {
- result[out_cnt++] = b64[bits >> 18];
- result[out_cnt++] = b64[(bits >> 12) & 0x3f];
- result[out_cnt++] = b64[(bits >> 6) & 0x3f];
- result[out_cnt++] = b64[bits & 0x3f];
- bits = 0;
- char_count = 0;
- } else {
- bits <<= 8;
- }
- }
- if (char_count != 0) {
- bits <<= 16 - (8 * char_count);
- result[out_cnt++] = b64[bits >> 18];
- result[out_cnt++] = b64[(bits >> 12) & 0x3f];
- if (char_count == 1) {
- result[out_cnt++] = '=';
- result[out_cnt++] = '=';
- } else {
- result[out_cnt++] = b64[(bits >> 6) & 0x3f];
- result[out_cnt++] = '=';
- }
- }
- result[out_cnt] = '\0'; /* terminate */
- return result;
+ return ldb_base64_encode(mem_ctx, data.data, data.length);
}
#ifdef VALGRIND
return count;
}
#endif
+
+
+/*
+ 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)
+{
+ char *ret;
+ int i;
+ if (!s || !*s) {
+ return talloc_strdup(mem_ctx, "");
+ }
+ ret = talloc_size(mem_ctx, strlen(s)+2);
+ if (!ret) {
+ return ret;
+ }
+
+ memcpy(ret+1, s, strlen(s)+1);
+ ret[0] = '.';
+
+ for (i=0;ret[i];i++) {
+ if (ret[i] == '.') {
+ char *p = strchr(ret+i+1, '.');
+ if (p) {
+ ret[i] = p-(ret+i+1);
+ } else {
+ ret[i] = strlen(ret+i+1);
+ }
+ }
+ }
+
+ return ret;
+}
+
+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);
+
+ *strings = talloc_realloc(mem_ctx,
+ *strings,
+ const char *, ((*num)+1));
+
+ if ((*strings == NULL) || (dup_str == NULL))
+ return False;
+
+ (*strings)[*num] = dup_str;
+ *num += 1;
+
+ return True;
+}
+
+
+
+/*
+ varient of strcmp() that handles NULL ptrs
+*/
+int strcmp_safe(const char *s1, const char *s2)
+{
+ if (s1 == s2) {
+ return 0;
+ }
+ if (s1 == NULL || s2 == NULL) {
+ return s1?-1:1;
+ }
+ return strcmp(s1, s2);
+}
+
+
+/*******************************************************************
+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)
+{
+ size_t len;
+
+ len = strnlen(src, n);
+ if (len+1 <= n) {
+ len += 1;
+ }
+
+ return len;
+}
+
+
+/*******************************************************************
+ Return a string representing a CIFS attribute for a file.
+********************************************************************/
+char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib)
+{
+ int i, len;
+ const struct {
+ char c;
+ uint16_t attr;
+ } attr_strs[] = {
+ {'V', FILE_ATTRIBUTE_VOLUME},
+ {'D', FILE_ATTRIBUTE_DIRECTORY},
+ {'A', FILE_ATTRIBUTE_ARCHIVE},
+ {'H', FILE_ATTRIBUTE_HIDDEN},
+ {'S', FILE_ATTRIBUTE_SYSTEM},
+ {'N', FILE_ATTRIBUTE_NORMAL},
+ {'R', FILE_ATTRIBUTE_READONLY},
+ {'d', FILE_ATTRIBUTE_DEVICE},
+ {'t', FILE_ATTRIBUTE_TEMPORARY},
+ {'s', FILE_ATTRIBUTE_SPARSE},
+ {'r', FILE_ATTRIBUTE_REPARSE_POINT},
+ {'c', FILE_ATTRIBUTE_COMPRESSED},
+ {'o', FILE_ATTRIBUTE_OFFLINE},
+ {'n', FILE_ATTRIBUTE_NONINDEXED},
+ {'e', FILE_ATTRIBUTE_ENCRYPTED}
+ };
+ char *ret;
+
+ ret = talloc_size(mem_ctx, ARRAY_SIZE(attr_strs)+1);
+ if (!ret) {
+ return NULL;
+ }
+
+ for (len=i=0; i<ARRAY_SIZE(attr_strs); i++) {
+ if (attrib & attr_strs[i].attr) {
+ ret[len++] = attr_strs[i].c;
+ }
+ }
+
+ ret[len] = 0;
+
+ return ret;
+}