2 Unix SMB/CIFS implementation.
3 Character set conversion Extensions
4 Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5 Copyright (C) Andrew Tridgell 2001
6 Copyright (C) Simo Sorce 2001
7 Copyright (C) Jelmer Vernooij 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/iconv.h"
25 #include "libcli/smb/smb_common.h"
30 * @brief Character-set conversion routines built on our iconv.
32 * @note Samba's internal character set (at least in the 3.0 series)
33 * is always the same as the one for the Unix filesystem. It is
34 * <b>not</b> necessarily UTF-8 and may be different on machines that
35 * need i18n filenames to be compatible with Unix software. It does
36 * have to be a superset of ASCII. All multibyte sequences must start
37 * with a byte with the high bit set.
43 * Convert string from one encoding to another, making error checking etc
45 * @param mem_ctx Memory context
46 * @param cd Iconv handle
47 * @param src pointer to source string (multibyte or singlebyte)
48 * @param srclen length of the source string in bytes
49 * @param dest pointer to destination string (multibyte or singlebyte)
50 * @param destlen maximal length allowed for string
51 * @returns the number of bytes occupied in the destination
53 _PUBLIC_ ssize_t iconv_talloc(TALLOC_CTX *ctx,
55 void const *src, size_t srclen,
58 size_t i_len, o_len, destlen;
59 void **dest = (void **)dst;
61 const char *inbuf = (const char *)src;
66 /* it is _very_ rare that a conversion increases the size by
71 destlen = 2 + (destlen*3);
72 ob = talloc_realloc(ctx, outbuf, char, destlen);
74 DEBUG(0, ("iconv_talloc: realloc failed!\n"));
81 /* we give iconv 2 less bytes to allow us to terminate at the
85 retval = smb_iconv(cd,
88 if(retval == (size_t)-1) {
89 const char *reason="unknown error";
92 reason="Incomplete multibyte sequence";
97 reason="Illegal multibyte sequence";
100 DEBUG(0,("Conversion error: %s - ",reason));
101 dump_data(0, (const uint8_t *) inbuf, i_len);
106 destlen = (destlen-2) - o_len;
108 /* guarantee null termination in all charsets */
109 SSVAL(ob, destlen, 0);
118 * Convert string from one encoding to another, making error checking etc
120 * @param src pointer to source string (multibyte or singlebyte)
121 * @param srclen length of the source string in bytes
122 * @param dest pointer to destination string (multibyte or singlebyte)
123 * @param destlen maximal length allowed for string
124 * @returns the number of bytes occupied in the destination
125 * on error, returns -1, and sets errno
127 _PUBLIC_ ssize_t convert_string_error(struct smb_iconv_handle *ic,
128 charset_t from, charset_t to,
129 void const *src, size_t srclen,
130 void *dest, size_t destlen, size_t *converted_size)
134 const char* inbuf = (const char*)src;
135 char* outbuf = (char*)dest;
136 smb_iconv_t descriptor;
138 if (srclen == (size_t)-1)
139 srclen = strlen(inbuf)+1;
141 descriptor = get_conv_handle(ic, from, to);
142 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
143 if (converted_size) {
153 retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
155 if (converted_size != NULL)
156 *converted_size = destlen-o_len;
162 * Convert string from one encoding to another, making error checking etc
164 * @param src pointer to source string (multibyte or singlebyte)
165 * @param srclen length of the source string in bytes
166 * @param dest pointer to destination string (multibyte or singlebyte)
167 * @param destlen maximal length allowed for string
168 * @returns the number of bytes occupied in the destination
170 _PUBLIC_ bool convert_string_handle(struct smb_iconv_handle *ic,
171 charset_t from, charset_t to,
172 void const *src, size_t srclen,
173 void *dest, size_t destlen, size_t *converted_size)
177 retval = convert_string_error(ic, from, to, src, srclen, dest, destlen, converted_size);
178 if(retval==(size_t)-1) {
182 reason="Incomplete multibyte sequence";
185 reason="No more room";
186 if (from == CH_UNIX) {
187 DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d - '%s'\n",
188 charset_name(ic, from), charset_name(ic, to),
189 (int)srclen, (int)destlen,
192 DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d\n",
193 charset_name(ic, from), charset_name(ic, to),
194 (int)srclen, (int)destlen));
198 reason="Illegal multibyte sequence";
208 * Convert between character sets, allocating a new buffer using talloc for the result.
210 * @param srclen length of source buffer.
211 * @param dest always set at least to NULL
212 * @note -1 is not accepted for srclen.
214 * @returns Size in bytes of the converted string; or -1 in case of error.
217 _PUBLIC_ bool convert_string_talloc_handle(TALLOC_CTX *ctx,
218 struct smb_iconv_handle *ic,
219 charset_t from, charset_t to,
220 void const *src, size_t srclen,
221 void *dst, size_t *converted_size)
223 void **dest = (void **)dst;
224 smb_iconv_t descriptor;
229 if (src == NULL || srclen == (size_t)-1 || srclen == 0)
232 descriptor = get_conv_handle(ic, from, to);
234 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
235 /* conversion not supported, return -1*/
236 DEBUG(3, ("convert_string_talloc: conversion from %s to %s not supported!\n",
237 charset_name(ic, from),
238 charset_name(ic, to)));
242 ret = iconv_talloc(ctx, descriptor, src, srclen, dest);
245 if (converted_size != NULL)
246 *converted_size = ret;