diff options
-rw-r--r-- | lib/util/charset/charset.h | 9 | ||||
-rw-r--r-- | lib/util/charset/iconv.c | 85 | ||||
-rw-r--r-- | lib/util/charset/wscript_build | 8 | ||||
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/lib/iconv.c | 775 | ||||
-rw-r--r-- | source3/modules/charset_macosxfs.c | 5 | ||||
-rw-r--r-- | source3/modules/developer.c | 8 | ||||
-rw-r--r-- | source3/modules/weird.c | 5 | ||||
-rw-r--r-- | source3/wscript_build | 4 |
10 files changed, 106 insertions, 796 deletions
diff --git a/lib/util/charset/charset.h b/lib/util/charset/charset.h index 901885d846..28d762578b 100644 --- a/lib/util/charset/charset.h +++ b/lib/util/charset/charset.h @@ -218,7 +218,7 @@ smb_iconv_t smb_iconv_open_ex(TALLOC_CTX *mem_ctx, const char *tocode, const char *fromcode, bool native_iconv); void load_case_tables(void); -bool charset_register_backend(const void *_funcs); +bool smb_register_charset(const struct charset_functions *funcs_in); /* * Define stub for charset module which implements 8-bit encoding with gaps. @@ -293,8 +293,11 @@ struct charset_functions CHARSETNAME ## _functions = \ NTSTATUS charset_ ## CHARSETNAME ## _init(void); \ NTSTATUS charset_ ## CHARSETNAME ## _init(void) \ { \ - return smb_register_charset(& CHARSETNAME ## _functions); \ -} \ + if (!smb_register_charset(& CHARSETNAME ## _functions)) { \ + return NT_STATUS_INTERNAL_ERROR; \ + } \ + return NT_STATUS_OK; \ +} \ #endif /* __CHARSET_H__ */ diff --git a/lib/util/charset/iconv.c b/lib/util/charset/iconv.c index 66a8180061..cee2d26aa4 100644 --- a/lib/util/charset/iconv.c +++ b/lib/util/charset/iconv.c @@ -23,6 +23,13 @@ #include "system/iconv.h" #include "system/filesys.h" +#ifdef strcasecmp +#undef strcasecmp +#endif + +#ifdef static_decl_charset +static_decl_charset; +#endif /** * @file @@ -49,6 +56,7 @@ static size_t ascii_pull (void *,const char **, size_t *, char **, size_t *); static size_t ascii_push (void *,const char **, size_t *, char **, size_t *); +static size_t latin1_push(void *,const char **, size_t *, char **, size_t *); static size_t utf8_pull (void *,const char **, size_t *, char **, size_t *); static size_t utf8_push (void *,const char **, size_t *, char **, size_t *); static size_t utf16_munged_pull(void *,const char **, size_t *, char **, size_t *); @@ -72,29 +80,64 @@ static const struct charset_functions builtin_functions[] = { {"UTF16_MUNGED", utf16_munged_pull, iconv_copy}, {"ASCII", ascii_pull, ascii_push}, + {"646", ascii_pull, ascii_push}, + {"ISO-8859-1", ascii_pull, latin1_push}, {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} }; static struct charset_functions *charsets = NULL; -bool charset_register_backend(const void *_funcs) +static struct charset_functions *find_charset_functions(const char *name) { - struct charset_functions *funcs = (struct charset_functions *)memdup(_funcs,sizeof(struct charset_functions)); struct charset_functions *c; /* Check whether we already have this charset... */ for (c = charsets; c != NULL; c = c->next) { - if(!strcasecmp(c->name, funcs->name)) { - DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); - return false; + if(strcasecmp(c->name, name) == 0) { + return c; } + c = c->next; + } + + return NULL; +} + +bool smb_register_charset(const struct charset_functions *funcs_in) +{ + struct charset_functions *funcs; + + DEBUG(5, ("Attempting to register new charset %s\n", funcs_in->name)); + /* Check whether we already have this charset... */ + if (find_charset_functions(funcs_in->name)) { + DEBUG(0, ("Duplicate charset %s, not registering\n", funcs_in->name)); + return false; + } + + funcs = talloc(NULL, struct charset_functions); + if (!funcs) { + DEBUG(0, ("Out of memory duplicating charset %s\n", funcs_in->name)); + return false; } + *funcs = *funcs_in; funcs->next = funcs->prev = NULL; + DEBUG(5, ("Registered charset %s\n", funcs->name)); DLIST_ADD(charsets, funcs); return true; } +static void lazy_initialize_iconv(void) +{ + static bool initialized; + +#ifdef static_init_charset + if (!initialized) { + static_init_charset; + initialized = true; + } +#endif +} + #ifdef HAVE_NATIVE_ICONV /* if there was an error then reset the internal state, this ensures that we don't have a shift state remaining for @@ -158,7 +201,7 @@ static bool is_utf16(const char *name) strcasecmp(name, "UTF-16LE") == 0; } -int smb_iconv_t_destructor(smb_iconv_t hwd) +static int smb_iconv_t_destructor(smb_iconv_t hwd) { #ifdef HAVE_NATIVE_ICONV if (hwd->cd_pull != NULL && hwd->cd_pull != (iconv_t)-1) @@ -179,6 +222,8 @@ _PUBLIC_ smb_iconv_t smb_iconv_open_ex(TALLOC_CTX *mem_ctx, const char *tocode, const struct charset_functions *from=NULL, *to=NULL; int i; + lazy_initialize_iconv(); + ret = (smb_iconv_t)talloc_named(mem_ctx, sizeof(*ret), "iconv(%s,%s)", tocode, fromcode); @@ -282,7 +327,7 @@ failed: */ _PUBLIC_ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) { - return smb_iconv_open_ex(talloc_autofree_context(), tocode, fromcode, true); + return smb_iconv_open_ex(NULL, tocode, fromcode, true); } /* @@ -347,6 +392,32 @@ static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, return ir_count; } +static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + (*outbuf)[0] = (*inbuf)[0]; + if ((*inbuf)[1]) ir_count++; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) diff --git a/lib/util/charset/wscript_build b/lib/util/charset/wscript_build index 4137bf6cee..18479a9978 100644 --- a/lib/util/charset/wscript_build +++ b/lib/util/charset/wscript_build @@ -3,11 +3,15 @@ if bld.env._SAMBA_BUILD_ == 4: bld.SAMBA_SUBSYSTEM('CHARSET', - source='iconv.c charcnv.c util_unistr.c', - public_deps='iconv CODEPOINTS', + source='charcnv.c util_unistr.c', + public_deps='ICONV_WRAPPER CODEPOINTS', public_headers='charset.h', ) +bld.SAMBA_SUBSYSTEM('ICONV_WRAPPER', + source='iconv.c', + public_deps='iconv') + bld.SAMBA_SUBSYSTEM('CODEPOINTS', source='codepoints.c', deps='DYNCONFIG' diff --git a/source3/Makefile.in b/source3/Makefile.in index f037314247..686d04c0fe 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -458,7 +458,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/ms_fnmatch.o lib/errmap_unix.o \ lib/tallocmsg.o lib/dmallocmsg.o \ libsmb/clisigning.o libsmb/smb_signing.o \ - lib/iconv.o intl/lang_tdb.o \ + ../lib/util/charset/iconv.o intl/lang_tdb.o \ lib/conn_tdb.o lib/adt_tree.o lib/gencache.o \ lib/sessionid_tdb.o \ lib/module.o lib/events.o @LIBTEVENT_OBJ0@ \ diff --git a/source3/include/proto.h b/source3/include/proto.h index 8ca4db2b61..6af1613afa 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -409,7 +409,6 @@ int bitmap_find(struct bitmap *bm, unsigned ofs); /* The following definitions come from lib/charcnv.c */ -NTSTATUS smb_register_charset(struct charset_functions *funcs); char lp_failed_convert_char(void); void lazy_initialize_conv(void); void gfree_charcnv(void); diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c deleted file mode 100644 index a6ed429abc..0000000000 --- a/source3/lib/iconv.c +++ /dev/null @@ -1,775 +0,0 @@ -/* - Unix SMB/CIFS implementation. - minimal iconv implementation - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jelmer Vernooij 2002,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 - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -/* - * We have to use strcasecmp here as the character conversions - * haven't been initialised yet. JRA. - */ - -#undef strcasecmp - -/** - * @file - * - * @brief Samba wrapper/stub for iconv character set conversion. - * - * iconv is the XPG2 interface for converting between character - * encodings. This file provides a Samba wrapper around it, and also - * a simple reimplementation that is used if the system does not - * implement iconv. - * - * Samba only works with encodings that are supersets of ASCII: ascii - * characters like whitespace can be tested for directly, multibyte - * sequences start with a byte with the high bit set, and strings are - * terminated by a nul byte. - * - * Note that the only function provided by iconv is conversion between - * characters. It doesn't directly support operations like - * uppercasing or comparison. We have to convert to UCS-2 and compare - * there. - * - * @sa Samba Developers Guide - **/ - -static_decl_charset; - -static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *); -static size_t ascii_push(void *,const char **, size_t *, char **, size_t *); -static size_t latin1_push(void *,const char **, size_t *, char **, size_t *); -static size_t utf8_pull(void *,const char **, size_t *, char **, size_t *); -static size_t utf8_push(void *,const char **, size_t *, char **, size_t *); -static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *); -static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); -static size_t iconv_copy(void *,const char **, size_t *, char **, size_t *); -static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); - -static struct charset_functions builtin_functions[] = { - /* windows is really neither UCS-2 not UTF-16 */ - {"UCS-2LE", iconv_copy, iconv_copy}, - {"UTF-16LE", iconv_copy, iconv_copy}, - {"UCS-2BE", iconv_swab, iconv_swab}, - {"UTF-16BE", iconv_swab, iconv_swab}, - - /* we include the UTF-8 alias to cope with differing locale settings */ - {"UTF8", utf8_pull, utf8_push}, - {"UTF-8", utf8_pull, utf8_push}, - {"ASCII", ascii_pull, ascii_push}, - {"646", ascii_pull, ascii_push}, - {"ISO-8859-1", ascii_pull, latin1_push}, - {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}, - {NULL, NULL, NULL} -}; - -static struct charset_functions *charsets = NULL; - -static struct charset_functions *find_charset_functions(const char *name) -{ - struct charset_functions *c = charsets; - - while(c) { - if (strcasecmp(name, c->name) == 0) { - return c; - } - c = c->next; - } - - return NULL; -} - -NTSTATUS smb_register_charset(struct charset_functions *funcs) -{ - if (!funcs) { - return NT_STATUS_INVALID_PARAMETER; - } - - DEBUG(5, ("Attempting to register new charset %s\n", funcs->name)); - /* Check whether we already have this charset... */ - if (find_charset_functions(funcs->name)) { - DEBUG(0, ("Duplicate charset %s, not registering\n", funcs->name)); - return NT_STATUS_OBJECT_NAME_COLLISION; - } - - funcs->next = funcs->prev = NULL; - DEBUG(5, ("Registered charset %s\n", funcs->name)); - DLIST_ADD(charsets, funcs); - return NT_STATUS_OK; -} - -static void lazy_initialize_iconv(void) -{ - static bool initialized; - int i; - - if (!initialized) { - initialized = True; - for(i = 0; builtin_functions[i].name; i++) - smb_register_charset(&builtin_functions[i]); - static_init_charset; - } -} - -#ifdef HAVE_NATIVE_ICONV -/* if there was an error then reset the internal state, - this ensures that we don't have a shift state remaining for - character sets like SJIS */ -static size_t sys_iconv(void *cd, - const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - size_t ret = iconv((iconv_t)cd, - (void *)inbuf, inbytesleft, - outbuf, outbytesleft); - if (ret == (size_t)-1) { - int saved_errno = errno; - iconv(cd, NULL, NULL, NULL, NULL); - errno = saved_errno; - } - return ret; -} -#endif - -/** - * This is a simple portable iconv() implementaion. - * - * It only knows about a very small number of character sets - just - * enough that Samba works on systems that don't have iconv. - **/ -size_t smb_iconv(smb_iconv_t cd, - const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - char cvtbuf[2048]; - char *bufp = cvtbuf; - size_t bufsize; - - /* in many cases we can go direct */ - if (cd->direct) { - return cd->direct(cd->cd_direct, - inbuf, inbytesleft, outbuf, outbytesleft); - } - - - /* otherwise we have to do it chunks at a time */ - while (*inbytesleft > 0) { - bufp = cvtbuf; - bufsize = sizeof(cvtbuf); - - if (cd->pull(cd->cd_pull, - inbuf, inbytesleft, &bufp, &bufsize) == -1 - && errno != E2BIG) return -1; - - bufp = cvtbuf; - bufsize = sizeof(cvtbuf) - bufsize; - - if (cd->push(cd->cd_push, - (const char **)&bufp, &bufsize, - outbuf, outbytesleft) == -1) return -1; - } - - return 0; -} - - -static bool is_utf16(const char *name) -{ - return strcasecmp(name, "UCS-2LE") == 0 || - strcasecmp(name, "UTF-16LE") == 0; -} - -/* - simple iconv_open() wrapper - */ -smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode) -{ - smb_iconv_t ret; - struct charset_functions *from, *to; - - lazy_initialize_iconv(); - from = charsets; - to = charsets; - - ret = SMB_MALLOC_P(struct smb_iconv_s); - if (!ret) { - errno = ENOMEM; - return (smb_iconv_t)-1; - } - memset(ret, 0, sizeof(struct smb_iconv_s)); - - ret->from_name = SMB_STRDUP(fromcode); - ret->to_name = SMB_STRDUP(tocode); - - /* check for the simplest null conversion */ - if (strcasecmp(fromcode, tocode) == 0) { - ret->direct = iconv_copy; - return ret; - } - - /* check if we have a builtin function for this conversion */ - from = find_charset_functions(fromcode); - if(from)ret->pull = from->pull; - - to = find_charset_functions(tocode); - if(to)ret->push = to->push; - - /* check if we can use iconv for this conversion */ -#ifdef HAVE_NATIVE_ICONV - if (!ret->pull) { - ret->cd_pull = iconv_open("UTF-16LE", fromcode); - if (ret->cd_pull == (iconv_t)-1) - ret->cd_pull = iconv_open("UCS-2LE", fromcode); - if (ret->cd_pull != (iconv_t)-1) - ret->pull = sys_iconv; - } - - if (!ret->push) { - ret->cd_push = iconv_open(tocode, "UTF-16LE"); - if (ret->cd_push == (iconv_t)-1) - ret->cd_push = iconv_open(tocode, "UCS-2LE"); - if (ret->cd_push != (iconv_t)-1) - ret->push = sys_iconv; - } -#endif - - /* check if there is a module available that can do this conversion */ - if (!ret->pull && NT_STATUS_IS_OK(smb_probe_module("charset", fromcode))) { - if(!(from = find_charset_functions(fromcode))) - DEBUG(0, ("Module %s doesn't provide charset %s!\n", fromcode, fromcode)); - else - ret->pull = from->pull; - } - - if (!ret->push && NT_STATUS_IS_OK(smb_probe_module("charset", tocode))) { - if(!(to = find_charset_functions(tocode))) - DEBUG(0, ("Module %s doesn't provide charset %s!\n", tocode, tocode)); - else - ret->push = to->push; - } - - if (!ret->push || !ret->pull) { - SAFE_FREE(ret->from_name); - SAFE_FREE(ret->to_name); - SAFE_FREE(ret); - errno = EINVAL; - return (smb_iconv_t)-1; - } - - /* check for conversion to/from ucs2 */ - if (is_utf16(fromcode) && to) { - ret->direct = to->push; - ret->push = ret->pull = NULL; - return ret; - } - - if (is_utf16(tocode) && from) { - ret->direct = from->pull; - ret->push = ret->pull = NULL; - return ret; - } - - /* Check if we can do the conversion direct */ -#ifdef HAVE_NATIVE_ICONV - if (is_utf16(fromcode)) { - ret->direct = sys_iconv; - ret->cd_direct = ret->cd_push; - ret->cd_push = NULL; - return ret; - } - if (is_utf16(tocode)) { - ret->direct = sys_iconv; - ret->cd_direct = ret->cd_pull; - ret->cd_pull = NULL; - return ret; - } -#endif - - return ret; -} - -/* - simple iconv_close() wrapper -*/ -int smb_iconv_close (smb_iconv_t cd) -{ -#ifdef HAVE_NATIVE_ICONV - if (cd->cd_direct) iconv_close((iconv_t)cd->cd_direct); - if (cd->cd_pull) iconv_close((iconv_t)cd->cd_pull); - if (cd->cd_push) iconv_close((iconv_t)cd->cd_push); -#endif - - SAFE_FREE(cd->from_name); - SAFE_FREE(cd->to_name); - - memset(cd, 0, sizeof(*cd)); - SAFE_FREE(cd); - return 0; -} - - -/********************************************************************** - the following functions implement the builtin character sets in Samba - and also the "test" character sets that are designed to test - multi-byte character set support for english users -***********************************************************************/ - -static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 1 && *outbytesleft >= 2) { - (*outbuf)[0] = (*inbuf)[0]; - (*outbuf)[1] = 0; - (*inbytesleft) -= 1; - (*outbytesleft) -= 2; - (*inbuf) += 1; - (*outbuf) += 2; - } - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int ir_count=0; - - while (*inbytesleft >= 2 && *outbytesleft >= 1) { - (*outbuf)[0] = (*inbuf)[0] & 0x7F; - if ((*inbuf)[1]) ir_count++; - (*inbytesleft) -= 2; - (*outbytesleft) -= 1; - (*inbuf) += 2; - (*outbuf) += 1; - } - - if (*inbytesleft == 1) { - errno = EINVAL; - return -1; - } - - if (*inbytesleft > 1) { - errno = E2BIG; - return -1; - } - - return ir_count; -} - -static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int ir_count=0; - - while (*inbytesleft >= 2 && *outbytesleft >= 1) { - (*outbuf)[0] = (*inbuf)[0]; - if ((*inbuf)[1]) ir_count++; - (*inbytesleft) -= 2; - (*outbytesleft) -= 1; - (*inbuf) += 2; - (*outbuf) += 1; - } - - if (*inbytesleft == 1) { - errno = EINVAL; - return -1; - } - - if (*inbytesleft > 1) { - errno = E2BIG; - return -1; - } - - return ir_count; -} - -static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 1 && *outbytesleft >= 2) { - unsigned v; - - if ((*inbuf)[0] != '@') { - /* seven bit ascii case */ - (*outbuf)[0] = (*inbuf)[0]; - (*outbuf)[1] = 0; - (*inbytesleft) -= 1; - (*outbytesleft) -= 2; - (*inbuf) += 1; - (*outbuf) += 2; - continue; - } - /* it's a hex character */ - if (*inbytesleft < 5) { - errno = EINVAL; - return -1; - } - - if (sscanf(&(*inbuf)[1], "%04x", &v) != 1) { - errno = EILSEQ; - return -1; - } - - (*outbuf)[0] = v&0xff; - (*outbuf)[1] = v>>8; - (*inbytesleft) -= 5; - (*outbytesleft) -= 2; - (*inbuf) += 5; - (*outbuf) += 2; - } - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 2 && *outbytesleft >= 1) { - char buf[6]; - - if ((*inbuf)[1] == 0 && - ((*inbuf)[0] & 0x80) == 0 && - (*inbuf)[0] != '@') { - (*outbuf)[0] = (*inbuf)[0]; - (*inbytesleft) -= 2; - (*outbytesleft) -= 1; - (*inbuf) += 2; - (*outbuf) += 1; - continue; - } - if (*outbytesleft < 5) { - errno = E2BIG; - return -1; - } - snprintf(buf, 6, "@%04x", SVAL(*inbuf, 0)); - memcpy(*outbuf, buf, 5); - (*inbytesleft) -= 2; - (*outbytesleft) -= 5; - (*inbuf) += 2; - (*outbuf) += 5; - } - - if (*inbytesleft == 1) { - errno = EINVAL; - return -1; - } - - if (*inbytesleft > 1) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int n; - - n = MIN(*inbytesleft, *outbytesleft); - - swab(*inbuf, *outbuf, (n&~1)); - if (n&1) { - (*outbuf)[n-1] = 0; - } - - (*inbytesleft) -= n; - (*outbytesleft) -= n; - (*inbuf) += n; - (*outbuf) += n; - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - int n; - - n = MIN(*inbytesleft, *outbytesleft); - - memmove(*outbuf, *inbuf, n); - - (*inbytesleft) -= n; - (*outbytesleft) -= n; - (*inbuf) += n; - (*outbuf) += n; - - if (*inbytesleft > 0) { - errno = E2BIG; - return -1; - } - - return 0; -} - -static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - size_t in_left=*inbytesleft, out_left=*outbytesleft; - const uint8 *c = (const uint8 *)*inbuf; - uint8 *uc = (uint8 *)*outbuf; - - while (in_left >= 1 && out_left >= 2) { - unsigned int codepoint; - - if ((c[0] & 0x80) == 0) { - uc[0] = c[0]; - uc[1] = 0; - c += 1; - in_left -= 1; - out_left -= 2; - uc += 2; - continue; - } - - if ((c[0] & 0xe0) == 0xc0) { - if (in_left < 2 || - (c[1] & 0xc0) != 0x80) { - errno = EILSEQ; - goto error; - } - codepoint = (c[1]&0x3f) | ((c[0]&0x1f)<<6); - if (codepoint < 0x80) { - /* don't accept UTF-8 characters that are not minimally packed */ - errno = EILSEQ; - goto error; - } - uc[1] = codepoint >> 8; - uc[0] = codepoint & 0xff; - c += 2; - in_left -= 2; - out_left -= 2; - uc += 2; - continue; - } - - if ((c[0] & 0xf0) == 0xe0) { - if (in_left < 3 || - (c[1] & 0xc0) != 0x80 || - (c[2] & 0xc0) != 0x80) { - errno = EILSEQ; - goto error; - } - codepoint = (c[2]&0x3f) | ((c[1]&0x3f)<<6) | ((c[0]&0xf)<<12); - if (codepoint < 0x800) { - /* don't accept UTF-8 characters that are not minimally packed */ - errno = EILSEQ; - goto error; - } - uc[1] = codepoint >> 8; - uc[0] = codepoint & 0xff; - c += 3; - in_left -= 3; - out_left -= 2; - uc += 2; - continue; - } - - if ((c[0] & 0xf8) == 0xf0) { - if (in_left < 4 || - (c[1] & 0xc0) != 0x80 || - (c[2] & 0xc0) != 0x80 || - (c[3] & 0xc0) != 0x80) { - errno = EILSEQ; - goto error; - } - codepoint = - (c[3]&0x3f) | - ((c[2]&0x3f)<<6) | - ((c[1]&0x3f)<<12) | - ((c[0]&0x7)<<18); - if (codepoint < 0x10000 || codepoint > 0x10ffff) { - /* don't accept UTF-8 characters that are not minimally packed */ - errno = EILSEQ; - goto error; - } - - codepoint -= 0x10000; - - if (out_left < 4) { - errno = E2BIG; - goto error; - } - - uc[0] = (codepoint>>10) & 0xFF; - uc[1] = (codepoint>>18) | 0xd8; - uc[2] = codepoint & 0xFF; - uc[3] = ((codepoint>>8) & 0x3) | 0xdc; - c += 4; - in_left -= 4; - out_left -= 4; - uc += 4; - continue; - } - - /* we don't handle 5 byte sequences */ - errno = EINVAL; - goto error; - } - - if (in_left > 0) { - errno = E2BIG; - goto error; - } - - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = (char *)c; - *outbuf = (char *)uc; - return 0; - -error: - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = (char *)c; - *outbuf = (char *)uc; - return -1; -} - -static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - size_t in_left=*inbytesleft, out_left=*outbytesleft; - uint8 *c = (uint8 *)*outbuf; - const uint8 *uc = (const uint8 *)*inbuf; - - while (in_left >= 2 && out_left >= 1) { - unsigned int codepoint; - - if (uc[1] == 0 && !(uc[0] & 0x80)) { - /* simplest case */ - c[0] = uc[0]; - in_left -= 2; - out_left -= 1; - uc += 2; - c += 1; - continue; - } - - if ((uc[1]&0xf8) == 0) { - /* next simplest case */ - if (out_left < 2) { - errno = E2BIG; - goto error; - } - c[0] = 0xc0 | (uc[0]>>6) | (uc[1]<<2); - c[1] = 0x80 | (uc[0] & 0x3f); - in_left -= 2; - out_left -= 2; - uc += 2; - c += 2; - continue; - } - - if ((uc[1] & 0xfc) == 0xdc) { - /* its the second part of a 4 byte sequence. Illegal */ - if (in_left < 4) { - errno = EINVAL; - } else { - errno = EILSEQ; - } - goto error; - } - - if ((uc[1] & 0xfc) != 0xd8) { - codepoint = uc[0] | (uc[1]<<8); - if (out_left < 3) { - errno = E2BIG; - goto error; - } - c[0] = 0xe0 | (codepoint >> 12); - c[1] = 0x80 | ((codepoint >> 6) & 0x3f); - c[2] = 0x80 | (codepoint & 0x3f); - - in_left -= 2; - out_left -= 3; - uc += 2; - c += 3; - continue; - } - - /* its the first part of a 4 byte sequence */ - if (in_left < 4) { - errno = EINVAL; - goto error; - } - if ((uc[3] & 0xfc) != 0xdc) { - errno = EILSEQ; - goto error; - } - codepoint = 0x10000 + (uc[2] | ((uc[3] & 0x3)<<8) | - (uc[0]<<10) | ((uc[1] & 0x3)<<18)); - - if (out_left < 4) { - errno = E2BIG; - goto error; - } - c[0] = 0xf0 | (codepoint >> 18); - c[1] = 0x80 | ((codepoint >> 12) & 0x3f); - c[2] = 0x80 | ((codepoint >> 6) & 0x3f); - c[3] = 0x80 | (codepoint & 0x3f); - - in_left -= 4; - out_left -= 4; - uc += 4; - c += 4; - } - - if (in_left == 1) { - errno = EINVAL; - goto error; - } - - if (in_left > 1) { - errno = E2BIG; - goto error; - } - - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = (char *)uc; - *outbuf = (char *)c; - - return 0; - -error: - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = (char *)uc; - *outbuf = (char *)c; - return -1; -} - diff --git a/source3/modules/charset_macosxfs.c b/source3/modules/charset_macosxfs.c index baf2a0071c..8c2fdc7776 100644 --- a/source3/modules/charset_macosxfs.c +++ b/source3/modules/charset_macosxfs.c @@ -595,7 +595,10 @@ static struct charset_functions macosxfs_encoding_functions = { NTSTATUS charset_macosxfs_init(void) { - return smb_register_charset(&macosxfs_encoding_functions); + if (!smb_register_charset(&macosxfs_encoding_functions)) { + return NT_STATUS_INTERNAL_ERROR; + } + return NT_STATUS_OK; } /* eof */ diff --git a/source3/modules/developer.c b/source3/modules/developer.c index 37019256db..42471e2d33 100644 --- a/source3/modules/developer.c +++ b/source3/modules/developer.c @@ -124,8 +124,10 @@ static size_t weird_push(void *cd, char **inbuf, size_t *inbytesleft, struct charset_functions weird_functions = {"WEIRD", weird_pull, weird_push}; -int charset_weird_init(void) +NTSTATUS charset_weird_init(void) { - smb_register_charset(&weird_functions); - return True; + if (!smb_register_charset(&weird_functions)) { + return NT_STATUS_INTERNAL_ERROR; + } + return NT_STATUS_OK; } diff --git a/source3/modules/weird.c b/source3/modules/weird.c index eab17ce50e..5db8cdcecd 100644 --- a/source3/modules/weird.c +++ b/source3/modules/weird.c @@ -127,5 +127,8 @@ struct charset_functions weird_functions = {"WEIRD", weird_pull, weird_push}; NTSTATUS charset_weird_init(void); NTSTATUS charset_weird_init(void) { - return smb_register_charset(&weird_functions); + if (!smb_register_charset(&weird_functions)) { + return NT_STATUS_INTERNAL_ERROR; + } + return NT_STATUS_OK; } diff --git a/source3/wscript_build b/source3/wscript_build index 7152273ee3..762ef9ee77 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -989,8 +989,8 @@ bld.SAMBA3_SUBSYSTEM('tdb-wrap', vars=locals()) bld.SAMBA3_SUBSYSTEM('CHARSET', - source='''lib/util_str.c lib/util_unistr.c lib/charcnv.c lib/iconv.c''', - public_deps='iconv CODEPOINTS', + source='''lib/util_str.c lib/util_unistr.c lib/charcnv.c''', + public_deps='ICONV_WRAPPER CODEPOINTS', deps='DYNCONFIG') bld.SAMBA3_SUBSYSTEM('samba-util', |