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