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