dovecot: Moved mbox From_-line handling to lib-mail, since it's ...

dovecot at dovecot.org dovecot at dovecot.org
Mon Mar 3 02:55:46 EET 2008


details:   http://hg.dovecot.org/dovecot/rev/5d37ca11808d
changeset: 7316:5d37ca11808d
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Mar 03 02:54:46 2008 +0200
description:
Moved mbox From_-line handling to lib-mail, since it's also used by deliver.

diffstat:

7 files changed, 308 insertions(+), 304 deletions(-)
src/deliver/deliver.c                  |    2 
src/lib-mail/Makefile.am               |    2 
src/lib-mail/mbox-from.c               |  293 ++++++++++++++++++++++++++++++++
src/lib-mail/mbox-from.h               |   12 +
src/lib-storage/index/mbox/Makefile.am |    2 
src/lib-storage/index/mbox/mbox-from.c |  293 --------------------------------
src/lib-storage/index/mbox/mbox-from.h |    8 

diffs (truncated from 672 to 300 lines):

diff -r 533bee708cc0 -r 5d37ca11808d src/deliver/deliver.c
--- a/src/deliver/deliver.c	Mon Mar 03 02:38:58 2008 +0200
+++ b/src/deliver/deliver.c	Mon Mar 03 02:54:46 2008 +0200
@@ -28,7 +28,7 @@
 #include "auth-client.h"
 #include "mail-send.h"
 #include "duplicate.h"
-#include "mbox/mbox-from.h"
+#include "mbox-from.h"
 #include "../master/syslog-util.h"
 #include "../master/syslog-util.c" /* ugly, ugly.. */
 #include "deliver.h"
diff -r 533bee708cc0 -r 5d37ca11808d src/lib-mail/Makefile.am
--- a/src/lib-mail/Makefile.am	Mon Mar 03 02:38:58 2008 +0200
+++ b/src/lib-mail/Makefile.am	Mon Mar 03 02:54:46 2008 +0200
@@ -6,6 +6,7 @@ AM_CPPFLAGS = \
 
 libmail_a_SOURCES = \
 	istream-header-filter.c \
+	mbox-from.c \
 	message-address.c \
 	message-date.c \
 	message-decoder.c \
@@ -22,6 +23,7 @@ libmail_a_SOURCES = \
 
 headers = \
 	istream-header-filter.h \
+	mbox-from.h \
 	mail-types.h \
 	message-address.h \
 	message-date.h \
diff -r 533bee708cc0 -r 5d37ca11808d src/lib-mail/mbox-from.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-mail/mbox-from.c	Mon Mar 03 02:54:46 2008 +0200
@@ -0,0 +1,293 @@
+/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "utc-mktime.h"
+#include "mbox-from.h"
+
+#include <time.h>
+#include <ctype.h>
+
+static const char *weekdays[] = {
+	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+static const char *months[] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static int mbox_parse_month(const unsigned char *msg, struct tm *tm)
+{
+	int i;
+
+	for (i = 0; i < 12; i++) {
+		if (i_memcasecmp(months[i], msg, 3) == 0) {
+			tm->tm_mon = i;
+			break;
+		}
+	}
+
+	if (i == 12 && memcmp(msg, "???", 3) == 0) {
+		/* just a hack to parse one special mbox I have :) */
+		i = 0;
+	}
+
+	if (i == 12 || msg[3] != ' ')
+		return -1;
+	return 0;
+}
+
+static int mbox_parse_year(const unsigned char *msg, struct tm *tm)
+{
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) ||
+	    !i_isdigit(msg[2]) || !i_isdigit(msg[3]))
+		return -1;
+
+	tm->tm_year = (msg[0]-'0') * 1000 + (msg[1]-'0') * 100 +
+		(msg[2]-'0') * 10 + (msg[3]-'0') - 1900;
+	return 0;
+}
+
+int mbox_from_parse(const unsigned char *msg, size_t size,
+		    time_t *time_r, char **sender_r)
+{
+	const unsigned char *msg_start, *sender_end, *msg_end;
+	struct tm tm;
+	int esc, alt_stamp, timezone = 0, seen_timezone = FALSE;
+	time_t t;
+
+	*time_r = (time_t)-1;
+	*sender_r = NULL;
+
+	/* <sender> <date> <moreinfo> */
+	msg_start = msg;
+	msg_end = msg + size;
+
+	/* get sender */
+	if (msg < msg_end && *msg == '"') {
+		/* "x y z"@domain - skip the quoted part */
+		esc = FALSE;
+		msg++;
+		while (msg < msg_end && (*msg != '"' || esc)) {
+			if (*msg == '\r' || *msg == '\n')
+				return -1;
+			esc = *msg == '\\';
+			msg++;
+		}
+		msg++;
+	} 
+
+	while (msg < msg_end && *msg != ' ') {
+		if (*msg == '\r' || *msg == '\n')
+			return -1;
+		msg++;
+	}
+	sender_end = msg;
+	while (msg < msg_end && *msg == ' ') msg++;
+
+	/* next 24 chars should be in the date in asctime() format, eg.
+	   "Thu Nov  9 22:33:52 2001 +0300"
+
+	   - Some put the timezone before the year
+	   - Some use a named timezone before or after year, which we ignore
+	   - Some don't include seconds
+	*/
+	if (msg+24 > msg_end)
+		return -1;
+
+	memset(&tm, 0, sizeof(tm));
+
+	/* skip weekday */
+	msg += 4;
+
+	/* month */
+	if (mbox_parse_month(msg, &tm) < 0) {
+		/* Try alternate timestamp: "Thu, 9 Nov 2002 22:33:52" */
+		alt_stamp = TRUE;
+		msg++;
+
+		if (!i_isdigit(msg[0]))
+			return -1;
+		tm.tm_mday = msg[0]-'0';
+		msg++;
+
+		if (i_isdigit(msg[0])) {
+			tm.tm_mday = tm.tm_mday*10 + msg[0]-'0';
+			msg++;
+		}
+		if (msg[0] != ' ')
+			return -1;
+		msg++;
+
+		if (mbox_parse_month(msg, &tm) < 0)
+			return -1;
+		msg += 4;
+
+		if (mbox_parse_year(msg, &tm) < 0)
+			return -1;
+		msg += 5;
+	} else {
+		alt_stamp = FALSE;
+		msg += 4;
+
+		/* day. single digit is usually preceded by extra space */
+		if (msg[0] == ' ')
+			msg++;
+		if (msg[1] == ' ') {
+			if (!i_isdigit(msg[0]))
+				return -1;
+			tm.tm_mday = msg[0]-'0';
+			msg += 2;
+		} else {
+			if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ')
+				return -1;
+			tm.tm_mday = (msg[0]-'0') * 10 + (msg[1]-'0');
+			msg += 3;
+		}
+	}
+	if (tm.tm_mday == 0)
+		tm.tm_mday = 1;
+
+	/* hour */
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':')
+		return -1;
+	tm.tm_hour = (msg[0]-'0') * 10 + (msg[1]-'0');
+	msg += 3;
+
+	/* minute */
+	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]))
+		return -1;
+	tm.tm_min = (msg[0]-'0') * 10 + (msg[1]-'0');
+	msg += 2;
+
+	/* optional second */
+	if (msg[0] == ':') {
+		msg++;
+		if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]))
+			return -1;
+		tm.tm_sec = (msg[0]-'0') * 10 + (msg[1]-'0');
+		msg += 2;
+
+		if (msg[0] == ' ')
+			msg++;
+		else if (!alt_stamp)
+			return -1;
+	} else {
+		if (msg[0] != ' ')
+			return -1;
+		msg++;
+	}
+
+	/* optional named timezone */
+	if (alt_stamp)
+		;
+	else if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) ||
+		 !i_isdigit(msg[2]) || !i_isdigit(msg[3])) {
+		/* skip to next space */
+		while (msg < msg_end && *msg != ' ') {
+			if (*msg == '\r' || *msg == '\n')
+				return -1;
+			msg++;
+		}
+		if (msg+5 > msg_end)
+			return -1;
+		msg++;
+	} else if ((msg[0] == '-' || msg[0] == '+') &&
+		   i_isdigit(msg[1]) && i_isdigit(msg[2]) &&
+		   i_isdigit(msg[3]) && i_isdigit(msg[4]) && msg[5] == ' ') {
+		/* numeric timezone, use it */
+                seen_timezone = TRUE;
+		timezone = (msg[1]-'0') * 10*60*60 + (msg[2]-'0') * 60*60 +
+			(msg[3]-'0') * 10 + (msg[4]-'0');
+		if (msg[0] == '-') timezone = -timezone;
+		msg += 6;
+	}
+
+	if (!alt_stamp) {
+		/* year */
+		if (mbox_parse_year(msg, &tm) < 0)
+			return -1;
+		msg += 4;
+	}
+
+	tm.tm_isdst = -1;
+	if (!seen_timezone &&
+	    msg[0] == ' ' && (msg[1] == '-' || msg[1] == '+') &&
+	    i_isdigit(msg[2]) && i_isdigit(msg[3]) &&
+	    i_isdigit(msg[4]) && i_isdigit(msg[5])) {
+		seen_timezone = TRUE;
+		timezone = (msg[2]-'0') * 10*60*60 + (msg[3]-'0') * 60*60 +
+			(msg[4]-'0') * 10 + (msg[5]-'0');
+		if (msg[1] == '-') timezone = -timezone;
+	}
+
+	if (seen_timezone) {
+		t = utc_mktime(&tm);
+		if (t == (time_t)-1)
+			return -1;
+
+		t -= timezone;
+		*time_r = t;
+	} else {
+		/* assume local timezone */
+		*time_r = mktime(&tm);
+	}
+
+	*sender_r = i_strdup_until(msg_start, sender_end);
+	return 0;
+}
+
+const char *mbox_from_create(const char *sender, time_t time)
+{
+	string_t *str;
+	struct tm *tm;
+	int year;
+
+	str = t_str_new(256);
+	str_append(str, "From ");
+	str_append(str, sender);
+	str_append(str, "  ");
+
+	/* we could use simply asctime(), but i18n etc. may break it.
+	   Example: "Thu Nov 29 22:33:52 2001" */
+	tm = localtime(&time);
+
+	/* week day */
+	str_append(str, weekdays[tm->tm_wday]);
+	str_append_c(str, ' ');
+
+	/* month */
+	str_append(str, months[tm->tm_mon]);
+	str_append_c(str, ' ');
+
+	/* day */
+	str_append_c(str, (tm->tm_mday / 10) + '0');


More information about the dovecot-cvs mailing list