s3-prefork: add asynchronous functions
[Samba/bjacke.git] / source3 / lib / charcnv.c
blob7d7058cbb04d646991caff8f599cb2b771e27440
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;
303 Copy a string from a ucs2 source to a unix char* destination.
304 Flags can have:
305 STR_TERMINATE means the string in src is null terminated.
306 STR_NOALIGN means don't try to align.
307 if STR_TERMINATE is set then src_len is ignored if it is -1.
308 src_len is the length of the source area in bytes
309 Return the number of bytes occupied by the string in src.
310 The resulting string in "dest" is always null terminated.
313 static size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
315 size_t size = 0;
316 size_t ucs2_align_len = 0;
317 bool ret;
319 if (dest_len == (size_t)-1) {
320 /* No longer allow dest_len of -1. */
321 smb_panic("pull_ucs2 - invalid dest_len of -1");
324 if (!src_len) {
325 if (dest && dest_len > 0) {
326 dest[0] = '\0';
328 return 0;
331 if (ucs2_align(base_ptr, src, flags)) {
332 src = (const void *)((const char *)src + 1);
333 if (src_len != (size_t)-1)
334 src_len--;
335 ucs2_align_len = 1;
338 if (flags & STR_TERMINATE) {
339 /* src_len -1 is the default for null terminated strings. */
340 if (src_len != (size_t)-1) {
341 size_t len = strnlen_w((const smb_ucs2_t *)src,
342 src_len/2);
343 if (len < src_len/2)
344 len++;
345 src_len = len*2;
349 /* ucs2 is always a multiple of 2 bytes */
350 if (src_len != (size_t)-1)
351 src_len &= ~1;
353 ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, &size);
354 if (ret == false) {
355 size = 0;
356 dest_len = 0;
359 if (src_len == (size_t)-1)
360 src_len = size*2;
362 if (dest_len && size) {
363 /* Did we already process the terminating zero ? */
364 if (dest[MIN(size-1, dest_len-1)] != 0) {
365 dest[MIN(size, dest_len-1)] = 0;
367 } else {
368 dest[0] = 0;
371 return src_len + ucs2_align_len;
375 Copy a string from a ucs2 source to a unix char* destination.
376 Talloc version with a base pointer.
377 Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
378 needs fixing. JRA).
379 Flags can have:
380 STR_TERMINATE means the string in src is null terminated.
381 STR_NOALIGN means don't try to align.
382 if STR_TERMINATE is set then src_len is ignored if it is -1.
383 src_len is the length of the source area in bytes
384 Return the number of bytes occupied by the string in src.
385 The resulting string in "dest" is always null terminated.
388 static size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
389 const void *base_ptr,
390 char **ppdest,
391 const void *src,
392 size_t src_len,
393 int flags)
395 char *dest;
396 size_t dest_len;
397 size_t ucs2_align_len = 0;
399 *ppdest = NULL;
401 #ifdef DEVELOPER
402 /* Ensure we never use the braindead "malloc" varient. */
403 if (ctx == NULL) {
404 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
406 #endif
408 if (!src_len) {
409 return 0;
412 if (src_len == (size_t)-1) {
413 /* no longer used anywhere, but worth checking */
414 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
417 if (ucs2_align(base_ptr, src, flags)) {
418 src = (const void *)((const char *)src + 1);
419 src_len--;
420 ucs2_align_len = 1;
423 if (flags & STR_TERMINATE) {
424 /* src_len -1 is the default for null terminated strings. */
425 size_t len = strnlen_w((const smb_ucs2_t *)src,
426 src_len/2);
427 if (len < src_len/2)
428 len++;
429 src_len = len*2;
431 /* Ensure we don't use an insane length from the client. */
432 if (src_len >= 1024*1024) {
433 smb_panic("Bad src length in pull_ucs2_base_talloc\n");
437 /* ucs2 is always a multiple of 2 bytes */
438 src_len &= ~1;
440 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
441 (void *)&dest, &dest_len)) {
442 dest_len = 0;
445 if (dest_len) {
446 /* Did we already process the terminating zero ? */
447 if (dest[dest_len-1] != 0) {
448 size_t size = talloc_get_size(dest);
449 /* Have we got space to append the '\0' ? */
450 if (size <= dest_len) {
451 /* No, realloc. */
452 dest = talloc_realloc(ctx, dest, char,
453 dest_len+1);
454 if (!dest) {
455 /* talloc fail. */
456 dest_len = (size_t)-1;
457 return 0;
460 /* Yay - space ! */
461 dest[dest_len] = '\0';
462 dest_len++;
464 } else if (dest) {
465 dest[0] = 0;
468 *ppdest = dest;
469 return src_len + ucs2_align_len;
473 Copy a string from a char* src to a unicode or ascii
474 dos codepage destination choosing unicode or ascii based on the
475 flags supplied
476 Return the number of bytes occupied by the string in the destination.
477 flags can have:
478 STR_TERMINATE means include the null termination.
479 STR_UPPER means uppercase in the destination.
480 STR_ASCII use ascii even with unicode packet.
481 STR_NOALIGN means don't do alignment.
482 dest_len is the maximum length allowed in the destination. If dest_len
483 is -1 then no maxiumum is used.
486 size_t push_string_check_fn(void *dest, const char *src,
487 size_t dest_len, int flags)
489 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
490 return push_ucs2(NULL, dest, src, dest_len, flags);
492 return push_ascii(dest, src, dest_len, flags);
497 Copy a string from a char* src to a unicode or ascii
498 dos codepage destination choosing unicode or ascii based on the
499 flags in the SMB buffer starting at base_ptr.
500 Return the number of bytes occupied by the string in the destination.
501 flags can have:
502 STR_TERMINATE means include the null termination.
503 STR_UPPER means uppercase in the destination.
504 STR_ASCII use ascii even with unicode packet.
505 STR_NOALIGN means don't do alignment.
506 dest_len is the maximum length allowed in the destination. If dest_len
507 is -1 then no maxiumum is used.
510 size_t push_string_base(const char *base, uint16 flags2,
511 void *dest, const char *src,
512 size_t dest_len, int flags)
515 if (!(flags & STR_ASCII) && \
516 ((flags & STR_UNICODE || \
517 (flags2 & FLAGS2_UNICODE_STRINGS)))) {
518 return push_ucs2(base, dest, src, dest_len, flags);
520 return push_ascii(dest, src, dest_len, flags);
524 Copy a string from a unicode or ascii source (depending on
525 the packet flags) to a char* destination.
526 Flags can have:
527 STR_TERMINATE means the string in src is null terminated.
528 STR_UNICODE means to force as unicode.
529 STR_ASCII use ascii even with unicode packet.
530 STR_NOALIGN means don't do alignment.
531 if STR_TERMINATE is set then src_len is ignored is it is -1
532 src_len is the length of the source area in bytes.
533 Return the number of bytes occupied by the string in src.
534 The resulting string in "dest" is always null terminated.
537 size_t pull_string_fn(const void *base_ptr,
538 uint16 smb_flags2,
539 char *dest,
540 const void *src,
541 size_t dest_len,
542 size_t src_len,
543 int flags)
545 if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
546 smb_panic("No base ptr to get flg2 and neither ASCII nor "
547 "UNICODE defined");
550 if (!(flags & STR_ASCII) && \
551 ((flags & STR_UNICODE || \
552 (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
553 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
555 return pull_ascii(dest, src, dest_len, src_len, flags);
559 Copy a string from a unicode or ascii source (depending on
560 the packet flags) to a char* destination.
561 Variant that uses talloc.
562 Flags can have:
563 STR_TERMINATE means the string in src is null terminated.
564 STR_UNICODE means to force as unicode.
565 STR_ASCII use ascii even with unicode packet.
566 STR_NOALIGN means don't do alignment.
567 if STR_TERMINATE is set then src_len is ignored is it is -1
568 src_len is the length of the source area in bytes.
569 Return the number of bytes occupied by the string in src.
570 The resulting string in "dest" is always null terminated.
573 size_t pull_string_talloc(TALLOC_CTX *ctx,
574 const void *base_ptr,
575 uint16 smb_flags2,
576 char **ppdest,
577 const void *src,
578 size_t src_len,
579 int flags)
581 if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
582 smb_panic("No base ptr to get flg2 and neither ASCII nor "
583 "UNICODE defined");
586 if (!(flags & STR_ASCII) && \
587 ((flags & STR_UNICODE || \
588 (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
589 return pull_ucs2_base_talloc(ctx,
590 base_ptr,
591 ppdest,
592 src,
593 src_len,
594 flags);
596 return pull_ascii_base_talloc(ctx,
597 ppdest,
598 src,
599 src_len,
600 flags);
604 size_t align_string(const void *base_ptr, const char *p, int flags)
606 if (!(flags & STR_ASCII) && \
607 ((flags & STR_UNICODE || \
608 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
609 return ucs2_align(base_ptr, p, flags);
611 return 0;
614 /*******************************************************************
615 Write a string in (little-endian) unicode format. src is in
616 the current DOS codepage. len is the length in bytes of the
617 string pointed to by dst.
619 if null_terminate is True then null terminate the packet (adds 2 bytes)
621 the return value is the length in bytes consumed by the string, including the
622 null termination if applied
623 ********************************************************************/
625 size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
627 int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
628 : STR_UNICODE|STR_NOALIGN;
629 return push_ucs2(NULL, dst, src, len, flags);
633 /* Converts a string from internal samba format to unicode
636 int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags)
638 return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
641 /* Converts a string from internal samba format to unicode. Always terminates.
642 * Actually just a wrapper round push_ucs2_talloc().
645 int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
647 size_t size;
648 if (push_ucs2_talloc(ctx, dest, src, &size))
649 return size;
650 else
651 return -1;