summaryrefslogtreecommitdiff
path: root/source4/lib/util_str.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/util_str.c')
-rw-r--r--source4/lib/util_str.c325
1 files changed, 173 insertions, 152 deletions
diff --git a/source4/lib/util_str.c b/source4/lib/util_str.c
index faa8690849..a71a9ee703 100644
--- a/source4/lib/util_str.c
+++ b/source4/lib/util_str.c
@@ -1,8 +1,10 @@
/*
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
@@ -22,6 +24,11 @@
#include "includes.h"
/**
+ * @file
+ * @brief String utilities.
+ **/
+
+/**
* Get the next token from a string, return False if none found.
* Handles double-quotes.
*
@@ -120,19 +127,20 @@ char **toktocliplist(const char *ptr, int *ctok, const char *sep)
**/
static int StrCaseCmp_slow(const char *s1, const char *s2)
{
- smb_ucs2_t *u1, *u2;
+ smb_ucs2_t *u1 = NULL;
+ smb_ucs2_t *u2;
int ret;
- if (convert_string_allocate(CH_UNIX, CH_UTF16, s1, strlen(s1)+1, &u1) == -1 ||
- convert_string_allocate(CH_UNIX, CH_UTF16, s2, strlen(s2)+1, &u2) == -1) {
+ if (convert_string_talloc(NULL, CH_UNIX, CH_UTF16, s1, strlen(s1)+1, (void **)&u1) == -1 ||
+ convert_string_talloc(u1, CH_UNIX, CH_UTF16, s2, strlen(s2)+1, (void **)&u2) == -1) {
+ talloc_free(u1);
/* fallback to a simple comparison */
return strcasecmp(s1, s2);
}
ret = strcasecmp_w(u1, u2);
- free(u1);
- free(u2);
+ talloc_free(u1);
return ret;
}
@@ -221,21 +229,6 @@ int strwicmp(const char *psz1, const char *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
**/
@@ -243,39 +236,13 @@ char *strupper_talloc(TALLOC_CTX *mem_ctx, const char *s)
void string_replace(char *s,char oldc,char newc)
{
if (strchr(s, oldc)) {
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
+ push_ucs2(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);
+ pull_ucs2(s, tmpbuf, strlen(s)+1, sizeof(tmpbuf), STR_TERMINATE);
}
}
/**
- 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_t 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.
**/
@@ -297,7 +264,9 @@ BOOL trim_string(char *s,const char *front,const char *back)
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;
}
@@ -320,7 +289,7 @@ BOOL trim_string(char *s,const char *front,const char *back)
BOOL strhasupper(const char *s)
{
smb_ucs2_t *ptr;
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
+ push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
for(ptr=tmpbuf;*ptr;ptr++)
if(isupper_w(*ptr))
return True;
@@ -334,7 +303,7 @@ BOOL strhasupper(const char *s)
BOOL strhaslower(const char *s)
{
smb_ucs2_t *ptr;
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
+ push_ucs2(tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
for(ptr=tmpbuf;*ptr;ptr++)
if(islower_w(*ptr))
return True;
@@ -349,10 +318,17 @@ 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++)
+ smb_ucs2_t *alloc_tmpbuf = NULL;
+
+ if (push_ucs2_talloc(NULL, &alloc_tmpbuf, s) == (size_t)-1) {
+ return 0;
+ }
+
+ for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
if(*ptr==UCS2_CHAR(c))
count++;
+
+ talloc_free(alloc_tmpbuf);
return(count);
}
@@ -507,6 +483,78 @@ char *StrnCpy(char *dest,const char *src,size_t n)
/**
+ 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.
+
+ 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;
+ uint8_t lonybble, hinybble;
+ const char *hexchars = "0123456789ABCDEF";
+ char *p1 = NULL, *p2 = NULL;
+
+ for (i = 0; i < len && strhex[i] != 0; i++) {
+ if (strncasecmp(hexchars, "0x", 2) == 0) {
+ i++; /* skip two chars */
+ continue;
+ }
+
+ if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
+ break;
+
+ i++; /* next hex digit */
+
+ if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
+ break;
+
+ /* get the two nybbles */
+ hinybble = PTR_DIFF(p1, hexchars);
+ lonybble = PTR_DIFF(p2, hexchars);
+
+ p[num_chars] = (hinybble << 4) | lonybble;
+ num_chars++;
+
+ p1 = NULL;
+ p2 = NULL;
+ }
+ 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.
**/
@@ -688,7 +736,7 @@ char *strchr_m(const char *s, char c)
pstring s2;
smb_ucs2_t *p;
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
+ push_ucs2(ws, s, sizeof(ws), STR_TERMINATE);
p = strchr_w(ws, UCS2_CHAR(c));
if (!p)
return NULL;
@@ -703,7 +751,7 @@ char *strrchr_m(const char *s, char c)
pstring s2;
smb_ucs2_t *p;
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
+ push_ucs2(ws, s, sizeof(ws), STR_TERMINATE);
p = strrchr_w(ws, UCS2_CHAR(c));
if (!p)
return NULL;
@@ -713,11 +761,54 @@ char *strrchr_m(const char *s, char c)
}
/**
+ Convert a string to lower case, allocated with talloc
+**/
+
+char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
+{
+ size_t size;
+ smb_ucs2_t *buffer;
+ char *dest;
+
+ size = push_ucs2_talloc(ctx, &buffer, src);
+ if (size == -1) {
+ return NULL;
+ }
+ strlower_w(buffer);
+
+ size = pull_ucs2_talloc(ctx, &dest, buffer);
+ talloc_free(buffer);
+ return dest;
+}
+
+/**
+ Convert a string to UPPER case, allocated with talloc
+**/
+
+char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+{
+ size_t size;
+ smb_ucs2_t *buffer;
+ char *dest;
+
+ size = push_ucs2_talloc(ctx, &buffer, src);
+ if (size == -1) {
+ return NULL;
+ }
+ strupper_w(buffer);
+
+ size = pull_ucs2_talloc(ctx, &dest, buffer);
+ talloc_free(buffer);
+ return dest;
+}
+
+/**
Convert a string to lower case.
**/
void strlower_m(char *s)
{
+ char *lower;
/* 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
@@ -733,15 +824,20 @@ void strlower_m(char *s)
/* 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);
+ lower = strlower_talloc(NULL, s);
+ if (lower) {
+ safe_strcpy(s, lower, strlen(s));
+ }
+ talloc_free(lower);
}
/**
- Convert a string to upper case.
+ Convert a string to UPPER case.
**/
void strupper_m(char *s)
{
+ char *upper;
/* 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
@@ -755,18 +851,27 @@ void strupper_m(char *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);
+ /* I assume that uppercased string takes the same number of bytes
+ * as source string even in UTF-8 encoding. (VIV) */
+ upper = strupper_talloc(NULL, s);
+ if (upper) {
+ safe_strcpy(s, upper, strlen(s));
+ }
+ talloc_free(upper);
}
-
/**
- 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)
{
size_t count = 0;
+ smb_ucs2_t *tmp;
+
+ size_t len;
if (!s) {
return 0;
@@ -781,8 +886,12 @@ size_t strlen_m(const char *s)
return count;
}
- push_ucs2(NULL,tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- return count + strlen_w(tmpbuf);
+ SMB_ASSERT(push_ucs2_talloc(NULL, &tmp, s) != -1);
+
+ len = count + strlen_w(tmp);
+ talloc_free(tmp);
+
+ return len;
}
/**
@@ -799,21 +908,6 @@ size_t strlen_m_term(const char *s)
}
/**
- 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.
@@ -1185,79 +1279,6 @@ void ipstr_list_free(char* ipstr_list)
}
/**
- 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.
-
- 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;
- uint8_t lonybble, hinybble;
- const char *hexchars = "0123456789ABCDEF";
- char *p1 = NULL, *p2 = NULL;
-
- for (i = 0; i < len && strhex[i] != 0; i++) {
- if (strncasecmp(hexchars, "0x", 2) == 0) {
- i++; /* skip two chars */
- continue;
- }
-
- if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
- break;
-
- i++; /* next hex digit */
-
- if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
- break;
-
- /* get the two nybbles */
- hinybble = PTR_DIFF(p1, hexchars);
- lonybble = PTR_DIFF(p2, hexchars);
-
- p[num_chars] = (hinybble << 4) | lonybble;
- num_chars++;
-
- p1 = NULL;
- p2 = NULL;
- }
- 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]);
-}
-
-
-/**
Unescape a URL encoded string, in place.
**/