use strnlen to prevent coredumps
[kai/samba.git] / source3 / lib / util_str.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    
5    Copyright (C) Andrew Tridgell 1992-2001
6    Copyright (C) Simo Sorce      2001-2002
7    Copyright (C) Martin Pool     2003
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 /**
27  * @file
28  * @brief String utilities.
29  **/
30
31 /**
32  * Get the next token from a string, return False if none found.
33  * Handles double-quotes.
34  * 
35  * Based on a routine by GJC@VILLAGE.COM. 
36  * Extensively modified by Andrew.Tridgell@anu.edu.au
37  **/
38 BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
39 {
40         const char *s;
41         BOOL quoted;
42         size_t len=1;
43
44         if (!ptr)
45                 return(False);
46
47         s = *ptr;
48
49         /* default to simple separators */
50         if (!sep)
51                 sep = " \t\n\r";
52
53         /* find the first non sep char */
54         while (*s && strchr_m(sep,*s))
55                 s++;
56         
57         /* nothing left? */
58         if (! *s)
59                 return(False);
60         
61         /* copy over the token */
62         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
63                 if (*s == '\"') {
64                         quoted = !quoted;
65                 } else {
66                         len++;
67                         *buff++ = *s;
68                 }
69         }
70         
71         *ptr = (*s) ? s+1 : s;  
72         *buff = 0;
73         
74         return(True);
75 }
76
77 /**
78 This is like next_token but is not re-entrant and "remembers" the first 
79 parameter so you can pass NULL. This is useful for user interface code
80 but beware the fact that it is not re-entrant!
81 **/
82
83 static const char *last_ptr=NULL;
84
85 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
86 {
87         BOOL ret;
88         if (!ptr)
89                 ptr = (const char **)&last_ptr;
90
91         ret = next_token(ptr, buff, sep, bufsize);
92         last_ptr = *ptr;
93         return ret;     
94 }
95
96 static uint16 tmpbuf[sizeof(pstring)];
97
98 void set_first_token(char *ptr)
99 {
100         last_ptr = ptr;
101 }
102
103 /**
104  Convert list of tokens to array; dependent on above routine.
105  Uses last_ptr from above - bit of a hack.
106 **/
107
108 char **toktocliplist(int *ctok, const char *sep)
109 {
110         char *s=last_ptr;
111         int ictok=0;
112         char **ret, **iret;
113
114         if (!sep)
115                 sep = " \t\n\r";
116
117         while(*s && strchr_m(sep,*s))
118                 s++;
119
120         /* nothing left? */
121         if (!*s)
122                 return(NULL);
123
124         do {
125                 ictok++;
126                 while(*s && (!strchr_m(sep,*s)))
127                         s++;
128                 while(*s && strchr_m(sep,*s))
129                         *s++=0;
130         } while(*s);
131         
132         *ctok=ictok;
133         s=last_ptr;
134         
135         if (!(ret=iret=malloc(ictok*sizeof(char *))))
136                 return NULL;
137         
138         while(ictok--) {    
139                 *iret++=s;
140                 while(*s++)
141                         ;
142                 while(!*s)
143                         s++;
144         }
145
146         return ret;
147 }
148
149 /**
150  * Case insensitive string compararison.
151  *
152  * iconv does not directly give us a way to compare strings in
153  * arbitrary unix character sets -- all we can is convert and then
154  * compare.  This is expensive.
155  *
156  * As an optimization, we do a first pass that considers only the
157  * prefix of the strings that is entirely 7-bit.  Within this, we
158  * check whether they have the same value.
159  *
160  * Hopefully this will often give the answer without needing to copy.
161  * In particular it should speed comparisons to literal ascii strings
162  * or comparisons of strings that are "obviously" different.
163  *
164  * If we find a non-ascii character we fall back to converting via
165  * iconv.
166  *
167  * This should never be slower than convering the whole thing, and
168  * often faster.
169  *
170  * A different optimization would be to compare for bitwise equality
171  * in the binary encoding.  (It would be possible thought hairy to do
172  * both simultaneously.)  But in that case if they turn out to be
173  * different, we'd need to restart the whole thing.
174  *
175  * Even better is to implement strcasecmp for each encoding and use a
176  * function pointer. 
177  **/
178 int StrCaseCmp(const char *s, const char *t)
179 {
180
181         const char * ps, * pt;
182         pstring buf1, buf2;
183
184         for (ps = s, pt = t; ; ps++, pt++) {
185                 char us, ut;
186
187                 if (!*ps && !*pt)
188                         return 0; /* both ended */
189                 else if (!*ps)
190                         return -1; /* s is a prefix */
191                 else if (!*pt)
192                         return +1; /* t is a prefix */
193                 else if ((*ps & 0x80) || (*pt & 0x80))
194                         /* not ascii anymore, do it the hard way from here on in */
195                         break;
196
197                 us = toupper(*ps);
198                 ut = toupper(*pt);
199                 if (us == ut)
200                         continue;
201                 else if (us < ut)
202                         return -1;
203                 else if (us > ut)
204                         return +1;
205         }
206
207         /* TODO: Don't do this with a fixed-length buffer.  This could
208          * still be much more efficient. */
209         /* TODO: Hardcode a char-by-char comparison for UTF-8, which
210          * can be much faster. */
211         /* TODO: Test case for this! */
212
213         unix_strupper(ps, strlen(ps)+1, buf1, sizeof(buf1));
214         unix_strupper(pt, strlen(pt)+1, buf2, sizeof(buf2));
215
216         return strcmp(buf1, buf2);
217 }
218
219
220 /**
221  Case insensitive string compararison, length limited.
222 **/
223 int StrnCaseCmp(const char *s, const char *t, size_t n)
224 {
225         pstring buf1, buf2;
226         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
227         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
228         return strncmp(buf1,buf2,n);
229 }
230
231 /**
232  * Compare 2 strings.
233  *
234  * @note The comparison is case-insensitive.
235  **/
236 BOOL strequal(const char *s1, const char *s2)
237 {
238         if (s1 == s2)
239                 return(True);
240         if (!s1 || !s2)
241                 return(False);
242   
243         return(StrCaseCmp(s1,s2)==0);
244 }
245
246 /**
247  * Compare 2 strings up to and including the nth char.
248  *
249  * @note The comparison is case-insensitive.
250  **/
251 BOOL strnequal(const char *s1,const char *s2,size_t n)
252 {
253   if (s1 == s2)
254           return(True);
255   if (!s1 || !s2 || !n)
256           return(False);
257   
258   return(StrnCaseCmp(s1,s2,n)==0);
259 }
260
261 /**
262  Compare 2 strings (case sensitive).
263 **/
264
265 BOOL strcsequal(const char *s1,const char *s2)
266 {
267   if (s1 == s2)
268           return(True);
269   if (!s1 || !s2)
270           return(False);
271   
272   return(strcmp(s1,s2)==0);
273 }
274
275 /**
276 Do a case-insensitive, whitespace-ignoring string compare.
277 **/
278
279 int strwicmp(const char *psz1, const char *psz2)
280 {
281         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
282         /* appropriate value. */
283         if (psz1 == psz2)
284                 return (0);
285         else if (psz1 == NULL)
286                 return (-1);
287         else if (psz2 == NULL)
288                 return (1);
289
290         /* sync the strings on first non-whitespace */
291         while (1) {
292                 while (isspace((int)*psz1))
293                         psz1++;
294                 while (isspace((int)*psz2))
295                         psz2++;
296                 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
297                     || *psz2 == '\0')
298                         break;
299                 psz1++;
300                 psz2++;
301         }
302         return (*psz1 - *psz2);
303 }
304
305
306 /**
307  Convert a string to upper case, but don't modify it.
308 **/
309
310 char *strupper_static(const char *s)
311 {
312         static pstring str;
313
314         pstrcpy(str, s);
315         strupper(str);
316
317         return str;
318 }
319
320 /**
321  Convert a string to "normal" form.
322 **/
323
324 void strnorm(char *s)
325 {
326         extern int case_default;
327         if (case_default == CASE_UPPER)
328                 strupper(s);
329         else
330                 strlower(s);
331 }
332
333 /**
334  Check if a string is in "normal" case.
335 **/
336
337 BOOL strisnormal(const char *s)
338 {
339         extern int case_default;
340         if (case_default == CASE_UPPER)
341                 return(!strhaslower(s));
342         
343         return(!strhasupper(s));
344 }
345
346
347 /**
348  String replace.
349  NOTE: oldc and newc must be 7 bit characters
350 **/
351
352 void string_replace(char *s,char oldc,char newc)
353 {
354         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
355         string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
356         pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
357 }
358
359 /**
360  Skip past some strings in a buffer.
361 **/
362
363 char *skip_string(char *buf,size_t n)
364 {
365         while (n--)
366                 buf += strlen(buf) + 1;
367         return(buf);
368 }
369
370 /**
371  Count the number of characters in a string. Normally this will
372  be the same as the number of bytes in a string for single byte strings,
373  but will be different for multibyte.
374 **/
375
376 size_t str_charnum(const char *s)
377 {
378         uint16 tmpbuf2[sizeof(pstring)];
379         push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
380         return strlen_w(tmpbuf2);
381 }
382
383 /**
384  Count the number of characters in a string. Normally this will
385  be the same as the number of bytes in a string for single byte strings,
386  but will be different for multibyte.
387 **/
388
389 size_t str_ascii_charnum(const char *s)
390 {
391         pstring tmpbuf2;
392         push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
393         return strlen(tmpbuf2);
394 }
395
396 /**
397  Trim the specified elements off the front and back of a string.
398 **/
399
400 BOOL trim_string(char *s,const char *front,const char *back)
401 {
402         BOOL ret = False;
403         size_t front_len;
404         size_t back_len;
405         size_t len;
406
407         /* Ignore null or empty strings. */
408         if (!s || (s[0] == '\0'))
409                 return False;
410
411         front_len       = front? strlen(front) : 0;
412         back_len        = back? strlen(back) : 0;
413
414         len = strlen(s);
415
416         if (front_len) {
417                 while (len && strncmp(s, front, front_len)==0) {
418                         memcpy(s, s+front_len, (len-front_len)+1);
419                         len -= front_len;
420                         ret=True;
421                 }
422         }
423         
424         if (back_len) {
425                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
426                         s[len-back_len]='\0';
427                         len -= back_len;
428                         ret=True;
429                 }
430         }
431         return ret;
432 }
433
434 /**
435  Does a string have any uppercase chars in it?
436 **/
437
438 BOOL strhasupper(const char *s)
439 {
440         smb_ucs2_t *ptr;
441         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
442         for(ptr=tmpbuf;*ptr;ptr++)
443                 if(isupper_w(*ptr))
444                         return True;
445         return(False);
446 }
447
448 /**
449  Does a string have any lowercase chars in it?
450 **/
451
452 BOOL strhaslower(const char *s)
453 {
454         smb_ucs2_t *ptr;
455         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
456         for(ptr=tmpbuf;*ptr;ptr++)
457                 if(islower_w(*ptr))
458                         return True;
459         return(False);
460 }
461
462 /**
463  Find the number of 'c' chars in a string
464 **/
465
466 size_t count_chars(const char *s,char c)
467 {
468         smb_ucs2_t *ptr;
469         int count;
470         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
471         for(count=0,ptr=tmpbuf;*ptr;ptr++)
472                 if(*ptr==UCS2_CHAR(c))
473                         count++;
474         return(count);
475 }
476
477 /**
478  Safe string copy into a known length string. maxlength does not
479  include the terminating zero.
480 **/
481
482 char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_t maxlength)
483 {
484         size_t len;
485
486         if (!dest) {
487                 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
488                 return NULL;
489         }
490
491         clobber_region(fn,line,dest, maxlength+1);
492
493         if (!src) {
494                 *dest = 0;
495                 return dest;
496         }  
497
498         len = strnlen(src, maxlength+1);
499
500         if (len > maxlength) {
501                 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
502                          (unsigned int)(len-maxlength), len, maxlength, src));
503                 len = maxlength;
504         }
505       
506         memmove(dest, src, len);
507         dest[len] = 0;
508         return dest;
509 }  
510
511 /**
512  Safe string cat into a string. maxlength does not
513  include the terminating zero.
514 **/
515 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
516 {
517         size_t src_len, dest_len;
518
519         if (!dest) {
520                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
521                 return NULL;
522         }
523
524         if (!src)
525                 return dest;
526         
527         src_len = strnlen(src, maxlength + 1);
528         dest_len = strnlen(dest, maxlength + 1);
529
530         clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
531
532         if (src_len + dest_len > maxlength) {
533                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
534                          (int)(src_len + dest_len - maxlength), src));
535                 if (maxlength > dest_len) {
536                         memcpy(&dest[dest_len], src, maxlength - dest_len);
537                 }
538                 dest[maxlength] = 0;
539                 return NULL;
540         }
541
542         memcpy(&dest[dest_len], src, src_len);
543         dest[dest_len + src_len] = 0;
544         return dest;
545 }
546
547 /**
548  Paranoid strcpy into a buffer of given length (includes terminating
549  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
550  and replaces with '_'. Deliberately does *NOT* check for multibyte
551  characters. Don't change it !
552 **/
553 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
554 {
555         size_t len, i;
556
557         clobber_region(fn, line, dest, maxlength);
558
559         if (!dest) {
560                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
561                 return NULL;
562         }
563
564         if (!src) {
565                 *dest = 0;
566                 return dest;
567         }  
568
569         len = strlen(src);
570         if (len >= maxlength)
571                 len = maxlength - 1;
572
573         if (!other_safe_chars)
574                 other_safe_chars = "";
575
576         for(i = 0; i < len; i++) {
577                 int val = (src[i] & 0xff);
578                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
579                         dest[i] = src[i];
580                 else
581                         dest[i] = '_';
582         }
583
584         dest[i] = '\0';
585
586         return dest;
587 }
588
589 /**
590  Like strncpy but always null terminates. Make sure there is room!
591  The variable n should always be one less than the available size.
592 **/
593 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
594 {
595         char *d = dest;
596
597         clobber_region(fn, line, dest, n+1);
598
599         if (!dest)
600                 return(NULL);
601         
602         if (!src) {
603                 *dest = 0;
604                 return(dest);
605         }
606         while (n-- && (*d++ = *src++))
607                 ;
608         *d = 0;
609         return(dest);
610 }
611
612 #if 0
613 /**
614  Like strncpy but copies up to the character marker.  always null terminates.
615  returns a pointer to the character marker in the source string (src).
616 **/
617
618 static char *strncpyn(char *dest, const char *src, size_t n, char c)
619 {
620         char *p;
621         size_t str_len;
622
623         clobber_region(dest, n+1);
624
625         p = strchr_m(src, c);
626         if (p == NULL) {
627                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
628                 return NULL;
629         }
630
631         str_len = PTR_DIFF(p, src);
632         strncpy(dest, src, MIN(n, str_len));
633         dest[str_len] = '\0';
634
635         return p;
636 }
637 #endif
638
639 /**
640  Routine to get hex characters and turn them into a 16 byte array.
641  the array can be variable length, and any non-hex-numeric
642  characters are skipped.  "0xnn" or "0Xnn" is specially catered
643  for.
644
645  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
646
647 **/
648
649 size_t strhex_to_str(char *p, size_t len, const char *strhex)
650 {
651         size_t i;
652         size_t num_chars = 0;
653         unsigned char   lonybble, hinybble;
654         const char     *hexchars = "0123456789ABCDEF";
655         char           *p1 = NULL, *p2 = NULL;
656
657         for (i = 0; i < len && strhex[i] != 0; i++) {
658                 if (strnequal(hexchars, "0x", 2)) {
659                         i++; /* skip two chars */
660                         continue;
661                 }
662
663                 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
664                         break;
665
666                 i++; /* next hex digit */
667
668                 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
669                         break;
670
671                 /* get the two nybbles */
672                 hinybble = PTR_DIFF(p1, hexchars);
673                 lonybble = PTR_DIFF(p2, hexchars);
674
675                 p[num_chars] = (hinybble << 4) | lonybble;
676                 num_chars++;
677
678                 p1 = NULL;
679                 p2 = NULL;
680         }
681         return num_chars;
682 }
683
684 /**
685  Check if a string is part of a list.
686 **/
687
688 BOOL in_list(char *s,char *list,BOOL casesensitive)
689 {
690         pstring tok;
691         const char *p=list;
692
693         if (!list)
694                 return(False);
695
696         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
697                 if (casesensitive) {
698                         if (strcmp(tok,s) == 0)
699                                 return(True);
700                 } else {
701                         if (StrCaseCmp(tok,s) == 0)
702                                 return(True);
703                 }
704         }
705         return(False);
706 }
707
708 /* this is used to prevent lots of mallocs of size 1 */
709 static char *null_string = NULL;
710
711 /**
712  Set a string value, allocing the space for the string
713 **/
714
715 static BOOL string_init(char **dest,const char *src)
716 {
717         size_t l;
718         if (!src)     
719                 src = "";
720
721         l = strlen(src);
722
723         if (l == 0) {
724                 if (!null_string) {
725                         if((null_string = (char *)malloc(1)) == NULL) {
726                                 DEBUG(0,("string_init: malloc fail for null_string.\n"));
727                                 return False;
728                         }
729                         *null_string = 0;
730                 }
731                 *dest = null_string;
732         } else {
733                 (*dest) = strdup(src);
734                 if ((*dest) == NULL) {
735                         DEBUG(0,("Out of memory in string_init\n"));
736                         return False;
737                 }
738         }
739         return(True);
740 }
741
742 /**
743  Free a string value.
744 **/
745
746 void string_free(char **s)
747 {
748         if (!s || !(*s))
749                 return;
750         if (*s == null_string)
751                 *s = NULL;
752         SAFE_FREE(*s);
753 }
754
755 /**
756  Set a string value, deallocating any existing space, and allocing the space
757  for the string
758 **/
759
760 BOOL string_set(char **dest,const char *src)
761 {
762         string_free(dest);
763         return(string_init(dest,src));
764 }
765
766 /**
767  Substitute a string for a pattern in another string. Make sure there is 
768  enough room!
769
770  This routine looks for pattern in s and replaces it with 
771  insert. It may do multiple replacements.
772
773  Any of " ; ' $ or ` in the insert string are replaced with _
774  if len==0 then the string cannot be extended. This is different from the old
775  use of len==0 which was for no length checks to be done.
776 **/
777
778 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
779 {
780         char *p;
781         ssize_t ls,lp,li, i;
782
783         if (!insert || !pattern || !*pattern || !s)
784                 return;
785
786         ls = (ssize_t)strlen(s);
787         lp = (ssize_t)strlen(pattern);
788         li = (ssize_t)strlen(insert);
789
790         if (len == 0)
791                 len = ls + 1; /* len is number of *bytes* */
792
793         while (lp <= ls && (p = strstr(s,pattern))) {
794                 if (ls + (li-lp) >= len) {
795                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
796                                  (int)(ls + (li-lp) - len),
797                                  pattern, (int)len));
798                         break;
799                 }
800                 if (li != lp) {
801                         memmove(p+li,p+lp,strlen(p+lp)+1);
802                 }
803                 for (i=0;i<li;i++) {
804                         switch (insert[i]) {
805                         case '`':
806                         case '"':
807                         case '\'':
808                         case ';':
809                         case '$':
810                         case '%':
811                         case '\r':
812                         case '\n':
813                                 p[i] = '_';
814                                 break;
815                         default:
816                                 p[i] = insert[i];
817                         }
818                 }
819                 s = p + li;
820                 ls += (li-lp);
821         }
822 }
823
824 void fstring_sub(char *s,const char *pattern,const char *insert)
825 {
826         string_sub(s, pattern, insert, sizeof(fstring));
827 }
828
829 void pstring_sub(char *s,const char *pattern,const char *insert)
830 {
831         string_sub(s, pattern, insert, sizeof(pstring));
832 }
833
834 /**
835  Similar to string_sub, but it will accept only allocated strings
836  and may realloc them so pay attention at what you pass on no
837  pointers inside strings, no pstrings or const may be passed
838  as string.
839 **/
840
841 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
842 {
843         char *p, *in;
844         char *s;
845         ssize_t ls,lp,li,ld, i;
846
847         if (!insert || !pattern || !*pattern || !string || !*string)
848                 return NULL;
849
850         s = string;
851
852         in = strdup(insert);
853         if (!in) {
854                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
855                 return NULL;
856         }
857         ls = (ssize_t)strlen(s);
858         lp = (ssize_t)strlen(pattern);
859         li = (ssize_t)strlen(insert);
860         ld = li - lp;
861         for (i=0;i<li;i++) {
862                 switch (in[i]) {
863                         case '`':
864                         case '"':
865                         case '\'':
866                         case ';':
867                         case '$':
868                         case '%':
869                         case '\r':
870                         case '\n':
871                                 in[i] = '_';
872                         default:
873                                 /* ok */
874                                 break;
875                 }
876         }
877         
878         while ((p = strstr(s,pattern))) {
879                 if (ld > 0) {
880                         char *t = Realloc(string, ls + ld + 1);
881                         if (!t) {
882                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
883                                 SAFE_FREE(in);
884                                 return NULL;
885                         }
886                         string = t;
887                         p = t + (p - s);
888                 }
889                 if (li != lp) {
890                         memmove(p+li,p+lp,strlen(p+lp)+1);
891                 }
892                 memcpy(p, in, li);
893                 s = p + li;
894                 ls += ld;
895         }
896         SAFE_FREE(in);
897         return string;
898 }
899
900 /**
901  Similar to string_sub() but allows for any character to be substituted. 
902  Use with caution!
903  if len==0 then the string cannot be extended. This is different from the old
904  use of len==0 which was for no length checks to be done.
905 **/
906
907 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
908 {
909         char *p;
910         ssize_t ls,lp,li;
911
912         if (!insert || !pattern || !s)
913                 return;
914
915         ls = (ssize_t)strlen(s);
916         lp = (ssize_t)strlen(pattern);
917         li = (ssize_t)strlen(insert);
918
919         if (!*pattern)
920                 return;
921         
922         if (len == 0)
923                 len = ls + 1; /* len is number of *bytes* */
924         
925         while (lp <= ls && (p = strstr(s,pattern))) {
926                 if (ls + (li-lp) >= len) {
927                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
928                                  (int)(ls + (li-lp) - len),
929                                  pattern, (int)len));
930                         break;
931                 }
932                 if (li != lp) {
933                         memmove(p+li,p+lp,strlen(p+lp)+1);
934                 }
935                 memcpy(p, insert, li);
936                 s = p + li;
937                 ls += (li-lp);
938         }
939 }
940
941 /**
942  Similar to all_string_sub but for unicode strings.
943  Return a new allocated unicode string.
944  similar to string_sub() but allows for any character to be substituted.
945  Use with caution!
946 **/
947
948 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
949                                 const smb_ucs2_t *insert)
950 {
951         smb_ucs2_t *r, *rp;
952         const smb_ucs2_t *sp;
953         size_t  lr, lp, li, lt;
954
955         if (!insert || !pattern || !*pattern || !s)
956                 return NULL;
957
958         lt = (size_t)strlen_w(s);
959         lp = (size_t)strlen_w(pattern);
960         li = (size_t)strlen_w(insert);
961
962         if (li > lp) {
963                 const smb_ucs2_t *st = s;
964                 int ld = li - lp;
965                 while ((sp = strstr_w(st, pattern))) {
966                         st = sp + lp;
967                         lt += ld;
968                 }
969         }
970
971         r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
972         if (!r) {
973                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
974                 return NULL;
975         }
976
977         while ((sp = strstr_w(s, pattern))) {
978                 memcpy(rp, s, (sp - s));
979                 rp += ((sp - s) / sizeof(smb_ucs2_t));
980                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
981                 s = sp + lp;
982                 rp += li;
983         }
984         lr = ((rp - r) / sizeof(smb_ucs2_t));
985         if (lr < lt) {
986                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
987                 rp += (lt - lr);
988         }
989         *rp = 0;
990
991         return r;
992 }
993
994 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
995                                              const char *insert)
996 {
997         wpstring p, i;
998
999         if (!insert || !pattern || !s)
1000                 return NULL;
1001         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1002         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1003         return all_string_sub_w(s, p, i);
1004 }
1005
1006 #if 0
1007 /**
1008  Splits out the front and back at a separator.
1009 **/
1010
1011 static void split_at_last_component(char *path, char *front, char sep, char *back)
1012 {
1013         char *p = strrchr_m(path, sep);
1014
1015         if (p != NULL)
1016                 *p = 0;
1017
1018         if (front != NULL)
1019                 pstrcpy(front, path);
1020
1021         if (p != NULL) {
1022                 if (back != NULL)
1023                         pstrcpy(back, p+1);
1024                 *p = '\\';
1025         } else {
1026                 if (back != NULL)
1027                         back[0] = 0;
1028         }
1029 }
1030 #endif
1031
1032 /**
1033  Write an octal as a string.
1034 **/
1035
1036 const char *octal_string(int i)
1037 {
1038         static char ret[64];
1039         if (i == -1)
1040                 return "-1";
1041         slprintf(ret, sizeof(ret)-1, "0%o", i);
1042         return ret;
1043 }
1044
1045
1046 /**
1047  Truncate a string at a specified length.
1048 **/
1049
1050 char *string_truncate(char *s, unsigned int length)
1051 {
1052         if (s && strlen(s) > length)
1053                 s[length] = 0;
1054         return s;
1055 }
1056
1057 /**
1058  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
1059  We convert via ucs2 for now.
1060 **/
1061
1062 char *strchr_m(const char *s, char c)
1063 {
1064         wpstring ws;
1065         pstring s2;
1066         smb_ucs2_t *p;
1067
1068         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1069         p = strchr_w(ws, UCS2_CHAR(c));
1070         if (!p)
1071                 return NULL;
1072         *p = 0;
1073         pull_ucs2_pstring(s2, ws);
1074         return (char *)(s+strlen(s2));
1075 }
1076
1077 char *strrchr_m(const char *s, char c)
1078 {
1079         wpstring ws;
1080         pstring s2;
1081         smb_ucs2_t *p;
1082
1083         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1084         p = strrchr_w(ws, UCS2_CHAR(c));
1085         if (!p)
1086                 return NULL;
1087         *p = 0;
1088         pull_ucs2_pstring(s2, ws);
1089         return (char *)(s+strlen(s2));
1090 }
1091
1092 /**
1093  Convert a string to lower case.
1094 **/
1095
1096 void strlower_m(char *s)
1097 {
1098         /* this is quite a common operation, so we want it to be
1099            fast. We optimise for the ascii case, knowing that all our
1100            supported multi-byte character sets are ascii-compatible
1101            (ie. they match for the first 128 chars) */
1102
1103         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1104                 *s = tolower((unsigned char)*s);
1105                 s++;
1106         }
1107
1108         if (!*s)
1109                 return;
1110
1111         /* I assume that lowercased string takes the same number of bytes
1112          * as source string even in UTF-8 encoding. (VIV) */
1113         unix_strlower(s,strlen(s)+1,s,strlen(s)+1);     
1114 }
1115
1116 /**
1117  Duplicate convert a string to lower case.
1118 **/
1119
1120 char *strdup_lower(const char *s)
1121 {
1122         char *t = strdup(s);
1123         if (t == NULL) {
1124                 DEBUG(0, ("strdup_lower: Out of memory!\n"));
1125                 return NULL;
1126         }
1127         strlower_m(t);
1128         return t;
1129 }
1130
1131 /**
1132  Convert a string to upper case.
1133 **/
1134
1135 void strupper_m(char *s)
1136 {
1137         /* this is quite a common operation, so we want it to be
1138            fast. We optimise for the ascii case, knowing that all our
1139            supported multi-byte character sets are ascii-compatible
1140            (ie. they match for the first 128 chars) */
1141
1142         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1143                 *s = toupper((unsigned char)*s);
1144                 s++;
1145         }
1146
1147         if (!*s)
1148                 return;
1149
1150         /* I assume that lowercased string takes the same number of bytes
1151          * as source string even in multibyte encoding. (VIV) */
1152         unix_strupper(s,strlen(s)+1,s,strlen(s)+1);     
1153 }
1154
1155 /**
1156  Convert a string to upper case.
1157 **/
1158
1159 char *strdup_upper(const char *s)
1160 {
1161         char *t = strdup(s);
1162         if (t == NULL) {
1163                 DEBUG(0, ("strdup_upper: Out of memory!\n"));
1164                 return NULL;
1165         }
1166         strupper_m(t);
1167         return t;
1168 }
1169
1170 /**
1171  Return a RFC2254 binary string representation of a buffer.
1172  Used in LDAP filters.
1173  Caller must free.
1174 **/
1175
1176 char *binary_string(char *buf, int len)
1177 {
1178         char *s;
1179         int i, j;
1180         const char *hex = "0123456789ABCDEF";
1181         s = malloc(len * 3 + 1);
1182         if (!s)
1183                 return NULL;
1184         for (j=i=0;i<len;i++) {
1185                 s[j] = '\\';
1186                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1187                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1188                 j += 3;
1189         }
1190         s[j] = 0;
1191         return s;
1192 }
1193
1194 /**
1195  Just a typesafety wrapper for snprintf into a pstring.
1196 **/
1197
1198  int pstr_sprintf(pstring s, const char *fmt, ...)
1199 {
1200         va_list ap;
1201         int ret;
1202
1203         va_start(ap, fmt);
1204         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1205         va_end(ap);
1206         return ret;
1207 }
1208
1209 #if 0
1210 /**
1211  Just a typesafety wrapper for snprintf into a fstring.
1212 **/
1213
1214 static int fstr_sprintf(fstring s, const char *fmt, ...)
1215 {
1216         va_list ap;
1217         int ret;
1218
1219         va_start(ap, fmt);
1220         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1221         va_end(ap);
1222         return ret;
1223 }
1224 #endif
1225
1226 #ifndef HAVE_STRNDUP
1227 /**
1228  Some platforms don't have strndup.
1229 **/
1230
1231  char *strndup(const char *s, size_t n)
1232 {
1233         char *ret;
1234         
1235         n = strnlen(s, n);
1236         ret = malloc(n+1);
1237         if (!ret)
1238                 return NULL;
1239         memcpy(ret, s, n);
1240         ret[n] = 0;
1241
1242         return ret;
1243 }
1244 #endif
1245
1246 #ifndef HAVE_STRNLEN
1247 /**
1248  Some platforms don't have strnlen
1249 **/
1250
1251  size_t strnlen(const char *s, size_t n)
1252 {
1253         int i;
1254         for (i=0; s[i] && i<n; i++)
1255                 /* noop */ ;
1256         return i;
1257 }
1258 #endif
1259
1260 /**
1261  List of Strings manipulation functions
1262 **/
1263
1264 #define S_LIST_ABS 16 /* List Allocation Block Size */
1265
1266 char **str_list_make(const char *string, const char *sep)
1267 {
1268         char **list, **rlist;
1269         const char *str;
1270         char *s;
1271         int num, lsize;
1272         pstring tok;
1273         
1274         if (!string || !*string)
1275                 return NULL;
1276         s = strdup(string);
1277         if (!s) {
1278                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1279                 return NULL;
1280         }
1281         if (!sep) sep = LIST_SEP;
1282         
1283         num = lsize = 0;
1284         list = NULL;
1285         
1286         str = s;
1287         while (next_token(&str, tok, sep, sizeof(tok))) {               
1288                 if (num == lsize) {
1289                         lsize += S_LIST_ABS;
1290                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1291                         if (!rlist) {
1292                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1293                                 str_list_free(&list);
1294                                 SAFE_FREE(s);
1295                                 return NULL;
1296                         } else
1297                                 list = rlist;
1298                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1299                 }
1300                 
1301                 list[num] = strdup(tok);
1302                 if (!list[num]) {
1303                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1304                         str_list_free(&list);
1305                         SAFE_FREE(s);
1306                         return NULL;
1307                 }
1308         
1309                 num++;  
1310         }
1311         
1312         SAFE_FREE(s);
1313         return list;
1314 }
1315
1316 BOOL str_list_copy(char ***dest, const char **src)
1317 {
1318         char **list, **rlist;
1319         int num, lsize;
1320         
1321         *dest = NULL;
1322         if (!src)
1323                 return False;
1324         
1325         num = lsize = 0;
1326         list = NULL;
1327                 
1328         while (src[num]) {
1329                 if (num == lsize) {
1330                         lsize += S_LIST_ABS;
1331                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1332                         if (!rlist) {
1333                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1334                                 str_list_free(&list);
1335                                 return False;
1336                         } else
1337                                 list = rlist;
1338                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1339                 }
1340                 
1341                 list[num] = strdup(src[num]);
1342                 if (!list[num]) {
1343                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1344                         str_list_free(&list);
1345                         return False;
1346                 }
1347
1348                 num++;
1349         }
1350         
1351         *dest = list;
1352         return True;    
1353 }
1354
1355 /**
1356  * Return true if all the elements of the list match exactly.
1357  **/
1358 BOOL str_list_compare(char **list1, char **list2)
1359 {
1360         int num;
1361         
1362         if (!list1 || !list2)
1363                 return (list1 == list2); 
1364         
1365         for (num = 0; list1[num]; num++) {
1366                 if (!list2[num])
1367                         return False;
1368                 if (!strcsequal(list1[num], list2[num]))
1369                         return False;
1370         }
1371         if (list2[num])
1372                 return False; /* if list2 has more elements than list1 fail */
1373         
1374         return True;
1375 }
1376
1377 void str_list_free(char ***list)
1378 {
1379         char **tlist;
1380         
1381         if (!list || !*list)
1382                 return;
1383         tlist = *list;
1384         for(; *tlist; tlist++)
1385                 SAFE_FREE(*tlist);
1386         SAFE_FREE(*list);
1387 }
1388
1389 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1390 {
1391         char *p, *s, *t;
1392         ssize_t ls, lp, li, ld, i, d;
1393
1394         if (!list)
1395                 return False;
1396         if (!pattern)
1397                 return False;
1398         if (!insert)
1399                 return False;
1400
1401         lp = (ssize_t)strlen(pattern);
1402         li = (ssize_t)strlen(insert);
1403         ld = li -lp;
1404                         
1405         while (*list) {
1406                 s = *list;
1407                 ls = (ssize_t)strlen(s);
1408
1409                 while ((p = strstr(s, pattern))) {
1410                         t = *list;
1411                         d = p -t;
1412                         if (ld) {
1413                                 t = (char *) malloc(ls +ld +1);
1414                                 if (!t) {
1415                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1416                                         return False;
1417                                 }
1418                                 memcpy(t, *list, d);
1419                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1420                                 SAFE_FREE(*list);
1421                                 *list = t;
1422                                 ls += ld;
1423                                 s = t +d +li;
1424                         }
1425                         
1426                         for (i = 0; i < li; i++) {
1427                                 switch (insert[i]) {
1428                                         case '`':
1429                                         case '"':
1430                                         case '\'':
1431                                         case ';':
1432                                         case '$':
1433                                         case '%':
1434                                         case '\r':
1435                                         case '\n':
1436                                                 t[d +i] = '_';
1437                                                 break;
1438                                         default:
1439                                                 t[d +i] = insert[i];
1440                                 }
1441                         }       
1442                 }
1443                 
1444                 list++;
1445         }
1446         
1447         return True;
1448 }
1449
1450
1451 #define IPSTR_LIST_SEP  ","
1452
1453 /**
1454  * Add ip string representation to ipstr list. Used also
1455  * as part of @function ipstr_list_make
1456  *
1457  * @param ipstr_list pointer to string containing ip list;
1458  *        MUST BE already allocated and IS reallocated if necessary
1459  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1460  *        as a result of reallocation)
1461  * @param ip IP address which is to be added to list
1462  * @return pointer to string appended with new ip and possibly
1463  *         reallocated to new length
1464  **/
1465
1466 char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip)
1467 {
1468         char* new_ipstr = NULL;
1469         
1470         /* arguments checking */
1471         if (!ipstr_list || !ip) return NULL;
1472
1473         /* attempt to convert ip to a string and append colon separator to it */
1474         if (*ipstr_list) {
1475                 asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip));
1476                 SAFE_FREE(*ipstr_list);
1477         } else {
1478                 asprintf(&new_ipstr, "%s", inet_ntoa(*ip));
1479         }
1480         *ipstr_list = new_ipstr;
1481         return *ipstr_list;
1482 }
1483
1484
1485 /**
1486  * Allocate and initialise an ipstr list using ip adresses
1487  * passed as arguments.
1488  *
1489  * @param ipstr_list pointer to string meant to be allocated and set
1490  * @param ip_list array of ip addresses to place in the list
1491  * @param ip_count number of addresses stored in ip_list
1492  * @return pointer to allocated ip string
1493  **/
1494  
1495 char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count)
1496 {
1497         int i;
1498         
1499         /* arguments checking */
1500         if (!ip_list && !ipstr_list) return 0;
1501
1502         *ipstr_list = NULL;
1503         
1504         /* process ip addresses given as arguments */
1505         for (i = 0; i < ip_count; i++)
1506                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1507         
1508         return (*ipstr_list);
1509 }
1510
1511
1512 /**
1513  * Parse given ip string list into array of ip addresses
1514  * (as in_addr structures)
1515  *
1516  * @param ipstr ip string list to be parsed 
1517  * @param ip_list pointer to array of ip addresses which is
1518  *        allocated by this function and must be freed by caller
1519  * @return number of succesfully parsed addresses
1520  **/
1521  
1522 int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list)
1523 {
1524         fstring token_str;
1525         int count;
1526
1527         if (!ipstr_list || !ip_list) return 0;
1528         
1529         for (*ip_list = NULL, count = 0;
1530              next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
1531              count++) {
1532              
1533                 struct in_addr addr;
1534
1535                 /* convert single token to ip address */
1536                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1537                         break;
1538                 
1539                 /* prepare place for another in_addr structure */
1540                 *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr));
1541                 if (!*ip_list) return -1;
1542                 
1543                 (*ip_list)[count] = addr;
1544         }
1545         
1546         return count;
1547 }
1548
1549
1550 /**
1551  * Safely free ip string list
1552  *
1553  * @param ipstr_list ip string list to be freed
1554  **/
1555
1556 void ipstr_list_free(char* ipstr_list)
1557 {
1558         SAFE_FREE(ipstr_list);
1559 }
1560
1561
1562 /**
1563  Unescape a URL encoded string, in place.
1564 **/
1565
1566 void rfc1738_unescape(char *buf)
1567 {
1568         char *p=buf;
1569
1570         while ((p=strchr_m(p,'+')))
1571                 *p = ' ';
1572
1573         p = buf;
1574
1575         while (p && *p && (p=strchr_m(p,'%'))) {
1576                 int c1 = p[1];
1577                 int c2 = p[2];
1578
1579                 if (c1 >= '0' && c1 <= '9')
1580                         c1 = c1 - '0';
1581                 else if (c1 >= 'A' && c1 <= 'F')
1582                         c1 = 10 + c1 - 'A';
1583                 else if (c1 >= 'a' && c1 <= 'f')
1584                         c1 = 10 + c1 - 'a';
1585                 else {p++; continue;}
1586
1587                 if (c2 >= '0' && c2 <= '9')
1588                         c2 = c2 - '0';
1589                 else if (c2 >= 'A' && c2 <= 'F')
1590                         c2 = 10 + c2 - 'A';
1591                 else if (c2 >= 'a' && c2 <= 'f')
1592                         c2 = 10 + c2 - 'a';
1593                 else {p++; continue;}
1594                         
1595                 *p = (c1<<4) | c2;
1596
1597                 memmove(p+1, p+3, strlen(p+3)+1);
1598                 p++;
1599         }
1600 }
1601
1602 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1603
1604 /**
1605  * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1606  **/
1607 DATA_BLOB base64_decode_data_blob(const char *s)
1608 {
1609         int bit_offset, byte_offset, idx, i, n;
1610         DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1611         unsigned char *d = decoded.data;
1612         char *p;
1613
1614         n=i=0;
1615
1616         while (*s && (p=strchr_m(b64,*s))) {
1617                 idx = (int)(p - b64);
1618                 byte_offset = (i*6)/8;
1619                 bit_offset = (i*6)%8;
1620                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1621                 if (bit_offset < 3) {
1622                         d[byte_offset] |= (idx << (2-bit_offset));
1623                         n = byte_offset+1;
1624                 } else {
1625                         d[byte_offset] |= (idx >> (bit_offset-2));
1626                         d[byte_offset+1] = 0;
1627                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1628                         n = byte_offset+2;
1629                 }
1630                 s++; i++;
1631         }
1632
1633         /* fix up length */
1634         decoded.length = n;
1635         return decoded;
1636 }
1637
1638 /**
1639  * Decode a base64 string in-place - wrapper for the above
1640  **/
1641 void base64_decode_inplace(char *s)
1642 {
1643         DATA_BLOB decoded = base64_decode_data_blob(s);
1644         memcpy(s, decoded.data, decoded.length);
1645         data_blob_free(&decoded);
1646
1647         /* null terminate */
1648         s[decoded.length] = '\0';
1649 }
1650
1651 /**
1652  * Encode a base64 string into a malloc()ed string caller to free.
1653  *
1654  *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1655  **/
1656 char * base64_encode_data_blob(DATA_BLOB data)
1657 {
1658         int bits = 0;
1659         int char_count = 0;
1660         size_t out_cnt = 0;
1661         size_t len = data.length;
1662         size_t output_len = data.length * 2;
1663         char *result = malloc(output_len); /* get us plenty of space */
1664
1665         while (len-- && out_cnt < (data.length * 2) - 5) {
1666                 int c = (unsigned char) *(data.data++);
1667                 bits += c;
1668                 char_count++;
1669                 if (char_count == 3) {
1670                         result[out_cnt++] = b64[bits >> 18];
1671                         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1672                         result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1673             result[out_cnt++] = b64[bits & 0x3f];
1674             bits = 0;
1675             char_count = 0;
1676         } else {
1677             bits <<= 8;
1678         }
1679     }
1680     if (char_count != 0) {
1681         bits <<= 16 - (8 * char_count);
1682         result[out_cnt++] = b64[bits >> 18];
1683         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1684         if (char_count == 1) {
1685             result[out_cnt++] = '=';
1686             result[out_cnt++] = '=';
1687         } else {
1688             result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1689             result[out_cnt++] = '=';
1690         }
1691     }
1692     result[out_cnt] = '\0';     /* terminate */
1693     return result;
1694 }
1695