c59620ed32b1377693564302171cc137dec312ed
[nivanova/samba-autobuild/.git] / lib / util / charset / util_unistr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce 2001
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/locale.h"
23
24 /**
25  * Get the next token from a string, return False if none found.
26  * Handles double-quotes.
27  * 
28  * Based on a routine by GJC@VILLAGE.COM. 
29  * Extensively modified by Andrew.Tridgell@anu.edu.au
30  **/
31 _PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
32 {
33         const char *s;
34         bool quoted;
35         size_t len=1;
36
37         if (!ptr)
38                 return false;
39
40         s = *ptr;
41
42         /* default to simple separators */
43         if (!sep)
44                 sep = " \t\n\r";
45
46         /* find the first non sep char */
47         while (*s && strchr_m(sep,*s))
48                 s++;
49         
50         /* nothing left? */
51         if (!*s)
52                 return false;
53         
54         /* copy over the token */
55         for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
56                 if (*s == '\"') {
57                         quoted = !quoted;
58                 } else {
59                         len++;
60                         *buff++ = *s;
61                 }
62         }
63         
64         *ptr = (*s) ? s+1 : s;  
65         *buff = 0;
66         
67         return true;
68 }
69
70
71 /**
72  String replace.
73  NOTE: oldc and newc must be 7 bit characters
74 **/
75 _PUBLIC_ void string_replace_m(char *s, char oldc, char newc)
76 {
77         struct smb_iconv_convenience *ic = get_iconv_convenience();
78         while (s && *s) {
79                 size_t size;
80                 codepoint_t c = next_codepoint_convenience(ic, s, &size);
81                 if (c == oldc) {
82                         *s = newc;
83                 }
84                 s += size;
85         }
86 }
87
88 /**
89  Paranoid strcpy into a buffer of given length (includes terminating
90  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
91  and replaces with '_'. Deliberately does *NOT* check for multibyte
92  characters. Don't change it !
93 **/
94
95 _PUBLIC_ char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
96 {
97         size_t len, i;
98
99         if (maxlength == 0) {
100                 /* can't fit any bytes at all! */
101                 return NULL;
102         }
103
104         if (!dest) {
105                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
106                 return NULL;
107         }
108
109         if (!src) {
110                 *dest = 0;
111                 return dest;
112         }  
113
114         len = strlen(src);
115         if (len >= maxlength)
116                 len = maxlength - 1;
117
118         if (!other_safe_chars)
119                 other_safe_chars = "";
120
121         for(i = 0; i < len; i++) {
122                 int val = (src[i] & 0xff);
123                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
124                         dest[i] = src[i];
125                 else
126                         dest[i] = '_';
127         }
128
129         dest[i] = '\0';
130
131         return dest;
132 }
133
134 /**
135  Convert a string to lower case, allocated with talloc
136 **/
137 _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
138 {
139         size_t size=0;
140         char *dest;
141         struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
142
143         if(src == NULL) {
144                 return NULL;
145         }
146
147         /* this takes advantage of the fact that upper/lower can't
148            change the length of a character by more than 1 byte */
149         dest = talloc_array(ctx, char, 2*(strlen(src))+1);
150         if (dest == NULL) {
151                 return NULL;
152         }
153
154         while (*src) {
155                 size_t c_size;
156                 codepoint_t c = next_codepoint_convenience(iconv_convenience, src, &c_size);
157                 src += c_size;
158
159                 c = tolower_m(c);
160
161                 c_size = push_codepoint_convenience(iconv_convenience, dest+size, c);
162                 if (c_size == -1) {
163                         talloc_free(dest);
164                         return NULL;
165                 }
166                 size += c_size;
167         }
168
169         dest[size] = 0;
170
171         /* trim it so talloc_append_string() works */
172         dest = talloc_realloc(ctx, dest, char, size+1);
173
174         talloc_set_name_const(dest, dest);
175
176         return dest;
177 }
178
179 /**
180  Convert a string to UPPER case, allocated with talloc
181  source length limited to n bytes
182 **/
183 _PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
184 {
185         size_t size=0;
186         char *dest;
187         struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
188
189         if (!src) {
190                 return NULL;
191         }
192
193         /* this takes advantage of the fact that upper/lower can't
194            change the length of a character by more than 1 byte */
195         dest = talloc_array(ctx, char, 2*(n+1));
196         if (dest == NULL) {
197                 return NULL;
198         }
199
200         while (n-- && *src) {
201                 size_t c_size;
202                 codepoint_t c = next_codepoint_convenience(iconv_convenience, src, &c_size);
203                 src += c_size;
204
205                 c = toupper_m(c);
206
207                 c_size = push_codepoint_convenience(iconv_convenience, dest+size, c);
208                 if (c_size == -1) {
209                         talloc_free(dest);
210                         return NULL;
211                 }
212                 size += c_size;
213         }
214
215         dest[size] = 0;
216
217         /* trim it so talloc_append_string() works */
218         dest = talloc_realloc(ctx, dest, char, size+1);
219
220         talloc_set_name_const(dest, dest);
221
222         return dest;
223 }
224
225 /**
226  Convert a string to UPPER case, allocated with talloc
227 **/
228 _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
229 {
230         return strupper_talloc_n(ctx, src, src?strlen(src):0);
231 }
232
233 /**
234  talloc_strdup() a unix string to upper case.
235 **/
236 _PUBLIC_ char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *src)
237 {
238         return strupper_talloc(ctx, src);
239 }
240
241 /**
242  Convert a string to lower case.
243 **/
244 _PUBLIC_ void strlower_m(char *s)
245 {
246         char *d;
247         struct smb_iconv_convenience *iconv_convenience;
248
249         /* this is quite a common operation, so we want it to be
250            fast. We optimise for the ascii case, knowing that all our
251            supported multi-byte character sets are ascii-compatible
252            (ie. they match for the first 128 chars) */
253         while (*s && !(((uint8_t)*s) & 0x80)) {
254                 *s = tolower((uint8_t)*s);
255                 s++;
256         }
257
258         if (!*s)
259                 return;
260
261         iconv_convenience = get_iconv_convenience();
262
263         d = s;
264
265         while (*s) {
266                 size_t c_size, c_size2;
267                 codepoint_t c = next_codepoint_convenience(iconv_convenience, s, &c_size);
268                 c_size2 = push_codepoint_convenience(iconv_convenience, d, tolower_m(c));
269                 if (c_size2 > c_size) {
270                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
271                                  c, tolower_m(c), (int)c_size, (int)c_size2));
272                         smb_panic("codepoint expansion in strlower_m\n");
273                 }
274                 s += c_size;
275                 d += c_size2;
276         }
277         *d = 0;
278 }
279
280 /**
281  Convert a string to UPPER case.
282 **/
283 _PUBLIC_ void strupper_m(char *s)
284 {
285         char *d;
286         struct smb_iconv_convenience *iconv_convenience;
287
288         /* this is quite a common operation, so we want it to be
289            fast. We optimise for the ascii case, knowing that all our
290            supported multi-byte character sets are ascii-compatible
291            (ie. they match for the first 128 chars) */
292         while (*s && !(((uint8_t)*s) & 0x80)) {
293                 *s = toupper((uint8_t)*s);
294                 s++;
295         }
296
297         if (!*s)
298                 return;
299
300         iconv_convenience = get_iconv_convenience();
301
302         d = s;
303
304         while (*s) {
305                 size_t c_size, c_size2;
306                 codepoint_t c = next_codepoint_convenience(iconv_convenience, s, &c_size);
307                 c_size2 = push_codepoint_convenience(iconv_convenience, d, toupper_m(c));
308                 if (c_size2 > c_size) {
309                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
310                                  c, toupper_m(c), (int)c_size, (int)c_size2));
311                         smb_panic("codepoint expansion in strupper_m\n");
312                 }
313                 s += c_size;
314                 d += c_size2;
315         }
316         *d = 0;
317 }
318
319
320 /**
321  Find the number of 'c' chars in a string
322 **/
323 _PUBLIC_ size_t count_chars_m(const char *s, char c)
324 {
325         struct smb_iconv_convenience *ic = get_iconv_convenience();
326         size_t count = 0;
327
328         while (*s) {
329                 size_t size;
330                 codepoint_t c2 = next_codepoint_convenience(ic, s, &size);
331                 if (c2 == c) count++;
332                 s += size;
333         }
334
335         return count;
336 }
337
338
339 /**
340  * Copy a string from a char* unix src to a dos codepage string destination.
341  *
342  * @return the number of bytes occupied by the string in the destination.
343  *
344  * @param flags can include
345  * <dl>
346  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
347  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
348  * </dl>
349  *
350  * @param dest_len the maximum length in bytes allowed in the
351  * destination.  If @p dest_len is -1 then no maximum is used.
352  **/
353 static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
354 {
355         size_t src_len;
356         ssize_t ret;
357
358         if (flags & STR_UPPER) {
359                 char *tmpbuf = strupper_talloc(NULL, src);
360                 if (tmpbuf == NULL) {
361                         return -1;
362                 }
363                 ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
364                 talloc_free(tmpbuf);
365                 return ret;
366         }
367
368         src_len = strlen(src);
369
370         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
371                 src_len++;
372
373         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
374 }
375
376 /**
377  * Copy a string from a unix char* src to an ASCII destination,
378  * allocating a buffer using talloc().
379  *
380  * @param dest always set at least to NULL 
381  *
382  * @returns The number of bytes occupied by the string in the destination
383  *         or -1 in case of error.
384  **/
385 _PUBLIC_ bool push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
386 {
387         size_t src_len = strlen(src)+1;
388         *dest = NULL;
389         return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest, converted_size);
390 }
391
392
393 /**
394  * Copy a string from a dos codepage source to a unix char* destination.
395  *
396  * The resulting string in "dest" is always null terminated.
397  *
398  * @param flags can have:
399  * <dl>
400  * <dt>STR_TERMINATE</dt>
401  * <dd>STR_TERMINATE means the string in @p src
402  * is null terminated, and src_len is ignored.</dd>
403  * </dl>
404  *
405  * @param src_len is the length of the source area in bytes.
406  * @returns the number of bytes occupied by the string in @p src.
407  **/
408 static ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
409 {
410         size_t ret;
411
412         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
413                 if (src_len == (size_t)-1) {
414                         src_len = strlen((const char *)src) + 1;
415                 } else {
416                         size_t len = strnlen((const char *)src, src_len);
417                         if (len < src_len)
418                                 len++;
419                         src_len = len;
420                 }
421         }
422
423         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
424
425         if (dest_len)
426                 dest[MIN(ret, dest_len-1)] = 0;
427
428         return src_len;
429 }
430
431 /**
432  * Copy a string from a char* src to a unicode destination.
433  *
434  * @returns the number of bytes occupied by the string in the destination.
435  *
436  * @param flags can have:
437  *
438  * <dl>
439  * <dt>STR_TERMINATE <dd>means include the null termination.
440  * <dt>STR_UPPER     <dd>means uppercase in the destination.
441  * <dt>STR_NOALIGN   <dd>means don't do alignment.
442  * </dl>
443  *
444  * @param dest_len is the maximum length allowed in the
445  * destination. If dest_len is -1 then no maxiumum is used.
446  **/
447 static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags)
448 {
449         size_t len=0;
450         size_t src_len = strlen(src);
451         size_t ret;
452
453         if (flags & STR_UPPER) {
454                 char *tmpbuf = strupper_talloc(NULL, src);
455                 if (tmpbuf == NULL) {
456                         return -1;
457                 }
458                 ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
459                 talloc_free(tmpbuf);
460                 return ret;
461         }
462
463         if (flags & STR_TERMINATE)
464                 src_len++;
465
466         if (ucs2_align(NULL, dest, flags)) {
467                 *(char *)dest = 0;
468                 dest = (void *)((char *)dest + 1);
469                 if (dest_len) dest_len--;
470                 len++;
471         }
472
473         /* ucs2 is always a multiple of 2 bytes */
474         dest_len &= ~1;
475
476         ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
477         if (ret == (size_t)-1) {
478                 return 0;
479         }
480
481         len += ret;
482
483         return len;
484 }
485
486
487 /**
488  * Copy a string from a unix char* src to a UCS2 destination,
489  * allocating a buffer using talloc().
490  *
491  * @param dest always set at least to NULL 
492  *
493  * @returns The number of bytes occupied by the string in the destination
494  *         or -1 in case of error.
495  **/
496 _PUBLIC_ bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src, size_t *converted_size)
497 {
498         size_t src_len = strlen(src)+1;
499         *dest = NULL;
500         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (void **)dest, converted_size);
501 }
502
503
504 /**
505  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
506  *
507  * @param dest always set at least to NULL 
508  *
509  * @returns The number of bytes occupied by the string in the destination
510  **/
511
512 _PUBLIC_ bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
513 {
514         size_t src_len = strlen(src)+1;
515         *dest = NULL;
516         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, converted_size);
517 }
518
519 /**
520  Copy a string from a ucs2 source to a unix char* destination.
521  Flags can have:
522   STR_TERMINATE means the string in src is null terminated.
523   STR_NOALIGN   means don't try to align.
524  if STR_TERMINATE is set then src_len is ignored if it is -1.
525  src_len is the length of the source area in bytes
526  Return the number of bytes occupied by the string in src.
527  The resulting string in "dest" is always null terminated.
528 **/
529
530 static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
531 {
532         size_t ret;
533
534         if (ucs2_align(NULL, src, flags)) {
535                 src = (const void *)((const char *)src + 1);
536                 if (src_len > 0)
537                         src_len--;
538         }
539
540         if (flags & STR_TERMINATE) {
541                 if (src_len == (size_t)-1) {
542                         src_len = utf16_len(src);
543                 } else {
544                         src_len = utf16_len_n(src, src_len);
545                 }
546         }
547
548         /* ucs2 is always a multiple of 2 bytes */
549         if (src_len != (size_t)-1)
550                 src_len &= ~1;
551         
552         ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len);
553         if (dest_len)
554                 dest[MIN(ret, dest_len-1)] = 0;
555
556         return src_len;
557 }
558
559 /**
560  * Copy a string from a ASCII src to a unix char * destination, allocating a buffer using talloc
561  *
562  * @param dest always set at least to NULL 
563  *
564  * @returns The number of bytes occupied by the string in the destination
565  **/
566
567 _PUBLIC_ bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
568 {
569         size_t src_len = strlen(src)+1;
570         *dest = NULL;
571         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, converted_size);
572 }
573
574 /**
575  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
576  *
577  * @param dest always set at least to NULL 
578  *
579  * @returns The number of bytes occupied by the string in the destination
580  **/
581
582 _PUBLIC_ bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src, size_t *converted_size)
583 {
584         size_t src_len = utf16_len(src);
585         *dest = NULL;
586         return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest, converted_size);
587 }
588
589 /**
590  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
591  *
592  * @param dest always set at least to NULL 
593  *
594  * @returns The number of bytes occupied by the string in the destination
595  **/
596
597 _PUBLIC_ bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
598 {
599         size_t src_len = strlen(src)+1;
600         *dest = NULL;
601         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, converted_size);
602 }
603
604 /**
605  Copy a string from a char* src to a unicode or ascii
606  dos codepage destination choosing unicode or ascii based on the 
607  flags in the SMB buffer starting at base_ptr.
608  Return the number of bytes occupied by the string in the destination.
609  flags can have:
610   STR_TERMINATE means include the null termination.
611   STR_UPPER     means uppercase in the destination.
612   STR_ASCII     use ascii even with unicode packet.
613   STR_NOALIGN   means don't do alignment.
614  dest_len is the maximum length allowed in the destination. If dest_len
615  is -1 then no maxiumum is used.
616 **/
617
618 _PUBLIC_ ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
619 {
620         if (flags & STR_ASCII) {
621                 return push_ascii(dest, src, dest_len, flags);
622         } else if (flags & STR_UNICODE) {
623                 return push_ucs2(dest, src, dest_len, flags);
624         } else {
625                 smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set");
626                 return -1;
627         }
628 }
629
630
631 /**
632  Copy a string from a unicode or ascii source (depending on
633  the packet flags) to a char* destination.
634  Flags can have:
635   STR_TERMINATE means the string in src is null terminated.
636   STR_UNICODE   means to force as unicode.
637   STR_ASCII     use ascii even with unicode packet.
638   STR_NOALIGN   means don't do alignment.
639  if STR_TERMINATE is set then src_len is ignored is it is -1
640  src_len is the length of the source area in bytes.
641  Return the number of bytes occupied by the string in src.
642  The resulting string in "dest" is always null terminated.
643 **/
644
645 _PUBLIC_ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
646 {
647         if (flags & STR_ASCII) {
648                 return pull_ascii(dest, src, dest_len, src_len, flags);
649         } else if (flags & STR_UNICODE) {
650                 return pull_ucs2(dest, src, dest_len, src_len, flags);
651         } else {
652                 smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set");
653                 return -1;
654         }
655 }
656
657
658 /**
659  * Convert string from one encoding to another, making error checking etc
660  *
661  * @param src pointer to source string (multibyte or singlebyte)
662  * @param srclen length of the source string in bytes
663  * @param dest pointer to destination string (multibyte or singlebyte)
664  * @param destlen maximal length allowed for string
665  * @returns the number of bytes occupied in the destination
666  **/
667 _PUBLIC_ size_t convert_string(charset_t from, charset_t to,
668                                void const *src, size_t srclen, 
669                                void *dest, size_t destlen)
670 {
671         size_t ret;
672         if (!convert_string_convenience(get_iconv_convenience(), from, to, 
673                                         src, srclen,
674                                         dest, destlen, &ret))
675                 return -1;
676         return ret;
677 }
678
679 /**
680  * Convert between character sets, allocating a new buffer using talloc for the result.
681  *
682  * @param srclen length of source buffer.
683  * @param dest always set at least to NULL
684  * @param converted_size Size in bytes of the converted string
685  * @note -1 is not accepted for srclen.
686  *
687  * @returns boolean indication whether the conversion succeeded
688  **/
689
690 _PUBLIC_ bool convert_string_talloc(TALLOC_CTX *ctx, 
691                                     charset_t from, charset_t to, 
692                                     void const *src, size_t srclen, 
693                                     void *dest, size_t *converted_size)
694 {
695         return convert_string_talloc_convenience(ctx, get_iconv_convenience(),
696                                                  from, to, src, srclen, dest,
697                                                  converted_size);
698 }
699