source: trunk/server/source3/lib/charcnv.c@ 874

Last change on this file since 874 was 874, checked in by Silvan Scherrer, 11 years ago

samba server 3.6: update trunk to 3.6.24

File size: 42.2 KB
Line 
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
8
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.
13
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.
18
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/>.
21
22*/
23#include "includes.h"
24
25/* We can parameterize this if someone complains.... JRA. */
26
27char lp_failed_convert_char(void)
28{
29 return '_';
30}
31
32/**
33 * @file
34 *
35 * @brief Character-set conversion routines built on our iconv.
36 *
37 * @note Samba's internal character set (at least in the 3.0 series)
38 * is always the same as the one for the Unix filesystem. It is
39 * <b>not</b> necessarily UTF-8 and may be different on machines that
40 * need i18n filenames to be compatible with Unix software. It does
41 * have to be a superset of ASCII. All multibyte sequences must start
42 * with a byte with the high bit set.
43 *
44 * @sa lib/iconv.c
45 */
46
47
48static bool conv_silent; /* Should we do a debug if the conversion fails ? */
49static bool initialized;
50
51void lazy_initialize_conv(void)
52{
53 if (!initialized) {
54 load_case_tables_library();
55 init_iconv();
56 initialized = true;
57 }
58}
59
60/**
61 * Destroy global objects allocated by init_iconv()
62 **/
63void gfree_charcnv(void)
64{
65 TALLOC_FREE(global_iconv_convenience);
66 initialized = false;
67}
68
69/**
70 * Initialize iconv conversion descriptors.
71 *
72 * This is called the first time it is needed, and also called again
73 * every time the configuration is reloaded, because the charset or
74 * codepage might have changed.
75 **/
76void init_iconv(void)
77{
78 global_iconv_convenience = smb_iconv_convenience_reinit(NULL, lp_dos_charset(),
79 lp_unix_charset(), lp_display_charset(),
80 true, global_iconv_convenience);
81}
82
83/**
84 * Convert string from one encoding to another, making error checking etc
85 * Slow path version - uses (slow) iconv.
86 *
87 * @param src pointer to source string (multibyte or singlebyte)
88 * @param srclen length of the source string in bytes
89 * @param dest pointer to destination string (multibyte or singlebyte)
90 * @param destlen maximal length allowed for string
91 * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
92 * @returns the number of bytes occupied in the destination
93 *
94 * Ensure the srclen contains the terminating zero.
95 *
96 **/
97
98static size_t convert_string_internal(charset_t from, charset_t to,
99 void const *src, size_t srclen,
100 void *dest, size_t destlen, bool allow_bad_conv)
101{
102 size_t i_len, o_len;
103 size_t retval;
104 const char* inbuf = (const char*)src;
105 char* outbuf = (char*)dest;
106 smb_iconv_t descriptor;
107 struct smb_iconv_convenience *ic;
108
109 lazy_initialize_conv();
110 ic = get_iconv_convenience();
111 descriptor = get_conv_handle(ic, from, to);
112
113 if (srclen == (size_t)-1) {
114 if (from == CH_UTF16LE || from == CH_UTF16BE) {
115 srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
116 } else {
117 srclen = strlen((const char *)src)+1;
118 }
119 }
120
121
122 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
123 if (!conv_silent)
124 DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
125 return (size_t)-1;
126 }
127
128 i_len=srclen;
129 o_len=destlen;
130
131 again:
132
133 retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
134 if(retval==(size_t)-1) {
135 const char *reason="unknown error";
136 switch(errno) {
137 case EINVAL:
138 reason="Incomplete multibyte sequence";
139 if (!conv_silent)
140 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
141 if (allow_bad_conv)
142 goto use_as_is;
143 return (size_t)-1;
144 case E2BIG:
145 reason="No more room";
146 if (!conv_silent) {
147 if (from == CH_UNIX) {
148 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
149 charset_name(ic, from), charset_name(ic, to),
150 (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
151 } else {
152 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
153 charset_name(ic, from), charset_name(ic, to),
154 (unsigned int)srclen, (unsigned int)destlen));
155 }
156 }
157 break;
158 case EILSEQ:
159 reason="Illegal multibyte sequence";
160 if (!conv_silent)
161 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
162 if (allow_bad_conv)
163 goto use_as_is;
164
165 return (size_t)-1;
166 default:
167 if (!conv_silent)
168 DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
169 return (size_t)-1;
170 }
171 /* smb_panic(reason); */
172 }
173 return destlen-o_len;
174
175 use_as_is:
176
177 /*
178 * Conversion not supported. This is actually an error, but there are so
179 * many misconfigured iconv systems and smb.conf's out there we can't just
180 * fail. Do a very bad conversion instead.... JRA.
181 */
182
183 {
184 if (o_len == 0 || i_len == 0)
185 return destlen - o_len;
186
187 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
188 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
189 /* Can't convert from utf16 any endian to multibyte.
190 Replace with the default fail char.
191 */
192 if (i_len < 2)
193 return destlen - o_len;
194 if (i_len >= 2) {
195 *outbuf = lp_failed_convert_char();
196
197 outbuf++;
198 o_len--;
199
200 inbuf += 2;
201 i_len -= 2;
202 }
203
204 if (o_len == 0 || i_len == 0)
205 return destlen - o_len;
206
207 /* Keep trying with the next char... */
208 goto again;
209
210 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
211 /* Can't convert to UTF16LE - just widen by adding the
212 default fail char then zero.
213 */
214 if (o_len < 2)
215 return destlen - o_len;
216
217 outbuf[0] = lp_failed_convert_char();
218 outbuf[1] = '\0';
219
220 inbuf++;
221 i_len--;
222
223 outbuf += 2;
224 o_len -= 2;
225
226 if (o_len == 0 || i_len == 0)
227 return destlen - o_len;
228
229 /* Keep trying with the next char... */
230 goto again;
231
232 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
233 to != CH_UTF16LE && to != CH_UTF16BE) {
234 /* Failed multibyte to multibyte. Just copy the default fail char and
235 try again. */
236 outbuf[0] = lp_failed_convert_char();
237
238 inbuf++;
239 i_len--;
240
241 outbuf++;
242 o_len--;
243
244 if (o_len == 0 || i_len == 0)
245 return destlen - o_len;
246
247 /* Keep trying with the next char... */
248 goto again;
249
250 } else {
251 /* Keep compiler happy.... */
252 return destlen - o_len;
253 }
254 }
255}
256
257/**
258 * Convert string from one encoding to another, making error checking etc
259 * Fast path version - handles ASCII first.
260 *
261 * @param src pointer to source string (multibyte or singlebyte)
262 * @param srclen length of the source string in bytes, or -1 for nul terminated.
263 * @param dest pointer to destination string (multibyte or singlebyte)
264 * @param destlen maximal length allowed for string - *NEVER* -1.
265 * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
266 * @returns the number of bytes occupied in the destination
267 *
268 * Ensure the srclen contains the terminating zero.
269 *
270 * This function has been hand-tuned to provide a fast path.
271 * Don't change unless you really know what you are doing. JRA.
272 **/
273
274size_t convert_string(charset_t from, charset_t to,
275 void const *src, size_t srclen,
276 void *dest, size_t destlen, bool allow_bad_conv)
277{
278 /*
279 * NB. We deliberately don't do a strlen here if srclen == -1.
280 * This is very expensive over millions of calls and is taken
281 * care of in the slow path in convert_string_internal. JRA.
282 */
283
284#ifdef DEVELOPER
285 SMB_ASSERT(destlen != (size_t)-1);
286#endif
287
288 if (srclen == 0)
289 return 0;
290
291 if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
292 const unsigned char *p = (const unsigned char *)src;
293 unsigned char *q = (unsigned char *)dest;
294 size_t slen = srclen;
295 size_t dlen = destlen;
296 unsigned char lastp = '\0';
297 size_t retval = 0;
298
299 /* If all characters are ascii, fast path here. */
300 while (slen && dlen) {
301 if ((lastp = *p) <= 0x7f) {
302 *q++ = *p++;
303 if (slen != (size_t)-1) {
304 slen--;
305 }
306 dlen--;
307 retval++;
308 if (!lastp)
309 break;
310 } else {
311#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
312 goto general_case;
313#else
314 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
315 if (ret == (size_t)-1) {
316 return ret;
317 }
318 return retval + ret;
319#endif
320 }
321 }
322 if (!dlen) {
323 /* Even if we fast path we should note if we ran out of room. */
324 if (((slen != (size_t)-1) && slen) ||
325 ((slen == (size_t)-1) && lastp)) {
326 errno = E2BIG;
327 }
328 }
329 return retval;
330 } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
331 const unsigned char *p = (const unsigned char *)src;
332 unsigned char *q = (unsigned char *)dest;
333 size_t retval = 0;
334 size_t slen = srclen;
335 size_t dlen = destlen;
336 unsigned char lastp = '\0';
337
338 /* If all characters are ascii, fast path here. */
339 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
340 if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
341 *q++ = *p;
342 if (slen != (size_t)-1) {
343 slen -= 2;
344 }
345 p += 2;
346 dlen--;
347 retval++;
348 if (!lastp)
349 break;
350 } else {
351#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
352 goto general_case;
353#else
354 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
355 if (ret == (size_t)-1) {
356 return ret;
357 }
358 return retval + ret;
359#endif
360 }
361 }
362 if (!dlen) {
363 /* Even if we fast path we should note if we ran out of room. */
364 if (((slen != (size_t)-1) && slen) ||
365 ((slen == (size_t)-1) && lastp)) {
366 errno = E2BIG;
367 }
368 }
369 return retval;
370 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
371 const unsigned char *p = (const unsigned char *)src;
372 unsigned char *q = (unsigned char *)dest;
373 size_t retval = 0;
374 size_t slen = srclen;
375 size_t dlen = destlen;
376 unsigned char lastp = '\0';
377
378 /* If all characters are ascii, fast path here. */
379 while (slen && (dlen >= 2)) {
380 if ((lastp = *p) <= 0x7F) {
381 *q++ = *p++;
382 *q++ = '\0';
383 if (slen != (size_t)-1) {
384 slen--;
385 }
386 dlen -= 2;
387 retval += 2;
388 if (!lastp)
389 break;
390 } else {
391#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
392 goto general_case;
393#else
394 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
395 if (ret == (size_t)-1) {
396 return ret;
397 }
398 return retval + ret;
399#endif
400 }
401 }
402 if (!dlen) {
403 /* Even if we fast path we should note if we ran out of room. */
404 if (((slen != (size_t)-1) && slen) ||
405 ((slen == (size_t)-1) && lastp)) {
406 errno = E2BIG;
407 }
408 }
409 return retval;
410 }
411
412#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
413 general_case:
414#endif
415 return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
416}
417
418/**
419 * Convert between character sets, allocating a new buffer using talloc for the result.
420 *
421 * @param srclen length of source buffer.
422 * @param dest always set at least to NULL
423 * @parm converted_size set to the number of bytes occupied by the string in
424 * the destination on success.
425 * @note -1 is not accepted for srclen.
426 *
427 * @return true if new buffer was correctly allocated, and string was
428 * converted.
429 *
430 * Ensure the srclen contains the terminating zero.
431 *
432 * I hate the goto's in this function. It's embarressing.....
433 * There has to be a cleaner way to do this. JRA.
434 */
435bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
436 void const *src, size_t srclen, void *dst,
437 size_t *converted_size, bool allow_bad_conv)
438
439{
440 size_t i_len, o_len, destlen = (srclen * 3) / 2;
441 size_t retval;
442 const char *inbuf = (const char *)src;
443 char *outbuf = NULL, *ob = NULL;
444 smb_iconv_t descriptor;
445 void **dest = (void **)dst;
446 struct smb_iconv_convenience *ic;
447
448 *dest = NULL;
449
450 if (!converted_size) {
451 errno = EINVAL;
452 return false;
453 }
454
455 if (src == NULL || srclen == (size_t)-1) {
456 errno = EINVAL;
457 return false;
458 }
459
460 if (srclen == 0) {
461 /* We really should treat this as an error, but
462 there are too many callers that need this to
463 return a NULL terminated string in the correct
464 character set. */
465 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
466 destlen = 2;
467 } else {
468 destlen = 1;
469 }
470 ob = talloc_zero_array(ctx, char, destlen);
471 if (ob == NULL) {
472 errno = ENOMEM;
473 return false;
474 }
475 *converted_size = destlen;
476 *dest = ob;
477 return true;
478 }
479
480 lazy_initialize_conv();
481 ic = get_iconv_convenience();
482 descriptor = get_conv_handle(ic, from, to);
483
484 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
485 if (!conv_silent)
486 DEBUG(0,("convert_string_talloc: Conversion not supported.\n"));
487 errno = EOPNOTSUPP;
488 return false;
489 }
490
491 convert:
492
493 /* +2 is for ucs2 null termination. */
494 if ((destlen*2)+2 < destlen) {
495 /* wrapped ! abort. */
496 if (!conv_silent)
497 DEBUG(0, ("convert_string_talloc: destlen wrapped !\n"));
498 TALLOC_FREE(outbuf);
499 errno = EOPNOTSUPP;
500 return false;
501 } else {
502 destlen = destlen * 2;
503 }
504
505 /* +2 is for ucs2 null termination. */
506 ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
507
508 if (!ob) {
509 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
510 errno = ENOMEM;
511 return false;
512 }
513 outbuf = ob;
514 i_len = srclen;
515 o_len = destlen;
516
517 again:
518
519 retval = smb_iconv(descriptor,
520 &inbuf, &i_len,
521 &outbuf, &o_len);
522 if(retval == (size_t)-1) {
523 const char *reason="unknown error";
524 switch(errno) {
525 case EINVAL:
526 reason="Incomplete multibyte sequence";
527 if (!conv_silent)
528 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
529 if (allow_bad_conv)
530 goto use_as_is;
531 break;
532 case E2BIG:
533 goto convert;
534 case EILSEQ:
535 reason="Illegal multibyte sequence";
536 if (!conv_silent)
537 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
538 if (allow_bad_conv)
539 goto use_as_is;
540 break;
541 }
542 if (!conv_silent)
543 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
544 /* smb_panic(reason); */
545 TALLOC_FREE(ob);
546 return false;
547 }
548
549 out:
550
551 destlen = destlen - o_len;
552 /* Don't shrink unless we're reclaiming a lot of
553 * space. This is in the hot codepath and these
554 * reallocs *cost*. JRA.
555 */
556 if (o_len > 1024) {
557 /* We're shrinking here so we know the +2 is safe from wrap. */
558 ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
559 }
560
561 if (destlen && !ob) {
562 DEBUG(0, ("convert_string_talloc: out of memory!\n"));
563 errno = ENOMEM;
564 return false;
565 }
566
567 *dest = ob;
568
569 /* Must ucs2 null terminate in the extra space we allocated. */
570 ob[destlen] = '\0';
571 ob[destlen+1] = '\0';
572
573 /* Ensure we can never return a *converted_size of zero. */
574 if (destlen == 0) {
575 /* This can happen from a bad iconv "use_as_is:" call. */
576 if (to == CH_UTF16LE|| to == CH_UTF16BE || to == CH_UTF16MUNGED) {
577 destlen = 2;
578 } else {
579 destlen = 1;
580 }
581 }
582
583 *converted_size = destlen;
584 return true;
585
586 use_as_is:
587
588 /*
589 * Conversion not supported. This is actually an error, but there are so
590 * many misconfigured iconv systems and smb.conf's out there we can't just
591 * fail. Do a very bad conversion instead.... JRA.
592 */
593
594 {
595 if (o_len == 0 || i_len == 0)
596 goto out;
597
598 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
599 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
600 /* Can't convert from utf16 any endian to multibyte.
601 Replace with the default fail char.
602 */
603
604 if (i_len < 2)
605 goto out;
606
607 if (i_len >= 2) {
608 *outbuf = lp_failed_convert_char();
609
610 outbuf++;
611 o_len--;
612
613 inbuf += 2;
614 i_len -= 2;
615 }
616
617 if (o_len == 0 || i_len == 0)
618 goto out;
619
620 /* Keep trying with the next char... */
621 goto again;
622
623 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
624 /* Can't convert to UTF16LE - just widen by adding the
625 default fail char then zero.
626 */
627 if (o_len < 2)
628 goto out;
629
630 outbuf[0] = lp_failed_convert_char();
631 outbuf[1] = '\0';
632
633 inbuf++;
634 i_len--;
635
636 outbuf += 2;
637 o_len -= 2;
638
639 if (o_len == 0 || i_len == 0)
640 goto out;
641
642 /* Keep trying with the next char... */
643 goto again;
644
645 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
646 to != CH_UTF16LE && to != CH_UTF16BE) {
647 /* Failed multibyte to multibyte. Just copy the default fail char and
648 try again. */
649 outbuf[0] = lp_failed_convert_char();
650
651 inbuf++;
652 i_len--;
653
654 outbuf++;
655 o_len--;
656
657 if (o_len == 0 || i_len == 0)
658 goto out;
659
660 /* Keep trying with the next char... */
661 goto again;
662
663 } else {
664 /* Keep compiler happy.... */
665 goto out;
666 }
667 }
668}
669
670size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
671{
672 size_t size;
673 smb_ucs2_t *buffer;
674
675 if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
676 return (size_t)-1;
677 }
678
679 if (!strupper_w(buffer) && (dest == src)) {
680 TALLOC_FREE(buffer);
681 return srclen;
682 }
683
684 size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
685 TALLOC_FREE(buffer);
686 return size;
687}
688
689/**
690 talloc_strdup() a unix string to upper case.
691**/
692
693char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
694{
695 char *out_buffer = talloc_strdup(ctx,s);
696 const unsigned char *p = (const unsigned char *)s;
697 unsigned char *q = (unsigned char *)out_buffer;
698
699 if (!q) {
700 return NULL;
701 }
702
703 /* this is quite a common operation, so we want it to be
704 fast. We optimise for the ascii case, knowing that all our
705 supported multi-byte character sets are ascii-compatible
706 (ie. they match for the first 128 chars) */
707
708 while (*p) {
709 if (*p & 0x80)
710 break;
711 *q++ = toupper_ascii_fast(*p);
712 p++;
713 }
714
715 if (*p) {
716 /* MB case. */
717 size_t converted_size, converted_size2;
718 smb_ucs2_t *ubuf = NULL;
719
720 /* We're not using the ascii buffer above. */
721 TALLOC_FREE(out_buffer);
722
723 if (!convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, s,
724 strlen(s)+1, (void *)&ubuf,
725 &converted_size, True))
726 {
727 return NULL;
728 }
729
730 strupper_w(ubuf);
731
732 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, ubuf,
733 converted_size, (void *)&out_buffer,
734 &converted_size2, True))
735 {
736 TALLOC_FREE(ubuf);
737 return NULL;
738 }
739
740 /* Don't need the intermediate buffer
741 * anymore.
742 */
743 TALLOC_FREE(ubuf);
744 }
745
746 return out_buffer;
747}
748
749char *strupper_talloc(TALLOC_CTX *ctx, const char *s) {
750 return talloc_strdup_upper(ctx, s);
751}
752
753
754size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
755{
756 size_t size;
757 smb_ucs2_t *buffer = NULL;
758
759 if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
760 (void **)(void *)&buffer, &size,
761 True))
762 {
763 smb_panic("failed to create UCS2 buffer");
764 }
765 if (!strlower_w(buffer) && (dest == src)) {
766 TALLOC_FREE(buffer);
767 return srclen;
768 }
769 size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
770 TALLOC_FREE(buffer);
771 return size;
772}
773
774
775char *talloc_strdup_lower(TALLOC_CTX *ctx, const char *s)
776{
777 size_t converted_size;
778 smb_ucs2_t *buffer = NULL;
779 char *out_buffer;
780
781 if (!push_ucs2_talloc(ctx, &buffer, s, &converted_size)) {
782 return NULL;
783 }
784
785 strlower_w(buffer);
786
787 if (!pull_ucs2_talloc(ctx, &out_buffer, buffer, &converted_size)) {
788 TALLOC_FREE(buffer);
789 return NULL;
790 }
791
792 TALLOC_FREE(buffer);
793
794 return out_buffer;
795}
796
797char *strlower_talloc(TALLOC_CTX *ctx, const char *s) {
798 return talloc_strdup_lower(ctx, s);
799}
800
801size_t ucs2_align(const void *base_ptr, const void *p, int flags)
802{
803 if (flags & (STR_NOALIGN|STR_ASCII))
804 return 0;
805 return PTR_DIFF(p, base_ptr) & 1;
806}
807
808
809/**
810 * Copy a string from a char* unix src to a dos codepage string destination.
811 *
812 * @return the number of bytes occupied by the string in the destination.
813 *
814 * @param flags can include
815 * <dl>
816 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
817 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
818 * </dl>
819 *
820 * @param dest_len the maximum length in bytes allowed in the
821 * destination.
822 **/
823size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
824{
825 size_t src_len = 0;
826 char *tmpbuf = NULL;
827 size_t ret;
828
829 /* No longer allow a length of -1. */
830 if (dest_len == (size_t)-1) {
831 smb_panic("push_ascii - dest_len == -1");
832 }
833
834 if (flags & STR_UPPER) {
835 tmpbuf = SMB_STRDUP(src);
836 if (!tmpbuf) {
837 smb_panic("malloc fail");
838 }
839 strupper_m(tmpbuf);
840 src = tmpbuf;
841 }
842
843 src_len = strlen(src);
844 if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
845 src_len++;
846 }
847
848 ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
849
850 SAFE_FREE(tmpbuf);
851 if (ret == (size_t)-1) {
852 if ((flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
853 && dest_len > 0) {
854 ((char *)dest)[0] = '\0';
855 }
856 return 0;
857 }
858 return ret;
859}
860
861size_t push_ascii_fstring(void *dest, const char *src)
862{
863 return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
864}
865
866/********************************************************************
867 Push an nstring - ensure null terminated. Written by
868 moriyama@miraclelinux.com (MORIYAMA Masayuki).
869********************************************************************/
870
871size_t push_ascii_nstring(void *dest, const char *src)
872{
873 size_t i, buffer_len, dest_len;
874 smb_ucs2_t *buffer;
875
876 conv_silent = True;
877 if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &buffer_len)) {
878 smb_panic("failed to create UCS2 buffer");
879 }
880
881 /* We're using buffer_len below to count ucs2 characters, not bytes. */
882 buffer_len /= sizeof(smb_ucs2_t);
883
884 dest_len = 0;
885 for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
886 unsigned char mb[10];
887 /* Convert one smb_ucs2_t character at a time. */
888 size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
889 if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
890 memcpy((char *)dest + dest_len, mb, mb_len);
891 dest_len += mb_len;
892 } else {
893 errno = E2BIG;
894 break;
895 }
896 }
897 ((char *)dest)[dest_len] = '\0';
898
899 conv_silent = False;
900 TALLOC_FREE(buffer);
901 return dest_len;
902}
903
904/********************************************************************
905 Push and malloc an ascii string. src and dest null terminated.
906********************************************************************/
907
908bool push_ascii_talloc(TALLOC_CTX *mem_ctx, char **dest, const char *src, size_t *converted_size)
909{
910 size_t src_len = strlen(src)+1;
911
912 *dest = NULL;
913 return convert_string_talloc(mem_ctx, CH_UNIX, CH_DOS, src, src_len,
914 (void **)dest, converted_size, True);
915}
916
917/**
918 * Copy a string from a dos codepage source to a unix char* destination.
919 *
920 * The resulting string in "dest" is always null terminated.
921 *
922 * @param flags can have:
923 * <dl>
924 * <dt>STR_TERMINATE</dt>
925 * <dd>STR_TERMINATE means the string in @p src
926 * is null terminated, and src_len is ignored.</dd>
927 * </dl>
928 *
929 * @param src_len is the length of the source area in bytes.
930 * @returns the number of bytes occupied by the string in @p src.
931 **/
932size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
933{
934 size_t ret;
935
936 if (dest_len == (size_t)-1) {
937 /* No longer allow dest_len of -1. */
938 smb_panic("pull_ascii - invalid dest_len of -1");
939 }
940
941 if (flags & STR_TERMINATE) {
942 if (src_len == (size_t)-1) {
943 src_len = strlen((const char *)src) + 1;
944 } else {
945 size_t len = strnlen((const char *)src, src_len);
946 if (len < src_len)
947 len++;
948 src_len = len;
949 }
950 }
951
952 ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
953 if (ret == (size_t)-1) {
954 ret = 0;
955 dest_len = 0;
956 }
957
958 if (dest_len && ret) {
959 /* Did we already process the terminating zero ? */
960 if (dest[MIN(ret-1, dest_len-1)] != 0) {
961 dest[MIN(ret, dest_len-1)] = 0;
962 }
963 } else {
964 dest[0] = 0;
965 }
966
967 return src_len;
968}
969
970/**
971 * Copy a string from a dos codepage source to a unix char* destination.
972 * Talloc version.
973 *
974 * The resulting string in "dest" is always null terminated.
975 *
976 * @param flags can have:
977 * <dl>
978 * <dt>STR_TERMINATE</dt>
979 * <dd>STR_TERMINATE means the string in @p src
980 * is null terminated, and src_len is ignored.</dd>
981 * </dl>
982 *
983 * @param src_len is the length of the source area in bytes.
984 * @returns the number of bytes occupied by the string in @p src.
985 **/
986
987static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
988 char **ppdest,
989 const void *src,
990 size_t src_len,
991 int flags)
992{
993 char *dest = NULL;
994 size_t dest_len;
995
996 *ppdest = NULL;
997
998 if (!src_len) {
999 return 0;
1000 }
1001
1002 if (flags & STR_TERMINATE) {
1003 if (src_len == (size_t)-1) {
1004 src_len = strlen((const char *)src) + 1;
1005 } else {
1006 size_t len = strnlen((const char *)src, src_len);
1007 if (len < src_len)
1008 len++;
1009 src_len = len;
1010 }
1011 /* Ensure we don't use an insane length from the client. */
1012 if (src_len >= 1024*1024) {
1013 char *msg = talloc_asprintf(ctx,
1014 "Bad src length (%u) in "
1015 "pull_ascii_base_talloc",
1016 (unsigned int)src_len);
1017 smb_panic(msg);
1018 }
1019 } else {
1020 /* Can't have an unlimited length
1021 * non STR_TERMINATE'd.
1022 */
1023 if (src_len == (size_t)-1) {
1024 errno = EINVAL;
1025 return 0;
1026 }
1027 }
1028
1029 /* src_len != -1 here. */
1030
1031 if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
1032 &dest_len, True)) {
1033 dest_len = 0;
1034 }
1035
1036 if (dest_len && dest) {
1037 /* Did we already process the terminating zero ? */
1038 if (dest[dest_len-1] != 0) {
1039 size_t size = talloc_get_size(dest);
1040 /* Have we got space to append the '\0' ? */
1041 if (size <= dest_len) {
1042 /* No, realloc. */
1043 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
1044 dest_len+1);
1045 if (!dest) {
1046 /* talloc fail. */
1047 dest_len = (size_t)-1;
1048 return 0;
1049 }
1050 }
1051 /* Yay - space ! */
1052 dest[dest_len] = '\0';
1053 dest_len++;
1054 }
1055 } else if (dest) {
1056 dest[0] = 0;
1057 }
1058
1059 *ppdest = dest;
1060 return src_len;
1061}
1062
1063size_t pull_ascii_fstring(char *dest, const void *src)
1064{
1065 return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
1066}
1067
1068/* When pulling an nstring it can expand into a larger size (dos cp -> utf8). Cope with this. */
1069
1070size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
1071{
1072 return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
1073}
1074
1075/**
1076 * Copy a string from a char* src to a unicode destination.
1077 *
1078 * @returns the number of bytes occupied by the string in the destination.
1079 *
1080 * @param flags can have:
1081 *
1082 * <dl>
1083 * <dt>STR_TERMINATE <dd>means include the null termination.
1084 * <dt>STR_UPPER <dd>means uppercase in the destination.
1085 * <dt>STR_NOALIGN <dd>means don't do alignment.
1086 * </dl>
1087 *
1088 * @param dest_len is the maximum length allowed in the
1089 * destination.
1090 **/
1091
1092size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
1093{
1094 size_t len=0;
1095 size_t src_len;
1096 size_t ret;
1097
1098 if (dest_len == (size_t)-1) {
1099 /* No longer allow dest_len of -1. */
1100 smb_panic("push_ucs2 - invalid dest_len of -1");
1101 }
1102
1103 if (flags & STR_TERMINATE)
1104 src_len = (size_t)-1;
1105 else
1106 src_len = strlen(src);
1107
1108 if (ucs2_align(base_ptr, dest, flags)) {
1109 *(char *)dest = 0;
1110 dest = (void *)((char *)dest + 1);
1111 if (dest_len)
1112 dest_len--;
1113 len++;
1114 }
1115
1116 /* ucs2 is always a multiple of 2 bytes */
1117 dest_len &= ~1;
1118
1119 ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
1120 if (ret == (size_t)-1) {
1121 if ((flags & STR_TERMINATE) &&
1122 dest &&
1123 dest_len) {
1124 *(char *)dest = 0;
1125 }
1126 return len;
1127 }
1128
1129 len += ret;
1130
1131 if (flags & STR_UPPER) {
1132 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
1133 size_t i;
1134
1135 /* We check for i < (ret / 2) below as the dest string isn't null
1136 terminated if STR_TERMINATE isn't set. */
1137
1138 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
1139 smb_ucs2_t v = toupper_w(dest_ucs2[i]);
1140 if (v != dest_ucs2[i]) {
1141 dest_ucs2[i] = v;
1142 }
1143 }
1144 }
1145
1146 return len;
1147}
1148
1149
1150/**
1151 * Copy a string from a unix char* src to a UCS2 destination,
1152 * allocating a buffer using talloc().
1153 *
1154 * @param dest always set at least to NULL
1155 * @parm converted_size set to the number of bytes occupied by the string in
1156 * the destination on success.
1157 *
1158 * @return true if new buffer was correctly allocated, and string was
1159 * converted.
1160 **/
1161bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src,
1162 size_t *converted_size)
1163{
1164 size_t src_len = strlen(src)+1;
1165
1166 *dest = NULL;
1167 return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len,
1168 (void **)dest, converted_size, True);
1169}
1170
1171
1172/**
1173 Copy a string from a char* src to a UTF-8 destination.
1174 Return the number of bytes occupied by the string in the destination
1175 Flags can have:
1176 STR_TERMINATE means include the null termination
1177 STR_UPPER means uppercase in the destination
1178 dest_len is the maximum length allowed in the destination. If dest_len
1179 is -1 then no maxiumum is used.
1180**/
1181
1182static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
1183{
1184 size_t src_len = 0;
1185 size_t ret;
1186 char *tmpbuf = NULL;
1187
1188 if (dest_len == (size_t)-1) {
1189 /* No longer allow dest_len of -1. */
1190 smb_panic("push_utf8 - invalid dest_len of -1");
1191 }
1192
1193 if (flags & STR_UPPER) {
1194 tmpbuf = strupper_talloc(talloc_tos(), src);
1195 if (!tmpbuf) {
1196 return (size_t)-1;
1197 }
1198 src = tmpbuf;
1199 src_len = strlen(src);
1200 }
1201
1202 src_len = strlen(src);
1203 if (flags & STR_TERMINATE) {
1204 src_len++;
1205 }
1206
1207 ret = convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
1208 TALLOC_FREE(tmpbuf);
1209 return ret;
1210}
1211
1212size_t push_utf8_fstring(void *dest, const char *src)
1213{
1214 return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
1215}
1216
1217/**
1218 * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1219 *
1220 * @param dest always set at least to NULL
1221 * @parm converted_size set to the number of bytes occupied by the string in
1222 * the destination on success.
1223 *
1224 * @return true if new buffer was correctly allocated, and string was
1225 * converted.
1226 **/
1227
1228bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1229 size_t *converted_size)
1230{
1231 size_t src_len = strlen(src)+1;
1232
1233 *dest = NULL;
1234 return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len,
1235 (void**)dest, converted_size, True);
1236}
1237
1238/**
1239 Copy a string from a ucs2 source to a unix char* destination.
1240 Flags can have:
1241 STR_TERMINATE means the string in src is null terminated.
1242 STR_NOALIGN means don't try to align.
1243 if STR_TERMINATE is set then src_len is ignored if it is -1.
1244 src_len is the length of the source area in bytes
1245 Return the number of bytes occupied by the string in src.
1246 The resulting string in "dest" is always null terminated.
1247**/
1248
1249size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1250{
1251 size_t ret;
1252 size_t ucs2_align_len = 0;
1253
1254 if (dest_len == (size_t)-1) {
1255 /* No longer allow dest_len of -1. */
1256 smb_panic("pull_ucs2 - invalid dest_len of -1");
1257 }
1258
1259 if (!src_len) {
1260 if (dest && dest_len > 0) {
1261 dest[0] = '\0';
1262 }
1263 return 0;
1264 }
1265
1266 if (ucs2_align(base_ptr, src, flags)) {
1267 src = (const void *)((const char *)src + 1);
1268 if (src_len != (size_t)-1)
1269 src_len--;
1270 ucs2_align_len = 1;
1271 }
1272
1273 if (flags & STR_TERMINATE) {
1274 /* src_len -1 is the default for null terminated strings. */
1275 if (src_len != (size_t)-1) {
1276 size_t len = strnlen_w((const smb_ucs2_t *)src,
1277 src_len/2);
1278 if (len < src_len/2)
1279 len++;
1280 src_len = len*2;
1281 }
1282 }
1283
1284 /* ucs2 is always a multiple of 2 bytes */
1285 if (src_len != (size_t)-1)
1286 src_len &= ~1;
1287
1288 ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
1289 if (ret == (size_t)-1) {
1290 ret = 0;
1291 dest_len = 0;
1292 }
1293
1294 if (src_len == (size_t)-1)
1295 src_len = ret*2;
1296
1297 if (dest_len && ret) {
1298 /* Did we already process the terminating zero ? */
1299 if (dest[MIN(ret-1, dest_len-1)] != 0) {
1300 dest[MIN(ret, dest_len-1)] = 0;
1301 }
1302 } else {
1303 dest[0] = 0;
1304 }
1305
1306 return src_len + ucs2_align_len;
1307}
1308
1309/**
1310 Copy a string from a ucs2 source to a unix char* destination.
1311 Talloc version with a base pointer.
1312 Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1313 needs fixing. JRA).
1314 Flags can have:
1315 STR_TERMINATE means the string in src is null terminated.
1316 STR_NOALIGN means don't try to align.
1317 if STR_TERMINATE is set then src_len is ignored if it is -1.
1318 src_len is the length of the source area in bytes
1319 Return the number of bytes occupied by the string in src.
1320 The resulting string in "dest" is always null terminated.
1321**/
1322
1323size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
1324 const void *base_ptr,
1325 char **ppdest,
1326 const void *src,
1327 size_t src_len,
1328 int flags)
1329{
1330 char *dest;
1331 size_t dest_len;
1332 size_t ucs2_align_len = 0;
1333
1334 *ppdest = NULL;
1335
1336#ifdef DEVELOPER
1337 /* Ensure we never use the braindead "malloc" varient. */
1338 if (ctx == NULL) {
1339 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
1340 }
1341#endif
1342
1343 if (!src_len) {
1344 return 0;
1345 }
1346
1347 if (ucs2_align(base_ptr, src, flags)) {
1348 src = (const void *)((const char *)src + 1);
1349 if (src_len != (size_t)-1)
1350 src_len--;
1351 ucs2_align_len = 1;
1352 }
1353
1354 if (flags & STR_TERMINATE) {
1355 /* src_len -1 is the default for null terminated strings. */
1356 if (src_len != (size_t)-1) {
1357 size_t len = strnlen_w((const smb_ucs2_t *)src,
1358 src_len/2);
1359 if (len < src_len/2)
1360 len++;
1361 src_len = len*2;
1362 } else {
1363 /*
1364 * src_len == -1 - alloc interface won't take this
1365 * so we must calculate.
1366 */
1367 src_len = (strlen_w((const smb_ucs2_t *)src)+1)*sizeof(smb_ucs2_t);
1368 }
1369 /* Ensure we don't use an insane length from the client. */
1370 if (src_len >= 1024*1024) {
1371 smb_panic("Bad src length in pull_ucs2_base_talloc\n");
1372 }
1373 } else {
1374 /* Can't have an unlimited length
1375 * non STR_TERMINATE'd.
1376 */
1377 if (src_len == (size_t)-1) {
1378 errno = EINVAL;
1379 return 0;
1380 }
1381 }
1382
1383 /* src_len != -1 here. */
1384
1385 /* ucs2 is always a multiple of 2 bytes */
1386 src_len &= ~1;
1387
1388 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1389 (void *)&dest, &dest_len, True)) {
1390 dest_len = 0;
1391 }
1392
1393 if (dest_len) {
1394 /* Did we already process the terminating zero ? */
1395 if (dest[dest_len-1] != 0) {
1396 size_t size = talloc_get_size(dest);
1397 /* Have we got space to append the '\0' ? */
1398 if (size <= dest_len) {
1399 /* No, realloc. */
1400 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
1401 dest_len+1);
1402 if (!dest) {
1403 /* talloc fail. */
1404 dest_len = (size_t)-1;
1405 return 0;
1406 }
1407 }
1408 /* Yay - space ! */
1409 dest[dest_len] = '\0';
1410 dest_len++;
1411 }
1412 } else if (dest) {
1413 dest[0] = 0;
1414 }
1415
1416 *ppdest = dest;
1417 return src_len + ucs2_align_len;
1418}
1419
1420size_t pull_ucs2_fstring(char *dest, const void *src)
1421{
1422 return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
1423}
1424
1425/**
1426 * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1427 *
1428 * @param dest always set at least to NULL
1429 * @parm converted_size set to the number of bytes occupied by the string in
1430 * the destination on success.
1431 *
1432 * @return true if new buffer was correctly allocated, and string was
1433 * converted.
1434 **/
1435
1436bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src,
1437 size_t *converted_size)
1438{
1439 size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1440
1441 *dest = NULL;
1442 return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1443 (void **)dest, converted_size, True);
1444}
1445
1446/**
1447 * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1448 *
1449 * @param dest always set at least to NULL
1450 * @parm converted_size set to the number of bytes occupied by the string in
1451 * the destination on success.
1452 *
1453 * @return true if new buffer was correctly allocated, and string was
1454 * converted.
1455 **/
1456
1457bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1458 size_t *converted_size)
1459{
1460 size_t src_len = strlen(src)+1;
1461
1462 *dest = NULL;
1463 return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len,
1464 (void **)dest, converted_size, True);
1465}
1466
1467
1468/**
1469 * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1470 *
1471 * @param dest always set at least to NULL
1472 * @parm converted_size set to the number of bytes occupied by the string in
1473 * the destination on success.
1474 *
1475 * @return true if new buffer was correctly allocated, and string was
1476 * converted.
1477 **/
1478
1479bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1480 size_t *converted_size)
1481{
1482 size_t src_len = strlen(src)+1;
1483
1484 *dest = NULL;
1485 return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len,
1486 (void **)dest, converted_size, True);
1487}
1488
1489/**
1490 Copy a string from a char* src to a unicode or ascii
1491 dos codepage destination choosing unicode or ascii based on the
1492 flags supplied
1493 Return the number of bytes occupied by the string in the destination.
1494 flags can have:
1495 STR_TERMINATE means include the null termination.
1496 STR_UPPER means uppercase in the destination.
1497 STR_ASCII use ascii even with unicode packet.
1498 STR_NOALIGN means don't do alignment.
1499 dest_len is the maximum length allowed in the destination. If dest_len
1500 is -1 then no maxiumum is used.
1501**/
1502
1503size_t push_string_check_fn(const char *function, unsigned int line,
1504 void *dest, const char *src,
1505 size_t dest_len, int flags)
1506{
1507#ifdef DEVELOPER
1508 /* We really need to zero fill here, not clobber
1509 * region, as we want to ensure that valgrind thinks
1510 * all of the outgoing buffer has been written to
1511 * so a send() or write() won't trap an error.
1512 * JRA.
1513 */
1514#if 0
1515 clobber_region(function, line, dest, dest_len);
1516#else
1517 memset(dest, '\0', dest_len);
1518#endif
1519#endif
1520
1521 if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
1522 return push_ucs2(NULL, dest, src, dest_len, flags);
1523 }
1524 return push_ascii(dest, src, dest_len, flags);
1525}
1526
1527
1528/**
1529 Copy a string from a char* src to a unicode or ascii
1530 dos codepage destination choosing unicode or ascii based on the
1531 flags in the SMB buffer starting at base_ptr.
1532 Return the number of bytes occupied by the string in the destination.
1533 flags can have:
1534 STR_TERMINATE means include the null termination.
1535 STR_UPPER means uppercase in the destination.
1536 STR_ASCII use ascii even with unicode packet.
1537 STR_NOALIGN means don't do alignment.
1538 dest_len is the maximum length allowed in the destination. If dest_len
1539 is -1 then no maxiumum is used.
1540**/
1541
1542size_t push_string_base(const char *function, unsigned int line,
1543 const char *base, uint16 flags2,
1544 void *dest, const char *src,
1545 size_t dest_len, int flags)
1546{
1547#ifdef DEVELOPER
1548 /* We really need to zero fill here, not clobber
1549 * region, as we want to ensure that valgrind thinks
1550 * all of the outgoing buffer has been written to
1551 * so a send() or write() won't trap an error.
1552 * JRA.
1553 */
1554#if 0
1555 clobber_region(function, line, dest, dest_len);
1556#else
1557 memset(dest, '\0', dest_len);
1558#endif
1559#endif
1560
1561 if (!(flags & STR_ASCII) && \
1562 ((flags & STR_UNICODE || \
1563 (flags2 & FLAGS2_UNICODE_STRINGS)))) {
1564 return push_ucs2(base, dest, src, dest_len, flags);
1565 }
1566 return push_ascii(dest, src, dest_len, flags);
1567}
1568
1569/**
1570 Copy a string from a char* src to a unicode or ascii
1571 dos codepage destination choosing unicode or ascii based on the
1572 flags supplied
1573 Return the number of bytes occupied by the string in the destination.
1574 flags can have:
1575 STR_TERMINATE means include the null termination.
1576 STR_UPPER means uppercase in the destination.
1577 STR_ASCII use ascii even with unicode packet.
1578 STR_NOALIGN means don't do alignment.
1579 dest_len is the maximum length allowed in the destination. If dest_len
1580 is -1 then no maxiumum is used.
1581**/
1582
1583ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
1584{
1585 size_t ret;
1586#ifdef DEVELOPER
1587 /* We really need to zero fill here, not clobber
1588 * region, as we want to ensure that valgrind thinks
1589 * all of the outgoing buffer has been written to
1590 * so a send() or write() won't trap an error.
1591 * JRA.
1592 */
1593 memset(dest, '\0', dest_len);
1594#endif
1595
1596 if (!(flags & STR_ASCII) && \
1597 (flags & STR_UNICODE)) {
1598 ret = push_ucs2(NULL, dest, src, dest_len, flags);
1599 } else {
1600 ret = push_ascii(dest, src, dest_len, flags);
1601 }
1602 if (ret == (size_t)-1) {
1603 return -1;
1604 }
1605 return ret;
1606}
1607
1608/**
1609 Copy a string from a unicode or ascii source (depending on
1610 the packet flags) to a char* destination.
1611 Flags can have:
1612 STR_TERMINATE means the string in src is null terminated.
1613 STR_UNICODE means to force as unicode.
1614 STR_ASCII use ascii even with unicode packet.
1615 STR_NOALIGN means don't do alignment.
1616 if STR_TERMINATE is set then src_len is ignored is it is -1
1617 src_len is the length of the source area in bytes.
1618 Return the number of bytes occupied by the string in src.
1619 The resulting string in "dest" is always null terminated.
1620**/
1621
1622size_t pull_string_fn(const char *function,
1623 unsigned int line,
1624 const void *base_ptr,
1625 uint16 smb_flags2,
1626 char *dest,
1627 const void *src,
1628 size_t dest_len,
1629 size_t src_len,
1630 int flags)
1631{
1632#ifdef DEVELOPER
1633 clobber_region(function, line, dest, dest_len);
1634#endif
1635
1636 if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1637 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1638 "UNICODE defined");
1639 }
1640
1641 if (!(flags & STR_ASCII) && \
1642 ((flags & STR_UNICODE || \
1643 (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1644 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1645 }
1646 return pull_ascii(dest, src, dest_len, src_len, flags);
1647}
1648
1649/**
1650 Copy a string from a unicode or ascii source (depending on
1651 the packet flags) to a char* destination.
1652 Variant that uses talloc.
1653 Flags can have:
1654 STR_TERMINATE means the string in src is null terminated.
1655 STR_UNICODE means to force as unicode.
1656 STR_ASCII use ascii even with unicode packet.
1657 STR_NOALIGN means don't do alignment.
1658 if STR_TERMINATE is set then src_len is ignored is it is -1
1659 src_len is the length of the source area in bytes.
1660 Return the number of bytes occupied by the string in src.
1661 The resulting string in "dest" is always null terminated.
1662**/
1663
1664size_t pull_string_talloc_fn(const char *function,
1665 unsigned int line,
1666 TALLOC_CTX *ctx,
1667 const void *base_ptr,
1668 uint16 smb_flags2,
1669 char **ppdest,
1670 const void *src,
1671 size_t src_len,
1672 int flags)
1673{
1674 if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1675 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1676 "UNICODE defined");
1677 }
1678
1679 if (!(flags & STR_ASCII) && \
1680 ((flags & STR_UNICODE || \
1681 (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1682 return pull_ucs2_base_talloc(ctx,
1683 base_ptr,
1684 ppdest,
1685 src,
1686 src_len,
1687 flags);
1688 }
1689 return pull_ascii_base_talloc(ctx,
1690 ppdest,
1691 src,
1692 src_len,
1693 flags);
1694}
1695
1696
1697size_t align_string(const void *base_ptr, const char *p, int flags)
1698{
1699 if (!(flags & STR_ASCII) && \
1700 ((flags & STR_UNICODE || \
1701 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1702 return ucs2_align(base_ptr, p, flags);
1703 }
1704 return 0;
1705}
1706
Note: See TracBrowser for help on using the repository browser.