Mercurial > dovecot > original-hg > dovecot-1.2
changeset 6962:659e4a606aae HEAD
Replaced SEARCH_<flag> with a generic SEARCH_FLAGS. Use value.size for
SEARCH_LARGER and SEARCH_SMALLER and give an error if it's not a valid
number.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 08 Dec 2007 18:26:42 +0200 |
parents | 16f761cdc910 |
children | 5fb86ed98860 |
files | src/imap/imap-expunge.c src/imap/imap-search.c src/lib-storage/index/index-search.c src/lib-storage/mail-search.h |
diffstat | 4 files changed, 177 insertions(+), 130 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/imap-expunge.c Sat Dec 08 17:47:48 2007 +0200 +++ b/src/imap/imap-expunge.c Sat Dec 08 18:26:42 2007 +0200 @@ -19,7 +19,8 @@ } memset(&search_arg, 0, sizeof(search_arg)); - search_arg.type = SEARCH_DELETED; + search_arg.type = SEARCH_FLAGS; + search_arg.value.flags = MAIL_DELETED; search_arg.next = next_search_arg; t = mailbox_transaction_begin(box, 0);
--- a/src/imap/imap-search.c Sat Dec 08 17:47:48 2007 +0200 +++ b/src/imap/imap-search.c Sat Dec 08 18:26:42 2007 +0200 @@ -8,6 +8,8 @@ #include "imap-parser.h" #include "imap-messageset.h" +#include <stdlib.h> + struct search_build_data { pool_t pool; struct mailbox *box; @@ -63,58 +65,125 @@ return arg; } -#define ARG_NEW(type) \ - arg_new(data, args, next_sarg, type, TRUE, NULL) - -#define ARG_NEW_FLAG(type) \ - arg_new(data, args, next_sarg, type, FALSE, NULL) - -#define ARG_NEW_HEADER(type, hdr_name) \ - arg_new(data, args, next_sarg, type, TRUE, hdr_name) - -static bool arg_new(struct search_build_data *data, - const struct imap_arg **args, - struct mail_search_arg **next_sarg, - enum mail_search_arg_type type, bool have_value, - const char *hdr_name) +static bool +arg_get_next(struct search_build_data *data, const struct imap_arg **args, + const char **value_r) { - struct mail_search_arg *sarg; - - *next_sarg = sarg = search_arg_new(data->pool, type); - if (!have_value) - return TRUE; - if ((*args)->type == IMAP_ARG_EOL) { data->error = "Missing parameter for argument"; return FALSE; } - if ((*args)->type != IMAP_ARG_ATOM && (*args)->type != IMAP_ARG_STRING) { data->error = "Invalid parameter for argument"; return FALSE; } - switch (type) { - case SEARCH_BEFORE: - case SEARCH_ON: - case SEARCH_SINCE: - case SEARCH_SENTBEFORE: - case SEARCH_SENTON: - case SEARCH_SENTSINCE: - if (!imap_parse_date(IMAP_ARG_STR(*args), &sarg->value.time)) { - data->error = "Invalid search date parameter"; - return FALSE; - } - default: - sarg->value.str = p_strdup(data->pool, IMAP_ARG_STR(*args)); - break; + *value_r = IMAP_ARG_STR(*args); + *args += 1; + return TRUE; +} + +#define ARG_NEW_SINGLE(type) \ + arg_new_single(data, next_sarg, type) +static bool +arg_new_single(struct search_build_data *data, + struct mail_search_arg **next_sarg, + enum mail_search_arg_type type) +{ + *next_sarg = search_arg_new(data->pool, type); + return TRUE; +} + +#define ARG_NEW_STR(type) \ + arg_new_str(data, args, next_sarg, type) +static bool +arg_new_str(struct search_build_data *data, + const struct imap_arg **args, struct mail_search_arg **next_sarg, + enum mail_search_arg_type type) +{ + struct mail_search_arg *sarg; + const char *value; + + *next_sarg = sarg = search_arg_new(data->pool, type); + if (!arg_get_next(data, args, &value)) + return FALSE; + sarg->value.str = p_strdup(data->pool, value); + return TRUE; +} + +#define ARG_NEW_FLAGS(flags) \ + arg_new_flags(data, next_sarg, flags) +static bool +arg_new_flags(struct search_build_data *data, + struct mail_search_arg **next_sarg, enum mail_flags flags) +{ + struct mail_search_arg *sarg; + + *next_sarg = sarg = search_arg_new(data->pool, SEARCH_FLAGS); + sarg->value.flags = flags; + return TRUE; +} + +#define ARG_NEW_SIZE(type) \ + arg_new_size(data, args, next_sarg, type) +static bool +arg_new_size(struct search_build_data *data, + const struct imap_arg **args, struct mail_search_arg **next_sarg, + enum mail_search_arg_type type) +{ + struct mail_search_arg *sarg; + const char *value; + char *p; + + *next_sarg = sarg = search_arg_new(data->pool, type); + if (!arg_get_next(data, args, &value)) + return FALSE; + + sarg->value.size = strtoull(value, &p, 10); + if (*p != '\0') { + data->error = "Invalid search size parameter"; + return FALSE; } - *args += 1; + return TRUE; +} + +#define ARG_NEW_DATE(type) \ + arg_new_date(data, args, next_sarg, 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) +{ + struct mail_search_arg *sarg; + const char *value; - if (hdr_name != NULL) - sarg->hdr_field_name = p_strdup(data->pool, hdr_name); + *next_sarg = sarg = search_arg_new(data->pool, type); + if (!arg_get_next(data, args, &value)) + return FALSE; + if (!imap_parse_date(value, &sarg->value.time)) { + data->error = "Invalid search date parameter"; + return FALSE; + } + return TRUE; +} +#define ARG_NEW_HEADER(type, hdr_name) \ + arg_new_header(data, args, next_sarg, type, hdr_name) +static bool +arg_new_header(struct search_build_data *data, + const struct imap_arg **args, struct mail_search_arg **next_sarg, + enum mail_search_arg_type type, const char *hdr_name) +{ + struct mail_search_arg *sarg; + const char *value; + + *next_sarg = sarg = search_arg_new(data->pool, type); + if (!arg_get_next(data, args, &value)) + return FALSE; + + sarg->hdr_field_name = p_strdup(data->pool, hdr_name); + sarg->value.str = p_strdup(data->pool, value); return TRUE; } @@ -171,9 +240,9 @@ switch (*str) { case 'A': if (strcmp(str, "ANSWERED") == 0) - return ARG_NEW_FLAG(SEARCH_ANSWERED); + return ARG_NEW_FLAGS(MAIL_ANSWERED); else if (strcmp(str, "ALL") == 0) - return ARG_NEW_FLAG(SEARCH_ALL); + return ARG_NEW_SINGLE(SEARCH_ALL); break; case 'B': if (strcmp(str, "BODY") == 0) { @@ -181,12 +250,12 @@ if (IMAP_ARG_TYPE_IS_STRING((*args)->type) && *IMAP_ARG_STR(*args) == '\0') { *args += 1; - return ARG_NEW_FLAG(SEARCH_ALL); + return ARG_NEW_SINGLE(SEARCH_ALL); } - return ARG_NEW(SEARCH_BODY); + return ARG_NEW_STR(SEARCH_BODY); } else if (strcmp(str, "BEFORE") == 0) { /* <date> */ - return ARG_NEW(SEARCH_BEFORE); + return ARG_NEW_DATE(SEARCH_BEFORE); } else if (strcmp(str, "BCC") == 0) { /* <string> */ return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str); @@ -200,13 +269,13 @@ break; case 'D': if (strcmp(str, "DELETED") == 0) - return ARG_NEW_FLAG(SEARCH_DELETED); + return ARG_NEW_FLAGS(MAIL_DELETED); else if (strcmp(str, "DRAFT") == 0) - return ARG_NEW_FLAG(SEARCH_DRAFT); + return ARG_NEW_FLAGS(MAIL_DRAFT); break; case 'F': if (strcmp(str, "FLAGGED") == 0) - return ARG_NEW_FLAG(SEARCH_FLAGGED); + return ARG_NEW_FLAGS(MAIL_FLAGGED); else if (strcmp(str, "FROM") == 0) { /* <string> */ return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str); @@ -235,13 +304,13 @@ case 'K': if (strcmp(str, "KEYWORD") == 0) { /* <flag> */ - return ARG_NEW(SEARCH_KEYWORD); + return ARG_NEW_STR(SEARCH_KEYWORD); } break; case 'L': if (strcmp(str, "LARGER") == 0) { /* <n> */ - return ARG_NEW(SEARCH_LARGER); + return ARG_NEW_SIZE(SEARCH_LARGER); } break; case 'N': @@ -255,9 +324,11 @@ *next_sarg = search_arg_new(data->pool, SEARCH_SUB); subargs = &(*next_sarg)->value.subargs; - *subargs = search_arg_new(data->pool, SEARCH_RECENT); + *subargs = search_arg_new(data->pool, SEARCH_FLAGS); + (*subargs)->value.flags = MAIL_RECENT; (*subargs)->next = search_arg_new(data->pool, - SEARCH_SEEN); + SEARCH_FLAGS); + (*subargs)->next->value.flags = MAIL_SEEN; (*subargs)->next->not = TRUE; return TRUE; } @@ -292,10 +363,10 @@ return TRUE; } if (strcmp(str, "ON") == 0) { /* <date> */ - return ARG_NEW(SEARCH_ON); + return ARG_NEW_DATE(SEARCH_ON); } if (strcmp(str, "OLD") == 0) { /* OLD == NOT RECENT */ - if (!ARG_NEW_FLAG(SEARCH_RECENT)) + if (!ARG_NEW_FLAGS(MAIL_RECENT)) return FALSE; (*next_sarg)->not = TRUE; @@ -304,29 +375,29 @@ break; case 'R': if (strcmp(str, "RECENT") == 0) - return ARG_NEW_FLAG(SEARCH_RECENT); + return ARG_NEW_FLAGS(MAIL_RECENT); break; case 'S': if (strcmp(str, "SEEN") == 0) - return ARG_NEW_FLAG(SEARCH_SEEN); + return ARG_NEW_FLAGS(MAIL_SEEN); else if (strcmp(str, "SUBJECT") == 0) { /* <string> */ return ARG_NEW_HEADER(SEARCH_HEADER, str); } else if (strcmp(str, "SENTBEFORE") == 0) { /* <date> */ - return ARG_NEW(SEARCH_SENTBEFORE); + return ARG_NEW_DATE(SEARCH_SENTBEFORE); } else if (strcmp(str, "SENTON") == 0) { /* <date> */ - return ARG_NEW(SEARCH_SENTON); + return ARG_NEW_DATE(SEARCH_SENTON); } else if (strcmp(str, "SENTSINCE") == 0) { /* <date> */ - return ARG_NEW(SEARCH_SENTSINCE); + return ARG_NEW_DATE(SEARCH_SENTSINCE); } else if (strcmp(str, "SINCE") == 0) { /* <date> */ - return ARG_NEW(SEARCH_SINCE); + return ARG_NEW_DATE(SEARCH_SINCE); } else if (strcmp(str, "SMALLER") == 0) { /* <n> */ - return ARG_NEW(SEARCH_SMALLER); + return ARG_NEW_SIZE(SEARCH_SMALLER); } break; case 'T': @@ -335,9 +406,9 @@ if (IMAP_ARG_TYPE_IS_STRING((*args)->type) && *IMAP_ARG_STR(*args) == '\0') { *args += 1; - return ARG_NEW_FLAG(SEARCH_ALL); + return ARG_NEW_SINGLE(SEARCH_ALL); } - return ARG_NEW(SEARCH_TEXT); + return ARG_NEW_STR(SEARCH_TEXT); } else if (strcmp(str, "TO") == 0) { /* <string> */ return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str); @@ -346,7 +417,7 @@ case 'U': if (strcmp(str, "UID") == 0) { /* <message set> */ - if (!ARG_NEW(SEARCH_SEQSET)) + if (!ARG_NEW_STR(SEARCH_SEQSET)) return FALSE; return imap_uidset_parse(data->pool, data->box, @@ -354,33 +425,33 @@ &(*next_sarg)->value.seqset, &data->error) == 0; } else if (strcmp(str, "UNANSWERED") == 0) { - if (!ARG_NEW_FLAG(SEARCH_ANSWERED)) + if (!ARG_NEW_FLAGS(MAIL_ANSWERED)) return FALSE; (*next_sarg)->not = TRUE; return TRUE; } else if (strcmp(str, "UNDELETED") == 0) { - if (!ARG_NEW_FLAG(SEARCH_DELETED)) + if (!ARG_NEW_FLAGS(MAIL_DELETED)) return FALSE; (*next_sarg)->not = TRUE; return TRUE; } else if (strcmp(str, "UNDRAFT") == 0) { - if (!ARG_NEW_FLAG(SEARCH_DRAFT)) + if (!ARG_NEW_FLAGS(MAIL_DRAFT)) return FALSE; (*next_sarg)->not = TRUE; return TRUE; } else if (strcmp(str, "UNFLAGGED") == 0) { - if (!ARG_NEW_FLAG(SEARCH_FLAGGED)) + if (!ARG_NEW_FLAGS(MAIL_FLAGGED)) return FALSE; (*next_sarg)->not = TRUE; return TRUE; } else if (strcmp(str, "UNKEYWORD") == 0) { /* <flag> */ - if (!ARG_NEW(SEARCH_KEYWORD)) + if (!ARG_NEW_STR(SEARCH_KEYWORD)) return FALSE; (*next_sarg)->not = TRUE; return TRUE; } else if (strcmp(str, "UNSEEN") == 0) { - if (!ARG_NEW_FLAG(SEARCH_SEEN)) + if (!ARG_NEW_FLAGS(MAIL_SEEN)) return FALSE; (*next_sarg)->not = TRUE; return TRUE; @@ -392,17 +463,17 @@ if (IMAP_ARG_TYPE_IS_STRING((*args)->type) && *IMAP_ARG_STR(*args) == '\0') { *args += 1; - return ARG_NEW_FLAG(SEARCH_ALL); + return ARG_NEW_SINGLE(SEARCH_ALL); } - return ARG_NEW(SEARCH_BODY_FAST); + return ARG_NEW_STR(SEARCH_BODY_FAST); } else if (strcmp(str, "X-TEXT-FAST") == 0) { /* <string> */ if (IMAP_ARG_TYPE_IS_STRING((*args)->type) && *IMAP_ARG_STR(*args) == '\0') { *args += 1; - return ARG_NEW_FLAG(SEARCH_ALL); + return ARG_NEW_SINGLE(SEARCH_ALL); } - return ARG_NEW(SEARCH_TEXT_FAST); + return ARG_NEW_STR(SEARCH_TEXT_FAST); } break; default: @@ -414,7 +485,7 @@ return FALSE; } - if (!ARG_NEW_FLAG(SEARCH_SEQSET)) + if (!ARG_NEW_SINGLE(SEARCH_SEQSET)) return FALSE; (*next_sarg)->value.seqset = seqset;
--- a/src/lib-storage/index/index-search.c Sat Dec 08 17:47:48 2007 +0200 +++ b/src/lib-storage/index/index-search.c Sat Dec 08 18:26:42 2007 +0200 @@ -40,6 +40,7 @@ unsigned int failed:1; unsigned int sorted:1; unsigned int have_seqsets:1; + unsigned int have_flags:1; }; struct search_header_context { @@ -77,48 +78,26 @@ return FALSE; } -static uoff_t str_to_uoff_t(const char *str) -{ - uoff_t num; - - num = 0; - while (*str != '\0') { - if (*str < '0' || *str > '9') - return 0; - - num = num*10 + (*str - '0'); - str++; - } - - return num; -} - /* Returns >0 = matched, 0 = not matched, -1 = unknown */ static int search_arg_match_index(struct index_mail *imail, - enum mail_search_arg_type type, - const char *value) + struct mail_search_arg *arg) { - enum mail_flags flags = imail->data.flags; + enum mail_flags flags; const char *const *keywords; - switch (type) { + switch (arg->type) { /* flags */ - case SEARCH_ANSWERED: - return flags & MAIL_ANSWERED; - case SEARCH_DELETED: - return flags & MAIL_DELETED; - case SEARCH_DRAFT: - return flags & MAIL_DRAFT; - case SEARCH_FLAGGED: - return flags & MAIL_FLAGGED; - case SEARCH_SEEN: - return flags & MAIL_SEEN; - case SEARCH_RECENT: - return mail_get_flags(&imail->mail.mail) & MAIL_RECENT; + case SEARCH_FLAGS: + flags = imail->data.flags; + if ((arg->value.flags & MAIL_RECENT) != 0 && + index_mailbox_is_recent(imail->ibox, + imail->mail.mail.uid)) + flags |= MAIL_RECENT; + return (flags & arg->value.flags) == arg->value.flags; case SEARCH_KEYWORD: keywords = mail_get_keywords(&imail->mail.mail); while (*keywords != NULL) { - if (strcasecmp(*keywords, value) == 0) + if (strcasecmp(*keywords, arg->value.str) == 0) return 1; keywords++; } @@ -159,8 +138,7 @@ static void search_index_arg(struct mail_search_arg *arg, struct index_search_context *ctx) { - switch (search_arg_match_index(ctx->imail, arg->type, - arg->value.str)) { + switch (search_arg_match_index(ctx->imail, arg)) { case -1: /* unknown */ break; @@ -177,7 +155,7 @@ static int search_arg_match_cached(struct index_search_context *ctx, struct mail_search_arg *arg) { - uoff_t virtual_size, search_size; + uoff_t virtual_size; time_t date; int timezone_offset; @@ -231,11 +209,10 @@ if (mail_get_virtual_size(ctx->mail, &virtual_size) < 0) return -1; - search_size = str_to_uoff_t(arg->value.str); if (arg->type == SEARCH_SMALLER) - return virtual_size < search_size; + return virtual_size < arg->value.size; else - return virtual_size > search_size; + return virtual_size > arg->value.size; default: return -1; @@ -757,8 +734,14 @@ uint32_t *seq1, uint32_t *seq2) { for (; args != NULL; args = args->next) { - switch (args->type) { - case SEARCH_SEEN: + if (args->type != SEARCH_FLAGS) { + if (args->type == SEARCH_ALL) { + if (args->not) + return FALSE; + } + continue; + } + if ((args->value.flags & MAIL_SEEN) != 0) { /* SEEN with 0 seen? */ if (!args->not && hdr->seen_messages_count == 0) return FALSE; @@ -775,8 +758,8 @@ search_limit_lowwater(ctx, hdr->first_unseen_uid_lowwater, seq1); } - break; - case SEARCH_DELETED: + } + if ((args->value.flags & MAIL_DELETED) != 0) { /* DELETED with 0 deleted? */ if (!args->not && hdr->deleted_messages_count == 0) return FALSE; @@ -794,13 +777,6 @@ search_limit_lowwater(ctx, hdr->first_deleted_uid_lowwater, seq1); } - break; - case SEARCH_ALL: - if (args->not) - return FALSE; - break; - default: - break; } }
--- a/src/lib-storage/mail-search.h Sat Dec 08 17:47:48 2007 +0200 +++ b/src/lib-storage/mail-search.h Sat Dec 08 18:26:42 2007 +0200 @@ -1,6 +1,8 @@ #ifndef MAIL_SEARCH_H #define MAIL_SEARCH_H +#include "mail-types.h" + enum mail_search_arg_type { SEARCH_OR, SEARCH_SUB, @@ -10,12 +12,7 @@ SEARCH_SEQSET, /* flags */ - SEARCH_ANSWERED, - SEARCH_DELETED, - SEARCH_DRAFT, - SEARCH_FLAGGED, - SEARCH_SEEN, - SEARCH_RECENT, + SEARCH_FLAGS, SEARCH_KEYWORD, /* dates */ @@ -55,6 +52,8 @@ struct mail_search_seqset *seqset; const char *str; time_t time; + uoff_t size; + enum mail_flags flags; } value; void *context;