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