imap-sync.c revision ba5c8b0ae7460752adaf911901bf263788f62c72
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2014 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-common.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ostream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-user.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-search-build.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-quote.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-fetch.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-notify.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-commands.h"
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen#include "imap-sync.h"
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenstruct client_sync_context {
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen /* if multiple commands are in progress, we may need to wait for them
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen to finish before syncing mailbox. */
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen unsigned int counter;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen enum mailbox_sync_flags flags;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen enum imap_sync_flags imap_flags;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen const char *tagline;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen imap_sync_callback_t *callback;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen};
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainenstruct imap_sync_context {
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen struct client *client;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen struct mailbox *box;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen enum imap_sync_flags imap_flags;
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen struct mailbox_transaction_context *t;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox_sync_context *sync_ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail *mail;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct mailbox_status status;
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen struct mailbox_sync_status sync_status;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen struct mailbox_sync_rec sync_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(keywords) tmp_keywords;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(seq_range) expunges;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t seq;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(seq_range) search_adds, search_removes;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen unsigned int search_update_idx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int messages_count;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen unsigned int failed:1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen unsigned int finished:1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen unsigned int no_newmail:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int have_new_mails:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int search_update_notifying:1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen};
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainenstatic void uids_to_seqs(struct mailbox *box, ARRAY_TYPE(seq_range) *uids)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen T_BEGIN {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen ARRAY_TYPE(seq_range) seqs;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen const struct seq_range *range;
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen uint32_t seq1, seq2;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen t_array_init(&seqs, array_count(uids));
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen array_foreach(uids, range) {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen mailbox_get_seq_range(box, range->seq1, range->seq2,
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen &seq1, &seq2);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen /* since we have to notify about expunged messages,
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen we expect that all the referenced UIDs exist */
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen i_assert(seq1 != 0);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen i_assert(seq2 - seq1 == range->seq2 - range->seq1);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen seq_range_array_add_range(&seqs, seq1, seq2);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen /* replace uids with seqs */
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen array_clear(uids);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen array_append_array(uids, &seqs);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen } T_END;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen}
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainenstatic int search_update_fetch_more(const struct imap_search_update *update)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen{
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen int ret;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if ((ret = imap_fetch_more_no_lock_update(update->fetch_ctx)) <= 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return ret;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen /* finished the FETCH */
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (imap_fetch_end(update->fetch_ctx) < 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return 1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen}
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainenstatic int
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainenimap_sync_send_fetch_to_search_update(struct imap_sync_context *ctx,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen const struct imap_search_update *update)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen{
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen struct mail_search_args *search_args;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen struct mail_search_arg *arg;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen ARRAY_TYPE(seq_range) seqs;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (ctx->search_update_notifying)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen return search_update_fetch_more(update);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen i_assert(!update->fetch_ctx->state.fetching);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (array_count(&ctx->search_adds) == 0 || !ctx->have_new_mails)
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen return 1;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen search_args = mail_search_build_init();
6288d3611eda14a017dae9927b73f46afb646c96Timo Sirainen arg = mail_search_build_add(search_args, SEARCH_UIDSET);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen p_array_init(&arg->value.seqset, search_args->pool, 1);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen /* find the newly appended messages: ctx->messages_count is the message
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen count before new messages found by sync, client->messages_count is
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen the number of messages after. */
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen t_array_init(&seqs, 1);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen seq_range_array_add_range(&seqs, ctx->messages_count+1,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen ctx->client->messages_count);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mailbox_get_uid_range(ctx->client->mailbox, &seqs, &arg->value.seqset);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen /* remove messages not in the search_adds list */
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen seq_range_array_intersect(&arg->value.seqset, &ctx->search_adds);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen imap_fetch_begin(update->fetch_ctx, ctx->client->mailbox, search_args);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mail_search_args_unref(&search_args);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen return search_update_fetch_more(update);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen}
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenimap_sync_send_search_update(struct imap_sync_context *ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct imap_search_update *update,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen bool removes_only)
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen string_t *cmd;
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen int ret = 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!ctx->search_update_notifying) {
2e937ed8585299b2e879a28314902a5f644813d2Timo Sirainen mailbox_search_result_sync(update->result, &ctx->search_removes,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen &ctx->search_adds);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (array_count(&ctx->search_adds) == 0 &&
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen array_count(&ctx->search_removes) == 0)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return 1;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen i_assert(array_count(&ctx->search_adds) == 0 || !removes_only);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (update->fetch_ctx != NULL) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ret = imap_sync_send_fetch_to_search_update(ctx, update);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ret == 0) {
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen ctx->search_update_notifying = TRUE;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen return 0;
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ctx->search_update_notifying = FALSE;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen cmd = t_str_new(256);
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen str_append(cmd, "* ESEARCH (TAG ");
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen imap_append_string(cmd, update->tag);
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen str_append_c(cmd, ')');
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen if (update->return_uids)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen str_append(cmd, " UID");
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen else {
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen /* convert to sequences */
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen uids_to_seqs(ctx->client->mailbox, &ctx->search_removes);
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen uids_to_seqs(ctx->client->mailbox, &ctx->search_adds);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (array_count(&ctx->search_removes) != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_printfa(cmd, " REMOVEFROM (0 ");
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen imap_write_seq_range(cmd, &ctx->search_removes);
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen str_append_c(cmd, ')');
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (array_count(&ctx->search_adds) != 0) {
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen str_printfa(cmd, " ADDTO (0 ");
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen imap_write_seq_range(cmd, &ctx->search_adds);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen str_append_c(cmd, ')');
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen str_append(cmd, "\r\n");
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen o_stream_nsend(ctx->client->output, str_data(cmd), str_len(cmd));
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen return ret;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenstatic int
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenimap_sync_send_search_updates(struct imap_sync_context *ctx, bool removes_only)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct imap_search_update *updates;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen unsigned int i, count;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret = 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!array_is_created(&ctx->client->search_updates))
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (!array_is_created(&ctx->search_removes)) {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen i_array_init(&ctx->search_removes, 64);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen i_array_init(&ctx->search_adds, 128);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen }
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen updates = array_get(&ctx->client->search_updates, &count);
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen for (i = ctx->search_update_idx; i < count; i++) {
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen T_BEGIN {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ret = imap_sync_send_search_update(ctx, &updates[i],
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen removes_only);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } T_END;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret <= 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen ctx->search_update_idx = i;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return ret;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainenstruct imap_sync_context *
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainenimap_sync_init(struct client *client, struct mailbox *box,
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags)
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen{
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen struct imap_sync_context *ctx;
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen i_assert(client->mailbox == box);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen if (client->notify_immediate_expunges) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* NOTIFY enabled without SELECTED-DELAYED */
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen flags &= ~MAILBOX_SYNC_FLAG_NO_EXPUNGES;
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen }
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen ctx = i_new(struct imap_sync_context, 1);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->client = client;
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen ctx->box = box;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->imap_flags = imap_flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* make sure user can't DoS the system by causing Dovecot to create
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen tons of useless namespaces. */
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mail_user_drop_useless_namespaces(client->user);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->sync_ctx = mailbox_sync_init(box, flags);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->t = mailbox_transaction_begin(box, 0);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->mail = mail_alloc(ctx->t, MAIL_FETCH_FLAGS, NULL);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->messages_count = client->messages_count;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen i_array_init(&ctx->tmp_keywords, client->keywords.announce_count + 8);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen i_array_init(&ctx->expunges, 128);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen /* always send UIDs in FETCH replies */
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen ctx->imap_flags |= IMAP_SYNC_FLAG_SEND_UID;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen client_send_mailbox_flags(client, FALSE);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* send search updates the first time after sync is initialized.
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen it now contains expunged messages that must be sent before
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen EXPUNGE replies. */
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (imap_sync_send_search_updates(ctx, TRUE) == 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen i_unreached();
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->search_update_idx = 0;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return ctx;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
f0f9c8e94abac18f8acd91b9e724c4c32863723aTimo Sirainenstatic void
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainenimap_sync_send_highestmodseq(struct imap_sync_context *ctx,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen struct client_command_context *sync_cmd)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen{
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen struct client *client = ctx->client;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen uint64_t send_modseq = 0;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (ctx->sync_status.sync_delayed_expunges &&
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen client->highest_fetch_modseq > client->sync_last_full_modseq) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen /* if client updates highest-modseq using returned MODSEQs
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen it loses expunges. try to avoid this by sending it a lower
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen pre-expunge HIGHESTMODSEQ reply. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen send_modseq = client->sync_last_full_modseq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else if (!ctx->sync_status.sync_delayed_expunges &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->status.highest_modseq > client->sync_last_full_modseq &&
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen ctx->status.highest_modseq > client->highest_fetch_modseq) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* we've probably sent some VANISHED or EXISTS replies which
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen increased the highest-modseq. notify the client about
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen this. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen send_modseq = ctx->status.highest_modseq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (send_modseq == 0) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* no sending */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen } else if (sync_cmd->sync != NULL && /* IDLE doesn't have ->sync */
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen sync_cmd->sync->tagline != NULL && /* NOTIFY doesn't have tagline */
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen strncmp(sync_cmd->sync->tagline, "OK ", 3) == 0 &&
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen sync_cmd->sync->tagline[3] != '[') {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* modify the tagged reply directly */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_cmd->sync->tagline = p_strdup_printf(sync_cmd->pool,
8af07808ba203f8709e2ff9eaf2291e1c4a4d53dTimo Sirainen "OK [HIGHESTMODSEQ %llu] %s",
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen (unsigned long long)send_modseq,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen sync_cmd->sync->tagline + 3);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* send an untagged OK reply */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen client_send_line(client, t_strdup_printf(
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen "* OK [HIGHESTMODSEQ %llu] Highest",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen (unsigned long long)send_modseq));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (!ctx->sync_status.sync_delayed_expunges) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* no delayed expunges, remember this for future */
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen client->sync_last_full_modseq = ctx->status.highest_modseq;
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen }
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen client->highest_fetch_modseq = 0;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic int imap_sync_finish(struct imap_sync_context *ctx, bool aborting)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct client *client = ctx->client;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen int ret = ctx->failed ? -1 : 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (ctx->finished)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen return ret;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen ctx->finished = TRUE;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_free(&ctx->mail);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* the transaction is used only for fetching modseqs/flags.
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen it can't really fail.. */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen (void)mailbox_transaction_commit(&ctx->t);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (array_is_created(&ctx->expunges))
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen array_free(&ctx->expunges);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (mailbox_sync_deinit(&ctx->sync_ctx, &ctx->sync_status) < 0 ||
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen ctx->failed) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen ctx->failed = TRUE;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mailbox_get_open_status(ctx->box, STATUS_UIDVALIDITY |
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen STATUS_MESSAGES | STATUS_RECENT |
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen STATUS_HIGHESTMODSEQ, &ctx->status);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.uidvalidity != client->uidvalidity) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* most clients would get confused by this. disconnect them. */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client_disconnect_with_error(client,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen "Mailbox UIDVALIDITY changed");
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (!ctx->no_newmail && !aborting) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.messages < ctx->messages_count)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen i_panic("Message count decreased");
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.messages != ctx->messages_count &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client->notify_count_changes) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client_send_line(client,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen t_strdup_printf("* %u EXISTS", ctx->status.messages));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->have_new_mails = TRUE;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.recent != client->recent_count &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client->notify_count_changes) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client_send_line(client,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen t_strdup_printf("* %u RECENT", ctx->status.recent));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client->messages_count = ctx->status.messages;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client->recent_count = ctx->status.recent;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int imap_sync_notify_more(struct imap_sync_context *ctx)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen int ret = 1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->have_new_mails && ctx->client->notify_ctx != NULL) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* send FETCH replies for the new mails */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if ((ret = imap_client_notify_newmails(ctx->client)) == 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ret < 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->failed = TRUE;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* send search updates the second time after syncing in done.
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen now it contains added/removed messages. */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if ((ret = imap_sync_send_search_updates(ctx, FALSE)) < 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ctx->failed = TRUE;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenint imap_sync_deinit(struct imap_sync_context *ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct client_command_context *sync_cmd)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen int ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = imap_sync_finish(ctx, TRUE);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen imap_client_notify_finished(ctx->client);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if ((ctx->client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0 &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen !ctx->client->nonpermanent_modseqs)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen imap_sync_send_highestmodseq(ctx, sync_cmd);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (array_is_created(&ctx->search_removes)) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen array_free(&ctx->search_removes);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen array_free(&ctx->search_adds);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen array_free(&ctx->tmp_keywords);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen i_free(ctx);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic void imap_sync_add_modseq(struct imap_sync_context *ctx, string_t *str)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen uint64_t modseq;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen modseq = mail_get_modseq(ctx->mail);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->client->highest_fetch_modseq < modseq)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->client->highest_fetch_modseq = modseq;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen str_printfa(str, "MODSEQ (%llu)", (unsigned long long)modseq);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainenstatic int imap_sync_send_flags(struct imap_sync_context *ctx, string_t *str)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen enum mail_flags flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const char *const *keywords;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_set_seq(ctx->mail, ctx->seq);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen flags = mail_get_flags(ctx->mail);
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_get_keyword_indexes(ctx->mail));
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((flags & MAIL_DELETED) != 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->client->sync_seen_deletes = TRUE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_truncate(str, 0);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen str_printfa(str, "* %u FETCH (", ctx->seq);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen str_printfa(str, "UID %u ", ctx->mail->uid);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if ((mailbox_get_enabled_features(ctx->box) &
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen MAILBOX_FEATURE_CONDSTORE) != 0 &&
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen !ctx->client->nonpermanent_modseqs) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen imap_sync_add_modseq(ctx, str);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen str_append_c(str, ' ');
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen str_append(str, "FLAGS (");
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen imap_write_flags(str, flags, keywords);
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen str_append(str, "))");
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen return client_send_line_next(ctx->client, str_c(str));
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int imap_sync_send_modseq(struct imap_sync_context *ctx, string_t *str)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_set_seq(ctx->mail, ctx->seq);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen str_truncate(str, 0);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen str_printfa(str, "* %u FETCH (", ctx->seq);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen str_printfa(str, "UID %u ", ctx->mail->uid);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen imap_sync_add_modseq(ctx, str);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen str_append_c(str, ')');
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return client_send_line_next(ctx->client, str_c(str));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic void imap_sync_vanished(struct imap_sync_context *ctx)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const struct seq_range *seqs;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen unsigned int i, count;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen string_t *line;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen uint32_t seq, prev_uid, start_uid;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen bool comma = FALSE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* Convert expunge sequences to UIDs and send them in VANISHED line. */
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen seqs = array_get(&ctx->expunges, &count);
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen if (count == 0)
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen return;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen line = t_str_new(256);
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen str_append(line, "* VANISHED ");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (i = 0; i < count; i++) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen start_uid = 0; prev_uid = (uint32_t)-1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (seq = seqs[i].seq1; seq <= seqs[i].seq2; seq++) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen mail_set_seq(ctx->mail, seq);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (prev_uid + 1 != ctx->mail->uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (start_uid != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!comma)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen comma = TRUE;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen else
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_append_c(line, ',');
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_printfa(line, "%u", start_uid);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (start_uid != prev_uid) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_printfa(line, ":%u",
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen prev_uid);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen start_uid = ctx->mail->uid;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen prev_uid = ctx->mail->uid;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (!comma)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen comma = TRUE;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen else
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_append_c(line, ',');
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_printfa(line, "%u", start_uid);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (start_uid != prev_uid)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_printfa(line, ":%u", prev_uid);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen str_append(line, "\r\n");
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen o_stream_nsend(ctx->client->output, str_data(line), str_len(line));
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen}
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int imap_sync_send_expunges(struct imap_sync_context *ctx, string_t *str)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen{
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen int ret = 1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (!ctx->client->notify_count_changes) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* NOTIFY: MessageEvent not specified for selected mailbox */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return 1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (array_is_created(&ctx->expunges)) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* Use a single VANISHED line */
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen seq_range_array_add_range(&ctx->expunges,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->sync_rec.seq1,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->sync_rec.seq2);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return 1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ctx->seq == 0)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->seq = ctx->sync_rec.seq2;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen for (; ctx->seq >= ctx->sync_rec.seq1; ctx->seq--) {
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen if (ret == 0) {
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen /* buffer full, continue later */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen str_truncate(str, 0);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen str_printfa(str, "* %u EXPUNGE", ctx->seq);
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen ret = client_send_line_next(ctx->client, str_c(str));
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen }
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen return 1;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen}
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenint imap_sync_more(struct imap_sync_context *ctx)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen{
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen string_t *str;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen int ret = 1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ctx->finished)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return imap_sync_notify_more(ctx);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* finish syncing even when client has disconnected. otherwise our
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen internal state (ctx->messages_count) can get messed up and unless
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen we immediately stop handling all commands and syncs we could end up
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen assert-crashing. */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen str = t_str_new(256);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen for (;;) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ctx->seq == 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* get next one */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (!mailbox_sync_next(ctx->sync_ctx, &ctx->sync_rec)) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* finished */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ret = 1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen break;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ctx->sync_rec.seq2 > ctx->messages_count) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* don't send change notifications of messages we
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen haven't even announced to client yet */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ctx->sync_rec.seq1 > ctx->messages_count) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ctx->seq = 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen continue;
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ctx->sync_rec.seq2 = ctx->messages_count;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen /* EXPUNGEs must come last */
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen i_assert(!array_is_created(&ctx->expunges) ||
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen array_count(&ctx->expunges) == 0 ||
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ctx->sync_rec.type == MAILBOX_SYNC_TYPE_EXPUNGE);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen switch (ctx->sync_rec.type) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen case MAILBOX_SYNC_TYPE_FLAGS:
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (!ctx->client->notify_flag_changes) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* NOTIFY: FlagChange not specified for
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen selected mailbox */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen }
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen if (ctx->seq == 0)
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen ctx->seq = ctx->sync_rec.seq1;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen ret = 1;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen if (ret == 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen break;
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen ret = imap_sync_send_flags(ctx, str);
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen }
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen break;
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen case MAILBOX_SYNC_TYPE_EXPUNGE:
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen ret = imap_sync_send_expunges(ctx, str);
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (ret > 0) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen /* update only after we're finished, so that
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen the seq2 > messages_count check above
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen doesn't break */
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen ctx->messages_count -=
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen ctx->sync_rec.seq2 -
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen ctx->sync_rec.seq1 + 1;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen case MAILBOX_SYNC_TYPE_MODSEQ:
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if ((ctx->client->enabled_features &
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen MAILBOX_FEATURE_CONDSTORE) == 0)
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen break;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (!ctx->client->notify_flag_changes) {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen /* NOTIFY: FlagChange not specified for
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen selected mailbox. The RFC doesn't explicitly
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen specify MODSEQ changes, but they're close
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen enough to flag changes. */
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen break;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen if (ctx->seq == 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->seq = ctx->sync_rec.seq1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen ret = 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen if (ret == 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = imap_sync_send_modseq(ctx, str);
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen break;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen if (ret == 0) {
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen /* buffer full */
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen break;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx->seq = 0;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret > 0) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (array_is_created(&ctx->expunges))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen imap_sync_vanished(ctx);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (imap_sync_finish(ctx, FALSE) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen return imap_sync_more(ctx);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenbool imap_sync_is_allowed(struct client *client)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (client->syncing)
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen return FALSE;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (client->mailbox != NULL &&
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen mailbox_transaction_get_count(client->mailbox) > 0)
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen return FALSE;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen return TRUE;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen}
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainenstatic bool cmd_finish_sync(struct client_command_context *cmd)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (cmd->sync->callback != NULL)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return cmd->sync->callback(cmd);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (cmd->sync->tagline != NULL)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen client_send_tagline(cmd, cmd->sync->tagline);
60d3fa9883237e896a8704275b6116fa46f7ffdaTimo Sirainen return TRUE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic bool cmd_sync_continue(struct client_command_context *sync_cmd)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct client_command_context *cmd, *prev;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen struct client *client = sync_cmd->client;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen struct imap_sync_context *ctx = sync_cmd->context;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen int ret;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(ctx->client == client);
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((ret = imap_sync_more(ctx)) == 0)
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen return FALSE;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (ret < 0)
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen ctx->failed = TRUE;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen client->syncing = FALSE;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (imap_sync_deinit(ctx, sync_cmd) < 0) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen client_send_untagged_storage_error(client,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mailbox_get_storage(client->mailbox));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_cmd->context = NULL;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* Finish all commands that waited for this sync. Go through the queue
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen backwards, so that tagged replies are sent in the same order as
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen they were received. This fixes problems with clients that rely on
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen this (Apple Mail 3.2) */
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen for (cmd = client->command_queue; cmd->next != NULL; cmd = cmd->next) ;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (; cmd != NULL; cmd = prev) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen prev = cmd->prev;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen cmd != sync_cmd &&
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen cmd->sync->counter+1 == client->sync_counter) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (cmd_finish_sync(cmd))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen client_command_free(&cmd);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return cmd_finish_sync(sync_cmd);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic void get_common_sync_flags(struct client *client,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen enum mailbox_sync_flags *flags_r,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen enum imap_sync_flags *imap_flags_r)
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen{
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen struct client_command_context *cmd;
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen unsigned int count = 0, fast_count = 0, noexpunges_count = 0;
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *flags_r = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *imap_flags_r = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if (cmd->sync != NULL &&
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen cmd->sync->counter == client->sync_counter) {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen fast_count++;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen noexpunges_count++;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *flags_r |= cmd->sync->flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *imap_flags_r |= cmd->sync->imap_flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen count++;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(noexpunges_count == 0 || noexpunges_count == count);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (fast_count != count)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *flags_r &= ~MAILBOX_SYNC_FLAG_FAST;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen i_assert((*flags_r & MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) == 0);
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainenstatic bool cmd_sync_client(struct client_command_context *sync_cmd)
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen{
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen struct client *client = sync_cmd->client;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen struct imap_sync_context *ctx;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen enum mailbox_sync_flags flags;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen enum imap_sync_flags imap_flags;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen bool no_newmail;
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen /* there may be multiple commands waiting. use their combined flags */
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen get_common_sync_flags(client, &flags, &imap_flags);
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen client->sync_counter++;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen
6e4cd4ba520bc22ce375de378f4751136ebcf75aTimo Sirainen no_newmail = (client->set->parsed_workarounds & WORKAROUND_DELAY_NEWMAIL) != 0 &&
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen client->notify_ctx == NULL && /* always disabled with NOTIFY */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (imap_flags & IMAP_SYNC_FLAG_SAFE) == 0;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if (no_newmail) {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen /* expunges might break the client just as badly as new mail
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen notifications. */
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen flags |= MAILBOX_SYNC_FLAG_NO_EXPUNGES;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen }
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen client->syncing = TRUE;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ctx = imap_sync_init(client, client->mailbox, imap_flags, flags);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->no_newmail = no_newmail;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen /* handle the syncing using sync_cmd. it doesn't actually matter which
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen one of the pending commands it is. */
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen sync_cmd->func = cmd_sync_continue;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen sync_cmd->context = ctx;
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen sync_cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (!cmd_sync_continue(sync_cmd)) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen return FALSE;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen }
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen client_command_free(&sync_cmd);
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen cmd_sync_delayed(client);
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen return TRUE;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen}
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen
c9a03c8a03a782488981f81bd7c6b5e01ff55f06Timo Sirainenstatic bool ATTR_NULL(4, 5)
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainencmd_sync_full(struct client_command_context *cmd, enum mailbox_sync_flags flags,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen enum imap_sync_flags imap_flags, const char *tagline,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen imap_sync_callback_t *callback)
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen{
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen struct client *client = cmd->client;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(client->output_cmd_lock == NULL);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (cmd->cancel)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return TRUE;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (client->mailbox == NULL) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen /* no mailbox selected, no point in delaying the sync */
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen i_assert(callback == NULL);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (tagline != NULL)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen client_send_tagline(cmd, tagline);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen return TRUE;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen cmd->sync = p_new(cmd->pool, struct client_sync_context, 1);
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen cmd->sync->counter = client->sync_counter;
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen cmd->sync->flags = flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen cmd->sync->imap_flags = imap_flags;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen cmd->sync->tagline = p_strdup(cmd->pool, tagline);
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen cmd->sync->callback = callback;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen cmd->state = CLIENT_COMMAND_STATE_WAIT_SYNC;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen cmd->func = NULL;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen cmd->context = NULL;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (client->input_lock == cmd)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen client->input_lock = NULL;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen return FALSE;
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenbool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen enum imap_sync_flags imap_flags, const char *tagline)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return cmd_sync_full(cmd, flags, imap_flags, tagline, NULL);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenbool cmd_sync_callback(struct client_command_context *cmd,
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen enum mailbox_sync_flags flags,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen enum imap_sync_flags imap_flags,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen imap_sync_callback_t *callback)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return cmd_sync_full(cmd, flags, imap_flags, NULL, callback);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen}
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenstatic bool cmd_sync_drop_fast(struct client *client)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct client_command_context *cmd, *prev;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen bool ret = FALSE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (client->command_queue == NULL)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return FALSE;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen for (cmd = client->command_queue; cmd->next != NULL; cmd = cmd->next) ;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen for (; cmd != NULL; cmd = prev) {
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen prev = cmd->next;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen if (cmd->state != CLIENT_COMMAND_STATE_WAIT_SYNC)
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen continue;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen i_assert(cmd->sync != NULL);
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (cmd_finish_sync(cmd)) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen client_command_free(&cmd);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ret = TRUE;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return ret;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen}
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenstatic bool cmd_sync_delayed_real(struct client *client)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct client_command_context *cmd, *first_expunge, *first_nonexpunge;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (client->output_cmd_lock != NULL) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen /* wait until we can send output to client */
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen return FALSE;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (!imap_sync_is_allowed(client)) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen /* wait until mailbox can be synced */
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen return cmd_sync_drop_fast(client);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* separate syncs that can send expunges from those that can't */
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen first_expunge = first_nonexpunge = NULL;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen if (cmd->sync != NULL &&
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen cmd->sync->counter == client->sync_counter) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) {
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (first_nonexpunge == NULL)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen first_nonexpunge = cmd;
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen } else {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (first_expunge == NULL)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen first_expunge = cmd;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen if (first_expunge != NULL && first_nonexpunge != NULL) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* sync expunges after nonexpunges */
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen for (cmd = first_expunge; cmd != NULL; cmd = cmd->next) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (cmd->sync != NULL &&
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen cmd->sync->counter == client->sync_counter &&
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen (cmd->sync->flags &
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0)
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen cmd->sync->counter++;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen }
34d2ee1fa2b299267fcefd378f80690e7f601dfbTimo Sirainen first_expunge = NULL;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen cmd = first_nonexpunge != NULL ? first_nonexpunge : first_expunge;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if (cmd == NULL)
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen return cmd_sync_drop_fast(client);
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen i_assert(client->mailbox != NULL);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return cmd_sync_client(cmd);
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen}
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainenbool cmd_sync_delayed(struct client *client)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen{
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen bool ret;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen T_BEGIN {
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen ret = cmd_sync_delayed_real(client);
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen } T_END;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen return ret;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen}
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen