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