diff options
author | Andrew Bartlett <abartlet@samba.org> | 2004-09-23 00:51:45 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:59:05 -0500 |
commit | 9a9dcc7250ccd4544cb797c15b3bc3dfbb760be0 (patch) | |
tree | 35948c622b3ba1657fafc7f498c8674c0220e658 /source4/lib | |
parent | 70c88af1f909a7dcf65293da0ddd1e13ff53a9d5 (diff) | |
download | samba-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')
-rw-r--r-- | source4/lib/charcnv.c | 379 | ||||
-rw-r--r-- | source4/lib/util_str.c | 325 | ||||
-rw-r--r-- | source4/lib/util_unistr.c | 7 |
3 files changed, 267 insertions, 444 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; } 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. **/ diff --git a/source4/lib/util_unistr.c b/source4/lib/util_unistr.c index 4b303a894d..a05df0983b 100644 --- a/source4/lib/util_unistr.c +++ b/source4/lib/util_unistr.c @@ -342,3 +342,10 @@ const smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p) return NULL; } +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; +} + |