Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
[jra/samba/.git] / source / 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         if (ctx) {
618                 ob = (char *)TALLOC_REALLOC(ctx,ob,destlen);
619         } else {
620                 ob = (char *)SMB_REALLOC(ob,destlen);
621         }
622
623         if (destlen && !ob) {
624                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
625                 return (size_t)-1;
626         }
627
628         *dest = ob;
629         return destlen;
630
631  use_as_is:
632
633         /* 
634          * Conversion not supported. This is actually an error, but there are so
635          * many misconfigured iconv systems and smb.conf's out there we can't just
636          * fail. Do a very bad conversion instead.... JRA.
637          */
638
639         {
640                 if (o_len == 0 || i_len == 0)
641                         goto out;
642
643                 if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
644                                 ((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
645                         /* Can't convert from utf16 any endian to multibyte.
646                            Replace with the default fail char.
647                         */
648
649                         if (i_len < 2)
650                                 goto out;
651
652                         if (i_len >= 2) {
653                                 *outbuf = lp_failed_convert_char();
654
655                                 outbuf++;
656                                 o_len--;
657
658                                 inbuf += 2;
659                                 i_len -= 2;
660                         }
661
662                         if (o_len == 0 || i_len == 0)
663                                 goto out;
664
665                         /* Keep trying with the next char... */
666                         goto again;
667
668                 } else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
669                         /* Can't convert to UTF16LE - just widen by adding the
670                            default fail char then zero.
671                         */
672                         if (o_len < 2)
673                                 goto out;
674
675                         outbuf[0] = lp_failed_convert_char();
676                         outbuf[1] = '\0';
677
678                         inbuf++;
679                         i_len--;
680
681                         outbuf += 2;
682                         o_len -= 2;
683
684                         if (o_len == 0 || i_len == 0)
685                                 goto out;
686
687                         /* Keep trying with the next char... */
688                         goto again;
689
690                 } else if (from != CH_UTF16LE && from != CH_UTF16BE &&
691                                 to != CH_UTF16LE && to != CH_UTF16BE) {
692                         /* Failed multibyte to multibyte. Just copy the default fail char and
693                            try again. */
694                         outbuf[0] = lp_failed_convert_char();
695
696                         inbuf++;
697                         i_len--;
698
699                         outbuf++;
700                         o_len--;
701
702                         if (o_len == 0 || i_len == 0)
703                                 goto out;
704
705                         /* Keep trying with the next char... */
706                         goto again;
707
708                 } else {
709                         /* Keep compiler happy.... */
710                         goto out;
711                 }
712         }
713 }
714
715 /**
716  * Convert between character sets, allocating a new buffer using talloc for the result.
717  *
718  * @param srclen length of source buffer.
719  * @param dest always set at least to NULL
720  * @note -1 is not accepted for srclen.
721  *
722  * @returns Size in bytes of the converted string; or -1 in case of error.
723  **/
724 size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
725                              void const *src, size_t srclen, void *dst,
726                              bool allow_bad_conv)
727 {
728         void **dest = (void **)dst;
729         size_t dest_len;
730
731         *dest = NULL;
732         dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv);
733         if (dest_len == (size_t)-1)
734                 return (size_t)-1;
735         if (*dest == NULL)
736                 return (size_t)-1;
737         return dest_len;
738 }
739
740 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
741 {
742         size_t size;
743         smb_ucs2_t *buffer;
744
745         size = push_ucs2_allocate(&buffer, src);
746         if (size == (size_t)-1) {
747                 return (size_t)-1;
748         }
749         if (!strupper_w(buffer) && (dest == src)) {
750                 free(buffer);
751                 return srclen;
752         }
753
754         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
755         free(buffer);
756         return size;
757 }
758
759 /**
760  strdup() a unix string to upper case.
761 **/
762
763 char *strdup_upper(const char *s)
764 {
765         char *out_buffer = SMB_STRDUP(s);
766         const unsigned char *p = (const unsigned char *)s;
767         unsigned char *q = (unsigned char *)out_buffer;
768
769         if (!q) {
770                 return NULL;
771         }
772
773         /* this is quite a common operation, so we want it to be
774            fast. We optimise for the ascii case, knowing that all our
775            supported multi-byte character sets are ascii-compatible
776            (ie. they match for the first 128 chars) */
777
778         while (*p) {
779                 if (*p & 0x80)
780                         break;
781                 *q++ = toupper_ascii(*p);
782                 p++;
783         }
784
785         if (*p) {
786                 /* MB case. */
787                 size_t size;
788                 smb_ucs2_t *buffer = NULL;
789
790                 SAFE_FREE(out_buffer);
791                 size = convert_string_allocate(NULL,
792                                         CH_UNIX,
793                                         CH_UTF16LE,
794                                         s,
795                                         strlen(s) + 1,
796                                         (void **)(void *)&buffer,
797                                         True);
798                 if (size == (size_t)-1) {
799                         return NULL;
800                 }
801
802                 strupper_w(buffer);
803
804                 size = convert_string_allocate(NULL,
805                                         CH_UTF16LE,
806                                         CH_UNIX,
807                                         buffer,
808                                         size,
809                                         (void **)(void *)&out_buffer,
810                                         True);
811
812                 /* Don't need the intermediate buffer
813                  * anymore.
814                  */
815
816                 TALLOC_FREE(buffer);
817                 if (size == (size_t)-1) {
818                         return NULL;
819                 }
820         }
821
822         return out_buffer;
823 }
824
825 /**
826  talloc_strdup() a unix string to upper case.
827 **/
828
829 char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
830 {
831         char *out_buffer = talloc_strdup(ctx,s);
832         const unsigned char *p = (const unsigned char *)s;
833         unsigned char *q = (unsigned char *)out_buffer;
834
835         if (!q) {
836                 return NULL;
837         }
838
839         /* this is quite a common operation, so we want it to be
840            fast. We optimise for the ascii case, knowing that all our
841            supported multi-byte character sets are ascii-compatible
842            (ie. they match for the first 128 chars) */
843
844         while (*p) {
845                 if (*p & 0x80)
846                         break;
847                 *q++ = toupper_ascii(*p);
848                 p++;
849         }
850
851         if (*p) {
852                 /* MB case. */
853                 size_t size;
854                 smb_ucs2_t *ubuf = NULL;
855
856                 /* We're not using the ascii buffer above. */
857                 TALLOC_FREE(out_buffer);
858
859                 size = convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE,
860                                 s, strlen(s)+1,
861                                 (void *)&ubuf,
862                                 True);
863                 if (size == (size_t)-1) {
864                         return NULL;
865                 }
866
867                 strupper_w(ubuf);
868
869                 size = convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX,
870                                 ubuf, size,
871                                 (void *)&out_buffer,
872                                 True);
873
874                 /* Don't need the intermediate buffer
875                  * anymore.
876                  */
877
878                 TALLOC_FREE(ubuf);
879
880                 if (size == (size_t)-1) {
881                         return NULL;
882                 }
883         }
884
885         return out_buffer;
886 }
887
888 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
889 {
890         size_t size;
891         smb_ucs2_t *buffer = NULL;
892
893         size = convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, srclen,
894                                        (void **)(void *)&buffer, True);
895         if (size == (size_t)-1 || !buffer) {
896                 smb_panic("failed to create UCS2 buffer");
897         }
898         if (!strlower_w(buffer) && (dest == src)) {
899                 SAFE_FREE(buffer);
900                 return srclen;
901         }
902         size = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, True);
903         SAFE_FREE(buffer);
904         return size;
905 }
906
907 /**
908  strdup() a unix string to lower case.
909 **/
910
911 char *strdup_lower(const char *s)
912 {
913         size_t size;
914         smb_ucs2_t *buffer = NULL;
915         char *out_buffer;
916
917         size = push_ucs2_allocate(&buffer, s);
918         if (size == -1 || !buffer) {
919                 return NULL;
920         }
921
922         strlower_w(buffer);
923
924         size = pull_ucs2_allocate(&out_buffer, buffer);
925         SAFE_FREE(buffer);
926
927         if (size == (size_t)-1) {
928                 return NULL;
929         }
930
931         return out_buffer;
932 }
933
934 size_t ucs2_align(const void *base_ptr, const void *p, int flags)
935 {
936         if (flags & (STR_NOALIGN|STR_ASCII))
937                 return 0;
938         return PTR_DIFF(p, base_ptr) & 1;
939 }
940
941
942 /**
943  * Copy a string from a char* unix src to a dos codepage string destination.
944  *
945  * @return the number of bytes occupied by the string in the destination.
946  *
947  * @param flags can include
948  * <dl>
949  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
950  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
951  * </dl>
952  *
953  * @param dest_len the maximum length in bytes allowed in the
954  * destination.
955  **/
956 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
957 {
958         size_t src_len = strlen(src);
959         char *tmpbuf = NULL;
960         size_t ret;
961
962         /* No longer allow a length of -1. */
963         if (dest_len == (size_t)-1) {
964                 smb_panic("push_ascii - dest_len == -1");
965         }
966
967         if (flags & STR_UPPER) {
968                 tmpbuf = SMB_STRDUP(src);
969                 if (!tmpbuf) {
970                         smb_panic("malloc fail");
971                 }
972                 strupper_m(tmpbuf);
973                 src = tmpbuf;
974         }
975
976         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
977                 src_len++;
978         }
979
980         ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
981         if (ret == (size_t)-1 &&
982                         (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
983                         && dest_len > 0) {
984                 ((char *)dest)[0] = '\0';
985         }
986         SAFE_FREE(tmpbuf);
987         return ret;
988 }
989
990 size_t push_ascii_fstring(void *dest, const char *src)
991 {
992         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
993 }
994
995 /********************************************************************
996  Push an nstring - ensure null terminated. Written by
997  moriyama@miraclelinux.com (MORIYAMA Masayuki).
998 ********************************************************************/
999
1000 size_t push_ascii_nstring(void *dest, const char *src)
1001 {
1002         size_t i, buffer_len, dest_len;
1003         smb_ucs2_t *buffer;
1004
1005         conv_silent = True;
1006         buffer_len = push_ucs2_allocate(&buffer, src);
1007         if (buffer_len == (size_t)-1) {
1008                 smb_panic("failed to create UCS2 buffer");
1009         }
1010
1011         /* We're using buffer_len below to count ucs2 characters, not bytes. */
1012         buffer_len /= sizeof(smb_ucs2_t);
1013
1014         dest_len = 0;
1015         for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
1016                 unsigned char mb[10];
1017                 /* Convert one smb_ucs2_t character at a time. */
1018                 size_t mb_len = convert_string(CH_UTF16LE, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
1019                 if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
1020                         memcpy((char *)dest + dest_len, mb, mb_len);
1021                         dest_len += mb_len;
1022                 } else {
1023                         errno = E2BIG;
1024                         break;
1025                 }
1026         }
1027         ((char *)dest)[dest_len] = '\0';
1028
1029         SAFE_FREE(buffer);
1030         conv_silent = False;
1031         return dest_len;
1032 }
1033
1034 /********************************************************************
1035  Push and malloc an ascii string. src and dest null terminated.
1036 ********************************************************************/
1037
1038 size_t push_ascii_allocate(char **dest, const char *src)
1039 {
1040         size_t src_len = strlen(src)+1;
1041
1042         *dest = NULL;
1043         return convert_string_allocate(NULL, CH_UNIX, CH_DOS, src, src_len, (void **)dest, True);
1044 }
1045
1046 /**
1047  * Copy a string from a dos codepage source to a unix char* destination.
1048  *
1049  * The resulting string in "dest" is always null terminated.
1050  *
1051  * @param flags can have:
1052  * <dl>
1053  * <dt>STR_TERMINATE</dt>
1054  * <dd>STR_TERMINATE means the string in @p src
1055  * is null terminated, and src_len is ignored.</dd>
1056  * </dl>
1057  *
1058  * @param src_len is the length of the source area in bytes.
1059  * @returns the number of bytes occupied by the string in @p src.
1060  **/
1061 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1062 {
1063         size_t ret;
1064
1065         if (dest_len == (size_t)-1) {
1066                 /* No longer allow dest_len of -1. */
1067                 smb_panic("pull_ascii - invalid dest_len of -1");
1068         }
1069
1070         if (flags & STR_TERMINATE) {
1071                 if (src_len == (size_t)-1) {
1072                         src_len = strlen((const char *)src) + 1;
1073                 } else {
1074                         size_t len = strnlen((const char *)src, src_len);
1075                         if (len < src_len)
1076                                 len++;
1077                         src_len = len;
1078                 }
1079         }
1080
1081         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
1082         if (ret == (size_t)-1) {
1083                 ret = 0;
1084                 dest_len = 0;
1085         }
1086
1087         if (dest_len && ret) {
1088                 /* Did we already process the terminating zero ? */
1089                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
1090                         dest[MIN(ret, dest_len-1)] = 0;
1091                 }
1092         } else  {
1093                 dest[0] = 0;
1094         }
1095
1096         return src_len;
1097 }
1098
1099 /**
1100  * Copy a string from a dos codepage source to a unix char* destination.
1101  Talloc version.
1102  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1103  needs fixing. JRA).
1104  *
1105  * The resulting string in "dest" is always null terminated.
1106  *
1107  * @param flags can have:
1108  * <dl>
1109  * <dt>STR_TERMINATE</dt>
1110  * <dd>STR_TERMINATE means the string in @p src
1111  * is null terminated, and src_len is ignored.</dd>
1112  * </dl>
1113  *
1114  * @param src_len is the length of the source area in bytes.
1115  * @returns the number of bytes occupied by the string in @p src.
1116  **/
1117
1118 static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
1119                                         char **ppdest,
1120                                         const void *src,
1121                                         size_t src_len,
1122                                         int flags)
1123 {
1124         char *dest = NULL;
1125         size_t dest_len = 0;
1126
1127 #ifdef DEVELOPER
1128         /* Ensure we never use the braindead "malloc" varient. */
1129         if (ctx == NULL) {
1130                 smb_panic("NULL talloc CTX in pull_ascii_base_talloc\n");
1131         }
1132 #endif
1133
1134         *ppdest = NULL;
1135
1136         if (flags & STR_TERMINATE) {
1137                 if (src_len == (size_t)-1) {
1138                         src_len = strlen((const char *)src) + 1;
1139                 } else {
1140                         size_t len = strnlen((const char *)src, src_len);
1141                         if (len < src_len)
1142                                 len++;
1143                         src_len = len;
1144                 }
1145                 /* Ensure we don't use an insane length from the client. */
1146                 if (src_len >= 1024*1024) {
1147                         char *msg = talloc_asprintf(ctx,
1148                                         "Bad src length (%u) in "
1149                                         "pull_ascii_base_talloc",
1150                                         (unsigned int)src_len);
1151                         smb_panic(msg);
1152                 }
1153         }
1154
1155         dest_len = convert_string_allocate(ctx,
1156                                 CH_DOS,
1157                                 CH_UNIX,
1158                                 src,
1159                                 src_len,
1160                                 &dest,
1161                                 True);
1162
1163         if (dest_len == (size_t)-1) {
1164                 dest_len = 0;
1165         }
1166
1167         if (dest_len && dest) {
1168                 /* Did we already process the terminating zero ? */
1169                 if (dest[dest_len-1] != 0) {
1170                         dest[dest_len-1] = 0;
1171                 }
1172         } else if (dest) {
1173                 dest[0] = 0;
1174         }
1175
1176         *ppdest = dest;
1177         return src_len;
1178 }
1179
1180 size_t pull_ascii_fstring(char *dest, const void *src)
1181 {
1182         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
1183 }
1184
1185 /* When pulling an nstring it can expand into a larger size (dos cp -> utf8). Cope with this. */
1186
1187 size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
1188 {
1189         return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
1190 }
1191
1192 /**
1193  * Copy a string from a char* src to a unicode destination.
1194  *
1195  * @returns the number of bytes occupied by the string in the destination.
1196  *
1197  * @param flags can have:
1198  *
1199  * <dl>
1200  * <dt>STR_TERMINATE <dd>means include the null termination.
1201  * <dt>STR_UPPER     <dd>means uppercase in the destination.
1202  * <dt>STR_NOALIGN   <dd>means don't do alignment.
1203  * </dl>
1204  *
1205  * @param dest_len is the maximum length allowed in the
1206  * destination.
1207  **/
1208
1209 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
1210 {
1211         size_t len=0;
1212         size_t src_len;
1213         size_t ret;
1214
1215         if (dest_len == (size_t)-1) {
1216                 /* No longer allow dest_len of -1. */
1217                 smb_panic("push_ucs2 - invalid dest_len of -1");
1218         }
1219
1220         if (flags & STR_TERMINATE)
1221                 src_len = (size_t)-1;
1222         else
1223                 src_len = strlen(src);
1224
1225         if (ucs2_align(base_ptr, dest, flags)) {
1226                 *(char *)dest = 0;
1227                 dest = (void *)((char *)dest + 1);
1228                 if (dest_len)
1229                         dest_len--;
1230                 len++;
1231         }
1232
1233         /* ucs2 is always a multiple of 2 bytes */
1234         dest_len &= ~1;
1235
1236         ret =  convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, True);
1237         if (ret == (size_t)-1) {
1238                 if ((flags & STR_TERMINATE) &&
1239                                 dest &&
1240                                 dest_len) {
1241                         *(char *)dest = 0;
1242                 }
1243                 return len;
1244         }
1245
1246         len += ret;
1247
1248         if (flags & STR_UPPER) {
1249                 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
1250                 size_t i;
1251
1252                 /* We check for i < (ret / 2) below as the dest string isn't null
1253                    terminated if STR_TERMINATE isn't set. */
1254
1255                 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
1256                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
1257                         if (v != dest_ucs2[i]) {
1258                                 dest_ucs2[i] = v;
1259                         }
1260                 }
1261         }
1262
1263         return len;
1264 }
1265
1266
1267 /**
1268  * Copy a string from a unix char* src to a UCS2 destination,
1269  * allocating a buffer using talloc().
1270  *
1271  * @param dest always set at least to NULL 
1272  *
1273  * @returns The number of bytes occupied by the string in the destination
1274  *         or -1 in case of error.
1275  **/
1276 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
1277 {
1278         size_t src_len = strlen(src)+1;
1279
1280         *dest = NULL;
1281         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
1282 }
1283
1284
1285 /**
1286  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
1287  *
1288  * @param dest always set at least to NULL 
1289  *
1290  * @returns The number of bytes occupied by the string in the destination
1291  *         or -1 in case of error.
1292  **/
1293
1294 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
1295 {
1296         size_t src_len = strlen(src)+1;
1297
1298         *dest = NULL;
1299         return convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, src, src_len, (void **)dest, True);
1300 }
1301
1302 /**
1303  Copy a string from a char* src to a UTF-8 destination.
1304  Return the number of bytes occupied by the string in the destination
1305  Flags can have:
1306   STR_TERMINATE means include the null termination
1307   STR_UPPER     means uppercase in the destination
1308  dest_len is the maximum length allowed in the destination. If dest_len
1309  is -1 then no maxiumum is used.
1310 **/
1311
1312 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
1313 {
1314         size_t src_len = 0;
1315         size_t ret;
1316         char *tmpbuf = NULL;
1317
1318         if (dest_len == (size_t)-1) {
1319                 /* No longer allow dest_len of -1. */
1320                 smb_panic("push_utf8 - invalid dest_len of -1");
1321         }
1322
1323         if (flags & STR_UPPER) {
1324                 tmpbuf = strdup_upper(src);
1325                 if (!tmpbuf) {
1326                         return (size_t)-1;
1327                 }
1328                 src = tmpbuf;
1329                 src_len = strlen(src);
1330         }
1331
1332         src_len = strlen(src);
1333         if (flags & STR_TERMINATE) {
1334                 src_len++;
1335         }
1336
1337         ret = convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
1338         SAFE_FREE(tmpbuf);
1339         return ret;
1340 }
1341
1342 size_t push_utf8_fstring(void *dest, const char *src)
1343 {
1344         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
1345 }
1346
1347 /**
1348  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1349  *
1350  * @param dest always set at least to NULL 
1351  *
1352  * @returns The number of bytes occupied by the string in the destination
1353  **/
1354
1355 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1356 {
1357         size_t src_len = strlen(src)+1;
1358
1359         *dest = NULL;
1360         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
1361 }
1362
1363 /**
1364  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
1365  *
1366  * @param dest always set at least to NULL 
1367  *
1368  * @returns The number of bytes occupied by the string in the destination
1369  **/
1370
1371 size_t push_utf8_allocate(char **dest, const char *src)
1372 {
1373         size_t src_len = strlen(src)+1;
1374
1375         *dest = NULL;
1376         return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);      
1377 }
1378
1379 /**
1380  Copy a string from a ucs2 source to a unix char* destination.
1381  Flags can have:
1382   STR_TERMINATE means the string in src is null terminated.
1383   STR_NOALIGN   means don't try to align.
1384  if STR_TERMINATE is set then src_len is ignored if it is -1.
1385  src_len is the length of the source area in bytes
1386  Return the number of bytes occupied by the string in src.
1387  The resulting string in "dest" is always null terminated.
1388 **/
1389
1390 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1391 {
1392         size_t ret;
1393
1394         if (dest_len == (size_t)-1) {
1395                 /* No longer allow dest_len of -1. */
1396                 smb_panic("pull_ucs2 - invalid dest_len of -1");
1397         }
1398
1399         if (!src_len) {
1400                 if (dest && dest_len > 0) {
1401                         dest[0] = '\0';
1402                 }
1403                 return 0;
1404         }
1405
1406         if (ucs2_align(base_ptr, src, flags)) {
1407                 src = (const void *)((const char *)src + 1);
1408                 if (src_len != (size_t)-1)
1409                         src_len--;
1410         }
1411
1412         if (flags & STR_TERMINATE) {
1413                 /* src_len -1 is the default for null terminated strings. */
1414                 if (src_len != (size_t)-1) {
1415                         size_t len = strnlen_w((const smb_ucs2_t *)src,
1416                                                 src_len/2);
1417                         if (len < src_len/2)
1418                                 len++;
1419                         src_len = len*2;
1420                 }
1421         }
1422
1423         /* ucs2 is always a multiple of 2 bytes */
1424         if (src_len != (size_t)-1)
1425                 src_len &= ~1;
1426
1427         ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, True);
1428         if (ret == (size_t)-1) {
1429                 ret = 0;
1430                 dest_len = 0;
1431         }
1432
1433         if (src_len == (size_t)-1)
1434                 src_len = ret*2;
1435
1436         if (dest_len && ret) {
1437                 /* Did we already process the terminating zero ? */
1438                 if (dest[MIN(ret-1, dest_len-1)] != 0) {
1439                         dest[MIN(ret, dest_len-1)] = 0;
1440                 }
1441         } else {
1442                 dest[0] = 0;
1443         }
1444
1445         return src_len;
1446 }
1447
1448 /**
1449  Copy a string from a ucs2 source to a unix char* destination.
1450  Talloc version with a base pointer.
1451  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1452  needs fixing. JRA).
1453  Flags can have:
1454   STR_TERMINATE means the string in src is null terminated.
1455   STR_NOALIGN   means don't try to align.
1456  if STR_TERMINATE is set then src_len is ignored if it is -1.
1457  src_len is the length of the source area in bytes
1458  Return the number of bytes occupied by the string in src.
1459  The resulting string in "dest" is always null terminated.
1460 **/
1461
1462 size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
1463                         const void *base_ptr,
1464                         char **ppdest,
1465                         const void *src,
1466                         size_t src_len,
1467                         int flags)
1468 {
1469         char *dest;
1470         size_t dest_len;
1471
1472         *ppdest = NULL;
1473
1474 #ifdef DEVELOPER
1475         /* Ensure we never use the braindead "malloc" varient. */
1476         if (ctx == NULL) {
1477                 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
1478         }
1479 #endif
1480
1481         if (!src_len) {
1482                 return 0;
1483         }
1484
1485         if (ucs2_align(base_ptr, src, flags)) {
1486                 src = (const void *)((const char *)src + 1);
1487                 if (src_len != (size_t)-1)
1488                         src_len--;
1489         }
1490
1491         if (flags & STR_TERMINATE) {
1492                 /* src_len -1 is the default for null terminated strings. */
1493                 if (src_len != (size_t)-1) {
1494                         size_t len = strnlen_w((const smb_ucs2_t *)src,
1495                                                 src_len/2);
1496                         if (len < src_len/2)
1497                                 len++;
1498                         src_len = len*2;
1499                 } else {
1500                         /*
1501                          * src_len == -1 - alloc interface won't take this
1502                          * so we must calculate.
1503                          */
1504                         src_len = (strlen_w((const smb_ucs2_t *)src)+1)*sizeof(smb_ucs2_t);
1505                 }
1506                 /* Ensure we don't use an insane length from the client. */
1507                 if (src_len >= 1024*1024) {
1508                         smb_panic("Bad src length in pull_ucs2_base_talloc\n");
1509                 }
1510         }
1511
1512         /* ucs2 is always a multiple of 2 bytes */
1513         if (src_len != (size_t)-1) {
1514                 src_len &= ~1;
1515         }
1516
1517         dest_len = convert_string_talloc(ctx,
1518                                         CH_UTF16LE,
1519                                         CH_UNIX,
1520                                         src,
1521                                         src_len,
1522                                         (void *)&dest,
1523                                         True);
1524         if (dest_len == (size_t)-1) {
1525                 dest_len = 0;
1526         }
1527
1528         if (src_len == (size_t)-1)
1529                 src_len = dest_len*2;
1530
1531         if (dest_len) {
1532                 /* Did we already process the terminating zero ? */
1533                 if (dest[dest_len-1] != 0) {
1534                         size_t size = talloc_get_size(dest);
1535                         /* Have we got space to append the '\0' ? */
1536                         if (size <= dest_len) {
1537                                 /* No, realloc. */
1538                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
1539                                                 dest_len+1);
1540                                 if (!dest) {
1541                                         /* talloc fail. */
1542                                         dest_len = (size_t)-1;
1543                                         return 0;
1544                                 }
1545                         }
1546                         /* Yay - space ! */
1547                         dest[dest_len] = '\0';
1548                         dest_len++;
1549                 }
1550         } else if (dest) {
1551                 dest[0] = 0;
1552         }
1553
1554         *ppdest = dest;
1555         return src_len;
1556 }
1557
1558 size_t pull_ucs2_fstring(char *dest, const void *src)
1559 {
1560         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
1561 }
1562
1563 /**
1564  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1565  *
1566  * @param dest always set at least to NULL 
1567  *
1568  * @returns The number of bytes occupied by the string in the destination
1569  **/
1570
1571 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
1572 {
1573         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1574         *dest = NULL;
1575         return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
1576 }
1577
1578 /**
1579  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
1580  *
1581  * @param dest always set at least to NULL 
1582  *
1583  * @returns The number of bytes occupied by the string in the destination
1584  **/
1585
1586 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
1587 {
1588         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1589         *dest = NULL;
1590         return convert_string_allocate(NULL, CH_UTF16LE, CH_UNIX, src, src_len, (void **)dest, True);
1591 }
1592
1593 /**
1594  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1595  *
1596  * @param dest always set at least to NULL 
1597  *
1598  * @returns The number of bytes occupied by the string in the destination
1599  **/
1600
1601 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1602 {
1603         size_t src_len = strlen(src)+1;
1604         *dest = NULL;
1605         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1606 }
1607
1608 /**
1609  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
1610  *
1611  * @param dest always set at least to NULL 
1612  *
1613  * @returns The number of bytes occupied by the string in the destination
1614  **/
1615
1616 size_t pull_utf8_allocate(char **dest, const char *src)
1617 {
1618         size_t src_len = strlen(src)+1;
1619         *dest = NULL;
1620         return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1621 }
1622  
1623 /**
1624  * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1625  *
1626  * @param dest always set at least to NULL 
1627  *
1628  * @returns The number of bytes occupied by the string in the destination
1629  **/
1630
1631 size_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1632 {
1633         size_t src_len = strlen(src)+1;
1634         *dest = NULL;
1635         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True);
1636 }
1637
1638 /**
1639  Copy a string from a char* src to a unicode or ascii
1640  dos codepage destination choosing unicode or ascii based on the 
1641  flags in the SMB buffer starting at base_ptr.
1642  Return the number of bytes occupied by the string in the destination.
1643  flags can have:
1644   STR_TERMINATE means include the null termination.
1645   STR_UPPER     means uppercase in the destination.
1646   STR_ASCII     use ascii even with unicode packet.
1647   STR_NOALIGN   means don't do alignment.
1648  dest_len is the maximum length allowed in the destination. If dest_len
1649  is -1 then no maxiumum is used.
1650 **/
1651
1652 size_t push_string_fn(const char *function, unsigned int line,
1653                       const void *base_ptr, uint16 flags2,
1654                       void *dest, const char *src,
1655                       size_t dest_len, int flags)
1656 {
1657 #ifdef DEVELOPER
1658         /* We really need to zero fill here, not clobber
1659          * region, as we want to ensure that valgrind thinks
1660          * all of the outgoing buffer has been written to
1661          * so a send() or write() won't trap an error.
1662          * JRA.
1663          */
1664 #if 0
1665         clobber_region(function, line, dest, dest_len);
1666 #else
1667         memset(dest, '\0', dest_len);
1668 #endif
1669 #endif
1670
1671         if (!(flags & STR_ASCII) && \
1672             ((flags & STR_UNICODE || \
1673               (flags2 & FLAGS2_UNICODE_STRINGS)))) {
1674                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
1675         }
1676         return push_ascii(dest, src, dest_len, flags);
1677 }
1678
1679
1680 /**
1681  Copy a string from a unicode or ascii source (depending on
1682  the packet flags) to a char* destination.
1683  Flags can have:
1684   STR_TERMINATE means the string in src is null terminated.
1685   STR_UNICODE   means to force as unicode.
1686   STR_ASCII     use ascii even with unicode packet.
1687   STR_NOALIGN   means don't do alignment.
1688  if STR_TERMINATE is set then src_len is ignored is it is -1
1689  src_len is the length of the source area in bytes.
1690  Return the number of bytes occupied by the string in src.
1691  The resulting string in "dest" is always null terminated.
1692 **/
1693
1694 size_t pull_string_fn(const char *function,
1695                         unsigned int line,
1696                         const void *base_ptr,
1697                         uint16 smb_flags2,
1698                         char *dest,
1699                         const void *src,
1700                         size_t dest_len,
1701                         size_t src_len,
1702                         int flags)
1703 {
1704 #ifdef DEVELOPER
1705         clobber_region(function, line, dest, dest_len);
1706 #endif
1707
1708         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1709                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1710                           "UNICODE defined");
1711         }
1712
1713         if (!(flags & STR_ASCII) && \
1714             ((flags & STR_UNICODE || \
1715               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1716                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1717         }
1718         return pull_ascii(dest, src, dest_len, src_len, flags);
1719 }
1720
1721 /**
1722  Copy a string from a unicode or ascii source (depending on
1723  the packet flags) to a char* destination.
1724  Variant that uses talloc.
1725  Flags can have:
1726   STR_TERMINATE means the string in src is null terminated.
1727   STR_UNICODE   means to force as unicode.
1728   STR_ASCII     use ascii even with unicode packet.
1729   STR_NOALIGN   means don't do alignment.
1730  if STR_TERMINATE is set then src_len is ignored is it is -1
1731  src_len is the length of the source area in bytes.
1732  Return the number of bytes occupied by the string in src.
1733  The resulting string in "dest" is always null terminated.
1734 **/
1735
1736 size_t pull_string_talloc_fn(const char *function,
1737                         unsigned int line,
1738                         TALLOC_CTX *ctx,
1739                         const void *base_ptr,
1740                         uint16 smb_flags2,
1741                         char **ppdest,
1742                         const void *src,
1743                         size_t src_len,
1744                         int flags)
1745 {
1746         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
1747                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1748                           "UNICODE defined");
1749         }
1750
1751         if (!(flags & STR_ASCII) && \
1752             ((flags & STR_UNICODE || \
1753               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
1754                 return pull_ucs2_base_talloc(ctx,
1755                                         base_ptr,
1756                                         ppdest,
1757                                         src,
1758                                         src_len,
1759                                         flags);
1760         }
1761         return pull_ascii_base_talloc(ctx,
1762                                         ppdest,
1763                                         src,
1764                                         src_len,
1765                                         flags);
1766 }
1767
1768
1769 size_t align_string(const void *base_ptr, const char *p, int flags)
1770 {
1771         if (!(flags & STR_ASCII) && \
1772             ((flags & STR_UNICODE || \
1773               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1774                 return ucs2_align(base_ptr, p, flags);
1775         }
1776         return 0;
1777 }
1778
1779 /*
1780   Return the unicode codepoint for the next multi-byte CH_UNIX character
1781   in the string. The unicode codepoint (codepoint_t) is an unsinged 32 bit value.
1782
1783   Also return the number of bytes consumed (which tells the caller
1784   how many bytes to skip to get to the next CH_UNIX character).
1785
1786   Return INVALID_CODEPOINT if the next character cannot be converted.
1787 */
1788
1789 codepoint_t next_codepoint(const char *str, size_t *size)
1790 {
1791         /* It cannot occupy more than 4 bytes in UTF16 format */
1792         uint8_t buf[4];
1793         smb_iconv_t descriptor;
1794         size_t ilen_orig;
1795         size_t ilen;
1796         size_t olen;
1797         char *outbuf;
1798
1799         if ((str[0] & 0x80) == 0) {
1800                 *size = 1;
1801                 return (codepoint_t)str[0];
1802         }
1803
1804         /* We assume that no multi-byte character can take
1805            more than 5 bytes. This is OK as we only
1806            support codepoints up to 1M */
1807
1808         ilen_orig = strnlen(str, 5);
1809         ilen = ilen_orig;
1810
1811         lazy_initialize_conv();
1812
1813         descriptor = conv_handles[CH_UNIX][CH_UTF16LE];
1814         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
1815                 *size = 1;
1816                 return INVALID_CODEPOINT;
1817         }
1818
1819         /* This looks a little strange, but it is needed to cope
1820            with codepoints above 64k which are encoded as per RFC2781. */
1821         olen = 2;
1822         outbuf = (char *)buf;
1823         smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);
1824         if (olen == 2) {
1825                 /* We failed to convert to a 2 byte character.
1826                    See if we can convert to a 4 UTF16-LE byte char encoding.
1827                 */
1828                 olen = 4;
1829                 outbuf = (char *)buf;
1830                 smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
1831                 if (olen == 4) {
1832                         /* We didn't convert any bytes */
1833                         *size = 1;
1834                         return INVALID_CODEPOINT;
1835                 }
1836                 olen = 4 - olen;
1837         } else {
1838                 olen = 2 - olen;
1839         }
1840
1841         *size = ilen_orig - ilen;
1842
1843         if (olen == 2) {
1844                 /* 2 byte, UTF16-LE encoded value. */
1845                 return (codepoint_t)SVAL(buf, 0);
1846         }
1847         if (olen == 4) {
1848                 /* Decode a 4 byte UTF16-LE character manually.
1849                    See RFC2871 for the encoding machanism.
1850                 */
1851                 codepoint_t w1 = SVAL(buf,0) & ~0xD800;
1852                 codepoint_t w2 = SVAL(buf,2) & ~0xDC00;
1853
1854                 return (codepoint_t)0x10000 +
1855                                 (w1 << 10) + w2;
1856         }
1857
1858         /* no other length is valid */
1859         return INVALID_CODEPOINT;
1860 }