Mercurial > dovecot > original-hg > dovecot-1.2
diff src/lib-storage/index/index-search.c @ 408:e057845d94ca HEAD
Dropped sent_time and alignment from MailIndexRecord. SEARCH can now use
cached ENVELOPE data to search FROM, TO, CC, BCC, SUBJECT, HEADER MESSAGE-ID
and HEADER IN-REPLY-TO. They're never cached anymore now. Also SEARCH SENT*
had to be changed to use ENVELOPE (or fallback to Date-header parsing)
because sent_time was removed.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 12 Oct 2002 01:33:54 +0300 |
parents | d037915978ca |
children | 1f0e7229ee58 |
line wrap: on
line diff
--- a/src/lib-storage/index/index-search.c Fri Oct 11 15:46:18 2002 +0300 +++ b/src/lib-storage/index/index-search.c Sat Oct 12 01:33:54 2002 +0300 @@ -4,7 +4,10 @@ #include "iobuffer.h" #include "mmap-util.h" #include "rfc822-tokenize.h" +#include "rfc822-date.h" +#include "message-size.h" #include "imap-date.h" +#include "imap-envelope.h" #include "index-storage.h" #include "mail-index-util.h" #include "mail-modifylog.h" @@ -155,19 +158,6 @@ return FALSE; return rec->internal_date >= t; - case SEARCH_SENTBEFORE: - if (!imap_parse_date(value, &t)) - return FALSE; - return rec->sent_date < t; - case SEARCH_SENTON: - if (!imap_parse_date(value, &t)) - return FALSE; - return rec->sent_date >= t && rec->sent_date < t + 3600*24; - case SEARCH_SENTSINCE: - if (!imap_parse_date(value, &t)) - return FALSE; - return rec->sent_date >= t; - /* sizes, only with fastscanning */ case SEARCH_SMALLER: if (!mail_index_get_virtual_size(ibox->index, rec, TRUE, &size)) @@ -201,21 +191,42 @@ } } -static int match_field(MailIndex *index, MailIndexRecord *rec, - MailField field, const char *value) +static int search_sent(MailSearchArgType type, const char *value, + const char *sent_value) { - const char *field_value; - size_t i, value_len; + time_t search_time, sent_time; + int timezone_offset; + + if (!imap_parse_date(value, &search_time)) + return 0; + + /* NOTE: RFC2060 doesn't specify if timezones should affect + matching, so we ignore them. */ + if (!rfc822_parse_date(sent_value, &sent_time, &timezone_offset)) + return 0; - field_value = index->lookup_field(index, rec, field); - if (field_value == NULL) - return -1; + switch (type) { + case SEARCH_SENTBEFORE: + return sent_time < search_time; + case SEARCH_SENTON: + return sent_time >= search_time && + sent_time < search_time + 3600*24; + case SEARCH_SENTSINCE: + return sent_time >= search_time; + default: + i_assert(0); + } +} - /* note: value is already uppercased */ - value_len = strlen(value); - for (i = 0; field_value[i] != '\0'; i++) { - if (value[0] == i_toupper(field_value[i]) && - strncasecmp(value, field_value+i, value_len) == 0) +static int search_substr(const char *haystack, const char *needle) +{ + size_t i, needle_len; + + /* note: needle is already uppercased */ + needle_len = strlen(needle); + for (i = 0; haystack[i] != '\0'; i++) { + if (needle[0] == i_toupper(haystack[i]) && + strncasecmp(needle, haystack+i, needle_len) == 0) return 1; } @@ -226,20 +237,64 @@ static int search_arg_match_cached(MailIndex *index, MailIndexRecord *rec, MailSearchArgType type, const char *value) { + ImapEnvelopeField env_field; + const char *envelope, *field; + int ret; + switch (type) { + case SEARCH_SENTBEFORE: + case SEARCH_SENTON: + case SEARCH_SENTSINCE: + env_field = IMAP_ENVELOPE_DATE; + break; + case SEARCH_FROM: - return match_field(index, rec, FIELD_TYPE_FROM, value); + env_field = IMAP_ENVELOPE_FROM; + break; case SEARCH_TO: - return match_field(index, rec, FIELD_TYPE_TO, value); + env_field = IMAP_ENVELOPE_TO; + break; case SEARCH_CC: - return match_field(index, rec, FIELD_TYPE_CC, value); + env_field = IMAP_ENVELOPE_CC; + break; case SEARCH_BCC: - return match_field(index, rec, FIELD_TYPE_BCC, value); + env_field = IMAP_ENVELOPE_BCC; + break; case SEARCH_SUBJECT: - return match_field(index, rec, FIELD_TYPE_SUBJECT, value); + env_field = IMAP_ENVELOPE_SUBJECT; + break; + + case SEARCH_IN_REPLY_TO: + env_field = IMAP_ENVELOPE_IN_REPLY_TO; + break; + case SEARCH_MESSAGE_ID: + env_field = IMAP_ENVELOPE_MESSAGE_ID; + break; default: return -1; } + + t_push(); + + /* get field from hopefully cached envelope */ + envelope = index->lookup_field(index, rec, FIELD_TYPE_ENVELOPE); + field = envelope == NULL ? NULL : + imap_envelope_parse(envelope, env_field); + + if (field == NULL) + ret = -1; + else { + switch (type) { + case SEARCH_SENTBEFORE: + case SEARCH_SENTON: + case SEARCH_SENTSINCE: + ret = search_sent(type, value, field); + default: + ret = search_substr(field, value); + } + } + t_pop(); + return ret; } static void search_cached_arg(MailSearchArg *arg, void *context) @@ -351,6 +406,17 @@ /* first check that the field name matches to argument. */ switch (arg->type) { + case SEARCH_SENTBEFORE: + case SEARCH_SENTON: + case SEARCH_SENTSINCE: + /* date is handled differently than others */ + if (ctx->name_len == 4 && + strncasecmp(ctx->name, "Date", 4) == 0) { + search_sent(arg->type, arg->value.str, + t_strndup(ctx->value, ctx->value_len)); + } + return; + case SEARCH_FROM: if (ctx->name_len != 4 || strncasecmp(ctx->name, "From", 4) != 0) @@ -407,6 +473,7 @@ SearchHeaderContext *ctx = context; if ((name_len > 0 && ctx->custom_header) || + (name_len == 4 && strncasecmp(name, "Date", 4) == 0) || (name_len == 4 && strncasecmp(name, "From", 4) == 0) || (name_len == 2 && strncasecmp(name, "To", 2) == 0) || (name_len == 2 && strncasecmp(name, "Cc", 2) == 0) || @@ -505,6 +572,7 @@ MailSearchArg *args) { IOBuffer *inbuf; + MessageSize hdr_size; int have_headers, have_body, have_text; /* first check what we need to use */ @@ -524,7 +592,15 @@ /* header checks */ ctx.custom_header = TRUE; ctx.args = args; - message_parse_header(NULL, inbuf, NULL, search_header, &ctx); + message_parse_header(NULL, inbuf, &hdr_size, + search_header, &ctx); + + i_assert(rec->header_size == 0 || + hdr_size.physical_size == rec->header_size); + } else if (rec->header_size == 0) { + message_get_header_size(inbuf, &hdr_size); + } else { + hdr_size.physical_size = rec->header_size; } if (have_text) { @@ -536,15 +612,14 @@ } } - search_arg_match_data(inbuf, rec->header_size, + search_arg_match_data(inbuf, hdr_size.physical_size, args, search_text_header); } if (have_text || have_body) { - if (inbuf->offset != rec->header_size) { + if (inbuf->offset == 0) { /* skip over headers */ - i_assert(inbuf->offset == 0); - io_buffer_skip(inbuf, rec->header_size); + io_buffer_skip(inbuf, hdr_size.physical_size); } search_arg_match_data(inbuf, rec->body_size, args,