0c34317a3bcc9a18682efd6ab6d8d5bc398dae72
[nivanova/samba-autobuild/.git] / source3 / lib / charcnv.c
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
27 char 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
48 static bool initialized;
49
50 void lazy_initialize_conv(void)
51 {
52         if (!initialized) {
53                 load_case_tables_library();
54                 init_iconv();
55                 initialized = true;
56         }
57 }
58
59 /**
60  * Destroy global objects allocated by init_iconv()
61  **/
62 void gfree_charcnv(void)
63 {
64         TALLOC_FREE(global_iconv_convenience);
65         initialized = false;
66 }
67
68 /**
69  * Initialize iconv conversion descriptors.
70  *
71  * This is called the first time it is needed, and also called again
72  * every time the configuration is reloaded, because the charset or
73  * codepage might have changed.
74  **/
75 void init_iconv(void)
76 {
77         global_iconv_convenience = smb_iconv_convenience_reinit(NULL, lp_dos_charset(),
78                                                                 lp_unix_charset(), lp_display_charset(),
79                                                                 true, global_iconv_convenience);
80 }
81
82 /**
83  * Convert string from one encoding to another, making error checking etc
84  * Slow path version - uses (slow) iconv.
85  *
86  * @param src pointer to source string (multibyte or singlebyte)
87  * @param srclen length of the source string in bytes
88  * @param dest pointer to destination string (multibyte or singlebyte)
89  * @param destlen maximal length allowed for string
90  * @returns the number of bytes occupied in the destination
91  *
92  * Ensure the srclen contains the terminating zero.
93  *
94  **/
95
96 static size_t convert_string_internal(charset_t from, charset_t to,
97                       void const *src, size_t srclen, 
98                       void *dest, size_t destlen, size_t *converted_size)
99 {
100         size_t i_len, o_len;
101         size_t retval;
102         const char* inbuf = (const char*)src;
103         char* outbuf = (char*)dest;
104         smb_iconv_t descriptor;
105         struct smb_iconv_convenience *ic;
106
107         lazy_initialize_conv();
108         ic = get_iconv_convenience();
109         descriptor = get_conv_handle(ic, from, to);
110
111         if (srclen == (size_t)-1) {
112                 if (from == CH_UTF16LE || from == CH_UTF16BE) {
113                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
114                 } else {
115                         srclen = strlen((const char *)src)+1;
116                 }
117         }
118
119
120         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
121                 errno = EINVAL;
122                 return (size_t)-1;
123         }
124
125         i_len=srclen;
126         o_len=destlen;
127
128         retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
129         if (converted_size != NULL)
130                 *converted_size = destlen-o_len;
131         return retval;
132 }
133
134 /**
135  * Convert string from one encoding to another, making error checking etc
136  * Fast path version - handles ASCII first.
137  *
138  * @param src pointer to source string (multibyte or singlebyte)
139  * @param srclen length of the source string in bytes, or -1 for nul terminated.
140  * @param dest pointer to destination string (multibyte or singlebyte)
141  * @param destlen maximal length allowed for string - *NEVER* -1.
142  * @returns the number of bytes occupied in the destination
143  *
144  * Ensure the srclen contains the terminating zero.
145  *
146  * This function has been hand-tuned to provide a fast path.
147  * Don't change unless you really know what you are doing. JRA.
148  **/
149
150 size_t convert_string_error(charset_t from, charset_t to,
151                             void const *src, size_t srclen,
152                             void *dest, size_t destlen,
153                             size_t *converted_size)
154 {
155         /*
156          * NB. We deliberately don't do a strlen here if srclen == -1.
157          * This is very expensive over millions of calls and is taken
158          * care of in the slow path in convert_string_internal. JRA.
159          */
160
161 #ifdef DEVELOPER
162         SMB_ASSERT(destlen != (size_t)-1);
163 #endif
164
165         if (converted_size) {
166                 *converted_size = 0;
167         }
168
169         if (srclen == 0)
170                 return 0;
171
172         if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
173                 const unsigned char *p = (const unsigned char *)src;
174                 unsigned char *q = (unsigned char *)dest;
175                 size_t slen = srclen;
176                 size_t dlen = destlen;
177                 unsigned char lastp = '\0';
178                 size_t retval = 0;
179
180                 /* If all characters are ascii, fast path here. */
181                 while (slen && dlen) {
182                         if ((lastp = *p) <= 0x7f) {
183                                 *q++ = *p++;
184                                 if (slen != (size_t)-1) {
185                                         slen--;
186                                 }
187                                 dlen--;
188                                 retval++;
189                                 if (!lastp)
190                                         break;
191                         } else {
192 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
193                                 goto general_case;
194 #else
195                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, converted_size);
196                                 if (converted_size) {
197                                         *converted_size += retval;
198                                 }
199                                 return ret;
200 #endif
201                         }
202                 }
203                 if (!dlen) {
204                         /* Even if we fast path we should note if we ran out of room. */
205                         if (((slen != (size_t)-1) && slen) ||
206                                         ((slen == (size_t)-1) && lastp)) {
207                                 errno = E2BIG;
208                         }
209                 }
210                 return retval;
211         } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
212                 const unsigned char *p = (const unsigned char *)src;
213                 unsigned char *q = (unsigned char *)dest;
214                 size_t retval = 0;
215                 size_t slen = srclen;
216                 size_t dlen = destlen;
217                 unsigned char lastp = '\0';
218
219                 /* If all characters are ascii, fast path here. */
220                 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
221                         if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
222                                 *q++ = *p;
223                                 if (slen != (size_t)-1) {
224                                         slen -= 2;
225                                 }
226                                 p += 2;
227                                 dlen--;
228                                 retval++;
229                                 if (!lastp)
230                                         break;
231                         } else {
232 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
233                                 goto general_case;
234 #else
235                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, converted_size);
236                                 if (converted_size) {
237                                         *converted_size += retval;
238                                 }
239                                 return ret;
240 #endif
241                         }
242                 }
243                 if (!dlen) {
244                         /* Even if we fast path we should note if we ran out of room. */
245                         if (((slen != (size_t)-1) && slen) ||
246                                         ((slen == (size_t)-1) && lastp)) {
247                                 errno = E2BIG;
248                         }
249                 }
250                 return retval;
251         } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
252                 const unsigned char *p = (const unsigned char *)src;
253                 unsigned char *q = (unsigned char *)dest;
254                 size_t retval = 0;
255                 size_t slen = srclen;
256                 size_t dlen = destlen;
257                 unsigned char lastp = '\0';
258
259                 /* If all characters are ascii, fast path here. */
260                 while (slen && (dlen >= 2)) {
261                         if ((lastp = *p) <= 0x7F) {
262                                 *q++ = *p++;
263                                 *q++ = '\0';
264                                 if (slen != (size_t)-1) {
265                                         slen--;
266                                 }
267                                 dlen -= 2;
268                                 retval += 2;
269                                 if (!lastp)
270                                         break;
271                         } else {
272 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
273                                 goto general_case;
274 #else
275                                 size_t ret = convert_string_internal(from, to, p, slen, q, dlen, converted_size);
276                                 if (converted_size) {
277                                         *converted_size += retval;
278                                 }
279                                 return ret;
280 #endif
281                         }
282                 }
283                 if (converted_size) {
284                         *converted_size += retval;
285                 }
286                 if (!dlen) {
287                         /* Even if we fast path we should note if we ran out of room. */
288                         if (((slen != (size_t)-1) && slen) ||
289                                         ((slen == (size_t)-1) && lastp)) {
290                                 errno = E2BIG;
291                                 return -1;
292                         }
293                 }
294                 return 0;
295         }
296
297 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
298   general_case:
299 #endif
300         return convert_string_internal(from, to, src, srclen, dest, destlen, converted_size);
301 }
302
303 size_t convert_string(charset_t from, charset_t to,
304                       void const *src, size_t srclen,
305                       void *dest, size_t destlen) {
306         size_t converted_size;
307         size_t retval = convert_string_error(from, to, src, srclen, dest, destlen, &converted_size);
308         if(retval==(size_t)-1) {
309                 const char *reason="unknown error";
310                 switch(errno) {
311                         case EINVAL:
312                                 reason="Incomplete multibyte sequence";
313                                 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,src));
314                                 return (size_t)-1;
315                         case E2BIG:
316                         {
317                                 struct smb_iconv_handle *ic;
318                                 lazy_initialize_conv();
319                                 ic = get_iconv_handle();
320
321                                 reason="No more room";
322                                 if (from == CH_UNIX) {
323                                         DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
324                                                  charset_name(ic, from), charset_name(ic, to),
325                                                  (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
326                                 } else {
327                                         DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
328                                                  charset_name(ic, from), charset_name(ic, to),
329                                                  (unsigned int)srclen, (unsigned int)destlen));
330                                 }
331                                 break;
332                         }
333                         case EILSEQ:
334                                 reason="Illegal multibyte sequence";
335                                 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,src));
336                                 return (size_t)-1;
337                         default:
338                                 DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,src));
339                                 return (size_t)-1;
340                 }
341                 /* smb_panic(reason); */
342         }
343         return converted_size;
344 }
345
346
347 /**
348  * Convert between character sets, allocating a new buffer using talloc for the result.
349  *
350  * @param srclen length of source buffer.
351  * @param dest always set at least to NULL
352  * @parm converted_size set to the number of bytes occupied by the string in
353  * the destination on success.
354  * @note -1 is not accepted for srclen.
355  *
356  * @return true if new buffer was correctly allocated, and string was
357  * converted.
358  *
359  * Ensure the srclen contains the terminating zero.
360  *
361  * I hate the goto's in this function. It's embarressing.....
362  * There has to be a cleaner way to do this. JRA.
363  */
364 bool convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
365                            void const *src, size_t srclen, void *dst,
366                            size_t *converted_size)
367
368 {
369         size_t i_len, o_len, destlen = (srclen * 3) / 2;
370         size_t retval;
371         const char *inbuf = (const char *)src;
372         char *outbuf = NULL, *ob = NULL;
373         smb_iconv_t descriptor;
374         void **dest = (void **)dst;
375         struct smb_iconv_convenience *ic;
376
377         *dest = NULL;
378
379         if (!converted_size) {
380                 errno = EINVAL;
381                 return false;
382         }
383
384         if (src == NULL || srclen == (size_t)-1) {
385                 errno = EINVAL;
386                 return false;
387         }
388         if (srclen == 0) {
389                 ob = talloc_strdup(ctx, "");
390                 if (ob == NULL) {
391                         errno = ENOMEM;
392                         return false;
393                 }
394                 *dest = ob;
395                 *converted_size = 0;
396                 return true;
397         }
398
399         lazy_initialize_conv();
400         ic = get_iconv_convenience();
401         descriptor = get_conv_handle(ic, from, to);
402
403         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
404                 DEBUG(0,("convert_string_talloc: Conversion not supported.\n"));
405                 errno = EOPNOTSUPP;
406                 return false;
407         }
408
409   convert:
410
411         /* +2 is for ucs2 null termination. */
412         if ((destlen*2)+2 < destlen) {
413                 /* wrapped ! abort. */
414                 DEBUG(0, ("convert_string_talloc: destlen wrapped !\n"));
415                 TALLOC_FREE(outbuf);
416                 errno = EOPNOTSUPP;
417                 return false;
418         } else {
419                 destlen = destlen * 2;
420         }
421
422         /* +2 is for ucs2 null termination. */
423         ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
424
425         if (!ob) {
426                 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
427                 errno = ENOMEM;
428                 return false;
429         }
430         outbuf = ob;
431         i_len = srclen;
432         o_len = destlen;
433
434         retval = smb_iconv(descriptor,
435                            &inbuf, &i_len,
436                            &outbuf, &o_len);
437         if(retval == (size_t)-1)                {
438                 const char *reason="unknown error";
439                 switch(errno) {
440                         case EINVAL:
441                                 reason="Incomplete multibyte sequence";
442                                 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
443                                 break;
444                         case E2BIG:
445                                 goto convert;
446                         case EILSEQ:
447                                 reason="Illegal multibyte sequence";
448                                 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason,inbuf));
449                                 break;
450                 }
451                 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
452                 /* smb_panic(reason); */
453                 TALLOC_FREE(ob);
454                 return false;
455         }
456
457         destlen = destlen - o_len;
458         /* Don't shrink unless we're reclaiming a lot of
459          * space. This is in the hot codepath and these
460          * reallocs *cost*. JRA.
461          */
462         if (o_len > 1024) {
463                 /* We're shrinking here so we know the +2 is safe from wrap. */
464                 ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
465         }
466
467         if (destlen && !ob) {
468                 DEBUG(0, ("convert_string_talloc: out of memory!\n"));
469                 errno = ENOMEM;
470                 return false;
471         }
472
473         *dest = ob;
474
475         /* Must ucs2 null terminate in the extra space we allocated. */
476         ob[destlen] = '\0';
477         ob[destlen+1] = '\0';
478
479         *converted_size = destlen;
480         return true;
481 }
482
483 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
484 {
485         size_t size;
486         smb_ucs2_t *buffer;
487
488         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
489                 return (size_t)-1;
490         }
491
492         if (!strupper_w(buffer) && (dest == src)) {
493                 TALLOC_FREE(buffer);
494                 return srclen;
495         }
496
497         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen);
498         TALLOC_FREE(buffer);
499         return size;
500 }
501
502 /**
503  talloc_strdup() a unix string to upper case.
504 **/
505
506 char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
507 {
508         char *out_buffer = talloc_strdup(ctx,s);
509         const unsigned char *p = (const unsigned char *)s;
510         unsigned char *q = (unsigned char *)out_buffer;
511
512         if (!q) {
513                 return NULL;
514         }
515
516         /* this is quite a common operation, so we want it to be
517            fast. We optimise for the ascii case, knowing that all our
518            supported multi-byte character sets are ascii-compatible
519            (ie. they match for the first 128 chars) */
520
521         while (*p) {
522                 if (*p & 0x80)
523                         break;
524                 *q++ = toupper_ascii_fast(*p);
525                 p++;
526         }
527
528         if (*p) {
529                 /* MB case. */
530                 size_t converted_size, converted_size2;
531                 smb_ucs2_t *ubuf = NULL;
532
533                 /* We're not using the ascii buffer above. */
534                 TALLOC_FREE(out_buffer);
535
536                 if (!convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, s,
537                                            strlen(s)+1, (void *)&ubuf,
538                                            &converted_size))
539                 {
540                         return NULL;
541                 }
542
543                 strupper_w(ubuf);
544
545                 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, ubuf,
546                                            converted_size, (void *)&out_buffer,
547                                            &converted_size2))
548                 {
549                         TALLOC_FREE(ubuf);
550                         return NULL;
551                 }
552
553                 /* Don't need the intermediate buffer
554                  * anymore.
555                  */
556                 TALLOC_FREE(ubuf);
557         }
558
559         return out_buffer;
560 }
561
562 char *strupper_talloc(TALLOC_CTX *ctx, const char *s) {
563         return talloc_strdup_upper(ctx, s);
564 }
565
566
567 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
568 {
569         size_t size;
570         smb_ucs2_t *buffer = NULL;
571
572         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
573                                    (void **)(void *)&buffer, &size))
574         {
575                 smb_panic("failed to create UCS2 buffer");
576         }
577         if (!strlower_w(buffer) && (dest == src)) {
578                 TALLOC_FREE(buffer);
579                 return srclen;
580         }
581         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen);
582         TALLOC_FREE(buffer);
583         return size;
584 }
585
586
587 char *talloc_strdup_lower(TALLOC_CTX *ctx, const char *s)
588 {
589         size_t converted_size;
590         smb_ucs2_t *buffer = NULL;
591         char *out_buffer;
592
593         if (!push_ucs2_talloc(ctx, &buffer, s, &converted_size)) {
594                 return NULL;
595         }
596
597         strlower_w(buffer);
598
599         if (!pull_ucs2_talloc(ctx, &out_buffer, buffer, &converted_size)) {
600                 TALLOC_FREE(buffer);
601                 return NULL;
602         }
603
604         TALLOC_FREE(buffer);
605
606         return out_buffer;
607 }
608
609 char *strlower_talloc(TALLOC_CTX *ctx, const char *s) {
610         return talloc_strdup_lower(ctx, s);
611 }
612
613 size_t ucs2_align(const void *base_ptr, const void *p, int flags)
614 {
615         if (flags & (STR_NOALIGN|STR_ASCII))
616                 return 0;
617         return PTR_DIFF(p, base_ptr) & 1;
618 }
619
620
621 /**
622  * Copy a string from a char* unix src to a dos codepage string destination.
623  *
624  * @return the number of bytes occupied by the string in the destination.
625  *
626  * @param flags can include
627  * <dl>
628  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
629  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
630  * </dl>
631  *
632  * @param dest_len the maximum length in bytes allowed in the
633  * destination.
634  **/
635 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
636 {
637         size_t src_len = strlen(src);
638         char *tmpbuf = NULL;
639         size_t ret;
640
641         /* No longer allow a length of -1. */
642         if (dest_len == (size_t)-1) {
643                 smb_panic("push_ascii - dest_len == -1");
644         }
645
646         if (flags & STR_UPPER) {
647                 tmpbuf = SMB_STRDUP(src);
648                 if (!tmpbuf) {
649                         smb_panic("malloc fail");
650                 }
651                 strupper_m(tmpbuf);
652                 src = tmpbuf;
653         }
654
655         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
656                 src_len++;
657         }
658
659         ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
660         if (ret == (size_t)-1 &&
661                         (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
662                         && dest_len > 0) {
663                 ((char *)dest)[0] = '\0';
664         }
665         SAFE_FREE(tmpbuf);
666         return ret;
667 }
668
669 /********************************************************************
670  Push and malloc an ascii string. src and dest null terminated.
671 ********************************************************************/
672
673 bool push_ascii_talloc(TALLOC_CTX *mem_ctx, char **dest, const char *src, size_t *converted_size)
674 {
675         size_t src_len = strlen(src)+1;
676
677         *dest = NULL;
678         return convert_string_talloc(mem_ctx, CH_UNIX, CH_DOS, src, src_len,
679                                      (void **)dest, converted_size);
680 }
681
682 /**
683  * Copy a string from a dos codepage source to a unix char* destination.
684  *
685  * The resulting string in "dest" is always null terminated.
686  *
687  * @param flags can have:
688  * <dl>
689  * <dt>STR_TERMINATE</dt>
690  * <dd>STR_TERMINATE means the string in @p src
691  * is null terminated, and src_len is ignored.</dd>
692  * </dl>
693  *
694  * @param src_len is the length of the source area in bytes.
695  * @returns the number of bytes occupied by the string in @p src.
696  **/
697 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
698 {
699         size_t ret;
700
701         if (dest_len == (size_t)-1) {
702                 /* No longer allow dest_len of -1. */
703                 smb_panic("pull_ascii - invalid dest_len of -1");
704         }
705
706         if (flags & STR_TERMINATE) {
707                 if (src_len == (size_t)-1) {
708                         src_len = strlen((const char *)src) + 1;
709                 } else {
710                         size_t len = strnlen((const char *)src, src_len);
711                         if (len < src_len)
712                                 len++;
713                         src_len = len;
714                 }
715         }
716
717         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
718         if (ret == (size_t)-1) {
719                 ret = 0;
720                 dest_len = 0;
721         }
722
723         if (dest_len && ret) {
724                 /* Did we already process the terminating zero ? */
725                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
726                         dest[MIN(ret, dest_len-1)] = 0;
727                 }
728         } else  {
729                 dest[0] = 0;
730         }
731
732         return src_len;
733 }
734
735 /**
736  * Copy a string from a dos codepage source to a unix char* destination.
737  * Talloc version.
738  *
739  * The resulting string in "dest" is always null terminated.
740  *
741  * @param flags can have:
742  * <dl>
743  * <dt>STR_TERMINATE</dt>
744  * <dd>STR_TERMINATE means the string in @p src
745  * is null terminated, and src_len is ignored.</dd>
746  * </dl>
747  *
748  * @param src_len is the length of the source area in bytes.
749  * @returns the number of bytes occupied by the string in @p src.
750  **/
751
752 static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
753                                      char **ppdest,
754                                      const void *src,
755                                      size_t src_len,
756                                      int flags)
757 {
758         char *dest = NULL;
759         size_t dest_len;
760
761         *ppdest = NULL;
762
763         if (!src_len) {
764                 return 0;
765         }
766
767         if (src_len == (size_t)-1) {
768                 smb_panic("sec_len == -1 in pull_ascii_base_talloc");
769         }
770
771         if (flags & STR_TERMINATE) {
772                 size_t len = strnlen((const char *)src, src_len);
773                 if (len < src_len)
774                         len++;
775                 src_len = len;
776                 /* Ensure we don't use an insane length from the client. */
777                 if (src_len >= 1024*1024) {
778                         char *msg = talloc_asprintf(ctx,
779                                         "Bad src length (%u) in "
780                                         "pull_ascii_base_talloc",
781                                         (unsigned int)src_len);
782                         smb_panic(msg);
783                 }
784         }
785
786         /* src_len != -1 here. */
787
788         if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
789                                      &dest_len)) {
790                 dest_len = 0;
791         }
792
793         if (dest_len && dest) {
794                 /* Did we already process the terminating zero ? */
795                 if (dest[dest_len-1] != 0) {
796                         size_t size = talloc_get_size(dest);
797                         /* Have we got space to append the '\0' ? */
798                         if (size <= dest_len) {
799                                 /* No, realloc. */
800                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
801                                                 dest_len+1);
802                                 if (!dest) {
803                                         /* talloc fail. */
804                                         dest_len = (size_t)-1;
805                                         return 0;
806                                 }
807                         }
808                         /* Yay - space ! */
809                         dest[dest_len] = '\0';
810                         dest_len++;
811                 }
812         } else if (dest) {
813                 dest[0] = 0;
814         }
815
816         *ppdest = dest;
817         return src_len;
818 }
819
820 /**
821  * Copy a string from a char* src to a unicode destination.
822  *
823  * @returns the number of bytes occupied by the string in the destination.
824  *
825  * @param flags can have:
826  *
827  * <dl>
828  * <dt>STR_TERMINATE <dd>means include the null termination.
829  * <dt>STR_UPPER     <dd>means uppercase in the destination.
830  * <dt>STR_NOALIGN   <dd>means don't do alignment.
831  * </dl>
832  *
833  * @param dest_len is the maximum length allowed in the
834  * destination.
835  **/
836
837 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
838 {
839         size_t len=0;
840         size_t src_len;
841         size_t ret;
842
843         if (dest_len == (size_t)-1) {
844                 /* No longer allow dest_len of -1. */
845                 smb_panic("push_ucs2 - invalid dest_len of -1");
846         }
847
848         if (flags & STR_TERMINATE)
849                 src_len = (size_t)-1;
850         else
851                 src_len = strlen(src);
852
853         if (ucs2_align(base_ptr, dest, flags)) {
854                 *(char *)dest = 0;
855                 dest = (void *)((char *)dest + 1);
856                 if (dest_len)
857                         dest_len--;
858                 len++;
859         }
860
861         /* ucs2 is always a multiple of 2 bytes */
862         dest_len &= ~1;
863
864         ret =  convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len);
865         if (ret == (size_t)-1) {
866                 if ((flags & STR_TERMINATE) &&
867                                 dest &&
868                                 dest_len) {
869                         *(char *)dest = 0;
870                 }
871                 return len;
872         }
873
874         len += ret;
875
876         if (flags & STR_UPPER) {
877                 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
878                 size_t i;
879
880                 /* We check for i < (ret / 2) below as the dest string isn't null
881                    terminated if STR_TERMINATE isn't set. */
882
883                 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
884                         smb_ucs2_t v = toupper_m(dest_ucs2[i]);
885                         if (v != dest_ucs2[i]) {
886                                 dest_ucs2[i] = v;
887                         }
888                 }
889         }
890
891         return len;
892 }
893
894
895 /**
896  * Copy a string from a unix char* src to a UCS2 destination,
897  * allocating a buffer using talloc().
898  *
899  * @param dest always set at least to NULL 
900  * @parm converted_size set to the number of bytes occupied by the string in
901  * the destination on success.
902  *
903  * @return true if new buffer was correctly allocated, and string was
904  * converted.
905  **/
906 bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src,
907                       size_t *converted_size)
908 {
909         size_t src_len = strlen(src)+1;
910
911         *dest = NULL;
912         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len,
913                                      (void **)dest, converted_size);
914 }
915
916
917 /**
918  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
919  *
920  * @param dest always set at least to NULL 
921  * @parm converted_size set to the number of bytes occupied by the string in
922  * the destination on success.
923  *
924  * @return true if new buffer was correctly allocated, and string was
925  * converted.
926  **/
927
928 bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
929                       size_t *converted_size)
930 {
931         size_t src_len = strlen(src)+1;
932
933         *dest = NULL;
934         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len,
935                                      (void**)dest, converted_size);
936 }
937
938 /**
939  Copy a string from a ucs2 source to a unix char* destination.
940  Flags can have:
941   STR_TERMINATE means the string in src is null terminated.
942   STR_NOALIGN   means don't try to align.
943  if STR_TERMINATE is set then src_len is ignored if it is -1.
944  src_len is the length of the source area in bytes
945  Return the number of bytes occupied by the string in src.
946  The resulting string in "dest" is always null terminated.
947 **/
948
949 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
950 {
951         size_t ret;
952         size_t ucs2_align_len = 0;
953
954         if (dest_len == (size_t)-1) {
955                 /* No longer allow dest_len of -1. */
956                 smb_panic("pull_ucs2 - invalid dest_len of -1");
957         }
958
959         if (!src_len) {
960                 if (dest && dest_len > 0) {
961                         dest[0] = '\0';
962                 }
963                 return 0;
964         }
965
966         if (ucs2_align(base_ptr, src, flags)) {
967                 src = (const void *)((const char *)src + 1);
968                 if (src_len != (size_t)-1)
969                         src_len--;
970                 ucs2_align_len = 1;
971         }
972
973         if (flags & STR_TERMINATE) {
974                 /* src_len -1 is the default for null terminated strings. */
975                 if (src_len != (size_t)-1) {
976                         size_t len = strnlen_w((const smb_ucs2_t *)src,
977                                                 src_len/2);
978                         if (len < src_len/2)
979                                 len++;
980                         src_len = len*2;
981                 }
982         }
983
984         /* ucs2 is always a multiple of 2 bytes */
985         if (src_len != (size_t)-1)
986                 src_len &= ~1;
987
988         ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len);
989         if (ret == (size_t)-1) {
990                 ret = 0;
991                 dest_len = 0;
992         }
993
994         if (src_len == (size_t)-1)
995                 src_len = ret*2;
996
997         if (dest_len && ret) {
998                 /* Did we already process the terminating zero ? */
999                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
1000                         dest[MIN(ret, dest_len-1)] = 0;
1001                 }
1002         } else {
1003                 dest[0] = 0;
1004         }
1005
1006         return src_len + ucs2_align_len;
1007 }
1008
1009 /**
1010  Copy a string from a ucs2 source to a unix char* destination.
1011  Talloc version with a base pointer.
1012  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1013  needs fixing. JRA).
1014  Flags can have:
1015   STR_TERMINATE means the string in src is null terminated.
1016   STR_NOALIGN   means don't try to align.
1017  if STR_TERMINATE is set then src_len is ignored if it is -1.
1018  src_len is the length of the source area in bytes
1019  Return the number of bytes occupied by the string in src.
1020  The resulting string in "dest" is always null terminated.
1021 **/
1022
1023 static size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
1024                                     const void *base_ptr,
1025                                     char **ppdest,
1026                                     const void *src,
1027                                     size_t src_len,
1028                                     int flags)
1029 {
1030         char *dest;
1031         size_t dest_len;
1032         size_t ucs2_align_len = 0;
1033
1034         *ppdest = NULL;
1035
1036 #ifdef DEVELOPER
1037         /* Ensure we never use the braindead "malloc" varient. */
1038         if (ctx == NULL) {
1039                 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
1040         }
1041 #endif
1042
1043         if (!src_len) {
1044                 return 0;
1045         }
1046
1047         if (src_len == (size_t)-1) {
1048                 /* no longer used anywhere, but worth checking */
1049                 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
1050         }
1051
1052         if (ucs2_align(base_ptr, src, flags)) {
1053                 src = (const void *)((const char *)src + 1);
1054                 src_len--;
1055                 ucs2_align_len = 1;
1056         }
1057
1058         if (flags & STR_TERMINATE) {
1059                 /* src_len -1 is the default for null terminated strings. */
1060                 size_t len = strnlen_w((const smb_ucs2_t *)src,
1061                                        src_len/2);
1062                 if (len < src_len/2)
1063                         len++;
1064                 src_len = len*2;
1065
1066                 /* Ensure we don't use an insane length from the client. */
1067                 if (src_len >= 1024*1024) {
1068                         smb_panic("Bad src length in pull_ucs2_base_talloc\n");
1069                 }
1070         }
1071
1072         /* ucs2 is always a multiple of 2 bytes */
1073         src_len &= ~1;
1074
1075         if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1076                                    (void *)&dest, &dest_len)) {
1077                 dest_len = 0;
1078         }
1079
1080         if (dest_len) {
1081                 /* Did we already process the terminating zero ? */
1082                 if (dest[dest_len-1] != 0) {
1083                         size_t size = talloc_get_size(dest);
1084                         /* Have we got space to append the '\0' ? */
1085                         if (size <= dest_len) {
1086                                 /* No, realloc. */
1087                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
1088                                                 dest_len+1);
1089                                 if (!dest) {
1090                                         /* talloc fail. */
1091                                         dest_len = (size_t)-1;
1092                                         return 0;
1093                                 }
1094                         }
1095                         /* Yay - space ! */
1096                         dest[dest_len] = '\0';
1097                         dest_len++;
1098                 }
1099         } else if (dest) {
1100                 dest[0] = 0;
1101         }
1102
1103         *ppdest = dest;
1104         return src_len + ucs2_align_len;
1105 }
1106
1107 /**
1108  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1109  *
1110  * @param dest always set at least to NULL 
1111  * @parm converted_size set to the number of bytes occupied by the string in
1112  * the destination on success.
1113  *
1114  * @return true if new buffer was correctly allocated, and string was
1115  * converted.
1116  **/
1117
1118 bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src,
1119                       size_t *converted_size)
1120 {
1121         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1122
1123         *dest = NULL;
1124         return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
1125                                      (void **)dest, converted_size);
1126 }
1127
1128 /**
1129  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1130  *
1131  * @param dest always set at least to NULL 
1132  * @parm converted_size set to the number of bytes occupied by the string in
1133  * the destination on success.
1134  *
1135  * @return true if new buffer was correctly allocated, and string was
1136  * converted.
1137  **/
1138
1139 bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
1140                       size_t *converted_size)
1141 {
1142         size_t src_len = strlen(src)+1;
1143
1144         *dest = NULL;
1145         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len,
1146                                      (void **)dest, converted_size);
1147 }
1148
1149  
1150 /**
1151  * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1152  *
1153  * @param dest always set at least to NULL 
1154  * @parm converted_size set to the number of bytes occupied by the string in
1155  * the destination on success.
1156  *
1157  * @return true if new buffer was correctly allocated, and string was
1158  * converted.
1159  **/
1160
1161 bool pull_ascii_talloc(TALLOC_CTX *ctx, char **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_DOS, CH_UNIX, src, src_len,
1168                                      (void **)dest, converted_size);
1169 }
1170
1171 /**
1172  Copy a string from a char* src to a unicode or ascii
1173  dos codepage destination choosing unicode or ascii based on the 
1174  flags supplied
1175  Return the number of bytes occupied by the string in the destination.
1176  flags can have:
1177   STR_TERMINATE means include the null termination.
1178   STR_UPPER     means uppercase in the destination.
1179   STR_ASCII     use ascii even with unicode packet.
1180   STR_NOALIGN   means don't do alignment.
1181  dest_len is the maximum length allowed in the destination. If dest_len
1182  is -1 then no maxiumum is used.
1183 **/
1184
1185 size_t push_string_check_fn(void *dest, const char *src,
1186                          size_t dest_len, int flags)
1187 {
1188         if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
1189                 return push_ucs2(NULL, dest, src, dest_len, flags);
1190         }
1191         return push_ascii(dest, src, dest_len, flags);
1192 }
1193
1194
1195 /**
1196  Copy a string from a char* src to a unicode or ascii
1197  dos codepage destination choosing unicode or ascii based on the 
1198  flags in the SMB buffer starting at base_ptr.
1199  Return the number of bytes occupied by the string in the destination.
1200  flags can have:
1201   STR_TERMINATE means include the null termination.
1202   STR_UPPER     means uppercase in the destination.
1203   STR_ASCII     use ascii even with unicode packet.
1204   STR_NOALIGN   means don't do alignment.
1205  dest_len is the maximum length allowed in the destination. If dest_len
1206  is -1 then no maxiumum is used.
1207 **/
1208
1209 size_t push_string_base(const char *base, uint16 flags2,
1210                         void *dest, const char *src,
1211                         size_t dest_len, int flags)
1212 {
1213
1214         if (!(flags & STR_ASCII) && \
1215             ((flags & STR_UNICODE || \
1216               (flags2 & FLAGS2_UNICODE_STRINGS)))) {
1217                 return push_ucs2(base, dest, src, dest_len, flags);
1218         }
1219         return push_ascii(dest, src, dest_len, flags);
1220 }
1221
1222 /**
1223  Copy a string from a char* src to a unicode or ascii
1224  dos codepage destination choosing unicode or ascii based on the 
1225  flags supplied
1226  Return the number of bytes occupied by the string in the destination.
1227  flags can have:
1228   STR_TERMINATE means include the null termination.
1229   STR_UPPER     means uppercase in the destination.
1230   STR_ASCII     use ascii even with unicode packet.
1231   STR_NOALIGN   means don't do alignment.
1232  dest_len is the maximum length allowed in the destination. If dest_len
1233  is -1 then no maxiumum is used.
1234 **/
1235
1236 ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
1237 {
1238         size_t ret;
1239
1240         if (!(flags & STR_ASCII) && \
1241             (flags & STR_UNICODE)) {
1242                 ret = push_ucs2(NULL, dest, src, dest_len, flags);
1243         } else {
1244                 ret = push_ascii(dest, src, dest_len, flags);
1245         }
1246         if (ret == (size_t)-1) {
1247                 return -1;
1248         }
1249         return ret;
1250 }
1251
1252 /**
1253  Copy a string from a unicode or ascii source (depending on
1254  the packet flags) to a char* destination.
1255  Flags can have:
1256   STR_TERMINATE means the string in src is null terminated.
1257   STR_UNICODE   means to force as unicode.
1258   STR_ASCII     use ascii even with unicode packet.
1259   STR_NOALIGN   means don't do alignment.
1260  if STR_TERMINATE is set then src_len is ignored is it is -1
1261  src_len is the length of the source area in bytes.
1262  Return the number of bytes occupied by the string in src.
1263  The resulting string in "dest" is always null terminated.
1264 **/
1265
1266 size_t pull_string_fn(const void *base_ptr,
1267                    uint16 smb_flags2,
1268                    char *dest,
1269                    const void *src,
1270                    size_t dest_len,
1271                    size_t src_len,
1272                    int flags)
1273 {
1274         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1275                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1276                           "UNICODE defined");
1277         }
1278
1279         if (!(flags & STR_ASCII) && \
1280             ((flags & STR_UNICODE || \
1281               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1282                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1283         }
1284         return pull_ascii(dest, src, dest_len, src_len, flags);
1285 }
1286
1287 /**
1288  Copy a string from a unicode or ascii source (depending on
1289  the packet flags) to a char* destination.
1290  Variant that uses talloc.
1291  Flags can have:
1292   STR_TERMINATE means the string in src is null terminated.
1293   STR_UNICODE   means to force as unicode.
1294   STR_ASCII     use ascii even with unicode packet.
1295   STR_NOALIGN   means don't do alignment.
1296  if STR_TERMINATE is set then src_len is ignored is it is -1
1297  src_len is the length of the source area in bytes.
1298  Return the number of bytes occupied by the string in src.
1299  The resulting string in "dest" is always null terminated.
1300 **/
1301
1302 size_t pull_string_talloc(TALLOC_CTX *ctx,
1303                           const void *base_ptr,
1304                           uint16 smb_flags2,
1305                           char **ppdest,
1306                           const void *src,
1307                           size_t src_len,
1308                           int flags)
1309 {
1310         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1311                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1312                           "UNICODE defined");
1313         }
1314
1315         if (!(flags & STR_ASCII) && \
1316             ((flags & STR_UNICODE || \
1317               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1318                 return pull_ucs2_base_talloc(ctx,
1319                                         base_ptr,
1320                                         ppdest,
1321                                         src,
1322                                         src_len,
1323                                         flags);
1324         }
1325         return pull_ascii_base_talloc(ctx,
1326                                         ppdest,
1327                                         src,
1328                                         src_len,
1329                                         flags);
1330 }
1331
1332
1333 size_t align_string(const void *base_ptr, const char *p, int flags)
1334 {
1335         if (!(flags & STR_ASCII) && \
1336             ((flags & STR_UNICODE || \
1337               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1338                 return ucs2_align(base_ptr, p, flags);
1339         }
1340         return 0;
1341 }
1342