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