summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-01-26 14:10:06 +0100
committerChristian Grothoff <christian@grothoff.org>2021-01-26 14:10:06 +0100
commit2b35e3796f91fb8e89b161650aa239497d2bb89a (patch)
tree622a66d054a9a26fc2faf2135931412edda82fd5 /src
parent6cd6582a4fd20aafcb595d52b506d2e2a973b2ee (diff)
downloadexchange-2b35e3796f91fb8e89b161650aa239497d2bb89a.tar.gz
exchange-2b35e3796f91fb8e89b161650aa239497d2bb89a.tar.bz2
exchange-2b35e3796f91fb8e89b161650aa239497d2bb89a.zip
strptime is locale-dependent, re-implement for C locale-only
Diffstat (limited to 'src')
-rw-r--r--src/lib/exchange_api_handle.c93
1 files changed, 75 insertions, 18 deletions
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index 553a44bf..04376074 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -1299,37 +1299,94 @@ TEAH_path_to_url (struct TALER_EXCHANGE_Handle *h,
/**
+ * Define a max length for the HTTP "Expire:" header
+ */
+#define MAX_DATE_LINE_LEN 32
+
+
+/**
* Parse HTTP timestamp.
*
- * @param date header to parse header
+ * @param dateline header to parse header
* @param at where to write the result
* @return #GNUNET_OK on success
*/
static int
-parse_date_string (const char *date,
+parse_date_string (const char *dateline,
struct GNUNET_TIME_Absolute *at)
{
- struct tm now;
+ static const char *MONTHS[] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
+ int year;
+ int mon;
+ int day;
+ int hour;
+ int min;
+ int sec;
+ char month[4];
+ struct tm tm;
time_t t;
- const char *end;
- memset (&now,
- 0,
- sizeof (now));
- end = strptime (date,
- "%a, %d %b %Y %H:%M:%S %Z", /* RFC-1123 standard spec */
- &now);
- if ( (NULL == end) ||
- ( (*end != '\n') &&
- (*end != '\r') ) )
+ /* We recognize the three formats in RFC2616, section 3.3.1. Month
+ names are always in English. The formats are:
+ Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ Note that the first is preferred.
+ */
+
+ if (strlen (dateline) > MAX_DATE_LINE_LEN)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not parse date input `%s', failure at `%s'\n",
- date,
- end);
+ GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- t = mktime (&now);
+ while (*dateline == ' ')
+ ++dateline;
+ while (*dateline && *dateline != ' ')
+ ++dateline;
+ while (*dateline == ' ')
+ ++dateline;
+ /* We just skipped over the day of the week. Now we have:*/
+ if ( (sscanf (dateline,
+ "%d %3s %d %d:%d:%d",
+ &day, month, &year, &hour, &min, &sec) != 6) &&
+ (sscanf (dateline,
+ "%d-%3s-%d %d:%d:%d",
+ &day, month, &year, &hour, &min, &sec) != 6) &&
+ (sscanf (dateline,
+ "%3s %d %d:%d:%d %d",
+ month, &day, &hour, &min, &sec, &year) != 6) )
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ /* Two digit dates are defined to be relative to 1900; all other dates
+ * are supposed to be represented as four digits. */
+ if (year < 100)
+ year += 1900;
+
+ for (mon = 0; ; mon++)
+ {
+ if (! MONTHS[mon])
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (0 == strcasecmp (month,
+ MONTHS[mon]))
+ break;
+ }
+
+ memset (&tm, 0, sizeof(tm));
+ tm.tm_year = year - 1900;
+ tm.tm_mon = mon;
+ tm.tm_mday = day;
+ tm.tm_hour = hour;
+ tm.tm_min = min;
+ tm.tm_sec = sec;
+
+ t = mktime (&tm);
if (((time_t) -1) == t)
{
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,