r3940: typo.
[tprouty/samba.git] / source / lib / charcnv.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Character set conversion Extensions
4    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5    Copyright (C) Andrew Tridgell 2001
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Martin Pool 2003
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 */
24 #include "includes.h"
25
26 /* We can parameterize this if someone complains.... JRA. */
27
28 char lp_failed_convert_char(void)
29 {
30         return '_';
31 }
32
33 /**
34  * @file
35  *
36  * @brief Character-set conversion routines built on our iconv.
37  * 
38  * @note Samba's internal character set (at least in the 3.0 series)
39  * is always the same as the one for the Unix filesystem.  It is
40  * <b>not</b> necessarily UTF-8 and may be different on machines that
41  * need i18n filenames to be compatible with Unix software.  It does
42  * have to be a superset of ASCII.  All multibyte sequences must start
43  * with a byte with the high bit set.
44  *
45  * @sa lib/iconv.c
46  */
47
48
49 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
50 static BOOL conv_silent; /* Should we do a debug if the conversion fails ? */
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_UCS2) ret = "UTF-16LE";
60         else if (ch == CH_UNIX) ret = lp_unix_charset();
61         else if (ch == CH_DOS) ret = lp_dos_charset();
62         else if (ch == CH_DISPLAY) ret = lp_display_charset();
63         else if (ch == CH_UTF8) ret = "UTF8";
64
65 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
66         if (ret && !strcmp(ret, "LOCALE")) {
67                 const char *ln = NULL;
68
69 #ifdef HAVE_SETLOCALE
70                 setlocale(LC_ALL, "");
71 #endif
72                 ln = nl_langinfo(CODESET);
73                 if (ln) {
74                         /* Check whether the charset name is supported
75                            by iconv */
76                         smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE");
77                         if (handle == (smb_iconv_t) -1) {
78                                 DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln));
79                                 ln = NULL;
80                         } else {
81                                 DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln));
82                                 smb_iconv_close(handle);
83                         }
84                 }
85                 ret = ln;
86         }
87 #endif
88
89         if (!ret || !*ret) ret = "ASCII";
90         return ret;
91 }
92
93 void lazy_initialize_conv(void)
94 {
95         static int initialized = False;
96
97         if (!initialized) {
98                 initialized = True;
99                 load_case_tables();
100                 init_iconv();
101         }
102 }
103
104 /**
105  * Initialize iconv conversion descriptors.
106  *
107  * This is called the first time it is needed, and also called again
108  * every time the configuration is reloaded, because the charset or
109  * codepage might have changed.
110  **/
111 void init_iconv(void)
112 {
113         int c1, c2;
114         BOOL did_reload = False;
115
116         /* so that charset_name() works we need to get the UNIX<->UCS2 going
117            first */
118         if (!conv_handles[CH_UNIX][CH_UCS2])
119                 conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII");
120
121         if (!conv_handles[CH_UCS2][CH_UNIX])
122                 conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2));
123
124         for (c1=0;c1<NUM_CHARSETS;c1++) {
125                 for (c2=0;c2<NUM_CHARSETS;c2++) {
126                         const char *n1 = charset_name((charset_t)c1);
127                         const char *n2 = charset_name((charset_t)c2);
128                         if (conv_handles[c1][c2] &&
129                             strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
130                             strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
131                                 continue;
132
133                         did_reload = True;
134
135                         if (conv_handles[c1][c2])
136                                 smb_iconv_close(conv_handles[c1][c2]);
137
138                         conv_handles[c1][c2] = smb_iconv_open(n2,n1);
139                         if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
140                                 DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
141                                          charset_name((charset_t)c1), charset_name((charset_t)c2)));
142                                 if (c1 != CH_UCS2) {
143                                         n1 = "ASCII";
144                                 }
145                                 if (c2 != CH_UCS2) {
146                                         n2 = "ASCII";
147                                 }
148                                 DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
149                                         n1, n2 ));
150                                 conv_handles[c1][c2] = smb_iconv_open(n2,n1);
151                                 if (!conv_handles[c1][c2]) {
152                                         DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2));
153                                         smb_panic("init_iconv: conv_handle initialization failed.");
154                                 }
155                         }
156                 }
157         }
158
159         if (did_reload) {
160                 /* XXX: Does this really get called every time the dos
161                  * codepage changes? */
162                 /* XXX: Is the did_reload test too strict? */
163                 conv_silent = True;
164                 init_doschar_table();
165                 init_valid_table();
166                 conv_silent = False;
167         }
168 }
169
170 /**
171  * Convert string from one encoding to another, making error checking etc
172  * Slow path version - uses (slow) iconv.
173  *
174  * @param src pointer to source string (multibyte or singlebyte)
175  * @param srclen length of the source string in bytes
176  * @param dest pointer to destination string (multibyte or singlebyte)
177  * @param destlen maximal length allowed for string
178  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
179  * @returns the number of bytes occupied in the destination
180  *
181  * Ensure the srclen contains the terminating zero.
182  *
183  **/
184
185 static size_t convert_string_internal(charset_t from, charset_t to,
186                       void const *src, size_t srclen, 
187                       void *dest, size_t destlen, BOOL allow_bad_conv)
188 {
189         size_t i_len, o_len;
190         size_t retval;
191         const char* inbuf = (const char*)src;
192         char* outbuf = (char*)dest;
193         smb_iconv_t descriptor;
194
195         lazy_initialize_conv();
196
197         descriptor = conv_handles[from][to];
198
199         if (srclen == (size_t)-1) {
200                 if (from == CH_UCS2) {
201                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
202                 } else {
203                         srclen = strlen((const char *)src)+1;
204                 }
205         }
206
207
208         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
209                 if (!conv_silent)
210                         DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
211                 return (size_t)-1;
212         }
213
214         i_len=srclen;
215         o_len=destlen;
216
217  again:
218
219         retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
220         if(retval==(size_t)-1) {
221                 const char *reason="unknown error";
222                 switch(errno) {
223                         case EINVAL:
224                                 reason="Incomplete multibyte sequence";
225                                 if (!conv_silent)
226                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
227                                 if (allow_bad_conv)
228                                         goto use_as_is;
229                                 break;
230                         case E2BIG:
231                                 reason="No more room"; 
232                                 if (!conv_silent) {
233                                         if (from == CH_UNIX) {
234                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
235                                                         charset_name(from), charset_name(to),
236                                                         (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
237                                         } else {
238                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
239                                                         charset_name(from), charset_name(to),
240                                                         (unsigned int)srclen, (unsigned int)destlen));
241                                         }
242                                 }
243                                 break;
244                         case EILSEQ:
245                                 reason="Illegal multibyte sequence";
246                                 if (!conv_silent)
247                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
248                                 if (allow_bad_conv)
249                                         goto use_as_is;
250                                 break;
251                         default:
252                                 if (!conv_silent)
253                                         DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
254                                 break;
255                 }
256                 /* smb_panic(reason); */
257         }
258         return destlen-o_len;
259
260  use_as_is:
261
262         /* 
263          * Conversion not supported. This is actually an error, but there are so
264          * many misconfigured iconv systems and smb.conf's out there we can't just
265          * fail. Do a very bad conversion instead.... JRA.
266          */
267
268         {
269                 if (o_len == 0 || i_len == 0)
270                         return destlen - o_len;
271
272                 if (from == CH_UCS2 && to != CH_UCS2) {
273                         /* Can't convert from ucs2 to multibyte. Replace with the default fail char. */
274                         if (i_len < 2)
275                                 return destlen - o_len;
276                         if (i_len >= 2) {
277                                 *outbuf = lp_failed_convert_char();
278
279                                 outbuf++;
280                                 o_len--;
281
282                                 inbuf += 2;
283                                 i_len -= 2;
284                         }
285
286                         if (o_len == 0 || i_len == 0)
287                                 return destlen - o_len;
288
289                         /* Keep trying with the next char... */
290                         goto again;
291
292                 } else if (from != CH_UCS2 && to == CH_UCS2) {
293                         /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */
294                         if (o_len < 2)
295                                 return destlen - o_len;
296
297                         outbuf[0] = lp_failed_convert_char();
298                         outbuf[1] = '\0';
299
300                         inbuf++;
301                         i_len--;
302
303                         outbuf += 2;
304                         o_len -= 2;
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_UCS2 && to != CH_UCS2) {
313                         /* Failed multibyte to multibyte. Just copy the default fail char and
314                                 try again. */
315                         outbuf[0] = lp_failed_convert_char();
316
317                         inbuf++;
318                         i_len--;
319
320                         outbuf++;
321                         o_len--;
322
323                         if (o_len == 0 || i_len == 0)
324                                 return destlen - o_len;
325
326                         /* Keep trying with the next char... */
327                         goto again;
328
329                 } else {
330                         /* Keep compiler happy.... */
331                         return destlen - o_len;
332                 }
333         }
334 }
335
336 /**
337  * Convert string from one encoding to another, making error checking etc
338  * Fast path version - handles ASCII first.
339  *
340  * @param src pointer to source string (multibyte or singlebyte)
341  * @param srclen length of the source string in bytes, or -1 for nul terminated.
342  * @param dest pointer to destination string (multibyte or singlebyte)
343  * @param destlen maximal length allowed for string - *NEVER* -1.
344  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
345  * @returns the number of bytes occupied in the destination
346  *
347  * Ensure the srclen contains the terminating zero.
348  *
349  * This function has been hand-tuned to provide a fast path.
350  * Don't change unless you really know what you are doing. JRA.
351  **/
352
353 size_t convert_string(charset_t from, charset_t to,
354                       void const *src, size_t srclen, 
355                       void *dest, size_t destlen, BOOL allow_bad_conv)
356 {
357         /*
358          * NB. We deliberately don't do a strlen here if srclen == -1.
359          * This is very expensive over millions of calls and is taken
360          * care of in the slow path in convert_string_internal. JRA.
361          */
362
363 #ifdef DEVELOPER
364         SMB_ASSERT(destlen != (size_t)-1);
365 #endif
366
367         if (srclen == 0)
368                 return 0;
369
370         if (from != CH_UCS2 && to != CH_UCS2) {
371                 const unsigned char *p = (const unsigned char *)src;
372                 unsigned char *q = (unsigned char *)dest;
373                 size_t slen = srclen;
374                 size_t dlen = destlen;
375                 unsigned char lastp = '\0';
376                 size_t retval = 0;
377
378                 /* If all characters are ascii, fast path here. */
379                 while (slen && dlen) {
380                         if ((lastp = *p) <= 0x7f) {
381                                 *q++ = *p++;
382                                 if (slen != (size_t)-1) {
383                                         slen--;
384                                 }
385                                 dlen--;
386                                 retval++;
387                                 if (!lastp)
388                                         break;
389                         } else {
390 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
391                                 goto general_case;
392 #else
393                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
394 #endif
395                         }
396                 }
397                 if (!dlen) {
398                         /* Even if we fast path we should note if we ran out of room. */
399                         if (((slen != (size_t)-1) && slen) ||
400                                         ((slen == (size_t)-1) && lastp)) {
401                                 errno = E2BIG;
402                         }
403                 }
404                 return retval;
405         } else if (from == CH_UCS2 && to != CH_UCS2) {
406                 const unsigned char *p = (const unsigned char *)src;
407                 unsigned char *q = (unsigned char *)dest;
408                 size_t retval = 0;
409                 size_t slen = srclen;
410                 size_t dlen = destlen;
411                 unsigned char lastp = '\0';
412
413                 /* If all characters are ascii, fast path here. */
414                 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
415                         if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
416                                 *q++ = *p;
417                                 if (slen != (size_t)-1) {
418                                         slen -= 2;
419                                 }
420                                 p += 2;
421                                 dlen--;
422                                 retval++;
423                                 if (!lastp)
424                                         break;
425                         } else {
426 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
427                                 goto general_case;
428 #else
429                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
430 #endif
431                         }
432                 }
433                 if (!dlen) {
434                         /* Even if we fast path we should note if we ran out of room. */
435                         if (((slen != (size_t)-1) && slen) ||
436                                         ((slen == (size_t)-1) && lastp)) {
437                                 errno = E2BIG;
438                         }
439                 }
440                 return retval;
441         } else if (from != CH_UCS2 && to == CH_UCS2) {
442                 const unsigned char *p = (const unsigned char *)src;
443                 unsigned char *q = (unsigned char *)dest;
444                 size_t retval = 0;
445                 size_t slen = srclen;
446                 size_t dlen = destlen;
447                 unsigned char lastp = '\0';
448
449                 /* If all characters are ascii, fast path here. */
450                 while (slen && (dlen >= 2)) {
451                         if ((lastp = *p) <= 0x7F) {
452                                 *q++ = *p++;
453                                 *q++ = '\0';
454                                 if (slen != (size_t)-1) {
455                                         slen--;
456                                 }
457                                 dlen -= 2;
458                                 retval += 2;
459                                 if (!lastp)
460                                         break;
461                         } else {
462 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
463                                 goto general_case;
464 #else
465                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
466 #endif
467                         }
468                 }
469                 if (!dlen) {
470                         /* Even if we fast path we should note if we ran out of room. */
471                         if (((slen != (size_t)-1) && slen) ||
472                                         ((slen == (size_t)-1) && lastp)) {
473                                 errno = E2BIG;
474                         }
475                 }
476                 return retval;
477         }
478
479 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
480   general_case:
481 #endif
482         return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
483 }
484
485 /**
486  * Convert between character sets, allocating a new buffer for the result.
487  *
488  * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
489  * @param srclen length of source buffer.
490  * @param dest always set at least to NULL
491  * @note -1 is not accepted for srclen.
492  *
493  * @returns Size in bytes of the converted string; or -1 in case of error.
494  *
495  * Ensure the srclen contains the terminating zero.
496  * 
497  * I hate the goto's in this function. It's embarressing.....
498  * There has to be a cleaner way to do this. JRA.
499  **/
500
501 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
502                                void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
503 {
504         size_t i_len, o_len, destlen = MAX(srclen, 512);
505         size_t retval;
506         const char *inbuf = (const char *)src;
507         char *outbuf = NULL, *ob = NULL;
508         smb_iconv_t descriptor;
509
510         *dest = NULL;
511
512         if (src == NULL || srclen == (size_t)-1)
513                 return (size_t)-1;
514         if (srclen == 0)
515                 return 0;
516
517         lazy_initialize_conv();
518
519         descriptor = conv_handles[from][to];
520
521         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
522                 if (!conv_silent)
523                         DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
524                 return (size_t)-1;
525         }
526
527   convert:
528
529         if ((destlen*2) < destlen) {
530                 /* wrapped ! abort. */
531                 if (!conv_silent)
532                         DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
533                 if (!ctx)
534                         SAFE_FREE(outbuf);
535                 return (size_t)-1;
536         } else {
537                 destlen = destlen * 2;
538         }
539
540         if (ctx)
541                 ob = (char *)talloc_realloc(ctx, ob, destlen);
542         else
543                 ob = (char *)Realloc(ob, destlen);
544
545         if (!ob) {
546                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
547                 if (!ctx)
548                         SAFE_FREE(outbuf);
549                 return (size_t)-1;
550         } else {
551                 outbuf = ob;
552         }
553         i_len = srclen;
554         o_len = destlen;
555
556  again:
557
558         retval = smb_iconv(descriptor,
559                            &inbuf, &i_len,
560                            &outbuf, &o_len);
561         if(retval == (size_t)-1)                {
562                 const char *reason="unknown error";
563                 switch(errno) {
564                         case EINVAL:
565                                 reason="Incomplete multibyte sequence";
566                                 if (!conv_silent)
567                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
568                                 if (allow_bad_conv)
569                                         goto use_as_is;
570                                 break;
571                         case E2BIG:
572                                 goto convert;           
573                         case EILSEQ:
574                                 reason="Illegal multibyte sequence";
575                                 if (!conv_silent)
576                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
577                                 if (allow_bad_conv)
578                                         goto use_as_is;
579                                 break;
580                 }
581                 if (!conv_silent)
582                         DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
583                 /* smb_panic(reason); */
584                 return (size_t)-1;
585         }
586
587   out:
588
589         destlen = destlen - o_len;
590         if (ctx)
591                 *dest = (char *)talloc_realloc(ctx,ob,destlen);
592         else
593                 *dest = (char *)Realloc(ob,destlen);
594         if (destlen && !*dest) {
595                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
596                 if (!ctx)
597                         SAFE_FREE(ob);
598                 return (size_t)-1;
599         }
600
601         return destlen;
602
603  use_as_is:
604
605         /* 
606          * Conversion not supported. This is actually an error, but there are so
607          * many misconfigured iconv systems and smb.conf's out there we can't just
608          * fail. Do a very bad conversion instead.... JRA.
609          */
610
611         {
612                 if (o_len == 0 || i_len == 0)
613                         goto out;
614
615                 if (from == CH_UCS2 && to != CH_UCS2) {
616                         /* Can't convert from ucs2 to multibyte. Just use the default fail char. */
617                         if (i_len < 2)
618                                 goto out;
619
620                         if (i_len >= 2) {
621                                 *outbuf = lp_failed_convert_char();
622
623                                 outbuf++;
624                                 o_len--;
625
626                                 inbuf += 2;
627                                 i_len -= 2;
628                         }
629
630                         if (o_len == 0 || i_len == 0)
631                                 goto out;
632
633                         /* Keep trying with the next char... */
634                         goto again;
635
636                 } else if (from != CH_UCS2 && to == CH_UCS2) {
637                         /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */
638                         if (o_len < 2)
639                                 goto out;
640
641                         outbuf[0] = lp_failed_convert_char();
642                         outbuf[1] = '\0';
643
644                         inbuf++;
645                         i_len--;
646
647                         outbuf += 2;
648                         o_len -= 2;
649
650                         if (o_len == 0 || i_len == 0)
651                                 goto out;
652
653                         /* Keep trying with the next char... */
654                         goto again;
655
656                 } else if (from != CH_UCS2 && to != CH_UCS2) {
657                         /* Failed multibyte to multibyte. Just copy the default fail char and
658                                 try again. */
659                         outbuf[0] = lp_failed_convert_char();
660
661                         inbuf++;
662                         i_len--;
663
664                         outbuf++;
665                         o_len--;
666
667                         if (o_len == 0 || i_len == 0)
668                                 goto out;
669
670                         /* Keep trying with the next char... */
671                         goto again;
672
673                 } else {
674                         /* Keep compiler happy.... */
675                         goto out;
676                 }
677         }
678 }
679
680 /**
681  * Convert between character sets, allocating a new buffer using talloc for the result.
682  *
683  * @param srclen length of source buffer.
684  * @param dest always set at least to NULL 
685  * @note -1 is not accepted for srclen.
686  *
687  * @returns Size in bytes of the converted string; or -1 in case of error.
688  **/
689 static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
690                                 void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
691 {
692         size_t dest_len;
693
694         *dest = NULL;
695         dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv);
696         if (dest_len == (size_t)-1)
697                 return (size_t)-1;
698         if (*dest == NULL)
699                 return (size_t)-1;
700         return dest_len;
701 }
702
703 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
704 {
705         size_t size;
706         smb_ucs2_t *buffer;
707         
708         size = push_ucs2_allocate(&buffer, src);
709         if (size == (size_t)-1) {
710                 smb_panic("failed to create UCS2 buffer");
711         }
712         if (!strupper_w(buffer) && (dest == src)) {
713                 free(buffer);
714                 return srclen;
715         }
716         
717         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True);
718         free(buffer);
719         return size;
720 }
721
722 /**
723  strdup() a unix string to upper case.
724  Max size is pstring.
725 **/
726
727 char *strdup_upper(const char *s)
728 {
729         pstring out_buffer;
730         const unsigned char *p = (const unsigned char *)s;
731         unsigned char *q = (unsigned char *)out_buffer;
732
733         /* this is quite a common operation, so we want it to be
734            fast. We optimise for the ascii case, knowing that all our
735            supported multi-byte character sets are ascii-compatible
736            (ie. they match for the first 128 chars) */
737
738         while (1) {
739                 if (*p & 0x80)
740                         break;
741                 *q++ = toupper(*p);
742                 if (!*p)
743                         break;
744                 p++;
745                 if (p - ( const unsigned char *)s >= sizeof(pstring))
746                         break;
747         }
748
749         if (*p) {
750                 /* MB case. */
751                 size_t size;
752                 wpstring buffer;
753                 size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer), True);
754                 if (size == (size_t)-1) {
755                         return NULL;
756                 }
757
758                 strupper_w(buffer);
759         
760                 size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
761                 if (size == (size_t)-1) {
762                         return NULL;
763                 }
764         }
765
766         return strdup(out_buffer);
767 }
768
769 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
770 {
771         size_t size;
772         smb_ucs2_t *buffer = NULL;
773         
774         size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
775                                        (void **) &buffer, True);
776         if (size == (size_t)-1 || !buffer) {
777                 smb_panic("failed to create UCS2 buffer");
778         }
779         if (!strlower_w(buffer) && (dest == src)) {
780                 SAFE_FREE(buffer);
781                 return srclen;
782         }
783         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True);
784         SAFE_FREE(buffer);
785         return size;
786 }
787
788 /**
789  strdup() a unix string to lower case.
790 **/
791
792 char *strdup_lower(const char *s)
793 {
794         size_t size;
795         smb_ucs2_t *buffer = NULL;
796         char *out_buffer;
797         
798         size = push_ucs2_allocate(&buffer, s);
799         if (size == -1 || !buffer) {
800                 return NULL;
801         }
802
803         strlower_w(buffer);
804         
805         size = pull_ucs2_allocate(&out_buffer, buffer);
806         SAFE_FREE(buffer);
807
808         if (size == (size_t)-1) {
809                 return NULL;
810         }
811         
812         return out_buffer;
813 }
814
815 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
816 {
817         if (flags & (STR_NOALIGN|STR_ASCII))
818                 return 0;
819         return PTR_DIFF(p, base_ptr) & 1;
820 }
821
822
823 /**
824  * Copy a string from a char* unix src to a dos codepage string destination.
825  *
826  * @return the number of bytes occupied by the string in the destination.
827  *
828  * @param flags can include
829  * <dl>
830  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
831  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
832  * </dl>
833  *
834  * @param dest_len the maximum length in bytes allowed in the
835  * destination.  If @p dest_len is -1 then no maximum is used.
836  **/
837 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
838 {
839         size_t src_len = strlen(src);
840         pstring tmpbuf;
841
842         /* treat a pstring as "unlimited" length */
843         if (dest_len == (size_t)-1)
844                 dest_len = sizeof(pstring);
845
846         if (flags & STR_UPPER) {
847                 pstrcpy(tmpbuf, src);
848                 strupper_m(tmpbuf);
849                 src = tmpbuf;
850         }
851
852         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
853                 src_len++;
854
855         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
856 }
857
858 size_t push_ascii_fstring(void *dest, const char *src)
859 {
860         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
861 }
862
863 size_t push_ascii_pstring(void *dest, const char *src)
864 {
865         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
866 }
867
868 /********************************************************************
869  Push an nstring - ensure null terminated. Written by
870  moriyama@miraclelinux.com (MORIYAMA Masayuki).
871 ********************************************************************/
872
873 size_t push_ascii_nstring(void *dest, const char *src)
874 {
875         size_t i, buffer_len, dest_len;
876         smb_ucs2_t *buffer;
877
878         conv_silent = True;
879         buffer_len = push_ucs2_allocate(&buffer, src);
880         if (buffer_len == (size_t)-1) {
881                 smb_panic("failed to create UCS2 buffer");
882         }
883
884         /* We're using buffer_len below to count ucs2 characters, not bytes. */
885         buffer_len /= sizeof(smb_ucs2_t);
886
887         dest_len = 0;
888         for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
889                 unsigned char mb[10];
890                 /* Convert one smb_ucs2_t character at a time. */
891                 size_t mb_len = convert_string(CH_UCS2, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
892                 if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
893                         memcpy((char *)dest + dest_len, mb, mb_len);
894                         dest_len += mb_len;
895                 } else {
896                         errno = E2BIG;
897                         break;
898                 }
899         }
900         ((char *)dest)[dest_len] = '\0';
901
902         SAFE_FREE(buffer);
903         conv_silent = False;
904         return dest_len;
905 }
906
907 /**
908  * Copy a string from a dos codepage source to a unix char* destination.
909  *
910  * The resulting string in "dest" is always null terminated.
911  *
912  * @param flags can have:
913  * <dl>
914  * <dt>STR_TERMINATE</dt>
915  * <dd>STR_TERMINATE means the string in @p src
916  * is null terminated, and src_len is ignored.</dd>
917  * </dl>
918  *
919  * @param src_len is the length of the source area in bytes.
920  * @returns the number of bytes occupied by the string in @p src.
921  **/
922 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
923 {
924         size_t ret;
925
926         if (dest_len == (size_t)-1)
927                 dest_len = sizeof(pstring);
928
929         if (flags & STR_TERMINATE) {
930                 if (src_len == (size_t)-1) {
931                         src_len = strlen(src) + 1;
932                 } else {
933                         size_t len = strnlen(src, src_len);
934                         if (len < src_len)
935                                 len++;
936                         src_len = len;
937                 }
938         }
939
940         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
941         if (ret == (size_t)-1) {
942                 dest_len = 0;
943         }
944
945         if (dest_len)
946                 dest[MIN(ret, dest_len-1)] = 0;
947         else 
948                 dest[0] = 0;
949
950         return src_len;
951 }
952
953 size_t pull_ascii_pstring(char *dest, const void *src)
954 {
955         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
956 }
957
958 size_t pull_ascii_fstring(char *dest, const void *src)
959 {
960         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
961 }
962
963 /* When pulling an nstring it can expand into a larger size (dos cp -> utf8). Cope with this. */
964
965 size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
966 {
967         return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
968 }
969
970 /**
971  * Copy a string from a char* src to a unicode destination.
972  *
973  * @returns the number of bytes occupied by the string in the destination.
974  *
975  * @param flags can have:
976  *
977  * <dl>
978  * <dt>STR_TERMINATE <dd>means include the null termination.
979  * <dt>STR_UPPER     <dd>means uppercase in the destination.
980  * <dt>STR_NOALIGN   <dd>means don't do alignment.
981  * </dl>
982  *
983  * @param dest_len is the maximum length allowed in the
984  * destination. If dest_len is -1 then no maxiumum is used.
985  **/
986
987 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
988 {
989         size_t len=0;
990         size_t src_len;
991         size_t ret;
992
993         /* treat a pstring as "unlimited" length */
994         if (dest_len == (size_t)-1)
995                 dest_len = sizeof(pstring);
996
997         if (flags & STR_TERMINATE)
998                 src_len = (size_t)-1;
999         else
1000                 src_len = strlen(src);
1001
1002         if (ucs2_align(base_ptr, dest, flags)) {
1003                 *(char *)dest = 0;
1004                 dest = (void *)((char *)dest + 1);
1005                 if (dest_len)
1006                         dest_len--;
1007                 len++;
1008         }
1009
1010         /* ucs2 is always a multiple of 2 bytes */
1011         dest_len &= ~1;
1012
1013         ret =  convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len, True);
1014         if (ret == (size_t)-1) {
1015                 return 0;
1016         }
1017
1018         len += ret;
1019
1020         if (flags & STR_UPPER) {
1021                 smb_ucs2_t *dest_ucs2 = dest;
1022                 size_t i;
1023                 for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
1024                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
1025                         if (v != dest_ucs2[i]) {
1026                                 dest_ucs2[i] = v;
1027                         }
1028                 }
1029         }
1030
1031         return len;
1032 }
1033
1034
1035 /**
1036  * Copy a string from a unix char* src to a UCS2 destination,
1037  * allocating a buffer using talloc().
1038  *
1039  * @param dest always set at least to NULL 
1040  *
1041  * @returns The number of bytes occupied by the string in the destination
1042  *         or -1 in case of error.
1043  **/
1044 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
1045 {
1046         size_t src_len = strlen(src)+1;
1047
1048         *dest = NULL;
1049         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
1050 }
1051
1052
1053 /**
1054  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
1055  *
1056  * @param dest always set at least to NULL 
1057  *
1058  * @returns The number of bytes occupied by the string in the destination
1059  *         or -1 in case of error.
1060  **/
1061
1062 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
1063 {
1064         size_t src_len = strlen(src)+1;
1065
1066         *dest = NULL;
1067         return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
1068 }
1069
1070 /**
1071  Copy a string from a char* src to a UTF-8 destination.
1072  Return the number of bytes occupied by the string in the destination
1073  Flags can have:
1074   STR_TERMINATE means include the null termination
1075   STR_UPPER     means uppercase in the destination
1076  dest_len is the maximum length allowed in the destination. If dest_len
1077  is -1 then no maxiumum is used.
1078 **/
1079
1080 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
1081 {
1082         size_t src_len = strlen(src);
1083         pstring tmpbuf;
1084
1085         /* treat a pstring as "unlimited" length */
1086         if (dest_len == (size_t)-1)
1087                 dest_len = sizeof(pstring);
1088
1089         if (flags & STR_UPPER) {
1090                 pstrcpy(tmpbuf, src);
1091                 strupper_m(tmpbuf);
1092                 src = tmpbuf;
1093         }
1094
1095         if (flags & STR_TERMINATE)
1096                 src_len++;
1097
1098         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
1099 }
1100
1101 size_t push_utf8_fstring(void *dest, const char *src)
1102 {
1103         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
1104 }
1105
1106 /**
1107  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1108  *
1109  * @param dest always set at least to NULL 
1110  *
1111  * @returns The number of bytes occupied by the string in the destination
1112  **/
1113
1114 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1115 {
1116         size_t src_len = strlen(src)+1;
1117
1118         *dest = NULL;
1119         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
1120 }
1121
1122 /**
1123  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
1124  *
1125  * @param dest always set at least to NULL 
1126  *
1127  * @returns The number of bytes occupied by the string in the destination
1128  **/
1129
1130 size_t push_utf8_allocate(char **dest, const char *src)
1131 {
1132         size_t src_len = strlen(src)+1;
1133
1134         *dest = NULL;
1135         return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);      
1136 }
1137
1138 /**
1139  Copy a string from a ucs2 source to a unix char* destination.
1140  Flags can have:
1141   STR_TERMINATE means the string in src is null terminated.
1142   STR_NOALIGN   means don't try to align.
1143  if STR_TERMINATE is set then src_len is ignored if it is -1.
1144  src_len is the length of the source area in bytes
1145  Return the number of bytes occupied by the string in src.
1146  The resulting string in "dest" is always null terminated.
1147 **/
1148
1149 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1150 {
1151         size_t ret;
1152
1153         if (dest_len == (size_t)-1)
1154                 dest_len = sizeof(pstring);
1155
1156         if (ucs2_align(base_ptr, src, flags)) {
1157                 src = (const void *)((const char *)src + 1);
1158                 if (src_len != (size_t)-1)
1159                         src_len--;
1160         }
1161
1162         if (flags & STR_TERMINATE) {
1163                 /* src_len -1 is the default for null terminated strings. */
1164                 if (src_len != (size_t)-1) {
1165                         size_t len = strnlen_w(src, src_len/2);
1166                         if (len < src_len/2)
1167                                 len++;
1168                         src_len = len*2;
1169                 }
1170         }
1171
1172         /* ucs2 is always a multiple of 2 bytes */
1173         if (src_len != (size_t)-1)
1174                 src_len &= ~1;
1175         
1176         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len, True);
1177         if (ret == (size_t)-1) {
1178                 return 0;
1179         }
1180
1181         if (src_len == (size_t)-1)
1182                 src_len = ret*2;
1183                 
1184         if (dest_len)
1185                 dest[MIN(ret, dest_len-1)] = 0;
1186         else 
1187                 dest[0] = 0;
1188
1189         return src_len;
1190 }
1191
1192 size_t pull_ucs2_pstring(char *dest, const void *src)
1193 {
1194         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
1195 }
1196
1197 size_t pull_ucs2_fstring(char *dest, const void *src)
1198 {
1199         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
1200 }
1201
1202 /**
1203  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1204  *
1205  * @param dest always set at least to NULL 
1206  *
1207  * @returns The number of bytes occupied by the string in the destination
1208  **/
1209
1210 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
1211 {
1212         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1213         *dest = NULL;
1214         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
1215 }
1216
1217 /**
1218  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
1219  *
1220  * @param dest always set at least to NULL 
1221  *
1222  * @returns The number of bytes occupied by the string in the destination
1223  **/
1224
1225 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
1226 {
1227         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1228         *dest = NULL;
1229         return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
1230 }
1231
1232 /**
1233  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1234  *
1235  * @param dest always set at least to NULL 
1236  *
1237  * @returns The number of bytes occupied by the string in the destination
1238  **/
1239
1240 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1241 {
1242         size_t src_len = strlen(src)+1;
1243         *dest = NULL;
1244         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1245 }
1246
1247 /**
1248  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
1249  *
1250  * @param dest always set at least to NULL 
1251  *
1252  * @returns The number of bytes occupied by the string in the destination
1253  **/
1254
1255 size_t pull_utf8_allocate(char **dest, const char *src)
1256 {
1257         size_t src_len = strlen(src)+1;
1258         *dest = NULL;
1259         return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1260 }
1261  
1262 /**
1263  Copy a string from a char* src to a unicode or ascii
1264  dos codepage destination choosing unicode or ascii based on the 
1265  flags in the SMB buffer starting at base_ptr.
1266  Return the number of bytes occupied by the string in the destination.
1267  flags can have:
1268   STR_TERMINATE means include the null termination.
1269   STR_UPPER     means uppercase in the destination.
1270   STR_ASCII     use ascii even with unicode packet.
1271   STR_NOALIGN   means don't do alignment.
1272  dest_len is the maximum length allowed in the destination. If dest_len
1273  is -1 then no maxiumum is used.
1274 **/
1275
1276 size_t push_string_fn(const char *function, unsigned int line, const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
1277 {
1278 #ifdef DEVELOPER
1279         /* We really need to zero fill here, not clobber
1280          * region, as we want to ensure that valgrind thinks
1281          * all of the outgoing buffer has been written to
1282          * so a send() or write() won't trap an error.
1283          * JRA.
1284          */
1285 #if 0
1286         if (dest_len != (size_t)-1)
1287                 clobber_region(function, line, dest, dest_len);
1288 #else
1289         if (dest_len != (size_t)-1)
1290                 memset(dest, '\0', dest_len);
1291 #endif
1292 #endif
1293
1294         if (!(flags & STR_ASCII) && \
1295             ((flags & STR_UNICODE || \
1296               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1297                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
1298         }
1299         return push_ascii(dest, src, dest_len, flags);
1300 }
1301
1302
1303 /**
1304  Copy a string from a unicode or ascii source (depending on
1305  the packet flags) to a char* destination.
1306  Flags can have:
1307   STR_TERMINATE means the string in src is null terminated.
1308   STR_UNICODE   means to force as unicode.
1309   STR_ASCII     use ascii even with unicode packet.
1310   STR_NOALIGN   means don't do alignment.
1311  if STR_TERMINATE is set then src_len is ignored is it is -1
1312  src_len is the length of the source area in bytes.
1313  Return the number of bytes occupied by the string in src.
1314  The resulting string in "dest" is always null terminated.
1315 **/
1316
1317 size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1318 {
1319 #ifdef DEVELOPER
1320         if (dest_len != (size_t)-1)
1321                 clobber_region(function, line, dest, dest_len);
1322 #endif
1323
1324         if (!(flags & STR_ASCII) && \
1325             ((flags & STR_UNICODE || \
1326               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1327                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1328         }
1329         return pull_ascii(dest, src, dest_len, src_len, flags);
1330 }
1331
1332 size_t align_string(const void *base_ptr, const char *p, int flags)
1333 {
1334         if (!(flags & STR_ASCII) && \
1335             ((flags & STR_UNICODE || \
1336               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1337                 return ucs2_align(base_ptr, p, flags);
1338         }
1339         return 0;
1340 }
1341
1342 /****************************************************************
1343  Calculate the size (in bytes) of the next multibyte character in
1344  our internal character set. Note that p must be pointing to a
1345  valid mb char, not within one.
1346 ****************************************************************/
1347
1348 size_t next_mb_char_size(const char *s)
1349 {
1350         size_t i;
1351
1352         if (!(*s & 0x80))
1353                 return 1; /* ascii. */
1354
1355         conv_silent = True;
1356         for ( i = 1; i <=4; i++ ) {
1357                 smb_ucs2_t uc;
1358                 if (convert_string(CH_UNIX, CH_UCS2, s, i, &uc, 2, False) == 2) {
1359 #if 0 /* JRATEST */
1360                         DEBUG(10,("next_mb_char_size: size %u at string %s\n",
1361                                 (unsigned int)i, s));
1362 #endif
1363                         conv_silent = False;
1364                         return i;
1365                 }
1366         }
1367         /* We're hosed - we don't know how big this is... */
1368         DEBUG(10,("next_mb_char_size: unknown size at string %s\n", s));
1369         conv_silent = False;
1370         return 1;
1371 }