wafsamba: ensure TO_LIST does not fail with empty string
[Samba/gebeck_regimport.git] / source3 / lib / charcnv.c
blob5863d72f38059fb611db20de83b06e84be1611df
1 /*
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) Martin Pool 2003
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/>.
23 #include "includes.h"
25 /**
26 * Destroy global objects allocated by init_iconv()
27 **/
28 void gfree_charcnv(void)
30 TALLOC_FREE(global_iconv_handle);
33 /**
34 * Copy a string from a char* unix src to a dos codepage string destination.
36 * @return the number of bytes occupied by the string in the destination.
38 * @param flags can include
39 * <dl>
40 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
41 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
42 * </dl>
44 * @param dest_len the maximum length in bytes allowed in the
45 * destination.
46 **/
47 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
49 size_t src_len = strlen(src);
50 char *tmpbuf = NULL;
51 size_t size;
52 bool ret;
54 /* No longer allow a length of -1. */
55 if (dest_len == (size_t)-1) {
56 smb_panic("push_ascii - dest_len == -1");
59 if (flags & STR_UPPER) {
60 tmpbuf = SMB_STRDUP(src);
61 if (!tmpbuf) {
62 smb_panic("malloc fail");
64 strupper_m(tmpbuf);
65 src = tmpbuf;
68 if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
69 src_len++;
72 ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, &size);
73 if (ret == false &&
74 (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
75 && dest_len > 0) {
76 ((char *)dest)[0] = '\0';
78 SAFE_FREE(tmpbuf);
79 return ret ? size : (size_t)-1;
82 /********************************************************************
83 Push and malloc an ascii string. src and dest null terminated.
84 ********************************************************************/
86 /**
87 * Copy a string from a dos codepage source to a unix char* destination.
89 * The resulting string in "dest" is always null terminated.
91 * @param flags can have:
92 * <dl>
93 * <dt>STR_TERMINATE</dt>
94 * <dd>STR_TERMINATE means the string in @p src
95 * is null terminated, and src_len is ignored.</dd>
96 * </dl>
98 * @param src_len is the length of the source area in bytes.
99 * @returns the number of bytes occupied by the string in @p src.
101 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
103 bool ret;
104 size_t size = 0;
106 if (dest_len == (size_t)-1) {
107 /* No longer allow dest_len of -1. */
108 smb_panic("pull_ascii - invalid dest_len of -1");
111 if (flags & STR_TERMINATE) {
112 if (src_len == (size_t)-1) {
113 src_len = strlen((const char *)src) + 1;
114 } else {
115 size_t len = strnlen((const char *)src, src_len);
116 if (len < src_len)
117 len++;
118 src_len = len;
122 ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, &size);
123 if (ret == false) {
124 size = 0;
125 dest_len = 0;
128 if (dest_len && size) {
129 /* Did we already process the terminating zero ? */
130 if (dest[MIN(size-1, dest_len-1)] != 0) {
131 dest[MIN(size, dest_len-1)] = 0;
133 } else {
134 dest[0] = 0;
137 return src_len;
141 * Copy a string from a dos codepage source to a unix char* destination.
142 * Talloc version.
144 * The resulting string in "dest" is always null terminated.
146 * @param flags can have:
147 * <dl>
148 * <dt>STR_TERMINATE</dt>
149 * <dd>STR_TERMINATE means the string in @p src
150 * is null terminated, and src_len is ignored.</dd>
151 * </dl>
153 * @param src_len is the length of the source area in bytes.
154 * @returns the number of bytes occupied by the string in @p src.
157 static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
158 char **ppdest,
159 const void *src,
160 size_t src_len,
161 int flags)
163 char *dest = NULL;
164 size_t dest_len;
166 *ppdest = NULL;
168 if (!src_len) {
169 return 0;
172 if (src_len == (size_t)-1) {
173 smb_panic("sec_len == -1 in pull_ascii_base_talloc");
176 if (flags & STR_TERMINATE) {
177 size_t len = strnlen((const char *)src, src_len);
178 if (len < src_len)
179 len++;
180 src_len = len;
181 /* Ensure we don't use an insane length from the client. */
182 if (src_len >= 1024*1024) {
183 char *msg = talloc_asprintf(ctx,
184 "Bad src length (%u) in "
185 "pull_ascii_base_talloc",
186 (unsigned int)src_len);
187 smb_panic(msg);
191 /* src_len != -1 here. */
193 if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
194 &dest_len)) {
195 dest_len = 0;
198 if (dest_len && dest) {
199 /* Did we already process the terminating zero ? */
200 if (dest[dest_len-1] != 0) {
201 size_t size = talloc_get_size(dest);
202 /* Have we got space to append the '\0' ? */
203 if (size <= dest_len) {
204 /* No, realloc. */
205 dest = talloc_realloc(ctx, dest, char,
206 dest_len+1);
207 if (!dest) {
208 /* talloc fail. */
209 dest_len = (size_t)-1;
210 return 0;
213 /* Yay - space ! */
214 dest[dest_len] = '\0';
215 dest_len++;
217 } else if (dest) {
218 dest[0] = 0;
221 *ppdest = dest;
222 return src_len;
226 * Copy a string from a char* src to a unicode destination.
228 * @returns the number of bytes occupied by the string in the destination.
230 * @param flags can have:
232 * <dl>
233 * <dt>STR_TERMINATE <dd>means include the null termination.
234 * <dt>STR_UPPER <dd>means uppercase in the destination.
235 * <dt>STR_NOALIGN <dd>means don't do alignment.
236 * </dl>
238 * @param dest_len is the maximum length allowed in the
239 * destination.
242 static size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
244 size_t len=0;
245 size_t src_len;
246 size_t size = 0;
247 bool ret;
249 if (dest_len == (size_t)-1) {
250 /* No longer allow dest_len of -1. */
251 smb_panic("push_ucs2 - invalid dest_len of -1");
254 if (flags & STR_TERMINATE)
255 src_len = (size_t)-1;
256 else
257 src_len = strlen(src);
259 if (ucs2_align(base_ptr, dest, flags)) {
260 *(char *)dest = 0;
261 dest = (void *)((char *)dest + 1);
262 if (dest_len)
263 dest_len--;
264 len++;
267 /* ucs2 is always a multiple of 2 bytes */
268 dest_len &= ~1;
270 ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, &size);
271 if (ret == false) {
272 if ((flags & STR_TERMINATE) &&
273 dest &&
274 dest_len) {
275 *(char *)dest = 0;
277 return len;
280 len += size;
282 if (flags & STR_UPPER) {
283 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
284 size_t i;
286 /* We check for i < (ret / 2) below as the dest string isn't null
287 terminated if STR_TERMINATE isn't set. */
289 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
290 smb_ucs2_t v = toupper_w(dest_ucs2[i]);
291 if (v != dest_ucs2[i]) {
292 dest_ucs2[i] = v;
297 return len;
301 Copy a string from a ucs2 source to a unix char* destination.
302 Talloc version with a base pointer.
303 Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
304 needs fixing. JRA).
305 Flags can have:
306 STR_TERMINATE means the string in src is null terminated.
307 STR_NOALIGN means don't try to align.
308 if STR_TERMINATE is set then src_len is ignored if it is -1.
309 src_len is the length of the source area in bytes
310 Return the number of bytes occupied by the string in src.
311 The resulting string in "dest" is always null terminated.
314 static size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
315 const void *base_ptr,
316 char **ppdest,
317 const void *src,
318 size_t src_len,
319 int flags)
321 char *dest;
322 size_t dest_len;
323 size_t ucs2_align_len = 0;
325 *ppdest = NULL;
327 #ifdef DEVELOPER
328 /* Ensure we never use the braindead "malloc" varient. */
329 if (ctx == NULL) {
330 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
332 #endif
334 if (!src_len) {
335 return 0;
338 if (src_len == (size_t)-1) {
339 /* no longer used anywhere, but worth checking */
340 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
343 if (ucs2_align(base_ptr, src, flags)) {
344 src = (const void *)((const char *)src + 1);
345 src_len--;
346 ucs2_align_len = 1;
349 if (flags & STR_TERMINATE) {
350 /* src_len -1 is the default for null terminated strings. */
351 size_t len = strnlen_w((const smb_ucs2_t *)src,
352 src_len/2);
353 if (len < src_len/2)
354 len++;
355 src_len = len*2;
357 /* Ensure we don't use an insane length from the client. */
358 if (src_len >= 1024*1024) {
359 smb_panic("Bad src length in pull_ucs2_base_talloc\n");
363 /* ucs2 is always a multiple of 2 bytes */
364 src_len &= ~1;
366 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
367 (void *)&dest, &dest_len)) {
368 dest_len = 0;
371 if (dest_len) {
372 /* Did we already process the terminating zero ? */
373 if (dest[dest_len-1] != 0) {
374 size_t size = talloc_get_size(dest);
375 /* Have we got space to append the '\0' ? */
376 if (size <= dest_len) {
377 /* No, realloc. */
378 dest = talloc_realloc(ctx, dest, char,
379 dest_len+1);
380 if (!dest) {
381 /* talloc fail. */
382 dest_len = (size_t)-1;
383 return 0;
386 /* Yay - space ! */
387 dest[dest_len] = '\0';
388 dest_len++;
390 } else if (dest) {
391 dest[0] = 0;
394 *ppdest = dest;
395 return src_len + ucs2_align_len;
399 Copy a string from a char* src to a unicode or ascii
400 dos codepage destination choosing unicode or ascii based on the
401 flags supplied
402 Return the number of bytes occupied by the string in the destination.
403 flags can have:
404 STR_TERMINATE means include the null termination.
405 STR_UPPER means uppercase in the destination.
406 STR_ASCII use ascii even with unicode packet.
407 STR_NOALIGN means don't do alignment.
408 dest_len is the maximum length allowed in the destination. If dest_len
409 is -1 then no maxiumum is used.
412 size_t push_string_check_fn(void *dest, const char *src,
413 size_t dest_len, int flags)
415 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
416 return push_ucs2(NULL, dest, src, dest_len, flags);
418 return push_ascii(dest, src, dest_len, flags);
423 Copy a string from a char* src to a unicode or ascii
424 dos codepage destination choosing unicode or ascii based on the
425 flags in the SMB buffer starting at base_ptr.
426 Return the number of bytes occupied by the string in the destination.
427 flags can have:
428 STR_TERMINATE means include the null termination.
429 STR_UPPER means uppercase in the destination.
430 STR_ASCII use ascii even with unicode packet.
431 STR_NOALIGN means don't do alignment.
432 dest_len is the maximum length allowed in the destination. If dest_len
433 is -1 then no maxiumum is used.
436 size_t push_string_base(const char *base, uint16 flags2,
437 void *dest, const char *src,
438 size_t dest_len, int flags)
441 if (!(flags & STR_ASCII) && \
442 ((flags & STR_UNICODE || \
443 (flags2 & FLAGS2_UNICODE_STRINGS)))) {
444 return push_ucs2(base, dest, src, dest_len, flags);
446 return push_ascii(dest, src, dest_len, flags);
450 Copy a string from a unicode or ascii source (depending on
451 the packet flags) to a char* destination.
452 Variant that uses talloc.
453 Flags can have:
454 STR_TERMINATE means the string in src is null terminated.
455 STR_UNICODE means to force as unicode.
456 STR_ASCII use ascii even with unicode packet.
457 STR_NOALIGN means don't do alignment.
458 if STR_TERMINATE is set then src_len is ignored is it is -1
459 src_len is the length of the source area in bytes.
460 Return the number of bytes occupied by the string in src.
461 The resulting string in "dest" is always null terminated.
464 size_t pull_string_talloc(TALLOC_CTX *ctx,
465 const void *base_ptr,
466 uint16 smb_flags2,
467 char **ppdest,
468 const void *src,
469 size_t src_len,
470 int flags)
472 if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
473 smb_panic("No base ptr to get flg2 and neither ASCII nor "
474 "UNICODE defined");
477 if (!(flags & STR_ASCII) && \
478 ((flags & STR_UNICODE || \
479 (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
480 return pull_ucs2_base_talloc(ctx,
481 base_ptr,
482 ppdest,
483 src,
484 src_len,
485 flags);
487 return pull_ascii_base_talloc(ctx,
488 ppdest,
489 src,
490 src_len,
491 flags);
495 size_t align_string(const void *base_ptr, const char *p, int flags)
497 if (!(flags & STR_ASCII) && \
498 ((flags & STR_UNICODE || \
499 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
500 return ucs2_align(base_ptr, p, flags);
502 return 0;
505 /*******************************************************************
506 Write a string in (little-endian) unicode format. src is in
507 the current DOS codepage. len is the length in bytes of the
508 string pointed to by dst.
510 if null_terminate is True then null terminate the packet (adds 2 bytes)
512 the return value is the length in bytes consumed by the string, including the
513 null termination if applied
514 ********************************************************************/
516 size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
518 int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
519 : STR_UNICODE|STR_NOALIGN;
520 return push_ucs2(NULL, dst, src, len, flags);
524 /* Converts a string from internal samba format to unicode. Always terminates.
525 * Actually just a wrapper round push_ucs2_talloc().
528 int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
530 size_t size;
531 if (push_ucs2_talloc(ctx, dest, src, &size))
532 return size;
533 else
534 return -1;