Updated FSF's address.
[gnupg.git] / jnlib / stringhelp.c
1 /* stringhelp.c -  standard string helper functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005,
3  *               2006  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <ctype.h>
28 #ifdef HAVE_W32_SYSTEM
29 #include <windows.h>
30 #endif
31
32 #include "libjnlib-config.h"
33 #include "utf8conv.h"
34 #include "stringhelp.h"
35
36
37 /*
38  * Look for the substring SUB in buffer and return a pointer to that
39  * substring in BUFFER or NULL if not found.
40  * Comparison is case-insensitive.
41  */
42 const char *
43 memistr (const void *buffer, size_t buflen, const char *sub)
44 {
45   const unsigned char *buf = buffer;
46   const unsigned char *t = (const unsigned char *)buffer;
47   const unsigned char *s = (const unsigned char *)sub;
48   size_t n = buflen;
49
50   for ( ; n ; t++, n-- )
51     {
52       if ( toupper (*t) == toupper (*s) )
53         {
54           for ( buf=t++, buflen = n--, s++;
55                 n && toupper (*t) == toupper (*s); t++, s++, n-- )
56             ;
57           if (!*s)
58             return (const char*)buf;
59           t = buf;
60           s = (const unsigned char *)sub ;
61           n = buflen;
62         }
63     }
64   return NULL;
65 }
66
67 const char *
68 ascii_memistr ( const void *buffer, size_t buflen, const char *sub )
69 {
70   const unsigned char *buf = buffer;
71   const unsigned char *t = (const unsigned char *)buf;
72   const unsigned char *s = (const unsigned char *)sub;
73   size_t n = buflen;
74
75   for ( ; n ; t++, n-- )
76     {
77       if (ascii_toupper (*t) == ascii_toupper (*s) )
78         {
79           for ( buf=t++, buflen = n--, s++;
80                 n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- )
81             ;
82           if (!*s)
83             return (const char*)buf;
84           t = (const unsigned char *)buf;
85           s = (const unsigned char *)sub ;
86           n = buflen;
87         }
88     }
89   return NULL;
90 }
91
92 /* This function is similar to strncpy().  However it won't copy more
93    than N - 1 characters and makes sure that a '\0' is appended. With
94    N given as 0, nothing will happen.  With DEST given as NULL, memory
95    will be allocated using jnlib_xmalloc (i.e. if it runs out of core
96    the function terminates).  Returns DES or a pointer to the
97    allocated memory.
98  */
99 char *
100 mem2str( char *dest , const void *src , size_t n )
101 {
102     char *d;
103     const char *s;
104
105     if( n ) {
106         if( !dest )
107             dest = jnlib_xmalloc( n ) ;
108         d = dest;
109         s = src ;
110         for(n--; n && *s; n-- )
111             *d++ = *s++;
112         *d = '\0' ;
113     }
114
115     return dest ;
116 }
117
118
119 /****************
120  * remove leading and trailing white spaces
121  */
122 char *
123 trim_spaces( char *str )
124 {
125     char *string, *p, *mark;
126
127     string = str;
128     /* find first non space character */
129     for( p=string; *p && isspace( *(byte*)p ) ; p++ )
130         ;
131     /* move characters */
132     for( (mark = NULL); (*string = *p); string++, p++ )
133         if( isspace( *(byte*)p ) ) {
134             if( !mark )
135                 mark = string ;
136         }
137         else
138             mark = NULL ;
139     if( mark )
140         *mark = '\0' ;  /* remove trailing spaces */
141
142     return str ;
143 }
144
145 /****************
146  * remove trailing white spaces
147  */
148 char *
149 trim_trailing_spaces( char *string )
150 {
151     char *p, *mark;
152
153     for( mark = NULL, p = string; *p; p++ ) {
154         if( isspace( *(byte*)p ) ) {
155             if( !mark )
156                 mark = p;
157         }
158         else
159             mark = NULL;
160     }
161     if( mark )
162         *mark = '\0' ;
163
164     return string ;
165 }
166
167
168 unsigned
169 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
170 {
171     byte *p, *mark;
172     unsigned n;
173
174     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
175         if( strchr(trimchars, *p ) ) {
176             if( !mark )
177                 mark = p;
178         }
179         else
180             mark = NULL;
181     }
182
183     if( mark ) {
184         *mark = 0;
185         return mark - line;
186     }
187     return len;
188 }
189
190 /****************
191  * remove trailing white spaces and return the length of the buffer
192  */
193 unsigned
194 trim_trailing_ws( byte *line, unsigned len )
195 {
196     return trim_trailing_chars( line, len, " \t\r\n" );
197 }
198
199 size_t
200 length_sans_trailing_chars (const unsigned char *line, size_t len,
201                             const char *trimchars )
202 {
203   const unsigned char *p, *mark;
204   size_t n;
205   
206   for( mark=NULL, p=line, n=0; n < len; n++, p++ )
207     {
208       if (strchr (trimchars, *p ))
209         {
210           if( !mark )
211             mark = p;
212         }
213       else
214         mark = NULL;
215     }
216   
217   if (mark) 
218     return mark - line;
219   return len;
220 }
221
222 /*
223  *  Return the length of line ignoring trailing white-space.
224  */
225 size_t
226 length_sans_trailing_ws (const unsigned char *line, size_t len)
227 {
228   return length_sans_trailing_chars (line, len, " \t\r\n");
229 }
230
231
232
233 /***************
234  * Extract from a given path the filename component.
235  *
236  */
237 char *
238 make_basename(const char *filepath, const char *inputpath)
239 {
240     char *p;
241
242 #ifdef __riscos__
243     return riscos_make_basename(filepath, inputpath);
244 #endif
245
246     if ( !(p=strrchr(filepath, '/')) )
247 #ifdef HAVE_DRIVE_LETTERS
248         if ( !(p=strrchr(filepath, '\\')) )
249             if ( !(p=strrchr(filepath, ':')) )
250 #endif
251               {
252                 return jnlib_xstrdup(filepath);
253               }
254
255     return jnlib_xstrdup(p+1);
256 }
257
258
259
260 /***************
261  * Extract from a given filename the path prepended to it.
262  * If their isn't a path prepended to the filename, a dot
263  * is returned ('.').
264  *
265  */
266 char *
267 make_dirname(const char *filepath)
268 {
269     char *dirname;
270     int  dirname_length;
271     char *p;
272
273     if ( !(p=strrchr(filepath, '/')) )
274       #ifdef HAVE_DRIVE_LETTERS
275         if ( !(p=strrchr(filepath, '\\')) )
276             if ( !(p=strrchr(filepath, ':')) )
277       #endif
278               {
279                 return jnlib_xstrdup(".");
280               }
281
282     dirname_length = p-filepath;
283     dirname = jnlib_xmalloc(dirname_length+1);
284     strncpy(dirname, filepath, dirname_length);
285     dirname[dirname_length] = 0;
286
287     return dirname;
288 }
289
290
291
292 /****************
293  * Construct a filename from the NULL terminated list of parts.
294  * Tilde expansion is done here.
295  */
296 char *
297 make_filename( const char *first_part, ... )
298 {
299     va_list arg_ptr ;
300     size_t n;
301     const char *s;
302     char *name, *home, *p;
303
304     va_start( arg_ptr, first_part ) ;
305     n = strlen(first_part)+1;
306     while( (s=va_arg(arg_ptr, const char *)) )
307         n += strlen(s) + 1;
308     va_end(arg_ptr);
309
310     home = NULL;
311     if( *first_part == '~' && first_part[1] == '/'
312                            && (home = getenv("HOME")) && *home )
313         n += strlen(home);
314
315     name = jnlib_xmalloc(n);
316     p = home ? stpcpy(stpcpy(name,home), first_part+1)
317              : stpcpy(name, first_part);
318     va_start( arg_ptr, first_part ) ;
319     while( (s=va_arg(arg_ptr, const char *)) )
320         p = stpcpy(stpcpy(p,"/"), s);
321     va_end(arg_ptr);
322
323     return name;
324 }
325
326
327 int
328 compare_filenames( const char *a, const char *b )
329 {
330     /* ? check whether this is an absolute filename and
331      * resolve symlinks?
332      */
333 #ifdef HAVE_DRIVE_LETTERS
334     return stricmp(a,b);
335 #else
336     return strcmp(a,b);
337 #endif
338 }
339
340
341 /* Convert 2 hex characters at S to a byte value.  Return this value
342    or -1 if there is an error. */
343 int
344 hextobyte (const char *s)
345 {
346   int c;
347
348   if ( *s >= '0' && *s <= '9' )
349     c = 16 * (*s - '0');
350   else if ( *s >= 'A' && *s <= 'F' )
351     c = 16 * (10 + *s - 'A');
352   else if ( *s >= 'a' && *s <= 'f' )
353     c = 16 * (10 + *s - 'a');
354   else
355     return -1;
356   s++;
357   if ( *s >= '0' && *s <= '9' )
358     c += *s - '0';
359   else if ( *s >= 'A' && *s <= 'F' )
360     c += 10 + *s - 'A';
361   else if ( *s >= 'a' && *s <= 'f' )
362     c += 10 + *s - 'a';
363   else
364     return -1;
365   return c;
366 }
367
368
369 /* Print a BUFFER to stream FP while replacing all control characters
370    and the characters DELIM and DELIM2 with standard C escape
371    sequences.  Returns the number of characters printed. */
372 size_t 
373 print_sanitized_buffer2 (FILE *fp, const void *buffer, size_t length,
374                          int delim, int delim2)
375 {
376   const unsigned char *p = buffer;
377   size_t count = 0;
378
379   for (; length; length--, p++, count++)
380     {
381       /* Fixme: Check whether *p < 0xa0 is correct for utf8 encoding. */
382       if (*p < 0x20 
383           || (*p >= 0x7f && *p < 0xa0)
384           || *p == delim 
385           || *p == delim2
386           || ((delim || delim2) && *p=='\\'))
387         {
388           putc ('\\', fp);
389           count++;
390           if (*p == '\n')
391             {
392               putc ('n', fp);
393               count++;
394             }
395           else if (*p == '\r')
396             {
397               putc ('r', fp);
398               count++;
399             }
400           else if (*p == '\f')
401             {
402               putc ('f', fp);
403               count++;
404             }
405           else if (*p == '\v')
406             {
407               putc ('v', fp);
408               count++;
409             }
410           else if (*p == '\b')
411             {
412               putc ('b', fp);
413               count++;
414             }
415           else if (!*p)
416             {
417               putc('0', fp);
418               count++;
419             }
420           else
421             {
422               fprintf (fp, "x%02x", *p);
423               count += 3;
424             }
425         }
426       else
427         {
428           putc (*p, fp);
429           count++;
430         }
431     }
432
433   return count;
434 }
435
436 /* Same as print_sanitized_buffer2 but with just one delimiter. */
437 size_t 
438 print_sanitized_buffer (FILE *fp, const void *buffer, size_t length,
439                         int delim)
440 {
441   return print_sanitized_buffer2 (fp, buffer, length, delim, 0);
442 }
443
444
445 size_t 
446 print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
447                              size_t length, int delim)
448 {
449   const char *p = buffer;
450   size_t i;
451
452   /* We can handle plain ascii simpler, so check for it first. */
453   for (i=0; i < length; i++ ) 
454     {
455       if ( (p[i] & 0x80) )
456         break;
457     }
458   if (i < length)
459     {
460         char *buf = utf8_to_native (p, length, delim);
461         /*(utf8 conversion already does the control character quoting)*/
462         i = strlen (buf);
463         fputs (buf, fp);
464         jnlib_free (buf);
465         return i;
466     }
467   else
468     return print_sanitized_buffer (fp, p, length, delim);
469 }
470
471
472 size_t 
473 print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2)
474 {
475   return string? print_sanitized_buffer2 (fp, string, strlen (string),
476                                           delim, delim2):0;
477 }
478
479 size_t 
480 print_sanitized_string (FILE *fp, const char *string, int delim)
481 {
482   return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
483 }
484
485 size_t 
486 print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
487 {
488   return string? print_sanitized_utf8_buffer (fp,
489                                               string, strlen (string),
490                                               delim) : 0;
491 }
492
493 /* Create a string from the buffer P_ARG of length N which is suitable for
494    printing.  Caller must release the created string using xfree. */
495 char *
496 sanitize_buffer (const void *p_arg, size_t n, int delim)
497 {
498   const unsigned char *p = p_arg;
499   size_t save_n, buflen;
500   const unsigned char *save_p;
501   char *buffer, *d;
502
503   /* First count length. */
504   for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) 
505     {
506       if ( *p < 0x20 || *p == 0x7f || *p == delim  || (delim && *p=='\\'))
507         {
508           if ( *p=='\n' || *p=='\r' || *p=='\f'
509                || *p=='\v' || *p=='\b' || !*p )
510             buflen += 2;
511           else
512             buflen += 5;
513         }
514       else
515         buflen++;
516     }
517   p = save_p;
518   n = save_n;
519   /* And now make the string */
520   d = buffer = jnlib_xmalloc( buflen );
521   for ( ; n; n--, p++ )
522     {
523       if (*p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\')) {
524         *d++ = '\\';
525         if( *p == '\n' )
526           *d++ = 'n';
527         else if( *p == '\r' )
528           *d++ = 'r';
529         else if( *p == '\f' )
530           *d++ = 'f';
531         else if( *p == '\v' )
532           *d++ = 'v';
533         else if( *p == '\b' )
534           *d++ = 'b';
535         else if( !*p )
536           *d++ = '0';
537         else {
538           sprintf(d, "x%02x", *p );
539           d += 3;
540         }
541       }
542       else
543         *d++ = *p;
544     }
545   *d = 0;
546   return buffer;
547 }
548
549
550 /****************************************************
551  **********  W32 specific functions  ****************
552  ****************************************************/
553
554 #ifdef HAVE_W32_SYSTEM
555 const char *
556 w32_strerror (int ec)
557 {
558   static char strerr[256];
559   
560   if (ec == -1)
561     ec = (int)GetLastError ();
562   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec,
563                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
564                  strerr, DIM (strerr)-1, NULL);
565   return strerr;    
566 }
567 #endif /*HAVE_W32_SYSTEM*/
568
569
570 /****************************************************
571  ******** Locale insensitive ctype functions ********
572  ****************************************************/
573 /* FIXME: replace them by a table lookup and macros */
574 int
575 ascii_isupper (int c)
576 {
577     return c >= 'A' && c <= 'Z';
578 }
579
580 int
581 ascii_islower (int c)
582 {
583     return c >= 'a' && c <= 'z';
584 }
585
586 int 
587 ascii_toupper (int c)
588 {
589     if (c >= 'a' && c <= 'z')
590         c &= ~0x20;
591     return c;
592 }
593
594 int 
595 ascii_tolower (int c)
596 {
597     if (c >= 'A' && c <= 'Z')
598         c |= 0x20;
599     return c;
600 }
601
602
603 int
604 ascii_strcasecmp( const char *a, const char *b )
605 {
606     if (a == b)
607         return 0;
608
609     for (; *a && *b; a++, b++) {
610         if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
611             break;
612     }
613     return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
614 }
615
616 int 
617 ascii_strncasecmp (const char *a, const char *b, size_t n)
618 {
619   const unsigned char *p1 = (const unsigned char *)a;
620   const unsigned char *p2 = (const unsigned char *)b;
621   unsigned char c1, c2;
622
623   if (p1 == p2 || !n )
624     return 0;
625
626   do
627     {
628       c1 = ascii_tolower (*p1);
629       c2 = ascii_tolower (*p2);
630
631       if ( !--n || c1 == '\0')
632         break;
633
634       ++p1;
635       ++p2;
636     }
637   while (c1 == c2);
638   
639   return c1 - c2;
640 }
641
642
643 int
644 ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
645 {
646   const char *a = a_arg;
647   const char *b = b_arg;
648
649   if (a == b)
650     return 0;
651   for ( ; n; n--, a++, b++ )
652     {
653       if( *a != *b  && ascii_toupper (*a) != ascii_toupper (*b) )
654         return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
655     }
656   return 0;
657 }
658
659 int
660 ascii_strcmp( const char *a, const char *b )
661 {
662     if (a == b)
663         return 0;
664
665     for (; *a && *b; a++, b++) {
666         if (*a != *b )
667             break;
668     }
669     return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
670 }
671
672
673 void *
674 ascii_memcasemem (const void *haystack, size_t nhaystack,
675                   const void *needle, size_t nneedle)
676 {
677
678   if (!nneedle)
679     return (void*)haystack; /* finding an empty needle is really easy */
680   if (nneedle <= nhaystack)
681     {
682       const char *a = haystack;
683       const char *b = a + nhaystack - nneedle;
684       
685       for (; a <= b; a++)
686         {
687           if ( !ascii_memcasecmp (a, needle, nneedle) )
688             return (void *)a;
689         }
690     }
691   return NULL;
692 }
693
694 /*********************************************
695  ********** missing string functions *********
696  *********************************************/
697
698 #ifndef HAVE_STPCPY
699 char *
700 stpcpy(char *a,const char *b)
701 {
702     while( *b )
703         *a++ = *b++;
704     *a = 0;
705
706     return (char*)a;
707 }
708 #endif
709
710 #ifndef HAVE_STRLWR
711 char *
712 strlwr(char *s)
713 {
714     char *p;
715     for(p=s; *p; p++ )
716         *p = tolower(*p);
717     return s;
718 }
719 #endif
720
721
722 #ifndef HAVE_STRCASECMP
723 int
724 strcasecmp( const char *a, const char *b )
725 {
726     for( ; *a && *b; a++, b++ ) {
727         if( *a != *b && toupper(*a) != toupper(*b) )
728             break;
729     }
730     return *(const byte*)a - *(const byte*)b;
731 }
732 #endif
733
734
735 /****************
736  * mingw32/cpd has a memicmp()
737  */
738 #ifndef HAVE_MEMICMP
739 int
740 memicmp( const char *a, const char *b, size_t n )
741 {
742     for( ; n; n--, a++, b++ )
743         if( *a != *b  && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
744             return *(const byte *)a - *(const byte*)b;
745     return 0;
746 }
747 #endif
748
749