From 6243e2a30414ef059fe2fd3636563269f4b12d06 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 4 Aug 2005 23:56:18 +0000 Subject: r9078: - move charset stuff to lib/charset - don't use the global $LIBS variable for -liconv as $LIBS is not used anymore should fix the build on solaris 10 metze (This used to be commit 69ade058fde8e4cc62e4830c0b080e720d8e581d) --- source4/lib/charcnv.c | 723 ------------------------------------------ source4/lib/charset/charcnv.c | 723 ++++++++++++++++++++++++++++++++++++++++++ source4/lib/charset/config.m4 | 65 ++++ source4/lib/charset/config.mk | 10 + source4/lib/charset/iconv.c | 693 ++++++++++++++++++++++++++++++++++++++++ source4/lib/iconv.c | 693 ---------------------------------------- source4/lib/iconv.m4 | 66 ---- 7 files changed, 1491 insertions(+), 1482 deletions(-) delete mode 100644 source4/lib/charcnv.c create mode 100644 source4/lib/charset/charcnv.c create mode 100644 source4/lib/charset/config.m4 create mode 100644 source4/lib/charset/config.mk create mode 100644 source4/lib/charset/iconv.c delete mode 100644 source4/lib/iconv.c delete mode 100644 source4/lib/iconv.m4 (limited to 'source4/lib') diff --git a/source4/lib/charcnv.c b/source4/lib/charcnv.c deleted file mode 100644 index e632790155..0000000000 --- a/source4/lib/charcnv.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Character set conversion Extensions - Copyright (C) Igor Vergeichik 2001 - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Simo Sorce 2001 - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ -#include "includes.h" -#include "system/iconv.h" -#include "pstring.h" - -/** - * @file - * - * @brief Character-set conversion routines built on our iconv. - * - * @note Samba's internal character set (at least in the 3.0 series) - * is always the same as the one for the Unix filesystem. It is - * not necessarily UTF-8 and may be different on machines that - * need i18n filenames to be compatible with Unix software. It does - * have to be a superset of ASCII. All multibyte sequences must start - * with a byte with the high bit set. - * - * @sa lib/iconv.c - */ - -/** - * Return the name of a charset to give to iconv(). - **/ -static const char *charset_name(charset_t ch) -{ - const char *ret = NULL; - - if (ch == CH_UTF16) 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(); - else if (ch == CH_UTF8) ret = "UTF8"; - else if (ch == CH_UTF16BE) ret = "UTF-16BE"; - - if (!ret || !*ret) ret = "ASCII"; - return ret; -} - -static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; - -/** - re-initialize iconv conversion descriptors -**/ -void init_iconv(void) -{ - charset_t c1, c2; - for (c1=0;c1 - *
STR_TERMINATE
means include the null termination
- *
STR_UPPER
means uppercase in the destination
- * - * - * @param dest_len the maximum length in bytes allowed in the - * destination. If @p dest_len is -1 then no maximum is used. - **/ -ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) -{ - size_t src_len; - ssize_t ret; - - if (flags & STR_UPPER) { - char *tmpbuf = strupper_talloc(NULL, src); - if (tmpbuf == NULL) { - return -1; - } - ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER); - talloc_free(tmpbuf); - return ret; - } - - /* treat a pstring as "unlimited" length */ - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - src_len = strlen(src); - - if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) - src_len++; - - return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); -} - -/** - * Copy a string from a unix char* src to an ASCII destination, - * allocating a buffer using talloc(). - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - * or -1 in case of error. - **/ -ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - - *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest); -} - - -/** - * Copy a string from a dos codepage source to a unix char* destination. - * - * The resulting string in "dest" is always null terminated. - * - * @param flags can have: - *
- *
STR_TERMINATE
- *
STR_TERMINATE means the string in @p src - * is null terminated, and src_len is ignored.
- *
- * - * @param src_len is the length of the source area in bytes. - * @returns the number of bytes occupied by the string in @p src. - **/ -ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) -{ - size_t ret; - - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) { - if (src_len == (size_t)-1) { - src_len = strlen(src) + 1; - } else { - size_t len = strnlen(src, src_len); - if (len < src_len) - len++; - src_len = len; - } - } - - ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len); - - if (dest_len) - dest[MIN(ret, dest_len-1)] = 0; - - return src_len; -} - -/** - * Copy a string from a char* src to a unicode destination. - * - * @returns the number of bytes occupied by the string in the destination. - * - * @param flags can have: - * - *
- *
STR_TERMINATE
means include the null termination. - *
STR_UPPER
means uppercase in the destination. - *
STR_NOALIGN
means don't do alignment. - *
- * - * @param dest_len is the maximum length allowed in the - * destination. If dest_len is -1 then no maxiumum is used. - **/ -ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) -{ - size_t len=0; - size_t src_len = strlen(src); - size_t ret; - - if (flags & STR_UPPER) { - char *tmpbuf = strupper_talloc(NULL, src); - if (tmpbuf == NULL) { - return -1; - } - ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER); - talloc_free(tmpbuf); - return ret; - } - - /* treat a pstring as "unlimited" length */ - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (flags & STR_TERMINATE) - src_len++; - - if (ucs2_align(NULL, dest, flags)) { - *(char *)dest = 0; - dest = (void *)((char *)dest + 1); - if (dest_len) dest_len--; - len++; - } - - /* ucs2 is always a multiple of 2 bytes */ - dest_len &= ~1; - - ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len); - if (ret == (size_t)-1) { - return 0; - } - - len += ret; - - return len; -} - - -/** - * Copy a string from a unix char* src to a UCS2 destination, - * allocating a buffer using talloc(). - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - * or -1 in case of error. - **/ -ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest); -} - - -/** - * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - - *dest = NULL; - return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); -} - -/** - Copy a string from a ucs2 source to a unix char* destination. - Flags can have: - STR_TERMINATE means the string in src is null terminated. - STR_NOALIGN means don't try to align. - if STR_TERMINATE is set then src_len is ignored if it is -1. - src_len is the length of the source area in bytes - Return the number of bytes occupied by the string in src. - The resulting string in "dest" is always null terminated. -**/ - -size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) -{ - size_t ret; - - if (dest_len == (size_t)-1) - dest_len = sizeof(pstring); - - if (ucs2_align(NULL, src, flags)) { - src = (const void *)((const char *)src + 1); - if (src_len > 0) - src_len--; - } - - if (flags & STR_TERMINATE) { - if (src_len == (size_t)-1) { - src_len = utf16_len(src); - } else { - src_len = utf16_len_n(src, src_len); - } - } - - /* ucs2 is always a multiple of 2 bytes */ - if (src_len != (size_t)-1) - src_len &= ~1; - - ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len); - if (dest_len) - dest[MIN(ret, dest_len-1)] = 0; - - return src_len; -} - -/** - * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src) -{ - size_t src_len = utf16_len(src); - *dest = NULL; - return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest); -} - -/** - * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc - * - * @param dest always set at least to NULL - * - * @returns The number of bytes occupied by the string in the destination - **/ - -ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) -{ - size_t src_len = strlen(src)+1; - *dest = NULL; - return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest); -} - -/** - Copy a string from a char* src to a unicode or ascii - dos codepage destination choosing unicode or ascii based on the - flags in the SMB buffer starting at base_ptr. - Return the number of bytes occupied by the string in the destination. - flags can have: - STR_TERMINATE means include the null termination. - STR_UPPER means uppercase in the destination. - STR_ASCII use ascii even with unicode packet. - STR_NOALIGN means don't do alignment. - dest_len is the maximum length allowed in the destination. If dest_len - is -1 then no maxiumum is used. -**/ - -ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags) -{ - if (flags & STR_ASCII) { - return push_ascii(dest, src, dest_len, flags); - } else if (flags & STR_UNICODE) { - return push_ucs2(dest, src, dest_len, flags); - } else { - smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set"); - return -1; - } -} - - -/** - Copy a string from a unicode or ascii source (depending on - the packet flags) to a char* destination. - Flags can have: - STR_TERMINATE means the string in src is null terminated. - STR_UNICODE means to force as unicode. - STR_ASCII use ascii even with unicode packet. - STR_NOALIGN means don't do alignment. - if STR_TERMINATE is set then src_len is ignored is it is -1 - src_len is the length of the source area in bytes. - Return the number of bytes occupied by the string in src. - The resulting string in "dest" is always null terminated. -**/ - -ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) -{ - if (flags & STR_ASCII) { - return pull_ascii(dest, src, dest_len, src_len, flags); - } else if (flags & STR_UNICODE) { - return pull_ucs2(dest, src, dest_len, src_len, flags); - } else { - smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set"); - return -1; - } -} - - -/* - return the unicode codepoint for the next multi-byte CH_UNIX character - in the string - - also return the number of bytes consumed (which tells the caller - how many bytes to skip to get to the next CH_UNIX character) - - return INVALID_CODEPOINT if the next character cannot be converted -*/ -codepoint_t next_codepoint(const char *str, size_t *size) -{ - /* it cannot occupy more than 4 bytes in UTF16 format */ - uint8_t buf[4]; - smb_iconv_t descriptor; - size_t ilen_orig; - size_t ilen; - size_t olen; - char *outbuf; - - if ((str[0] & 0x80) == 0) { - *size = 1; - return (codepoint_t)str[0]; - } - - /* we assume that no multi-byte character can take - more than 5 bytes. This is OK as we only - support codepoints up to 1M */ - ilen_orig = strnlen(str, 5); - ilen = ilen_orig; - - descriptor = get_conv_handle(CH_UNIX, CH_UTF16); - if (descriptor == (smb_iconv_t)-1) { - *size = 1; - return INVALID_CODEPOINT; - } - - /* this looks a little strange, but it is needed to cope - with codepoints above 64k */ - olen = 2; - outbuf = buf; - smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); - if (olen == 2) { - olen = 4; - outbuf = buf; - smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); - if (olen == 4) { - /* we didn't convert any bytes */ - *size = 1; - return INVALID_CODEPOINT; - } - olen = 4 - olen; - } else { - olen = 2 - olen; - } - - *size = ilen_orig - ilen; - - if (olen == 2) { - return (codepoint_t)SVAL(buf, 0); - } - if (olen == 4) { - /* decode a 4 byte UTF16 character manually */ - return (codepoint_t)0x10000 + - (buf[2] | ((buf[3] & 0x3)<<8) | - (buf[0]<<10) | ((buf[1] & 0x3)<<18)); - } - - /* no other length is valid */ - return INVALID_CODEPOINT; -} - -/* - push a single codepoint into a CH_UNIX string the target string must - be able to hold the full character, which is guaranteed if it is at - least 5 bytes in size. The caller may pass less than 5 bytes if they - are sure the character will fit (for example, you can assume that - uppercase/lowercase of a character will not add more than 1 byte) - - return the number of bytes occupied by the CH_UNIX character, or - -1 on failure -*/ -ssize_t push_codepoint(char *str, codepoint_t c) -{ - smb_iconv_t descriptor; - uint8_t buf[4]; - size_t ilen, olen; - const char *inbuf; - - if (c < 128) { - *str = c; - return 1; - } - - descriptor = get_conv_handle(CH_UTF16, CH_UNIX); - if (descriptor == (smb_iconv_t)-1) { - return -1; - } - - if (c < 0x10000) { - ilen = 2; - olen = 5; - inbuf = buf; - SSVAL(buf, 0, c); - smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); - if (ilen != 0) { - return -1; - } - return 5 - olen; - } - - c -= 0x10000; - - buf[0] = (c>>10) & 0xFF; - buf[1] = (c>>18) | 0xd8; - buf[2] = c & 0xFF; - buf[3] = ((c>>8) & 0x3) | 0xdc; - - ilen = 4; - olen = 5; - inbuf = buf; - - smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); - if (ilen != 0) { - return -1; - } - return 5 - olen; -} diff --git a/source4/lib/charset/charcnv.c b/source4/lib/charset/charcnv.c new file mode 100644 index 0000000000..e632790155 --- /dev/null +++ b/source4/lib/charset/charcnv.c @@ -0,0 +1,723 @@ +/* + Unix SMB/CIFS implementation. + Character set conversion Extensions + Copyright (C) Igor Vergeichik 2001 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Simo Sorce 2001 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#include "includes.h" +#include "system/iconv.h" +#include "pstring.h" + +/** + * @file + * + * @brief Character-set conversion routines built on our iconv. + * + * @note Samba's internal character set (at least in the 3.0 series) + * is always the same as the one for the Unix filesystem. It is + * not necessarily UTF-8 and may be different on machines that + * need i18n filenames to be compatible with Unix software. It does + * have to be a superset of ASCII. All multibyte sequences must start + * with a byte with the high bit set. + * + * @sa lib/iconv.c + */ + +/** + * Return the name of a charset to give to iconv(). + **/ +static const char *charset_name(charset_t ch) +{ + const char *ret = NULL; + + if (ch == CH_UTF16) 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(); + else if (ch == CH_UTF8) ret = "UTF8"; + else if (ch == CH_UTF16BE) ret = "UTF-16BE"; + + if (!ret || !*ret) ret = "ASCII"; + return ret; +} + +static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; + +/** + re-initialize iconv conversion descriptors +**/ +void init_iconv(void) +{ + charset_t c1, c2; + for (c1=0;c1 + *
STR_TERMINATE
means include the null termination
+ *
STR_UPPER
means uppercase in the destination
+ * + * + * @param dest_len the maximum length in bytes allowed in the + * destination. If @p dest_len is -1 then no maximum is used. + **/ +ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t src_len; + ssize_t ret; + + if (flags & STR_UPPER) { + char *tmpbuf = strupper_talloc(NULL, src); + if (tmpbuf == NULL) { + return -1; + } + ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER); + talloc_free(tmpbuf); + return ret; + } + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + src_len = strlen(src); + + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) + src_len++; + + return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); +} + +/** + * Copy a string from a unix char* src to an ASCII destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ +ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest); +} + + +/** + * Copy a string from a dos codepage source to a unix char* destination. + * + * The resulting string in "dest" is always null terminated. + * + * @param flags can have: + *
+ *
STR_TERMINATE
+ *
STR_TERMINATE means the string in @p src + * is null terminated, and src_len is ignored.
+ *
+ * + * @param src_len is the length of the source area in bytes. + * @returns the number of bytes occupied by the string in @p src. + **/ +ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t ret; + + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) { + if (src_len == (size_t)-1) { + src_len = strlen(src) + 1; + } else { + size_t len = strnlen(src, src_len); + if (len < src_len) + len++; + src_len = len; + } + } + + ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len); + + if (dest_len) + dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + +/** + * Copy a string from a char* src to a unicode destination. + * + * @returns the number of bytes occupied by the string in the destination. + * + * @param flags can have: + * + *
+ *
STR_TERMINATE
means include the null termination. + *
STR_UPPER
means uppercase in the destination. + *
STR_NOALIGN
means don't do alignment. + *
+ * + * @param dest_len is the maximum length allowed in the + * destination. If dest_len is -1 then no maxiumum is used. + **/ +ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags) +{ + size_t len=0; + size_t src_len = strlen(src); + size_t ret; + + if (flags & STR_UPPER) { + char *tmpbuf = strupper_talloc(NULL, src); + if (tmpbuf == NULL) { + return -1; + } + ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER); + talloc_free(tmpbuf); + return ret; + } + + /* treat a pstring as "unlimited" length */ + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (flags & STR_TERMINATE) + src_len++; + + if (ucs2_align(NULL, dest, flags)) { + *(char *)dest = 0; + dest = (void *)((char *)dest + 1); + if (dest_len) dest_len--; + len++; + } + + /* ucs2 is always a multiple of 2 bytes */ + dest_len &= ~1; + + ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len); + if (ret == (size_t)-1) { + return 0; + } + + len += ret; + + return len; +} + + +/** + * Copy a string from a unix char* src to a UCS2 destination, + * allocating a buffer using talloc(). + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + * or -1 in case of error. + **/ +ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest); +} + + +/** + * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + + *dest = NULL; + return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); +} + +/** + Copy a string from a ucs2 source to a unix char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_NOALIGN means don't try to align. + if STR_TERMINATE is set then src_len is ignored if it is -1. + src_len is the length of the source area in bytes + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + size_t ret; + + if (dest_len == (size_t)-1) + dest_len = sizeof(pstring); + + if (ucs2_align(NULL, src, flags)) { + src = (const void *)((const char *)src + 1); + if (src_len > 0) + src_len--; + } + + if (flags & STR_TERMINATE) { + if (src_len == (size_t)-1) { + src_len = utf16_len(src); + } else { + src_len = utf16_len_n(src, src_len); + } + } + + /* ucs2 is always a multiple of 2 bytes */ + if (src_len != (size_t)-1) + src_len &= ~1; + + ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len); + if (dest_len) + dest[MIN(ret, dest_len-1)] = 0; + + return src_len; +} + +/** + * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src) +{ + size_t src_len = utf16_len(src); + *dest = NULL; + return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest); +} + +/** + * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest); +} + +/** + Copy a string from a char* src to a unicode or ascii + dos codepage destination choosing unicode or ascii based on the + flags in the SMB buffer starting at base_ptr. + Return the number of bytes occupied by the string in the destination. + flags can have: + STR_TERMINATE means include the null termination. + STR_UPPER means uppercase in the destination. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + dest_len is the maximum length allowed in the destination. If dest_len + is -1 then no maxiumum is used. +**/ + +ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags) +{ + if (flags & STR_ASCII) { + return push_ascii(dest, src, dest_len, flags); + } else if (flags & STR_UNICODE) { + return push_ucs2(dest, src, dest_len, flags); + } else { + smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; + } +} + + +/** + Copy a string from a unicode or ascii source (depending on + the packet flags) to a char* destination. + Flags can have: + STR_TERMINATE means the string in src is null terminated. + STR_UNICODE means to force as unicode. + STR_ASCII use ascii even with unicode packet. + STR_NOALIGN means don't do alignment. + if STR_TERMINATE is set then src_len is ignored is it is -1 + src_len is the length of the source area in bytes. + Return the number of bytes occupied by the string in src. + The resulting string in "dest" is always null terminated. +**/ + +ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags) +{ + if (flags & STR_ASCII) { + return pull_ascii(dest, src, dest_len, src_len, flags); + } else if (flags & STR_UNICODE) { + return pull_ucs2(dest, src, dest_len, src_len, flags); + } else { + smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set"); + return -1; + } +} + + +/* + return the unicode codepoint for the next multi-byte CH_UNIX character + in the string + + also return the number of bytes consumed (which tells the caller + how many bytes to skip to get to the next CH_UNIX character) + + return INVALID_CODEPOINT if the next character cannot be converted +*/ +codepoint_t next_codepoint(const char *str, size_t *size) +{ + /* it cannot occupy more than 4 bytes in UTF16 format */ + uint8_t buf[4]; + smb_iconv_t descriptor; + size_t ilen_orig; + size_t ilen; + size_t olen; + char *outbuf; + + if ((str[0] & 0x80) == 0) { + *size = 1; + return (codepoint_t)str[0]; + } + + /* we assume that no multi-byte character can take + more than 5 bytes. This is OK as we only + support codepoints up to 1M */ + ilen_orig = strnlen(str, 5); + ilen = ilen_orig; + + descriptor = get_conv_handle(CH_UNIX, CH_UTF16); + if (descriptor == (smb_iconv_t)-1) { + *size = 1; + return INVALID_CODEPOINT; + } + + /* this looks a little strange, but it is needed to cope + with codepoints above 64k */ + olen = 2; + outbuf = buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 2) { + olen = 4; + outbuf = buf; + smb_iconv(descriptor, &str, &ilen, &outbuf, &olen); + if (olen == 4) { + /* we didn't convert any bytes */ + *size = 1; + return INVALID_CODEPOINT; + } + olen = 4 - olen; + } else { + olen = 2 - olen; + } + + *size = ilen_orig - ilen; + + if (olen == 2) { + return (codepoint_t)SVAL(buf, 0); + } + if (olen == 4) { + /* decode a 4 byte UTF16 character manually */ + return (codepoint_t)0x10000 + + (buf[2] | ((buf[3] & 0x3)<<8) | + (buf[0]<<10) | ((buf[1] & 0x3)<<18)); + } + + /* no other length is valid */ + return INVALID_CODEPOINT; +} + +/* + push a single codepoint into a CH_UNIX string the target string must + be able to hold the full character, which is guaranteed if it is at + least 5 bytes in size. The caller may pass less than 5 bytes if they + are sure the character will fit (for example, you can assume that + uppercase/lowercase of a character will not add more than 1 byte) + + return the number of bytes occupied by the CH_UNIX character, or + -1 on failure +*/ +ssize_t push_codepoint(char *str, codepoint_t c) +{ + smb_iconv_t descriptor; + uint8_t buf[4]; + size_t ilen, olen; + const char *inbuf; + + if (c < 128) { + *str = c; + return 1; + } + + descriptor = get_conv_handle(CH_UTF16, CH_UNIX); + if (descriptor == (smb_iconv_t)-1) { + return -1; + } + + if (c < 0x10000) { + ilen = 2; + olen = 5; + inbuf = buf; + SSVAL(buf, 0, c); + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; + } + + c -= 0x10000; + + buf[0] = (c>>10) & 0xFF; + buf[1] = (c>>18) | 0xd8; + buf[2] = c & 0xFF; + buf[3] = ((c>>8) & 0x3) | 0xdc; + + ilen = 4; + olen = 5; + inbuf = buf; + + smb_iconv(descriptor, &inbuf, &ilen, &str, &olen); + if (ilen != 0) { + return -1; + } + return 5 - olen; +} diff --git a/source4/lib/charset/config.m4 b/source4/lib/charset/config.m4 new file mode 100644 index 0000000000..9812c356ff --- /dev/null +++ b/source4/lib/charset/config.m4 @@ -0,0 +1,65 @@ +dnl # ICONV/CHARSET subsystem + +ICONV_LOCATION=standard +LOOK_DIRS="/usr /usr/local /sw" +AC_ARG_WITH(libiconv, +[ --with-libiconv=BASEDIR Use libiconv in BASEDIR/lib and BASEDIR/include (default=auto) ], +[ + if test "$withval" = "no" ; then + AC_MSG_ERROR(I won't take no for an answer) + else + if test "$withval" != "yes" ; then + LOOK_DIRS="$withval $LOOK_DIRS" + fi + fi +]) + +ICONV_FOUND="no" +for i in $LOOK_DIRS ; do + save_LIBS=$LIBS + save_LDFLAGS=$LDFLAGS + save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="-I$i/include" + LDFLAGS="-L$i/lib" + LIBS= + export LDFLAGS LIBS CPPFLAGS +dnl Try to find iconv(3) + jm_ICONV($i) + + TMP_ICONV_LIBS="$LIBS" + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + export LDFLAGS LIBS CPPFLAGS + + if test -n "$ICONV_FOUND" ; then + LIB_ADD_DIR(ICONV_LDFLAGS, $i/lib) + CFLAGS_ADD_DIR(ICONV_CPPFLAGS, $i/include) + ICONV_LIBS="$TMP_ICONV_LIBS" + break + fi +done + +############ +# check for iconv in libc +AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ +AC_TRY_RUN([ +#include +main() { + iconv_t cd = iconv_open("ASCII", "UCS-2LE"); + if (cd == 0 || cd == (iconv_t)-1) return -1; + return 0; +} +], +samba_cv_HAVE_NATIVE_ICONV=yes,samba_cv_HAVE_NATIVE_ICONV=no,samba_cv_HAVE_NATIVE_ICONV=cross)]) +if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then + AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) +fi + +if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; then + AC_MSG_WARN([Sufficient support for iconv function was not found. + Install libiconv from http://freshmeat.net/projects/libiconv/ for better charset compatibility!]) +fi + +SMB_EXT_LIB(ICONV,[${ICONV_LIBS}],[${ICONV_CFLAGS}],[${ICONV_CPPFLAGS}],[${ICONV_LDFLAGS}]) diff --git a/source4/lib/charset/config.mk b/source4/lib/charset/config.mk new file mode 100644 index 0000000000..6b0fe02b72 --- /dev/null +++ b/source4/lib/charset/config.mk @@ -0,0 +1,10 @@ +################################################ +# Start SUBSYSTEM CHARSET +[SUBSYSTEM::CHARSET] +INIT_OBJ_FILES = \ + lib/charset/iconv.o +ADD_OBJ_FILES = \ + lib/charset/charcnv.o +REQUIRED_SUBSYSTEMS = EXT_LIB_ICONV +# End SUBSYSTEM CHARSET +################################################ diff --git a/source4/lib/charset/iconv.c b/source4/lib/charset/iconv.c new file mode 100644 index 0000000000..df590444e5 --- /dev/null +++ b/source4/lib/charset/iconv.c @@ -0,0 +1,693 @@ +/* + Unix SMB/CIFS implementation. + minimal iconv implementation + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Jelmer Vernooij 2002 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" +#include "system/iconv.h" +#include "system/filesys.h" + + +/** + * @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 UTF-16LE and + * compare there. + * + * @sa Samba Developers Guide + **/ + +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 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 const struct charset_functions builtin_functions[] = { + /* windows is closest to 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}, + {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} +}; + +static struct charset_functions *charsets = NULL; + +NTSTATUS charset_register_backend(const void *_funcs) +{ + struct charset_functions *funcs = memdup(_funcs,sizeof(struct charset_functions)); + struct charset_functions *c = charsets; + + /* Check whether we already have this charset... */ + while(c) { + if(!strcasecmp(c->name, funcs->name)){ + DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + c = c->next; + } + + funcs->next = funcs->prev = NULL; + DLIST_ADD(charsets, funcs); + return NT_STATUS_OK; +} + +#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, + discard_const_p(char *, inbuf), inbytesleft, + outbuf, outbytesleft); + if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); + 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]; + 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) { + char *bufp1 = cvtbuf; + const char *bufp2 = cvtbuf; + + bufsize = sizeof(cvtbuf); + + if (cd->pull(cd->cd_pull, + inbuf, inbytesleft, &bufp1, &bufsize) == -1 + && errno != E2BIG) return -1; + + bufsize = sizeof(cvtbuf) - bufsize; + + if (cd->push(cd->cd_push, + &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; + const struct charset_functions *from=NULL, *to=NULL; + int i; + + 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)); + + /* check for the simplest null conversion */ + if (strcmp(fromcode, tocode) == 0) { + ret->direct = iconv_copy; + return ret; + } + + for (i=0;inext) { + 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("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, "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 + if (!from || !to) { + goto failed; + } +#endif + + /* check for conversion to/from ucs2 */ + if (is_utf16(fromcode) && to) { + ret->direct = to->push; + return ret; + } + if (is_utf16(tocode) && from) { + ret->direct = from->pull; + return ret; + } + +#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 + + /* the general case has to go via a buffer */ + if (!ret->pull) ret->pull = from->pull; + if (!ret->push) ret->push = to->push; + return ret; + +failed: + talloc_free(ret); + errno = EINVAL; + return (smb_iconv_t)-1; +} + +/* + 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 + + talloc_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 ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + uint_t 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_t *c = (const uint8_t *)*inbuf; + uint8_t *uc = (uint8_t *)*outbuf; + + while (in_left >= 1 && out_left >= 2) { + 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; + } + uc[1] = (c[0]>>2) & 0x7; + uc[0] = (c[0]<<6) | (c[1]&0x3f); + 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; + } + uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF); + uc[0] = (c[1]<<6) | (c[2]&0x3f); + c += 3; + in_left -= 3; + out_left -= 2; + uc += 2; + continue; + } + + if ((c[0] & 0xf8) == 0xf0) { + unsigned int codepoint; + 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) { + /* accept UTF-8 characters that are not + minimally packed, but pack the result */ + uc[0] = (codepoint & 0xFF); + uc[1] = (codepoint >> 8); + c += 4; + in_left -= 4; + out_left -= 2; + uc += 2; + continue; + } + + 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 = c; + *outbuf = uc; + return 0; + +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = c; + *outbuf = 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_t *c = (uint8_t *)*outbuf; + const uint8_t *uc = (const uint8_t *)*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 = uc; + *outbuf = c; + + return 0; + +error: + *inbytesleft = in_left; + *outbytesleft = out_left; + *inbuf = uc; + *outbuf = c; + return -1; +} + + + diff --git a/source4/lib/iconv.c b/source4/lib/iconv.c deleted file mode 100644 index df590444e5..0000000000 --- a/source4/lib/iconv.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - Unix SMB/CIFS implementation. - minimal iconv implementation - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jelmer Vernooij 2002 - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "dlinklist.h" -#include "system/iconv.h" -#include "system/filesys.h" - - -/** - * @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 UTF-16LE and - * compare there. - * - * @sa Samba Developers Guide - **/ - -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 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 const struct charset_functions builtin_functions[] = { - /* windows is closest to 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}, - {"UCS2-HEX", ucs2hex_pull, ucs2hex_push} -}; - -static struct charset_functions *charsets = NULL; - -NTSTATUS charset_register_backend(const void *_funcs) -{ - struct charset_functions *funcs = memdup(_funcs,sizeof(struct charset_functions)); - struct charset_functions *c = charsets; - - /* Check whether we already have this charset... */ - while(c) { - if(!strcasecmp(c->name, funcs->name)){ - DEBUG(2, ("Duplicate charset %s, not registering\n", funcs->name)); - return NT_STATUS_OBJECT_NAME_COLLISION; - } - c = c->next; - } - - funcs->next = funcs->prev = NULL; - DLIST_ADD(charsets, funcs); - return NT_STATUS_OK; -} - -#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, - discard_const_p(char *, inbuf), inbytesleft, - outbuf, outbytesleft); - if (ret == (size_t)-1) iconv(cd, NULL, NULL, NULL, NULL); - 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]; - 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) { - char *bufp1 = cvtbuf; - const char *bufp2 = cvtbuf; - - bufsize = sizeof(cvtbuf); - - if (cd->pull(cd->cd_pull, - inbuf, inbytesleft, &bufp1, &bufsize) == -1 - && errno != E2BIG) return -1; - - bufsize = sizeof(cvtbuf) - bufsize; - - if (cd->push(cd->cd_push, - &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; - const struct charset_functions *from=NULL, *to=NULL; - int i; - - 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)); - - /* check for the simplest null conversion */ - if (strcmp(fromcode, tocode) == 0) { - ret->direct = iconv_copy; - return ret; - } - - for (i=0;inext) { - 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("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, "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 - if (!from || !to) { - goto failed; - } -#endif - - /* check for conversion to/from ucs2 */ - if (is_utf16(fromcode) && to) { - ret->direct = to->push; - return ret; - } - if (is_utf16(tocode) && from) { - ret->direct = from->pull; - return ret; - } - -#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 - - /* the general case has to go via a buffer */ - if (!ret->pull) ret->pull = from->pull; - if (!ret->push) ret->push = to->push; - return ret; - -failed: - talloc_free(ret); - errno = EINVAL; - return (smb_iconv_t)-1; -} - -/* - 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 - - talloc_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 ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, - char **outbuf, size_t *outbytesleft) -{ - while (*inbytesleft >= 1 && *outbytesleft >= 2) { - uint_t 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_t *c = (const uint8_t *)*inbuf; - uint8_t *uc = (uint8_t *)*outbuf; - - while (in_left >= 1 && out_left >= 2) { - 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; - } - uc[1] = (c[0]>>2) & 0x7; - uc[0] = (c[0]<<6) | (c[1]&0x3f); - 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; - } - uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF); - uc[0] = (c[1]<<6) | (c[2]&0x3f); - c += 3; - in_left -= 3; - out_left -= 2; - uc += 2; - continue; - } - - if ((c[0] & 0xf8) == 0xf0) { - unsigned int codepoint; - 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) { - /* accept UTF-8 characters that are not - minimally packed, but pack the result */ - uc[0] = (codepoint & 0xFF); - uc[1] = (codepoint >> 8); - c += 4; - in_left -= 4; - out_left -= 2; - uc += 2; - continue; - } - - 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 = c; - *outbuf = uc; - return 0; - -error: - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = c; - *outbuf = 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_t *c = (uint8_t *)*outbuf; - const uint8_t *uc = (const uint8_t *)*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 = uc; - *outbuf = c; - - return 0; - -error: - *inbytesleft = in_left; - *outbytesleft = out_left; - *inbuf = uc; - *outbuf = c; - return -1; -} - - - diff --git a/source4/lib/iconv.m4 b/source4/lib/iconv.m4 deleted file mode 100644 index 282fa69b2d..0000000000 --- a/source4/lib/iconv.m4 +++ /dev/null @@ -1,66 +0,0 @@ -dnl # ICONV/CHARSET subsystem - -ICONV_LOCATION=standard -LOOK_DIRS="/usr /usr/local /sw" -AC_ARG_WITH(libiconv, -[ --with-libiconv=BASEDIR Use libiconv in BASEDIR/lib and BASEDIR/include (default=auto) ], -[ - if test "$withval" = "no" ; then - AC_MSG_ERROR(I won't take no for an answer) - else - if test "$withval" != "yes" ; then - LOOK_DIRS="$withval $LOOK_DIRS" - fi - fi -]) - -ICONV_FOUND="no" -for i in $LOOK_DIRS ; do - save_LIBS=$LIBS - save_LDFLAGS=$LDFLAGS - save_CPPFLAGS=$CPPFLAGS - CPPFLAGS="-I$i/include" - LDFLAGS="-L$i/lib" - LIBS= - export LDFLAGS LIBS CPPFLAGS -dnl Try to find iconv(3) - jm_ICONV($i) - - CPPFLAGS=$save_CPPFLAGS - if test -n "$ICONV_FOUND" ; then - LDFLAGS=$save_LDFLAGS - LIB_ADD_DIR(LDFLAGS, "$i/lib") - CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") - LIBS="$save_LIBS $LIBS" - ICONV_LOCATION=$i - export LDFLAGS LIBS CPPFLAGS - break - else - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS - export LDFLAGS LIBS CPPFLAGS - fi -done - -############ -# check for iconv in libc -AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ -AC_TRY_RUN([ -#include -main() { - iconv_t cd = iconv_open("ASCII", "UCS-2LE"); - if (cd == 0 || cd == (iconv_t)-1) return -1; - return 0; -} -], -samba_cv_HAVE_NATIVE_ICONV=yes,samba_cv_HAVE_NATIVE_ICONV=no,samba_cv_HAVE_NATIVE_ICONV=cross)]) -if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then - AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) -fi - -if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; then - AC_MSG_WARN([Sufficient support for iconv function was not found. - Install libiconv from http://freshmeat.net/projects/libiconv/ for better charset compatibility!]) -fi - -SMB_SUBSYSTEM(CHARSET,lib/iconv.o,lib/charcnv.o,[${TMP_CHARSET_LIBS}]) -- cgit