Mercurial > dovecot > core-2.2
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: