diff options
author | June McEnroe <june@causal.agency> | 2021-04-11 17:10:47 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2021-04-11 17:10:47 -0400 |
commit | 18e9dcbf8479242c16fe94dfca5da5dbb3b93a01 (patch) | |
tree | 3c4393288576a6cdb70d1a9da61c501da5dc9041 | |
parent | Remove unnecessary capture group in URL regex (diff) | |
download | bubger-18e9dcbf8479242c16fe94dfca5da5dbb3b93a01.tar.gz bubger-18e9dcbf8479242c16fe94dfca5da5dbb3b93a01.zip |
Parse dates in a hopefully more portable fashion
On GNU, struct tm doesn't have tm_gmtoff and %z or %Z in strptime do nothing. mktime(3) interprets the struct as local time, regardless of any tm_gmtoff, except on FreeBSD. Parse the zone portion of the date manually, subtract it from the struct tm fields, and call timegm(3). While here, correctly parse the optional seconds portion of the time.
-rw-r--r-- | parse.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/parse.c b/parse.c index b4f429e..da1ba47 100644 --- a/parse.c +++ b/parse.c @@ -67,6 +67,30 @@ static char *parseID(char *id) { return &id[1]; } +static time_t parseDate(const char *date) { + struct tm tm = {0}; + if (isalpha(*date)) { + date = strptime(date, "%a, ", &tm); + if (!date) goto err; + } + date = strptime(date, "%e %b %Y %H:%M", &tm); + if (!date) goto err; + if (*date == ':') { + date = strptime(date, ":%S", &tm); + if (!date) goto err; + } + while (isspace(*date)) date++; + if (*date == '+' || *date == '-') { + long zone = strtol(date, NULL, 10); + tm.tm_hour -= zone / 100; + tm.tm_min -= zone % 100; + } + return timegm(&tm); + +err: + errx(EX_PROTOCOL, "invalid envelope date format"); +} + void parseEnvelope(struct Envelope *envelope, struct List list) { enum { Date, Subject, From, Sender, ReplyTo, @@ -77,22 +101,8 @@ void parseEnvelope(struct Envelope *envelope, struct List list) { errx(EX_PROTOCOL, "missing envelope structure fields"); } - struct tm time; - const char *date = dataCheck(list.ptr[Date], String).string; - envelope->date = date; - if (isalpha(date[0])) { - date = strptime(date, "%a, %e %b %Y %H:%M:%S ", &time); - } else { - date = strptime(date, "%e %b %Y %H:%M:%S ", &time); - } - if (date && (date[0] == '+' || date[0] == '-')) { - date = strptime(date, "%z", &time); - } else if (date) { - date = strptime(date, "%Z", &time); - } - if (!date) errx(EX_PROTOCOL, "invalid envelope date format"); - envelope->time = mktime(&time); - + envelope->date = dataCheck(list.ptr[Date], String).string; + envelope->time = parseDate(envelope->date); envelope->subject = decodeHeader( dataCheck(list.ptr[Subject], String).string ); |