imap-sync.c revision 35283613d4c04ce18836e9fc431582c87b3710a0
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "imap-common.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "str.h"
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen#include "ostream.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "mail-storage.h"
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen#include "mail-user.h"
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen#include "imap-quote.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include "imap-util.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "imap-sync.h"
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "imap-commands.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenstruct client_sync_context {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen /* if multiple commands are in progress, we may need to wait for them
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen to finish before syncing mailbox. */
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen unsigned int counter;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen enum mailbox_sync_flags flags;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen enum imap_sync_flags imap_flags;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen const char *tagline;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen imap_sync_callback_t *callback;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen};
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenstruct imap_sync_context {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct client *client;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct mailbox *box;
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen enum imap_sync_flags imap_flags;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct mailbox_transaction_context *t;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct mailbox_sync_context *sync_ctx;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct mail *mail;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct mailbox_sync_rec sync_rec;
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen ARRAY_TYPE(keywords) tmp_keywords;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ARRAY_TYPE(seq_range) expunges;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen uint32_t seq;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ARRAY_TYPE(seq_range) search_adds, search_removes;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen unsigned int messages_count;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen unsigned int failed:1;
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen unsigned int no_newmail:1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen};
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic void uids_to_seqs(struct mailbox *box, ARRAY_TYPE(seq_range) *uids)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen{
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen T_BEGIN {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ARRAY_TYPE(seq_range) seqs;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen const struct seq_range *range;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen uint32_t seq1, seq2;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen t_array_init(&seqs, array_count(uids));
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_foreach(uids, range) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen mailbox_get_seq_range(box, range->seq1, range->seq2,
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen &seq1, &seq2);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* since we have to notify about expunged messages,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen we expect that all the referenced UIDs exist */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen i_assert(seq1 != 0);
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen i_assert(seq2 - seq1 == range->seq2 - range->seq1);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen seq_range_array_add_range(&seqs, seq1, seq2);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* replace uids with seqs */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen array_clear(uids);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen array_append_array(uids, &seqs);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen } T_END;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic void
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenimap_sync_send_search_update(struct imap_sync_context *ctx,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen const struct imap_search_update *update)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen{
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen string_t *cmd;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen mailbox_search_result_sync(update->result, &ctx->search_removes,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen &ctx->search_adds);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (array_count(&ctx->search_adds) == 0 &&
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen array_count(&ctx->search_removes) == 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen cmd = t_str_new(256);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen str_append(cmd, "* ESEARCH (TAG ");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen imap_quote_append_string(cmd, update->tag, FALSE);
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen str_append_c(cmd, ')');
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (update->return_uids)
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen str_append(cmd, " UID");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen else {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* convert to sequences */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen uids_to_seqs(ctx->client->mailbox, &ctx->search_removes);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen uids_to_seqs(ctx->client->mailbox, &ctx->search_adds);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (array_count(&ctx->search_removes) != 0) {
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen str_printfa(cmd, " REMOVEFROM (0 ");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen imap_write_seq_range(cmd, &ctx->search_removes);
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen str_append_c(cmd, ')');
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (array_count(&ctx->search_adds) != 0) {
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen str_printfa(cmd, " ADDTO (0 ");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen imap_write_seq_range(cmd, &ctx->search_adds);
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen str_append_c(cmd, ')');
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
f2bd9e507b8befdd95a983f86664febf5c19bd95Timo Sirainen str_append(cmd, "\r\n");
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen o_stream_send(ctx->client->output, str_data(cmd), str_len(cmd));
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic void imap_sync_send_search_updates(struct imap_sync_context *ctx)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen{
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen const struct imap_search_update *update;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!array_is_created(&ctx->client->search_updates))
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!array_is_created(&ctx->search_removes)) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen i_array_init(&ctx->search_removes, 64);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen i_array_init(&ctx->search_adds, 128);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_foreach(&ctx->client->search_updates, update) T_BEGIN {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen imap_sync_send_search_update(ctx, update);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen } T_END;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenstruct imap_sync_context *
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenimap_sync_init(struct client *client, struct mailbox *box,
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen struct imap_sync_context *ctx;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_assert(client->mailbox == box);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx = i_new(struct imap_sync_context, 1);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->client = client;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->box = box;
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen ctx->imap_flags = imap_flags;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen /* make sure user can't DoS the system by causing Dovecot to create
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen tons of useless namespaces. */
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen mail_user_drop_useless_namespaces(client->user);
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->sync_ctx = mailbox_sync_init(box, flags);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->t = mailbox_transaction_begin(box, 0);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen ctx->mail = mail_alloc(ctx->t, MAIL_FETCH_FLAGS, 0);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->messages_count = client->messages_count;
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen i_array_init(&ctx->tmp_keywords, client->keywords.announce_count + 8);
bc3698b8892df8003b410daea6f5bbcd20433808Timo Sirainen
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen i_array_init(&ctx->expunges, 128);
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen /* always send UIDs in FETCH replies */
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen ctx->imap_flags |= IMAP_SYNC_FLAG_SEND_UID;
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen client_send_mailbox_flags(client, FALSE);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* send search updates the first time after sync is initialized.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen it now contains expunged messages that must be sent before
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen EXPUNGE replies. */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen imap_sync_send_search_updates(ctx);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return ctx;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenstatic void
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenimap_sync_send_highestmodseq(struct imap_sync_context *ctx,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen const struct mailbox_status *status,
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen const struct mailbox_sync_status *sync_status,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen struct client_command_context *sync_cmd)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen{
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen struct client *client = ctx->client;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen uint64_t send_modseq = 0;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen if (sync_status->sync_delayed_expunges &&
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen client->highest_fetch_modseq > client->sync_last_full_modseq) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* if client updates highest-modseq using returned MODSEQs
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen it loses expunges. try to avoid this by sending it a lower
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen pre-expunge HIGHESTMODSEQ reply. */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen send_modseq = client->sync_last_full_modseq;
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen } else if (!sync_status->sync_delayed_expunges &&
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen status->highest_modseq > client->sync_last_full_modseq &&
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen status->highest_modseq > client->highest_fetch_modseq) {
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen /* we've probably sent some VANISHED or EXISTS replies which
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen increased the highest-modseq. notify the client about
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen this. */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen send_modseq = status->highest_modseq;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (send_modseq == 0) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* no sending */
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen } else if (sync_cmd->sync != NULL && /* IDLE doesn't have ->sync */
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen strncmp(sync_cmd->sync->tagline, "OK ", 3) == 0 &&
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen sync_cmd->sync->tagline[3] != '[') {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* modify the tagged reply directly */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen sync_cmd->sync->tagline = p_strdup_printf(sync_cmd->pool,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen "OK [HIGHESTMODSEQ %llu] %s",
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen (unsigned long long)send_modseq,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen sync_cmd->sync->tagline + 3);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen } else {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* send an untagged OK reply */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen client_send_line(client, t_strdup_printf(
2d9644d34a78b24dc7769cd96497e700a0fb1cf1Timo Sirainen "* OK [HIGHESTMODSEQ %llu] Highest",
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen (unsigned long long)send_modseq));
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen if (!sync_status->sync_delayed_expunges) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* no delayed expunges, remember this for future */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen client->sync_last_full_modseq = status->highest_modseq;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen client->highest_fetch_modseq = 0;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen}
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenint imap_sync_deinit(struct imap_sync_context *ctx,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen struct client_command_context *sync_cmd)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen{
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen struct client *client = ctx->client;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen struct mailbox_status status;
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen struct mailbox_sync_status sync_status;
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen int ret;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_free(&ctx->mail);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (array_is_created(&ctx->expunges))
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen array_free(&ctx->expunges);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen if (mailbox_sync_deinit(&ctx->sync_ctx, &sync_status) < 0 ||
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen ctx->failed) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mailbox_transaction_rollback(&ctx->t);
f5a24412980cb19b07cb0cd12dba75886f281875Timo Sirainen array_free(&ctx->tmp_keywords);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_free(ctx);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return -1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mailbox_get_open_status(ctx->box, STATUS_UIDVALIDITY |
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen STATUS_MESSAGES | STATUS_RECENT |
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen STATUS_HIGHESTMODSEQ, &status);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
63f36c2b47217fc2dc4ed49cfc1907311d5ed366Timo Sirainen ret = mailbox_transaction_commit(&ctx->t);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen if (status.uidvalidity != client->uidvalidity) {
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen /* most clients would get confused by this. disconnect them. */
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen client_disconnect_with_error(client,
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen "Mailbox UIDVALIDITY changed");
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen }
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen if (!ctx->no_newmail) {
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen if (status.messages < ctx->messages_count)
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen i_panic("Message count decreased");
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen client->messages_count = status.messages;
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen if (status.messages != ctx->messages_count) {
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen client_send_line(client,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen t_strdup_printf("* %u EXISTS", status.messages));
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen }
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen if (status.recent != client->recent_count &&
17b03c9db961e1c004284907d969eb11b08a795eTimo Sirainen !ctx->no_newmail) {
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen client->recent_count = status.recent;
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen client_send_line(client,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen t_strdup_printf("* %u RECENT", status.recent));
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* send search updates the second time after syncing in done.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen now it contains added/removed messages. */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen imap_sync_send_search_updates(ctx);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen imap_sync_send_highestmodseq(ctx, &status, &sync_status,
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen sync_cmd);
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (array_is_created(&ctx->search_removes)) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen array_free(&ctx->search_removes);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen array_free(&ctx->search_adds);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen array_free(&ctx->tmp_keywords);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_free(ctx);
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen return ret;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenstatic void imap_sync_add_modseq(struct imap_sync_context *ctx, string_t *str)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen{
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen uint64_t modseq;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen modseq = mail_get_modseq(ctx->mail);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (ctx->client->highest_fetch_modseq < modseq)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen ctx->client->highest_fetch_modseq = modseq;
6384258c2f84e635d8ceffc3eeddad71f7538040Timo Sirainen str_printfa(str, "MODSEQ (%llu)", (unsigned long long)modseq);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen}
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainenstatic int imap_sync_send_flags(struct imap_sync_context *ctx, string_t *str)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen enum mail_flags flags;
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen const char *const *keywords;
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen mail_set_seq(ctx->mail, ctx->seq);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen flags = mail_get_flags(ctx->mail);
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen mail_get_keyword_indexes(ctx->mail));
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if ((flags & MAIL_DELETED) != 0)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ctx->client->sync_seen_deletes = TRUE;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen str_truncate(str, 0);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen str_printfa(str, "* %u FETCH (", ctx->seq);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen str_printfa(str, "UID %u ", ctx->mail->uid);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if ((mailbox_get_enabled_features(ctx->box) &
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen MAILBOX_FEATURE_CONDSTORE) != 0) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen imap_sync_add_modseq(ctx, str);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen str_append_c(str, ' ');
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen }
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen str_append(str, "FLAGS (");
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen imap_write_flags(str, flags, keywords);
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen str_append(str, "))");
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen return client_send_line(ctx->client, str_c(str));
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen}
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainenstatic int imap_sync_send_modseq(struct imap_sync_context *ctx, string_t *str)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen{
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen mail_set_seq(ctx->mail, ctx->seq);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen str_truncate(str, 0);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen str_printfa(str, "* %u FETCH (", ctx->seq);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen str_printfa(str, "UID %u ", ctx->mail->uid);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen imap_sync_add_modseq(ctx, str);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen str_append_c(str, ')');
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return client_send_line(ctx->client, str_c(str));
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen}
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenstatic void imap_sync_vanished(struct imap_sync_context *ctx)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen{
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen const struct seq_range *seqs;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen unsigned int i, count;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen string_t *line;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen uint32_t seq, prev_uid, start_uid;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen bool comma = FALSE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* Convert expunge sequences to UIDs and send them in VANISHED line. */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen seqs = array_get(&ctx->expunges, &count);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (count == 0)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen line = t_str_new(256);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_append(line, "* VANISHED ");
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen for (i = 0; i < count; i++) {
c8625391da3ee51b31e69b88895708a3d149dd1bTimo Sirainen start_uid = 0; prev_uid = (uint32_t)-1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen for (seq = seqs[i].seq1; seq <= seqs[i].seq2; seq++) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail_set_seq(ctx->mail, seq);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (prev_uid + 1 != ctx->mail->uid) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (start_uid != 0) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (!comma)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen comma = TRUE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen else
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_append_c(line, ',');
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_printfa(line, "%u", start_uid);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (start_uid != prev_uid) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_printfa(line, ":%u",
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen prev_uid);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen start_uid = ctx->mail->uid;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen prev_uid = ctx->mail->uid;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (!comma)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen comma = TRUE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen else
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_append_c(line, ',');
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_printfa(line, "%u", start_uid);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (start_uid != prev_uid)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_printfa(line, ":%u", prev_uid);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen str_append(line, "\r\n");
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen o_stream_send(ctx->client->output, str_data(line), str_len(line));
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen}
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainenint imap_sync_more(struct imap_sync_context *ctx)
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainen{
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen string_t *str;
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen int ret = 1;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen /* finish syncing even when client has disconnected. otherwise our
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen internal state (ctx->messages_count) can get messed up and unless
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen we immediately stop handling all commands and syncs we could end up
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen assert-crashing. */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen str = t_str_new(256);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (;;) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (ctx->seq == 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* get next one */
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen if (!mailbox_sync_next(ctx->sync_ctx, &ctx->sync_rec)) {
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen /* finished */
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen ret = 1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen break;
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen if (ctx->sync_rec.seq2 > ctx->messages_count) {
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen /* don't send change notifications of messages we
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen haven't even announced to client yet */
10cfe8a2bdc5ccfc05380689c71c27209327538fTimo Sirainen if (ctx->sync_rec.seq1 > ctx->messages_count) {
10cfe8a2bdc5ccfc05380689c71c27209327538fTimo Sirainen ctx->seq = 0;
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen continue;
10cfe8a2bdc5ccfc05380689c71c27209327538fTimo Sirainen }
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen ctx->sync_rec.seq2 = ctx->messages_count;
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen }
a54be2bd26d6f0860d194d3aeedfa6b7fc14d24cTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* EXPUNGEs must come last */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen i_assert(!array_is_created(&ctx->expunges) ||
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen array_count(&ctx->expunges) == 0 ||
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ctx->sync_rec.type == MAILBOX_SYNC_TYPE_EXPUNGE);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen switch (ctx->sync_rec.type) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen case MAILBOX_SYNC_TYPE_FLAGS:
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (ctx->seq == 0)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->seq = ctx->sync_rec.seq1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen ret = 1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen if (ret == 0)
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen break;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen ret = imap_sync_send_flags(ctx, str);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen break;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen case MAILBOX_SYNC_TYPE_EXPUNGE:
e30e068c8fac372ae217b3b31791a0c8c8046b7fTimo Sirainen ctx->client->sync_seen_expunges = TRUE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (array_is_created(&ctx->expunges)) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* Use a single VANISHED line */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen seq_range_array_add_range(&ctx->expunges,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ctx->sync_rec.seq1,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ctx->sync_rec.seq2);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ctx->messages_count -=
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ctx->sync_rec.seq2 -
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ctx->sync_rec.seq1 + 1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen break;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen if (ctx->seq == 0)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->seq = ctx->sync_rec.seq2;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen ret = 1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (; ctx->seq >= ctx->sync_rec.seq1; ctx->seq--) {
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen if (ret == 0)
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen break;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen str_truncate(str, 0);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen str_printfa(str, "* %u EXPUNGE", ctx->seq);
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen ret = client_send_line(ctx->client, str_c(str));
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen if (ctx->seq < ctx->sync_rec.seq1) {
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen /* update only after we're finished, so that
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen the seq2 > messages_count check above
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen doesn't break */
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen ctx->messages_count -=
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen ctx->sync_rec.seq2 -
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen ctx->sync_rec.seq1 + 1;
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen break;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen case MAILBOX_SYNC_TYPE_MODSEQ:
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if ((ctx->client->enabled_features &
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen MAILBOX_FEATURE_CONDSTORE) == 0)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen break;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if (ctx->seq == 0)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen ctx->seq = ctx->sync_rec.seq1;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen ret = 1;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen if (ret == 0)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen break;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen ret = imap_sync_send_modseq(ctx, str);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen }
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen break;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen if (ret == 0) {
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen /* buffer full */
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen break;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen }
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->seq = 0;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (array_is_created(&ctx->expunges))
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen imap_sync_vanished(ctx);
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen return ret;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainenbool imap_sync_is_allowed(struct client *client)
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen{
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen if (client->syncing)
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen return FALSE;
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen if (client->mailbox != NULL &&
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen mailbox_transaction_get_count(client->mailbox) > 0)
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen return FALSE;
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen return TRUE;
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen}
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenstatic bool cmd_finish_sync(struct client_command_context *cmd)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen{
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (cmd->sync->callback != NULL)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return cmd->sync->callback(cmd);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen else {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen client_send_tagline(cmd, cmd->sync->tagline);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return TRUE;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen }
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen}
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic bool cmd_sync_continue(struct client_command_context *sync_cmd)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen struct client_command_context *cmd, *prev;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct client *client = sync_cmd->client;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct imap_sync_context *ctx = sync_cmd->context;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen int ret;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen i_assert(ctx->client == client);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if ((ret = imap_sync_more(ctx)) == 0)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return FALSE;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen if (ret < 0)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->failed = TRUE;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen client->syncing = FALSE;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (imap_sync_deinit(ctx, sync_cmd) < 0) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen client_send_untagged_storage_error(client,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen mailbox_get_storage(client->mailbox));
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen sync_cmd->context = NULL;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen /* Finish all commands that waited for this sync. Go through the queue
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen backwards, so that tagged replies are sent in the same order as
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen they were received. This fixes problems with clients that rely on
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen this (Apple Mail 3.2) */
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen for (cmd = client->command_queue; cmd->next != NULL; cmd = cmd->next) ;
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen for (; cmd != NULL; cmd = prev) {
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen prev = cmd->prev;
3419b088ffe531799bdb47b3ff3fce85c8b7569aTimo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC &&
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen cmd != sync_cmd &&
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->counter+1 == client->sync_counter) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (cmd_finish_sync(cmd))
2d340205d897e23fbecb40c8e63a4ca49bd6739bTimo Sirainen client_command_free(&cmd);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return cmd_finish_sync(sync_cmd);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic void get_common_sync_flags(struct client *client,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen enum mailbox_sync_flags *flags_r,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen enum imap_sync_flags *imap_flags_r)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen{
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct client_command_context *cmd;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen unsigned int count = 0, fast_count = 0, noexpunges_count = 0;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen *flags_r = 0;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen *imap_flags_r = 0;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (cmd->sync != NULL &&
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->counter == client->sync_counter) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen fast_count++;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen noexpunges_count++;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen *flags_r |= cmd->sync->flags;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen *imap_flags_r |= cmd->sync->imap_flags;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen count++;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen i_assert(noexpunges_count == 0 || noexpunges_count == count);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (fast_count != count)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen *flags_r &= ~MAILBOX_SYNC_FLAG_FAST;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
2372e16bfae0a245bfde6e908cde0919aa11ee0bTimo Sirainen i_assert((*flags_r & MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) == 0);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen}
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic bool cmd_sync_client(struct client_command_context *sync_cmd)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen{
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct client *client = sync_cmd->client;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct imap_sync_context *ctx;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen enum mailbox_sync_flags flags;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen enum imap_sync_flags imap_flags;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen bool no_newmail;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* there may be multiple commands waiting. use their combined flags */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen get_common_sync_flags(client, &flags, &imap_flags);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen client->sync_counter++;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
a8284e999d091cd29210fa75ecdc8076376a7345Timo Sirainen no_newmail = (client->set->parsed_workarounds & WORKAROUND_DELAY_NEWMAIL) != 0 &&
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen (imap_flags & IMAP_SYNC_FLAG_SAFE) == 0;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (no_newmail) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* expunges might break the client just as badly as new mail
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen notifications. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen flags |= MAILBOX_SYNC_FLAG_NO_EXPUNGES;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen client->syncing = TRUE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx = imap_sync_init(client, client->mailbox, imap_flags, flags);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx->no_newmail = no_newmail;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* handle the syncing using sync_cmd. it doesn't actually matter which
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen one of the pending commands it is. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen sync_cmd->func = cmd_sync_continue;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen sync_cmd->context = ctx;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen sync_cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (!cmd_sync_continue(sync_cmd)) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return FALSE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
2d340205d897e23fbecb40c8e63a4ca49bd6739bTimo Sirainen client_command_free(&sync_cmd);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen (void)cmd_sync_delayed(client);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return TRUE;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenstatic bool
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainencmd_sync_full(struct client_command_context *cmd, enum mailbox_sync_flags flags,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen enum imap_sync_flags imap_flags, const char *tagline,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen imap_sync_callback_t *callback)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen{
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen struct client *client = cmd->client;
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen i_assert(client->output_lock == cmd || client->output_lock == NULL);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (cmd->cancel)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return TRUE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (client->mailbox == NULL) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* no mailbox selected, no point in delaying the sync */
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen i_assert(callback == NULL);
e60a349c641bb2f4723e4a395a25f55531682d2bTimo Sirainen client_send_tagline(cmd, tagline);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return TRUE;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync = p_new(cmd->pool, struct client_sync_context, 1);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->counter = client->sync_counter;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->flags = flags;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->imap_flags = imap_flags;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->tagline = p_strdup(cmd->pool, tagline);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->callback = callback;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen cmd->state = CLIENT_COMMAND_STATE_WAIT_SYNC;
294f1a51763015cda0e2d874c5027d6fe7a2cd54Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen cmd->func = NULL;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen cmd->context = NULL;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen client->output_lock = NULL;
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen if (client->input_lock == cmd)
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen client->input_lock = NULL;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return FALSE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen}
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenbool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen enum imap_sync_flags imap_flags, const char *tagline)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen{
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return cmd_sync_full(cmd, flags, imap_flags, tagline, NULL);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen}
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenbool cmd_sync_callback(struct client_command_context *cmd,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen enum mailbox_sync_flags flags,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen enum imap_sync_flags imap_flags,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen imap_sync_callback_t *callback)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen{
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen return cmd_sync_full(cmd, flags, imap_flags, NULL, callback);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen}
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic bool cmd_sync_drop_fast(struct client *client)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen{
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen struct client_command_context *cmd, *prev;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen bool ret = FALSE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen if (client->command_queue == NULL)
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen return FALSE;
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen for (cmd = client->command_queue; cmd->next != NULL; cmd = cmd->next) ;
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen for (; cmd != NULL; cmd = prev) {
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen prev = cmd->next;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen if (cmd->state != CLIENT_COMMAND_STATE_WAIT_SYNC)
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen continue;
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen i_assert(cmd->sync != NULL);
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (cmd_finish_sync(cmd)) {
2d340205d897e23fbecb40c8e63a4ca49bd6739bTimo Sirainen client_command_free(&cmd);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ret = TRUE;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return ret;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen}
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainenstatic bool cmd_sync_delayed_real(struct client *client)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen{
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen struct client_command_context *cmd, *first_expunge, *first_nonexpunge;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (client->output_lock != NULL) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* wait until we can send output to client */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return FALSE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen if (!imap_sync_is_allowed(client)) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* wait until mailbox can be synced */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return cmd_sync_drop_fast(client);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen /* separate syncs that can send expunges from those that can't */
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen first_expunge = first_nonexpunge = NULL;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (cmd->sync != NULL &&
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen cmd->sync->counter == client->sync_counter) {
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) {
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (first_nonexpunge == NULL)
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen first_nonexpunge = cmd;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen } else {
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (first_expunge == NULL)
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen first_expunge = cmd;
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (first_expunge != NULL && first_nonexpunge != NULL) {
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen /* sync expunges after nonexpunges */
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen for (cmd = first_expunge; cmd != NULL; cmd = cmd->next) {
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen if (cmd->sync != NULL &&
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen cmd->sync->counter == client->sync_counter &&
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen (cmd->sync->flags &
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen MAILBOX_SYNC_FLAG_NO_EXPUNGES) == 0)
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen cmd->sync->counter++;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen first_expunge = NULL;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen cmd = first_nonexpunge != NULL ? first_nonexpunge : first_expunge;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (cmd == NULL)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return cmd_sync_drop_fast(client);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen i_assert(client->mailbox != NULL);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return cmd_sync_client(cmd);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen}
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainenbool cmd_sync_delayed(struct client *client)
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen{
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen bool ret;
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen T_BEGIN {
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen ret = cmd_sync_delayed_real(client);
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen } T_END;
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen return ret;
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainen}