4f4ca93cfdd8275589535c06a29b410226355b65
[nivanova/samba-autobuild/.git] / lib / util / charset / util_str.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    Copyright (C) Andrew Bartlett 2011
7    Copyright (C) Jeremy Allison  1992-2007
8    Copyright (C) Martin Pool     2003
9    Copyright (C) James Peach     2006
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "system/locale.h"
27
28 #ifdef strcasecmp
29 #undef strcasecmp
30 #endif
31
32 /**
33  Case insensitive string compararison, handle specified for testing
34 **/
35 _PUBLIC_ int strcasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
36                                  const char *s1, const char *s2)
37 {
38         codepoint_t c1=0, c2=0;
39         size_t size1, size2;
40
41         /* handle null ptr comparisons to simplify the use in qsort */
42         if (s1 == s2) return 0;
43         if (s1 == NULL) return -1;
44         if (s2 == NULL) return 1;
45
46         while (*s1 && *s2) {
47                 c1 = next_codepoint_handle(iconv_handle, s1, &size1);
48                 c2 = next_codepoint_handle(iconv_handle, s2, &size2);
49
50                 s1 += size1;
51                 s2 += size2;
52
53                 if (c1 == c2) {
54                         continue;
55                 }
56
57                 if (c1 == INVALID_CODEPOINT ||
58                     c2 == INVALID_CODEPOINT) {
59                         /* what else can we do?? */
60                         return strcasecmp(s1, s2);
61                 }
62
63                 if (toupper_m(c1) != toupper_m(c2)) {
64                         return c1 - c2;
65                 }
66         }
67
68         return *s1 - *s2;
69 }
70
71 /**
72  Case insensitive string compararison
73 **/
74 _PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
75 {
76         struct smb_iconv_handle *iconv_handle = get_iconv_handle();
77         return strcasecmp_m_handle(iconv_handle, s1, s2);
78 }
79
80 /**
81  Case insensitive string compararison, length limited, handle specified for testing
82 **/
83 _PUBLIC_ int strncasecmp_m_handle(struct smb_iconv_handle *iconv_handle,
84                                   const char *s1, const char *s2, size_t n)
85 {
86         codepoint_t c1=0, c2=0;
87         size_t size1, size2;
88
89         /* handle null ptr comparisons to simplify the use in qsort */
90         if (s1 == s2) return 0;
91         if (s1 == NULL) return -1;
92         if (s2 == NULL) return 1;
93
94         while (*s1 && *s2 && n) {
95                 n--;
96
97                 c1 = next_codepoint_handle(iconv_handle, s1, &size1);
98                 c2 = next_codepoint_handle(iconv_handle, s2, &size2);
99
100                 s1 += size1;
101                 s2 += size2;
102
103                 if (c1 == c2) {
104                         continue;
105                 }
106
107                 if (c1 == INVALID_CODEPOINT ||
108                     c2 == INVALID_CODEPOINT) {
109                         /* what else can we do?? */
110                         return strcasecmp(s1, s2);
111                 }
112
113                 if (toupper_m(c1) != toupper_m(c2)) {
114                         return c1 - c2;
115                 }
116         }
117
118         if (n == 0) {
119                 return 0;
120         }
121
122         return *s1 - *s2;
123 }
124
125 /**
126  Case insensitive string compararison, length limited
127 **/
128 _PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
129 {
130         struct smb_iconv_handle *iconv_handle = get_iconv_handle();
131         return strncasecmp_m_handle(iconv_handle, s1, s2, n);
132 }
133
134 /**
135  * Compare 2 strings.
136  *
137  * @note The comparison is case-insensitive.
138  **/
139 _PUBLIC_ bool strequal_m(const char *s1, const char *s2)
140 {
141         return strcasecmp_m(s1,s2) == 0;
142 }
143
144 /**
145  Compare 2 strings (case sensitive).
146 **/
147 _PUBLIC_ bool strcsequal(const char *s1,const char *s2)
148 {
149         if (s1 == s2)
150                 return true;
151         if (!s1 || !s2)
152                 return false;
153
154         return strcmp(s1,s2) == 0;
155 }
156
157 /**
158  * Calculate the number of units (8 or 16-bit, depending on the
159  * destination charset), that would be needed to convert the input
160  * string which is expected to be in in src_charset encoding to the
161  * destination charset (which should be a unicode charset).
162  */
163 _PUBLIC_ size_t strlen_m_ext_handle(struct smb_iconv_handle *ic,
164                                     const char *s, charset_t src_charset, charset_t dst_charset)
165 {
166         size_t count = 0;
167
168 #ifdef DEVELOPER
169         switch (dst_charset) {
170         case CH_DOS:
171         case CH_UNIX:
172         case CH_DISPLAY:
173                 smb_panic("cannot call strlen_m_ext() with a variable dest charset (must be UTF16* or UTF8)");
174         default:
175                 break;
176         }
177
178         switch (src_charset) {
179         case CH_UTF16LE:
180         case CH_UTF16BE:
181                 smb_panic("cannot call strlen_m_ext() with a UTF16 src charset (must be DOS, UNIX, DISPLAY or UTF8)");
182         default:
183                 break;
184         }
185 #endif
186         if (!s) {
187                 return 0;
188         }
189
190         while (*s && !(((uint8_t)*s) & 0x80)) {
191                 s++;
192                 count++;
193         }
194
195         if (!*s) {
196                 return count;
197         }
198
199         while (*s) {
200                 size_t c_size;
201                 codepoint_t c = next_codepoint_handle_ext(ic, s, src_charset, &c_size);
202                 s += c_size;
203
204                 switch (dst_charset) {
205                 case CH_UTF16LE:
206                 case CH_UTF16BE:
207                 case CH_UTF16MUNGED:
208                         if (c < 0x10000) {
209                                 /* Unicode char fits into 16 bits. */
210                                 count += 1;
211                         } else {
212                                 /* Double-width unicode char - 32 bits. */
213                                 count += 2;
214                         }
215                         break;
216                 case CH_UTF8:
217                         /*
218                          * this only checks ranges, and does not
219                          * check for invalid codepoints
220                          */
221                         if (c < 0x80) {
222                                 count += 1;
223                         } else if (c < 0x800) {
224                                 count += 2;
225                         } else if (c < 0x10000) {
226                                 count += 3;
227                         } else {
228                                 count += 4;
229                         }
230                         break;
231                 default:
232                         /*
233                          * non-unicode encoding:
234                          * assume that each codepoint fits into
235                          * one unit in the destination encoding.
236                          */
237                         count += 1;
238                 }
239         }
240
241         return count;
242 }
243
244 /**
245  * Calculate the number of units (8 or 16-bit, depending on the
246  * destination charset), that would be needed to convert the input
247  * string which is expected to be in in src_charset encoding to the
248  * destination charset (which should be a unicode charset).
249  */
250 _PUBLIC_ size_t strlen_m_ext(const char *s, charset_t src_charset, charset_t dst_charset)
251 {
252         struct smb_iconv_handle *ic = get_iconv_handle();
253         return strlen_m_ext_handle(ic, s, src_charset, dst_charset);
254 }
255
256 _PUBLIC_ size_t strlen_m_ext_term(const char *s, const charset_t src_charset,
257                                   const charset_t dst_charset)
258 {
259         if (!s) {
260                 return 0;
261         }
262         return strlen_m_ext(s, src_charset, dst_charset) + 1;
263 }
264
265 /**
266  * Calculate the number of 16-bit units that would be needed to convert
267  * the input string which is expected to be in CH_UNIX encoding to UTF16.
268  *
269  * This will be the same as the number of bytes in a string for single
270  * byte strings, but will be different for multibyte.
271  */
272 _PUBLIC_ size_t strlen_m(const char *s)
273 {
274         return strlen_m_ext(s, CH_UNIX, CH_UTF16LE);
275 }
276
277 /**
278    Work out the number of multibyte chars in a string, including the NULL
279    terminator.
280 **/
281 _PUBLIC_ size_t strlen_m_term(const char *s)
282 {
283         if (!s) {
284                 return 0;
285         }
286
287         return strlen_m(s) + 1;
288 }
289
290 /*
291  * Weird helper routine for the winreg pipe: If nothing is around, return 0,
292  * if a string is there, include the terminator.
293  */
294
295 _PUBLIC_ size_t strlen_m_term_null(const char *s)
296 {
297         size_t len;
298         if (!s) {
299                 return 0;
300         }
301         len = strlen_m(s);
302         if (len == 0) {
303                 return 0;
304         }
305
306         return len+1;
307 }
308
309 /**
310  Strchr and strrchr_m are a bit complex on general multi-byte strings.
311 **/
312 _PUBLIC_ char *strchr_m(const char *src, char c)
313 {
314         const char *s;
315         struct smb_iconv_handle *ic = get_iconv_handle();
316         if (src == NULL) {
317                 return NULL;
318         }
319         /* characters below 0x3F are guaranteed to not appear in
320            non-initial position in multi-byte charsets */
321         if ((c & 0xC0) == 0) {
322                 return strchr(src, c);
323         }
324
325         /* this is quite a common operation, so we want it to be
326            fast. We optimise for the ascii case, knowing that all our
327            supported multi-byte character sets are ascii-compatible
328            (ie. they match for the first 128 chars) */
329
330         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
331                 if (*s == c)
332                         return discard_const_p(char, s);
333         }
334
335         if (!*s)
336                 return NULL;
337
338 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
339         /* With compose characters we must restart from the beginning. JRA. */
340         s = src;
341 #endif
342
343         while (*s) {
344                 size_t size;
345                 codepoint_t c2 = next_codepoint_handle(ic, s, &size);
346                 if (c2 == c) {
347                         return discard_const_p(char, s);
348                 }
349                 s += size;
350         }
351
352         return NULL;
353 }
354
355 /**
356  * Multibyte-character version of strrchr
357  */
358 _PUBLIC_ char *strrchr_m(const char *s, char c)
359 {
360         struct smb_iconv_handle *ic = get_iconv_handle();
361         char *ret = NULL;
362
363         if (s == NULL) {
364                 return NULL;
365         }
366
367         /* characters below 0x3F are guaranteed to not appear in
368            non-initial position in multi-byte charsets */
369         if ((c & 0xC0) == 0) {
370                 return strrchr(s, c);
371         }
372
373         /* this is quite a common operation, so we want it to be
374            fast. We optimise for the ascii case, knowing that all our
375            supported multi-byte character sets are ascii-compatible
376            (ie. they match for the first 128 chars). Also, in Samba
377            we only search for ascii characters in 'c' and that
378            in all mb character sets with a compound character
379            containing c, if 'c' is not a match at position
380            p, then p[-1] > 0x7f. JRA. */
381
382         {
383                 size_t len = strlen(s);
384                 const char *cp = s;
385                 bool got_mb = false;
386
387                 if (len == 0)
388                         return NULL;
389                 cp += (len - 1);
390                 do {
391                         if (c == *cp) {
392                                 /* Could be a match. Part of a multibyte ? */
393                                 if ((cp > s) &&
394                                         (((unsigned char)cp[-1]) & 0x80)) {
395                                         /* Yep - go slow :-( */
396                                         got_mb = true;
397                                         break;
398                                 }
399                                 /* No - we have a match ! */
400                                 return discard_const_p(char , cp);
401                         }
402                 } while (cp-- != s);
403                 if (!got_mb)
404                         return NULL;
405         }
406
407         while (*s) {
408                 size_t size;
409                 codepoint_t c2 = next_codepoint_handle(ic, s, &size);
410                 if (c2 == c) {
411                         ret = discard_const_p(char, s);
412                 }
413                 s += size;
414         }
415
416         return ret;
417 }
418
419 /**
420   return True if any (multi-byte) character is lower case
421 */
422 _PUBLIC_ bool strhaslower_handle(struct smb_iconv_handle *ic,
423                                  const char *string)
424 {
425         while (*string) {
426                 size_t c_size;
427                 codepoint_t s;
428                 codepoint_t t;
429
430                 s = next_codepoint_handle(ic, string, &c_size);
431                 string += c_size;
432
433                 t = toupper_m(s);
434
435                 if (s != t) {
436                         return true; /* that means it has lower case chars */
437                 }
438         }
439
440         return false;
441 }
442
443 _PUBLIC_ bool strhaslower(const char *string)
444 {
445         struct smb_iconv_handle *ic = get_iconv_handle();
446         return strhaslower_handle(ic, string);
447 }
448
449 /**
450   return True if any (multi-byte) character is upper case
451 */
452 _PUBLIC_ bool strhasupper_handle(struct smb_iconv_handle *ic,
453                                  const char *string)
454 {
455         while (*string) {
456                 size_t c_size;
457                 codepoint_t s;
458                 codepoint_t t;
459
460                 s = next_codepoint_handle(ic, string, &c_size);
461                 string += c_size;
462
463                 t = tolower_m(s);
464
465                 if (s != t) {
466                         return true; /* that means it has upper case chars */
467                 }
468         }
469
470         return false;
471 }
472
473 _PUBLIC_ bool strhasupper(const char *string)
474 {
475         struct smb_iconv_handle *ic = get_iconv_handle();
476         return strhasupper_handle(ic, string);
477 }
478
479 /***********************************************************************
480  strstr_m - We convert via ucs2 for now.
481 ***********************************************************************/
482
483 char *strstr_m(const char *src, const char *findstr)
484 {
485         smb_ucs2_t *p;
486         smb_ucs2_t *src_w, *find_w;
487         const char *s;
488         char *s2;
489         char *retp;
490
491         size_t converted_size, findstr_len = 0;
492
493         /* for correctness */
494         if (!findstr[0]) {
495                 return discard_const_p(char, src);
496         }
497
498         /* Samba does single character findstr calls a *lot*. */
499         if (findstr[1] == '\0')
500                 return strchr_m(src, *findstr);
501
502         /* We optimise for the ascii case, knowing that all our
503            supported multi-byte character sets are ascii-compatible
504            (ie. they match for the first 128 chars) */
505
506         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
507                 if (*s == *findstr) {
508                         if (!findstr_len)
509                                 findstr_len = strlen(findstr);
510
511                         if (strncmp(s, findstr, findstr_len) == 0) {
512                                 return discard_const_p(char, s);
513                         }
514                 }
515         }
516
517         if (!*s)
518                 return NULL;
519
520 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
521         /* 'make check' fails unless we do this */
522
523         /* With compose characters we must restart from the beginning. JRA. */
524         s = src;
525 #endif
526
527         if (!push_ucs2_talloc(talloc_tos(), &src_w, src, &converted_size)) {
528                 DEBUG(0,("strstr_m: src malloc fail\n"));
529                 return NULL;
530         }
531
532         if (!push_ucs2_talloc(talloc_tos(), &find_w, findstr, &converted_size)) {
533                 TALLOC_FREE(src_w);
534                 DEBUG(0,("strstr_m: find malloc fail\n"));
535                 return NULL;
536         }
537
538         p = strstr_w(src_w, find_w);
539
540         if (!p) {
541                 TALLOC_FREE(src_w);
542                 TALLOC_FREE(find_w);
543                 return NULL;
544         }
545
546         *p = 0;
547         if (!pull_ucs2_talloc(talloc_tos(), &s2, src_w, &converted_size)) {
548                 TALLOC_FREE(src_w);
549                 TALLOC_FREE(find_w);
550                 DEBUG(0,("strstr_m: dest malloc fail\n"));
551                 return NULL;
552         }
553         retp = (char *)(s+strlen(s2));
554         TALLOC_FREE(src_w);
555         TALLOC_FREE(find_w);
556         TALLOC_FREE(s2);
557         return retp;
558 }