From: Timo Sirainen Date: Tue, 13 Apr 2010 13:52:23 +0000 (+0300) Subject: lib-storage: Added support for searching save date. X-Git-Tag: 2.0.beta5~133 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=71acee685176766c9fb54937af18d3907dabec05;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Added support for searching save date. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c index 58749ffa6c..5c63ea55b1 100644 --- a/src/lib-storage/index/index-search.c +++ b/src/lib-storage/index/index-search.c @@ -215,20 +215,38 @@ static int search_arg_match_cached(struct index_search_context *ctx, struct tm *tm; uoff_t virtual_size; time_t date; - int timezone_offset; + int tz_offset; + bool have_tz_offset; switch (arg->type) { /* internal dates */ case SEARCH_BEFORE: case SEARCH_ON: case SEARCH_SINCE: - if (mail_get_received_date(ctx->mail, &date) < 0) - return -1; + have_tz_offset = FALSE; tz_offset = 0; date = (time_t)-1; + switch (arg->value.date_type) { + case MAIL_SEARCH_DATE_TYPE_SENT: + if (mail_get_date(ctx->mail, &date, &tz_offset) < 0) + return -1; + have_tz_offset = TRUE; + break; + case MAIL_SEARCH_DATE_TYPE_RECEIVED: + if (mail_get_received_date(ctx->mail, &date) < 0) + return -1; + break; + case MAIL_SEARCH_DATE_TYPE_SAVED: + if (mail_get_save_date(ctx->mail, &date) < 0) + return -1; + break; + } if ((arg->value.search_flags & MAIL_SEARCH_ARG_FLAG_USE_TZ) == 0) { - tm = localtime(&date); - date += utc_offset(tm, date)*60; + if (!have_tz_offset) { + tm = localtime(&date); + tz_offset = utc_offset(tm, date); + } + date += tz_offset * 60; } switch (arg->type) { @@ -244,32 +262,6 @@ static int search_arg_match_cached(struct index_search_context *ctx, break; } - /* sent dates */ - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: - /* NOTE: RFC-3501 specifies that timezone is ignored - in searches. date is returned as UTC, so change it. */ - if (mail_get_date(ctx->mail, &date, &timezone_offset) < 0) - return -1; - - if ((arg->value.search_flags & - MAIL_SEARCH_ARG_FLAG_USE_TZ) == 0) - date += timezone_offset * 60; - - switch (arg->type) { - case SEARCH_SENTBEFORE: - return date < arg->value.time; - case SEARCH_SENTON: - return date >= arg->value.time && - date < arg->value.time + 3600*24; - case SEARCH_SENTSINCE: - return date >= arg->value.time; - default: - /* unreachable */ - break; - } - /* sizes */ case SEARCH_SMALLER: case SEARCH_LARGER: @@ -331,12 +323,12 @@ static int search_sent(enum mail_search_arg_type type, time_t search_time, sent_time += timezone_offset * 60; switch (type) { - case SEARCH_SENTBEFORE: + case SEARCH_BEFORE: return sent_time < search_time; - case SEARCH_SENTON: + case SEARCH_ON: return sent_time >= search_time && sent_time < search_time + 3600*24; - case SEARCH_SENTSINCE: + case SEARCH_SINCE: return sent_time >= search_time; default: i_unreached(); @@ -400,9 +392,12 @@ static void search_header_arg(struct mail_search_arg *arg, /* first check that the field name matches to argument. */ switch (arg->type) { - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: + case SEARCH_BEFORE: + case SEARCH_ON: + case SEARCH_SINCE: + if (arg->value.date_type != MAIL_SEARCH_DATE_TYPE_SENT) + return; + /* date is handled differently than others */ if (strcasecmp(ctx->hdr->name, "Date") == 0) { if (ctx->hdr->continues) { @@ -491,9 +486,12 @@ static void search_header_unmatch(struct mail_search_arg *arg, void *context ATTR_UNUSED) { switch (arg->type) { - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: + case SEARCH_BEFORE: + case SEARCH_ON: + case SEARCH_SINCE: + if (arg->value.date_type != MAIL_SEARCH_DATE_TYPE_SENT) + break; + if (arg->not) { /* date header not found, so we match only for NOT searches */ @@ -1167,9 +1165,6 @@ static bool search_arg_is_static(struct mail_search_arg *arg) case SEARCH_BEFORE: case SEARCH_ON: case SEARCH_SINCE: - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: case SEARCH_SMALLER: case SEARCH_LARGER: case SEARCH_HEADER: diff --git a/src/lib-storage/mail-search-build.c b/src/lib-storage/mail-search-build.c index 14bb79ae3b..086956f37a 100644 --- a/src/lib-storage/mail-search-build.c +++ b/src/lib-storage/mail-search-build.c @@ -105,12 +105,13 @@ arg_new_size(struct search_build_data *data, return TRUE; } -#define ARG_NEW_DATE(type) \ - arg_new_date(data, args, next_sarg, type) +#define ARG_NEW_DATE(type, date_type) \ + arg_new_date(data, args, next_sarg, type, date_type) static bool arg_new_date(struct search_build_data *data, const struct imap_arg **args, struct mail_search_arg **next_sarg, - enum mail_search_arg_type type) + enum mail_search_arg_type type, + enum mail_search_date_type date_type) { struct mail_search_arg *sarg; const char *value; @@ -122,6 +123,7 @@ arg_new_date(struct search_build_data *data, data->error = "Invalid search date parameter"; return FALSE; } + sarg->value.date_type = date_type; return TRUE; } @@ -316,7 +318,8 @@ static bool search_arg_build(struct search_build_data *data, return ARG_NEW_STR(SEARCH_BODY); } else if (strcmp(key, "BEFORE") == 0) { /* */ - return ARG_NEW_DATE(SEARCH_BEFORE); + return ARG_NEW_DATE(SEARCH_BEFORE, + MAIL_SEARCH_DATE_TYPE_RECEIVED); } else if (strcmp(key, "BCC") == 0) { /* */ return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, key); @@ -445,7 +448,8 @@ static bool search_arg_build(struct search_build_data *data, return TRUE; } if (strcmp(key, "ON") == 0) { /* */ - return ARG_NEW_DATE(SEARCH_ON); + return ARG_NEW_DATE(SEARCH_ON, + MAIL_SEARCH_DATE_TYPE_RECEIVED); } if (strcmp(key, "OLD") == 0) { /* OLD == NOT RECENT */ if (!ARG_NEW_FLAGS(MAIL_RECENT)) @@ -476,16 +480,20 @@ static bool search_arg_build(struct search_build_data *data, return ARG_NEW_HEADER(SEARCH_HEADER_COMPRESS_LWSP, key); } else if (strcmp(key, "SENTBEFORE") == 0) { /* */ - return ARG_NEW_DATE(SEARCH_SENTBEFORE); + return ARG_NEW_DATE(SEARCH_BEFORE, + MAIL_SEARCH_DATE_TYPE_SENT); } else if (strcmp(key, "SENTON") == 0) { /* */ - return ARG_NEW_DATE(SEARCH_SENTON); + return ARG_NEW_DATE(SEARCH_ON, + MAIL_SEARCH_DATE_TYPE_SENT); } else if (strcmp(key, "SENTSINCE") == 0) { /* */ - return ARG_NEW_DATE(SEARCH_SENTSINCE); + return ARG_NEW_DATE(SEARCH_SINCE, + MAIL_SEARCH_DATE_TYPE_SENT); } else if (strcmp(key, "SINCE") == 0) { /* */ - return ARG_NEW_DATE(SEARCH_SINCE); + return ARG_NEW_DATE(SEARCH_SINCE, + MAIL_SEARCH_DATE_TYPE_RECEIVED); } else if (strcmp(key, "SMALLER") == 0) { /* */ return ARG_NEW_SIZE(SEARCH_SMALLER); @@ -589,6 +597,18 @@ static bool search_arg_build(struct search_build_data *data, } else if (strcmp(key, "X-MAILBOX") == 0) { /* */ return ARG_NEW_STR(SEARCH_MAILBOX); + } else if (strcmp(key, "X-SAVEDBEFORE") == 0) { + /* */ + return ARG_NEW_DATE(SEARCH_BEFORE, + MAIL_SEARCH_DATE_TYPE_SAVED); + } else if (strcmp(key, "X-SAVEDON") == 0) { + /* */ + return ARG_NEW_DATE(SEARCH_ON, + MAIL_SEARCH_DATE_TYPE_SAVED); + } else if (strcmp(key, "X-SAVEDSINCE") == 0) { + /* */ + return ARG_NEW_DATE(SEARCH_SINCE, + MAIL_SEARCH_DATE_TYPE_SAVED); } break; default: diff --git a/src/lib-storage/mail-search.c b/src/lib-storage/mail-search.c index fff19b629c..8b9d27deb4 100644 --- a/src/lib-storage/mail-search.c +++ b/src/lib-storage/mail-search.c @@ -277,10 +277,8 @@ mail_search_arg_dup_one(pool_t pool, const struct mail_search_arg *arg) case SEARCH_BEFORE: case SEARCH_ON: case SEARCH_SINCE: - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: new_arg->value.time = arg->value.time; + new_arg->value.date_type = arg->value.date_type; break; case SEARCH_SMALLER: case SEARCH_LARGER: @@ -461,10 +459,11 @@ search_arg_analyze(struct mail_search_arg *arg, buffer_t *headers, subarg = subarg->next; } break; - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: - buffer_append(headers, &date_hdr, sizeof(const char *)); + case SEARCH_BEFORE: + case SEARCH_ON: + case SEARCH_SINCE: + if (arg->value.date_type == MAIL_SEARCH_DATE_TYPE_SENT) + buffer_append(headers, &date_hdr, sizeof(const char *)); break; case SEARCH_HEADER: case SEARCH_HEADER_ADDRESS: @@ -752,10 +751,8 @@ static bool mail_search_arg_one_equals(const struct mail_search_arg *arg1, case SEARCH_BEFORE: case SEARCH_ON: case SEARCH_SINCE: - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: - return arg1->value.time == arg2->value.time; + return arg1->value.time == arg2->value.time && + arg1->value.date_type == arg2->value.date_type; case SEARCH_SMALLER: case SEARCH_LARGER: diff --git a/src/lib-storage/mail-search.h b/src/lib-storage/mail-search.h index fa42a691b8..5f489e4d3b 100644 --- a/src/lib-storage/mail-search.h +++ b/src/lib-storage/mail-search.h @@ -18,13 +18,10 @@ enum mail_search_arg_type { SEARCH_FLAGS, SEARCH_KEYWORDS, - /* dates */ + /* dates (date_type required) */ SEARCH_BEFORE, SEARCH_ON, /* time must point to beginning of the day */ SEARCH_SINCE, - SEARCH_SENTBEFORE, - SEARCH_SENTON, /* time must point to beginning of the day */ - SEARCH_SENTSINCE, /* sizes */ SEARCH_SMALLER, @@ -48,8 +45,14 @@ enum mail_search_arg_type { SEARCH_MAILBOX }; +enum mail_search_date_type { + MAIL_SEARCH_DATE_TYPE_SENT = 1, + MAIL_SEARCH_DATE_TYPE_RECEIVED, + MAIL_SEARCH_DATE_TYPE_SAVED +}; + enum mail_search_arg_flag { - /* For (SENT)BEFORE/SINCE/ON searches: Don't drop timezone from + /* For BEFORE/SINCE/ON searches: Don't drop timezone from comparisons */ MAIL_SEARCH_ARG_FLAG_USE_TZ = 0x01, }; @@ -77,6 +80,7 @@ struct mail_search_arg { uoff_t size; enum mail_flags flags; enum mail_search_arg_flag search_flags; + enum mail_search_date_type date_type; enum mail_thread_type thread_type; struct mail_keywords *keywords; struct mail_search_modseq *modseq;