summaryrefslogtreecommitdiff
path: root/source4/lib/charcnv.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-09-23 00:51:45 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:59:05 -0500
commit9a9dcc7250ccd4544cb797c15b3bc3dfbb760be0 (patch)
tree35948c622b3ba1657fafc7f498c8674c0220e658 /source4/lib/charcnv.c
parent70c88af1f909a7dcf65293da0ddd1e13ff53a9d5 (diff)
downloadsamba-9a9dcc7250ccd4544cb797c15b3bc3dfbb760be0.tar.gz
samba-9a9dcc7250ccd4544cb797c15b3bc3dfbb760be0.tar.bz2
samba-9a9dcc7250ccd4544cb797c15b3bc3dfbb760be0.zip
r2552: Character set conversion and string handling updates.
The intial motivation for this commit was to merge in some of the bugfixes present in Samba3's chrcnv and string handling code into Samba4. However, along the way I found a lot of unused functions, and decided to do a bit more... The strlen_m code now does not use a fixed buffer, but more work is needed to finish off other functions in str_util.c. These fixed length buffers hav caused very nasty, hard to chase down bugs at some sites. The strupper_m() function has a strupper_talloc() to replace it (we need to go around and fix more uses, but it's a start). Use of these new functions will avoid bugs where the upper or lowercase version of a string is a different length. I have removed the push_*_allocate functions, which are replaced by calls to push_*_talloc. Likewise, pstring and other 'fixed length' wrappers are removed, where possible. I have removed the first ('base pointer') argument, used by push_ucs2, as the Samba4 way of doing things ensures that this is always on an even boundary anyway. (It was used in only one place, in any case). (This used to be commit dfecb0150627b500cb026b8a4932fe87902ca392)
Diffstat (limited to 'source4/lib/charcnv.c')
-rw-r--r--source4/lib/charcnv.c379
1 files changed, 87 insertions, 292 deletions
diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c
index f30f5b9239..fd550895d0 100644
--- a/source4/lib/charcnv.c
+++ b/source4/lib/charcnv.c
@@ -181,7 +181,7 @@ ssize_t convert_string(charset_t from, charset_t to,
}
/**
- * Convert between character sets, allocating a new buffer for the result.
+ * Convert between character sets, allocating a new buffer using talloc for the result.
*
* @param srclen length of source buffer.
* @param dest always set at least to NULL
@@ -190,7 +190,7 @@ ssize_t convert_string(charset_t from, charset_t to,
* @returns Size in bytes of the converted string; or -1 in case of error.
**/
-ssize_t convert_string_allocate(charset_t from, charset_t to,
+ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
void const *src, size_t srclen, void **dest)
{
size_t i_len, o_len, destlen;
@@ -210,7 +210,7 @@ ssize_t convert_string_allocate(charset_t from, charset_t to,
if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
/* conversion not supported, return -1*/
- DEBUG(3, ("convert_string_allocate: conversion not supported!\n"));
+ DEBUG(3, ("convert_string_talloc: conversion not supported!\n"));
return -1;
}
@@ -218,10 +218,14 @@ ssize_t convert_string_allocate(charset_t from, charset_t to,
outbuf = NULL;
convert:
destlen = destlen * 2;
- ob = (char *)realloc(outbuf, destlen);
+ if (outbuf == NULL) {
+ ob = talloc_array_p(ctx, char, destlen);
+ } else {
+ ob = (char *)talloc_realloc(outbuf, destlen);
+ }
if (!ob) {
- DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
- SAFE_FREE(outbuf);
+ DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
+ talloc_free(outbuf);
return (size_t)-1;
}
else
@@ -244,100 +248,25 @@ convert:
break;
}
DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
+ talloc_free(outbuf);
/* smb_panic(reason); */
return (size_t)-1;
}
destlen = destlen - o_len;
- *dest = (char *)Realloc(ob,destlen);
+ /* +2 for mandetory null termination, UTF8 or UTF16 */
+ *dest = (char *)talloc_realloc(ob,destlen+2);
if (!*dest) {
- DEBUG(0, ("convert_string_allocate: out of memory!\n"));
- SAFE_FREE(ob);
+ DEBUG(0, ("convert_string_talloc: out of memory!\n"));
+ talloc_free(ob);
return (size_t)-1;
}
+ ((char *)*dest)[destlen] = '\0';
+ ((char *)*dest)[destlen+1] = '\0';
return destlen;
}
-
-/**
- * Convert between character sets, allocating a new buffer using talloc for the result.
- *
- * @param srclen length of source buffer.
- * @param dest always set at least to NULL
- * @note -1 is not accepted for srclen.
- *
- * @returns Size in bytes of the converted string; or -1 in case of error.
- **/
-ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
- void const *src, size_t srclen, const void **dest)
-{
- void *alloced_string;
- size_t dest_len;
- void *dst;
-
- *dest = NULL;
- dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string);
- if (dest_len == (size_t)-1)
- return (size_t)-1;
- dst = talloc(ctx, dest_len + 2);
- /* we want to be absolutely sure that the result is terminated */
- memcpy(dst, alloced_string, dest_len);
- SSVAL(dst, dest_len, 0);
- SAFE_FREE(alloced_string);
- if (dst == NULL)
- return -1;
- *dest = dst;
- return dest_len;
-}
-
-size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
-{
- size_t size;
- smb_ucs2_t *buffer;
-
- size = convert_string_allocate(CH_UNIX, CH_UTF16, src, srclen,
- (void **) &buffer);
- if (size == -1) {
- smb_panic("failed to create UCS2 buffer");
- }
- if (!strupper_w(buffer) && (dest == src)) {
- free(buffer);
- return srclen;
- }
-
- size = convert_string(CH_UTF16, CH_UNIX, buffer, size, dest, destlen);
- free(buffer);
- return size;
-}
-
-size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
-{
- size_t size;
- smb_ucs2_t *buffer;
-
- size = convert_string_allocate(CH_UNIX, CH_UTF16, src, srclen,
- (void **) &buffer);
- if (size == -1) {
- smb_panic("failed to create UCS2 buffer");
- }
- if (!strlower_w(buffer) && (dest == src)) {
- free(buffer);
- return srclen;
- }
- size = convert_string(CH_UTF16, CH_UNIX, buffer, size, dest, destlen);
- free(buffer);
- return size;
-}
-
-size_t ucs2_align(const void *base_ptr, const void *p, int flags)
-{
- if (flags & (STR_NOALIGN|STR_ASCII))
- return 0;
- return PTR_DIFF(p, base_ptr) & 1;
-}
-
-
/**
* Copy a string from a char* unix src to a dos codepage string destination.
*
@@ -354,30 +283,49 @@ size_t ucs2_align(const void *base_ptr, const void *p, int flags)
**/
ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
{
- size_t src_len = strlen(src);
- pstring tmpbuf;
+ size_t src_len;
+ ssize_t ret;
+ char *tmpbuf = NULL;
/* treat a pstring as "unlimited" length */
if (dest_len == (size_t)-1)
dest_len = sizeof(pstring);
if (flags & STR_UPPER) {
- pstrcpy(tmpbuf, src);
- strupper(tmpbuf);
+ tmpbuf = strupper_talloc(NULL, src);
+ if (!tmpbuf) {
+ return -1;
+ }
src = tmpbuf;
}
+ src_len = strlen(src);
if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
src_len++;
- return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
+ ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
+ talloc_free(tmpbuf);
+ return ret;
}
-ssize_t push_pstring(void *dest, const char *src)
+/**
+ * Copy a string from a unix char* src to an ASCII destination,
+ * allocating a buffer using talloc().
+ *
+ * @param dest always set at least to NULL
+ *
+ * @returns The number of bytes occupied by the string in the destination
+ * or -1 in case of error.
+ **/
+ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
{
- return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
+ size_t src_len = strlen(src)+1;
+
+ *dest = NULL;
+ return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest);
}
+
/**
* Copy a string from a dos codepage source to a unix char* destination.
*
@@ -435,26 +383,20 @@ ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len,
* @param dest_len is the maximum length allowed in the
* destination. If dest_len is -1 then no maxiumum is used.
**/
-ssize_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
+ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags)
{
size_t len=0;
size_t src_len = strlen(src);
- pstring tmpbuf;
+ size_t ret;
/* treat a pstring as "unlimited" length */
if (dest_len == (size_t)-1)
dest_len = sizeof(pstring);
- if (flags & STR_UPPER) {
- pstrcpy(tmpbuf, src);
- strupper(tmpbuf);
- src = tmpbuf;
- }
-
if (flags & STR_TERMINATE)
src_len++;
- if (ucs2_align(base_ptr, dest, flags)) {
+ if (ucs2_align(NULL, dest, flags)) {
*(char *)dest = 0;
dest = (void *)((char *)dest + 1);
if (dest_len) dest_len--;
@@ -464,7 +406,24 @@ ssize_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest
/* ucs2 is always a multiple of 2 bytes */
dest_len &= ~1;
- len += convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
+ ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
+ if (ret == (size_t)-1) {
+ return 0;
+ }
+
+ len += ret;
+
+ if (flags & STR_UPPER) {
+ smb_ucs2_t *dest_ucs2 = dest;
+ size_t i;
+ for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
+ smb_ucs2_t v = toupper_w(dest_ucs2[i]);
+ if (v != dest_ucs2[i]) {
+ dest_ucs2[i] = v;
+ }
+ }
+ }
+
return len;
}
@@ -483,59 +442,11 @@ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (const void **)dest);
+ return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (void **)dest);
}
/**
- * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
- *
- * @param dest always set at least to NULL
- *
- * @returns The number of bytes occupied by the string in the destination
- * or -1 in case of error.
- **/
-
-ssize_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
-{
- size_t src_len = strlen(src)+1;
-
- *dest = NULL;
- return convert_string_allocate(CH_UNIX, CH_UTF16, src, src_len, (void **)dest);
-}
-
-/**
- Copy a string from a char* src to a UTF-8 destination.
- Return the number of bytes occupied by the string in the destination
- Flags can have:
- STR_TERMINATE means include the null termination
- STR_UPPER means uppercase in the destination
- dest_len is the maximum length allowed in the destination. If dest_len
- is -1 then no maxiumum is used.
-**/
-
-ssize_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
-{
- size_t src_len = strlen(src);
- pstring tmpbuf;
-
- /* treat a pstring as "unlimited" length */
- if (dest_len == (size_t)-1)
- dest_len = sizeof(pstring);
-
- if (flags & STR_UPPER) {
- pstrcpy(tmpbuf, src);
- strupper(tmpbuf);
- src = tmpbuf;
- }
-
- if (flags & STR_TERMINATE)
- src_len++;
-
- return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
-}
-
-/**
* Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
*
* @param dest always set at least to NULL
@@ -548,23 +459,7 @@ ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (const void **)dest);
-}
-
-/**
- * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
- *
- * @param dest always set at least to NULL
- *
- * @returns The number of bytes occupied by the string in the destination
- **/
-
-ssize_t push_utf8_allocate(char **dest, const char *src)
-{
- size_t src_len = strlen(src)+1;
-
- *dest = NULL;
- return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
+ return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
}
/**
@@ -578,14 +473,14 @@ ssize_t push_utf8_allocate(char **dest, const char *src)
The resulting string in "dest" is always null terminated.
**/
-size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
+size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
{
size_t ret;
if (dest_len == (size_t)-1)
dest_len = sizeof(pstring);
- if (ucs2_align(base_ptr, src, flags)) {
+ if (ucs2_align(NULL, src, flags)) {
src = (const void *)((const char *)src + 1);
if (src_len > 0)
src_len--;
@@ -615,7 +510,7 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_
ssize_t pull_ucs2_pstring(char *dest, const void *src)
{
- return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
+ return pull_ucs2(dest, src, sizeof(pstring), -1, STR_TERMINATE);
}
/**
@@ -630,57 +525,7 @@ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
{
size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
*dest = NULL;
- return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (const void **)dest);
-}
-
-/**
- * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
- *
- * @param dest always set at least to NULL
- *
- * @returns The number of bytes occupied by the string in the destination
- **/
-
-ssize_t pull_ucs2_allocate(void **dest, const smb_ucs2_t *src)
-{
- size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
- *dest = NULL;
- return convert_string_allocate(CH_UTF16, CH_UNIX, src, src_len, dest);
-}
-
-/**
- Copy a string from a utf-8 source to a unix char* destination.
- Flags can have:
- STR_TERMINATE means the string in src is null terminated.
- if STR_TERMINATE is set then src_len is ignored.
- src_len is the length of the source area in bytes
- Return the number of bytes occupied by the string in src.
- The resulting string in "dest" is always null terminated.
-**/
-
-ssize_t pull_utf8(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
-{
- size_t ret;
-
- if (dest_len == (size_t)-1)
- dest_len = sizeof(pstring);
-
- if (flags & STR_TERMINATE) {
- if (src_len == (size_t)-1) {
- src_len = strlen(src) + 1;
- } else {
- size_t len = strnlen(src, src_len);
- if (len < src_len)
- len++;
- src_len = len;
- }
- }
-
- ret = convert_string(CH_UTF8, CH_UNIX, src, src_len, dest, dest_len);
- if (dest_len)
- dest[MIN(ret, dest_len-1)] = 0;
-
- return src_len;
+ return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest);
}
/**
@@ -695,25 +540,10 @@ ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
{
size_t src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (const void **)dest);
+ return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
}
/**
- * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
- *
- * @param dest always set at least to NULL
- *
- * @returns The number of bytes occupied by the string in the destination
- **/
-
-ssize_t pull_utf8_allocate(void **dest, const char *src)
-{
- size_t src_len = strlen(src)+1;
- *dest = NULL;
- return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);
-}
-
-/**
Copy a string from a char* src to a unicode or ascii
dos codepage destination choosing unicode or ascii based on the
flags in the SMB buffer starting at base_ptr.
@@ -727,14 +557,16 @@ ssize_t pull_utf8_allocate(void **dest, const char *src)
is -1 then no maxiumum is used.
**/
-ssize_t push_string(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
+ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
{
- if (!(flags & STR_ASCII) && \
- (((flags & STR_UNICODE) || \
- (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) {
- return push_ucs2(base_ptr, dest, src, dest_len, flags);
+ if (flags & STR_ASCII) {
+ return push_ascii(dest, src, dest_len, flags);
+ } else if (flags & STR_UNICODE) {
+ return push_ucs2(dest, src, dest_len, flags);
+ } else {
+ smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set");
+ return -1;
}
- return push_ascii(dest, src, dest_len, flags);
}
@@ -752,52 +584,15 @@ ssize_t push_string(const void *base_ptr, void *dest, const char *src, size_t de
The resulting string in "dest" is always null terminated.
**/
-ssize_t pull_string(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
+ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
{
- if (!(flags & STR_ASCII) && \
- (((flags & STR_UNICODE) || \
- (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) {
- return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
- }
- return pull_ascii(dest, src, dest_len, src_len, flags);
-}
-
-ssize_t align_string(const void *base_ptr, const char *p, int flags)
-{
- if (!(flags & STR_ASCII) && \
- ((flags & STR_UNICODE || \
- (SVAL(base_ptr, NBT_HDR_SIZE+HDR_FLG2) & FLAGS2_UNICODE_STRINGS)))) {
- return ucs2_align(base_ptr, p, flags);
- }
- return 0;
-}
-
-/**
- Copy a string from a unicode or ascii source (depending on
- the packet flags) to a TALLOC'ed destination.
- Flags can have:
- STR_TERMINATE means the string in src is null terminated.
- STR_UNICODE means to force as unicode.
- STR_ASCII use ascii even with unicode packet.
- STR_NOALIGN means don't do alignment.
- if STR_TERMINATE is set then src_len is ignored is it is -1
- src_len is the length of the source area in bytes.
- Return the number of bytes occupied by the string in src.
- The resulting string in "dest" is always null terminated.
-**/
-
-ssize_t pull_string_talloc(TALLOC_CTX *ctx, char **dest, const void *src, size_t src_len, int flags)
-{
- if (!(flags & STR_ASCII) && \
- (flags & STR_UNICODE)) {
- return pull_ucs2_talloc(ctx, dest, src);
- }
- *dest = NULL;
- if (flags & STR_TERMINATE) {
- *dest = talloc_strdup(ctx, src);
- return strlen(*dest);
+ if (flags & STR_ASCII) {
+ return pull_ascii(dest, src, dest_len, src_len, flags);
+ } else if (flags & STR_UNICODE) {
+ return pull_ucs2(dest, src, dest_len, src_len, flags);
+ } else {
+ smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set");
+ return -1;
}
- *dest = talloc_strndup(ctx, src, src_len);
- return src_len;
}