core: Add gpgme_data_set_flag to add more meta data to data objects.
[gpgme.git] / src / conversion.c
1 /* conversion.c - String conversion helper functions.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2007 g10 Code GmbH
4
5    This file is part of GPGME.
6
7    GPGME 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 2.1 of
10    the License, or (at your option) any later version.
11
12    GPGME 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.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h>
28 #ifdef HAVE_SYS_TYPES_H
29   /* Solaris 8 needs sys/types.h before time.h.  */
30 # include <sys/types.h>
31 #endif
32 #include <time.h>
33 #include <errno.h>
34
35 #include "gpgme.h"
36 #include "util.h"
37 #include "debug.h"
38
39 #define atoi_1(p)   (*(p) - '0' )
40 #define atoi_2(p)   ((atoi_1(p) * 10) + atoi_1((p)+1))
41 #define atoi_4(p)   ((atoi_2(p) * 100) + atoi_2((p)+2))
42
43
44 \f
45 /* Convert two hexadecimal digits from STR to the value they
46    represent.  Returns -1 if one of the characters is not a
47    hexadecimal digit.  */
48 int
49 _gpgme_hextobyte (const char *str)
50 {
51   int val = 0;
52   int i;
53
54 #define NROFHEXDIGITS 2
55   for (i = 0; i < NROFHEXDIGITS; i++)
56     {
57       if (*str >= '0' && *str <= '9')
58         val += *str - '0';
59       else if (*str >= 'A' && *str <= 'F')
60         val += 10 + *str - 'A';
61       else if (*str >= 'a' && *str <= 'f')
62         val += 10 + *str - 'a';
63       else
64         return -1;
65       if (i < NROFHEXDIGITS - 1)
66         val *= 16;
67       str++;
68     }
69   return val;
70 }
71
72
73 /* Decode the C formatted string SRC and store the result in the
74    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
75    large enough buffer is allocated with malloc and *DESTP is set to
76    the result.  Currently, LEN is only used to specify if allocation
77    is desired or not, the caller is expected to make sure that *DESTP
78    is large enough if LEN is not zero.  */
79 gpgme_error_t
80 _gpgme_decode_c_string (const char *src, char **destp, size_t len)
81 {
82   char *dest;
83
84   /* Set up the destination buffer.  */
85   if (len)
86     {
87       if (len < strlen (src) + 1)
88         return gpg_error (GPG_ERR_INTERNAL);
89
90       dest = *destp;
91     }
92   else
93     {
94       /* The converted string will never be larger than the original
95          string.  */
96       dest = malloc (strlen (src) + 1);
97       if (!dest)
98         return gpg_error_from_syserror ();
99
100       *destp = dest;
101     }
102
103   /* Convert the string.  */
104   while (*src)
105     {
106       if (*src != '\\')
107         {
108           *(dest++) = *(src++);
109           continue;
110         }
111
112       switch (src[1])
113         {
114 #define DECODE_ONE(match,result)        \
115         case match:                     \
116           src += 2;                     \
117           *(dest++) = result;           \
118           break;
119
120           DECODE_ONE ('\'', '\'');
121           DECODE_ONE ('\"', '\"');
122           DECODE_ONE ('\?', '\?');
123           DECODE_ONE ('\\', '\\');
124           DECODE_ONE ('a', '\a');
125           DECODE_ONE ('b', '\b');
126           DECODE_ONE ('f', '\f');
127           DECODE_ONE ('n', '\n');
128           DECODE_ONE ('r', '\r');
129           DECODE_ONE ('t', '\t');
130           DECODE_ONE ('v', '\v');
131
132         case 'x':
133           {
134             int val = _gpgme_hextobyte (&src[2]);
135
136             if (val == -1)
137               {
138                 /* Should not happen.  */
139                 *(dest++) = *(src++);
140                 *(dest++) = *(src++);
141                 if (*src)
142                   *(dest++) = *(src++);
143                 if (*src)
144                   *(dest++) = *(src++);
145               }
146             else
147               {
148                 if (!val)
149                   {
150                     /* A binary zero is not representable in a C
151                        string.  */
152                     *(dest++) = '\\';
153                     *(dest++) = '0';
154                   }
155                 else
156                   *((unsigned char *) dest++) = val;
157                 src += 4;
158               }
159           }
160           break;
161
162         default:
163           {
164             /* Should not happen.  */
165             *(dest++) = *(src++);
166             *(dest++) = *(src++);
167           }
168         }
169     }
170   *(dest++) = 0;
171
172   return 0;
173 }
174
175
176 /* Decode the percent escaped string SRC and store the result in the
177    buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
178    large enough buffer is allocated with malloc and *DESTP is set to
179    the result.  Currently, LEN is only used to specify if allocation
180    is desired or not, the caller is expected to make sure that *DESTP
181    is large enough if LEN is not zero.  If BINARY is 1, then '\0'
182    characters are allowed in the output.  */
183 gpgme_error_t
184 _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
185                               int binary)
186 {
187   char *dest;
188
189   /* Set up the destination buffer.  */
190   if (len)
191     {
192       if (len < strlen (src) + 1)
193         return gpg_error (GPG_ERR_INTERNAL);
194
195       dest = *destp;
196     }
197   else
198     {
199       /* The converted string will never be larger than the original
200          string.  */
201       dest = malloc (strlen (src) + 1);
202       if (!dest)
203         return gpg_error_from_syserror ();
204
205       *destp = dest;
206     }
207
208   /* Convert the string.  */
209   while (*src)
210     {
211       if (*src != '%')
212         {
213           *(dest++) = *(src++);
214           continue;
215         }
216       else
217         {
218           int val = _gpgme_hextobyte (&src[1]);
219
220           if (val == -1)
221             {
222               /* Should not happen.  */
223               *(dest++) = *(src++);
224               if (*src)
225                 *(dest++) = *(src++);
226               if (*src)
227                 *(dest++) = *(src++);
228             }
229           else
230             {
231               if (!val && !binary)
232                 {
233                   /* A binary zero is not representable in a C
234                      string.  */
235                   *(dest++) = '\\';
236                   *(dest++) = '0';
237                 }
238               else
239                 *((unsigned char *) dest++) = val;
240               src += 3;
241             }
242         }
243     }
244   *(dest++) = 0;
245
246   return 0;
247 }
248
249
250 /* Encode the string SRC with percent escaping and store the result in
251    the buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
252    large enough buffer is allocated with malloc and *DESTP is set to
253    the result.  Currently, LEN is only used to specify if allocation
254    is desired or not, the caller is expected to make sure that *DESTP
255    is large enough if LEN is not zero.  If BINARY is 1, then '\0'
256    characters are allowed in the output.  */
257 gpgme_error_t
258 _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
259 {
260   size_t destlen;
261   char *dest;
262   const char *str;
263
264   destlen = 0;
265   str = src;
266   /* We percent-escape the + character because the user might need a
267      "percent plus" escaped string (special gpg format).  But we
268      percent-escape the space character, which works with and without
269      the special plus format.  */
270   while (*str)
271     {
272       if (*str == '+' || *str == '\"' || *str == '%'
273           || *(const unsigned char *)str <= 0x20)
274         destlen += 3;
275       else
276         destlen++;
277       str++;
278     }
279   /* Terminating nul byte.  */
280   destlen++;
281
282   /* Set up the destination buffer.  */
283   if (len)
284     {
285       if (len < destlen)
286         return gpg_error (GPG_ERR_INTERNAL);
287
288       dest = *destp;
289     }
290   else
291     {
292       /* The converted string will never be larger than the original
293          string.  */
294       dest = malloc (destlen);
295       if (!dest)
296         return gpg_error_from_syserror ();
297
298       *destp = dest;
299     }
300
301   /* Convert the string.  */
302   while (*src)
303     {
304       if (*src == '+' || *src == '\"' || *src == '%'
305           || *(const unsigned char *)src <= 0x20)
306         {
307           snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
308           dest += 3;
309         }
310       else
311         *(dest++) = *src;
312       src++;
313     }
314   *(dest++) = 0;
315
316   return 0;
317 }
318
319
320 /* Split a string into space delimited fields and remove leading and
321  * trailing spaces from each field.  A pointer to the each field is
322  * stored in ARRAY.  Stop splitting at ARRAYSIZE fields.  The function
323  * modifies STRING.  The number of parsed fields is returned.
324  */
325 int
326 _gpgme_split_fields (char *string, char **array, int arraysize)
327 {
328   int n = 0;
329   char *p, *pend;
330
331   for (p = string; *p == ' '; p++)
332     ;
333   do
334     {
335       if (n == arraysize)
336         break;
337       array[n++] = p;
338       pend = strchr (p, ' ');
339       if (!pend)
340         break;
341       *pend++ = 0;
342       for (p = pend; *p == ' '; p++)
343         ;
344     }
345   while (*p);
346
347   return n;
348 }
349
350 /* Convert the field STRING into an unsigned long value.  Check for
351  * trailing garbage.  */
352 gpgme_error_t
353 _gpgme_strtoul_field (const char *string, unsigned long *result)
354 {
355   char *endp;
356
357   gpg_err_set_errno (0);
358   *result = strtoul (string, &endp, 0);
359   if (errno)
360     return gpg_error_from_syserror ();
361   if (endp == string || *endp)
362     return gpg_error (GPG_ERR_INV_VALUE);
363   return 0;
364 }
365
366
367 /* Convert STRING into an offset value.  Note that this functions only
368  * allows for a base-10 length.  This function is similar to atoi()
369  * and thus there is no error checking.  */
370 gpgme_off_t
371 _gpgme_string_to_off (const char *string)
372 {
373   gpgme_off_t value = 0;
374
375   while (*string == ' ' || *string == '\t')
376     string++;
377   for (; *string >= '0' && *string <= '9'; string++)
378     {
379       value *= 10;
380       value += atoi_1 (string);
381     }
382   return value;
383 }
384
385
386 #ifdef HAVE_W32_SYSTEM
387 static time_t
388 _gpgme_timegm (struct tm *tm)
389 {
390   /* This one is thread safe.  */
391   SYSTEMTIME st;
392   FILETIME ft;
393   unsigned long long cnsecs;
394
395   st.wYear   = tm->tm_year + 1900;
396   st.wMonth  = tm->tm_mon  + 1;
397   st.wDay    = tm->tm_mday;
398   st.wHour   = tm->tm_hour;
399   st.wMinute = tm->tm_min;
400   st.wSecond = tm->tm_sec;
401   st.wMilliseconds = 0; /* Not available.  */
402   st.wDayOfWeek = 0;    /* Ignored.  */
403
404   /* System time is UTC thus the conversion is pretty easy.  */
405   if (!SystemTimeToFileTime (&st, &ft))
406     {
407       gpg_err_set_errno (EINVAL);
408       return (time_t)(-1);
409     }
410
411   cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
412             | ft.dwLowDateTime);
413   cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
414   return (time_t)(cnsecs / 10000000ULL);
415 }
416 #endif
417
418
419 /* Parse the string TIMESTAMP into a time_t.  The string may either be
420    seconds since Epoch or in the ISO 8601 format like
421    "20390815T143012".  Returns 0 for an empty string or seconds since
422    Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
423    point to the next non-parsed character in TIMESTRING. */
424 time_t
425 _gpgme_parse_timestamp (const char *timestamp, char **endp)
426 {
427   /* Need to skip leading spaces, because that is what strtoul does
428      but not our ISO 8601 checking code. */
429   while (*timestamp && *timestamp== ' ')
430     timestamp++;
431   if (!*timestamp)
432     return 0;
433
434   if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
435     {
436       struct tm buf;
437       int year;
438
439       year = atoi_4 (timestamp);
440       if (year < 1900)
441         return (time_t)(-1);
442
443       if (endp)
444         *endp = (char*)(timestamp + 15);
445
446       /* Fixme: We would better use a configure test to see whether
447          mktime can handle dates beyond 2038. */
448       if (sizeof (time_t) <= 4 && year >= 2038)
449         return (time_t)2145914603; /* 2037-12-31 23:23:23 */
450
451       memset (&buf, 0, sizeof buf);
452       buf.tm_year = year - 1900;
453       buf.tm_mon = atoi_2 (timestamp+4) - 1;
454       buf.tm_mday = atoi_2 (timestamp+6);
455       buf.tm_hour = atoi_2 (timestamp+9);
456       buf.tm_min = atoi_2 (timestamp+11);
457       buf.tm_sec = atoi_2 (timestamp+13);
458
459 #ifdef HAVE_W32_SYSTEM
460       return _gpgme_timegm (&buf);
461 #else
462 #ifdef HAVE_TIMEGM
463       return timegm (&buf);
464 #else
465       {
466         time_t tim;
467
468         putenv ("TZ=UTC");
469         tim = mktime (&buf);
470 #ifdef __GNUC__
471 #warning fixme: we must somehow reset TZ here.  It is not threadsafe anyway.
472 #endif
473         return tim;
474       }
475 #endif /* !HAVE_TIMEGM */
476 #endif /* !HAVE_W32_SYSTEM */
477     }
478   else
479     return (time_t)strtoul (timestamp, endp, 10);
480 }
481
482
483 /* The GPG backend uses OpenPGP algorithm numbers which we need to map
484    to our algorithm numbers.  This function MUST not change ERRNO. */
485 int
486 _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
487 {
488   if (protocol == GPGME_PROTOCOL_OPENPGP)
489     {
490       switch (algo)
491         {
492         case 1: case 2: case 3: case 16: case 17: break;
493         case 18: algo = GPGME_PK_ECDH; break;
494         case 19: algo = GPGME_PK_ECDSA; break;
495         case 20: break;
496         case 22: algo = GPGME_PK_EDDSA; break;
497         default: algo = 0; break; /* Unknown.  */
498         }
499     }
500
501   return algo;
502 }