diff options
Diffstat (limited to 'lib/util')
-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 |
3 files changed, 90 insertions, 12 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' |