Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[tprouty/samba.git] / source / lib / util_unistr.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #ifndef MAXUNI
25 #define MAXUNI 1024
26 #endif
27
28 /*******************************************************************
29  Write a string in (little-endian) unicode format. src is in
30  the current DOS codepage. len is the length in bytes of the
31  string pointed to by dst.
32
33  if null_terminate is True then null terminate the packet (adds 2 bytes)
34
35  the return value is the length in bytes consumed by the string, including the
36  null termination if applied
37 ********************************************************************/
38
39 size_t dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
40 {
41         return push_ucs2(NULL, dst, src, len, 
42                          STR_UNICODE|STR_NOALIGN | (null_terminate?STR_TERMINATE:0));
43 }
44
45
46 /*******************************************************************
47  Skip past a unicode string, but not more than len. Always move
48  past a terminating zero if found.
49 ********************************************************************/
50
51 char *skip_unibuf(char *src, size_t len)
52 {
53     char *srcend = src + len;
54
55     while (src < srcend && SVAL(src,0))
56         src += 2;
57
58     if(!SVAL(src,0))
59         src += 2;
60
61     return src;
62 }
63
64 /* Copy a string from little-endian or big-endian unicode source (depending
65  * on flags) to internal samba format destination
66  */ 
67 int rpcstr_pull(char* dest, void *src, int dest_len, int src_len, int flags)
68 {
69         if(dest_len==-1) dest_len=MAXUNI-3;
70         return pull_ucs2(NULL, dest, src, dest_len, src_len, flags|STR_UNICODE|STR_NOALIGN);
71 }
72
73 /* Copy a string from a unistr2 source to internal samba format
74    destination.  Use this instead of direct calls to rpcstr_pull() to avoid
75    having to determine whether the source string is null terminated. */
76
77 int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
78 {
79         return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring),
80                          src->uni_str_len * 2, 0);
81 }
82
83 /* Converts a string from internal samba format to unicode
84  */ 
85 int rpcstr_push(void* dest, const char *src, int dest_len, int flags)
86 {
87         return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
88 }
89
90 /*******************************************************************
91  Return a DOS codepage version of a little-endian unicode string.
92  len is the filename length (ignoring any terminating zero) in uin16
93  units. Always null terminates.
94  Hack alert: uses fixed buffer(s).
95 ********************************************************************/
96 char *dos_unistrn2(const uint16 *src, int len)
97 {
98         static char lbufs[8][MAXUNI];
99         static int nexti;
100         char *lbuf = lbufs[nexti];
101         nexti = (nexti+1)%8;
102         pull_ucs2(NULL, lbuf, src, MAXUNI-3, len*2, STR_NOALIGN);
103         return lbuf;
104 }
105
106 /*******************************************************************
107  Convert a (little-endian) UNISTR2 structure to an ASCII string
108 ********************************************************************/
109 void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
110 {
111         if (str == NULL) {
112                 *dest='\0';
113                 return;
114         }
115         pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
116 }
117
118
119 /*******************************************************************
120 Return a number stored in a buffer
121 ********************************************************************/
122
123 uint32 buffer2_to_uint32(BUFFER2 *str)
124 {
125         if (str->buf_len == 4)
126                 return IVAL(str->buffer, 0);
127         else
128                 return 0;
129 }
130
131 /*******************************************************************
132  Mapping tables for UNICODE character. Allows toupper/tolower and
133  isXXX functions to work.
134
135  tridge: split into 2 pieces. This saves us 5/6 of the memory
136  with a small speed penalty
137  The magic constants are the lower/upper range of the tables two
138  parts
139 ********************************************************************/
140
141 typedef struct {
142         smb_ucs2_t lower;
143         smb_ucs2_t upper;
144         unsigned char flags;
145 } smb_unicode_table_t;
146
147 #define TABLE1_BOUNDARY 9450
148 #define TABLE2_BOUNDARY 64256
149
150 static smb_unicode_table_t map_table1[] = {
151 #include "unicode_map_table1.h"
152 };
153
154 static smb_unicode_table_t map_table2[] = {
155 #include "unicode_map_table2.h"
156 };
157
158 static unsigned char map_table_flags(smb_ucs2_t v)
159 {
160         v = SVAL(&v,0);
161         if (v < TABLE1_BOUNDARY) return map_table1[v].flags;
162         if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].flags;
163         return 0;
164 }
165
166 static smb_ucs2_t map_table_lower(smb_ucs2_t v)
167 {
168         v = SVAL(&v,0);
169         if (v < TABLE1_BOUNDARY) return map_table1[v].lower;
170         if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].lower;
171         return v;
172 }
173
174 static smb_ucs2_t map_table_upper(smb_ucs2_t v)
175 {
176         v = SVAL(&v,0);
177         if (v < TABLE1_BOUNDARY) return map_table1[v].upper;
178         if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].upper;
179         return v;
180 }
181
182 /*******************************************************************
183  Is an upper case wchar.
184 ********************************************************************/
185
186 int isupper_w( smb_ucs2_t val)
187 {
188         return (map_table_flags(val) & UNI_UPPER);
189 }
190
191 /*******************************************************************
192  Is a lower case wchar.
193 ********************************************************************/
194
195 int islower_w( smb_ucs2_t val)
196 {
197         return (map_table_flags(val) & UNI_LOWER);
198 }
199
200 /*******************************************************************
201  Convert a wchar to upper case.
202 ********************************************************************/
203
204 smb_ucs2_t toupper_w( smb_ucs2_t val )
205 {
206         val = map_table_upper(val);
207         val = SVAL(&val,0);
208         return val;
209 }
210
211 /*******************************************************************
212  Convert a wchar to lower case.
213 ********************************************************************/
214
215 smb_ucs2_t tolower_w( smb_ucs2_t val )
216 {
217         val = map_table_lower(val);
218         val = SVAL(&val,0);
219         return val;
220 }
221
222 /*******************************************************************
223  Count the number of characters in a smb_ucs2_t string.
224 ********************************************************************/
225 size_t strlen_w(const smb_ucs2_t *src)
226 {
227         size_t len;
228
229         for(len = 0; *src++; len++) ;
230
231         return len;
232 }
233
234 /*******************************************************************
235 wide strchr()
236 ********************************************************************/
237 smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
238 {
239         while (*s != 0) {
240                 if (c == *s) return (smb_ucs2_t *)s;
241                 s++;
242         }
243         return NULL;
244 }
245
246
247 /*******************************************************************
248  Convert a string to lower case.
249  return True if any char is converted
250 ********************************************************************/
251 BOOL strlower_w(smb_ucs2_t *s)
252 {
253         BOOL ret = False;
254         while (*s) {
255                 if (isupper_w(*s)) {
256                         *s = tolower_w(*s);
257                         ret = True;
258                 }
259                 s++;
260         }
261         return ret;
262 }
263
264 /*******************************************************************
265  Convert a string to upper case.
266  return True if any char is converted
267 ********************************************************************/
268 BOOL strupper_w(smb_ucs2_t *s)
269 {
270         BOOL ret = False;
271         while (*s) {
272                 if (islower_w(*s)) {
273                         *s = toupper_w(*s);
274                         ret = True;
275                 }
276                 s++;
277         }
278         return ret;
279 }
280
281 /*******************************************************************
282 case insensitive string comparison
283 ********************************************************************/
284 int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
285 {
286         while (*b && tolower_w(*a) == tolower_w(*b)) { a++; b++; }
287         return (tolower_w(*a) - tolower_w(*b));
288 }
289
290
291 /*******************************************************************
292 duplicate string
293 ********************************************************************/
294 smb_ucs2_t *strdup_w(const smb_ucs2_t *src)
295 {
296         smb_ucs2_t *dest;
297         uint32 len;
298         
299         len = strlen_w(src);
300         dest = (smb_ucs2_t *)malloc((len+1)*sizeof(smb_ucs2_t));
301         if (!dest) {
302                 DEBUG(0,("strdup_w: out of memory!\n"));
303                 return NULL;
304         }
305
306         memcpy(dest, src, (len+1)*sizeof(smb_ucs2_t));
307         
308         return dest;
309 }
310
311 /*******************************************************************
312 copy a string with max len
313 ********************************************************************/
314
315 smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
316 {
317         size_t len;
318         
319         if (!dest || !src) return NULL;
320         
321         for (len = 0; (src[len] != 0) && (len < max); len++)
322                 dest[len] = src[len];
323         while (len < max)
324                 dest[len++] = 0;
325         
326         return dest;
327 }
328
329
330 /*******************************************************************
331 append a string of len bytes and add a terminator
332 ********************************************************************/
333
334 smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
335 {       
336         size_t start;
337         size_t len;     
338         
339         if (!dest || !src) return NULL;
340         
341         start = strlen_w(dest);
342         len = strlen_w(src);
343         if (len > max) len = max;
344
345         memcpy(&dest[start], src, len);                 
346         dest[start+len+1] = 0;
347         
348         return dest;
349 }
350
351
352 /*
353   The *_wa() functions take a combination of 7 bit ascii
354   and wide characters They are used so that you can use string
355   functions combining C string constants with ucs2 strings
356
357   The char* arguments must NOT be multibyte - to be completely sure
358   of this only pass string constants */
359
360
361 void pstrcpy_wa(smb_ucs2_t *dest, const char *src)
362 {
363         int i;
364         for (i=0;i<PSTRING_LEN;i++) {
365                 dest[i] = UCS2_CHAR(src[i]);
366                 if (src[i] == 0) return;
367         }
368 }
369
370 int strcmp_wa(const smb_ucs2_t *a, const char *b)
371 {
372         while (*b && *a == UCS2_CHAR(*b)) { a++; b++; }
373         return (*a - UCS2_CHAR(*b));
374 }
375
376
377
378 smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
379 {
380         while (*s != 0) {
381                 if (UCS2_CHAR(c) == *s) return (smb_ucs2_t *)s;
382                 s++;
383         }
384         return NULL;
385 }
386
387 smb_ucs2_t *strrchr_wa(const smb_ucs2_t *s, char c)
388 {
389         const smb_ucs2_t *p = s;
390         int len = strlen_w(s);
391         if (len == 0) return NULL;
392         p += (len-1);
393         do {
394                 if (UCS2_CHAR(c) == *p) return (smb_ucs2_t *)p;
395         } while (p-- != s);
396         return NULL;
397 }
398
399 smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)
400 {
401         while (*s != 0) {
402                 int i;
403                 for (i=0; p[i] && *s != UCS2_CHAR(p[i]); i++) 
404                         ;
405                 if (p[i]) return (smb_ucs2_t *)s;
406                 s++;
407         }
408         return NULL;
409 }
410
411
412 /*******************************************************************
413 copy a string with max len
414 ********************************************************************/
415
416 smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max)
417 {
418         smb_ucs2_t *ucs2_src;
419
420         if (!dest || !src) return NULL;
421         ucs2_src = (smb_ucs2_t *)malloc((strlen(src)+1)*sizeof(smb_ucs2_t));
422         if (!ucs2_src) {
423                 DEBUG(0,("strncpy_wa: out of memory!\n"));
424                 return NULL;
425         }
426         push_ucs2(NULL, ucs2_src, src, -1, STR_TERMINATE|STR_NOALIGN);
427         
428         strncpy_w(dest, ucs2_src, max);
429         SAFE_FREE(ucs2_src);
430         return dest;
431 }
432
433
434 /*******************************************************************
435 append a string of len bytes and add a terminator
436 ********************************************************************/
437
438 smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max)
439 {
440         smb_ucs2_t *ucs2_src;
441
442         if (!dest || !src) return NULL;
443         ucs2_src = (smb_ucs2_t *)malloc((strlen(src)+1)*sizeof(smb_ucs2_t));
444         if (!ucs2_src) {
445                 DEBUG(0,("strncat_wa: out of memory!\n"));
446                 return NULL;
447         }
448         push_ucs2(NULL, ucs2_src, src, -1, STR_TERMINATE|STR_NOALIGN);
449         
450         strncat_w(dest, ucs2_src, max);
451         SAFE_FREE(ucs2_src);
452         return dest;
453 }