First part of patch from moriyama@miraclelinux.com (MORIYAMA Masayuki) to
[bbaumbach/samba-autobuild/.git] / source3 / lib / charcnv.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Character set conversion Extensions
4    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5    Copyright (C) Andrew Tridgell 2001
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Martin Pool 2003
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 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 /********************************************************************
827  Push an nstring - ensure null terminated. Written by
828  moriyama@miraclelinux.com (MORIYAMA Masayuki).
829 ********************************************************************/
830
831 size_t push_ascii_nstring(void *dest, const char *src)
832 {
833         size_t i, buffer_len, dest_len;
834         smb_ucs2_t *buffer;
835
836         buffer_len = push_ucs2_allocate(&buffer, src);
837         if (buffer_len == (size_t)-1) {
838                 smb_panic("failed to create UCS2 buffer");
839         }
840
841         dest_len = 0;
842         for (i = 0; i < buffer_len; i++) {
843                 unsigned char mb[10];
844                 /* Convert one smb_ucs2_t character at a time. */
845                 size_t mb_len = convert_string(CH_UCS2, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
846                 if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
847                         memcpy((char *)dest + dest_len, mb, mb_len);
848                         dest_len += mb_len;
849                 } else {
850                         break;
851                 }
852         }
853         ((char *)dest)[dest_len] = '\0';
854
855         SAFE_FREE(buffer);
856         return dest_len;
857 }
858
859 /**
860  * Copy a string from a dos codepage source to a unix char* destination.
861  *
862  * The resulting string in "dest" is always null terminated.
863  *
864  * @param flags can have:
865  * <dl>
866  * <dt>STR_TERMINATE</dt>
867  * <dd>STR_TERMINATE means the string in @p src
868  * is null terminated, and src_len is ignored.</dd>
869  * </dl>
870  *
871  * @param src_len is the length of the source area in bytes.
872  * @returns the number of bytes occupied by the string in @p src.
873  **/
874 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
875 {
876         size_t ret;
877
878         if (dest_len == (size_t)-1)
879                 dest_len = sizeof(pstring);
880
881         if (flags & STR_TERMINATE) {
882                 if (src_len == (size_t)-1) {
883                         src_len = strlen(src) + 1;
884                 } else {
885                         size_t len = strnlen(src, src_len);
886                         if (len < src_len)
887                                 len++;
888                         src_len = len;
889                 }
890         }
891
892         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
893         if (ret == (size_t)-1) {
894                 dest_len = 0;
895         }
896
897         if (dest_len)
898                 dest[MIN(ret, dest_len-1)] = 0;
899         else 
900                 dest[0] = 0;
901
902         return src_len;
903 }
904
905 size_t pull_ascii_pstring(char *dest, const void *src)
906 {
907         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
908 }
909
910 size_t pull_ascii_fstring(char *dest, const void *src)
911 {
912         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
913 }
914
915 size_t pull_ascii_nstring(char *dest, const void *src)
916 {
917         return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE);
918 }
919
920 /**
921  * Copy a string from a char* src to a unicode destination.
922  *
923  * @returns the number of bytes occupied by the string in the destination.
924  *
925  * @param flags can have:
926  *
927  * <dl>
928  * <dt>STR_TERMINATE <dd>means include the null termination.
929  * <dt>STR_UPPER     <dd>means uppercase in the destination.
930  * <dt>STR_NOALIGN   <dd>means don't do alignment.
931  * </dl>
932  *
933  * @param dest_len is the maximum length allowed in the
934  * destination. If dest_len is -1 then no maxiumum is used.
935  **/
936
937 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
938 {
939         size_t len=0;
940         size_t src_len;
941         size_t ret;
942
943         /* treat a pstring as "unlimited" length */
944         if (dest_len == (size_t)-1)
945                 dest_len = sizeof(pstring);
946
947         if (flags & STR_TERMINATE)
948                 src_len = (size_t)-1;
949         else
950                 src_len = strlen(src);
951
952         if (ucs2_align(base_ptr, dest, flags)) {
953                 *(char *)dest = 0;
954                 dest = (void *)((char *)dest + 1);
955                 if (dest_len)
956                         dest_len--;
957                 len++;
958         }
959
960         /* ucs2 is always a multiple of 2 bytes */
961         dest_len &= ~1;
962
963         ret =  convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len, True);
964         if (ret == (size_t)-1) {
965                 return 0;
966         }
967
968         len += ret;
969
970         if (flags & STR_UPPER) {
971                 smb_ucs2_t *dest_ucs2 = dest;
972                 size_t i;
973                 for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
974                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
975                         if (v != dest_ucs2[i]) {
976                                 dest_ucs2[i] = v;
977                         }
978                 }
979         }
980
981         return len;
982 }
983
984
985 /**
986  * Copy a string from a unix char* src to a UCS2 destination,
987  * allocating a buffer using talloc().
988  *
989  * @param dest always set at least to NULL 
990  *
991  * @returns The number of bytes occupied by the string in the destination
992  *         or -1 in case of error.
993  **/
994 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
995 {
996         size_t src_len = strlen(src)+1;
997
998         *dest = NULL;
999         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
1000 }
1001
1002
1003 /**
1004  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
1005  *
1006  * @param dest always set at least to NULL 
1007  *
1008  * @returns The number of bytes occupied by the string in the destination
1009  *         or -1 in case of error.
1010  **/
1011
1012 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
1013 {
1014         size_t src_len = strlen(src)+1;
1015
1016         *dest = NULL;
1017         return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
1018 }
1019
1020 /**
1021  Copy a string from a char* src to a UTF-8 destination.
1022  Return the number of bytes occupied by the string in the destination
1023  Flags can have:
1024   STR_TERMINATE means include the null termination
1025   STR_UPPER     means uppercase in the destination
1026  dest_len is the maximum length allowed in the destination. If dest_len
1027  is -1 then no maxiumum is used.
1028 **/
1029
1030 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
1031 {
1032         size_t src_len = strlen(src);
1033         pstring tmpbuf;
1034
1035         /* treat a pstring as "unlimited" length */
1036         if (dest_len == (size_t)-1)
1037                 dest_len = sizeof(pstring);
1038
1039         if (flags & STR_UPPER) {
1040                 pstrcpy(tmpbuf, src);
1041                 strupper_m(tmpbuf);
1042                 src = tmpbuf;
1043         }
1044
1045         if (flags & STR_TERMINATE)
1046                 src_len++;
1047
1048         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
1049 }
1050
1051 size_t push_utf8_fstring(void *dest, const char *src)
1052 {
1053         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
1054 }
1055
1056 /**
1057  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1058  *
1059  * @param dest always set at least to NULL 
1060  *
1061  * @returns The number of bytes occupied by the string in the destination
1062  **/
1063
1064 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1065 {
1066         size_t src_len = strlen(src)+1;
1067
1068         *dest = NULL;
1069         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
1070 }
1071
1072 /**
1073  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
1074  *
1075  * @param dest always set at least to NULL 
1076  *
1077  * @returns The number of bytes occupied by the string in the destination
1078  **/
1079
1080 size_t push_utf8_allocate(char **dest, const char *src)
1081 {
1082         size_t src_len = strlen(src)+1;
1083
1084         *dest = NULL;
1085         return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);      
1086 }
1087
1088 /**
1089  Copy a string from a ucs2 source to a unix char* destination.
1090  Flags can have:
1091   STR_TERMINATE means the string in src is null terminated.
1092   STR_NOALIGN   means don't try to align.
1093  if STR_TERMINATE is set then src_len is ignored if it is -1.
1094  src_len is the length of the source area in bytes
1095  Return the number of bytes occupied by the string in src.
1096  The resulting string in "dest" is always null terminated.
1097 **/
1098
1099 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1100 {
1101         size_t ret;
1102
1103         if (dest_len == (size_t)-1)
1104                 dest_len = sizeof(pstring);
1105
1106         if (ucs2_align(base_ptr, src, flags)) {
1107                 src = (const void *)((const char *)src + 1);
1108                 if (src_len != (size_t)-1)
1109                         src_len--;
1110         }
1111
1112         if (flags & STR_TERMINATE) {
1113                 /* src_len -1 is the default for null terminated strings. */
1114                 if (src_len != (size_t)-1) {
1115                         size_t len = strnlen_w(src, src_len/2);
1116                         if (len < src_len/2)
1117                                 len++;
1118                         src_len = len*2;
1119                 }
1120         }
1121
1122         /* ucs2 is always a multiple of 2 bytes */
1123         if (src_len != (size_t)-1)
1124                 src_len &= ~1;
1125         
1126         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len, True);
1127         if (ret == (size_t)-1) {
1128                 return 0;
1129         }
1130
1131         if (src_len == (size_t)-1)
1132                 src_len = ret*2;
1133                 
1134         if (dest_len)
1135                 dest[MIN(ret, dest_len-1)] = 0;
1136         else 
1137                 dest[0] = 0;
1138
1139         return src_len;
1140 }
1141
1142 size_t pull_ucs2_pstring(char *dest, const void *src)
1143 {
1144         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
1145 }
1146
1147 size_t pull_ucs2_fstring(char *dest, const void *src)
1148 {
1149         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
1150 }
1151
1152 /**
1153  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1154  *
1155  * @param dest always set at least to NULL 
1156  *
1157  * @returns The number of bytes occupied by the string in the destination
1158  **/
1159
1160 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
1161 {
1162         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1163         *dest = NULL;
1164         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
1165 }
1166
1167 /**
1168  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
1169  *
1170  * @param dest always set at least to NULL 
1171  *
1172  * @returns The number of bytes occupied by the string in the destination
1173  **/
1174
1175 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
1176 {
1177         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1178         *dest = NULL;
1179         return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
1180 }
1181
1182 /**
1183  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1184  *
1185  * @param dest always set at least to NULL 
1186  *
1187  * @returns The number of bytes occupied by the string in the destination
1188  **/
1189
1190 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1191 {
1192         size_t src_len = strlen(src)+1;
1193         *dest = NULL;
1194         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1195 }
1196
1197 /**
1198  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
1199  *
1200  * @param dest always set at least to NULL 
1201  *
1202  * @returns The number of bytes occupied by the string in the destination
1203  **/
1204
1205 size_t pull_utf8_allocate(char **dest, const char *src)
1206 {
1207         size_t src_len = strlen(src)+1;
1208         *dest = NULL;
1209         return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1210 }
1211  
1212 /**
1213  Copy a string from a char* src to a unicode or ascii
1214  dos codepage destination choosing unicode or ascii based on the 
1215  flags in the SMB buffer starting at base_ptr.
1216  Return the number of bytes occupied by the string in the destination.
1217  flags can have:
1218   STR_TERMINATE means include the null termination.
1219   STR_UPPER     means uppercase in the destination.
1220   STR_ASCII     use ascii even with unicode packet.
1221   STR_NOALIGN   means don't do alignment.
1222  dest_len is the maximum length allowed in the destination. If dest_len
1223  is -1 then no maxiumum is used.
1224 **/
1225
1226 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)
1227 {
1228 #ifdef DEVELOPER
1229         /* We really need to zero fill here, not clobber
1230          * region, as we want to ensure that valgrind thinks
1231          * all of the outgoing buffer has been written to
1232          * so a send() or write() won't trap an error.
1233          * JRA.
1234          */
1235 #if 0
1236         if (dest_len != (size_t)-1)
1237                 clobber_region(function, line, dest, dest_len);
1238 #else
1239         if (dest_len != (size_t)-1)
1240                 memset(dest, '\0', dest_len);
1241 #endif
1242 #endif
1243
1244         if (!(flags & STR_ASCII) && \
1245             ((flags & STR_UNICODE || \
1246               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1247                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
1248         }
1249         return push_ascii(dest, src, dest_len, flags);
1250 }
1251
1252
1253 /**
1254  Copy a string from a unicode or ascii source (depending on
1255  the packet flags) to a char* destination.
1256  Flags can have:
1257   STR_TERMINATE means the string in src is null terminated.
1258   STR_UNICODE   means to force as unicode.
1259   STR_ASCII     use ascii even with unicode packet.
1260   STR_NOALIGN   means don't do alignment.
1261  if STR_TERMINATE is set then src_len is ignored is it is -1
1262  src_len is the length of the source area in bytes.
1263  Return the number of bytes occupied by the string in src.
1264  The resulting string in "dest" is always null terminated.
1265 **/
1266
1267 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)
1268 {
1269 #ifdef DEVELOPER
1270         if (dest_len != (size_t)-1)
1271                 clobber_region(function, line, dest, dest_len);
1272 #endif
1273
1274         if (!(flags & STR_ASCII) && \
1275             ((flags & STR_UNICODE || \
1276               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1277                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1278         }
1279         return pull_ascii(dest, src, dest_len, src_len, flags);
1280 }
1281
1282 size_t align_string(const void *base_ptr, const char *p, int flags)
1283 {
1284         if (!(flags & STR_ASCII) && \
1285             ((flags & STR_UNICODE || \
1286               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1287                 return ucs2_align(base_ptr, p, flags);
1288         }
1289         return 0;
1290 }