d6c842a65373ea501060b8d98a819ef58a9b286e
[import/samba-svnimport.git] / source / libndr / ndr_string.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    routines for marshalling/unmarshalling string types
5
6    Copyright (C) Andrew Tridgell 2003
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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 /**
26   pull a general string from the wire
27 */
28 NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
29 {
30         char *as=NULL;
31         uint32_t len1, ofs, len2;
32         uint16_t len3;
33         int ret;
34         charset_t chset = CH_UCS2;
35         unsigned byte_mul = 2;
36         unsigned flags = ndr->flags;
37         unsigned c_len_term = 0;
38
39         if (!(ndr_flags & NDR_SCALARS)) {
40                 return NT_STATUS_OK;
41         }
42
43         SMB_ASSERT(!NDR_BE(ndr));
44
45         if (flags & LIBNDR_FLAG_STR_ASCII) {
46                 chset = CH_DOS;
47                 byte_mul = 1;
48                 flags &= ~LIBNDR_FLAG_STR_ASCII;
49         }
50
51         if (flags & LIBNDR_FLAG_STR_UTF8) {
52                 chset = CH_UTF8;
53                 byte_mul = 1;
54                 flags &= ~LIBNDR_FLAG_STR_UTF8;
55         }
56
57         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
58         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
59                 c_len_term = 1;
60                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
61         }
62
63         switch (flags & LIBNDR_STRING_FLAGS) {
64         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
65         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
66                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
67                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
68                 if (ofs != 0) {
69                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
70                                               ndr->flags & LIBNDR_STRING_FLAGS);
71                 }
72                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
73                 if (len2 > len1) {
74                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
75                                               "Bad string lengths len1=%u ofs=%u len2=%u\n", 
76                                               len1, ofs, len2);
77                 }
78                 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
79                 if (len2 == 0) {
80                         as = talloc_strdup(ndr->current_mem_ctx, "");
81                 } else {
82                         ret = convert_string_talloc(ndr->current_mem_ctx,
83                                                     chset, CH_UNIX, 
84                                                     ndr->data+ndr->offset, 
85                                                     (len2 + c_len_term)*byte_mul,
86                                                     &as, True);
87                         if (ret == -1) {
88                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
89                                                       "Bad character conversion");
90                         }
91                 }
92                 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
93
94                 if (len1 != len2) {
95                         DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
96                 }
97
98                 /* this is a way of detecting if a string is sent with the wrong
99                    termination */
100                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
101                         if (strlen(as) < (len2 + c_len_term)) {
102                                 DEBUG(6,("short string '%s'\n", as));
103                         }
104                 } else {
105                         if (strlen(as) == (len2 + c_len_term)) {
106                                 DEBUG(6,("long string '%s'\n", as));
107                         }
108                 }
109                 *s = as;
110                 break;
111
112         case LIBNDR_FLAG_STR_SIZE4:
113         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
114                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
115                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
116                 if (len1 == 0) {
117                         as = talloc_strdup(ndr->current_mem_ctx, "");
118                 } else {
119                         ret = convert_string_talloc(ndr->current_mem_ctx,
120                                                     chset, CH_UNIX, 
121                                                     ndr->data+ndr->offset, 
122                                                     (len1 + c_len_term)*byte_mul,
123                                                     &as, False);
124                         if (ret == -1) {
125                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
126                                                       "Bad character conversion");
127                         }
128                 }
129                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
130
131                 /* this is a way of detecting if a string is sent with the wrong
132                    termination */
133                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
134                         if (strlen(as) < (len1 + c_len_term)) {
135                                 DEBUG(6,("short string '%s'\n", as));
136                         }
137                 } else {
138                         if (strlen(as) == (len1 + c_len_term)) {
139                                 DEBUG(6,("long string '%s'\n", as));
140                         }
141                 }
142                 *s = as;
143                 break;
144
145         case LIBNDR_FLAG_STR_LEN4:
146         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
147                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
148                 if (ofs != 0) {
149                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
150                                               ndr->flags & LIBNDR_STRING_FLAGS);
151                 }
152                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
153                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
154                 if (len1 == 0) {
155                         as = talloc_strdup(ndr->current_mem_ctx, "");
156                 } else {
157                         ret = convert_string_talloc(ndr->current_mem_ctx,
158                                                     chset, CH_UNIX, 
159                                                     ndr->data+ndr->offset, 
160                                                     (len1 + c_len_term)*byte_mul,
161                                                     &as, False);
162                         if (ret == -1) {
163                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
164                                                       "Bad character conversion");
165                         }
166                 }
167                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
168
169                 /* this is a way of detecting if a string is sent with the wrong
170                    termination */
171                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
172                         if (strlen(as) < (len1 + c_len_term)) {
173                                 DEBUG(6,("short string '%s'\n", as));
174                         }
175                 } else {
176                         if (strlen(as) == (len1 + c_len_term)) {
177                                 DEBUG(6,("long string '%s'\n", as));
178                         }
179                 }
180                 *s = as;
181                 break;
182
183
184         case LIBNDR_FLAG_STR_SIZE2:
185         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
186                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
187                 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
188                 if (len3 == 0) {
189                         as = talloc_strdup(ndr->current_mem_ctx, "");
190                 } else {
191                         ret = convert_string_talloc(ndr->current_mem_ctx,
192                                                     chset, CH_UNIX, 
193                                                     ndr->data+ndr->offset, 
194                                                     (len3 + c_len_term)*byte_mul,
195                                                     &as, False);
196                         if (ret == -1) {
197                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
198                                                       "Bad character conversion");
199                         }
200                 }
201                 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
202
203                 /* this is a way of detecting if a string is sent with the wrong
204                    termination */
205                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
206                         if (strlen(as) < (len3 + c_len_term)) {
207                                 DEBUG(6,("short string '%s'\n", as));
208                         }
209                 } else {
210                         if (strlen(as) == (len3 + c_len_term)) {
211                                 DEBUG(6,("long string '%s'\n", as));
212                         }
213                 }
214                 *s = as;
215                 break;
216
217         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
218                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
219                 NDR_PULL_NEED_BYTES(ndr, len3);
220                 if (len3 == 0) {
221                         as = talloc_strdup(ndr->current_mem_ctx, "");
222                 } else {
223                         ret = convert_string_talloc(ndr->current_mem_ctx,
224                                                     chset, CH_UNIX, 
225                                                     ndr->data+ndr->offset, 
226                                                     len3, &as, False);
227                         if (ret == -1) {
228                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
229                                                       "Bad character conversion");
230                         }
231                 }
232                 NDR_CHECK(ndr_pull_advance(ndr, len3));
233                 *s = as;
234                 break;
235
236         case LIBNDR_FLAG_STR_NULLTERM:
237                 if (byte_mul == 1) {
238                         len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
239                 } else {
240                         len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
241                 }
242                 ret = convert_string_talloc(ndr->current_mem_ctx,
243                                             chset, CH_UNIX, 
244                                             ndr->data+ndr->offset, 
245                                             len1, &as, False);
246                 if (ret == -1) {
247                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
248                                               "Bad character conversion");
249                 }
250                 NDR_CHECK(ndr_pull_advance(ndr, len1));
251                 *s = as;
252                 break;
253
254         case LIBNDR_FLAG_STR_FIXLEN15:
255         case LIBNDR_FLAG_STR_FIXLEN32:
256                 len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
257                 NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
258                 ret = convert_string_talloc(ndr->current_mem_ctx,
259                                             chset, CH_UNIX, 
260                                             ndr->data+ndr->offset, 
261                                             len1*byte_mul, &as, False);
262                 if (ret == -1) {
263                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
264                                               "Bad character conversion");
265                 }
266                 NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
267                 *s = as;
268                 break;
269
270         default:
271                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
272                                       ndr->flags & LIBNDR_STRING_FLAGS);
273         }
274
275         return NT_STATUS_OK;
276 }
277
278
279 /**
280   push a general string onto the wire
281 */
282 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
283 {
284         ssize_t s_len, c_len, d_len;
285         charset_t chset = CH_UCS2;
286         unsigned flags = ndr->flags;
287         unsigned byte_mul = 2;
288         uint8_t *dest = NULL;
289
290         if (!(ndr_flags & NDR_SCALARS)) {
291                 return NT_STATUS_OK;
292         }
293
294         SMB_ASSERT(!NDR_BE(ndr));
295         
296         s_len = s?strlen(s):0;
297
298         if (flags & LIBNDR_FLAG_STR_ASCII) {
299                 chset = CH_DOS;
300                 byte_mul = 1;
301                 flags &= ~LIBNDR_FLAG_STR_ASCII;
302         }
303
304         if (flags & LIBNDR_FLAG_STR_UTF8) {
305                 chset = CH_UTF8;
306                 byte_mul = 1;
307                 flags &= ~LIBNDR_FLAG_STR_UTF8;
308         }
309
310         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
311
312         if (!(flags & 
313               (LIBNDR_FLAG_STR_NOTERM |
314                LIBNDR_FLAG_STR_FIXLEN15 |
315                LIBNDR_FLAG_STR_FIXLEN32))) {
316                 s_len++;
317         }
318         d_len = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, &dest,
319                                       False);
320         if (d_len == -1) {
321                 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
322                                       "Bad character conversion");
323         }
324
325         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
326                 c_len = d_len;
327                 flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
328         } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
329                 c_len = (d_len / byte_mul)-1;
330                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
331         } else {
332                 c_len = d_len / byte_mul;
333         }
334
335         switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
336         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
337                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
338                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
339                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
340                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
341                 break;
342
343         case LIBNDR_FLAG_STR_LEN4:
344                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
345                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
346                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
347                 break;
348
349         case LIBNDR_FLAG_STR_SIZE4:
350                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
351                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
352                 break;
353
354         case LIBNDR_FLAG_STR_SIZE2:
355                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
356                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
357                 break;
358
359         case LIBNDR_FLAG_STR_NULLTERM:
360                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
361                 break;
362
363         case LIBNDR_FLAG_STR_FIXLEN15:
364         case LIBNDR_FLAG_STR_FIXLEN32: {
365                 ssize_t fix_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
366                 uint32_t pad_len = fix_len - d_len;
367                 if (d_len > fix_len) {
368                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
369                                               "Bad character conversion");
370                 }
371                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
372                 if (pad_len != 0) {
373                         NDR_CHECK(ndr_push_zero(ndr, pad_len));
374                 }
375                 break;
376         }
377
378         default:
379                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
380                                       ndr->flags & LIBNDR_STRING_FLAGS);
381         }
382
383         talloc_free(dest);
384
385         return NT_STATUS_OK;
386 }
387
388 /**
389   push a general string onto the wire
390 */
391 size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
392 {
393         size_t c_len;
394         unsigned flags = ndr->flags;
395         unsigned byte_mul = 2;
396         unsigned c_len_term = 1;
397
398         if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
399                 return 32;
400         }
401         if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
402                 return 15;
403         }
404         
405         c_len = s?strlen(s):0;
406
407         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
408                 byte_mul = 1;
409         }
410
411         if (flags & LIBNDR_FLAG_STR_NOTERM) {
412                 c_len_term = 0;
413         }
414
415         c_len = c_len + c_len_term;
416
417         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
418                 c_len = c_len * byte_mul;
419         }
420
421         return c_len;
422 }
423
424 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
425 {
426         if (s) {
427                 ndr->print(ndr, "%-25s: '%s'", name, s);
428         } else {
429                 ndr->print(ndr, "%-25s: NULL", name);
430         }
431 }
432
433 uint32_t ndr_size_string(int ret, const char * const* string, int flags) 
434 {
435         /* FIXME: Is this correct for all strings ? */
436         if(!(*string)) return ret;
437         return ret+strlen(*string)+1;
438 }
439
440 /**
441   pull a general string array from the wire
442 */
443 NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
444 {
445         const char **a = *_a;
446         uint32_t count;
447
448         if (!(ndr_flags & NDR_SCALARS)) {
449                 return NT_STATUS_OK;
450         }
451
452         for (count = 0;; count++) {
453                 TALLOC_CTX *tmp_ctx;
454                 const char *s = NULL;
455                 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
456                 NT_STATUS_HAVE_NO_MEMORY(a);
457                 a[count]   = NULL;
458                 a[count+1]   = NULL;
459
460                 tmp_ctx = ndr->current_mem_ctx;
461                 ndr->current_mem_ctx = a;
462                 NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
463                 ndr->current_mem_ctx = tmp_ctx;
464                 if (strcmp("", s)==0) {
465                         a[count] = NULL;
466                         break;
467                 } else {
468                         a[count] = s;
469                 }
470         }
471
472         *_a =a;
473         return NT_STATUS_OK;
474 }
475
476 /**
477   push a general string array onto the wire
478 */
479 NTSTATUS ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
480 {
481         uint32_t count;
482
483         if (!(ndr_flags & NDR_SCALARS)) {
484                 return NT_STATUS_OK;
485         }
486
487         for (count = 0; a && a[count]; count++) {
488                 NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
489         }
490
491         NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
492
493         return NT_STATUS_OK;
494 }
495
496 void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
497 {
498         uint32_t count;
499         uint32_t i;
500
501         for (count = 0; a && a[count]; count++) {}
502
503         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
504         ndr->depth++;
505         for (i=0;i<count;i++) {
506                 char *idx=NULL;
507                 asprintf(&idx, "[%d]", i);
508                 if (idx) {
509                         ndr_print_string(ndr, idx, a[i]);
510                         free(idx);
511                 }
512         }
513         ndr->depth--;
514 }
515
516 /**
517  * Return number of elements in a string including the last (zeroed) element 
518  */
519 uint32_t ndr_string_length(const void *_var, uint32_t element_size)
520 {
521         uint32_t i;
522         uint8_t zero[4] = {0,0,0,0};
523         const char *var = (const char *)_var;
524
525         for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
526
527         return i+1;
528 }
529
530 NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
531 {
532         uint32_t i;
533         struct ndr_pull_save save_offset;
534
535         ndr_pull_save(ndr, &save_offset);
536         ndr_pull_advance(ndr, (count - 1) * element_size);
537         NDR_PULL_NEED_BYTES(ndr, element_size);
538
539         for (i = 0; i < element_size; i++) {
540                  if (ndr->data[ndr->offset+i] != 0) {
541                         ndr_pull_restore(ndr, &save_offset);
542
543                         return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
544                  }
545         }
546
547         ndr_pull_restore(ndr, &save_offset);
548
549         return NT_STATUS_OK;
550 }
551
552 NTSTATUS ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, int chset)
553 {
554         int ret;
555         if (length == 0) {
556                 *var = talloc_strdup(ndr->current_mem_ctx, "");
557                 return NT_STATUS_OK;
558         }
559
560         SMB_ASSERT (!NDR_BE(ndr) || chset != CH_UCS2);
561
562         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
563
564         ret = convert_string_talloc(ndr->current_mem_ctx,
565                                     chset, CH_UNIX, 
566                                     ndr->data+ndr->offset, 
567                                     length*byte_mul,
568                                     var, False);
569         if (ret == -1) {
570                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
571                                       "Bad character conversion");
572         }
573         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
574
575         return NT_STATUS_OK;
576 }
577
578 NTSTATUS ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var,
579                           uint32_t length, uint8_t byte_mul, charset_t chset)
580 {
581         ssize_t ret, required;
582
583         SMB_ASSERT(!NDR_BE(ndr) || chset != CH_UCS2);
584
585         required = byte_mul * length;
586         
587         NDR_PUSH_NEED_BYTES(ndr, required);
588         ret = convert_string(CH_UNIX, chset, 
589                              var, strlen(var),
590                              ndr->data+ndr->offset, required, False);
591         if (ret == -1) {
592                 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
593                                       "Bad character conversion");
594         }
595
596         /* Make sure the remaining part of the string is filled with zeroes */
597         if (ret < required) {
598                 memset(ndr->data+ndr->offset+ret, 0, required-ret);
599         }
600
601         ndr->offset += required;
602
603         return NT_STATUS_OK;
604 }
605
606 /* Return number of elements in a string in the specified charset */
607 uint32_t ndr_charset_length(const void *var, int chset)
608 {
609         /* FIXME: Treat special chars special here, taking chset into account */
610         /* Also include 0 byte */
611         return strlen((const char *)var)+1;
612 }