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