From 18e9dcbf8479242c16fe94dfca5da5dbb3b93a01 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sun, 11 Apr 2021 17:10:47 -0400 Subject: 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. --- parse.c | 42 ++++++++++++++++++++++++++---------------- 1 file 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 ); -- cgit 1.4.1 2bb7f0ba0db60de2d09eca501041c46f710&showmsg=1'>unfollow)
Commit message (Collapse)Author
2021-05-19Replace freenode with tilde.chatJune McEnroe
2020-12-18Fix README formatting typo 1.3June McEnroe
2020-12-18Rewrite main loop linearlyJune McEnroe
2020-12-16Remove dig dependency from READMEJune McEnroe
2020-12-16Add git-notemap wrapperJune McEnroe
2020-12-16Take username as a required positional argumentJune McEnroe
2020-12-15Reformat STANDARDS sectionJune McEnroe
2020-12-15Add DNS and SRV RFCs to STANDARDSJune McEnroe
2020-12-15Remove dependency on dig/drillJune McEnroe
2020-12-15Add -lresolv on macOS, LinuxJune McEnroe
2020-12-15Implement getservinfo for SRV lookupJune McEnroe
2020-10-29Update README build instructions 1.2June McEnroe
2020-10-29Say OpenSSL in additional permission noticesJune McEnroe
2020-10-27Refactor IMAP structJune McEnroe
2020-10-27Rewrite compat and add configure scriptJune McEnroe
2020-10-24Use open_memstream rather than fmemopenJune McEnroe
2020-06-08Add additional permission for linking with LibreSSLJune McEnroe
https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs
2020-05-05Update email addresses 1.1June McEnroe
2020-05-05Update compat.h for split read/write streamsJune McEnroe
2020-05-05Encode the path as Subject with QJune McEnroe
2020-05-04Clean up notemap with dataCheckJune McEnroe
2020-05-04Update IMAP parserJune McEnroe
2020-04-08Use a real IMAP parserJune McEnroe
2020-01-28Call fopencookie with a+ 1.0June McEnroe
This fixes strange behaviour when interleaving reads and writes.
2020-01-28Add arc4random_buf compatibilityJune McEnroe