diff options
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; +} + |