Check that the socket is well and served by us.
[gnupg.git] / jnlib / stringhelp.c
1 /* stringhelp.c -  standard string helper functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005,
3  *               2006, 2007, 2008  Free Software Foundation, Inc.
4  *
5  * This file is part of JNLIB.
6  *
7  * JNLIB is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * JNLIB is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include <ctype.h>
26 #ifdef HAVE_W32_SYSTEM
27 #include <windows.h>
28 #endif
29
30 #include "libjnlib-config.h"
31 #include "utf8conv.h"
32 #include "stringhelp.h"
33
34
35 #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
36
37 /* Sometimes we want to avoid mixing slashes and backslashes on W32
38    and prefer backslashes.  There is usual no problem with mixing
39    them, however a very few W32 API calls can't grok plain slashes.
40    Printing filenames with mixed slashes also looks a bit strange.
41    This function has no effext on POSIX. */
42 static inline char *
43 change_slashes (char *name)
44 {
45   char *p;
46
47 #ifdef HAVE_DRIVE_LETTERS
48   if (strchr (name, '\\'))
49     {
50       for (p=name; *p; p++)
51         if (*p == '/')
52           *p = '\\';
53     }
54 #endif /*HAVE_DRIVE_LETTERS*/
55   return name;
56 }
57
58
59 /*
60  * Look for the substring SUB in buffer and return a pointer to that
61  * substring in BUFFER or NULL if not found.
62  * Comparison is case-insensitive.
63  */
64 const char *
65 memistr (const void *buffer, size_t buflen, const char *sub)
66 {
67   const unsigned char *buf = buffer;
68   const unsigned char *t = (const unsigned char *)buffer;
69   const unsigned char *s = (const unsigned char *)sub;
70   size_t n = buflen;
71
72   for ( ; n ; t++, n-- )
73     {
74       if ( toupper (*t) == toupper (*s) )
75         {
76           for ( buf=t++, buflen = n--, s++;
77                 n && toupper (*t) == toupper (*s); t++, s++, n-- )
78             ;
79           if (!*s)
80             return (const char*)buf;
81           t = buf;
82           s = (const unsigned char *)sub ;
83           n = buflen;
84         }
85     }
86   return NULL;
87 }
88
89 const char *
90 ascii_memistr ( const void *buffer, size_t buflen, const char *sub )
91 {
92   const unsigned char *buf = buffer;
93   const unsigned char *t = (const unsigned char *)buf;
94   const unsigned char *s = (const unsigned char *)sub;
95   size_t n = buflen;
96
97   for ( ; n ; t++, n-- )
98     {
99       if (ascii_toupper (*t) == ascii_toupper (*s) )
100         {
101           for ( buf=t++, buflen = n--, s++;
102                 n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- )
103             ;
104           if (!*s)
105             return (const char*)buf;
106           t = (const unsigned char *)buf;
107           s = (const unsigned char *)sub ;
108           n = buflen;
109         }
110     }
111   return NULL;
112 }
113
114 /* This function is similar to strncpy().  However it won't copy more
115    than N - 1 characters and makes sure that a '\0' is appended. With
116    N given as 0, nothing will happen.  With DEST given as NULL, memory
117    will be allocated using jnlib_xmalloc (i.e. if it runs out of core
118    the function terminates).  Returns DES or a pointer to the
119    allocated memory.
120  */
121 char *
122 mem2str( char *dest , const void *src , size_t n )
123 {
124     char *d;
125     const char *s;
126
127     if( n ) {
128         if( !dest )
129             dest = jnlib_xmalloc( n ) ;
130         d = dest;
131         s = src ;
132         for(n--; n && *s; n-- )
133             *d++ = *s++;
134         *d = '\0' ;
135     }
136
137     return dest ;
138 }
139
140
141 /****************
142  * remove leading and trailing white spaces
143  */
144 char *
145 trim_spaces( char *str )
146 {
147     char *string, *p, *mark;
148
149     string = str;
150     /* find first non space character */
151     for( p=string; *p && isspace( *(byte*)p ) ; p++ )
152         ;
153     /* move characters */
154     for( (mark = NULL); (*string = *p); string++, p++ )
155         if( isspace( *(byte*)p ) ) {
156             if( !mark )
157                 mark = string ;
158         }
159         else
160             mark = NULL ;
161     if( mark )
162         *mark = '\0' ;  /* remove trailing spaces */
163
164     return str ;
165 }
166
167 /****************
168  * remove trailing white spaces
169  */
170 char *
171 trim_trailing_spaces( char *string )
172 {
173     char *p, *mark;
174
175     for( mark = NULL, p = string; *p; p++ ) {
176         if( isspace( *(byte*)p ) ) {
177             if( !mark )
178                 mark = p;
179         }
180         else
181             mark = NULL;
182     }
183     if( mark )
184         *mark = '\0' ;
185
186     return string ;
187 }
188
189
190 unsigned
191 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
192 {
193     byte *p, *mark;
194     unsigned n;
195
196     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
197         if( strchr(trimchars, *p ) ) {
198             if( !mark )
199                 mark = p;
200         }
201         else
202             mark = NULL;
203     }
204
205     if( mark ) {
206         *mark = 0;
207         return mark - line;
208     }
209     return len;
210 }
211
212 /****************
213  * remove trailing white spaces and return the length of the buffer
214  */
215 unsigned
216 trim_trailing_ws( byte *line, unsigned len )
217 {
218     return trim_trailing_chars( line, len, " \t\r\n" );
219 }
220
221 size_t
222 length_sans_trailing_chars (const unsigned char *line, size_t len,
223                             const char *trimchars )
224 {
225   const unsigned char *p, *mark;
226   size_t n;
227   
228   for( mark=NULL, p=line, n=0; n < len; n++, p++ )
229     {
230       if (strchr (trimchars, *p ))
231         {
232           if( !mark )
233             mark = p;
234         }
235       else
236         mark = NULL;
237     }
238   
239   if (mark) 
240     return mark - line;
241   return len;
242 }
243
244 /*
245  *  Return the length of line ignoring trailing white-space.
246  */
247 size_t
248 length_sans_trailing_ws (const unsigned char *line, size_t len)
249 {
250   return length_sans_trailing_chars (line, len, " \t\r\n");
251 }
252
253
254
255 /***************
256  * Extract from a given path the filename component.
257  *
258  */
259 char *
260 make_basename(const char *filepath, const char *inputpath)
261 {
262 #ifdef __riscos__
263     return riscos_make_basename(filepath, inputpath);
264 #else
265     char *p;
266
267     (void)inputpath; /* Only required for riscos.  */
268
269     if ( !(p=strrchr(filepath, '/')) )
270 #ifdef HAVE_DRIVE_LETTERS
271         if ( !(p=strrchr(filepath, '\\')) )
272             if ( !(p=strrchr(filepath, ':')) )
273 #endif
274               {
275                 return jnlib_xstrdup(filepath);
276               }
277
278     return jnlib_xstrdup(p+1);
279 #endif
280 }
281
282
283
284 /***************
285  * Extract from a given filename the path prepended to it.
286  * If their isn't a path prepended to the filename, a dot
287  * is returned ('.').
288  *
289  */
290 char *
291 make_dirname(const char *filepath)
292 {
293     char *dirname;
294     int  dirname_length;
295     char *p;
296
297     if ( !(p=strrchr(filepath, '/')) )
298 #ifdef HAVE_DRIVE_LETTERS
299         if ( !(p=strrchr(filepath, '\\')) )
300             if ( !(p=strrchr(filepath, ':')) )
301 #endif
302               {
303                 return jnlib_xstrdup(".");
304               }
305
306     dirname_length = p-filepath;
307     dirname = jnlib_xmalloc(dirname_length+1);
308     strncpy(dirname, filepath, dirname_length);
309     dirname[dirname_length] = 0;
310
311     return dirname;
312 }
313
314
315 \f
316 /* Implementation of make_filename and make_filename_try.  We need to
317    use macros here toa void the use of the soemtimes problematic
318    va_copy fucntion which is not available on all systems.  */
319 #define MAKE_FILENAME_PART1                        \
320   va_list arg_ptr;                                 \
321   size_t n;                                        \
322   const char *s;                                   \
323   char *name, *home, *p;                           \
324                                                    \
325   va_start (arg_ptr, first_part);                  \
326   n = strlen (first_part) + 1;                     \
327   while ( (s = va_arg (arg_ptr, const char *)) )   \
328     n += strlen(s) + 1;                            \
329   va_end(arg_ptr);                                 \
330                                                    \
331   home = NULL;                                     \
332   if ( *first_part == '~' && first_part[1] == '/'  \
333        && (home = getenv("HOME")) && *home )       \
334     n += strlen (home);                            
335   
336 #define MAKE_FILENAME_PART2                         \
337   p = (home                                         \
338        ? stpcpy (stpcpy (name,home), first_part + 1)\
339        : stpcpy(name, first_part));                 \
340                                                     \
341   va_start (arg_ptr, first_part);                   \
342   while ( (s = va_arg(arg_ptr, const char *)) )     \
343     p = stpcpy (stpcpy (p,"/"), s);                 \
344   va_end(arg_ptr);                                  \
345   return change_slashes (name);
346
347
348 /* Construct a filename from the NULL terminated list of parts.  Tilde
349    expansion is done here.  This function will never fail. */
350 char *
351 make_filename (const char *first_part, ... )
352 {
353   MAKE_FILENAME_PART1
354   name = jnlib_xmalloc (n);
355   MAKE_FILENAME_PART2
356 }
357
358 /* Construct a filename from the NULL terminated list of parts.  Tilde
359    expansion is done here.  This function may return NULL on error. */
360 char *
361 make_filename_try (const char *first_part, ... )
362 {
363   MAKE_FILENAME_PART1
364   name = jnlib_xmalloc (n);
365   if (!name)
366     return NULL;
367   MAKE_FILENAME_PART2
368 }
369 #undef MAKE_FILENAME_PART1
370 #undef MAKE_FILENAME_PART2
371
372
373 \f
374 /* Compare whether the filenames are identical.  This is a
375    special version of strcmp() taking the semantics of filenames in
376    account.  Note that this function works only on the supplied names
377    without considereing any context like the current directory.  See
378    also same_file_p(). */
379 int
380 compare_filenames (const char *a, const char *b)
381 {
382 #ifdef HAVE_DRIVE_LETTERS
383   for ( ; *a && *b; a++, b++ ) 
384     {
385       if (*a != *b 
386           && (toupper (*(const unsigned char*)a)
387               != toupper (*(const unsigned char*)b) )
388           && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')))
389         break;
390     }
391   if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))
392     return 0;
393   else
394     return (toupper (*(const unsigned char*)a) 
395             - toupper (*(const unsigned char*)b));
396 #else
397     return strcmp(a,b);
398 #endif
399 }
400
401
402 /* Convert 2 hex characters at S to a byte value.  Return this value
403    or -1 if there is an error. */
404 int
405 hextobyte (const char *s)
406 {
407   int c;
408
409   if ( *s >= '0' && *s <= '9' )
410     c = 16 * (*s - '0');
411   else if ( *s >= 'A' && *s <= 'F' )
412     c = 16 * (10 + *s - 'A');
413   else if ( *s >= 'a' && *s <= 'f' )
414     c = 16 * (10 + *s - 'a');
415   else
416     return -1;
417   s++;
418   if ( *s >= '0' && *s <= '9' )
419     c += *s - '0';
420   else if ( *s >= 'A' && *s <= 'F' )
421     c += 10 + *s - 'A';
422   else if ( *s >= 'a' && *s <= 'f' )
423     c += 10 + *s - 'a';
424   else
425     return -1;
426   return c;
427 }
428
429
430 /* Print a BUFFER to stream FP while replacing all control characters
431    and the characters DELIM and DELIM2 with standard C escape
432    sequences.  Returns the number of characters printed. */
433 size_t 
434 print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length,
435                          int delim, int delim2)
436 {
437   const unsigned char *p = buffer;
438   size_t count = 0;
439
440   for (; length; length--, p++, count++)
441     {
442       if (*p < 0x20 
443           || *p == 0x7f
444           || *p == delim 
445           || *p == delim2
446           || ((delim || delim2) && *p=='\\'))
447         {
448           putc ('\\', fp);
449           count++;
450           if (*p == '\n')
451             {
452               putc ('n', fp);
453               count++;
454             }
455           else if (*p == '\r')
456             {
457               putc ('r', fp);
458               count++;
459             }
460           else if (*p == '\f')
461             {
462               putc ('f', fp);
463               count++;
464             }
465           else if (*p == '\v')
466             {
467               putc ('v', fp);
468               count++;
469             }
470           else if (*p == '\b')
471             {
472               putc ('b', fp);
473               count++;
474             }
475           else if (!*p)
476             {
477               putc('0', fp);
478               count++;
479             }
480           else
481             {
482               fprintf (fp, "x%02x", *p);
483               count += 3;
484             }
485         }
486       else
487         {
488           putc (*p, fp);
489           count++;
490         }
491     }
492
493   return count;
494 }
495
496 /* Same as print_sanitized_buffer2 but with just one delimiter. */
497 size_t 
498 print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
499                         int delim)
500 {
501   return print_sanitized_buffer2 (fp, buffer, length, delim, 0);
502 }
503
504
505 size_t 
506 print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
507                              size_t length, int delim)
508 {
509   const char *p = buffer;
510   size_t i;
511
512   /* We can handle plain ascii simpler, so check for it first. */
513   for (i=0; i < length; i++ ) 
514     {
515       if ( (p[i] & 0x80) )
516         break;
517     }
518   if (i < length)
519     {
520         char *buf = utf8_to_native (p, length, delim);
521         /*(utf8 conversion already does the control character quoting)*/
522         i = strlen (buf);
523         fputs (buf, fp);
524         jnlib_free (buf);
525         return i;
526     }
527   else
528     return print_sanitized_buffer (fp, p, length, delim);
529 }
530
531
532 size_t 
533 print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2)
534 {
535   return string? print_sanitized_buffer2 (fp, string, strlen (string),
536                                           delim, delim2):0;
537 }
538
539 size_t 
540 print_sanitized_string (FILE *fp, const char *string, int delim)
541 {
542   return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
543 }
544
545 size_t 
546 print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
547 {
548   return string? print_sanitized_utf8_buffer (fp,
549                                               string, strlen (string),
550                                               delim) : 0;
551 }
552
553 /* Create a string from the buffer P_ARG of length N which is suitable for
554    printing.  Caller must release the created string using xfree. */
555 char *
556 sanitize_buffer (const void *p_arg, size_t n, int delim)
557 {
558   const unsigned char *p = p_arg;
559   size_t save_n, buflen;
560   const unsigned char *save_p;
561   char *buffer, *d;
562
563   /* First count length. */
564   for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) 
565     {
566       if ( *p < 0x20 || *p == 0x7f || *p == delim  || (delim && *p=='\\'))
567         {
568           if ( *p=='\n' || *p=='\r' || *p=='\f'
569                || *p=='\v' || *p=='\b' || !*p )
570             buflen += 2;
571           else
572             buflen += 5;
573         }
574       else
575         buflen++;
576     }
577   p = save_p;
578   n = save_n;
579   /* And now make the string */
580   d = buffer = jnlib_xmalloc( buflen );
581   for ( ; n; n--, p++ )
582     {
583       if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
584         *d++ = '\\';
585         if( *p == '\n' )
586           *d++ = 'n';
587         else if( *p == '\r' )
588           *d++ = 'r';
589         else if( *p == '\f' )
590           *d++ = 'f';
591         else if( *p == '\v' )
592           *d++ = 'v';
593         else if( *p == '\b' )
594           *d++ = 'b';
595         else if( !*p )
596           *d++ = '0';
597         else {
598           sprintf(d, "x%02x", *p );
599           d += 3;
600         }
601       }
602       else
603         *d++ = *p;
604     }
605   *d = 0;
606   return buffer;
607 }
608
609
610 /* Given a string containing an UTF-8 encoded text, return the number
611    of characters in this string.  It differs from strlen in that it
612    only counts complete UTF-8 characters.  Note, that this function
613    does not take combined characters into account.  */
614 size_t
615 utf8_charcount (const char *s)
616 {
617   size_t n;
618
619   for (n=0; *s; s++)
620     if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
621       n++;
622
623   return n;
624 }
625
626
627 /****************************************************
628  **********  W32 specific functions  ****************
629  ****************************************************/
630
631 #ifdef HAVE_W32_SYSTEM
632 const char *
633 w32_strerror (int ec)
634 {
635   static char strerr[256];
636   
637   if (ec == -1)
638     ec = (int)GetLastError ();
639   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
640                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
641                  strerr, DIM (strerr)-1, NULL);
642   return strerr;    
643 }
644 #endif /*HAVE_W32_SYSTEM*/
645
646
647 /****************************************************
648  ******** Locale insensitive ctype functions ********
649  ****************************************************/
650 /* FIXME: replace them by a table lookup and macros */
651 int
652 ascii_isupper (int c)
653 {
654     return c >= 'A' && c <= 'Z';
655 }
656
657 int
658 ascii_islower (int c)
659 {
660     return c >= 'a' && c <= 'z';
661 }
662
663 int 
664 ascii_toupper (int c)
665 {
666     if (c >= 'a' && c <= 'z')
667         c &= ~0x20;
668     return c;
669 }
670
671 int 
672 ascii_tolower (int c)
673 {
674     if (c >= 'A' && c <= 'Z')
675         c |= 0x20;
676     return c;
677 }
678
679
680 int
681 ascii_strcasecmp( const char *a, const char *b )
682 {
683     if (a == b)
684         return 0;
685
686     for (; *a && *b; a++, b++) {
687         if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
688             break;
689     }
690     return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
691 }
692
693 int 
694 ascii_strncasecmp (const char *a, const char *b, size_t n)
695 {
696   const unsigned char *p1 = (const unsigned char *)a;
697   const unsigned char *p2 = (const unsigned char *)b;
698   unsigned char c1, c2;
699
700   if (p1 == p2 || !n )
701     return 0;
702
703   do
704     {
705       c1 = ascii_tolower (*p1);
706       c2 = ascii_tolower (*p2);
707
708       if ( !--n || c1 == '\0')
709         break;
710
711       ++p1;
712       ++p2;
713     }
714   while (c1 == c2);
715   
716   return c1 - c2;
717 }
718
719
720 int
721 ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
722 {
723   const char *a = a_arg;
724   const char *b = b_arg;
725
726   if (a == b)
727     return 0;
728   for ( ; n; n--, a++, b++ )
729     {
730       if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
731         return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
732     }
733   return 0;
734 }
735
736 int
737 ascii_strcmp( const char *a, const char *b )
738 {
739     if (a == b)
740         return 0;
741
742     for (; *a && *b; a++, b++) {
743         if (*a != *b )
744             break;
745     }
746     return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
747 }
748
749
750 void *
751 ascii_memcasemem (const void *haystack, size_t nhaystack,
752                   const void *needle, size_t nneedle)
753 {
754
755   if (!nneedle)
756     return (void*)haystack; /* finding an empty needle is really easy */
757   if (nneedle <= nhaystack)
758     {
759       const char *a = haystack;
760       const char *b = a + nhaystack - nneedle;
761       
762       for (; a <= b; a++)
763         {
764           if ( !ascii_memcasecmp (a, needle, nneedle) )
765             return (void *)a;
766         }
767     }
768   return NULL;
769 }
770
771 /*********************************************
772  ********** missing string functions *********
773  *********************************************/
774
775 #ifndef HAVE_STPCPY
776 char *
777 stpcpy(char *a,const char *b)
778 {
779     while( *b )
780         *a++ = *b++;
781     *a = 0;
782
783     return (char*)a;
784 }
785 #endif
786
787 #ifndef HAVE_STRSEP
788 /* Code taken from glibc-2.2.1/sysdeps/generic/strsep.c. */
789 char *
790 strsep (char **stringp, const char *delim)
791 {
792   char *begin, *end;
793
794   begin = *stringp;
795   if (begin == NULL)
796     return NULL;
797
798   /* A frequent case is when the delimiter string contains only one
799      character.  Here we don't need to call the expensive `strpbrk'
800      function and instead work using `strchr'.  */
801   if (delim[0] == '\0' || delim[1] == '\0')
802     {
803       char ch = delim[0];
804
805       if (ch == '\0')
806         end = NULL;
807       else
808         {
809           if (*begin == ch)
810             end = begin;
811           else if (*begin == '\0')
812             end = NULL;
813           else
814             end = strchr (begin + 1, ch);
815         }
816     }
817   else
818     /* Find the end of the token.  */
819     end = strpbrk (begin, delim);
820
821   if (end)
822     {
823       /* Terminate the token and set *STRINGP past NUL character.  */
824       *end++ = '\0';
825       *stringp = end;
826     }
827   else
828     /* No more delimiters; this is the last token.  */
829     *stringp = NULL;
830
831   return begin;
832 }
833 #endif /*HAVE_STRSEP*/
834
835
836 #ifndef HAVE_STRLWR
837 char *
838 strlwr(char *s)
839 {
840     char *p;
841     for(p=s; *p; p++ )
842         *p = tolower(*p);
843     return s;
844 }
845 #endif
846
847
848 #ifndef HAVE_STRCASECMP
849 int
850 strcasecmp( const char *a, const char *b )
851 {
852     for( ; *a && *b; a++, b++ ) {
853         if( *a != *b && toupper(*a) != toupper(*b) )
854             break;
855     }
856     return *(const byte*)a - *(const byte*)b;
857 }
858 #endif
859
860
861 /****************
862  * mingw32/cpd has a memicmp()
863  */
864 #ifndef HAVE_MEMICMP
865 int
866 memicmp( const char *a, const char *b, size_t n )
867 {
868     for( ; n; n--, a++, b++ )
869         if( *a != *b  && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
870             return *(const byte *)a - *(const byte*)b;
871     return 0;
872 }
873 #endif
874
875
876 #ifndef HAVE_MEMRCHR
877 void *
878 memrchr (const void *buffer, int c, size_t n)
879 {
880   const unsigned char *p = buffer;
881
882   for (p += n; n ; n--)
883     if (*--p == c)
884       return (void *)p;
885   return NULL;
886 }
887 #endif /*HAVE_MEMRCHR*/
888
889 \f
890 /* Percent-escape the string STR by replacing colons with '%3a'.  If
891    EXTRA is not NULL all characters in EXTRA are also escaped.  */
892 static char *
893 do_percent_escape (const char *str, const char *extra, int die)
894 {
895   int i, j;
896   char *ptr;
897
898   if (!str)
899     return NULL;
900
901   for (i=j=0; str[i]; i++)
902     if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
903       j++;
904   if (die)
905     ptr = jnlib_xmalloc (i + 2 * j + 1);
906   else
907     {
908       ptr = jnlib_malloc (i + 2 * j + 1);
909       if (!ptr)
910         return NULL;
911     }
912   i = 0;
913   while (*str)
914     {
915       if (*str == ':')
916         {
917           ptr[i++] = '%';
918           ptr[i++] = '3';
919           ptr[i++] = 'a';
920         }
921       else if (*str == '%')
922         {
923           ptr[i++] = '%';
924           ptr[i++] = '2';
925           ptr[i++] = '5';
926         }
927       else if (extra && strchr (extra, *str))
928         {
929           ptr[i++] = '%';
930           ptr[i++] = tohex_lower ((*str>>4)&15);
931           ptr[i++] = tohex_lower (*str&15);
932         }
933       else
934         ptr[i++] = *str;
935       str++;
936     }
937   ptr[i] = '\0';
938
939   return ptr;
940 }
941
942 /* Percent-escape the string STR by replacing colons with '%3a'.  If
943    EXTRA is not NULL all characters in EXTRA are also escaped.  */
944 char *
945 percent_escape (const char *str, const char *extra)
946 {
947   return do_percent_escape (str, extra, 1);
948 }
949
950 /* Same as percent_escape but return NULL instead of exiting on memory
951    error. */
952 char *
953 try_percent_escape (const char *str, const char *extra)
954 {
955   return do_percent_escape (str, extra, 0);
956 }