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>
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))
45 /* Convert two hexadecimal digits from STR to the value they
46 represent. Returns -1 if one of the characters is not a
49 _gpgme_hextobyte (const char *str)
54 #define NROFHEXDIGITS 2
55 for (i = 0; i < NROFHEXDIGITS; i++)
57 if (*str >= '0' && *str <= '9')
59 else if (*str >= 'A' && *str <= 'F')
60 val += 10 + *str - 'A';
61 else if (*str >= 'a' && *str <= 'f')
62 val += 10 + *str - 'a';
65 if (i < NROFHEXDIGITS - 1)
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. */
80 _gpgme_decode_c_string (const char *src, char **destp, size_t len)
84 /* Set up the destination buffer. */
87 if (len < strlen (src) + 1)
88 return gpg_error (GPG_ERR_INTERNAL);
94 /* The converted string will never be larger than the original
96 dest = malloc (strlen (src) + 1);
98 return gpg_error_from_syserror ();
103 /* Convert the string. */
108 *(dest++) = *(src++);
114 #define DECODE_ONE(match,result) \
117 *(dest++) = result; \
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');
134 int val = _gpgme_hextobyte (&src[2]);
138 /* Should not happen. */
139 *(dest++) = *(src++);
140 *(dest++) = *(src++);
142 *(dest++) = *(src++);
144 *(dest++) = *(src++);
150 /* A binary zero is not representable in a C
156 *((unsigned char *) dest++) = val;
164 /* Should not happen. */
165 *(dest++) = *(src++);
166 *(dest++) = *(src++);
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. */
184 _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
189 /* Set up the destination buffer. */
192 if (len < strlen (src) + 1)
193 return gpg_error (GPG_ERR_INTERNAL);
199 /* The converted string will never be larger than the original
201 dest = malloc (strlen (src) + 1);
203 return gpg_error_from_syserror ();
208 /* Convert the string. */
213 *(dest++) = *(src++);
218 int val = _gpgme_hextobyte (&src[1]);
222 /* Should not happen. */
223 *(dest++) = *(src++);
225 *(dest++) = *(src++);
227 *(dest++) = *(src++);
233 /* A binary zero is not representable in a C
239 *((unsigned char *) dest++) = val;
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. */
258 _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
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. */
272 if (*str == '+' || *str == '\"' || *str == '%'
273 || *(const unsigned char *)str <= 0x20)
279 /* Terminating nul byte. */
282 /* Set up the destination buffer. */
286 return gpg_error (GPG_ERR_INTERNAL);
292 /* The converted string will never be larger than the original
294 dest = malloc (destlen);
296 return gpg_error_from_syserror ();
301 /* Convert the string. */
304 if (*src == '+' || *src == '\"' || *src == '%'
305 || *(const unsigned char *)src <= 0x20)
307 snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
320 #ifdef HAVE_W32_SYSTEM
322 _gpgme_timegm (struct tm *tm)
324 /* This one is thread safe. */
327 unsigned long long cnsecs;
329 st.wYear = tm->tm_year + 1900;
330 st.wMonth = tm->tm_mon + 1;
331 st.wDay = tm->tm_mday;
332 st.wHour = tm->tm_hour;
333 st.wMinute = tm->tm_min;
334 st.wSecond = tm->tm_sec;
335 st.wMilliseconds = 0; /* Not available. */
336 st.wDayOfWeek = 0; /* Ignored. */
338 /* System time is UTC thus the conversion is pretty easy. */
339 if (!SystemTimeToFileTime (&st, &ft))
341 gpg_err_set_errno (EINVAL);
345 cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
347 cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01. */
348 return (time_t)(cnsecs / 10000000ULL);
353 /* Parse the string TIMESTAMP into a time_t. The string may either be
354 seconds since Epoch or in the ISO 8601 format like
355 "20390815T143012". Returns 0 for an empty string or seconds since
356 Epoch. Leading spaces are skipped. If ENDP is not NULL, it will
357 point to the next non-parsed character in TIMESTRING. */
359 _gpgme_parse_timestamp (const char *timestamp, char **endp)
361 /* Need to skip leading spaces, because that is what strtoul does
362 but not our ISO 8601 checking code. */
363 while (*timestamp && *timestamp== ' ')
368 if (strlen (timestamp) >= 15 && timestamp[8] == 'T')
373 year = atoi_4 (timestamp);
377 /* Fixme: We would better use a configure test to see whether
378 mktime can handle dates beyond 2038. */
379 if (sizeof (time_t) <= 4 && year >= 2038)
380 return (time_t)2145914603; /* 2037-12-31 23:23:23 */
382 memset (&buf, 0, sizeof buf);
383 buf.tm_year = year - 1900;
384 buf.tm_mon = atoi_2 (timestamp+4) - 1;
385 buf.tm_mday = atoi_2 (timestamp+6);
386 buf.tm_hour = atoi_2 (timestamp+9);
387 buf.tm_min = atoi_2 (timestamp+11);
388 buf.tm_sec = atoi_2 (timestamp+13);
391 *endp = (char*)(timestamp + 15);
392 #ifdef HAVE_W32_SYSTEM
393 return _gpgme_timegm (&buf);
396 return timegm (&buf);
404 #warning fixme: we must somehow reset TZ here. It is not threadsafe anyway.
408 #endif /* !HAVE_TIMEGM */
409 #endif /* !HAVE_W32_SYSTEM */
412 return (time_t)strtoul (timestamp, endp, 10);