Use cancel button in confirmation only if requested.
[gnupg.git] / jnlib / stringhelp.c
blob3760c1db322cd2d838b25ad9e043b20767e44f85
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.
5 * This file is part of JNLIB.
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.
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.
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/>.
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
30 #include "libjnlib-config.h"
31 #include "utf8conv.h"
32 #include "stringhelp.h"
35 #define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
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)
45 #ifdef HAVE_DRIVE_LETTERS
46 char *p;
48 if (strchr (name, '\\'))
50 for (p=name; *p; p++)
51 if (*p == '/')
52 *p = '\\';
54 #endif /*HAVE_DRIVE_LETTERS*/
55 return name;
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.
64 const char *
65 memistr (const void *buffer, size_t buflen, const char *sub)
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;
72 for ( ; n ; t++, n-- )
74 if ( toupper (*t) == toupper (*s) )
76 for ( buf=t++, buflen = n--, s++;
77 n && toupper (*t) == toupper (*s); t++, s++, n-- )
79 if (!*s)
80 return (const char*)buf;
81 t = buf;
82 s = (const unsigned char *)sub ;
83 n = buflen;
86 return NULL;
89 const char *
90 ascii_memistr ( const void *buffer, size_t buflen, const char *sub )
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;
97 for ( ; n ; t++, n-- )
99 if (ascii_toupper (*t) == ascii_toupper (*s) )
101 for ( buf=t++, buflen = n--, s++;
102 n && ascii_toupper (*t) == ascii_toupper (*s); t++, s++, n-- )
104 if (!*s)
105 return (const char*)buf;
106 t = (const unsigned char *)buf;
107 s = (const unsigned char *)sub ;
108 n = buflen;
111 return NULL;
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.
121 char *
122 mem2str( char *dest , const void *src , size_t n )
124 char *d;
125 const char *s;
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' ;
137 return dest ;
141 /****************
142 * remove leading and trailing white spaces
144 char *
145 trim_spaces( char *str )
147 char *string, *p, *mark;
149 string = str;
150 /* find first non space character */
151 for( p=string; *p && isspace( *(byte*)p ) ; p++ )
153 /* move characters */
154 for( (mark = NULL); (*string = *p); string++, p++ )
155 if( isspace( *(byte*)p ) ) {
156 if( !mark )
157 mark = string ;
159 else
160 mark = NULL ;
161 if( mark )
162 *mark = '\0' ; /* remove trailing spaces */
164 return str ;
167 /****************
168 * remove trailing white spaces
170 char *
171 trim_trailing_spaces( char *string )
173 char *p, *mark;
175 for( mark = NULL, p = string; *p; p++ ) {
176 if( isspace( *(byte*)p ) ) {
177 if( !mark )
178 mark = p;
180 else
181 mark = NULL;
183 if( mark )
184 *mark = '\0' ;
186 return string ;
190 unsigned
191 trim_trailing_chars( byte *line, unsigned len, const char *trimchars )
193 byte *p, *mark;
194 unsigned n;
196 for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
197 if( strchr(trimchars, *p ) ) {
198 if( !mark )
199 mark = p;
201 else
202 mark = NULL;
205 if( mark ) {
206 *mark = 0;
207 return mark - line;
209 return len;
212 /****************
213 * remove trailing white spaces and return the length of the buffer
215 unsigned
216 trim_trailing_ws( byte *line, unsigned len )
218 return trim_trailing_chars( line, len, " \t\r\n" );
221 size_t
222 length_sans_trailing_chars (const unsigned char *line, size_t len,
223 const char *trimchars )
225 const unsigned char *p, *mark;
226 size_t n;
228 for( mark=NULL, p=line, n=0; n < len; n++, p++ )
230 if (strchr (trimchars, *p ))
232 if( !mark )
233 mark = p;
235 else
236 mark = NULL;
239 if (mark)
240 return mark - line;
241 return len;
245 * Return the length of line ignoring trailing white-space.
247 size_t
248 length_sans_trailing_ws (const unsigned char *line, size_t len)
250 return length_sans_trailing_chars (line, len, " \t\r\n");
255 /***************
256 * Extract from a given path the filename component.
259 char *
260 make_basename(const char *filepath, const char *inputpath)
262 #ifdef __riscos__
263 return riscos_make_basename(filepath, inputpath);
264 #else
265 char *p;
267 (void)inputpath; /* Only required for riscos. */
269 if ( !(p=strrchr(filepath, '/')) )
270 #ifdef HAVE_DRIVE_LETTERS
271 if ( !(p=strrchr(filepath, '\\')) )
272 if ( !(p=strrchr(filepath, ':')) )
273 #endif
275 return jnlib_xstrdup(filepath);
278 return jnlib_xstrdup(p+1);
279 #endif
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 ('.').
290 char *
291 make_dirname(const char *filepath)
293 char *dirname;
294 int dirname_length;
295 char *p;
297 if ( !(p=strrchr(filepath, '/')) )
298 #ifdef HAVE_DRIVE_LETTERS
299 if ( !(p=strrchr(filepath, '\\')) )
300 if ( !(p=strrchr(filepath, ':')) )
301 #endif
303 return jnlib_xstrdup(".");
306 dirname_length = p-filepath;
307 dirname = jnlib_xmalloc(dirname_length+1);
308 strncpy(dirname, filepath, dirname_length);
309 dirname[dirname_length] = 0;
311 return dirname;
316 /* Implementation of make_filename and make_filename_try. We need to
317 use macros here to avoid the use of the sometimes problematic
318 va_copy function 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; \
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); \
331 home = NULL; \
332 if ( *first_part == '~' && first_part[1] == '/' \
333 && (home = getenv("HOME")) && *home ) \
334 n += strlen (home);
336 #define MAKE_FILENAME_PART2 \
337 p = (home \
338 ? stpcpy (stpcpy (name,home), first_part + 1)\
339 : stpcpy(name, first_part)); \
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);
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, ... )
353 MAKE_FILENAME_PART1
354 name = jnlib_xmalloc (n);
355 MAKE_FILENAME_PART2
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, ... )
363 MAKE_FILENAME_PART1
364 name = jnlib_xmalloc (n);
365 if (!name)
366 return NULL;
367 MAKE_FILENAME_PART2
369 #undef MAKE_FILENAME_PART1
370 #undef MAKE_FILENAME_PART2
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(). */
380 compare_filenames (const char *a, const char *b)
382 #ifdef HAVE_DRIVE_LETTERS
383 for ( ; *a && *b; a++, b++ )
385 if (*a != *b
386 && (toupper (*(const unsigned char*)a)
387 != toupper (*(const unsigned char*)b) )
388 && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')))
389 break;
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
402 /* Convert 2 hex characters at S to a byte value. Return this value
403 or -1 if there is an error. */
405 hextobyte (const char *s)
407 int c;
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;
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)
437 const unsigned char *p = buffer;
438 size_t count = 0;
440 for (; length; length--, p++, count++)
442 if (*p < 0x20
443 || *p == 0x7f
444 || *p == delim
445 || *p == delim2
446 || ((delim || delim2) && *p=='\\'))
448 putc ('\\', fp);
449 count++;
450 if (*p == '\n')
452 putc ('n', fp);
453 count++;
455 else if (*p == '\r')
457 putc ('r', fp);
458 count++;
460 else if (*p == '\f')
462 putc ('f', fp);
463 count++;
465 else if (*p == '\v')
467 putc ('v', fp);
468 count++;
470 else if (*p == '\b')
472 putc ('b', fp);
473 count++;
475 else if (!*p)
477 putc('0', fp);
478 count++;
480 else
482 fprintf (fp, "x%02x", *p);
483 count += 3;
486 else
488 putc (*p, fp);
489 count++;
493 return count;
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)
501 return print_sanitized_buffer2 (fp, buffer, length, delim, 0);
505 size_t
506 print_sanitized_utf8_buffer (FILE *fp, const void *buffer,
507 size_t length, int delim)
509 const char *p = buffer;
510 size_t i;
512 /* We can handle plain ascii simpler, so check for it first. */
513 for (i=0; i < length; i++ )
515 if ( (p[i] & 0x80) )
516 break;
518 if (i < length)
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;
527 else
528 return print_sanitized_buffer (fp, p, length, delim);
532 size_t
533 print_sanitized_string2 (FILE *fp, const char *string, int delim, int delim2)
535 return string? print_sanitized_buffer2 (fp, string, strlen (string),
536 delim, delim2):0;
539 size_t
540 print_sanitized_string (FILE *fp, const char *string, int delim)
542 return string? print_sanitized_buffer (fp, string, strlen (string), delim):0;
545 size_t
546 print_sanitized_utf8_string (FILE *fp, const char *string, int delim)
548 return string? print_sanitized_utf8_buffer (fp,
549 string, strlen (string),
550 delim) : 0;
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)
558 const unsigned char *p = p_arg;
559 size_t save_n, buflen;
560 const unsigned char *save_p;
561 char *buffer, *d;
563 /* First count length. */
564 for (save_n = n, save_p = p, buflen=1 ; n; n--, p++ )
566 if ( *p < 0x20 || *p == 0x7f || *p == delim || (delim && *p=='\\'))
568 if ( *p=='\n' || *p=='\r' || *p=='\f'
569 || *p=='\v' || *p=='\b' || !*p )
570 buflen += 2;
571 else
572 buflen += 5;
574 else
575 buflen++;
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++ )
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;
602 else
603 *d++ = *p;
605 *d = 0;
606 return buffer;
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)
617 size_t n;
619 for (n=0; *s; s++)
620 if ( (*s&0xc0) != 0x80 ) /* Exclude continuation bytes: 10xxxxxx */
621 n++;
623 return n;
627 /****************************************************
628 ********** W32 specific functions ****************
629 ****************************************************/
631 #ifdef HAVE_W32_SYSTEM
632 const char *
633 w32_strerror (int ec)
635 static char strerr[256];
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;
644 #endif /*HAVE_W32_SYSTEM*/
647 /****************************************************
648 ******** Locale insensitive ctype functions ********
649 ****************************************************/
650 /* FIXME: replace them by a table lookup and macros */
652 ascii_isupper (int c)
654 return c >= 'A' && c <= 'Z';
658 ascii_islower (int c)
660 return c >= 'a' && c <= 'z';
663 int
664 ascii_toupper (int c)
666 if (c >= 'a' && c <= 'z')
667 c &= ~0x20;
668 return c;
671 int
672 ascii_tolower (int c)
674 if (c >= 'A' && c <= 'Z')
675 c |= 0x20;
676 return c;
681 ascii_strcasecmp( const char *a, const char *b )
683 if (a == b)
684 return 0;
686 for (; *a && *b; a++, b++) {
687 if (*a != *b && ascii_toupper(*a) != ascii_toupper(*b))
688 break;
690 return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
693 int
694 ascii_strncasecmp (const char *a, const char *b, size_t n)
696 const unsigned char *p1 = (const unsigned char *)a;
697 const unsigned char *p2 = (const unsigned char *)b;
698 unsigned char c1, c2;
700 if (p1 == p2 || !n )
701 return 0;
705 c1 = ascii_tolower (*p1);
706 c2 = ascii_tolower (*p2);
708 if ( !--n || c1 == '\0')
709 break;
711 ++p1;
712 ++p2;
714 while (c1 == c2);
716 return c1 - c2;
721 ascii_memcasecmp (const void *a_arg, const void *b_arg, size_t n )
723 const char *a = a_arg;
724 const char *b = b_arg;
726 if (a == b)
727 return 0;
728 for ( ; n; n--, a++, b++ )
730 if( *a != *b && ascii_toupper (*a) != ascii_toupper (*b) )
731 return *a == *b? 0 : (ascii_toupper (*a) - ascii_toupper (*b));
733 return 0;
737 ascii_strcmp( const char *a, const char *b )
739 if (a == b)
740 return 0;
742 for (; *a && *b; a++, b++) {
743 if (*a != *b )
744 break;
746 return *a == *b? 0 : (*(signed char *)a - *(signed char *)b);
750 void *
751 ascii_memcasemem (const void *haystack, size_t nhaystack,
752 const void *needle, size_t nneedle)
755 if (!nneedle)
756 return (void*)haystack; /* finding an empty needle is really easy */
757 if (nneedle <= nhaystack)
759 const char *a = haystack;
760 const char *b = a + nhaystack - nneedle;
762 for (; a <= b; a++)
764 if ( !ascii_memcasecmp (a, needle, nneedle) )
765 return (void *)a;
768 return NULL;
771 /*********************************************
772 ********** missing string functions *********
773 *********************************************/
775 #ifndef HAVE_STPCPY
776 char *
777 stpcpy(char *a,const char *b)
779 while( *b )
780 *a++ = *b++;
781 *a = 0;
783 return (char*)a;
785 #endif
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)
792 char *begin, *end;
794 begin = *stringp;
795 if (begin == NULL)
796 return NULL;
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')
803 char ch = delim[0];
805 if (ch == '\0')
806 end = NULL;
807 else
809 if (*begin == ch)
810 end = begin;
811 else if (*begin == '\0')
812 end = NULL;
813 else
814 end = strchr (begin + 1, ch);
817 else
818 /* Find the end of the token. */
819 end = strpbrk (begin, delim);
821 if (end)
823 /* Terminate the token and set *STRINGP past NUL character. */
824 *end++ = '\0';
825 *stringp = end;
827 else
828 /* No more delimiters; this is the last token. */
829 *stringp = NULL;
831 return begin;
833 #endif /*HAVE_STRSEP*/
836 #ifndef HAVE_STRLWR
837 char *
838 strlwr(char *s)
840 char *p;
841 for(p=s; *p; p++ )
842 *p = tolower(*p);
843 return s;
845 #endif
848 #ifndef HAVE_STRCASECMP
850 strcasecmp( const char *a, const char *b )
852 for( ; *a && *b; a++, b++ ) {
853 if( *a != *b && toupper(*a) != toupper(*b) )
854 break;
856 return *(const byte*)a - *(const byte*)b;
858 #endif
861 /****************
862 * mingw32/cpd has a memicmp()
864 #ifndef HAVE_MEMICMP
866 memicmp( const char *a, const char *b, size_t n )
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;
873 #endif
876 #ifndef HAVE_MEMRCHR
877 void *
878 memrchr (const void *buffer, int c, size_t n)
880 const unsigned char *p = buffer;
882 for (p += n; n ; n--)
883 if (*--p == c)
884 return (void *)p;
885 return NULL;
887 #endif /*HAVE_MEMRCHR*/
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)
895 int i, j;
896 char *ptr;
898 if (!str)
899 return NULL;
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
908 ptr = jnlib_malloc (i + 2 * j + 1);
909 if (!ptr)
910 return NULL;
912 i = 0;
913 while (*str)
915 if (*str == ':')
917 ptr[i++] = '%';
918 ptr[i++] = '3';
919 ptr[i++] = 'a';
921 else if (*str == '%')
923 ptr[i++] = '%';
924 ptr[i++] = '2';
925 ptr[i++] = '5';
927 else if (extra && strchr (extra, *str))
929 ptr[i++] = '%';
930 ptr[i++] = tohex_lower ((*str>>4)&15);
931 ptr[i++] = tohex_lower (*str&15);
933 else
934 ptr[i++] = *str;
935 str++;
937 ptr[i] = '\0';
939 return ptr;
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)
947 return do_percent_escape (str, extra, 1);
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)
955 return do_percent_escape (str, extra, 0);