auth/auth_util.c:
[ira/wip.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  * @returns the number of bytes occupied in the destination
160  *
161  * Ensure the srclen contains the terminating zero.
162  *
163  **/
164
165 static size_t convert_string_internal(charset_t from, charset_t to,
166                       void const *src, size_t srclen, 
167                       void *dest, size_t destlen)
168 {
169         size_t i_len, o_len;
170         size_t retval;
171         const char* inbuf = (const char*)src;
172         char* outbuf = (char*)dest;
173         smb_iconv_t descriptor;
174
175         lazy_initialize_conv();
176
177         descriptor = conv_handles[from][to];
178
179         if (srclen == (size_t)-1) {
180                 if (from == CH_UCS2) {
181                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
182                 } else {
183                         srclen = strlen((const char *)src)+1;
184                 }
185         }
186
187         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
188                 if (!conv_silent)
189                         DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
190                 goto use_as_is;
191         }
192
193         i_len=srclen;
194         o_len=destlen;
195         retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len);
196         if(retval==(size_t)-1) {
197                 const char *reason="unknown error";
198                 switch(errno) {
199                         case EINVAL:
200                                 reason="Incomplete multibyte sequence";
201                                 if (!conv_silent)
202                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
203                                 goto use_as_is;
204                         case E2BIG:
205                                 reason="No more room"; 
206                                 if (!conv_silent)
207                                         DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n",
208                                                 (unsigned long)srclen, (unsigned long)destlen));
209                                 /* we are not sure we need srclen bytes,
210                                   may be more, may be less.
211                                   We only know we need more than destlen
212                                   bytes ---simo */
213                                break;
214                         case EILSEQ:
215                                 reason="Illegal multibyte sequence";
216                                 if (!conv_silent)
217                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
218                                 goto use_as_is;
219                         default:
220                                 if (!conv_silent)
221                                         DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
222                                 break;
223                 }
224                 /* smb_panic(reason); */
225         }
226         return destlen-o_len;
227
228  use_as_is:
229
230         /* conversion not supported, use as is */
231         {
232                 size_t len = MIN(srclen,destlen);
233                 if (len)
234                         memcpy(dest,src,len);
235                 return len;
236         }
237 }
238
239 /**
240  * Convert string from one encoding to another, making error checking etc
241  * Fast path version - handles ASCII first.
242  *
243  * @param src pointer to source string (multibyte or singlebyte)
244  * @param srclen length of the source string in bytes
245  * @param dest pointer to destination string (multibyte or singlebyte)
246  * @param destlen maximal length allowed for string
247  * @returns the number of bytes occupied in the destination
248  *
249  * Ensure the srclen contains the terminating zero.
250  *
251  * This function has been hand-tuned to provide a fast path.
252  * Don't change unless you really know what you are doing. JRA.
253  **/
254
255 size_t convert_string(charset_t from, charset_t to,
256                       void const *src, size_t srclen, 
257                       void *dest, size_t destlen)
258 {
259         /*
260          * NB. We deliberately don't do a strlen here is srclen == -1.
261          * This is very expensive over millions of calls and is taken
262          * care of in the slow path in convert_string_internal. JRA.
263          */
264
265         if (srclen == 0)
266                 return 0;
267
268         if (from != CH_UCS2 && to != CH_UCS2) {
269                 const unsigned char *p = (const unsigned char *)src;
270                 unsigned char *q = (unsigned char *)dest;
271                 size_t slen = srclen;
272                 size_t dlen = destlen;
273                 unsigned char lastp;
274                 size_t retval = 0;
275
276                 /* If all characters are ascii, fast path here. */
277                 while (slen && dlen) {
278                         if ((lastp = *p) <= 0x7f) {
279                                 *q++ = *p++;
280                                 if (slen != (size_t)-1) {
281                                         slen--;
282                                 }
283                                 dlen--;
284                                 retval++;
285                                 if (!lastp)
286                                         break;
287                         } else {
288 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
289                                 goto general_case;
290 #else
291                                 return retval + convert_string_internal(from, to, p, slen, q, dlen);
292 #endif
293                         }
294                 }
295                 return retval;
296         } else if (from == CH_UCS2 && to != CH_UCS2) {
297                 const unsigned char *p = (const unsigned char *)src;
298                 unsigned char *q = (unsigned char *)dest;
299                 size_t retval = 0;
300                 size_t slen = srclen;
301                 size_t dlen = destlen;
302                 unsigned char lastp;
303
304                 /* If all characters are ascii, fast path here. */
305                 while ((slen >= 2) && dlen) {
306                         if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
307                                 *q++ = *p;
308                                 if (slen != (size_t)-1) {
309                                         slen -= 2;
310                                 }
311                                 p += 2;
312                                 dlen--;
313                                 retval++;
314                                 if (!lastp)
315                                         break;
316                         } else {
317 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
318                                 goto general_case;
319 #else
320                                 return retval + convert_string_internal(from, to, p, slen, q, dlen);
321 #endif
322                         }
323                 }
324                 return retval;
325         } else if (from != CH_UCS2 && to == CH_UCS2) {
326                 const unsigned char *p = (const unsigned char *)src;
327                 unsigned char *q = (unsigned char *)dest;
328                 size_t retval = 0;
329                 size_t slen = srclen;
330                 size_t dlen = destlen;
331                 unsigned char lastp;
332
333                 /* If all characters are ascii, fast path here. */
334                 while (slen && (dlen >= 2)) {
335                         if ((lastp = *p) <= 0x7F) {
336                                 *q++ = *p++;
337                                 *q++ = '\0';
338                                 if (slen != (size_t)-1) {
339                                         slen--;
340                                 }
341                                 dlen -= 2;
342                                 retval += 2;
343                                 if (!lastp)
344                                         break;
345                         } else {
346 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
347                                 goto general_case;
348 #else
349                                 return retval + convert_string_internal(from, to, p, slen, q, dlen);
350 #endif
351                         }
352                 }
353                 return retval;
354         }
355
356 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
357   general_case:
358 #endif
359         return convert_string_internal(from, to, src, srclen, dest, destlen);
360 }
361
362 /**
363  * Convert between character sets, allocating a new buffer for the result.
364  *
365  * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
366  * @param srclen length of source buffer.
367  * @param dest always set at least to NULL
368  * @note -1 is not accepted for srclen.
369  *
370  * @returns Size in bytes of the converted string; or -1 in case of error.
371  *
372  * Ensure the srclen contains the terminating zero.
373  **/
374
375 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
376                                void const *src, size_t srclen, void **dest)
377 {
378         size_t i_len, o_len, destlen = MAX(srclen, 512);
379         size_t retval;
380         const char *inbuf = (const char *)src;
381         char *outbuf = NULL, *ob = NULL;
382         smb_iconv_t descriptor;
383
384         *dest = NULL;
385
386         if (src == NULL || srclen == (size_t)-1)
387                 return (size_t)-1;
388         if (srclen == 0)
389                 return 0;
390
391         lazy_initialize_conv();
392
393         descriptor = conv_handles[from][to];
394
395         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
396                 if (!conv_silent)
397                         DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
398                 goto use_as_is;
399         }
400
401 convert:
402         if ((destlen*2) < destlen) {
403                 /* wrapped ! abort. */
404                 if (!conv_silent)
405                         DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
406                 if (!ctx)
407                         SAFE_FREE(outbuf);
408                 return (size_t)-1;
409         } else {
410                 destlen = destlen * 2;
411         }
412
413         if (ctx)
414                 ob = (char *)talloc_realloc(ctx, ob, destlen);
415         else
416                 ob = (char *)Realloc(ob, destlen);
417
418         if (!ob) {
419                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
420                 if (!ctx)
421                         SAFE_FREE(outbuf);
422                 return (size_t)-1;
423         } else {
424                 outbuf = ob;
425         }
426         i_len = srclen;
427         o_len = destlen;
428         retval = smb_iconv(descriptor,
429                            (char **)&inbuf, &i_len,
430                            &outbuf, &o_len);
431         if(retval == (size_t)-1)                {
432                 const char *reason="unknown error";
433                 switch(errno) {
434                         case EINVAL:
435                                 reason="Incomplete multibyte sequence";
436                                 if (!conv_silent)
437                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
438                                 goto use_as_is;
439                         case E2BIG:
440                                 goto convert;           
441                         case EILSEQ:
442                                 reason="Illegal multibyte sequence";
443                                 if (!conv_silent)
444                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
445                                 goto use_as_is;
446                 }
447                 if (!conv_silent)
448                         DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
449                 /* smb_panic(reason); */
450                 return (size_t)-1;
451         }
452         
453         destlen = destlen - o_len;
454         if (ctx)
455                 *dest = (char *)talloc_realloc(ctx,ob,destlen);
456         else
457                 *dest = (char *)Realloc(ob,destlen);
458         if (destlen && !*dest) {
459                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
460                 if (!ctx)
461                         SAFE_FREE(ob);
462                 return (size_t)-1;
463         }
464
465         return destlen;
466
467   use_as_is:
468
469         /* conversion not supported, use as is */
470         {
471                 if (srclen && (destlen != srclen)) {
472                         destlen = srclen;
473                         if (ctx)
474                                 ob = (char *)talloc_realloc(ctx, ob, destlen);
475                         else
476                                 ob = (char *)Realloc(ob, destlen);
477                         if (!ob) {
478                                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
479                                 if (!ctx)
480                                         SAFE_FREE(outbuf);
481                                 return (size_t)-1;
482                         }
483                 }
484                 if (srclen && ob)
485                         memcpy(ob,(const char *)src,srclen);
486                 *dest = (char *)ob;
487                 return srclen;
488         }
489 }
490
491 /**
492  * Convert between character sets, allocating a new buffer using talloc for the result.
493  *
494  * @param srclen length of source buffer.
495  * @param dest always set at least to NULL 
496  * @note -1 is not accepted for srclen.
497  *
498  * @returns Size in bytes of the converted string; or -1 in case of error.
499  **/
500 static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
501                                 void const *src, size_t srclen, void **dest)
502 {
503         size_t dest_len;
504
505         *dest = NULL;
506         dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest);
507         if (dest_len == (size_t)-1)
508                 return (size_t)-1;
509         if (*dest == NULL)
510                 return (size_t)-1;
511         return dest_len;
512 }
513
514 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
515 {
516         size_t size;
517         smb_ucs2_t *buffer;
518         
519         size = push_ucs2_allocate(&buffer, src);
520         if (size == -1) {
521                 smb_panic("failed to create UCS2 buffer");
522         }
523         if (!strupper_w(buffer) && (dest == src)) {
524                 free(buffer);
525                 return srclen;
526         }
527         
528         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
529         free(buffer);
530         return size;
531 }
532
533 /**
534  strdup() a unix string to upper case.
535  Max size is pstring.
536 **/
537
538 char *strdup_upper(const char *s)
539 {
540         pstring out_buffer;
541         const unsigned char *p = (const unsigned char *)s;
542         unsigned char *q = (unsigned char *)out_buffer;
543
544         /* this is quite a common operation, so we want it to be
545            fast. We optimise for the ascii case, knowing that all our
546            supported multi-byte character sets are ascii-compatible
547            (ie. they match for the first 128 chars) */
548
549         while (1) {
550                 if (*p & 0x80)
551                         break;
552                 *q++ = toupper(*p);
553                 if (!*p)
554                         break;
555                 p++;
556                 if (p - ( const unsigned char *)s >= sizeof(pstring))
557                         break;
558         }
559
560         if (*p) {
561                 /* MB case. */
562                 size_t size;
563                 wpstring buffer;
564                 size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer));
565                 if (size == -1) {
566                         return NULL;
567                 }
568
569                 strupper_w(buffer);
570         
571                 size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer));
572                 if (size == -1) {
573                         return NULL;
574                 }
575         }
576
577         return strdup(out_buffer);
578 }
579
580 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
581 {
582         size_t size;
583         smb_ucs2_t *buffer = NULL;
584         
585         size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
586                                        (void **) &buffer);
587         if (size == -1 || !buffer) {
588                 smb_panic("failed to create UCS2 buffer");
589         }
590         if (!strlower_w(buffer) && (dest == src)) {
591                 SAFE_FREE(buffer);
592                 return srclen;
593         }
594         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
595         SAFE_FREE(buffer);
596         return size;
597 }
598
599 /**
600  strdup() a unix string to lower case.
601 **/
602
603 char *strdup_lower(const char *s)
604 {
605         size_t size;
606         smb_ucs2_t *buffer = NULL;
607         char *out_buffer;
608         
609         size = push_ucs2_allocate(&buffer, s);
610         if (size == -1 || !buffer) {
611                 return NULL;
612         }
613
614         strlower_w(buffer);
615         
616         size = pull_ucs2_allocate(&out_buffer, buffer);
617         SAFE_FREE(buffer);
618
619         if (size == -1) {
620                 return NULL;
621         }
622         
623         return out_buffer;
624 }
625
626 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
627 {
628         if (flags & (STR_NOALIGN|STR_ASCII))
629                 return 0;
630         return PTR_DIFF(p, base_ptr) & 1;
631 }
632
633
634 /**
635  * Copy a string from a char* unix src to a dos codepage string destination.
636  *
637  * @return the number of bytes occupied by the string in the destination.
638  *
639  * @param flags can include
640  * <dl>
641  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
642  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
643  * </dl>
644  *
645  * @param dest_len the maximum length in bytes allowed in the
646  * destination.  If @p dest_len is -1 then no maximum is used.
647  **/
648 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
649 {
650         size_t src_len = strlen(src);
651         pstring tmpbuf;
652
653         /* treat a pstring as "unlimited" length */
654         if (dest_len == (size_t)-1)
655                 dest_len = sizeof(pstring);
656
657         if (flags & STR_UPPER) {
658                 pstrcpy(tmpbuf, src);
659                 strupper_m(tmpbuf);
660                 src = tmpbuf;
661         }
662
663         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
664                 src_len++;
665
666         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
667 }
668
669 size_t push_ascii_fstring(void *dest, const char *src)
670 {
671         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
672 }
673
674 size_t push_ascii_pstring(void *dest, const char *src)
675 {
676         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
677 }
678
679 size_t push_ascii_nstring(void *dest, const char *src)
680 {
681         return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE);
682 }
683
684 /**
685  * Copy a string from a dos codepage source to a unix char* destination.
686  *
687  * The resulting string in "dest" is always null terminated.
688  *
689  * @param flags can have:
690  * <dl>
691  * <dt>STR_TERMINATE</dt>
692  * <dd>STR_TERMINATE means the string in @p src
693  * is null terminated, and src_len is ignored.</dd>
694  * </dl>
695  *
696  * @param src_len is the length of the source area in bytes.
697  * @returns the number of bytes occupied by the string in @p src.
698  **/
699 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
700 {
701         size_t ret;
702
703         if (dest_len == (size_t)-1)
704                 dest_len = sizeof(pstring);
705
706         if (flags & STR_TERMINATE) {
707                 if (src_len == (size_t)-1) {
708                         src_len = strlen(src) + 1;
709                 } else {
710                         size_t len = strnlen(src, src_len);
711                         if (len < src_len)
712                                 len++;
713                         src_len = len;
714                 }
715         }
716
717         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
718
719         if (dest_len)
720                 dest[MIN(ret, dest_len-1)] = 0;
721         else 
722                 dest[0] = 0;
723
724         return src_len;
725 }
726
727 size_t pull_ascii_pstring(char *dest, const void *src)
728 {
729         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
730 }
731
732 size_t pull_ascii_fstring(char *dest, const void *src)
733 {
734         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
735 }
736
737 size_t pull_ascii_nstring(char *dest, const void *src)
738 {
739         return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE);
740 }
741
742 /**
743  * Copy a string from a char* src to a unicode destination.
744  *
745  * @returns the number of bytes occupied by the string in the destination.
746  *
747  * @param flags can have:
748  *
749  * <dl>
750  * <dt>STR_TERMINATE <dd>means include the null termination.
751  * <dt>STR_UPPER     <dd>means uppercase in the destination.
752  * <dt>STR_NOALIGN   <dd>means don't do alignment.
753  * </dl>
754  *
755  * @param dest_len is the maximum length allowed in the
756  * destination. If dest_len is -1 then no maxiumum is used.
757  **/
758
759 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
760 {
761         size_t len=0;
762         size_t src_len;
763
764         /* treat a pstring as "unlimited" length */
765         if (dest_len == (size_t)-1)
766                 dest_len = sizeof(pstring);
767
768         if (flags & STR_TERMINATE)
769                 src_len = (size_t)-1;
770         else
771                 src_len = strlen(src);
772
773         if (ucs2_align(base_ptr, dest, flags)) {
774                 *(char *)dest = 0;
775                 dest = (void *)((char *)dest + 1);
776                 if (dest_len)
777                         dest_len--;
778                 len++;
779         }
780
781         /* ucs2 is always a multiple of 2 bytes */
782         dest_len &= ~1;
783
784         len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
785
786         if (flags & STR_UPPER) {
787                 smb_ucs2_t *dest_ucs2 = dest;
788                 size_t i;
789                 for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
790                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
791                         if (v != dest_ucs2[i]) {
792                                 dest_ucs2[i] = v;
793                         }
794                 }
795         }
796
797         return len;
798 }
799
800
801 /**
802  * Copy a string from a unix char* src to a UCS2 destination,
803  * allocating a buffer using talloc().
804  *
805  * @param dest always set at least to NULL 
806  *
807  * @returns The number of bytes occupied by the string in the destination
808  *         or -1 in case of error.
809  **/
810 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
811 {
812         size_t src_len = strlen(src)+1;
813
814         *dest = NULL;
815         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
816 }
817
818
819 /**
820  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
821  *
822  * @param dest always set at least to NULL 
823  *
824  * @returns The number of bytes occupied by the string in the destination
825  *         or -1 in case of error.
826  **/
827
828 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
829 {
830         size_t src_len = strlen(src)+1;
831
832         *dest = NULL;
833         return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);    
834 }
835
836 /**
837  Copy a string from a char* src to a UTF-8 destination.
838  Return the number of bytes occupied by the string in the destination
839  Flags can have:
840   STR_TERMINATE means include the null termination
841   STR_UPPER     means uppercase in the destination
842  dest_len is the maximum length allowed in the destination. If dest_len
843  is -1 then no maxiumum is used.
844 **/
845
846 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
847 {
848         size_t src_len = strlen(src);
849         pstring tmpbuf;
850
851         /* treat a pstring as "unlimited" length */
852         if (dest_len == (size_t)-1)
853                 dest_len = sizeof(pstring);
854
855         if (flags & STR_UPPER) {
856                 pstrcpy(tmpbuf, src);
857                 strupper_m(tmpbuf);
858                 src = tmpbuf;
859         }
860
861         if (flags & STR_TERMINATE)
862                 src_len++;
863
864         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
865 }
866
867 size_t push_utf8_fstring(void *dest, const char *src)
868 {
869         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
870 }
871
872 /**
873  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
874  *
875  * @param dest always set at least to NULL 
876  *
877  * @returns The number of bytes occupied by the string in the destination
878  **/
879
880 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
881 {
882         size_t src_len = strlen(src)+1;
883
884         *dest = NULL;
885         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
886 }
887
888 /**
889  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
890  *
891  * @param dest always set at least to NULL 
892  *
893  * @returns The number of bytes occupied by the string in the destination
894  **/
895
896 size_t push_utf8_allocate(char **dest, const char *src)
897 {
898         size_t src_len = strlen(src)+1;
899
900         *dest = NULL;
901         return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);    
902 }
903
904 /**
905  Copy a string from a ucs2 source to a unix char* destination.
906  Flags can have:
907   STR_TERMINATE means the string in src is null terminated.
908   STR_NOALIGN   means don't try to align.
909  if STR_TERMINATE is set then src_len is ignored if it is -1.
910  src_len is the length of the source area in bytes
911  Return the number of bytes occupied by the string in src.
912  The resulting string in "dest" is always null terminated.
913 **/
914
915 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
916 {
917         size_t ret;
918
919         if (dest_len == (size_t)-1)
920                 dest_len = sizeof(pstring);
921
922         if (ucs2_align(base_ptr, src, flags)) {
923                 src = (const void *)((const char *)src + 1);
924                 if (src_len > 0)
925                         src_len--;
926         }
927
928         if (flags & STR_TERMINATE) {
929                 /* src_len -1 is the default for null terminated strings. */
930                 if (src_len != (size_t)-1) {
931                         size_t len = strnlen_w(src, src_len/2);
932                         if (len < src_len/2)
933                                 len++;
934                         src_len = len*2;
935                 }
936         }
937
938         /* ucs2 is always a multiple of 2 bytes */
939         if (src_len != (size_t)-1)
940                 src_len &= ~1;
941         
942         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
943         if (dest_len)
944                 dest[MIN(ret, dest_len-1)] = 0;
945         else 
946                 dest[0] = 0;
947
948         return src_len;
949 }
950
951 size_t pull_ucs2_pstring(char *dest, const void *src)
952 {
953         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
954 }
955
956 size_t pull_ucs2_fstring(char *dest, const void *src)
957 {
958         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
959 }
960
961 /**
962  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
963  *
964  * @param dest always set at least to NULL 
965  *
966  * @returns The number of bytes occupied by the string in the destination
967  **/
968
969 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
970 {
971         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
972         *dest = NULL;
973         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
974 }
975
976 /**
977  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
978  *
979  * @param dest always set at least to NULL 
980  *
981  * @returns The number of bytes occupied by the string in the destination
982  **/
983
984 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
985 {
986         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
987         *dest = NULL;
988         return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);    
989 }
990
991 /**
992  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
993  *
994  * @param dest always set at least to NULL 
995  *
996  * @returns The number of bytes occupied by the string in the destination
997  **/
998
999 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1000 {
1001         size_t src_len = strlen(src)+1;
1002         *dest = NULL;
1003         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);       
1004 }
1005
1006 /**
1007  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
1008  *
1009  * @param dest always set at least to NULL 
1010  *
1011  * @returns The number of bytes occupied by the string in the destination
1012  **/
1013
1014 size_t pull_utf8_allocate(char **dest, const char *src)
1015 {
1016         size_t src_len = strlen(src)+1;
1017         *dest = NULL;
1018         return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);    
1019 }
1020  
1021 /**
1022  Copy a string from a char* src to a unicode or ascii
1023  dos codepage destination choosing unicode or ascii based on the 
1024  flags in the SMB buffer starting at base_ptr.
1025  Return the number of bytes occupied by the string in the destination.
1026  flags can have:
1027   STR_TERMINATE means include the null termination.
1028   STR_UPPER     means uppercase in the destination.
1029   STR_ASCII     use ascii even with unicode packet.
1030   STR_NOALIGN   means don't do alignment.
1031  dest_len is the maximum length allowed in the destination. If dest_len
1032  is -1 then no maxiumum is used.
1033 **/
1034
1035 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)
1036 {
1037 #ifdef DEVELOPER
1038         /* We really need to zero fill here, not clobber
1039          * region, as we want to ensure that valgrind thinks
1040          * all of the outgoing buffer has been written to
1041          * so a send() or write() won't trap an error.
1042          * JRA.
1043          */
1044 #if 0
1045         if (dest_len != (size_t)-1)
1046                 clobber_region(function, line, dest, dest_len);
1047 #else
1048         if (dest_len != (size_t)-1)
1049                 memset(dest, '\0', dest_len);
1050 #endif
1051 #endif
1052
1053         if (!(flags & STR_ASCII) && \
1054             ((flags & STR_UNICODE || \
1055               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1056                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
1057         }
1058         return push_ascii(dest, src, dest_len, flags);
1059 }
1060
1061
1062 /**
1063  Copy a string from a unicode or ascii source (depending on
1064  the packet flags) to a char* destination.
1065  Flags can have:
1066   STR_TERMINATE means the string in src is null terminated.
1067   STR_UNICODE   means to force as unicode.
1068   STR_ASCII     use ascii even with unicode packet.
1069   STR_NOALIGN   means don't do alignment.
1070  if STR_TERMINATE is set then src_len is ignored is it is -1
1071  src_len is the length of the source area in bytes.
1072  Return the number of bytes occupied by the string in src.
1073  The resulting string in "dest" is always null terminated.
1074 **/
1075
1076 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)
1077 {
1078 #ifdef DEVELOPER
1079         if (dest_len != (size_t)-1)
1080                 clobber_region(function, line, dest, dest_len);
1081 #endif
1082
1083         if (!(flags & STR_ASCII) && \
1084             ((flags & STR_UNICODE || \
1085               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1086                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1087         }
1088         return pull_ascii(dest, src, dest_len, src_len, flags);
1089 }
1090
1091 size_t align_string(const void *base_ptr, const char *p, int flags)
1092 {
1093         if (!(flags & STR_ASCII) && \
1094             ((flags & STR_UNICODE || \
1095               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1096                 return ucs2_align(base_ptr, p, flags);
1097         }
1098         return 0;
1099 }