summaryrefslogtreecommitdiff
path: root/lib/util
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util')
-rw-r--r--lib/util/charset/charset.h9
-rw-r--r--lib/util/charset/iconv.c85
-rw-r--r--lib/util/charset/wscript_build8
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'