Obsolete option --no-sig-create-check.
[gnupg.git] / util / miscutil.c
1 /* miscutil.c -  miscellaneous utilities
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003,
3  *               2004, 2005 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 3 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, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <time.h>
26 #include <ctype.h>
27 #ifdef HAVE_LANGINFO_H
28 #include <langinfo.h>
29 #endif
30 #include "types.h"
31 #include "util.h"
32 #include "i18n.h"
33
34 #ifndef HAVE_TIMEGM
35 time_t timegm (struct tm *tm);
36 #endif
37
38 #ifdef HAVE_UNSIGNED_TIME_T
39 # define INVALID_TIME_CHECK(a) ((a) == (time_t)(-1))
40 #else
41   /* Error or 32 bit time_t and value after 2038-01-19.  */
42 # define INVALID_TIME_CHECK(a) ((a) < 0)
43 #endif
44
45 /****************
46  * I know that the OpenPGP protocol has a Y2106 problem ;-)
47  */
48 u32
49 make_timestamp()
50 {
51     return time(NULL);
52 }
53
54 /****************
55  * Scan a date string and return a timestamp.
56  * The only supported format is "yyyy-mm-dd"
57  * Returns 0 for an invalid date.
58  */
59 u32
60 scan_isodatestr( const char *string )
61 {
62     int year, month, day;
63     struct tm tmbuf;
64     time_t stamp;
65     int i;
66
67     if( strlen(string) != 10 || string[4] != '-' || string[7] != '-' )
68         return 0;
69     for( i=0; i < 4; i++ )
70         if( !digitp(string+i) )
71             return 0;
72     if( !digitp(string+5) || !digitp(string+6) )
73         return 0;
74     if( !digitp(string+8) || !digitp(string+9) )
75         return 0;
76     year = atoi(string);
77     month = atoi(string+5);
78     day = atoi(string+8);
79     /* some basic checks */
80     if( year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 )
81         return 0;
82     memset( &tmbuf, 0, sizeof tmbuf );
83     tmbuf.tm_mday = day;
84     tmbuf.tm_mon = month-1;
85     tmbuf.tm_year = year - 1900;
86     tmbuf.tm_isdst = -1;
87     stamp = mktime( &tmbuf );
88     if( stamp == (time_t)-1 )
89         return 0;
90     return stamp;
91 }
92
93
94 /****************
95  * Return a string with a time value in the form: x Y, n D, n H
96  */
97
98 const char *
99 strtimevalue( u32 value )
100 {
101     static char buffer[30];
102     unsigned int years, days, hours, minutes;
103
104     value /= 60;
105     minutes = value % 60;
106     value /= 60;
107     hours = value % 24;
108     value /= 24;
109     days = value % 365;
110     value /= 365;
111     years = value;
112
113     sprintf(buffer,"%uy%ud%uh%um", years, days, hours, minutes );
114     if( years )
115         return buffer;
116     if( days )
117         return strchr( buffer, 'y' ) + 1;
118     return strchr( buffer, 'd' ) + 1;
119 }
120
121
122 /****************
123  * Note: this function returns GMT
124  */
125 const char *
126 strtimestamp( u32 stamp )
127 {
128     static char buffer[11+5];
129     struct tm *tp;
130     time_t atime = stamp;
131
132     if (INVALID_TIME_CHECK (atime)) {
133         strcpy (buffer, "????" "-??" "-??");
134     }
135     else {
136         tp = gmtime( &atime );
137         sprintf(buffer,"%04d-%02d-%02d",
138                 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
139     }
140     return buffer;
141 }
142
143
144 /****************
145  * Note: this function returns GMT
146  */
147 const char *
148 isotimestamp (u32 stamp)
149 {
150     static char buffer[25+5];
151     struct tm *tp;
152     time_t atime = stamp;
153
154     if (INVALID_TIME_CHECK (atime)) {
155         strcpy (buffer, "????" "-??" "-??" " " "??" ":" "??" ":" "??");
156     }
157     else {
158         tp = gmtime( &atime );
159         sprintf(buffer,"%04d-%02d-%02d %02d:%02d:%02d",
160                 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
161                 tp->tm_hour, tp->tm_min, tp->tm_sec);
162     }
163     return buffer;
164 }
165
166
167 /* Scan am ISO timestamp and return an Epoch based timestamp.  The only
168    supported format is "yyyymmddThhmmss" delimited by white space, nul, a
169    colon or a comma.  Returns 0 for an invalid string. */
170 u32
171 isotime2seconds (const char *string)
172 {
173   const char *s;
174   int year, month, day, hour, minu, sec;
175   struct tm tmbuf;
176   int i;
177   time_t result;
178
179   if (!*string)
180     return 0;
181   for (s=string, i=0; i < 8; i++, s++)
182     if (!digitp (s))
183       return 0;
184   if (*s != 'T')
185       return 0;
186   for (s++, i=9; i < 15; i++, s++)
187     if (!digitp (s))
188       return 0;
189   if ( !(!*s || (isascii (*s) && isspace(*s)) || *s == ':' || *s == ','))
190     return 0;  /* Wrong delimiter.  */
191
192   year  = atoi_4 (string);
193   month = atoi_2 (string + 4);
194   day   = atoi_2 (string + 6);
195   hour  = atoi_2 (string + 9);
196   minu  = atoi_2 (string + 11);
197   sec   = atoi_2 (string + 13);
198
199   /* Basic checks.  */
200   if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31
201       || hour > 23 || minu > 59 || sec > 61 )
202     return 0;
203
204   memset (&tmbuf, 0, sizeof tmbuf);
205   tmbuf.tm_sec  = sec;
206   tmbuf.tm_min  = minu;
207   tmbuf.tm_hour = hour;
208   tmbuf.tm_mday = day;
209   tmbuf.tm_mon  = month-1;
210   tmbuf.tm_year = year - 1900;
211   tmbuf.tm_isdst = -1;
212   result = timegm (&tmbuf);
213   return (result == (time_t)(-1))? 0 : (u32)result;
214 }
215
216
217 /****************
218  * Note: this function returns local time
219  */
220 const char *
221 asctimestamp( u32 stamp )
222 {
223     static char buffer[50];
224 #if defined (HAVE_STRFTIME) && defined (HAVE_NL_LANGINFO)
225       static char fmt[50];
226 #endif
227     struct tm *tp;
228     time_t atime = stamp;
229
230     if (INVALID_TIME_CHECK (atime))
231       {
232         strcpy (buffer, "????" "-??" "-??");
233         return buffer;
234       }
235
236     tp = localtime( &atime );
237 #ifdef HAVE_STRFTIME
238 #if defined(HAVE_NL_LANGINFO)
239 # if GNUPG_GCC_VERSION >= 40600
240 #  pragma GCC diagnostic push
241 #  pragma GCC diagnostic ignored "-Wformat-nonliteral"
242 # endif
243       mem2str( fmt, nl_langinfo(D_T_FMT), DIM(fmt)-3 );
244       if( strstr( fmt, "%Z" ) == NULL )
245         strcat( fmt, " %Z");
246       strftime( buffer, DIM(buffer)-1, fmt, tp );
247 # if GNUPG_GCC_VERSION >= 40600
248 #  pragma GCC diagnostic pop
249 # endif
250 #else
251       /* fixme: we should check whether the locale appends a " %Z"
252        * These locales from glibc don't put the " %Z":
253        * fi_FI hr_HR ja_JP lt_LT lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN
254        */
255       strftime( buffer, DIM(buffer)-1,
256 #ifdef HAVE_W32_SYSTEM
257                 "%c"
258 #else
259                 "%c %Z"
260 #endif
261                 , tp );
262 #endif
263     buffer[DIM(buffer)-1] = 0;
264 #else
265     mem2str( buffer, asctime(tp), DIM(buffer) );
266 #endif
267     return buffer;
268 }
269
270
271 /****************
272  * Print a string to FP, but filter all control characters out.
273  */
274 void
275 print_string2( FILE *fp, const byte *p, size_t n, int delim, int delim2 )
276 {
277     for( ; n; n--, p++ )
278         if (*p < 0x20
279             || *p == 0x7f
280             || *p == delim || *p == delim2
281             || ((delim || delim2) && *p=='\\'))
282           {
283             putc('\\', fp);
284             if( *p == '\n' )
285                 putc('n', fp);
286             else if( *p == '\r' )
287                 putc('r', fp);
288             else if( *p == '\f' )
289                 putc('f', fp);
290             else if( *p == '\v' )
291                 putc('v', fp);
292             else if( *p == '\b' )
293                 putc('b', fp);
294             else if( !*p )
295                 putc('0', fp);
296             else
297                 fprintf(fp, "x%02x", *p );
298           }
299         else
300           putc(*p, fp);
301 }
302
303 void
304 print_string( FILE *fp, const byte *p, size_t n, int delim )
305 {
306   print_string2(fp,p,n,delim,0);
307 }
308
309 /****************
310  * Print an UTF8 string to FP and filter all control characters out.
311  */
312 void
313 print_utf8_string2 ( FILE *fp, const byte *p, size_t n, int delim )
314 {
315     size_t i;
316     char *buf;
317
318     /* we can handle plain ascii simpler, so check for it first */
319     for(i=0; i < n; i++ ) {
320         if( p[i] & 0x80 )
321             break;
322     }
323     if( i < n ) {
324         buf = utf8_to_native ( p, n, delim );
325         /*(utf8 conversion already does the control character quoting)*/
326         fputs( buf, fp );
327         xfree( buf );
328     }
329     else
330         print_string( fp, p, n, delim );
331 }
332
333 void
334 print_utf8_string( FILE *fp, const byte *p, size_t n )
335 {
336     print_utf8_string2 (fp, p, n, 0);
337 }
338
339 /****************
340  * This function returns a string which is suitable for printing
341  * Caller must release it with xfree()
342  */
343 char *
344 make_printable_string( const byte *p, size_t n, int delim )
345 {
346     size_t save_n, buflen;
347     const byte *save_p;
348     char *buffer, *d;
349
350     /* first count length */
351     for(save_n = n, save_p = p, buflen=1 ; n; n--, p++ ) {
352         if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim ||
353             (delim && *p=='\\')) {
354             if( *p=='\n' || *p=='\r' || *p=='\f'
355                 || *p=='\v' || *p=='\b' || !*p )
356                 buflen += 2;
357             else
358                 buflen += 4;
359         }
360         else
361             buflen++;
362     }
363     p = save_p;
364     n = save_n;
365     /* and now make the string */
366     d = buffer = xmalloc( buflen );
367     for( ; n; n--, p++ ) {
368         if( *p < 0x20 || (*p >= 0x7f && *p < 0xa0) || *p == delim ||
369             (delim && *p=='\\')) {
370             *d++ = '\\';
371             if( *p == '\n' )
372                 *d++ = 'n';
373             else if( *p == '\r' )
374                 *d++ = 'r';
375             else if( *p == '\f' )
376                 *d++ = 'f';
377             else if( *p == '\v' )
378                 *d++ = 'v';
379             else if( *p == '\b' )
380                 *d++ = 'b';
381             else if( !*p )
382                 *d++ = '0';
383             else {
384                 sprintf(d, "x%02x", *p );
385                 d += 3;
386             }
387         }
388         else
389             *d++ = *p;
390     }
391     *d = 0;
392     return buffer;
393 }
394
395 int
396 answer_is_yes_no_default( const char *s, int def_answer )
397 {
398     /* TRANSLATORS: See doc/TRANSLATE about this string. */
399     const char *long_yes = _("yes");
400     const char *short_yes = _("yY");
401     /* TRANSLATORS: See doc/TRANSLATE about this string. */
402     const char *long_no = _("no");
403     const char *short_no = _("nN");
404
405     /* Note: we have to use the local dependent strcasecmp here */
406     if( match_multistr(long_yes,s) )
407         return 1;
408     if( *s && strchr( short_yes, *s ) && !s[1] )
409         return 1;
410     /* test for no strings to catch ambiguities for the next test */
411     if( match_multistr(long_no,s) )
412         return 0;
413     if( *s && strchr( short_no, *s ) && !s[1] )
414         return 0;
415     /* test for the english version (for those who are used to type yes) */
416     if( !ascii_strcasecmp(s, "yes" ) )
417         return 1;
418     if( *s && strchr( "yY", *s ) && !s[1] )
419         return 1;
420     return def_answer;
421 }
422
423 int
424 answer_is_yes( const char *s )
425 {
426   return answer_is_yes_no_default(s,0);
427 }
428
429 /****************
430  * Return 1 for yes, -1 for quit, or 0 for no
431  */
432 int
433 answer_is_yes_no_quit( const char *s )
434 {
435     /* TRANSLATORS: See doc/TRANSLATE about this string. */
436     const char *long_yes = _("yes");
437     /* TRANSLATORS: See doc/TRANSLATE about this string. */
438     const char *long_no = _("no");
439     /* TRANSLATORS: See doc/TRANSLATE about this string. */
440     const char *long_quit = _("quit");
441     const char *short_yes = _("yY");
442     const char *short_no = _("nN");
443     const char *short_quit = _("qQ");
444
445     if( match_multistr(long_no,s) )
446         return 0;
447     if( match_multistr(long_yes,s) )
448         return 1;
449     if( match_multistr(long_quit,s) )
450         return -1;
451     if( *s && strchr( short_no, *s ) && !s[1] )
452         return 0;
453     if( *s && strchr( short_yes, *s ) && !s[1] )
454         return 1;
455     if( *s && strchr( short_quit, *s ) && !s[1] )
456         return -1;
457     /* but not here */
458     if( !ascii_strcasecmp(s, "yes" ) )
459         return 1;
460     if( !ascii_strcasecmp(s, "quit" ) )
461         return -1;
462     if( *s && strchr( "yY", *s ) && !s[1] )
463         return 1;
464     if( *s && strchr( "qQ", *s ) && !s[1] )
465         return -1;
466     return 0;
467 }
468
469 /*
470    Return 1 for okay, 0 for for cancel or DEF_ANSWER for default.
471  */
472 int
473 answer_is_okay_cancel (const char *s, int def_answer)
474 {
475   /* TRANSLATORS: See doc/TRANSLATE about this string. */
476   const char *long_okay = _("okay|okay");
477   /* TRANSLATORS: See doc/TRANSLATE about this string. */
478   const char *long_cancel = _("cancel|cancel");
479   const char *short_okay = _("oO");
480   const char *short_cancel = _("cC");
481
482   /* Note: We have to use the locale dependent strcasecmp */
483   if ( match_multistr(long_okay,s) )
484     return 1;
485   if ( match_multistr(long_cancel,s) )
486     return 0;
487   if ( *s && strchr( short_okay, *s ) && !s[1] )
488     return 1;
489   if ( *s && strchr( short_cancel, *s ) && !s[1] )
490     return 0;
491   /* Always test for the English values (not locale here) */
492   if ( !ascii_strcasecmp(s, "okay" ) )
493     return 1;
494   if ( !ascii_strcasecmp(s, "ok" ) )
495     return 1;
496   if ( !ascii_strcasecmp(s, "cancel" ) )
497     return 0;
498   if ( *s && strchr( "oO", *s ) && !s[1] )
499     return 1;
500   if ( *s && strchr( "cC", *s ) && !s[1] )
501     return 0;
502   return def_answer;
503 }
504
505 /* Try match against each substring of multistr, delimited by | */
506 int
507 match_multistr(const char *multistr,const char *match)
508 {
509   do
510     {
511       size_t seglen=strcspn(multistr,"|");
512       if(!seglen)
513         break;
514       /* Using the localized strncasecmp */
515       if(strncasecmp(multistr,match,seglen)==0)
516         return 1;
517       multistr+=seglen;
518       if(*multistr=='|')
519         multistr++;
520     }
521   while(*multistr);
522
523   return 0;
524 }