imap-sync.c revision 505561860cdfee4eac51469fd27a59983ef72e8e
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
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;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen ARRAY_TYPE(seq_range) search_adds, search_removes;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic void uids_to_seqs(struct mailbox *box, ARRAY_TYPE(seq_range) *uids)
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen mailbox_get_seq_range(box, range->seq1, range->seq2,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* since we have to notify about expunged messages,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen we expect that all the referenced UIDs exist */
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen i_assert(seq2 - seq1 == range->seq2 - range->seq1);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* replace uids with seqs */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int search_update_fetch_more(const struct imap_search_update *update)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((ret = imap_fetch_more_no_lock_update(update->fetch_ctx)) <= 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* finished the FETCH */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenimap_sync_send_fetch_to_search_update(struct imap_sync_context *ctx,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (array_count(&ctx->search_adds) == 0 || !ctx->have_new_mails)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen arg = mail_search_build_add(search_args, SEARCH_UIDSET);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen p_array_init(&arg->value.seqset, search_args->pool, 1);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* find the newly appended messages: ctx->messages_count is the message
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen count before new messages found by sync, client->messages_count is
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen the number of messages after. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen seq_range_array_add_range(&seqs, ctx->messages_count+1,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_get_uid_range(ctx->client->mailbox, &seqs, &arg->value.seqset);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* remove messages not in the search_adds list */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen seq_range_array_intersect(&arg->value.seqset, &ctx->search_adds);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen imap_fetch_begin(update->fetch_ctx, ctx->client->mailbox, search_args);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenimap_sync_send_search_update(struct imap_sync_context *ctx,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mailbox_search_result_sync(update->result, &ctx->search_removes,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen i_assert(array_count(&ctx->search_adds) == 0 || !removes_only);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret = imap_sync_send_fetch_to_search_update(ctx, update);
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 imap_write_seq_range(cmd, &ctx->search_removes);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(ctx->client->output, str_data(cmd), str_len(cmd));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenimap_sync_send_search_updates(struct imap_sync_context *ctx, bool removes_only)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen unsigned int i, count;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!array_is_created(&ctx->client->search_updates))
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!array_is_created(&ctx->search_removes)) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen updates = array_get(&ctx->client->search_updates, &count);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen for (i = ctx->search_update_idx; i < count; i++) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ret = imap_sync_send_search_update(ctx, &updates[i],
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenimap_sync_init(struct client *client, struct mailbox *box,
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* NOTIFY enabled without SELECTED-DELAYED */
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);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->sync_ctx = mailbox_sync_init(box, flags);
ba5c8b0ae7460752adaf911901bf263788f62c72Phil Carmody ctx->mail = mail_alloc(ctx->t, MAIL_FETCH_FLAGS, NULL);
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen i_array_init(&ctx->tmp_keywords, client->keywords.announce_count + 8);
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen /* always send UIDs in FETCH replies */
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. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (imap_sync_send_search_updates(ctx, TRUE) == 0)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenimap_sync_send_highestmodseq(struct imap_sync_context *ctx,
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. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } else if (!ctx->sync_status.sync_delayed_expunges &&
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx->status.highest_modseq > client->sync_last_full_modseq &&
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen ctx->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 /* no sending */
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen } else if (sync_cmd->sync != NULL && /* IDLE doesn't have ->sync */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen sync_cmd->sync->tagline != NULL && /* NOTIFY doesn't have tagline */
07974f50bd55b06fd6d465f2c0e491794786e2faTimo Sirainen strncmp(sync_cmd->sync->tagline, "OK ", 3) == 0 &&
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 /* send an untagged OK reply */
2d9644d34a78b24dc7769cd96497e700a0fb1cf1Timo Sirainen "* OK [HIGHESTMODSEQ %llu] Highest",
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen (unsigned long long)send_modseq));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (!ctx->sync_status.sync_delayed_expunges) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* no delayed expunges, remember this for future */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->sync_last_full_modseq = ctx->status.highest_modseq;
270f00aeab7bede38764291e21a314211b884ab4Timo Sirainenstatic int imap_sync_finish(struct imap_sync_context *ctx, bool aborting)
7891195e3975d554df183670dba1fcecfa0a30c3Timo Sirainen /* the transaction is used only for fetching modseqs/flags.
7891195e3975d554df183670dba1fcecfa0a30c3Timo Sirainen it can't really fail.. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (mailbox_sync_deinit(&ctx->sync_ctx, &ctx->sync_status) < 0 ||
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mailbox_get_open_status(ctx->box, STATUS_UIDVALIDITY |
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx->status.uidvalidity != client->uidvalidity) {
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen /* most clients would get confused by this. disconnect them. */
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen "Mailbox UIDVALIDITY changed");
505561860cdfee4eac51469fd27a59983ef72e8eTimo Sirainen "IMAP session state is inconsistent, please relogin.");
505561860cdfee4eac51469fd27a59983ef72e8eTimo Sirainen /* we can't trust status information anymore, so don't try to
505561860cdfee4eac51469fd27a59983ef72e8eTimo Sirainen sync message counts. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx->status.messages < ctx->messages_count)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx->status.messages != ctx->messages_count &&
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen t_strdup_printf("* %u EXISTS", ctx->status.messages));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx->status.recent != client->recent_count &&
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen t_strdup_printf("* %u RECENT", ctx->status.recent));
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->messages_count = ctx->status.messages;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int imap_sync_notify_more(struct imap_sync_context *ctx)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (ctx->have_new_mails && ctx->client->notify_ctx != NULL) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* send FETCH replies for the new mails */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((ret = imap_client_notify_newmails(ctx->client)) == 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* send search updates the second time after syncing in done.
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen now it contains added/removed messages. */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if ((ret = imap_sync_send_search_updates(ctx, FALSE)) < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenint imap_sync_deinit(struct imap_sync_context *ctx,
59714981ae172b5113be7ca9b8be518b759fc86dTimo Sirainen if ((ctx->client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0 &&
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainenstatic void imap_sync_add_modseq(struct imap_sync_context *ctx, string_t *str)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (ctx->client->highest_fetch_modseq < modseq)
6384258c2f84e635d8ceffc3eeddad71f7538040Timo Sirainen str_printfa(str, "MODSEQ (%llu)", (unsigned long long)modseq);
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainenstatic int imap_sync_send_flags(struct imap_sync_context *ctx, string_t *str)
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen const char *const *keywords;
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID) != 0)
45c763dbebee268eda4a1e8bcc1ff82606b5ed0dTimo Sirainen if ((ctx->client->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0 &&
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen return client_send_line_next(ctx->client, str_c(str));
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainenstatic int imap_sync_send_modseq(struct imap_sync_context *ctx, string_t *str)
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID) != 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen return client_send_line_next(ctx->client, str_c(str));
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenstatic void imap_sync_vanished(struct imap_sync_context *ctx)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen unsigned int i, count;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* Convert expunge sequences to UIDs and send them in VANISHED line. */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen for (i = 0; i < count; i++) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen for (seq = seqs[i].seq1; seq <= seqs[i].seq2; seq++) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(ctx->client->output, str_data(line), str_len(line));
85ee28daca146e18a99a22f46c0d639e57a6ac95Timo Sirainenstatic int imap_sync_send_expunges(struct imap_sync_context *ctx, string_t *str)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* NOTIFY: MessageEvent not specified for selected mailbox */
85ee28daca146e18a99a22f46c0d639e57a6ac95Timo Sirainen /* Use a single VANISHED line */
85ee28daca146e18a99a22f46c0d639e57a6ac95Timo Sirainen for (; ctx->seq >= ctx->sync_rec.seq1; ctx->seq--) {
85ee28daca146e18a99a22f46c0d639e57a6ac95Timo Sirainen /* buffer full, continue later */
85ee28daca146e18a99a22f46c0d639e57a6ac95Timo Sirainen ret = client_send_line_next(ctx->client, str_c(str));
a4bc2c3962b94f83c7bb7bebe7af364f4dee7883Timo Sirainenint imap_sync_more(struct imap_sync_context *ctx)
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. */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen /* get next one */
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen if (!mailbox_sync_next(ctx->sync_ctx, &ctx->sync_rec)) {
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen /* finished */
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) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* EXPUNGEs must come last */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ctx->sync_rec.type == MAILBOX_SYNC_TYPE_EXPUNGE);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* NOTIFY: FlagChange not specified for
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen selected mailbox */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen /* update only after we're finished, so that
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen the seq2 > messages_count check above
d42c9a8f362b76740418c4f9f9441eb7fc661e57Timo Sirainen doesn't break */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* NOTIFY: FlagChange not specified for
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen selected mailbox. The RFC doesn't explicitly
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen specify MODSEQ changes, but they're close
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen enough to flag changes. */
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
0b7651dc6ad21cce8579b5957252ae0daf972668Timo Sirainen /* buffer full */
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainenbool imap_sync_is_allowed(struct client *client)
5735ada0f82788ee1b5228978d5bd8dad5a04219Timo Sirainen mailbox_transaction_get_count(client->mailbox) > 0)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenstatic bool cmd_finish_sync(struct client_command_context *cmd)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic bool cmd_sync_continue(struct client_command_context *sync_cmd)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct imap_sync_context *ctx = sync_cmd->context;
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) ;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC &&
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync->counter+1 == client->sync_counter) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic void get_common_sync_flags(struct client *client,
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen unsigned int count = 0, fast_count = 0, noexpunges_count = 0;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0)
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0)
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen i_assert(noexpunges_count == 0 || noexpunges_count == count);
2372e16bfae0a245bfde6e908cde0919aa11ee0bTimo Sirainen i_assert((*flags_r & MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) == 0);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic bool cmd_sync_client(struct client_command_context *sync_cmd)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* there may be multiple commands waiting. use their combined flags */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen get_common_sync_flags(client, &flags, &imap_flags);
a8284e999d091cd29210fa75ecdc8076376a7345Timo Sirainen no_newmail = (client->set->parsed_workarounds & WORKAROUND_DELAY_NEWMAIL) != 0 &&
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->notify_ctx == NULL && /* always disabled with NOTIFY */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* expunges might break the client just as badly as new mail
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen notifications. */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen ctx = imap_sync_init(client, client->mailbox, imap_flags, flags);
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->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
71caf493c651b8eab5adb170db0237f293928e92Timo Sirainenbool cmd_sync(struct client_command_context *cmd, enum mailbox_sync_flags flags,
71caf493c651b8eab5adb170db0237f293928e92Timo Sirainen enum imap_sync_flags imap_flags, const char *tagline)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* no mailbox selected, no point in delaying the sync */
362db49a9acfb297266cb9a09600689dcffce3ccTimo Sirainen cmd->tagline_reply = p_strdup(cmd->pool, tagline);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen cmd->sync = p_new(cmd->pool, struct client_sync_context, 1);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenstatic bool cmd_sync_drop_fast(struct client *client)
1939d1843ee6c7ca5e5baa3967b0332341440005Timo Sirainen for (cmd = client->command_queue; cmd->next != NULL; cmd = cmd->next) ;
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen if (cmd->state != CLIENT_COMMAND_STATE_WAIT_SYNC)
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0) {
d2470b3dfe91ca07459185384ee25080b42a1636Timo Sirainenstatic bool cmd_sync_delayed_real(struct client *client)
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen struct client_command_context *cmd, *first_expunge, *first_nonexpunge;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* wait until we can send output to client */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* wait until mailbox can be synced */
279b22f320f6139da5c1b0e2a5ead6692e7db947Timo Sirainen /* separate syncs that can send expunges from those that can't */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) != 0) {
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) {