imap-sync.c revision 68efcccb384f2d6871164b072457e87473502c51
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (C) 2002-2004 Timo Sirainen */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "common.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "str.h"
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include "mail-storage.h"
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose#include "imap-util.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "imap-sync.h"
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose#include "commands.h"
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bosestruct cmd_sync_context {
324fb26ba803a999bedc29e93c46c84f27abf5b7Sumit Bose const char *tagline;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct imap_sync_context *sync_ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagherstruct imap_sync_context {
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct client *client;
e65df5b966b27e13283c65f59f99ac44781e0333Simo Sorce struct mailbox *box;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
672f430c2e5d55226261a281bc3fa77311ace5a4Jakub Hrozek struct mailbox_transaction_context *t;
672f430c2e5d55226261a281bc3fa77311ace5a4Jakub Hrozek struct mailbox_sync_context *sync_ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mailbox_sync_rec sync_rec;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t seq;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int messages_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher int failed;
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher};
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagherstruct imap_sync_context *
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březinaimap_sync_init(struct client *client, struct mailbox *box,
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina enum mailbox_sync_flags flags)
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina{
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher struct imap_sync_context *ctx;
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(client->mailbox == box);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx = i_new(struct imap_sync_context, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->client = client;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->box = box;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->sync_ctx = mailbox_sync_init(box, flags);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->t = mailbox_transaction_begin(box, FALSE);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->messages_count = client->messages_count;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint imap_sync_deinit(struct imap_sync_context *ctx)
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce{
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce struct mailbox_status status;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (mailbox_sync_deinit(ctx->sync_ctx, &status) < 0 || ctx->failed) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek mailbox_transaction_rollback(ctx->t);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek i_free(ctx);
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce return -1;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce }
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek mailbox_transaction_commit(ctx->t, 0);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek t_push();
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek ctx->client->messages_count = status.messages;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (status.messages != ctx->messages_count) {
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek client_send_line(ctx->client,
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek t_strdup_printf("* %u EXISTS", status.messages));
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek }
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (status.recent != ctx->client->recent_count) {
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek ctx->client->recent_count = status.recent;
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek client_send_line(ctx->client,
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek t_strdup_printf("* %u RECENT", status.recent));
48130eef6c5c64a07094b9e8582ba358b2048f24Jakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /*FIXME:client_save_keywords(&client->keywords, keywords, keywords_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_send_mailbox_flags(client, mailbox, keywords, keywords_count);*/
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher t_pop();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_free(ctx);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint imap_sync_more(struct imap_sync_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail *mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_flags flags;
d921c1eba437662437847279f251a0a5d8f70127Maxim const char *const *keywords;
d921c1eba437662437847279f251a0a5d8f70127Maxim string_t *str;
d921c1eba437662437847279f251a0a5d8f70127Maxim int ret = 1;
d921c1eba437662437847279f251a0a5d8f70127Maxim
d921c1eba437662437847279f251a0a5d8f70127Maxim t_push();
d921c1eba437662437847279f251a0a5d8f70127Maxim str = t_str_new(256);
d921c1eba437662437847279f251a0a5d8f70127Maxim
327127bb7fcc07f882209f029e14026de1b23c94Maxim for (;;) {
327127bb7fcc07f882209f029e14026de1b23c94Maxim if (ctx->seq == 0) {
327127bb7fcc07f882209f029e14026de1b23c94Maxim /* get next one */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = mailbox_sync_next(ctx->sync_ctx,
d3da1c165cdb4c1ec126a8f4b6b544ca415b9d20Pavel Březina &ctx->sync_rec);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret <= 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* all finished ok */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek }
bc9235cfb80bd64a3bfa959e8d26d5ad1be0bdf4Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher switch (ctx->sync_rec.type) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case MAILBOX_SYNC_TYPE_FLAGS:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case MAILBOX_SYNC_TYPE_KEYWORDS:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ctx->seq == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->seq = ctx->sync_rec.seq1;
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose for (; ctx->seq <= ctx->sync_rec.seq2; ctx->seq++) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail = mailbox_fetch(ctx->t, ctx->seq,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher MAIL_FETCH_FLAGS);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher flags = mail->get_flags(mail);
068dbee9ca7bf5b37330eff91c94ae10f288d09fJakub Hrozek keywords = mail->get_keywords(mail);
98ce3c3e85a4bb2e1822bf8ab2a1c2ab9e3dd61dJakub Hrozek
be65f065fef1d387281096ef095a2acef39ecc12Jakub Hrozek str_truncate(str, 0);
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek str_printfa(str, "* %u FETCH (FLAGS (",
f36078af138f052cd9a30360867b0ebd0805af5eJakub Hrozek ctx->seq);
34c78b745eb349eef2b0f13ef2b722632aebe619Jan Cholasta imap_write_flags(str, flags, keywords);
e07a94a66985b674c5df11ca466792902164c4e2George McCollister str_append(str, "))");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = client_send_line(ctx->client, str_c(str));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret <= 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher t_pop();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case MAILBOX_SYNC_TYPE_EXPUNGE:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ctx->seq == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->seq = ctx->sync_rec.seq2;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->messages_count -=
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->sync_rec.seq2 -
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->sync_rec.seq1 + 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (; ctx->seq >= ctx->sync_rec.seq1; ctx->seq--) {
a5077712fc8c24e8cad08207b7b5a6603bde6a7cJakub Hrozek str_truncate(str, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher str_printfa(str, "* %u EXPUNGE", ctx->seq);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = client_send_line(ctx->client, str_c(str));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret <= 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher t_pop();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek ctx->seq = 0;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose }
6b0a7c72bb841d6885a620c68bd51d55109b66c7Jakub Hrozek t_pop();
a679f0167b646cffdae86546ed77e105576991b0Pavel Březina return ret;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher}
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagherint imap_sync_nonselected(struct mailbox *box, enum mailbox_sync_flags flags)
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher{
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher struct mailbox_sync_context *ctx;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher struct mailbox_sync_rec sync_rec;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher struct mailbox_status status;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher ctx = mailbox_sync_init(box, flags);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher while (mailbox_sync_next(ctx, &sync_rec) > 0)
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher ;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return mailbox_sync_deinit(ctx, &status);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kosstatic int cmd_sync_continue(struct client *client)
539b1be3507abdf8ac235b06eeed5011b0b5cde2Ondrej Kos{
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek struct cmd_sync_context *ctx = client->cmd_context;
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek if (imap_sync_more(ctx->sync_ctx) == 0)
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek return FALSE;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (imap_sync_deinit(ctx->sync_ctx) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_send_untagged_storage_error(client,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_get_storage(client->mailbox));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_send_tagline(client, ctx->tagline);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint cmd_sync(struct client *client, enum mailbox_sync_flags flags,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *tagline)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct cmd_sync_context *ctx;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (client->mailbox == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client_send_tagline(client, tagline);
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka return TRUE;
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka }
b50dffea929ee5cd0c59ba3c4822337cc162ff92Kamil Dudka
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx = p_new(client->cmd_pool, struct cmd_sync_context, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->tagline = p_strdup(client->cmd_pool, tagline);
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek ctx->sync_ctx = imap_sync_init(client, client->mailbox, flags);
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher client->cmd_func = cmd_sync_continue;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek client->cmd_context = ctx;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek client->command_pending = TRUE;
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek return cmd_sync_continue(client);
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek}
4d81fe27ced3d2e96866aeaf61661a925cb8edf1Jakub Hrozek