Line data Source code
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) Jeremy Allison 2005
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "replace.h"
23 : #include "charset.h"
24 : #include "lib/util/byteorder.h"
25 : #include "lib/util/debug.h"
26 : #include "lib/util/fault.h"
27 :
28 : /* Copy into a smb_ucs2_t from a possibly unaligned buffer. Return the copied smb_ucs2_t */
29 : #define COPY_UCS2_CHAR(dest,src) (((unsigned char *)(dest))[0] = ((const unsigned char *)(src))[0],\
30 : ((unsigned char *)(dest))[1] = ((const unsigned char *)(src))[1], (dest))
31 :
32 :
33 : /* return an ascii version of a ucs2 character */
34 : #define UCS2_TO_CHAR(c) (((c) >> UCS2_SHIFT) & 0xff)
35 :
36 : static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len);
37 :
38 : /*******************************************************************
39 : Count the number of two-byte pairs in a UTF16 string.
40 : ********************************************************************/
41 :
42 370024 : size_t strlen_w(const smb_ucs2_t *src)
43 : {
44 39 : size_t len;
45 39 : smb_ucs2_t c;
46 :
47 5805916 : for(len = 0; *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
48 1830 : ;
49 : }
50 :
51 370024 : return len;
52 : }
53 :
54 : /*******************************************************************
55 : Count up to max number of characters in a smb_ucs2_t string.
56 : ********************************************************************/
57 :
58 218005 : size_t strnlen_w(const smb_ucs2_t *src, size_t max)
59 : {
60 10716 : size_t len;
61 10716 : smb_ucs2_t c;
62 :
63 4573652 : for(len = 0; (len < max) && *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
64 214232 : ;
65 : }
66 :
67 218005 : return len;
68 : }
69 :
70 : /*******************************************************************
71 : Wide strchr().
72 : ********************************************************************/
73 :
74 9 : smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
75 : {
76 9 : smb_ucs2_t cp;
77 14 : while (*(COPY_UCS2_CHAR(&cp,s))) {
78 11 : if (c == cp) {
79 6 : return discard_const_p(smb_ucs2_t, s);
80 : }
81 5 : s++;
82 : }
83 3 : if (c == cp) {
84 0 : return discard_const_p(smb_ucs2_t, s);
85 : }
86 :
87 0 : return NULL;
88 : }
89 :
90 0 : smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
91 : {
92 0 : return strchr_w(s, UCS2_CHAR(c));
93 : }
94 :
95 : /*******************************************************************
96 : Wide strrchr().
97 : ********************************************************************/
98 :
99 25595 : smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
100 : {
101 0 : smb_ucs2_t cp;
102 25595 : const smb_ucs2_t *p = s;
103 25595 : int len = strlen_w(s);
104 :
105 25595 : if (len == 0) {
106 0 : return NULL;
107 : }
108 25595 : p += (len - 1);
109 0 : do {
110 97439 : if (c == *(COPY_UCS2_CHAR(&cp,p))) {
111 1497 : return discard_const_p(smb_ucs2_t, p);
112 : }
113 95942 : } while (p-- != s);
114 24098 : return NULL;
115 : }
116 :
117 : /*******************************************************************
118 : Wide version of strrchr that returns after doing strrchr 'n' times.
119 : ********************************************************************/
120 :
121 0 : smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n)
122 : {
123 0 : smb_ucs2_t cp;
124 0 : const smb_ucs2_t *p = s;
125 0 : int len = strlen_w(s);
126 :
127 0 : if (len == 0 || !n) {
128 0 : return NULL;
129 : }
130 0 : p += (len - 1);
131 0 : do {
132 0 : if (c == *(COPY_UCS2_CHAR(&cp,p))) {
133 0 : n--;
134 : }
135 :
136 0 : if (!n) {
137 0 : return discard_const_p(smb_ucs2_t, p);
138 : }
139 0 : } while (p-- != s);
140 0 : return NULL;
141 : }
142 :
143 : /*******************************************************************
144 : Wide strstr().
145 : ********************************************************************/
146 :
147 6 : smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
148 : {
149 6 : const smb_ucs2_t *r;
150 6 : size_t inslen;
151 :
152 6 : if (!s || !*s || !ins || !*ins) {
153 0 : return NULL;
154 : }
155 :
156 6 : inslen = strlen_w(ins);
157 6 : r = s;
158 :
159 9 : while ((r = strchr_w(r, *ins))) {
160 6 : if (strncmp_w(r, ins, inslen) == 0) {
161 3 : return discard_const_p(smb_ucs2_t, r);
162 : }
163 3 : r++;
164 : }
165 :
166 0 : return NULL;
167 : }
168 :
169 : /*******************************************************************
170 : Convert a string to lower case.
171 : return True if any char is converted
172 :
173 : This is unsafe for any string involving a UTF16 character
174 : ********************************************************************/
175 :
176 0 : bool strlower_w(smb_ucs2_t *s)
177 : {
178 0 : smb_ucs2_t cp;
179 0 : bool ret = false;
180 :
181 0 : while (*(COPY_UCS2_CHAR(&cp,s))) {
182 0 : smb_ucs2_t v = tolower_m(cp);
183 0 : if (v != cp) {
184 0 : (void)COPY_UCS2_CHAR(s,&v);
185 0 : ret = true;
186 : }
187 0 : s++;
188 : }
189 0 : return ret;
190 : }
191 :
192 : /*******************************************************************
193 : Convert a string to upper case.
194 : return True if any char is converted
195 :
196 : This is unsafe for any string involving a UTF16 character
197 : ********************************************************************/
198 :
199 4 : bool strupper_w(smb_ucs2_t *s)
200 : {
201 0 : smb_ucs2_t cp;
202 4 : bool ret = false;
203 8 : while (*(COPY_UCS2_CHAR(&cp,s))) {
204 4 : smb_ucs2_t v = toupper_m(cp);
205 4 : if (v != cp) {
206 0 : (void)COPY_UCS2_CHAR(s,&v);
207 0 : ret = true;
208 : }
209 4 : s++;
210 : }
211 4 : return ret;
212 : }
213 :
214 6 : static int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
215 : {
216 6 : smb_ucs2_t cpa, cpb;
217 6 : size_t n = 0;
218 :
219 22 : while ((n < len) && (*(COPY_UCS2_CHAR(&cpb,b))) && (*(COPY_UCS2_CHAR(&cpa,a)) == cpb)) {
220 16 : a++;
221 16 : b++;
222 16 : n++;
223 : }
224 6 : return (len - n)?(*(COPY_UCS2_CHAR(&cpa,a)) - *(COPY_UCS2_CHAR(&cpb,b))):0;
225 : }
226 :
227 : /*
228 : The *_wa() functions take a combination of 7 bit ascii
229 : and wide characters They are used so that you can use string
230 : functions combining C string constants with ucs2 strings
231 :
232 : The char* arguments must NOT be multibyte - to be completely sure
233 : of this only pass string constants */
234 :
235 0 : int strcmp_wa(const smb_ucs2_t *a, const char *b)
236 : {
237 0 : smb_ucs2_t cp = 0;
238 :
239 0 : while (*b && *(COPY_UCS2_CHAR(&cp,a)) == UCS2_CHAR(*b)) {
240 0 : a++;
241 0 : b++;
242 : }
243 0 : return (*(COPY_UCS2_CHAR(&cp,a)) - UCS2_CHAR(*b));
244 : }
245 :
246 391418 : smb_ucs2_t toupper_w(smb_ucs2_t v)
247 : {
248 276 : smb_ucs2_t ret;
249 : /* LE to native. */
250 391418 : codepoint_t cp = SVAL(&v,0);
251 391418 : cp = toupper_m(cp);
252 : /* native to LE. */
253 391418 : SSVAL(&ret,0,cp);
254 391418 : return ret;
255 : }
|