imap-sync.c revision a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "common.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "str.h"
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen#include "ostream.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "mail-storage.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include "imap-util.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "imap-sync.h"
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen#include "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;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen uint32_t seq;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo 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
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
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
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen client_send_mailbox_flags(client, FALSE);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return ctx;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenint imap_sync_deinit(struct imap_sync_context *ctx)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen{
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen struct mailbox_status status;
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen int ret;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_free(&ctx->mail);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen if (mailbox_sync_deinit(&ctx->sync_ctx, STATUS_UIDVALIDITY |
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen STATUS_MESSAGES | STATUS_RECENT, &status) < 0 ||
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen ctx->failed) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mailbox_transaction_rollback(&ctx->t);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_free(ctx);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen return -1;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
63f36c2b47217fc2dc4ed49cfc1907311d5ed366Timo Sirainen ret = mailbox_transaction_commit(&ctx->t);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen if (status.uidvalidity != ctx->client->uidvalidity) {
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen /* most clients would get confused by this. disconnect them. */
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen client_disconnect_with_error(ctx->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");
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen ctx->client->messages_count = status.messages;
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen if (status.messages != ctx->messages_count) {
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen client_send_line(ctx->client,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen t_strdup_printf("* %u EXISTS", status.messages));
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen }
17b03c9db961e1c004284907d969eb11b08a795eTimo Sirainen if (status.recent != ctx->client->recent_count &&
17b03c9db961e1c004284907d969eb11b08a795eTimo Sirainen !ctx->no_newmail) {
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen ctx->client->recent_count = status.recent;
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen client_send_line(ctx->client,
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen t_strdup_printf("* %u RECENT", status.recent));
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen array_free(&ctx->tmp_keywords);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_free(ctx);
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen return ret;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo 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) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen str_printfa(str, "MODSEQ %llu ",
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen (unsigned long long)mail_get_modseq(ctx->mail));
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);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen str_printfa(str, "MODSEQ %llu)",
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen (unsigned long long)mail_get_modseq(ctx->mail));
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return client_send_line(ctx->client, str_c(str));
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen}
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo 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
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
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++) {
88286b0527bcc0711e312e9db65ca121a45213e3Timo 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:
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--) {
88286b0527bcc0711e312e9db65ca121a45213e3Timo 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++) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo 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 }
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen if (ret <= 0) {
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen /* failure / buffer full */
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen break;
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen }
88286b0527bcc0711e312e9db65ca121a45213e3Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen ctx->seq = 0;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
68efcccb384f2d6871164b072457e87473502c51Timo Sirainen return ret;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo 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{
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct client_command_context *cmd;
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;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (imap_sync_deinit(ctx) < 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
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* finish all commands that waited for this sync */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
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))
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo 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 }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (fast_count != count)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen *flags_r &= ~MAILBOX_SYNC_FLAG_FAST;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (noexpunges_count != count)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen *flags_r &= ~MAILBOX_SYNC_FLAG_NO_EXPUNGES;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen i_assert((*flags_r & (MAILBOX_SYNC_AUTO_STOP |
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen 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
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen no_newmail = (client_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
c96eb61168670cfdd7596baba18856d3f086a093Timo 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{
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct client_command_context *cmd, *next;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen bool ret = FALSE;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = next) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen next = cmd->next;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC &&
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen (cmd->sync->flags & MAILBOX_SYNC_FLAG_FAST) != 0) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (cmd_finish_sync(cmd)) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen client_command_free(cmd);
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen ret = TRUE;
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return ret;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen}
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainenbool cmd_sync_delayed(struct client *client)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen{
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen struct client_command_context *cmd;
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
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (client->syncing ||
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen (client->mailbox != NULL &&
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen mailbox_transaction_get_count(client->mailbox) > 0)) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* wait until mailbox can be synced */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen return cmd_sync_drop_fast(client);
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen /* find a command that we can sync */
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen for (cmd = client->command_queue; cmd != NULL; cmd = cmd->next) {
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen if (cmd->state == CLIENT_COMMAND_STATE_WAIT_SYNC) {
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (cmd->sync->counter == client->sync_counter)
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen break;
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen }
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}