cmd-search.c revision b70c95140cf9abef23cb1c303f6f6ce110679e4f
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Options that don't return any seq/uid results */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (SEARCH_RETURN_ESEARCH | SEARCH_RETURN_MODSEQ | SEARCH_RETURN_SAVE | \
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenimap_partial_range_parse(struct imap_search_context *ctx, const char *str)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->partial1 = ctx->partial1 * 10 + *str-'0';
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (str++; *str >= '0' && *str <= '9'; str++)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->partial2 = ctx->partial2 * 10 + *str-'0';
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainensearch_parse_return_options(struct imap_search_context *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct client_command_context *cmd = ctx->cmd;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int idx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "SEARCH return options contain non-atoms.");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen name = t_str_ucase(IMAP_ARG_STR_NONULL(args));
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen "PARTIAL can be used only once.");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "PARTIAL range missing.");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "PARTIAL range broken.");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "Unknown SEARCH return option");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_UPDATE) != 0 &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen client_search_update_lookup(cmd->client, cmd->tag, &idx) != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen client_send_command_error(cmd, "Duplicate search update tag");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_PARTIAL) != 0 &&
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen (ctx->return_options & SEARCH_RETURN_ALL) != 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen client_send_command_error(cmd, "PARTIAL conflicts with ALL");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void imap_search_args_check(struct imap_search_context *ctx,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen imap_search_args_check(ctx, sargs->value.subargs);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic void imap_search_result_save(struct imap_search_context *ctx)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (!array_is_created(&client->search_updates))
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen else if (array_count(&client->search_updates) >=
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* too many updates */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen imap_quote_append_string(str, ctx->cmd->tag, FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen result = mailbox_search_result_save(ctx->search_ctx,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen update = array_append_space(&client->search_updates);
c3d9da3955043aef88c17b71f2081e894186aa6bTimo Sirainenimap_search_init(struct imap_search_context *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen client_enable(ctx->cmd->client, MAILBOX_FEATURE_CONDSTORE);
9a790c932a9e5d52939c5d9e56e8b0ef02166d43Timo Sirainen ctx->trans = mailbox_transaction_begin(ctx->box, 0);
9a790c932a9e5d52939c5d9e56e8b0ef02166d43Timo Sirainen ctx->search_ctx = mailbox_search_init(ctx->trans, sargs, NULL);
a62470cd293855dff816317d35356a989bda8f20Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_UPDATE) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void imap_search_send_result_standard(struct imap_search_context *ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i, count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; i < count; i++) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (seq = range[i].seq1; seq <= range[i].seq2; seq++)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (unsigned long long)ctx->highest_seen_modseq);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenimap_search_send_partial(struct imap_search_context *ctx, string_t *str)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, " PARTIAL (%u:%u ", ctx->partial1, ctx->partial2);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen seq_range_array_iter_init(&iter, &ctx->result);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!seq_range_array_iter_nth(&iter, ctx->partial1 - 1, &n1)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* no results (in range) */
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen if (!seq_range_array_iter_nth(&iter, ctx->partial2 - 1, &n2))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* FIXME: we should save the search result for later use */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen seq_range_array_remove_range(&ctx->result, 1, n1 - 1);
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainenstatic void imap_search_send_result(struct imap_search_context *ctx)
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen unsigned int count;
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen if ((ctx->return_options & SEARCH_RETURN_ESEARCH) == 0) {
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen (SEARCH_RETURN_ESEARCH | SEARCH_RETURN_SAVE)) {
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen /* we only wanted to save the result, don't return
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ESEARCH result. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen imap_quote_append_string(str, ctx->cmd->tag, FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_MIN) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_MAX) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, " MAX %u", range[count-1].seq2);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_ALL) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_PARTIAL) != 0)
c7a50b2c29780eaa3668bbac738e3fa3e4e171e8Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_COUNT) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, " COUNT %u", ctx->result_count);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (unsigned long long)ctx->highest_seen_modseq);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen o_stream_send(client->output, str_data(str), str_len(str));
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainenstatic int imap_search_deinit(struct imap_search_context *ctx)
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen if (mailbox_search_deinit(&ctx->search_ctx) < 0)
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen /* search failed */
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen if ((ctx->return_options & SEARCH_RETURN_SAVE) != 0)
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen array_clear(&ctx->cmd->client->search_saved_uidset);
e42e27fcc497c7b4a5cc0b6ff304abca5ccfcb4fTimo Sirainen (void)mailbox_transaction_commit(&ctx->trans);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void search_update_mail(struct imap_search_context *ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_MODSEQ) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((ctx->return_options & SEARCH_RETURN_SAVE) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen seq_range_array_add(&ctx->cmd->client->search_saved_uidset,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool cmd_search_more(struct client_command_context *cmd)
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen struct imap_search_context *ctx = cmd->context;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen enum search_return_options opts = ctx->return_options;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen unsigned int count;
&tryagain) > 0) {
if (minmax) {
SEARCH_RETURN_COUNT)) == 0) {
if (tryagain)
return FALSE;
i_unreached();
i_unreached();
return TRUE;
bool finished;
if (!finished)
const char *charset;
return FALSE;
return TRUE;
return TRUE;
args++;
return TRUE;
args++;
return FALSE;
args++;
return TRUE;
args++;
if (ret <= 0)
return ret < 0;
return TRUE;
return FALSE;