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
5 This file is part of GPGME.
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.
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.
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
28 #ifdef HAVE_SYS_TYPES_H
29 /* Solaris 8 needs sys/types.h before time.h. */
30 # include <sys/types.h>
40 #define atoi_1(p) (*(p) - '0' )
41 #define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
42 #define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
47 do_strconcat (const char *s1, va_list arg_ptr)
57 while (((argv[argc] = va_arg (arg_ptr, const char *))))
59 needed += strlen (argv[argc]);
60 if (argc >= DIM (argv)-1)
62 gpg_err_set_errno (EINVAL);
68 buffer = malloc (needed);
71 for (p = buffer, argc=0; argv[argc]; argc++)
72 p = stpcpy (p, argv[argc]);
78 /* Concatenate the string S1 with all the following strings up to a
79 * NULL. Returns a malloced buffer with the new string or NULL on a
80 malloc error or if too many arguments are given. */
82 _gpgme_strconcat (const char *s1, ...)
91 va_start (arg_ptr, s1);
92 result = do_strconcat (s1, arg_ptr);
101 /* Convert two hexadecimal digits from STR to the value they
102 represent. Returns -1 if one of the characters is not a
103 hexadecimal digit. */
105 _gpgme_hextobyte (const char *str)
110 #define NROFHEXDIGITS 2
111 for (i = 0; i < NROFHEXDIGITS; i++)
113 if (*str >= '0' && *str <= '9')
115 else if (*str >= 'A' && *str <= 'F')
116 val += 10 + *str - 'A';
117 else if (*str >= 'a' && *str <= 'f')
118 val += 10 + *str - 'a';
121 if (i < NROFHEXDIGITS - 1)
129 /* Decode the C formatted string SRC and store the result in the
130 buffer *DESTP which is LEN bytes long. If LEN is zero, then a
131 large enough buffer is allocated with malloc and *DESTP is set to
132 the result. Currently, LEN is only used to specify if allocation
133 is desired or not, the caller is expected to make sure that *DESTP
134 is large enough if LEN is not zero. */
136 _gpgme_decode_c_string (const char *src, char **destp, size_t len)
140 /* Set up the destination buffer. */
143 if (len < strlen (src) + 1)
144 return gpg_error (GPG_ERR_INTERNAL);
150 /* The converted string will never be larger than the original
152 dest = malloc (strlen (src) + 1);
154 return gpg_error_from_syserror ();
159 /* Convert the string. */
164 *(dest++) = *(src++);
170 #define DECODE_ONE(match,result) \
173 *(dest++) = result; \
176 DECODE_ONE ('\'', '\'');
177 DECODE_ONE ('\"', '\"');
178 DECODE_ONE ('\?', '\?');
179 DECODE_ONE ('\\', '\\');
180 DECODE_ONE ('a', '\a');
181 DECODE_ONE ('b', '\b');
182 DECODE_ONE ('f', '\f');
183 DECODE_ONE ('n', '\n');
184 DECODE_ONE ('r', '\r');
185 DECODE_ONE ('t', '\t');
186 DECODE_ONE ('v', '\v');
190 int val = _gpgme_hextobyte (&src[2]);
194 /* Should not happen. */
195 *(dest++) = *(src++);
196 *(dest++) = *(src++);
198 *(dest++) = *(src++);
200 *(dest++) = *(src++);
206 /* A binary zero is not representable in a C
212 *((unsigned char *) dest++) = val;
220 /* Should not happen. */
221 *(dest++) = *(src++);
222 *(dest++) = *(src++);
232 /* Decode the percent escaped string SRC and store the result in the
233 buffer *DESTP which is LEN bytes long. If LEN is zero, then a
234 large enough buffer is allocated with malloc and *DESTP is set to
235 the result. Currently, LEN is only used to specify if allocation
236 is desired or not, the caller is expected to make sure that *DESTP
237 is large enough if LEN is not zero. If BINARY is 1, then '\0'
238 characters are allowed in the output. */
240 _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
245 /* Set up the destination buffer. */
248 if (len < strlen (src) + 1)
249 return gpg_error (GPG_ERR_INTERNAL);
255 /* The converted string will never be larger than the original
257 dest = malloc (strlen (src) + 1);
259 return gpg_error_from_syserror ();
264 /* Convert the string. */
269 *(dest++) = *(src++);
274 int val = _gpgme_hextobyte (&src[1]);
278 /* Should not happen. */
279 *(dest++) = *(src++);
281 *(dest++) = *(src++);
283 *(dest++) = *(src++);
289 /* A binary zero is not representable in a C
295 *((unsigned char *) dest++) = val;
306 /* Encode the string SRC with percent escaping and store the result in
307 the buffer *DESTP which is LEN bytes long. If LEN is zero, then a
308 large enough buffer is allocated with malloc and *DESTP is set to
309 the result. Currently, LEN is only used to specify if allocation
310 is desired or not, the caller is expected to make sure that *DESTP
311 is large enough if LEN is not zero. If BINARY is 1, then '\0'
312 characters are allowed in the output. */
314 _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
322 /* We percent-escape the + character because the user might need a
323 "percent plus" escaped string (special gpg format). But we
324 percent-escape the space character, which works with and without
325 the special plus format. */
328 if (*str == '+' || *str == '\"' || *str == '%'
329 || *(const unsigned char *)str <= 0x20)
335 /* Terminating nul byte. */
338 /* Set up the destination buffer. */
342 return gpg_error (GPG_ERR_INTERNAL);
348 /* The converted string will never be larger than the original
350 dest = malloc (destlen);
352 return gpg_error_from_syserror ();
357 /* Convert the string. */
360 if (*src == '+' || *src == '\"' || *src == '%'
361 || *(const unsigned char *)src <= 0x20)
363 snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
376 /* Split a string into space delimited fields and remove leading and
377 * trailing spaces from each field. A pointer to each field is
378 * stored in ARRAY. Stop splitting at ARRAYSIZE fields. The function
379 * modifies STRING. The number of parsed fields is returned.
382 _gpgme_split_fields (char *string, char **array, int arraysize)
387 for (p = string; *p == ' '; p++)
394 pend = strchr (p, ' ');
398 for (p = pend; *p == ' '; p++)
406 /* Convert the field STRING into an unsigned long value. Check for
407 * trailing garbage. */
409 _gpgme_strtoul_field (const char *string, unsigned long *result)
413 gpg_err_set_errno (0);
414 *result = strtoul (string, &endp, 0);
416 return gpg_error_from_syserror ();
417 if (endp == string || *endp)
418 return gpg_error (GPG_ERR_INV_VALUE);
423 /* Convert STRING into an offset value. Note that this functions only
424 * allows for a base-10 length. This function is similar to atoi()
425 * and thus there is no error checking. */
427 _gpgme_string_to_off (const char *string)
429 gpgme_off_t value = 0;
431 while (*string == ' ' || *string == '\t')
433 for (; *string >= '0' && *string <= '9'; string++)
436 value += atoi_1 (string);
442 #ifdef HAVE_W32_SYSTEM
444 _gpgme_timegm (struct tm *tm)
446 /* This one is thread safe. */
449 unsigned long long cnsecs;
451 st.wYear = tm->tm_year + 1900;
452 st.wMonth = tm->tm_mon + 1;
453 st.wDay = tm->tm_mday;
454 st.wHour = tm->tm_hour;
455 st.wMinute = tm->tm_min;
456 st.wSecond = tm->tm_sec;
457 st.wMilliseconds = 0; /* Not available. */
458 st.wDayOfWeek = 0; /* Ignored. */
460 /* System time is UTC thus the conversion is pretty easy. */
461 if (!SystemTimeToFileTime (&st, &ft))
463 gpg_err_set_errno (EINVAL);
467 cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
469 cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01. */
470 return (time_t)(cnsecs / 10000000ULL);
475 /* Parse the string TIMESTAMP into a time_t. The string may either be
476 seconds since Epoch or in the ISO 8601 format like
477 "20390815T143012". Returns 0 for an empty string or seconds since
478 Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
479 point to the next non-parsed character in TIMESTRING. */
481 _gpgme_parse_timestamp (const char *timestamp, char **endp)
483 /* Need to skip leading spaces, because that is what strtoul does
484 but not our ISO 8601 checking code. */
485 while (*timestamp && *timestamp== ' ')
490 if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
495 year = atoi_4 (timestamp);
500 *endp = (char*)(timestamp + 15);
502 /* Fixme: We would better use a configure test to see whether
503 mktime can handle dates beyond 2038. */
504 if (sizeof (time_t) <= 4 && year >= 2038)
505 return (time_t)2145914603; /* 2037-12-31 23:23:23 */
507 memset (&buf, 0, sizeof buf);
508 buf.tm_year = year - 1900;
509 buf.tm_mon = atoi_2 (timestamp+4) - 1;
510 buf.tm_mday = atoi_2 (timestamp+6);
511 buf.tm_hour = atoi_2 (timestamp+9);
512 buf.tm_min = atoi_2 (timestamp+11);
513 buf.tm_sec = atoi_2 (timestamp+13);
515 #ifdef HAVE_W32_SYSTEM
516 return _gpgme_timegm (&buf);
519 return timegm (&buf);
527 #warning fixme: we must somehow reset TZ here. It is not threadsafe anyway.
531 #endif /* !HAVE_TIMEGM */
532 #endif /* !HAVE_W32_SYSTEM */
535 return (time_t)strtoul (timestamp, endp, 10);
539 /* This function is similar to _gpgme_parse_timestamp but returns an
540 * unsigned long and 0 on error. */
542 _gpgme_parse_timestamp_ul (const char *timestamp)
548 return 0; /* Shortcut empty strings. */
550 tim = _gpgme_parse_timestamp (timestamp, &tail);
551 if (tim == -1 || timestamp == tail || (*tail && *tail != ' '))
552 tim = 0; /* No time given or invalid engine. */
554 return (unsigned long)tim;
558 /* The GPG backend uses OpenPGP algorithm numbers which we need to map
559 to our algorithm numbers. This function MUST not change ERRNO. */
561 _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
563 if (protocol == GPGME_PROTOCOL_OPENPGP)
567 case 1: case 2: case 3: case 16: case 17: break;
568 case 18: algo = GPGME_PK_ECDH; break;
569 case 19: algo = GPGME_PK_ECDSA; break;
571 case 22: algo = GPGME_PK_EDDSA; break;
572 default: algo = 0; break; /* Unknown. */