0ff7d98d791237684df00166d91be95be1b912b5
[gnupg.git] / common / miscellaneous.c
1 /* miscellaneous.c - Stuff not fitting elsewhere
2  *      Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <errno.h>
23
24 #define JNLIB_NEED_LOG_LOGV
25 #include "util.h"
26 #include "iobuf.h"
27 #include "i18n.h"
28
29 /* Used by libgcrypt for logging.  */
30 static void
31 my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
32 {
33   (void)dummy;
34   
35   /* Map the log levels.  */
36   switch (level)
37     {
38     case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
39     case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
40     case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
41     case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
42     case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
43     case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
44     case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
45     default:            level = JNLIB_LOG_ERROR; break;  
46     }
47   log_logv (level, fmt, arg_ptr);
48 }
49
50
51 /* This function is called by libgcrypt on a fatal error.  */
52 static void
53 my_gcry_fatalerror_handler (void *opaque, int rc, const char *text)
54 {
55   (void)opaque;
56
57   log_fatal ("libgcrypt problem: %s\n", text ? text : gpg_strerror (rc));
58   abort ();
59 }
60
61
62 /* This function is called by libgcrypt if it ran out of core and
63    there is no way to return that error to the caller.  We do our own
64    function here to make use of our logging functions. */
65 static int
66 my_gcry_outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
67 {
68   static int been_here;  /* Used to protect against recursive calls. */
69
70   (void)opaque;
71
72   if (!been_here)
73     {
74       been_here = 1;
75       if ( (flags & 1) )
76         log_fatal (_("out of core in secure memory "
77                      "while allocating %lu bytes"), (unsigned long)req_n);
78       else
79         log_fatal (_("out of core while allocating %lu bytes"),
80                    (unsigned long)req_n);
81     }
82   return 0; /* Let libgcrypt call its own fatal error handler.
83                Actually this will turn out to be
84                my_gcry_fatalerror_handler. */
85 }
86
87
88 /* Setup libgcrypt to use our own logging functions.  Should be used
89    early at startup. */
90 void
91 setup_libgcrypt_logging (void)
92 {
93   gcry_set_log_handler (my_gcry_logger, NULL);
94   gcry_set_fatalerror_handler (my_gcry_fatalerror_handler, NULL);
95   gcry_set_outofcore_handler (my_gcry_outofcore_handler, NULL);
96 }
97
98 /* A wrapper around gcry_cipher_algo_name to return the string
99    "AES-128" instead of "AES".  Given that we have an alias in
100    libgcrypt for it, it does not harm to too much to return this other
101    string.  Some users complained that we print "AES" but "AES192"
102    and "AES256".  We can't fix that in libgcrypt but it is pretty
103    safe to do it in an application. */
104 const char *
105 gnupg_cipher_algo_name (int algo) 
106 {
107   const char *s;
108
109   s = gcry_cipher_algo_name (algo);
110   if (!strcmp (s, "AES"))
111     s = "AES128";
112   return s;
113 }
114
115
116 /* Decide whether the filename is stdout or a real filename and return
117  * an appropriate string.  */
118 const char *
119 print_fname_stdout (const char *s)
120 {
121     if( !s || (*s == '-' && !s[1]) )
122         return "[stdout]";
123     return s;
124 }
125
126
127 /* Decide whether the filename is stdin or a real filename and return
128  * an appropriate string.  */
129 const char *
130 print_fname_stdin (const char *s)
131 {
132     if( !s || (*s == '-' && !s[1]) )
133         return "[stdin]";
134     return s;
135 }
136
137
138 void
139 print_utf8_buffer2 (estream_t stream, const void *p, size_t n, int delim)
140 {
141   char tmp[2];
142   
143   tmp[0] = delim;
144   tmp[1] = 0;
145   es_write_sanitized_utf8_buffer (stream, p, n, tmp, NULL);
146 }
147
148
149 void
150 print_utf8_buffer (estream_t stream, const void *p, size_t n)
151 {
152   es_write_sanitized_utf8_buffer (stream, p, n, NULL, NULL);
153 }
154
155 /* Write LENGTH bytes of BUFFER to FP as a hex encoded string.
156    RESERVED must be 0. */
157 void
158 print_hexstring (FILE *fp, const void *buffer, size_t length, int reserved)
159 {
160 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
161   const unsigned char *s;
162
163   (void)reserved;
164
165   for (s = buffer; length; s++, length--)
166     {
167       putc ( tohex ((*s>>4)&15), fp);
168       putc ( tohex (*s&15), fp);
169     }
170 #undef tohex
171 }
172
173 char *
174 make_printable_string (const void *p, size_t n, int delim )
175 {
176   return sanitize_buffer (p, n, delim);
177 }
178
179
180
181 /*
182  * Check if the file is compressed.
183  */
184 int
185 is_file_compressed (const char *s, int *ret_rc)
186 {
187     iobuf_t a;
188     byte buf[4];
189     int i, rc = 0;
190     int overflow;
191
192     struct magic_compress_s {
193         size_t len;
194         byte magic[4];
195     } magic[] = {
196         { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
197         { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
198         { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
199     };
200     
201     if ( iobuf_is_pipe_filename (s) || !ret_rc )
202         return 0; /* We can't check stdin or no file was given */
203
204     a = iobuf_open( s );
205     if ( a == NULL ) {
206         *ret_rc = gpg_error_from_syserror ();
207         return 0;
208     }
209
210     if ( iobuf_get_filelength( a, &overflow ) < 4 && !overflow) {
211         *ret_rc = 0;
212         goto leave;
213     }
214
215     if ( iobuf_read( a, buf, 4 ) == -1 ) {
216         *ret_rc = a->error;
217         goto leave;
218     }
219
220     for ( i = 0; i < DIM( magic ); i++ ) {
221         if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
222             *ret_rc = 0;
223             rc = 1;
224             break;
225         }
226     }
227
228 leave:    
229     iobuf_close( a );
230     return rc;
231 }
232
233
234 /* Try match against each substring of multistr, delimited by | */
235 int
236 match_multistr (const char *multistr,const char *match)
237 {
238   do
239     {
240       size_t seglen = strcspn (multistr,"|");
241       if (!seglen)
242         break;
243       /* Using the localized strncasecmp! */
244       if (strncasecmp(multistr,match,seglen)==0)
245         return 1;
246       multistr += seglen;
247       if (*multistr == '|')
248         multistr++;
249     }
250   while (*multistr);
251
252   return 0;
253 }
254
255
256 \f
257 /* Parse the first portion of the version number S and store it at
258    NUMBER.  On success, the function returns a pointer into S starting
259    with the first character, which is not part of the initial number
260    portion; on failure, NULL is returned.  */
261 static const char*
262 parse_version_number (const char *s, int *number)
263 {
264   int val = 0;
265   
266   if (*s == '0' && digitp (s+1))
267     return NULL; /* Leading zeros are not allowed.  */
268   for (; digitp (s); s++ )
269     {
270       val *= 10;
271       val += *s - '0';
272     }
273   *number = val;
274   return val < 0? NULL : s;
275 }
276
277 /* Break up the complete string representation of the version number S,
278    which is expected to have this format:
279
280       <major number>.<minor number>.<micro number><patch level>.
281
282    The major, minor and micro number components will be stored at
283    MAJOR, MINOR and MICRO. On success, a pointer to the last
284    component, the patch level, will be returned; on failure, NULL will
285    be returned.  */
286 static const char *
287 parse_version_string (const char *s, int *major, int *minor, int *micro)
288 {
289   s = parse_version_number (s, major);
290   if (!s || *s != '.')
291     return NULL;
292   s++;
293   s = parse_version_number (s, minor);
294   if (!s || *s != '.')
295     return NULL;
296   s++;
297   s = parse_version_number (s, micro);
298   if (!s)
299     return NULL;
300   return s; /* Patchlevel.  */
301 }
302
303 /* Return true if version string is at least version B. */
304 int
305 gnupg_compare_version (const char *a, const char *b)
306 {
307   int a_major, a_minor, a_micro;
308   int b_major, b_minor, b_micro;
309   const char *a_plvl, *b_plvl;
310
311   if (!a || !b)
312     return 0;
313
314   /* Parse version A.  */
315   a_plvl = parse_version_string (a, &a_major, &a_minor, &a_micro);
316   if (!a_plvl )
317     return 0; /* Invalid version number.  */
318
319   /* Parse version B.  */
320   b_plvl = parse_version_string (b, &b_major, &b_minor, &b_micro);
321   if (!b_plvl )
322     return 0; /* Invalid version number.  */
323
324   /* Compare version numbers.  */
325   return (a_major > b_major
326           || (a_major == b_major && a_minor > b_minor)
327           || (a_major == b_major && a_minor == b_minor
328               && a_micro > b_micro)
329           || (a_major == b_major && a_minor == b_minor
330               && a_micro == b_micro
331               && strcmp (a_plvl, b_plvl) >= 0));
332 }
333