imap-search.c revision cc2259f1d0a6672d9bd69e5d37cbfd00bd2855d3
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "mail-storage.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "mail-search.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-date.h"
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen#include "imap-search.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "imap-parser.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "imap-messageset.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainenstruct search_build_data {
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen pool_t pool;
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen struct mailbox *box;
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainen const char *error;
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainen};
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic int
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenimap_uidset_parse(pool_t pool, struct mailbox *box, const char *uidset,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct mail_search_seqset **seqset_r, const char **error_r)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct mail_search_seqset *seqset, **p;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen bool last;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen *seqset_r = imap_messageset_parse(pool, uidset);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*seqset_r == NULL) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = "Invalid UID messageset";
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p = seqset_r;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen for (seqset = *seqset_r; seqset != NULL; seqset = seqset->next) {
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (seqset->seq1 == (uint32_t)-1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* last message, stays same */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen continue;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen last = seqset->seq2 == (uint32_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mailbox_get_uids(box, seqset->seq1, seqset->seq2,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen &seqset->seq1, &seqset->seq2);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (seqset->seq1 == 0 && last) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* we need special case for too_high_uid:* case */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen seqset->seq1 = seqset->seq2 = (uint32_t)-1;
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (seqset->seq1 != 0)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen p = &seqset->next;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen else
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen *p = seqset->next;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen *error_r = NULL;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return 0;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainenstatic struct mail_search_arg *
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainensearch_arg_new(pool_t pool, enum mail_search_arg_type type)
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen{
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen struct mail_search_arg *arg;
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen arg = p_new(pool, struct mail_search_arg, 1);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen arg->type = type;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen return arg;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen#define ARG_NEW(type) \
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen arg_new(data, args, next_sarg, type, TRUE, NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#define ARG_NEW_FLAG(type) \
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen arg_new(data, args, next_sarg, type, FALSE, NULL)
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen#define ARG_NEW_HEADER(type, hdr_name) \
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen arg_new(data, args, next_sarg, type, TRUE, hdr_name)
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainenstatic bool arg_new(struct search_build_data *data,
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen const struct imap_arg **args,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen struct mail_search_arg **next_sarg,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen enum mail_search_arg_type type, bool have_value,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen const char *hdr_name)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen struct mail_search_arg *sarg;
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *next_sarg = sarg = search_arg_new(data->pool, type);
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen if (!have_value)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return TRUE;
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen if ((*args)->type == IMAP_ARG_EOL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data->error = "Missing parameter for argument";
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen return FALSE;
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen }
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if ((*args)->type != IMAP_ARG_ATOM &&
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen (*args)->type != IMAP_ARG_STRING) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data->error = "Invalid parameter for argument";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen switch (type) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_BEFORE:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_ON:
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case SEARCH_SINCE:
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen case SEARCH_SENTBEFORE:
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen case SEARCH_SENTON:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case SEARCH_SENTSINCE:
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if (!imap_parse_date(IMAP_ARG_STR(*args), &sarg->value.time)) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen data->error = "Invalid search date parameter";
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return FALSE;
e03d986a74128f5ba30fcfda9f6e36578f5d8decTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen sarg->value.str = p_strdup(data->pool, IMAP_ARG_STR(*args));
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen break;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen *args += 1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (hdr_name != NULL)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen sarg->hdr_field_name = p_strdup(data->pool, hdr_name);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return TRUE;
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainenstatic bool search_arg_build(struct search_build_data *data,
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen const struct imap_arg **args,
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen struct mail_search_arg **next_sarg)
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen{
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen struct mail_search_seqset *seqset;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen struct mail_search_arg **subargs;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen const struct imap_arg *arg;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen const char *str;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen if ((*args)->type == IMAP_ARG_EOL) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen data->error = "Missing argument";
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return FALSE;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen arg = *args;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen if (arg->type == IMAP_ARG_NIL) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* NIL not allowed */
4b41116563110d00330896a568eff1078c382827Timo Sirainen data->error = "NIL not allowed";
4b41116563110d00330896a568eff1078c382827Timo Sirainen return FALSE;
4b41116563110d00330896a568eff1078c382827Timo Sirainen }
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (arg->type == IMAP_ARG_LIST) {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen const struct imap_arg *listargs = IMAP_ARG_LIST_ARGS(arg);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (listargs->type == IMAP_ARG_EOL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data->error = "Empty list not allowed";
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return FALSE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen *next_sarg = search_arg_new(data->pool, SEARCH_SUB);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen subargs = &(*next_sarg)->value.subargs;
dbe64f3893616a4005c8946be75d2dc8f6823d72Timo Sirainen while (listargs->type != IMAP_ARG_EOL) {
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainen if (!search_arg_build(data, &listargs, subargs))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen subargs = &(*subargs)->next;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen *args += 1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen i_assert(arg->type == IMAP_ARG_ATOM ||
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen arg->type == IMAP_ARG_STRING);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen /* string argument - get the name and jump to next */
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen str = IMAP_ARG_STR(arg);
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen *args += 1;
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen str = t_str_ucase(str);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen switch (*str) {
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen case 'A':
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen if (strcmp(str, "ANSWERED") == 0)
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen return ARG_NEW_FLAG(SEARCH_ANSWERED);
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen else if (strcmp(str, "ALL") == 0)
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen return ARG_NEW_FLAG(SEARCH_ALL);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case 'B':
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (strcmp(str, "BODY") == 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* <string> */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen *IMAP_ARG_STR(*args) == '\0') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *args += 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ARG_NEW_FLAG(SEARCH_ALL);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return ARG_NEW(SEARCH_BODY);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen } else if (strcmp(str, "BEFORE") == 0) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* <date> */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return ARG_NEW(SEARCH_BEFORE);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen } else if (strcmp(str, "BCC") == 0) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* <string> */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen }
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen break;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen case 'C':
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen if (strcmp(str, "CC") == 0) {
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen /* <string> */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen break;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen case 'D':
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen if (strcmp(str, "DELETED") == 0)
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen return ARG_NEW_FLAG(SEARCH_DELETED);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else if (strcmp(str, "DRAFT") == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return ARG_NEW_FLAG(SEARCH_DRAFT);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen break;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen case 'F':
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (strcmp(str, "FLAGGED") == 0)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return ARG_NEW_FLAG(SEARCH_FLAGGED);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else if (strcmp(str, "FROM") == 0) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* <string> */
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen }
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen break;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen case 'H':
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (strcmp(str, "HEADER") == 0) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* <field-name> <string> */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen const char *key;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if ((*args)->type == IMAP_ARG_EOL) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen data->error = "Missing parameter for HEADER";
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen return FALSE;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen if ((*args)->type != IMAP_ARG_ATOM &&
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen (*args)->type != IMAP_ARG_STRING) {
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen data->error = "Invalid parameter for HEADER";
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return FALSE;
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen }
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen key = t_str_ucase(IMAP_ARG_STR(*args));
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen *args += 1;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen return ARG_NEW_HEADER(SEARCH_HEADER, key);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen break;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen case 'K':
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (strcmp(str, "KEYWORD") == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* <flag> */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return ARG_NEW(SEARCH_KEYWORD);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen }
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen break;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen case 'L':
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen if (strcmp(str, "LARGER") == 0) {
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen /* <n> */
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen return ARG_NEW(SEARCH_LARGER);
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen }
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen break;
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen case 'N':
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen if (strcmp(str, "NOT") == 0) {
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen if (!search_arg_build(data, args, next_sarg))
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen return FALSE;
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen (*next_sarg)->not = !(*next_sarg)->not;
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen return TRUE;
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen } else if (strcmp(str, "NEW") == 0) {
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen /* NEW == (RECENT UNSEEN) */
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen *next_sarg = search_arg_new(data->pool, SEARCH_SUB);
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen subargs = &(*next_sarg)->value.subargs;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen *subargs = search_arg_new(data->pool, SEARCH_RECENT);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen (*subargs)->next = search_arg_new(data->pool,
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen SEARCH_SEEN);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen (*subargs)->next->not = TRUE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return TRUE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen break;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case 'O':
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (strcmp(str, "OR") == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* <search-key1> <search-key2> */
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen *next_sarg = search_arg_new(data->pool, SEARCH_OR);
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen subargs = &(*next_sarg)->value.subargs;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen for (;;) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (!search_arg_build(data, args, subargs))
c0225f7f6b43d34dc58c17d3304f0fd60ab89894Timo Sirainen return FALSE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen subargs = &(*subargs)->next;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen /* <key> OR <key> OR ... <key> - put them all
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen under one SEARCH_OR list. */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if ((*args)->type == IMAP_ARG_EOL)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen break;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if ((*args)->type != IMAP_ARG_ATOM ||
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen strcasecmp(IMAP_ARG_STR_NONULL(*args),
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "OR") != 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen break;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen *args += 1;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (!search_arg_build(data, args, subargs))
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return FALSE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return TRUE;
9af6cc9ebc9986c1275ebdfa29c39e152af1557eTimo Sirainen } if (strcmp(str, "ON") == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* <date> */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return ARG_NEW(SEARCH_ON);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen } if (strcmp(str, "OLD") == 0) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* OLD == NOT RECENT */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (!ARG_NEW_FLAG(SEARCH_RECENT))
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return FALSE;
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen (*next_sarg)->not = TRUE;
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen return TRUE;
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen }
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen break;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case 'R':
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (strcmp(str, "RECENT") == 0)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return ARG_NEW_FLAG(SEARCH_RECENT);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen break;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen case 'S':
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (strcmp(str, "SEEN") == 0)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return ARG_NEW_FLAG(SEARCH_SEEN);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else if (strcmp(str, "SUBJECT") == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* <string> */
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen return ARG_NEW_HEADER(SEARCH_HEADER, str);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else if (strcmp(str, "SENTBEFORE") == 0) {
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen /* <date> */
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen return ARG_NEW(SEARCH_SENTBEFORE);
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen } else if (strcmp(str, "SENTON") == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* <date> */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return ARG_NEW(SEARCH_SENTON);
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen } else if (strcmp(str, "SENTSINCE") == 0) {
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen /* <date> */
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen return ARG_NEW(SEARCH_SENTSINCE);
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen } else if (strcmp(str, "SINCE") == 0) {
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen /* <date> */
1eb17e61d3d38372674aa0c55caedb0185a985f5Timo Sirainen return ARG_NEW(SEARCH_SINCE);
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen } else if (strcmp(str, "SMALLER") == 0) {
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen /* <n> */
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen return ARG_NEW(SEARCH_SMALLER);
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen }
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen break;
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen case 'T':
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen if (strcmp(str, "TEXT") == 0) {
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen /* <string> */
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen *IMAP_ARG_STR(*args) == '\0') {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen *args += 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ARG_NEW_FLAG(SEARCH_ALL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
e4c90f0b88e40a8f92b8f5e1f1a3ea701e5c965cTimo Sirainen return ARG_NEW(SEARCH_TEXT);
defb12ecd360df672ffb2f4dbf4d1218a0a9549cTimo Sirainen } else if (strcmp(str, "TO") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* <string> */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen break;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen case 'U':
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (strcmp(str, "UID") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* <message set> */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!ARG_NEW(SEARCH_SEQSET))
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen return FALSE;
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return imap_uidset_parse(data->pool, data->box,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen (*next_sarg)->value.str,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen &(*next_sarg)->value.seqset,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen &data->error) == 0;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen } else if (strcmp(str, "UNANSWERED") == 0) {
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen if (!ARG_NEW_FLAG(SEARCH_ANSWERED))
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen return FALSE;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen (*next_sarg)->not = TRUE;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen return TRUE;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen } else if (strcmp(str, "UNDELETED") == 0) {
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen if (!ARG_NEW_FLAG(SEARCH_DELETED))
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen return FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen (*next_sarg)->not = TRUE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return TRUE;
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen } else if (strcmp(str, "UNDRAFT") == 0) {
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen if (!ARG_NEW_FLAG(SEARCH_DRAFT))
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen (*next_sarg)->not = TRUE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return TRUE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen } else if (strcmp(str, "UNFLAGGED") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!ARG_NEW_FLAG(SEARCH_FLAGGED))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (*next_sarg)->not = TRUE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return TRUE;
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen } else if (strcmp(str, "UNKEYWORD") == 0) {
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen /* <flag> */
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen if (!ARG_NEW(SEARCH_KEYWORD))
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen return FALSE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen (*next_sarg)->not = TRUE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return TRUE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen } else if (strcmp(str, "UNSEEN") == 0) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!ARG_NEW_FLAG(SEARCH_SEEN))
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return FALSE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen (*next_sarg)->not = TRUE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return TRUE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen break;
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen case 'X':
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen if (strcmp(str, "X-BODY-FAST") == 0) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* <string> */
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen *IMAP_ARG_STR(*args) == '\0') {
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen *args += 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return ARG_NEW_FLAG(SEARCH_ALL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen return ARG_NEW(SEARCH_BODY_FAST);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else if (strcmp(str, "X-TEXT-FAST") == 0) {
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen /* <string> */
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen *IMAP_ARG_STR(*args) == '\0') {
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen *args += 1;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return ARG_NEW_FLAG(SEARCH_ALL);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen }
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen return ARG_NEW(SEARCH_TEXT_FAST);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen }
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen break;
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen default:
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen if (*str == '*' || (*str >= '0' && *str <= '9')) {
e050e5c9b1688765f1fdfce9b7141f7b614383fdTimo Sirainen /* <message-set> */
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen seqset = imap_messageset_parse(data->pool, str);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (seqset == NULL) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen data->error = "Invalid messageset";
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen return FALSE;
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen }
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen if (!ARG_NEW_FLAG(SEARCH_SEQSET))
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return FALSE;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen (*next_sarg)->value.seqset = seqset;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return TRUE;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen break;
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen }
de58be41126e5d68008d2ea706d62ccdc1f29337Timo Sirainen
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen data->error = t_strconcat("Unknown argument ", str, NULL);
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen return FALSE;
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen}
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstruct mail_search_arg *
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenimap_search_args_build(pool_t pool, struct mailbox *box,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen const struct imap_arg *args, const char **error_r)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct search_build_data data;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct mail_search_arg *first_sarg, **sargs;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen *error_r = NULL;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen data.box = box;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen data.pool = pool;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen data.error = NULL;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* get the first arg */
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen first_sarg = NULL; sargs = &first_sarg;
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen while (args->type != IMAP_ARG_EOL) {
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen if (!search_arg_build(&data, &args, sargs)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = data.error;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sargs = &(*sargs)->next;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen return first_sarg;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenstatic int imap_search_get_msgset_arg(struct client_command_context *cmd,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *messageset,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct mail_search_arg **arg_r,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char **error_r)
ebe6df72f1309135f02b6a4d2aef1e81a073f91cTimo Sirainen{
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen struct mail_search_arg *arg;
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen
b83deefd2cf1e293373673eefb4d5cf60907978cTimo Sirainen arg = p_new(cmd->pool, struct mail_search_arg, 1);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen arg->type = SEARCH_SEQSET;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen arg->value.seqset = imap_messageset_parse(cmd->pool, messageset);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* when there are no messages, all messagesets are invalid.
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if there's at least one message:
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen - * gives seq1 = seq2 = (uint32_t)-1
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen - n:* should work if n <= messages_count
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen - n:m or m should work if m <= messages_count
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (arg->value.seqset == NULL || cmd->client->messages_count == 0 ||
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen (arg->value.seqset->seq1 > cmd->client->messages_count &&
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen arg->value.seqset->seq1 != (uint32_t)-1) ||
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen (arg->value.seqset->seq2 > cmd->client->messages_count &&
b3b4f3875850099c9292ad74d08bb385c3988f8fTimo Sirainen arg->value.seqset->seq2 != (uint32_t)-1)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "Invalid messageset";
return -1;
}
*arg_r = arg;
return 0;
}
static int
imap_search_get_uidset_arg(pool_t pool, struct mailbox *box, const char *uidset,
struct mail_search_arg **arg_r, const char **error_r)
{
struct mail_search_arg *arg;
arg = p_new(pool, struct mail_search_arg, 1);
arg->type = SEARCH_SEQSET;
*arg_r = arg;
return imap_uidset_parse(pool, box, uidset, &arg->value.seqset,
error_r);
}
struct mail_search_arg *
imap_search_get_arg(struct client_command_context *cmd,
const char *set, bool uid)
{
struct mail_search_arg *search_arg = NULL;
const char *error;
int ret;
if (!uid) {
ret = imap_search_get_msgset_arg(cmd, set, &search_arg, &error);
} else {
ret = imap_search_get_uidset_arg(cmd->pool,
cmd->client->mailbox, set,
&search_arg, &error);
}
if (ret < 0) {
client_send_command_error(cmd, error);
return NULL;
}
return search_arg;
}