imap-sync.c revision ba5c8b0ae7460752adaf911901bf263788f62c72
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2014 Dovecot authors, see the included COPYING file */
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;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(seq_range) search_adds, search_removes;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainenstatic void uids_to_seqs(struct mailbox *box, ARRAY_TYPE(seq_range) *uids)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen mailbox_get_seq_range(box, range->seq1, range->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(seq2 - seq1 == range->seq2 - range->seq1);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen /* replace uids with seqs */
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainenstatic int search_update_fetch_more(const struct imap_search_update *update)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if ((ret = imap_fetch_more_no_lock_update(update->fetch_ctx)) <= 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen /* finished the FETCH */
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainenimap_sync_send_fetch_to_search_update(struct imap_sync_context *ctx,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (array_count(&ctx->search_adds) == 0 || !ctx->have_new_mails)
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 /* 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 seq_range_array_add_range(&seqs, ctx->messages_count+1,
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 imap_fetch_begin(update->fetch_ctx, ctx->client->mailbox, search_args);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenimap_sync_send_search_update(struct imap_sync_context *ctx,
2e937ed8585299b2e879a28314902a5f644813d2Timo Sirainen mailbox_search_result_sync(update->result, &ctx->search_removes,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen i_assert(array_count(&ctx->search_adds) == 0 || !removes_only);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ret = imap_sync_send_fetch_to_search_update(ctx, update);
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);
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen imap_write_seq_range(cmd, &ctx->search_removes);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen o_stream_nsend(ctx->client->output, str_data(cmd), str_len(cmd));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenimap_sync_send_search_updates(struct imap_sync_context *ctx, bool removes_only)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen unsigned int i, count;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!array_is_created(&ctx->client->search_updates))
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (!array_is_created(&ctx->search_removes)) {
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen updates = array_get(&ctx->client->search_updates, &count);
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen for (i = ctx->search_update_idx; i < count; i++) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ret = imap_sync_send_search_update(ctx, &updates[i],
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainenimap_sync_init(struct client *client, struct mailbox *box,
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen enum imap_sync_flags imap_flags, enum mailbox_sync_flags flags)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* NOTIFY enabled without SELECTED-DELAYED */
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 ctx->sync_ctx = mailbox_sync_init(box, flags);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ctx->mail = mail_alloc(ctx->t, MAIL_FETCH_FLAGS, NULL);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen i_array_init(&ctx->tmp_keywords, client->keywords.announce_count + 8);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if ((client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen /* always send UIDs in FETCH replies */
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)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainenimap_sync_send_highestmodseq(struct imap_sync_context *ctx,
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. */
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
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 &&
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,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* send an untagged OK reply */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen "* OK [HIGHESTMODSEQ %llu] Highest",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen (unsigned long long)send_modseq));
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;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenstatic int imap_sync_finish(struct imap_sync_context *ctx, bool aborting)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* the transaction is used only for fetching modseqs/flags.
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen it can't really fail.. */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (mailbox_sync_deinit(&ctx->sync_ctx, &ctx->sync_status) < 0 ||
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mailbox_get_open_status(ctx->box, STATUS_UIDVALIDITY |
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.uidvalidity != client->uidvalidity) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* most clients would get confused by this. disconnect them. */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen "Mailbox UIDVALIDITY changed");
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.messages < ctx->messages_count)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.messages != ctx->messages_count &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen t_strdup_printf("* %u EXISTS", ctx->status.messages));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->status.recent != client->recent_count &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen t_strdup_printf("* %u RECENT", ctx->status.recent));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen client->messages_count = ctx->status.messages;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int imap_sync_notify_more(struct imap_sync_context *ctx)
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 /* 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 Sirainenint imap_sync_deinit(struct imap_sync_context *ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if ((ctx->client->enabled_features & MAILBOX_FEATURE_QRESYNC) != 0 &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic void imap_sync_add_modseq(struct imap_sync_context *ctx, string_t *str)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->client->highest_fetch_modseq < modseq)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen str_printfa(str, "MODSEQ (%llu)", (unsigned long long)modseq);
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainenstatic int imap_sync_send_flags(struct imap_sync_context *ctx, string_t *str)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const char *const *keywords;
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen keywords = client_get_keyword_names(ctx->client, &ctx->tmp_keywords,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen return client_send_line_next(ctx->client, str_c(str));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int imap_sync_send_modseq(struct imap_sync_context *ctx, string_t *str)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ctx->imap_flags & IMAP_SYNC_FLAG_SEND_UID)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return client_send_line_next(ctx->client, str_c(str));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic void imap_sync_vanished(struct imap_sync_context *ctx)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen unsigned int i, count;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* Convert expunge sequences to UIDs and send them in VANISHED line. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (i = 0; i < count; i++) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (seq = seqs[i].seq1; seq <= seqs[i].seq2; seq++) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen o_stream_nsend(ctx->client->output, str_data(line), str_len(line));
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int imap_sync_send_expunges(struct imap_sync_context *ctx, string_t *str)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* NOTIFY: MessageEvent not specified for selected mailbox */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* Use a single VANISHED line */
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen for (; ctx->seq >= ctx->sync_rec.seq1; ctx->seq--) {
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen /* buffer full, continue later */
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen ret = client_send_line_next(ctx->client, str_c(str));
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenint imap_sync_more(struct imap_sync_context *ctx)
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 /* get next one */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (!mailbox_sync_next(ctx->sync_ctx, &ctx->sync_rec)) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* finished */
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) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen /* EXPUNGEs must come last */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ctx->sync_rec.type == MAILBOX_SYNC_TYPE_EXPUNGE);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* NOTIFY: FlagChange not specified for
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen selected mailbox */
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen /* update only after we're finished, so that
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen the seq2 > messages_count check above
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen doesn't break */
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. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen /* buffer full */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenbool imap_sync_is_allowed(struct client *client)
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen mailbox_transaction_get_count(client->mailbox) > 0)
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainenstatic bool cmd_finish_sync(struct client_command_context *cmd)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic bool cmd_sync_continue(struct client_command_context *sync_cmd)
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen struct imap_sync_context *ctx = sync_cmd->context;
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 if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC &&
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen cmd->sync->counter+1 == client->sync_counter) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic void get_common_sync_flags(struct client *client,
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen unsigned int count = 0, fast_count = 0, noexpunges_count = 0;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0)
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(noexpunges_count == 0 || noexpunges_count == count);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen i_assert((*flags_r & MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) == 0);
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainenstatic bool cmd_sync_client(struct client_command_context *sync_cmd)
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen /* there may be multiple commands waiting. use their combined flags */
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen get_common_sync_flags(client, &flags, &imap_flags);
6e4cd4ba520bc22ce375de378f4751136ebcf75aTimo Sirainen no_newmail = (client->set->parsed_workarounds & WORKAROUND_DELAY_NEWMAIL) != 0 &&
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen client->notify_ctx == NULL && /* always disabled with NOTIFY */
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen /* expunges might break the client just as badly as new mail
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen notifications. */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen ctx = imap_sync_init(client, client->mailbox, imap_flags, flags);
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen /* handle the syncing using sync_cmd. it doesn't actually matter which
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen one of the pending commands it is. */
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen sync_cmd->state = CLIENT_COMMAND_STATE_WAIT_OUTPUT;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
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,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen /* no mailbox selected, no point in delaying the sync */
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen cmd->sync = p_new(cmd->pool, struct client_sync_context, 1);
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen cmd->sync->tagline = p_strdup(cmd->pool, tagline);
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)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return cmd_sync_full(cmd, flags, imap_flags, tagline, NULL);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenbool cmd_sync_callback(struct client_command_context *cmd,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return cmd_sync_full(cmd, flags, imap_flags, NULL, callback);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenstatic bool cmd_sync_drop_fast(struct client *client)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen for (cmd = client->command_queue; cmd->next != NULL; cmd = cmd->next) ;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen if (cmd->state != CLIENT_COMMAND_STATE_WAIT_SYNC)
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen if ((cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenstatic bool cmd_sync_delayed_real(struct client *client)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct client_command_context *cmd, *first_expunge, *first_nonexpunge;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen /* wait until we can send output to client */
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen /* wait until mailbox can be synced */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* separate syncs that can send expunges from those that can't */
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (cmd->sync->flags & MAILBOX_SYNC_FLAG_NO_EXPUNGES) {
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) {