changeset 119:2f67de235489 HEAD

Whops, we were using RFC822 dates everywhere instead of IMAP dates.
author Timo Sirainen <tss@iki.fi>
date Mon, 02 Sep 2002 22:08:47 +0300
parents 8abce0f7d065
children 82f566bc9d85
files src/imap/cmd-append.c src/lib-imap/Makefile.am src/lib-imap/imap-date.c src/lib-imap/imap-date.h src/lib-storage/index/index-fetch.c src/lib-storage/index/index-search.c
diffstat 6 files changed, 193 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-append.c	Mon Sep 02 21:32:25 2002 +0300
+++ b/src/imap/cmd-append.c	Mon Sep 02 22:08:47 2002 +0300
@@ -4,7 +4,7 @@
 #include "ioloop.h"
 #include "commands.h"
 #include "imap-parser.h"
-#include "rfc822-date.h"
+#include "imap-date.h"
 
 /* Returns -1 = error, 0 = need more data, 1 = successful. flags and
    internal_date may be NULL as a result, but mailbox and msg_size are always
@@ -98,7 +98,7 @@
 	if (internal_date_str == NULL) {
 		/* no time given, default to now. */
 		internal_date = ioloop_time;
-	} else if (!rfc822_parse_date(internal_date_str, &internal_date)) {
+	} else if (!imap_parse_datetime(internal_date_str, &internal_date)) {
 		client_send_tagline(client, "BAD Invalid internal date.");
 		return TRUE;
 	}
--- a/src/lib-imap/Makefile.am	Mon Sep 02 21:32:25 2002 +0300
+++ b/src/lib-imap/Makefile.am	Mon Sep 02 22:08:47 2002 +0300
@@ -6,6 +6,7 @@
 
 libimap_a_SOURCES = \
 	imap-bodystructure.c \
+	imap-date.c \
 	imap-envelope.c \
 	imap-match.c \
 	imap-message-cache.c \
@@ -14,6 +15,7 @@
 
 noinst_HEADERS = \
 	imap-bodystructure.h \
+	imap-date.h \
 	imap-envelope.h \
 	imap-match.h \
 	imap-message-cache.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-imap/imap-date.c	Mon Sep 02 22:08:47 2002 +0300
@@ -0,0 +1,165 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "lib.h"
+#include "gmtoff.h"
+
+#include <ctype.h>
+
+static const char *month_names[] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static int parse_timezone(const char *str)
+{
+	int offset;
+
+	/* +|-zone */
+	if ((*str != '+' && *str != '-') ||
+	    !i_isdigit(str[1]) || !i_isdigit(str[2]) ||
+	    !i_isdigit(str[3]) || !i_isdigit(str[4]))
+		return 0;
+
+	offset = (str[1]-'0') * 1000 + (str[2]-'0') * 100 +
+		(str[3]-'0') * 10 + (str[4]-'0');
+	return *str == '+' ? offset : -offset;
+}
+
+static const char *imap_parse_date_internal(const char *str, struct tm *tm)
+{
+	int i;
+
+	if (str == NULL || *str == '\0')
+		return NULL;
+
+	memset(tm, 0, sizeof(struct tm));
+
+	/* "dd-mon-yyyy [hh:mi:ss +|-zone]"
+	   dd is 1-2 digits and may be prefixed with space or zero. */
+
+	if (str[0] == ' ') {
+		/* " d-..." */
+		str++;
+	}
+
+	if (!(i_isdigit(str[0]) && (str[1] == '-' ||
+				    (i_isdigit(str[1]) && str[2] == '-'))))
+	      return NULL;
+
+	tm->tm_mday = (str[0]-'0');
+	if (str[1] == '-')
+		str += 2;
+	else {
+		tm->tm_mday = (tm->tm_mday * 10) + (str[1]-'0');
+		str += 3;
+	}
+
+	/* month name */
+	for (i = 0; i < 12; i++) {
+		if (strncasecmp(month_names[i], str, 3) == 0) {
+			tm->tm_mon = i;
+			break;
+		}
+	}
+	if (i == 12 || str[3] != '-')
+		return NULL;
+	str += 4;
+
+	/* yyyy */
+	if (!i_isdigit(str[0]) || !i_isdigit(str[1]) ||
+	    !i_isdigit(str[2]) || !i_isdigit(str[3]))
+		return NULL;
+
+	tm->tm_year = (str[0]-'0') * 1000 + (str[1]-'0') * 100 +
+		(str[2]-'0') * 10 + (str[3]-'0') - 1900;
+
+	str += 4;
+	return str;
+}
+
+int imap_parse_date(const char *str, time_t *time)
+{
+	struct tm tm;
+
+	str = imap_parse_date_internal(str, &tm);
+	if (str == NULL)
+		return FALSE;
+
+	tm.tm_isdst = -1;
+	*time = mktime(&tm);
+	return *time >= 0;
+}
+
+int imap_parse_datetime(const char *str, time_t *time)
+{
+	struct tm tm;
+	int zone_offset;
+
+	str = imap_parse_date_internal(str, &tm);
+	if (str == NULL)
+		return FALSE;
+
+	if (str[0] != ' ')
+		return FALSE;
+	str++;
+
+	/* hh: */
+	if (!i_isdigit(str[0]) || !i_isdigit(str[1]) || str[2] != '-')
+		return FALSE;
+	tm.tm_hour = (str[0]-'0') * 10 + (str[1]-'0');
+	str += 3;
+
+	/* mm: */
+	if (!i_isdigit(str[0]) || !i_isdigit(str[1]) || str[2] != '-')
+		return FALSE;
+	tm.tm_min = (str[0]-'0') * 10 + (str[1]-'0');
+	str += 3;
+
+	/* ss */
+	if (!i_isdigit(str[0]) || !i_isdigit(str[1]) || str[2] != ' ')
+		return FALSE;
+	tm.tm_sec = (str[0]-'0') * 10 + (str[1]-'0');
+	str += 3;
+
+	/* timezone */
+	zone_offset = parse_timezone(str);
+
+	tm.tm_isdst = -1;
+	*time = mktime(&tm);
+	if (*time < 0)
+		return FALSE;
+
+	*time -= zone_offset * 60;
+	return TRUE;
+}
+
+const char *imap_to_datetime(time_t time)
+{
+	struct tm *tm;
+	int offset, negative;
+
+	tm = localtime(&time);
+	offset = gmtoff(tm, time);
+	if (offset >= 0)
+		negative = 0;
+	else {
+		negative = 1;
+		offset = -offset;
+	}
+	offset /= 60;
+
+	return t_strdup_printf("%02d-%s-%04d %02d:%02d:%02d %c%02d%02d",
+			       tm->tm_mday, month_names[tm->tm_mon],
+			       tm->tm_year+1900,
+			       tm->tm_hour, tm->tm_min, tm->tm_sec,
+			       negative ? '-' : '+', offset / 60, offset % 60);
+}
+
+const char *imap_to_date(time_t time)
+{
+	struct tm *tm;
+
+	tm = localtime(&time);
+	return t_strdup_printf("%d-%s-%04d", tm->tm_mday,
+			       month_names[tm->tm_mon], tm->tm_year+1900);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-imap/imap-date.h	Mon Sep 02 22:08:47 2002 +0300
@@ -0,0 +1,10 @@
+#ifndef __IMAP_DATE_H
+#define __IMAP_DATE_H
+
+int imap_parse_date(const char *str, time_t *time);
+int imap_parse_datetime(const char *str, time_t *time);
+
+const char *imap_to_datetime(time_t time);
+const char *imap_to_date(time_t time);
+
+#endif
--- a/src/lib-storage/index/index-fetch.c	Mon Sep 02 21:32:25 2002 +0300
+++ b/src/lib-storage/index/index-fetch.c	Mon Sep 02 22:08:47 2002 +0300
@@ -3,11 +3,11 @@
 #include "lib.h"
 #include "iobuffer.h"
 #include "temp-string.h"
-#include "rfc822-date.h"
 #include "index-storage.h"
 #include "index-fetch.h"
 #include "mail-messageset.h"
 #include "message-send.h"
+#include "imap-date.h"
 #include "imap-util.h"
 #include "imap-message-cache.h"
 
@@ -76,7 +76,7 @@
 static void index_fetch_internaldate(MailIndexRecord *rec, FetchContext *ctx)
 {
 	t_string_printfa(ctx->str, " INTERNALDATE \"%s\"",
-                         rfc822_to_date(rec->internal_date));
+                         imap_to_datetime(rec->internal_date));
 }
 
 static void index_fetch_uid(MailIndexRecord *rec, FetchContext *ctx)
--- a/src/lib-storage/index/index-search.c	Mon Sep 02 21:32:25 2002 +0300
+++ b/src/lib-storage/index/index-search.c	Mon Sep 02 22:08:47 2002 +0300
@@ -3,8 +3,8 @@
 #include "lib.h"
 #include "iobuffer.h"
 #include "mmap-util.h"
-#include "rfc822-date.h"
 #include "rfc822-tokenize.h"
+#include "imap-date.h"
 #include "index-storage.h"
 #include "mail-search.h"
 
@@ -38,17 +38,6 @@
 	unsigned int max_searchword_len;
 } SearchTextContext;
 
-/* truncate timestamp to day */
-static time_t timestamp_trunc(time_t t)
-{
-	struct tm *tm;
-
-	tm = localtime(&t);
-	tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
-
-	return mktime(tm);
-}
-
 static int msgset_contains(const char *set, unsigned int match_num,
 			   unsigned int max_num)
 {
@@ -149,34 +138,31 @@
 
 	/* dates */
 	case SEARCH_BEFORE:
-		if (!rfc822_parse_date(value, &t))
+		if (!imap_parse_date(value, &t))
 			return FALSE;
-		return rec->internal_date < timestamp_trunc(t);
+		return rec->internal_date < t;
 	case SEARCH_ON:
-		if (!rfc822_parse_date(value, &t))
+		if (!imap_parse_date(value, &t))
 			return FALSE;
-		t = timestamp_trunc(t);
 		return rec->internal_date >= t &&
 			rec->internal_date < t + 3600*24;
 	case SEARCH_SINCE:
-		if (!rfc822_parse_date(value, &t))
+		if (!imap_parse_date(value, &t))
 			return FALSE;
-		return rec->internal_date >= timestamp_trunc(t);
+		return rec->internal_date >= t;
 
 	case SEARCH_SENTBEFORE:
-		if (!rfc822_parse_date(value, &t))
+		if (!imap_parse_date(value, &t))
 			return FALSE;
-		return rec->sent_date < timestamp_trunc(t);
+		return rec->sent_date < t;
 	case SEARCH_SENTON:
-		if (!rfc822_parse_date(value, &t))
+		if (!imap_parse_date(value, &t))
 			return FALSE;
-		t = timestamp_trunc(t);
-		return rec->sent_date >= t &&
-			rec->sent_date < t + 3600*24;
+		return rec->sent_date >= t && rec->sent_date < t + 3600*24;
 	case SEARCH_SENTSINCE:
-		if (!rfc822_parse_date(value, &t))
+		if (!imap_parse_date(value, &t))
 			return FALSE;
-		return rec->sent_date >= timestamp_trunc(t);
+		return rec->sent_date >= t;
 
 	/* sizes */
 	case SEARCH_SMALLER: