dda9f754b1155775b78191ba638cc8310476f907
[kai/samba.git] / source4 / lib / charset / charcnv.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Character set conversion Extensions
4    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5    Copyright (C) Andrew Tridgell 2001
6    Copyright (C) Simo Sorce 2001
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 "includes.h"
23 #include "system/iconv.h"
24 #include "param/param.h"
25
26 /**
27  * @file
28  *
29  * @brief Character-set conversion routines built on our iconv.
30  * 
31  * @note Samba's internal character set (at least in the 3.0 series)
32  * is always the same as the one for the Unix filesystem.  It is
33  * <b>not</b> necessarily UTF-8 and may be different on machines that
34  * need i18n filenames to be compatible with Unix software.  It does
35  * have to be a superset of ASCII.  All multibyte sequences must start
36  * with a byte with the high bit set.
37  *
38  * @sa lib/iconv.c
39  */
40
41 char *unix_charset = NULL;
42 char *dos_charset = NULL;
43 char *display_charset = NULL;
44
45 /**
46  * Return the name of a charset to give to iconv().
47  **/
48 static const char *charset_name(charset_t ch)
49 {
50         switch (ch) {
51         case CH_UTF16: return "UTF-16LE";
52         case CH_UNIX: return unix_charset;
53         case CH_DOS: return dos_charset;
54         case CH_DISPLAY: return display_charset;
55         case CH_UTF8: return "UTF8";
56         case CH_UTF16BE: return "UTF-16BE";
57         default:
58         return "ASCII";
59         }
60 }
61
62 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
63
64 /**
65  re-initialize iconv conversion descriptors
66 **/
67 _PUBLIC_ void init_iconv(void)
68 {
69         unsigned c1, c2;
70         for (c1=0;c1<NUM_CHARSETS;c1++) {
71                 for (c2=0;c2<NUM_CHARSETS;c2++) {
72                         if (conv_handles[c1][c2] != NULL) {
73                                 if (conv_handles[c1][c2] != (smb_iconv_t)-1) {
74                                         smb_iconv_close(conv_handles[c1][c2]);
75                                 }
76                                 conv_handles[c1][c2] = NULL;
77                         }
78                 }
79         }
80
81 }
82
83 /*
84   on-demand initialisation of conversion handles
85 */
86 static smb_iconv_t get_conv_handle(charset_t from, charset_t to)
87 {
88         const char *n1, *n2;
89         static int initialised;
90         /* auto-free iconv memory on exit so valgrind reports are easier
91            to look at */
92         if (initialised == 0) {
93                 initialised = 1;
94                 
95 #ifdef LC_ALL
96                 /* we set back the locale to C to get ASCII-compatible
97                    toupper/lower functions.  For now we do not need
98                    any other POSIX localisations anyway. When we
99                    should really need localized string functions one
100                    day we need to write our own ascii_tolower etc.
101                 */
102                 setlocale(LC_ALL, "C");
103 #endif
104
105                 atexit(init_iconv);
106         }
107
108         if (conv_handles[from][to]) {
109                 return conv_handles[from][to];
110         }
111
112         n1 = charset_name(from);
113         n2 = charset_name(to);
114
115         conv_handles[from][to] = smb_iconv_open(n2,n1);
116         
117         if (conv_handles[from][to] == (smb_iconv_t)-1) {
118                 if ((from == CH_DOS || to == CH_DOS) &&
119                     strcasecmp(charset_name(CH_DOS), "ASCII") != 0) {
120                         DEBUG(0,("dos charset '%s' unavailable - using ASCII\n",
121                                  charset_name(CH_DOS)));
122                         lp_set_cmdline("dos charset", "ASCII");
123
124                         n1 = charset_name(from);
125                         n2 = charset_name(to);
126                         
127                         conv_handles[from][to] = smb_iconv_open(n2,n1);
128                 }
129         }
130
131         return conv_handles[from][to];
132 }
133
134
135 /**
136  * Convert string from one encoding to another, making error checking etc
137  *
138  * @param src pointer to source string (multibyte or singlebyte)
139  * @param srclen length of the source string in bytes
140  * @param dest pointer to destination string (multibyte or singlebyte)
141  * @param destlen maximal length allowed for string
142  * @returns the number of bytes occupied in the destination
143  **/
144 _PUBLIC_ ssize_t convert_string(charset_t from, charset_t to,
145                       void const *src, size_t srclen, 
146                       void *dest, size_t destlen)
147 {
148         size_t i_len, o_len;
149         size_t retval;
150         const char* inbuf = (const char*)src;
151         char* outbuf = (char*)dest;
152         smb_iconv_t descriptor;
153
154         if (srclen == (size_t)-1)
155                 srclen = strlen(src)+1;
156
157         descriptor = get_conv_handle(from, to);
158
159         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
160                 /* conversion not supported, use as is */
161                 size_t len = MIN(srclen,destlen);
162                 memcpy(dest,src,len);
163                 return len;
164         }
165
166         i_len=srclen;
167         o_len=destlen;
168         retval = smb_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
169         if(retval==(size_t)-1) {
170                 const char *reason;
171                 switch(errno) {
172                         case EINVAL:
173                                 reason="Incomplete multibyte sequence";
174                                 return -1;
175                         case E2BIG:
176                                 reason="No more room"; 
177                                 if (from == CH_UNIX) {
178                                         DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d - '%s'\n",
179                                                  charset_name(from), charset_name(to),
180                                                  (int)srclen, (int)destlen, 
181                                                  (const char *)src));
182                                 } else {
183                                         DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d\n",
184                                                  charset_name(from), charset_name(to),
185                                                  (int)srclen, (int)destlen));
186                                 }
187                                return -1;
188                         case EILSEQ:
189                                reason="Illegal multibyte sequence";
190                                return -1;
191                 }
192                 /* smb_panic(reason); */
193         }
194         return destlen-o_len;
195 }
196
197 /**
198  * Convert between character sets, allocating a new buffer using talloc for the result.
199  *
200  * @param srclen length of source buffer.
201  * @param dest always set at least to NULL
202  * @note -1 is not accepted for srclen.
203  *
204  * @returns Size in bytes of the converted string; or -1 in case of error.
205  **/
206
207 _PUBLIC_ ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
208                               void const *src, size_t srclen, void **dest)
209 {
210         size_t i_len, o_len, destlen;
211         size_t retval;
212         const char *inbuf = (const char *)src;
213         char *outbuf, *ob;
214         smb_iconv_t descriptor;
215
216         *dest = NULL;
217
218         if (src == NULL || srclen == (size_t)-1 || srclen == 0)
219                 return (size_t)-1;
220
221         descriptor = get_conv_handle(from, to);
222
223         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
224                 /* conversion not supported, return -1*/
225                 DEBUG(3, ("convert_string_talloc: conversion from %s to %s not supported!\n",
226                           charset_name(from), charset_name(to)));
227                 return -1;
228         }
229
230         /* it is _very_ rare that a conversion increases the size by
231            more than 3x */
232         destlen = srclen;
233         outbuf = NULL;
234 convert:
235         destlen = 2 + (destlen*3);
236         ob = talloc_realloc(ctx, outbuf, char, destlen);
237         if (!ob) {
238                 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
239                 talloc_free(outbuf);
240                 return (size_t)-1;
241         } else {
242                 outbuf = ob;
243         }
244
245         /* we give iconv 2 less bytes to allow us to terminate at the
246            end */
247         i_len = srclen;
248         o_len = destlen-2;
249         retval = smb_iconv(descriptor,
250                            &inbuf, &i_len,
251                            &outbuf, &o_len);
252         if(retval == (size_t)-1)                {
253                 const char *reason="unknown error";
254                 switch(errno) {
255                         case EINVAL:
256                                 reason="Incomplete multibyte sequence";
257                                 break;
258                         case E2BIG:
259                                 goto convert;           
260                         case EILSEQ:
261                                 reason="Illegal multibyte sequence";
262                                 break;
263                 }
264                 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
265                 talloc_free(ob);
266                 return (size_t)-1;
267         }
268         
269         destlen = (destlen-2) - o_len;
270
271         /* guarantee null termination in all charsets */
272         SSVAL(ob, destlen, 0);
273
274         *dest = ob;
275
276         return destlen;
277 }
278
279 /**
280  * Copy a string from a char* unix src to a dos codepage string destination.
281  *
282  * @return the number of bytes occupied by the string in the destination.
283  *
284  * @param flags can include
285  * <dl>
286  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
287  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
288  * </dl>
289  *
290  * @param dest_len the maximum length in bytes allowed in the
291  * destination.  If @p dest_len is -1 then no maximum is used.
292  **/
293 static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
294 {
295         size_t src_len;
296         ssize_t ret;
297
298         if (flags & STR_UPPER) {
299                 char *tmpbuf = strupper_talloc(NULL, src);
300                 if (tmpbuf == NULL) {
301                         return -1;
302                 }
303                 ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
304                 talloc_free(tmpbuf);
305                 return ret;
306         }
307
308         src_len = strlen(src);
309
310         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
311                 src_len++;
312
313         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
314 }
315
316 /**
317  * Copy a string from a unix char* src to an ASCII destination,
318  * allocating a buffer using talloc().
319  *
320  * @param dest always set at least to NULL 
321  *
322  * @returns The number of bytes occupied by the string in the destination
323  *         or -1 in case of error.
324  **/
325 _PUBLIC_ ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
326 {
327         size_t src_len = strlen(src)+1;
328         *dest = NULL;
329         return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest);
330 }
331
332
333 /**
334  * Copy a string from a dos codepage source to a unix char* destination.
335  *
336  * The resulting string in "dest" is always null terminated.
337  *
338  * @param flags can have:
339  * <dl>
340  * <dt>STR_TERMINATE</dt>
341  * <dd>STR_TERMINATE means the string in @p src
342  * is null terminated, and src_len is ignored.</dd>
343  * </dl>
344  *
345  * @param src_len is the length of the source area in bytes.
346  * @returns the number of bytes occupied by the string in @p src.
347  **/
348 static ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
349 {
350         size_t ret;
351
352         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
353                 if (src_len == (size_t)-1) {
354                         src_len = strlen(src) + 1;
355                 } else {
356                         size_t len = strnlen(src, src_len);
357                         if (len < src_len)
358                                 len++;
359                         src_len = len;
360                 }
361         }
362
363         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
364
365         if (dest_len)
366                 dest[MIN(ret, dest_len-1)] = 0;
367
368         return src_len;
369 }
370
371 /**
372  * Copy a string from a char* src to a unicode destination.
373  *
374  * @returns the number of bytes occupied by the string in the destination.
375  *
376  * @param flags can have:
377  *
378  * <dl>
379  * <dt>STR_TERMINATE <dd>means include the null termination.
380  * <dt>STR_UPPER     <dd>means uppercase in the destination.
381  * <dt>STR_NOALIGN   <dd>means don't do alignment.
382  * </dl>
383  *
384  * @param dest_len is the maximum length allowed in the
385  * destination. If dest_len is -1 then no maxiumum is used.
386  **/
387 static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags)
388 {
389         size_t len=0;
390         size_t src_len = strlen(src);
391         size_t ret;
392
393         if (flags & STR_UPPER) {
394                 char *tmpbuf = strupper_talloc(NULL, src);
395                 if (tmpbuf == NULL) {
396                         return -1;
397                 }
398                 ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
399                 talloc_free(tmpbuf);
400                 return ret;
401         }
402
403         if (flags & STR_TERMINATE)
404                 src_len++;
405
406         if (ucs2_align(NULL, dest, flags)) {
407                 *(char *)dest = 0;
408                 dest = (void *)((char *)dest + 1);
409                 if (dest_len) dest_len--;
410                 len++;
411         }
412
413         /* ucs2 is always a multiple of 2 bytes */
414         dest_len &= ~1;
415
416         ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
417         if (ret == (size_t)-1) {
418                 return 0;
419         }
420
421         len += ret;
422
423         return len;
424 }
425
426
427 /**
428  * Copy a string from a unix char* src to a UCS2 destination,
429  * allocating a buffer using talloc().
430  *
431  * @param dest always set at least to NULL 
432  *
433  * @returns The number of bytes occupied by the string in the destination
434  *         or -1 in case of error.
435  **/
436 _PUBLIC_ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
437 {
438         size_t src_len = strlen(src)+1;
439         *dest = NULL;
440         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest);
441 }
442
443
444 /**
445  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
446  *
447  * @param dest always set at least to NULL 
448  *
449  * @returns The number of bytes occupied by the string in the destination
450  **/
451
452 _PUBLIC_ ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
453 {
454         size_t src_len = strlen(src)+1;
455         *dest = NULL;
456         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
457 }
458
459 /**
460  Copy a string from a ucs2 source to a unix char* destination.
461  Flags can have:
462   STR_TERMINATE means the string in src is null terminated.
463   STR_NOALIGN   means don't try to align.
464  if STR_TERMINATE is set then src_len is ignored if it is -1.
465  src_len is the length of the source area in bytes
466  Return the number of bytes occupied by the string in src.
467  The resulting string in "dest" is always null terminated.
468 **/
469
470 static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
471 {
472         size_t ret;
473
474         if (ucs2_align(NULL, src, flags)) {
475                 src = (const void *)((const char *)src + 1);
476                 if (src_len > 0)
477                         src_len--;
478         }
479
480         if (flags & STR_TERMINATE) {
481                 if (src_len == (size_t)-1) {
482                         src_len = utf16_len(src);
483                 } else {
484                         src_len = utf16_len_n(src, src_len);
485                 }
486         }
487
488         /* ucs2 is always a multiple of 2 bytes */
489         if (src_len != (size_t)-1)
490                 src_len &= ~1;
491         
492         ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len);
493         if (dest_len)
494                 dest[MIN(ret, dest_len-1)] = 0;
495
496         return src_len;
497 }
498
499 /**
500  * Copy a string from a ASCII src to a unix char * destination, allocating a buffer using talloc
501  *
502  * @param dest always set at least to NULL 
503  *
504  * @returns The number of bytes occupied by the string in the destination
505  **/
506
507 _PUBLIC_ ssize_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
508 {
509         size_t src_len = strlen(src)+1;
510         *dest = NULL;
511         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest);
512 }
513
514 /**
515  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
516  *
517  * @param dest always set at least to NULL 
518  *
519  * @returns The number of bytes occupied by the string in the destination
520  **/
521
522 _PUBLIC_ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src)
523 {
524         size_t src_len = utf16_len(src);
525         *dest = NULL;
526         return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest);
527 }
528
529 /**
530  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
531  *
532  * @param dest always set at least to NULL 
533  *
534  * @returns The number of bytes occupied by the string in the destination
535  **/
536
537 _PUBLIC_ ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
538 {
539         size_t src_len = strlen(src)+1;
540         *dest = NULL;
541         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
542 }
543
544 /**
545  Copy a string from a char* src to a unicode or ascii
546  dos codepage destination choosing unicode or ascii based on the 
547  flags in the SMB buffer starting at base_ptr.
548  Return the number of bytes occupied by the string in the destination.
549  flags can have:
550   STR_TERMINATE means include the null termination.
551   STR_UPPER     means uppercase in the destination.
552   STR_ASCII     use ascii even with unicode packet.
553   STR_NOALIGN   means don't do alignment.
554  dest_len is the maximum length allowed in the destination. If dest_len
555  is -1 then no maxiumum is used.
556 **/
557
558 _PUBLIC_ ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
559 {
560         if (flags & STR_ASCII) {
561                 return push_ascii(dest, src, dest_len, flags);
562         } else if (flags & STR_UNICODE) {
563                 return push_ucs2(dest, src, dest_len, flags);
564         } else {
565                 smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set");
566                 return -1;
567         }
568 }
569
570
571 /**
572  Copy a string from a unicode or ascii source (depending on
573  the packet flags) to a char* destination.
574  Flags can have:
575   STR_TERMINATE means the string in src is null terminated.
576   STR_UNICODE   means to force as unicode.
577   STR_ASCII     use ascii even with unicode packet.
578   STR_NOALIGN   means don't do alignment.
579  if STR_TERMINATE is set then src_len is ignored is it is -1
580  src_len is the length of the source area in bytes.
581  Return the number of bytes occupied by the string in src.
582  The resulting string in "dest" is always null terminated.
583 **/
584
585 _PUBLIC_ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
586 {
587         if (flags & STR_ASCII) {
588                 return pull_ascii(dest, src, dest_len, src_len, flags);
589         } else if (flags & STR_UNICODE) {
590                 return pull_ucs2(dest, src, dest_len, src_len, flags);
591         } else {
592                 smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set");
593                 return -1;
594         }
595 }
596
597
598 /*
599   return the unicode codepoint for the next multi-byte CH_UNIX character
600   in the string
601
602   also return the number of bytes consumed (which tells the caller
603   how many bytes to skip to get to the next CH_UNIX character)
604
605   return INVALID_CODEPOINT if the next character cannot be converted
606 */
607 _PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size)
608 {
609         /* it cannot occupy more than 4 bytes in UTF16 format */
610         uint8_t buf[4];
611         smb_iconv_t descriptor;
612         size_t ilen_orig;
613         size_t ilen;
614         size_t olen;
615         char *outbuf;
616
617         if ((str[0] & 0x80) == 0) {
618                 *size = 1;
619                 return (codepoint_t)str[0];
620         }
621
622         /* we assume that no multi-byte character can take
623            more than 5 bytes. This is OK as we only
624            support codepoints up to 1M */
625         ilen_orig = strnlen(str, 5);
626         ilen = ilen_orig;
627
628         descriptor = get_conv_handle(CH_UNIX, CH_UTF16);
629         if (descriptor == (smb_iconv_t)-1) {
630                 *size = 1;
631                 return INVALID_CODEPOINT;
632         }
633
634         /* this looks a little strange, but it is needed to cope
635            with codepoints above 64k */
636         olen = 2;
637         outbuf = (char *)buf;
638         smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
639         if (olen == 2) {
640                 olen = 4;
641                 outbuf = (char *)buf;
642                 smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
643                 if (olen == 4) {
644                         /* we didn't convert any bytes */
645                         *size = 1;
646                         return INVALID_CODEPOINT;
647                 }
648                 olen = 4 - olen;
649         } else {
650                 olen = 2 - olen;
651         }
652
653         *size = ilen_orig - ilen;
654
655         if (olen == 2) {
656                 return (codepoint_t)SVAL(buf, 0);
657         }
658         if (olen == 4) {
659                 /* decode a 4 byte UTF16 character manually */
660                 return (codepoint_t)0x10000 + 
661                         (buf[2] | ((buf[3] & 0x3)<<8) | 
662                          (buf[0]<<10) | ((buf[1] & 0x3)<<18));
663         }
664
665         /* no other length is valid */
666         return INVALID_CODEPOINT;
667 }
668
669 /*
670   push a single codepoint into a CH_UNIX string the target string must
671   be able to hold the full character, which is guaranteed if it is at
672   least 5 bytes in size. The caller may pass less than 5 bytes if they
673   are sure the character will fit (for example, you can assume that
674   uppercase/lowercase of a character will not add more than 1 byte)
675
676   return the number of bytes occupied by the CH_UNIX character, or
677   -1 on failure
678 */
679 _PUBLIC_ ssize_t push_codepoint(char *str, codepoint_t c)
680 {
681         smb_iconv_t descriptor;
682         uint8_t buf[4];
683         size_t ilen, olen;
684         const char *inbuf;
685         
686         if (c < 128) {
687                 *str = c;
688                 return 1;
689         }
690
691         descriptor = get_conv_handle(CH_UTF16, CH_UNIX);
692         if (descriptor == (smb_iconv_t)-1) {
693                 return -1;
694         }
695
696         if (c < 0x10000) {
697                 ilen = 2;
698                 olen = 5;
699                 inbuf = (char *)buf;
700                 SSVAL(buf, 0, c);
701                 smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);
702                 if (ilen != 0) {
703                         return -1;
704                 }
705                 return 5 - olen;
706         }
707
708         c -= 0x10000;
709
710         buf[0] = (c>>10) & 0xFF;
711         buf[1] = (c>>18) | 0xd8;
712         buf[2] = c & 0xFF;
713         buf[3] = ((c>>8) & 0x3) | 0xdc;
714
715         ilen = 4;
716         olen = 5;
717         inbuf = (char *)buf;
718
719         smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);
720         if (ilen != 0) {
721                 return -1;
722         }
723         return 5 - olen;
724 }