Fixup hot paths - add macro for toupper (c < 0x80).
[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 /* 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_valid_table();
182                 conv_silent = False;
183         }
184 }
185
186 /**
187  * Convert string from one encoding to another, making error checking etc
188  * Slow path version - uses (slow) iconv.
189  *
190  * @param src pointer to source string (multibyte or singlebyte)
191  * @param srclen length of the source string in bytes
192  * @param dest pointer to destination string (multibyte or singlebyte)
193  * @param destlen maximal length allowed for string
194  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
195  * @returns the number of bytes occupied in the destination
196  *
197  * Ensure the srclen contains the terminating zero.
198  *
199  **/
200
201 static size_t convert_string_internal(charset_t from, charset_t to,
202                       void const *src, size_t srclen, 
203                       void *dest, size_t destlen, bool allow_bad_conv)
204 {
205         size_t i_len, o_len;
206         size_t retval;
207         const char* inbuf = (const char*)src;
208         char* outbuf = (char*)dest;
209         smb_iconv_t descriptor;
210
211         lazy_initialize_conv();
212
213         descriptor = conv_handles[from][to];
214
215         if (srclen == (size_t)-1) {
216                 if (from == CH_UTF16LE || from == CH_UTF16BE) {
217                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
218                 } else {
219                         srclen = strlen((const char *)src)+1;
220                 }
221         }
222
223
224         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
225                 if (!conv_silent)
226                         DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
227                 return (size_t)-1;
228         }
229
230         i_len=srclen;
231         o_len=destlen;
232
233  again:
234
235         retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
236         if(retval==(size_t)-1) {
237                 const char *reason="unknown error";
238                 switch(errno) {
239                         case EINVAL:
240                                 reason="Incomplete multibyte sequence";
241                                 if (!conv_silent)
242                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
243                                 if (allow_bad_conv)
244                                         goto use_as_is;
245                                 break;
246                         case E2BIG:
247                                 reason="No more room"; 
248                                 if (!conv_silent) {
249                                         if (from == CH_UNIX) {
250                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
251                                                         charset_name(from), charset_name(to),
252                                                         (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
253                                         } else {
254                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
255                                                         charset_name(from), charset_name(to),
256                                                         (unsigned int)srclen, (unsigned int)destlen));
257                                         }
258                                 }
259                                 break;
260                         case EILSEQ:
261                                 reason="Illegal multibyte sequence";
262                                 if (!conv_silent)
263                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
264                                 if (allow_bad_conv)
265                                         goto use_as_is;
266                                 break;
267                         default:
268                                 if (!conv_silent)
269                                         DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
270                                 break;
271                 }
272                 /* smb_panic(reason); */
273         }
274         return destlen-o_len;
275
276  use_as_is:
277
278         /* 
279          * Conversion not supported. This is actually an error, but there are so
280          * many misconfigured iconv systems and smb.conf's out there we can't just
281          * fail. Do a very bad conversion instead.... JRA.
282          */
283
284         {
285                 if (o_len == 0 || i_len == 0)
286                         return destlen - o_len;
287
288                 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
289                                 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
290                         /* Can't convert from utf16 any endian to multibyte.
291                            Replace with the default fail char.
292                         */
293                         if (i_len < 2)
294                                 return destlen - o_len;
295                         if (i_len >= 2) {
296                                 *outbuf = lp_failed_convert_char();
297
298                                 outbuf++;
299                                 o_len--;
300
301                                 inbuf += 2;
302                                 i_len -= 2;
303                         }
304
305                         if (o_len == 0 || i_len == 0)
306                                 return destlen - o_len;
307
308                         /* Keep trying with the next char... */
309                         goto again;
310
311                 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
312                         /* Can't convert to UTF16LE - just widen by adding the
313                            default fail char then zero.
314                         */
315                         if (o_len < 2)
316                                 return destlen - o_len;
317
318                         outbuf[0] = lp_failed_convert_char();
319                         outbuf[1] = '\0';
320
321                         inbuf++;
322                         i_len--;
323
324                         outbuf += 2;
325                         o_len -= 2;
326
327                         if (o_len == 0 || i_len == 0)
328                                 return destlen - o_len;
329
330                         /* Keep trying with the next char... */
331                         goto again;
332
333                 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
334                                 to != CH_UTF16LE && to != CH_UTF16BE) {
335                         /* Failed multibyte to multibyte. Just copy the default fail char and
336                                 try again. */
337                         outbuf[0] = lp_failed_convert_char();
338
339                         inbuf++;
340                         i_len--;
341
342                         outbuf++;
343                         o_len--;
344
345                         if (o_len == 0 || i_len == 0)
346                                 return destlen - o_len;
347
348                         /* Keep trying with the next char... */
349                         goto again;
350
351                 } else {
352                         /* Keep compiler happy.... */
353                         return destlen - o_len;
354                 }
355         }
356 }
357
358 /**
359  * Convert string from one encoding to another, making error checking etc
360  * Fast path version - handles ASCII first.
361  *
362  * @param src pointer to source string (multibyte or singlebyte)
363  * @param srclen length of the source string in bytes, or -1 for nul terminated.
364  * @param dest pointer to destination string (multibyte or singlebyte)
365  * @param destlen maximal length allowed for string - *NEVER* -1.
366  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
367  * @returns the number of bytes occupied in the destination
368  *
369  * Ensure the srclen contains the terminating zero.
370  *
371  * This function has been hand-tuned to provide a fast path.
372  * Don't change unless you really know what you are doing. JRA.
373  **/
374
375 size_t convert_string(charset_t from, charset_t to,
376                       void const *src, size_t srclen, 
377                       void *dest, size_t destlen, bool allow_bad_conv)
378 {
379         /*
380          * NB. We deliberately don't do a strlen here if srclen == -1.
381          * This is very expensive over millions of calls and is taken
382          * care of in the slow path in convert_string_internal. JRA.
383          */
384
385 #ifdef DEVELOPER
386         SMB_ASSERT(destlen != (size_t)-1);
387 #endif
388
389         if (srclen == 0)
390                 return 0;
391
392         if (from != CH_UTF16LE && from != CH_UTF16BE && to != CH_UTF16LE && to != CH_UTF16BE) {
393                 const unsigned char *p = (const unsigned char *)src;
394                 unsigned char *q = (unsigned char *)dest;
395                 size_t slen = srclen;
396                 size_t dlen = destlen;
397                 unsigned char lastp = '\0';
398                 size_t retval = 0;
399
400                 /* If all characters are ascii, fast path here. */
401                 while (slen && dlen) {
402                         if ((lastp = *p) <= 0x7f) {
403                                 *q++ = *p++;
404                                 if (slen != (size_t)-1) {
405                                         slen--;
406                                 }
407                                 dlen--;
408                                 retval++;
409                                 if (!lastp)
410                                         break;
411                         } else {
412 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
413                                 goto general_case;
414 #else
415                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
416 #endif
417                         }
418                 }
419                 if (!dlen) {
420                         /* Even if we fast path we should note if we ran out of room. */
421                         if (((slen != (size_t)-1) && slen) ||
422                                         ((slen == (size_t)-1) && lastp)) {
423                                 errno = E2BIG;
424                         }
425                 }
426                 return retval;
427         } else if (from == CH_UTF16LE && to != CH_UTF16LE) {
428                 const unsigned char *p = (const unsigned char *)src;
429                 unsigned char *q = (unsigned char *)dest;
430                 size_t retval = 0;
431                 size_t slen = srclen;
432                 size_t dlen = destlen;
433                 unsigned char lastp = '\0';
434
435                 /* If all characters are ascii, fast path here. */
436                 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
437                         if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
438                                 *q++ = *p;
439                                 if (slen != (size_t)-1) {
440                                         slen -= 2;
441                                 }
442                                 p += 2;
443                                 dlen--;
444                                 retval++;
445                                 if (!lastp)
446                                         break;
447                         } else {
448 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
449                                 goto general_case;
450 #else
451                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
452 #endif
453                         }
454                 }
455                 if (!dlen) {
456                         /* Even if we fast path we should note if we ran out of room. */
457                         if (((slen != (size_t)-1) && slen) ||
458                                         ((slen == (size_t)-1) && lastp)) {
459                                 errno = E2BIG;
460                         }
461                 }
462                 return retval;
463         } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
464                 const unsigned char *p = (const unsigned char *)src;
465                 unsigned char *q = (unsigned char *)dest;
466                 size_t retval = 0;
467                 size_t slen = srclen;
468                 size_t dlen = destlen;
469                 unsigned char lastp = '\0';
470
471                 /* If all characters are ascii, fast path here. */
472                 while (slen && (dlen >= 2)) {
473                         if ((lastp = *p) <= 0x7F) {
474                                 *q++ = *p++;
475                                 *q++ = '\0';
476                                 if (slen != (size_t)-1) {
477                                         slen--;
478                                 }
479                                 dlen -= 2;
480                                 retval += 2;
481                                 if (!lastp)
482                                         break;
483                         } else {
484 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
485                                 goto general_case;
486 #else
487                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
488 #endif
489                         }
490                 }
491                 if (!dlen) {
492                         /* Even if we fast path we should note if we ran out of room. */
493                         if (((slen != (size_t)-1) && slen) ||
494                                         ((slen == (size_t)-1) && lastp)) {
495                                 errno = E2BIG;
496                         }
497                 }
498                 return retval;
499         }
500
501 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
502   general_case:
503 #endif
504         return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
505 }
506
507 /**
508  * Convert between character sets, allocating a new buffer for the result.
509  *
510  * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
511  * (this is a bad interface and needs fixing. JRA).
512  * @param srclen length of source buffer.
513  * @param dest always set at least to NULL
514  * @note -1 is not accepted for srclen.
515  *
516  * @returns Size in bytes of the converted string; or -1 in case of error.
517  *
518  * Ensure the srclen contains the terminating zero.
519  *
520  * I hate the goto's in this function. It's embarressing.....
521  * There has to be a cleaner way to do this. JRA.
522  **/
523
524 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
525                                void const *src, size_t srclen, void *dst, bool allow_bad_conv)
526 {
527         size_t i_len, o_len, destlen = MAX(srclen, 512);
528         size_t retval;
529         const char *inbuf = (const char *)src;
530         char *outbuf = NULL, *ob = NULL;
531         smb_iconv_t descriptor;
532         void **dest = (void **)dst;
533
534         *dest = NULL;
535
536         if (src == NULL || srclen == (size_t)-1)
537                 return (size_t)-1;
538         if (srclen == 0)
539                 return 0;
540
541         lazy_initialize_conv();
542
543         descriptor = conv_handles[from][to];
544
545         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
546                 if (!conv_silent)
547                         DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
548                 return (size_t)-1;
549         }
550
551   convert:
552
553         if ((destlen*2) < destlen) {
554                 /* wrapped ! abort. */
555                 if (!conv_silent)
556                         DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
557                 if (!ctx)
558                         SAFE_FREE(outbuf);
559                 return (size_t)-1;
560         } else {
561                 destlen = destlen * 2;
562         }
563
564         if (ctx) {
565                 ob = (char *)TALLOC_REALLOC(ctx, ob, destlen);
566         } else {
567                 ob = (char *)SMB_REALLOC(ob, destlen);
568         }
569
570         if (!ob) {
571                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
572                 return (size_t)-1;
573         }
574         outbuf = ob;
575         i_len = srclen;
576         o_len = destlen;
577
578  again:
579
580         retval = smb_iconv(descriptor,
581                            &inbuf, &i_len,
582                            &outbuf, &o_len);
583         if(retval == (size_t)-1)                {
584                 const char *reason="unknown error";
585                 switch(errno) {
586                         case EINVAL:
587                                 reason="Incomplete multibyte sequence";
588                                 if (!conv_silent)
589                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
590                                 if (allow_bad_conv)
591                                         goto use_as_is;
592                                 break;
593                         case E2BIG:
594                                 goto convert;
595                         case EILSEQ:
596                                 reason="Illegal multibyte sequence";
597                                 if (!conv_silent)
598                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
599                                 if (allow_bad_conv)
600                                         goto use_as_is;
601                                 break;
602                 }
603                 if (!conv_silent)
604                         DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
605                 /* smb_panic(reason); */
606                 if (ctx) {
607                         TALLOC_FREE(ob);
608                 } else {
609                         SAFE_FREE(ob);
610                 }
611                 return (size_t)-1;
612         }
613
614   out:
615
616         destlen = destlen - o_len;
617         /* Don't shrink unless we're reclaiming a lot of
618          * space. This is in the hot codepath and these
619          * reallocs *cost*. JRA.
620          */
621         if (o_len > 1024) {
622                 if (ctx) {
623                         ob = (char *)TALLOC_REALLOC(ctx,ob,destlen);
624                 } else {
625                         ob = (char *)SMB_REALLOC(ob,destlen);
626                 }
627         }
628
629         if (destlen && !ob) {
630                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
631                 return (size_t)-1;
632         }
633
634         *dest = ob;
635         return destlen;
636
637  use_as_is:
638
639         /* 
640          * Conversion not supported. This is actually an error, but there are so
641          * many misconfigured iconv systems and smb.conf's out there we can't just
642          * fail. Do a very bad conversion instead.... JRA.
643          */
644
645         {
646                 if (o_len == 0 || i_len == 0)
647                         goto out;
648
649                 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
650                                 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
651                         /* Can't convert from utf16 any endian to multibyte.
652                            Replace with the default fail char.
653                         */
654
655                         if (i_len < 2)
656                                 goto out;
657
658                         if (i_len >= 2) {
659                                 *outbuf = lp_failed_convert_char();
660
661                                 outbuf++;
662                                 o_len--;
663
664                                 inbuf += 2;
665                                 i_len -= 2;
666                         }
667
668                         if (o_len == 0 || i_len == 0)
669                                 goto out;
670
671                         /* Keep trying with the next char... */
672                         goto again;
673
674                 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
675                         /* Can't convert to UTF16LE - just widen by adding the
676                            default fail char then zero.
677                         */
678                         if (o_len < 2)
679                                 goto out;
680
681                         outbuf[0] = lp_failed_convert_char();
682                         outbuf[1] = '\0';
683
684                         inbuf++;
685                         i_len--;
686
687                         outbuf += 2;
688                         o_len -= 2;
689
690                         if (o_len == 0 || i_len == 0)
691                                 goto out;
692
693                         /* Keep trying with the next char... */
694                         goto again;
695
696                 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
697                                 to != CH_UTF16LE && to != CH_UTF16BE) {
698                         /* Failed multibyte to multibyte. Just copy the default fail char and
699                            try again. */
700                         outbuf[0] = lp_failed_convert_char();
701
702                         inbuf++;
703                         i_len--;
704
705                         outbuf++;
706                         o_len--;
707
708                         if (o_len == 0 || i_len == 0)
709                                 goto out;
710
711                         /* Keep trying with the next char... */
712                         goto again;
713
714                 } else {
715                         /* Keep compiler happy.... */
716                         goto out;
717                 }
718         }
719 }
720
721 /**
722  * Convert between character sets, allocating a new buffer using talloc for the result.
723  *
724  * @param srclen length of source buffer.
725  * @param dest always set at least to NULL
726  * @note -1 is not accepted for srclen.
727  *
728  * @returns Size in bytes of the converted string; or -1 in case of error.
729  **/
730 size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
731                              void const *src, size_t srclen, void *dst,
732                              bool allow_bad_conv)
733 {
734         void **dest = (void **)dst;
735         size_t dest_len;
736
737         *dest = NULL;
738         dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv);
739         if (dest_len == (size_t)-1)
740                 return (size_t)-1;
741         if (*dest == NULL)
742                 return (size_t)-1;
743         return dest_len;
744 }
745
746 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
747 {
748         size_t size;
749         smb_ucs2_t *buffer;
750
751         size = push_ucs2_allocate(&buffer, src);
752         if (size == (size_t)-1) {
753                 return (size_t)-1;
754         }
755         if (!strupper_w(buffer) && (dest == src)) {
756                 free(buffer);
757                 return srclen;
758         }
759
760         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
761         free(buffer);
762         return size;
763 }
764
765 /**
766  strdup() a unix string to upper case.
767 **/
768
769 char *strdup_upper(const char *s)
770 {
771         char *out_buffer = SMB_STRDUP(s);
772         const unsigned char *p = (const unsigned char *)s;
773         unsigned char *q = (unsigned char *)out_buffer;
774
775         if (!q) {
776                 return NULL;
777         }
778
779         /* this is quite a common operation, so we want it to be
780            fast. We optimise for the ascii case, knowing that all our
781            supported multi-byte character sets are ascii-compatible
782            (ie. they match for the first 128 chars) */
783
784         while (*p) {
785                 if (*p & 0x80)
786                         break;
787                 *q++ = toupper_ascii_fast(*p);
788                 p++;
789         }
790
791         if (*p) {
792                 /* MB case. */
793                 size_t size;
794                 smb_ucs2_t *buffer = NULL;
795
796                 SAFE_FREE(out_buffer);
797                 size = convert_string_allocate(NULL,
798                                         CH_UNIX,
799                                         CH_UTF16LE,
800                                         s,
801                                         strlen(s) + 1,
802                                         (void **)(void *)&buffer,
803                                         True);
804                 if (size == (size_t)-1) {
805                         return NULL;
806                 }
807
808                 strupper_w(buffer);
809
810                 size = convert_string_allocate(NULL,
811                                         CH_UTF16LE,
812                                         CH_UNIX,
813                                         buffer,
814                                         size,
815                                         (void **)(void *)&out_buffer,
816                                         True);
817
818                 /* Don't need the intermediate buffer
819                  * anymore.
820                  */
821
822                 TALLOC_FREE(buffer);
823                 if (size == (size_t)-1) {
824                         return NULL;
825                 }
826         }
827
828         return out_buffer;
829 }
830
831 /**
832  talloc_strdup() a unix string to upper case.
833 **/
834
835 char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
836 {
837         char *out_buffer = talloc_strdup(ctx,s);
838         const unsigned char *p = (const unsigned char *)s;
839         unsigned char *q = (unsigned char *)out_buffer;
840
841         if (!q) {
842                 return NULL;
843         }
844
845         /* this is quite a common operation, so we want it to be
846            fast. We optimise for the ascii case, knowing that all our
847            supported multi-byte character sets are ascii-compatible
848            (ie. they match for the first 128 chars) */
849
850         while (*p) {
851                 if (*p & 0x80)
852                         break;
853                 *q++ = toupper_ascii_fast(*p);
854                 p++;
855         }
856
857         if (*p) {
858                 /* MB case. */
859                 size_t size;
860                 smb_ucs2_t *ubuf = NULL;
861
862                 /* We're not using the ascii buffer above. */
863                 TALLOC_FREE(out_buffer);
864
865                 size = convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE,
866                                 s, strlen(s)+1,
867                                 (void *)&ubuf,
868                                 True);
869                 if (size == (size_t)-1) {
870                         return NULL;
871                 }
872
873                 strupper_w(ubuf);
874
875                 size = convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX,
876                                 ubuf, size,
877                                 (void *)&out_buffer,
878                                 True);
879
880                 /* Don't need the intermediate buffer
881                  * anymore.
882                  */
883
884                 TALLOC_FREE(ubuf);
885
886                 if (size == (size_t)-1) {
887                         return NULL;
888                 }
889         }
890
891         return out_buffer;
892 }
893
894 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
895 {
896         size_t size;
897         smb_ucs2_t *buffer = NULL;
898
899         size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
900                                        (void **)(void *)&buffer, True);
901         if (size == (size_t)-1 || !buffer) {
902                 smb_panic("failed to create UCS2 buffer");
903         }
904         if (!strlower_w(buffer) && (dest == src)) {
905                 SAFE_FREE(buffer);
906                 return srclen;
907         }
908         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
909         SAFE_FREE(buffer);
910         return size;
911 }
912
913 /**
914  strdup() a unix string to lower case.
915 **/
916
917 char *strdup_lower(const char *s)
918 {
919         size_t size;
920         smb_ucs2_t *buffer = NULL;
921         char *out_buffer;
922
923         size = push_ucs2_allocate(&buffer, s);
924         if (size == -1 || !buffer) {
925                 return NULL;
926         }
927
928         strlower_w(buffer);
929
930         size = pull_ucs2_allocate(&out_buffer, buffer);
931         SAFE_FREE(buffer);
932
933         if (size == (size_t)-1) {
934                 return NULL;
935         }
936
937         return out_buffer;
938 }
939
940 size_t ucs2_align(const void *base_ptr, const void *p, int flags)
941 {
942         if (flags & (STR_NOALIGN|STR_ASCII))
943                 return 0;
944         return PTR_DIFF(p, base_ptr) & 1;
945 }
946
947
948 /**
949  * Copy a string from a char* unix src to a dos codepage string destination.
950  *
951  * @return the number of bytes occupied by the string in the destination.
952  *
953  * @param flags can include
954  * <dl>
955  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
956  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
957  * </dl>
958  *
959  * @param dest_len the maximum length in bytes allowed in the
960  * destination.
961  **/
962 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
963 {
964         size_t src_len = strlen(src);
965         char *tmpbuf = NULL;
966         size_t ret;
967
968         /* No longer allow a length of -1. */
969         if (dest_len == (size_t)-1) {
970                 smb_panic("push_ascii - dest_len == -1");
971         }
972
973         if (flags & STR_UPPER) {
974                 tmpbuf = SMB_STRDUP(src);
975                 if (!tmpbuf) {
976                         smb_panic("malloc fail");
977                 }
978                 strupper_m(tmpbuf);
979                 src = tmpbuf;
980         }
981
982         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
983                 src_len++;
984         }
985
986         ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
987         if (ret == (size_t)-1 &&
988                         (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
989                         && dest_len > 0) {
990                 ((char *)dest)[0] = '\0';
991         }
992         SAFE_FREE(tmpbuf);
993         return ret;
994 }
995
996 size_t push_ascii_fstring(void *dest, const char *src)
997 {
998         return push_ascii(dest, src, sizeof(fstring), 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 size_t pull_ascii_fstring(char *dest, const void *src)
1187 {
1188         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
1189 }
1190
1191 /* When pulling an nstring it can expand into a larger size (dos cp -> utf8). Cope with this. */
1192
1193 size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
1194 {
1195         return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
1196 }
1197
1198 /**
1199  * Copy a string from a char* src to a unicode destination.
1200  *
1201  * @returns the number of bytes occupied by the string in the destination.
1202  *
1203  * @param flags can have:
1204  *
1205  * <dl>
1206  * <dt>STR_TERMINATE <dd>means include the null termination.
1207  * <dt>STR_UPPER     <dd>means uppercase in the destination.
1208  * <dt>STR_NOALIGN   <dd>means don't do alignment.
1209  * </dl>
1210  *
1211  * @param dest_len is the maximum length allowed in the
1212  * destination.
1213  **/
1214
1215 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
1216 {
1217         size_t len=0;
1218         size_t src_len;
1219         size_t ret;
1220
1221         if (dest_len == (size_t)-1) {
1222                 /* No longer allow dest_len of -1. */
1223                 smb_panic("push_ucs2 - invalid dest_len of -1");
1224         }
1225
1226         if (flags & STR_TERMINATE)
1227                 src_len = (size_t)-1;
1228         else
1229                 src_len = strlen(src);
1230
1231         if (ucs2_align(base_ptr, dest, flags)) {
1232                 *(char *)dest = 0;
1233                 dest = (void *)((char *)dest + 1);
1234                 if (dest_len)
1235                         dest_len--;
1236                 len++;
1237         }
1238
1239         /* ucs2 is always a multiple of 2 bytes */
1240         dest_len &= ~1;
1241
1242         ret =  convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
1243         if (ret == (size_t)-1) {
1244                 if ((flags & STR_TERMINATE) &&
1245                                 dest &&
1246                                 dest_len) {
1247                         *(char *)dest = 0;
1248                 }
1249                 return len;
1250         }
1251
1252         len += ret;
1253
1254         if (flags & STR_UPPER) {
1255                 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
1256                 size_t i;
1257
1258                 /* We check for i < (ret / 2) below as the dest string isn't null
1259                    terminated if STR_TERMINATE isn't set. */
1260
1261                 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
1262                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
1263                         if (v != dest_ucs2[i]) {
1264                                 dest_ucs2[i] = v;
1265                         }
1266                 }
1267         }
1268
1269         return len;
1270 }
1271
1272
1273 /**
1274  * Copy a string from a unix char* src to a UCS2 destination,
1275  * allocating a buffer using talloc().
1276  *
1277  * @param dest always set at least to NULL 
1278  *
1279  * @returns The number of bytes occupied by the string in the destination
1280  *         or -1 in case of error.
1281  **/
1282 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
1283 {
1284         size_t src_len = strlen(src)+1;
1285
1286         *dest = NULL;
1287         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
1288 }
1289
1290
1291 /**
1292  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
1293  *
1294  * @param dest always set at least to NULL 
1295  *
1296  * @returns The number of bytes occupied by the string in the destination
1297  *         or -1 in case of error.
1298  **/
1299
1300 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
1301 {
1302         size_t src_len = strlen(src)+1;
1303
1304         *dest = NULL;
1305         return convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
1306 }
1307
1308 /**
1309  Copy a string from a char* src to a UTF-8 destination.
1310  Return the number of bytes occupied by the string in the destination
1311  Flags can have:
1312   STR_TERMINATE means include the null termination
1313   STR_UPPER     means uppercase in the destination
1314  dest_len is the maximum length allowed in the destination. If dest_len
1315  is -1 then no maxiumum is used.
1316 **/
1317
1318 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
1319 {
1320         size_t src_len = 0;
1321         size_t ret;
1322         char *tmpbuf = NULL;
1323
1324         if (dest_len == (size_t)-1) {
1325                 /* No longer allow dest_len of -1. */
1326                 smb_panic("push_utf8 - invalid dest_len of -1");
1327         }
1328
1329         if (flags & STR_UPPER) {
1330                 tmpbuf = strdup_upper(src);
1331                 if (!tmpbuf) {
1332                         return (size_t)-1;
1333                 }
1334                 src = tmpbuf;
1335                 src_len = strlen(src);
1336         }
1337
1338         src_len = strlen(src);
1339         if (flags & STR_TERMINATE) {
1340                 src_len++;
1341         }
1342
1343         ret = convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
1344         SAFE_FREE(tmpbuf);
1345         return ret;
1346 }
1347
1348 size_t push_utf8_fstring(void *dest, const char *src)
1349 {
1350         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
1351 }
1352
1353 /**
1354  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1355  *
1356  * @param dest always set at least to NULL 
1357  *
1358  * @returns The number of bytes occupied by the string in the destination
1359  **/
1360
1361 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1362 {
1363         size_t src_len = strlen(src)+1;
1364
1365         *dest = NULL;
1366         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
1367 }
1368
1369 /**
1370  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
1371  *
1372  * @param dest always set at least to NULL 
1373  *
1374  * @returns The number of bytes occupied by the string in the destination
1375  **/
1376
1377 size_t push_utf8_allocate(char **dest, const char *src)
1378 {
1379         size_t src_len = strlen(src)+1;
1380
1381         *dest = NULL;
1382         return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);      
1383 }
1384
1385 /**
1386  Copy a string from a ucs2 source to a unix char* destination.
1387  Flags can have:
1388   STR_TERMINATE means the string in src is null terminated.
1389   STR_NOALIGN   means don't try to align.
1390  if STR_TERMINATE is set then src_len is ignored if it is -1.
1391  src_len is the length of the source area in bytes
1392  Return the number of bytes occupied by the string in src.
1393  The resulting string in "dest" is always null terminated.
1394 **/
1395
1396 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1397 {
1398         size_t ret;
1399
1400         if (dest_len == (size_t)-1) {
1401                 /* No longer allow dest_len of -1. */
1402                 smb_panic("pull_ucs2 - invalid dest_len of -1");
1403         }
1404
1405         if (!src_len) {
1406                 if (dest && dest_len > 0) {
1407                         dest[0] = '\0';
1408                 }
1409                 return 0;
1410         }
1411
1412         if (ucs2_align(base_ptr, src, flags)) {
1413                 src = (const void *)((const char *)src + 1);
1414                 if (src_len != (size_t)-1)
1415                         src_len--;
1416         }
1417
1418         if (flags & STR_TERMINATE) {
1419                 /* src_len -1 is the default for null terminated strings. */
1420                 if (src_len != (size_t)-1) {
1421                         size_t len = strnlen_w((const smb_ucs2_t *)src,
1422                                                 src_len/2);
1423                         if (len < src_len/2)
1424                                 len++;
1425                         src_len = len*2;
1426                 }
1427         }
1428
1429         /* ucs2 is always a multiple of 2 bytes */
1430         if (src_len != (size_t)-1)
1431                 src_len &= ~1;
1432
1433         ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
1434         if (ret == (size_t)-1) {
1435                 ret = 0;
1436                 dest_len = 0;
1437         }
1438
1439         if (src_len == (size_t)-1)
1440                 src_len = ret*2;
1441
1442         if (dest_len && ret) {
1443                 /* Did we already process the terminating zero ? */
1444                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
1445                         dest[MIN(ret, dest_len-1)] = 0;
1446                 }
1447         } else {
1448                 dest[0] = 0;
1449         }
1450
1451         return src_len;
1452 }
1453
1454 /**
1455  Copy a string from a ucs2 source to a unix char* destination.
1456  Talloc version with a base pointer.
1457  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1458  needs fixing. JRA).
1459  Flags can have:
1460   STR_TERMINATE means the string in src is null terminated.
1461   STR_NOALIGN   means don't try to align.
1462  if STR_TERMINATE is set then src_len is ignored if it is -1.
1463  src_len is the length of the source area in bytes
1464  Return the number of bytes occupied by the string in src.
1465  The resulting string in "dest" is always null terminated.
1466 **/
1467
1468 size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
1469                         const void *base_ptr,
1470                         char **ppdest,
1471                         const void *src,
1472                         size_t src_len,
1473                         int flags)
1474 {
1475         char *dest;
1476         size_t dest_len;
1477
1478         *ppdest = NULL;
1479
1480 #ifdef DEVELOPER
1481         /* Ensure we never use the braindead "malloc" varient. */
1482         if (ctx == NULL) {
1483                 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
1484         }
1485 #endif
1486
1487         if (!src_len) {
1488                 return 0;
1489         }
1490
1491         if (ucs2_align(base_ptr, src, flags)) {
1492                 src = (const void *)((const char *)src + 1);
1493                 if (src_len != (size_t)-1)
1494                         src_len--;
1495         }
1496
1497         if (flags & STR_TERMINATE) {
1498                 /* src_len -1 is the default for null terminated strings. */
1499                 if (src_len != (size_t)-1) {
1500                         size_t len = strnlen_w((const smb_ucs2_t *)src,
1501                                                 src_len/2);
1502                         if (len < src_len/2)
1503                                 len++;
1504                         src_len = len*2;
1505                 } else {
1506                         /*
1507                          * src_len == -1 - alloc interface won't take this
1508                          * so we must calculate.
1509                          */
1510                         src_len = (strlen_w((const smb_ucs2_t *)src)+1)*sizeof(smb_ucs2_t);
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_fstring(char *dest, const void *src)
1565 {
1566         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
1567 }
1568
1569 /**
1570  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1571  *
1572  * @param dest always set at least to NULL 
1573  *
1574  * @returns The number of bytes occupied by the string in the destination
1575  **/
1576
1577 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
1578 {
1579         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1580         *dest = NULL;
1581         return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
1582 }
1583
1584 /**
1585  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
1586  *
1587  * @param dest always set at least to NULL 
1588  *
1589  * @returns The number of bytes occupied by the string in the destination
1590  **/
1591
1592 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
1593 {
1594         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1595         *dest = NULL;
1596         return convert_string_allocate(NULL, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
1597 }
1598
1599 /**
1600  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1601  *
1602  * @param dest always set at least to NULL 
1603  *
1604  * @returns The number of bytes occupied by the string in the destination
1605  **/
1606
1607 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1608 {
1609         size_t src_len = strlen(src)+1;
1610         *dest = NULL;
1611         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1612 }
1613
1614 /**
1615  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
1616  *
1617  * @param dest always set at least to NULL 
1618  *
1619  * @returns The number of bytes occupied by the string in the destination
1620  **/
1621
1622 size_t pull_utf8_allocate(char **dest, const char *src)
1623 {
1624         size_t src_len = strlen(src)+1;
1625         *dest = NULL;
1626         return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1627 }
1628  
1629 /**
1630  * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1631  *
1632  * @param dest always set at least to NULL 
1633  *
1634  * @returns The number of bytes occupied by the string in the destination
1635  **/
1636
1637 size_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1638 {
1639         size_t src_len = strlen(src)+1;
1640         *dest = NULL;
1641         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True);
1642 }
1643
1644 /**
1645  Copy a string from a char* src to a unicode or ascii
1646  dos codepage destination choosing unicode or ascii based on the 
1647  flags in the SMB buffer starting at base_ptr.
1648  Return the number of bytes occupied by the string in the destination.
1649  flags can have:
1650   STR_TERMINATE means include the null termination.
1651   STR_UPPER     means uppercase in the destination.
1652   STR_ASCII     use ascii even with unicode packet.
1653   STR_NOALIGN   means don't do alignment.
1654  dest_len is the maximum length allowed in the destination. If dest_len
1655  is -1 then no maxiumum is used.
1656 **/
1657
1658 size_t push_string_fn(const char *function, unsigned int line,
1659                       const void *base_ptr, uint16 flags2,
1660                       void *dest, const char *src,
1661                       size_t dest_len, int flags)
1662 {
1663 #ifdef DEVELOPER
1664         /* We really need to zero fill here, not clobber
1665          * region, as we want to ensure that valgrind thinks
1666          * all of the outgoing buffer has been written to
1667          * so a send() or write() won't trap an error.
1668          * JRA.
1669          */
1670 #if 0
1671         clobber_region(function, line, dest, dest_len);
1672 #else
1673         memset(dest, '\0', dest_len);
1674 #endif
1675 #endif
1676
1677         if (!(flags & STR_ASCII) && \
1678             ((flags & STR_UNICODE || \
1679               (flags2 & FLAGS2_UNICODE_STRINGS)))) {
1680                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
1681         }
1682         return push_ascii(dest, src, dest_len, flags);
1683 }
1684
1685
1686 /**
1687  Copy a string from a unicode or ascii source (depending on
1688  the packet flags) to a char* destination.
1689  Flags can have:
1690   STR_TERMINATE means the string in src is null terminated.
1691   STR_UNICODE   means to force as unicode.
1692   STR_ASCII     use ascii even with unicode packet.
1693   STR_NOALIGN   means don't do alignment.
1694  if STR_TERMINATE is set then src_len is ignored is it is -1
1695  src_len is the length of the source area in bytes.
1696  Return the number of bytes occupied by the string in src.
1697  The resulting string in "dest" is always null terminated.
1698 **/
1699
1700 size_t pull_string_fn(const char *function,
1701                         unsigned int line,
1702                         const void *base_ptr,
1703                         uint16 smb_flags2,
1704                         char *dest,
1705                         const void *src,
1706                         size_t dest_len,
1707                         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 }