*/
#include "includes.h"
+#include "dlinklist.h"
+#include "system/iconv.h"
/**
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 const struct charset_functions const builtin_functions[] = {
+static const struct charset_functions builtin_functions[] = {
/* windows is closest to UTF-16 */
{"UCS-2LE", iconv_copy, iconv_copy},
{"UTF-16LE", iconv_copy, iconv_copy},
{"UTF8", utf8_pull, utf8_push},
{"UTF-8", utf8_pull, utf8_push},
{"ASCII", ascii_pull, ascii_push},
- {"UCS2-HEX", ucs2hex_pull, ucs2hex_push},
- {NULL, NULL, NULL}
+ {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}
};
static struct charset_functions *charsets = NULL;
-static NTSTATUS charset_register_backend(const void *_funcs)
+NTSTATUS charset_register_backend(const void *_funcs)
{
struct charset_functions *funcs = memdup(_funcs,sizeof(struct charset_functions));
struct charset_functions *c = charsets;
return NT_STATUS_OK;
}
-static void lazy_initialize_iconv(void)
-{
- static BOOL initialized = False;
- int i;
-
- if (!initialized) {
- initialized = True;
- register_subsystem("charset", charset_register_backend);
-
- for(i = 0; builtin_functions[i].name; i++)
- register_backend("charset", &builtin_functions[i]);
- }
-}
-
#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
char **outbuf, size_t *outbytesleft)
{
size_t ret = iconv((iconv_t)cd,
- inbuf, inbytesleft,
+ discard_const_p(char *, inbuf), inbytesleft,
outbuf, outbytesleft);
if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL);
return ret;
char **outbuf, size_t *outbytesleft)
{
char cvtbuf[2048];
- char *bufp = cvtbuf;
size_t bufsize;
/* in many cases we can go direct */
/* otherwise we have to do it chunks at a time */
while (*inbytesleft > 0) {
- bufp = cvtbuf;
+ char *bufp1 = cvtbuf;
+ const char *bufp2 = cvtbuf;
+
bufsize = sizeof(cvtbuf);
if (cd->pull(cd->cd_pull,
- inbuf, inbytesleft, &bufp, &bufsize) == -1
+ inbuf, inbytesleft, &bufp1, &bufsize) == -1
&& errno != E2BIG) return -1;
- bufp = cvtbuf;
bufsize = sizeof(cvtbuf) - bufsize;
if (cd->push(cd->cd_push,
- &bufp, &bufsize,
+ &bufp2, &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;
+ const struct charset_functions *from=NULL, *to=NULL;
+ int i;
- ret = (smb_iconv_t)malloc(sizeof(*ret));
+ ret = (smb_iconv_t)talloc_named(NULL, sizeof(*ret),
+ "iconv(%s,%s)", tocode, fromcode);
if (!ret) {
errno = ENOMEM;
return (smb_iconv_t)-1;
}
memset(ret, 0, sizeof(*ret));
- ret->from_name = strdup(fromcode);
- ret->to_name = strdup(tocode);
-
/* check for the simplest null conversion */
if (strcmp(fromcode, tocode) == 0) {
ret->direct = iconv_copy;
return ret;
}
- while (from) {
- if (strcasecmp(from->name, fromcode) == 0) break;
- from = from->next;
+ for (i=0;i<ARRAY_SIZE(builtin_functions);i++) {
+ if (strcasecmp(fromcode, builtin_functions[i].name) == 0) {
+ from = &builtin_functions[i];
+ }
+ if (strcasecmp(tocode, builtin_functions[i].name) == 0) {
+ to = &builtin_functions[i];
+ }
}
- while (to) {
- if (strcasecmp(to->name, tocode) == 0) break;
- to = to->next;
+ if (from == NULL) {
+ for (from=charsets; from; from=from->next) {
+ if (strcasecmp(from->name, fromcode) == 0) break;
+ }
+ }
+
+ if (to == NULL) {
+ for (to=charsets; to; to=to->next) {
+ if (strcasecmp(to->name, tocode) == 0) break;
+ }
}
#ifdef HAVE_NATIVE_ICONV
if (!from) {
ret->pull = sys_iconv;
- ret->cd_pull = iconv_open("UCS-2LE", fromcode);
+ 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) goto failed;
}
if (!to) {
ret->push = sys_iconv;
- ret->cd_push = iconv_open(tocode, "UCS-2LE");
+ 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) goto failed;
}
#else
#endif
/* check for conversion to/from ucs2 */
- if (strcasecmp(fromcode, "UTF-16LE") == 0 && to) {
+ if (is_utf16(fromcode) && to) {
ret->direct = to->push;
return ret;
}
- if (strcasecmp(tocode, "UTF-16LE") == 0 && from) {
+ if (is_utf16(tocode) && from) {
ret->direct = from->pull;
return ret;
}
#ifdef HAVE_NATIVE_ICONV
- if (strcasecmp(fromcode, "UTF-16LE") == 0) {
+ if (is_utf16(fromcode)) {
ret->direct = sys_iconv;
ret->cd_direct = ret->cd_push;
ret->cd_push = NULL;
return ret;
}
- if (strcasecmp(tocode, "UTF-16LE") == 0) {
+ if (is_utf16(tocode)) {
ret->direct = sys_iconv;
ret->cd_direct = ret->cd_pull;
ret->cd_pull = NULL;
return ret;
failed:
- SAFE_FREE(ret);
+ talloc_free(ret);
errno = EINVAL;
return (smb_iconv_t)-1;
}
/*
simple iconv_close() wrapper
*/
-int smb_iconv_close (smb_iconv_t cd)
+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_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);
+ talloc_free(cd);
return 0;
}
return -1;
}
+
+