diff options
author | Jeremy Allison <jra@samba.org> | 2004-08-30 21:35:43 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:52:32 -0500 |
commit | 651daa4b4256455b26b0affcdc45fe328b128c99 (patch) | |
tree | 90abd017d3dd931fb128aecef300e6424b9f8179 /source3/lib | |
parent | f1688d61df13aacb0e512fd16504cc94f803d808 (diff) | |
download | samba-651daa4b4256455b26b0affcdc45fe328b128c99.tar.gz samba-651daa4b4256455b26b0affcdc45fe328b128c99.tar.bz2 samba-651daa4b4256455b26b0affcdc45fe328b128c99.zip |
r2114: Shameless theft of iconv commit from Samba4 to keep the two libs more in sync :-).
try to cope with a wider range of UTF-16 characters when we are using
an external libiconv library.
Jeremy.
(This used to be commit 5d04cd6804f6fc3b556e7c3b53fa0d7af39797c1)
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/charcnv.c | 10 | ||||
-rw-r--r-- | source3/lib/iconv.c | 79 |
2 files changed, 60 insertions, 29 deletions
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 6cbf7562b0..21d34f30cb 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -56,7 +56,7 @@ static const char *charset_name(charset_t ch) { const char *ret = NULL; - if (ch == CH_UCS2) ret = "UCS-2LE"; + if (ch == CH_UCS2) ret = "UTF-16LE"; else if (ch == CH_UNIX) ret = lp_unix_charset(); else if (ch == CH_DOS) ret = lp_dos_charset(); else if (ch == CH_DISPLAY) ret = lp_display_charset(); @@ -116,10 +116,10 @@ void init_iconv(void) /* so that charset_name() works we need to get the UNIX<->UCS2 going first */ if (!conv_handles[CH_UNIX][CH_UCS2]) - conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII"); + conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII"); if (!conv_handles[CH_UCS2][CH_UNIX]) - conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE"); + conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2)); for (c1=0;c1<NUM_CHARSETS;c1++) { for (c2=0;c2<NUM_CHARSETS;c2++) { @@ -216,7 +216,7 @@ static size_t convert_string_internal(charset_t from, charset_t to, again: - retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len); + retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); if(retval==(size_t)-1) { const char *reason="unknown error"; switch(errno) { @@ -531,7 +531,7 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, again: retval = smb_iconv(descriptor, - (char **)&inbuf, &i_len, + &inbuf, &i_len, &outbuf, &o_len); if(retval == (size_t)-1) { const char *reason="unknown error"; diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index 4c9ecf992e..e10e42328c 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -51,18 +51,25 @@ * @sa Samba Developers Guide **/ -static size_t ascii_pull(void *,char **, size_t *, char **, size_t *); -static size_t ascii_push(void *,char **, size_t *, char **, size_t *); -static size_t latin1_push(void *,char **, size_t *, char **, size_t *); -static size_t utf8_pull(void *,char **, size_t *, char **, size_t *); -static size_t utf8_push(void *,char **, size_t *, char **, size_t *); -static size_t ucs2hex_pull(void *,char **, size_t *, char **, size_t *); -static size_t ucs2hex_push(void *,char **, size_t *, char **, size_t *); -static size_t iconv_copy(void *,char **, size_t *, char **, size_t *); +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}, + + /* 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}, @@ -122,12 +129,12 @@ static void lazy_initialize_iconv(void) this ensures that we don't have a shift state remaining for character sets like SJIS */ static size_t sys_iconv(void *cd, - char **inbuf, size_t *inbytesleft, + const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { #ifdef HAVE_NATIVE_ICONV size_t ret = iconv((iconv_t)cd, - inbuf, inbytesleft, + (char **)inbuf, inbytesleft, outbuf, outbytesleft); if (ret == (size_t)-1) { int saved_errno = errno; @@ -148,7 +155,7 @@ static size_t sys_iconv(void *cd, * enough that Samba works on systems that don't have iconv. **/ size_t smb_iconv(smb_iconv_t cd, - char **inbuf, size_t *inbytesleft, + const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { char cvtbuf[2048]; @@ -158,7 +165,7 @@ size_t smb_iconv(smb_iconv_t cd, /* in many cases we can go direct */ if (cd->direct) { return cd->direct(cd->cd_direct, - (char **)inbuf, inbytesleft, outbuf, outbytesleft); + inbuf, inbytesleft, outbuf, outbytesleft); } @@ -168,14 +175,14 @@ size_t smb_iconv(smb_iconv_t cd, bufsize = sizeof(cvtbuf); if (cd->pull(cd->cd_pull, - (char **)inbuf, inbytesleft, &bufp, &bufsize) == -1 + inbuf, inbytesleft, &bufp, &bufsize) == -1 && errno != E2BIG) return -1; bufp = cvtbuf; bufsize = sizeof(cvtbuf) - bufsize; if (cd->push(cd->cd_push, - &bufp, &bufsize, + (const char **)&bufp, &bufsize, outbuf, outbytesleft) == -1) return -1; } @@ -313,7 +320,7 @@ int smb_iconv_close (smb_iconv_t cd) multi-byte character set support for english users ***********************************************************************/ -static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { @@ -333,7 +340,7 @@ static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft, return 0; } -static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int ir_count=0; @@ -360,7 +367,7 @@ static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft, return ir_count; } -static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int ir_count=0; @@ -387,7 +394,7 @@ static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft, return ir_count; } -static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { @@ -430,7 +437,7 @@ static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft, return 0; } -static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 2 && *outbytesleft >= 1) { @@ -471,8 +478,32 @@ static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft, 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, char **inbuf, size_t *inbytesleft, +static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int n; @@ -494,11 +525,11 @@ static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft, return 0; } -static size_t utf8_pull(void *cd, char **inbuf, size_t *inbytesleft, +static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { - unsigned char *c = (unsigned char *)*inbuf; + const unsigned char *c = (const unsigned char *)*inbuf; unsigned char *uc = (unsigned char *)*outbuf; int len = 1; @@ -541,12 +572,12 @@ badseq: return -1; } -static size_t utf8_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 2 && *outbytesleft >= 1) { unsigned char *c = (unsigned char *)*outbuf; - unsigned char *uc = (unsigned char *)*inbuf; + const unsigned char *uc = (const unsigned char *)*inbuf; int len=1; if (uc[1] & 0xf8) { |