about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--parse.c42
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
 	);