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