dsync-mailbox-import.c revision b0ead8fffe8dfdee92fca875b91fadf3f3f2262b
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#include "lib.h"
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#include "array.h"
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher#include "hash.h"
c252d148fa8ab50aaaa8bbae7beb4d208025171dNikolai Kondrashov#include "str.h"
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher#include "hex-binary.h"
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher#include "istream.h"
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher#include "seq-range-array.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "imap-util.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "mail-storage-private.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "mail-search-build.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "dsync-transaction-log-scan.h"
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov#include "dsync-mail.h"
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek#include "dsync-mailbox.h"
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek#include "dsync-mailbox-import.h"
fd5a4eacd56700ffb08a73121aeacdc806cb0132Sumit Bose
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagherstruct importer_mail {
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher const char *guid;
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher uint32_t uid;
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher};
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagherstruct importer_new_mail {
9d453f1e8b28983b363b44c49b7cd701a994fd97Nikolai Kondrashov /* linked list of mails for this GUID */
428db8a58c0c149d5efccc6d788f70916c1d34d7Jakub Hrozek struct importer_new_mail *next;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* if non-NULL, this mail exists in both local and remote. this link
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher points to the other side. */
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher struct importer_new_mail *link;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *guid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct dsync_mail_change *change;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* the final UID for the message */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t final_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* the original local UID, or 0 if exists only remotely */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t local_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* the original remote UID, or 0 if exists only remotely */
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher uint32_t remote_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* UID for the mail in the virtual \All mailbox */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t virtual_all_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool uid_in_local:1;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose bool uid_is_usable:1;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose bool skip:1;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose bool expunged:1;
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose bool copy_failed:1;
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose bool saved:1;
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose};
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke/* for quickly testing that two-way sync doesn't actually do any unexpected
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke modifications. */
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose#define IMPORTER_DEBUG_CHANGE(importer) /*i_assert(!importer->master_brain)*/
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit BoseHASH_TABLE_DEFINE_TYPE(guid_new_mail, const char *, struct importer_new_mail *);
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit BoseHASH_TABLE_DEFINE_TYPE(uid_new_mail, void *, struct importer_new_mail *);
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bosestruct dsync_mailbox_importer {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pool_t pool;
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher struct mailbox *box;
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher uint32_t last_common_uid;
41291f19dbc5bf14f20729959b852fa605fcc02dJakub Hrozek uint64_t last_common_modseq, last_common_pvt_modseq;
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek uint32_t remote_uid_next;
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek uint32_t remote_first_recent_uid;
a5bb518446d5ce565d7ba819590a009cabb0b0b4Jakub Hrozek uint64_t remote_highest_modseq, remote_highest_pvt_modseq;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce time_t sync_since_timestamp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher time_t sync_until_timestamp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uoff_t sync_max_size;
d921c1eba437662437847279f251a0a5d8f70127Maxim enum mailbox_transaction_flags transaction_flags;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek unsigned int hdr_hash_version;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer unsigned int commit_msgs_interval;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_flags sync_flag;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *sync_keyword;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool sync_flag_dontwant;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce struct mailbox_transaction_context *trans, *ext_trans;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_search_context *search_ctx;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek struct mail *mail, *ext_mail;
5377441d7a846461c2d9a7a870cea711360a529aNikolai Kondrashov
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mailbox *virtual_all_box;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mailbox_transaction_context *virtual_trans;
32381402a4a9afc003782c9e2301fc59c9bda2a9Yassir Elley struct mail *virtual_mail;
dbfc407eef1d9ba2469687c3ffbe7fd8bb111d94Jakub Hrozek
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher struct mail *cur_mail;
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher const char *cur_guid;
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek const char *cur_hdr_hash;
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher /* UID => struct dsync_mail_change */
6dcbfe52d5e64205c0d922f3e89add066b42c496Jakub Hrozek HASH_TABLE_TYPE(dsync_uid_mail_change) local_changes;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher HASH_TABLE_TYPE(dsync_attr_change) local_attr_changes;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ARRAY_TYPE(seq_range) maybe_expunge_uids;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher ARRAY(struct dsync_mail_change *) maybe_saves;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek /* GUID => struct importer_new_mail */
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek HASH_TABLE_TYPE(guid_new_mail) import_guids;
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek /* UID => struct importer_new_mail */
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek HASH_TABLE_TYPE(uid_new_mail) import_uids;
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce ARRAY(struct importer_new_mail *) newmails;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ARRAY_TYPE(uint32_t) wanted_uids;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ARRAY_TYPE(uint32_t) saved_uids;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t highest_wanted_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ARRAY(struct dsync_mail_request) mail_requests;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher unsigned int mail_request_idx;
054b5d4bb98973698f74d66b14ccd14394b53f10Lukas Slebodnik
054b5d4bb98973698f74d66b14ccd14394b53f10Lukas Slebodnik uint32_t prev_uid, next_local_seq, local_uid_next;
62bda5f75bda6b77aea30d708c74efaf725d9367Lukas Slebodnik uint64_t local_initial_highestmodseq, local_initial_highestpvtmodseq;
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek unsigned int import_pos, import_count;
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek unsigned int first_unsaved_idx, saves_since_commit;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_error mail_error;
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher bool failed:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool require_full_resync:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool debug:1;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta bool stateful_import:1;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta bool last_common_uid_found:1;
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta bool cur_uid_has_change:1;
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta bool cur_mail_skip:1;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta bool local_expunged_guids_set:1;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta bool new_uids_assigned:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool want_mail_requests:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool master_brain:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool revert_local_changes:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool mails_have_guids:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool mails_use_guid128:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool delete_mailbox:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool empty_hdr_workaround:1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny
f1828234a850dd28465425248a83a993f262918fPavel Březinastatic const char *dsync_mail_change_type_names[] = {
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay "save", "expunge", "flag-change"
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina};
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březinastatic bool dsync_mailbox_save_newmails(struct dsync_mailbox_importer *importer,
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina const struct dsync_mail *mail,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct importer_new_mail *all_newmails,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool remote_mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int dsync_mailbox_import_commit(struct dsync_mailbox_importer *importer,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool final);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void ATTR_FORMAT(2, 3)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherimp_debug(struct dsync_mailbox_importer *importer, const char *fmt, ...)
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek{
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek va_list args;
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (importer->debug) T_BEGIN {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina va_start(args, fmt);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina i_debug("brain %c: Import %s: %s",
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek importer->master_brain ? 'M' : 'S',
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek mailbox_get_vname(importer->box),
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek t_strdup_vprintf(fmt, args));
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta va_end(args);
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta } T_END;
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta}
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozekstatic void
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozekdsync_import_unexpected_state(struct dsync_mailbox_importer *importer,
19d3aba12c70528708be9440aca66038a291f29eYassir Elley const char *error)
19d3aba12c70528708be9440aca66038a291f29eYassir Elley{
19d3aba12c70528708be9440aca66038a291f29eYassir Elley if (!importer->stateful_import) {
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek i_error("Mailbox %s: %s", mailbox_get_vname(importer->box),
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek error);
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek } else {
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose i_warning("Mailbox %s doesn't match previous state: %s "
45726939a48e605b0166521f94300ae04981a3a7Sumit Bose "(dsync must be run again without the state)",
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose mailbox_get_vname(importer->box), error);
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek }
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozek importer->require_full_resync = TRUE;
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose}
3be9e26dcd169d44ae105f1b8a0674464c700b77Sumit Bose
45726939a48e605b0166521f94300ae04981a3a7Sumit Bosestatic void
5484044ea7bb632b915f706685fce509f6eacc48Jakub Hrozekdsync_mailbox_import_search_init(struct dsync_mailbox_importer *importer)
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce{
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct mail_search_args *search_args;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce struct mail_search_arg *sarg;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose search_args = mail_search_build_init();
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose sarg = mail_search_build_add(search_args, SEARCH_UIDSET);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose p_array_init(&sarg->value.seqset, search_args->pool, 128);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose seq_range_array_add_range(&sarg->value.seqset,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->last_common_uid+1, (uint32_t)-1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce importer->search_ctx =
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek mailbox_search_init(importer->trans, search_args, NULL,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher 0, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_search_args_unref(&search_args);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mailbox_search_next(importer->search_ctx, &importer->cur_mail))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->next_local_seq = importer->cur_mail->seq;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* this flag causes cur_guid to be looked up later */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_mail_skip = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagherdsync_mailbox_import_transaction_begin(struct dsync_mailbox_importer *importer)
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek{
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher const enum mailbox_transaction_flags ext_trans_flags =
fe60346714a73ac3987f786731389320633dd245Pavel Březina importer->transaction_flags |
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose MAILBOX_TRANSACTION_FLAG_EXTERNAL |
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS;
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek importer->trans = mailbox_transaction_begin(importer->box,
e5e8252ec48bfdd4e7529debc705c8e090264b9aSumit Bose importer->transaction_flags);
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina importer->ext_trans = mailbox_transaction_begin(importer->box,
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher ext_trans_flags);
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina importer->mail = mail_alloc(importer->trans, 0, NULL);
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina importer->ext_mail = mail_alloc(importer->ext_trans, 0, NULL);
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina}
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březinastruct dsync_mailbox_importer *
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březinadsync_mailbox_import_init(struct mailbox *box,
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina struct mailbox *virtual_all_box,
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina struct dsync_transaction_log_scan *log_scan,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek uint32_t last_common_uid,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek uint64_t last_common_modseq,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek uint64_t last_common_pvt_modseq,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek uint32_t remote_uid_next,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek uint32_t remote_first_recent_uid,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek uint64_t remote_highest_modseq,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek uint64_t remote_highest_pvt_modseq,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher time_t sync_since_timestamp,
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek time_t sync_until_timestamp,
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek uoff_t sync_max_size,
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek const char *sync_flag,
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh unsigned int commit_msgs_interval,
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose enum dsync_mailbox_import_flags flags,
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha unsigned int hdr_hash_version)
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha{
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek struct dsync_mailbox_importer *importer;
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek struct mailbox_status status;
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose pool_t pool;
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose pool = pool_alloconly_create(MEMPOOL_GROWING"dsync mailbox importer",
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose 10240);
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek importer = p_new(pool, struct dsync_mailbox_importer, 1);
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek importer->pool = pool;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek importer->box = box;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek importer->virtual_all_box = virtual_all_box;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina importer->last_common_uid = last_common_uid;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek importer->last_common_modseq = last_common_modseq;
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl importer->last_common_pvt_modseq = last_common_pvt_modseq;
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl importer->last_common_uid_found =
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek last_common_uid != 0 || last_common_modseq != 0;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek importer->remote_uid_next = remote_uid_next;
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek importer->remote_first_recent_uid = remote_first_recent_uid;
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek importer->remote_highest_modseq = remote_highest_modseq;
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech importer->remote_highest_pvt_modseq = remote_highest_pvt_modseq;
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose importer->sync_since_timestamp = sync_since_timestamp;
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina importer->sync_until_timestamp = sync_until_timestamp;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose importer->sync_max_size = sync_max_size;
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose importer->stateful_import = importer->last_common_uid_found;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek if (sync_flag != NULL) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (sync_flag[0] == '-') {
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina importer->sync_flag_dontwant = TRUE;
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek sync_flag++;
2b62d5a414b8b7dba4f714dc5033e28dc4b1f4feJakub Hrozek }
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek if (sync_flag[0] == '\\')
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech importer->sync_flag = imap_parse_system_flag(sync_flag);
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek else
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose importer->sync_keyword = p_strdup(pool, sync_flag);
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek }
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek importer->commit_msgs_interval = commit_msgs_interval;
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina importer->transaction_flags = MAILBOX_TRANSACTION_FLAG_SYNC;
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl if ((flags & DSYNC_MAILBOX_IMPORT_FLAG_NO_NOTIFY) != 0)
62370340092503baeaf6587d7ffe4fe25bd9582dPavel Reichl importer->transaction_flags |= MAILBOX_TRANSACTION_FLAG_NO_NOTIFY;
b407fe0474a674bb42f0f42ab47c7f530a07a367Pavel Březina
583c1b9a052f4eb5ba046c5f2b7d2ed2a81b6d66Jakub Hrozek hash_table_create(&importer->import_guids, pool, 0, str_hash, strcmp);
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek hash_table_create_direct(&importer->import_uids, pool, 0);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek i_array_init(&importer->maybe_expunge_uids, 16);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek i_array_init(&importer->maybe_saves, 128);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek i_array_init(&importer->newmails, 128);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek i_array_init(&importer->wanted_uids, 128);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek i_array_init(&importer->saved_uids, 128);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek dsync_mailbox_import_transaction_begin(importer);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if ((flags & DSYNC_MAILBOX_IMPORT_FLAG_WANT_MAIL_REQUESTS) != 0) {
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik i_array_init(&importer->mail_requests, 128);
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik importer->want_mail_requests = TRUE;
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik }
91d312000e6ded4a93327c137b10c5beda55f65cSumit Bose importer->master_brain =
91d312000e6ded4a93327c137b10c5beda55f65cSumit Bose (flags & DSYNC_MAILBOX_IMPORT_FLAG_MASTER_BRAIN) != 0;
91d312000e6ded4a93327c137b10c5beda55f65cSumit Bose importer->revert_local_changes =
91d312000e6ded4a93327c137b10c5beda55f65cSumit Bose (flags & DSYNC_MAILBOX_IMPORT_FLAG_REVERT_LOCAL_CHANGES) != 0;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik importer->debug = (flags & DSYNC_MAILBOX_IMPORT_FLAG_DEBUG) != 0;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik importer->mails_have_guids =
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek (flags & DSYNC_MAILBOX_IMPORT_FLAG_MAILS_HAVE_GUIDS) != 0;
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek importer->mails_use_guid128 =
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (flags & DSYNC_MAILBOX_IMPORT_FLAG_MAILS_USE_GUID128) != 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->hdr_hash_version = hdr_hash_version;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek importer->empty_hdr_workaround =
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek (flags & DSYNC_MAILBOX_IMPORT_FLAG_EMPTY_HDR_WORKAROUND) != 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_get_open_status(importer->box, STATUS_UIDNEXT |
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek STATUS_HIGHESTMODSEQ | STATUS_HIGHESTPVTMODSEQ,
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek &status);
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek importer->local_uid_next = status.uidnext;
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek importer->local_initial_highestmodseq = status.highest_modseq;
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher importer->local_initial_highestpvtmodseq = status.highest_pvt_modseq;
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher dsync_mailbox_import_search_init(importer);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik if (!importer->stateful_import)
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik ;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik else if (importer->local_uid_next <= last_common_uid) {
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik dsync_import_unexpected_state(importer, t_strdup_printf(
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik "local UIDNEXT %u <= last common UID %u",
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik importer->local_uid_next, last_common_uid));
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik } else if (importer->local_initial_highestmodseq < last_common_modseq) {
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik dsync_import_unexpected_state(importer, t_strdup_printf(
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik "local HIGHESTMODSEQ %llu < last common HIGHESTMODSEQ %llu",
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik (unsigned long long)importer->local_initial_highestmodseq,
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher (unsigned long long)last_common_modseq));
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher } else if (importer->local_initial_highestpvtmodseq < last_common_pvt_modseq) {
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik dsync_import_unexpected_state(importer, t_strdup_printf(
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "local HIGHESTMODSEQ %llu < last common HIGHESTMODSEQ %llu",
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher (unsigned long long)importer->local_initial_highestpvtmodseq,
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek (unsigned long long)last_common_pvt_modseq));
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov }
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov importer->local_changes = dsync_transaction_log_scan_get_hash(log_scan);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->local_attr_changes = dsync_transaction_log_scan_get_attr_hash(log_scan);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return importer;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdsync_mailbox_import_lookup_attr(struct dsync_mailbox_importer *importer,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_attribute_type type, const char *key,
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik struct dsync_mailbox_attribute **attr_r)
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik{
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik struct dsync_mailbox_attribute lookup_attr, *attr;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik const struct dsync_mailbox_attribute *attr_change;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik struct mail_attribute_value value;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *attr_r = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mailbox_attribute_get_stream(importer->box, type, key, &value) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("Mailbox %s: Failed to get attribute %s: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_get_vname(importer->box), key,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_get_last_internal_error(importer->box,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher &importer->mail_error));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->failed = TRUE;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose return -1;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose }
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose lookup_attr.type = type;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose lookup_attr.key = key;
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose attr_change = hash_table_lookup(importer->local_attr_changes,
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose &lookup_attr);
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose if (attr_change == NULL &&
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose value.value == NULL && value.value_stream == NULL) {
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke /* we have no knowledge of this attribute */
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke return 0;
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke }
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke attr = t_new(struct dsync_mailbox_attribute, 1);
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke attr->type = type;
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose attr->key = key;
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose attr->value = value.value;
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose attr->value_stream = value.value_stream;
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose attr->last_change = value.last_change;
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose if (attr_change != NULL) {
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose attr->deleted = attr_change->deleted &&
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher !DSYNC_ATTR_HAS_VALUE(attr);
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher attr->modseq = attr_change->modseq;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *attr_r = attr;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return 0;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik}
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikstatic int
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikdsync_istreams_cmp(struct istream *input1, struct istream *input2, int *cmp_r)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik{
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik const unsigned char *data1, *data2;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik size_t size1, size2, size;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik *cmp_r = -1; /* quiet gcc */
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik for (;;) {
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik (void)i_stream_read_more(input1, &data1, &size1);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik (void)i_stream_read_more(input2, &data2, &size2);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (size1 == 0 || size2 == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher size = I_MIN(size1, size2);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *cmp_r = memcmp(data1, data2, size);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (*cmp_r != 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher i_stream_skip(input1, size);
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher i_stream_skip(input2, size);
15b266d9f14dad26da8678a79019749d0f69532eStephen Gallagher }
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik if (input1->stream_errno != 0) {
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik i_error("read(%s) failed: %s", i_stream_get_name(input1),
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher i_stream_get_error(input1));
b97595ae059c69b1960a6e7e56d74660388a683bJan Zeleny return -1;
6a6a821866091e0f722808566c25b951aa346d7cStephen Gallagher }
48d7840cae22c5ff4d786149b0d8ecee7efb8306Lukas Slebodnik if (input2->stream_errno != 0) {
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov i_error("read(%s) failed: %s", i_stream_get_name(input2),
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov i_stream_get_error(input2));
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov return -1;
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov }
60e51fd2764291df2332f36ff478777627d92b57Sumit Bose if (size1 == 0 && size2 == 0)
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik *cmp_r = 0;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik else
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek *cmp_r = size1 == 0 ? -1 : 1;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik return 0;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik}
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashovstatic int
7bb9ba8688ec1ca930d693eea05e936bc38f6d1bSumit Bosedsync_attributes_cmp_values(const struct dsync_mailbox_attribute *attr1,
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek const struct dsync_mailbox_attribute *attr2,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int *cmp_r)
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct istream *input1, *input2;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(attr1->value_stream != NULL || attr1->value != NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(attr2->value_stream != NULL || attr2->value != NULL);
17f08cbd0f909181536b93d6c12c7cd69995f09eSumit Bose
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov if (attr1->value != NULL && attr2->value != NULL) {
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov *cmp_r = strcmp(attr1->value, attr2->value);
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov return 0;
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov }
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov /* at least one of them is a stream. make both of them streams. */
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov input1 = attr1->value_stream != NULL ? attr1->value_stream :
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov i_stream_create_from_data(attr1->value, strlen(attr1->value));
a8d887323f83984679a7d9b827a70146656bb7b2Sumit Bose input2 = attr2->value_stream != NULL ? attr2->value_stream :
a8d887323f83984679a7d9b827a70146656bb7b2Sumit Bose i_stream_create_from_data(attr2->value, strlen(attr2->value));
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek i_stream_seek(input1, 0);
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov i_stream_seek(input2, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = dsync_istreams_cmp(input1, input2, cmp_r);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (attr1->value_stream == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_unref(&input1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (attr2->value_stream == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_stream_unref(&input2);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdsync_attributes_cmp(const struct dsync_mailbox_attribute *attr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct dsync_mailbox_attribute *local_attr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int *cmp_r)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (DSYNC_ATTR_HAS_VALUE(attr) &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher !DSYNC_ATTR_HAS_VALUE(local_attr)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* remote has a value and local doesn't -> use it */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *cmp_r = 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (!DSYNC_ATTR_HAS_VALUE(attr) &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher DSYNC_ATTR_HAS_VALUE(local_attr)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* remote doesn't have a value, bt local does -> skip */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *cmp_r = -1;
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose return 0;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher }
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return dsync_attributes_cmp_values(attr, local_attr, cmp_r);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
a5bb518446d5ce565d7ba819590a009cabb0b0b4Jakub Hrozek
eaaeaa7e00c3d4bfa792cc4d3c6770dc1e28ef0cSumit Bosestatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdsync_mailbox_import_attribute_real(struct dsync_mailbox_importer *importer,
c42ca36247022490ad65a33c453cb5e43900dbe9Lukas Slebodnik const struct dsync_mailbox_attribute *attr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct dsync_mailbox_attribute *local_attr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char **result_r)
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher{
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce struct mail_attribute_value value;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int cmp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool ignore = FALSE;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(DSYNC_ATTR_HAS_VALUE(attr) || attr->deleted);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
0ef783e186ef1c9f60e61a4e8e54c44cb366fdfePavel Březina if (attr->deleted &&
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek (local_attr == NULL || !DSYNC_ATTR_HAS_VALUE(local_attr))) {
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta /* attribute doesn't exist on either side -> ignore */
50c9d542e8bf641412debaa82a4dcf67ddb72258Lukas Slebodnik *result_r = "Nonexistent in both sides";
50c9d542e8bf641412debaa82a4dcf67ddb72258Lukas Slebodnik return 0;
50c9d542e8bf641412debaa82a4dcf67ddb72258Lukas Slebodnik }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (local_attr == NULL) {
b3b6189850d50c656d62efbd498789124c033b00Lukas Slebodnik /* we haven't seen this locally -> use whatever remote has */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Nonexistent locally";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (local_attr->modseq <= importer->last_common_modseq &&
e7ccfb139388c947ec2dee16cfe3005f5643b90dPetr Cech attr->modseq > importer->last_common_modseq &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->last_common_modseq > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we're doing incremental syncing, and we can see that the
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher attribute was changed remotely, but not locally -> use it */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Changed remotely";
c0f9698cd951b7223f251ff2511c4b22a6e4ba60Jan Zeleny } else if (local_attr->modseq > importer->last_common_modseq &&
769347ad4d35d43488eb98f980143495b0db415dStef Walter attr->modseq <= importer->last_common_modseq &&
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose importer->last_common_modseq > 0) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* we're doing incremental syncing, and we can see that the
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březina attribute was changed locally, but not remotely -> ignore */
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březina *result_r = "Changed locally";
769347ad4d35d43488eb98f980143495b0db415dStef Walter ignore = TRUE;
769347ad4d35d43488eb98f980143495b0db415dStef Walter } else if (attr->last_change > local_attr->last_change) {
376eaf187c13c2a1eaea0ffbdd970b6b563ab74cPetr Cech /* remote has a newer timestamp -> use it */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Remote has newer timestamp";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (attr->last_change < local_attr->last_change) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* remote has an older timestamp -> ignore */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Local has newer timestamp";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ignore = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina /* the timestamps are the same. now we're down to guessing
aea1d5c0ca9bb1470759b024c8b97b6c1f577193Pavel Březina the right answer, unless the values are actually equal,
d2d8f342cd5e90bb9fd947c448492225f959aa86Pavel Březina so check that first. next try to use modseqs, but if even
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina they are the same, fallback to just picking one based on the
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina value. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (dsync_attributes_cmp(attr, local_attr, &cmp) < 0) {
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek importer->mail_error = MAIL_ERROR_TEMP;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek importer->failed = TRUE;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek return -1;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek }
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek if (cmp == 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* identical scripts */
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina *result_r = "Unchanged value";
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (attr->modseq > local_attr->modseq) {
77d165f0629966db65753a3aee84a8b4971673afPavel Březina /* remote has a higher modseq -> use it */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Remote has newer modseq";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (attr->modseq < local_attr->modseq) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* remote has an older modseq -> ignore */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Local has newer modseq";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ignore = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (cmp < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ignore = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Value changed, but unknown which is newer - picking local";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Value changed, but unknown which is newer - picking remote";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
126c9338cf12a3e4404c36bbe4ec14b18f23537cMaxim if (ignore)
6499d0b915209b670f8e337c4fe76a8be9fa6576Simo Sorce return 0;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_zero(&value);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value.value = attr->value;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value.value_stream = attr->value_stream;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher value.last_change = attr->last_change;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mailbox_attribute_set(importer->trans, attr->type,
4e0404ca1b19830dc0f729e59efd5bbd0a9d6103Lukas Slebodnik attr->key, &value) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_error("Mailbox %s: Failed to set attribute %s: %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_get_vname(importer->box), attr->key,
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik mailbox_get_last_internal_error(importer->box, NULL));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* the attributes aren't vital, don't fail everything just
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher because of them. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint dsync_mailbox_import_attribute(struct dsync_mailbox_importer *importer,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct dsync_mailbox_attribute *attr)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose struct dsync_mailbox_attribute *local_attr;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher const char *result = "";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
2e6087c6cc903d5164b9a1d5e3d791fd046001d9Jakub Hrozek if (dsync_mailbox_import_lookup_attr(importer, attr->type,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher attr->key, &local_attr) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = dsync_mailbox_import_attribute_real(importer, attr,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher local_attr, &result);
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek if (local_attr != NULL && local_attr->value_stream != NULL)
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose i_stream_unref(&local_attr->value_stream);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
558ec7d717735bb16c210c675c2cc5bee1da4576Lukas Slebodnik imp_debug(importer, "Import attribute %s: %s", attr->key,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret < 0 ? "failed" : result);
3a4186ae40d0c3b7be46a4c973166f6048fcfe38Lukas Slebodnik return ret;
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce}
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void dsync_mail_error(struct dsync_mailbox_importer *importer,
46e36286953de4e5af5e4289b90a529929bdd17cPetr Cech struct mail *mail, const char *field)
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik{
29be7d76c949b82350c7603cfd362a1fcb47eb1bJan Zeleny const char *errstr;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_error error;
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher errstr = mailbox_get_last_internal_error(importer->box, &error);
823a5b3f4375f12b6edae4dd5169ee01771baebeJan Zeleny if (error == MAIL_ERROR_EXPUNGED)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta i_error("Mailbox %s: Can't lookup %s for UID=%u: %s",
7de6e3534fd61c7619ed34a6b1afe7230b5e6504Ondrej Kos mailbox_get_vname(mail->box), field, mail->uid, errstr);
701f13b5c8e27bcbfc79e77ce7c76d9f768a448cLukas Slebodnik importer->mail_error = error;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina importer->failed = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool
5a70b84cb66fb8c7a3fce0e3f2e4b61e0b2ea9d4Simo Sorcedsync_mail_change_guid_equals(struct dsync_mailbox_importer *importer,
5f90993426fa2bdc3b3d994c9e85e0805bb92bbcSimo Sorce const struct dsync_mail_change *change,
9959c512ac3ba36f7a0db7614f0357ce0bae748fJakub Hrozek const char *guid, const char **cmp_guid_r)
7452f1b637276ce582b120f8f5482ae7f3b6bd47Jakub Hrozek{
918b2a5a91f1c551d48f4bffed2a28c36fdb4be1Simo Sorce guid_128_t guid_128, change_guid_128;
bc052ea17d858c19f9cb9c9e2bc602e754f68831Sumit Bose
2fa8d6655ac37f9bdeb34420000052d921f4a543Michal Zidek if (change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE) {
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina if (guid_128_from_string(change->guid, change_guid_128) < 0)
6499d0b915209b670f8e337c4fe76a8be9fa6576Simo Sorce i_unreached();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (importer->mails_use_guid128) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_generate_guid_128_hash(change->guid, change_guid_128);
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (cmp_guid_r != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *cmp_guid_r = change->guid;
e850be1ff2e13bba9812c94c3d102c0a0b570820Jakub Hrozek return strcmp(change->guid, guid) == 0;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březina
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_generate_guid_128_hash(guid, guid_128);
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagher if (memcmp(change_guid_128, guid_128, GUID_128_SIZE) != 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (cmp_guid_r != NULL) {
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher *cmp_guid_r = t_strdup_printf("%s(guid128, orig=%s)",
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher binary_to_hex(change_guid_128, sizeof(change_guid_128)),
8c3a4809b3420657289b42f028a1c9019b112991Stephen Gallagher change->guid);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce }
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose return FALSE;
e7ccfb139388c947ec2dee16cfe3005f5643b90dPetr Cech }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina}
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholastastatic int
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březinaimporter_try_next_mail(struct dsync_mailbox_importer *importer,
7f0b01bf0a8f5c5b3ef145e81511b6db2cb4f98fPavel Březina uint32_t wanted_uid)
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek{
590582be38cdbfde387fcc57df92903d48c5a083Jakub Hrozek struct mail_private *pmail;
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina const char *hdr_hash;
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (importer->cur_mail == NULL) {
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina /* end of search */
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return -1;
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce }
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce while (importer->cur_mail->seq < importer->next_local_seq ||
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce importer->cur_mail->uid < wanted_uid) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!importer->cur_uid_has_change &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher !importer->last_common_uid_found) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* this message exists locally, but remote didn't send
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher expunge-change for it. if the message's
df4e1db5d41c903ae57fd880acc76a0ad84aa7b2Pavel Březina uid <= last-common-uid, it should be deleted */
364b3572bab5a9649e8f2d4da835d05d3c8ca7a9Pavel Březina seq_range_array_add(&importer->maybe_expunge_uids,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_mail->uid);
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek }
1f1e6cbc59868f06dee3ab4b3df660fcb77ce1c8Jakub Hrozek
4c11f752e1f10cf5740d53a3206bb795e9e34fe8Jan Zeleny importer->cur_mail_skip = FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!mailbox_search_next(importer->search_ctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher &importer->cur_mail)) {
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta importer->cur_mail = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_guid = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_hdr_hash = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
376eaf187c13c2a1eaea0ffbdd970b6b563ab74cPetr Cech importer->cur_uid_has_change = FALSE;
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina }
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina importer->cur_uid_has_change = importer->cur_mail->uid == wanted_uid;
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina if (importer->mails_have_guids) {
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina if (mail_get_special(importer->cur_mail, MAIL_FETCH_GUID,
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina &importer->cur_guid) < 0) {
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina dsync_mail_error(importer, importer->cur_mail, "GUID");
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina return 0;
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina }
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina } else {
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina if (dsync_mail_get_hdr_hash(importer->cur_mail,
cc2d77d5218c188119fa954c856e858cbde76947Pavel Březina importer->hdr_hash_version,
892ddeb5190dd5c1ffa26a95142a10a0034fc5e3Pavel Březina &hdr_hash) < 0) {
3b99f7a97553a0a357d50abe507d4f0060c4eceaPavel Březina dsync_mail_error(importer, importer->cur_mail,
3b99f7a97553a0a357d50abe507d4f0060c4eceaPavel Březina "header hash");
50c2a57dea6d38a4f6753a917a5d745b07036325Pavel Březina return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
f9961e5f82e0ef474d6492371bfdf9e74e208a99Pavel Březina pmail = (struct mail_private *)importer->cur_mail;
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher importer->cur_hdr_hash = p_strdup(pmail->pool, hdr_hash);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_guid = "";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* make sure next_local_seq gets updated in case we came here
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher because of min_uid */
3441d0c2d11aea0c39b009751a1898333c009674Stephen Gallagher importer->next_local_seq = importer->cur_mail->seq;
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher return 1;
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherimporter_next_mail(struct dsync_mailbox_importer *importer, uint32_t wanted_uid)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
cce3e8526176ce2fe9baa5bda1bb457b996b7bcfSumit Bose int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
e9eeb4302e0e426c6cc1a4e65b95a6f7066e80b9Pavel Březina for (;;) {
85feb8d77a2c832787880944e02104846c4d5376Pavel Březina T_BEGIN {
cc84fd46f356c4a36a721ab135a33ec77c93e34dJakub Hrozek ret = importer_try_next_mail(importer, wanted_uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } T_END;
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher if (ret != 0 || importer->failed)
cdaa29d2c5724a4c72bfa0f42284ccfac3d5a464Pavel Reichl break;
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher importer->next_local_seq = importer->cur_mail->seq + 1;
fae99bfe4bfc8b4a12e9c2a0ad01b3684c22f934Simo Sorce }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return ret > 0;
8ca73915a3bf60331468fed6b3b38652c979f95dJakub Hrozek}
d0599eaa9369fd867953e3c58b8d7bb445525ff5Pavel Březina
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int
213ce2a78b1abe3921d8dc13c949a28130d00aecJan Zelenyimporter_mail_cmp(const struct importer_mail *m1,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct importer_mail *m2)
38e2ec1c757955ab557fd95807afa58042d09482Jan Zeleny{
ad07ed37b6b51ef134d4524edaf2259e19ac984fJan Zeleny int ret;
1a853121ca2ba8ede6df429ee76942131ffb0f65Jan Zeleny
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (m1->guid == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose if (m2->guid == NULL)
3a62a99faf8e12965100d0b26fc9e07752bd3e2dStephen Gallagher return -1;
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher ret = strcmp(m1->guid, m2->guid);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina if (ret != 0)
b407fe0474a674bb42f0f42ab47c7f530a07a367Pavel Březina return ret;
4ddd5591c50e27dffa55f03fbce0dcc85cd50a8bPavel Březina
a679f0167b646cffdae86546ed77e105576991b0Pavel Březina if (m1->uid < m2->uid)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return -1;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina if (m1->uid > m2->uid)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return 1;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina return 0;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina}
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březinastatic void newmail_link(struct dsync_mailbox_importer *importer,
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct importer_new_mail *newmail, uint32_t remote_uid)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct importer_new_mail *first_mail, **last, *mail, *link = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (*newmail->guid != '\0') {
347f7c4d1e8e83fc7ffcaf9524a67e8b3ad5d7c5Jan Cholasta first_mail = hash_table_lookup(importer->import_guids,
4139a7a731f2831963a42b26aac111422be28792Jakub Hrozek newmail->guid);
50fe3d79ab12b795a687b676761bef265701626aStephen Gallagher if (first_mail == NULL) {
50fe3d79ab12b795a687b676761bef265701626aStephen Gallagher /* first mail for this GUID */
3f32406640d89face5e79244b4d8dab34adb6c7cPavel Březina hash_table_insert(importer->import_guids,
17d37aecdf397fcb7a1d0c75adebdb25d7be112ePavel Březina newmail->guid, newmail);
b1a822a16e3ef97e31d167f9e97efec06fc121dcJakub Hrozek return;
d43c9d18fb263b1ea4071b20e93ce4994583f62fJakub Hrozek }
077f8c9ca849ec895da3f0a25d15484ead08e99eLukas Slebodnik } else {
3e5e98aae4b14f5447c561ff5b0d854b74046312Pavel Březina if (remote_uid == 0) {
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina /* mail exists only locally. we don't want to request
bf6c3f07d653d474da9e43b2b7cced57fc4ea069Sumit Bose it, and we'll assume it has no duplicate
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bose instances. */
e293fba4f5459f3c2dad254dcc966407d8fc3312Jakub Hrozek return;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose }
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose first_mail = hash_table_lookup(importer->import_uids,
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose POINTER_CAST(remote_uid));
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if (first_mail == NULL) {
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer /* first mail for this UID */
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina hash_table_insert(importer->import_uids,
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik POINTER_CAST(remote_uid), newmail);
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose return;
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik }
284937e6b5b0c9d7a1d3382d0d2820d1168842fbPavel Březina }
aea1d5c0ca9bb1470759b024c8b97b6c1f577193Pavel Březina /* 1) add the newmail to the end of the linked list
23fb01bf67a6058fb508da6d81515e8b18634bebPavel Březina 2) find our link
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
53f1b03f4e61ebe21df0c2fd05e09e0504fd8881Jakub Hrozek FIXME: this loop is slow if the same GUID has a ton of instances.
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik Could it be improved in some way? */
347f7c4d1e8e83fc7ffcaf9524a67e8b3ad5d7c5Jan Cholasta last = &first_mail->next;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (mail = first_mail; mail != NULL; mail = mail->next) {
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek if (mail->final_uid == newmail->final_uid)
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce mail->uid_is_usable = TRUE;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (link == NULL && mail->link == NULL &&
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek mail->uid_in_local != newmail->uid_in_local)
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek link = mail;
374bf54785365273b20690bd3792c25a44738041Pavel Březina last = &mail->next;
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher }
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher *last = newmail;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose if (link != NULL && newmail->link == NULL) {
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose link->link = newmail;
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher newmail->link = link;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
2d5d7761ef2b0d43c39dadf877b87aae19231036Lukas Slebodnik}
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březinastatic void
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnikdsync_mailbox_revert_existing_uid(struct dsync_mailbox_importer *importer,
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik uint32_t uid, const char *reason)
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek{
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik i_assert(importer->revert_local_changes);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek /* UID either already exists or UIDNEXT is too high. we can't set the
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek wanted UID, so we'll need to delete the whole mailbox and resync */
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek i_warning("Deleting mailbox '%s': UID=%u already exists locally for a different mail: %s",
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek mailbox_get_vname(importer->box), uid, reason);
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek importer->delete_mailbox = TRUE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher importer->mail_error = MAIL_ERROR_TEMP;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher importer->failed = TRUE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherstatic bool dsync_mailbox_try_save_cur(struct dsync_mailbox_importer *importer,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher struct dsync_mail_change *save_change)
11e8f3ecdddf8edd8b1bbe9f41b49ce8b709b92aPetr Cech{
11e8f3ecdddf8edd8b1bbe9f41b49ce8b709b92aPetr Cech struct importer_mail m1, m2;
11e8f3ecdddf8edd8b1bbe9f41b49ce8b709b92aPetr Cech struct importer_new_mail *newmail;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt int diff;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt bool remote_saved;
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher i_zero(&m1);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (importer->cur_mail != NULL) {
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher m1.guid = importer->mails_have_guids ?
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher importer->cur_guid : importer->cur_hdr_hash;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik m1.uid = importer->cur_mail->uid;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik }
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik i_zero(&m2);
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik if (save_change != NULL) {
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik m2.guid = importer->mails_have_guids ?
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik save_change->guid : save_change->hdr_hash;
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher m2.uid = save_change->uid;
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher i_assert(save_change->type != DSYNC_MAIL_CHANGE_TYPE_EXPUNGE);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik }
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik if (importer->empty_hdr_workaround && !importer->mails_have_guids &&
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik importer->cur_mail != NULL && save_change != NULL &&
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik (dsync_mail_hdr_hash_is_empty(m1.guid) ||
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik dsync_mail_hdr_hash_is_empty(m2.guid))) {
69b46c32357ccf1aab9c0bd6d1afa33a8724ad77Lukas Slebodnik /* one of the headers is empty. assume it's broken and that
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik the header matches what we have currently. */
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik diff = 0;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik } else {
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik diff = importer_mail_cmp(&m1, &m2);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik }
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (diff < 0) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce /* add a record for local mail */
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce i_assert(importer->cur_mail != NULL);
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce if (importer->revert_local_changes) {
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (save_change == NULL &&
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik importer->cur_mail->uid >= importer->remote_uid_next) {
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose dsync_mailbox_revert_existing_uid(importer, importer->cur_mail->uid,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose t_strdup_printf("higher than remote's UIDs (remote UIDNEXT=%u)", importer->remote_uid_next));
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose return TRUE;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose }
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose mail_expunge(importer->cur_mail);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose importer->cur_mail_skip = TRUE;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose importer->next_local_seq++;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose return FALSE;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose }
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail = p_new(importer->pool, struct importer_new_mail, 1);
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail->guid = p_strdup(importer->pool, importer->cur_guid);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->final_uid = importer->cur_mail->uid;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->local_uid = importer->cur_mail->uid;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->uid_in_local = TRUE;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->uid_is_usable =
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce newmail->final_uid >= importer->remote_uid_next;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce remote_saved = FALSE;
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce } else if (diff > 0) {
625bb2ddf15e8f305a53afa44e87f2146fa930afSimo Sorce i_assert(save_change != NULL);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail = p_new(importer->pool, struct importer_new_mail, 1);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->guid = save_change->guid;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail->final_uid = save_change->uid;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail->remote_uid = save_change->uid;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail->uid_in_local = FALSE;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail->uid_is_usable =
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail->final_uid >= importer->local_uid_next;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose if (!newmail->uid_is_usable && importer->revert_local_changes) {
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose dsync_mailbox_revert_existing_uid(importer, newmail->final_uid,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose t_strdup_printf("UID >= local UIDNEXT=%u", importer->local_uid_next));
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose return TRUE;
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose }
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose remote_saved = TRUE;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik } else {
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik /* identical */
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik i_assert(importer->cur_mail != NULL);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik i_assert(save_change != NULL);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail = p_new(importer->pool, struct importer_new_mail, 1);
3b1aa479b377e570c6dff359a1f8099289a2af75Michal Židek newmail->guid = save_change->guid;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->final_uid = importer->cur_mail->uid;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->local_uid = importer->cur_mail->uid;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->remote_uid = save_change->uid;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->uid_in_local = TRUE;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->uid_is_usable = TRUE;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik newmail->link = newmail;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik remote_saved = TRUE;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik }
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (newmail->uid_in_local) {
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik importer->cur_mail_skip = TRUE;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose importer->next_local_seq++;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose }
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose /* NOTE: assumes save_change is allocated from importer pool */
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose newmail->change = save_change;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose array_append(&importer->newmails, &newmail, 1);
3b1aa479b377e570c6dff359a1f8099289a2af75Michal Židek newmail_link(importer, newmail,
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose save_change == NULL ? 0 : save_change->uid);
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose return remote_saved;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose}
0d5bb38364a6976e9c85d6349aa13a04d181a090Sumit Bose
bf01e8179cbb2be476805340636098deda7e1366Sumit Bosestatic bool ATTR_NULL(2)
bf01e8179cbb2be476805340636098deda7e1366Sumit Bosedsync_mailbox_try_save(struct dsync_mailbox_importer *importer,
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose struct dsync_mail_change *save_change)
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose{
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if (importer->cur_mail_skip) {
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if (!importer_next_mail(importer, 0) && save_change == NULL)
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose return FALSE;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose }
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher return dsync_mailbox_try_save_cur(importer, save_change);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherstatic void dsync_mailbox_save(struct dsync_mailbox_importer *importer,
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher struct dsync_mail_change *save_change)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
4c11f752e1f10cf5740d53a3206bb795e9e34fe8Jan Zeleny while (!dsync_mailbox_try_save(importer, save_change)) ;
c2352a73f52f600d95966ebe0b0819649ba923faStephen Gallagher}
6e9d7cbe43fdfc866b18f9ef0779bbfc10ad6f3aJakub Hrozek
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic bool
1f1e6cbc59868f06dee3ab4b3df660fcb77ce1c8Jakub Hrozekdsync_import_set_mail(struct dsync_mailbox_importer *importer,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny const struct dsync_mail_change *change)
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose{
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose const char *guid, *cmp_guid;
817b1bcafff27cc67630dd0cbd36df708c05fcccStephen Gallagher
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley if (!mail_set_uid(importer->mail, change->uid))
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return FALSE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (change->guid == NULL) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher /* GUID is unknown */
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina return TRUE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (*change->guid == '\0') {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher /* backend doesn't support GUIDs. if hdr_hash is set, we could
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter verify it, but since this message really is supposed to
d87e960c17d7598781cf032d06ba03a3ecadbfa2Pavel Březina match, it's probably too much trouble. */
42c28b9424b6ef8a0021b124773e171dd5defaddJakub Hrozek return TRUE;
df4e1db5d41c903ae57fd880acc76a0ad84aa7b2Pavel Březina }
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter
d9577dbd92555b0755881e37724019ef9c578404Stef Walter /* verify that GUID matches, just in case */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (mail_get_special(importer->mail, MAIL_FETCH_GUID, &guid) < 0) {
ae7247551b78a05a5397d3c790afad7ef51b0d9dPavel Březina dsync_mail_error(importer, importer->mail, "GUID");
d4aa049726ce8c6feeaf6995d4abb4cb5155b9a1Pavel Březina return FALSE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!dsync_mail_change_guid_equals(importer, change, guid, &cmp_guid)) {
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter dsync_import_unexpected_state(importer, t_strdup_printf(
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher "Unexpected GUID mismatch for UID=%u: %s != %s",
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher change->uid, guid, cmp_guid));
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return FALSE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return TRUE;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
29be7d76c949b82350c7603cfd362a1fcb47eb1bJan Zelenystatic bool dsync_check_cur_guid(struct dsync_mailbox_importer *importer,
dbea04f585a30d001b574317c068cd03a4fa332bJakub Hrozek const struct dsync_mail_change *change)
5a70b84cb66fb8c7a3fce0e3f2e4b61e0b2ea9d4Simo Sorce{
823a5b3f4375f12b6edae4dd5169ee01771baebeJan Zeleny const char *cmp_guid;
9959c512ac3ba36f7a0db7614f0357ce0bae748fJakub Hrozek
918b2a5a91f1c551d48f4bffed2a28c36fdb4be1Simo Sorce if (change->guid == NULL || change->guid[0] == '\0' ||
bc052ea17d858c19f9cb9c9e2bc602e754f68831Sumit Bose importer->cur_guid[0] == '\0')
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny return TRUE;
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidek if (!dsync_mail_change_guid_equals(importer, change,
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce importer->cur_guid, &cmp_guid)) {
22d381367c27910fe82f476a76b9f4ede555e35aLukas Slebodnik dsync_import_unexpected_state(importer, t_strdup_printf(
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik "Unexpected GUID mismatch (2) for UID=%u: %s != %s",
7de6e3534fd61c7619ed34a6b1afe7230b5e6504Ondrej Kos change->uid, importer->cur_guid, cmp_guid));
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina return FALSE;
de38d860e39585486e3ccbb42555196e319c7efdSumit Bose }
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik return TRUE;
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik}
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek
75ba524d356fed615a9c92152f64aebf0bdaf9c2Simo Sorcestatic void
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnikmerge_flags(uint32_t local_final, uint32_t local_add, uint32_t local_remove,
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik uint32_t remote_final, uint32_t remote_add, uint32_t remote_remove,
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik uint32_t pvt_mask, bool prefer_remote, bool prefer_pvt_remote,
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek uint32_t *change_add_r, uint32_t *change_remove_r,
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek bool *remote_changed, bool *remote_pvt_changed)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher uint32_t combined_add, combined_remove, conflict_flags;
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik uint32_t local_wanted, remote_wanted, conflict_pvt_flags;
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik /* resolve conflicts */
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik conflict_flags = local_add & remote_remove;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik if (conflict_flags != 0) {
7d8b7d82f0a91ed656320577fc781f24a66db9f8Sumit Bose conflict_pvt_flags = conflict_flags & pvt_mask;
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek conflict_flags &= ~pvt_mask;
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek if (prefer_remote)
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek local_add &= ~conflict_flags;
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek else
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta remote_remove &= ~conflict_flags;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta if (prefer_pvt_remote)
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta local_add &= ~conflict_pvt_flags;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta else
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta remote_remove &= ~conflict_pvt_flags;
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek conflict_flags = local_remove & remote_add;
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek if (conflict_flags != 0) {
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher conflict_pvt_flags = conflict_flags & pvt_mask;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conflict_flags &= ~pvt_mask;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (prefer_remote)
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek local_remove &= ~conflict_flags;
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek else
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek remote_add &= ~conflict_flags;
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek if (prefer_pvt_remote)
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek local_remove &= ~conflict_pvt_flags;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek else
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek remote_add &= ~conflict_pvt_flags;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek }
1e0fa55fb377db788e065de917ba8e149eb56161Jakub Hrozek
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek combined_add = local_add|remote_add;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek combined_remove = local_remove|remote_remove;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek i_assert((combined_add & combined_remove) == 0);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek /* don't change flags that are currently identical in both sides */
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek conflict_flags = local_final ^ remote_final;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek combined_add &= conflict_flags;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek combined_remove &= conflict_flags;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* see if there are conflicting final flags */
fd98a28d6e94080e52bbedc789b06606a6019b10Lukas Slebodnik local_wanted = (local_final|combined_add) & ~combined_remove;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik remote_wanted = (remote_final|combined_add) & ~combined_remove;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek conflict_flags = local_wanted ^ remote_wanted;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (conflict_flags != 0) {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (prefer_remote && prefer_pvt_remote)
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina local_wanted = remote_wanted;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina else if (prefer_remote && !prefer_pvt_remote) {
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina local_wanted = (local_wanted & pvt_mask) |
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina (remote_wanted & ~pvt_mask);
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina } else if (!prefer_remote && prefer_pvt_remote) {
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina local_wanted = (local_wanted & ~pvt_mask) |
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina (remote_wanted & pvt_mask);
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina }
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina }
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina *change_add_r = local_wanted & ~local_final;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina *change_remove_r = local_final & ~local_wanted;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina if ((local_wanted & ~pvt_mask) != (remote_final & ~pvt_mask))
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina *remote_changed = TRUE;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina if ((local_wanted & pvt_mask) != (remote_final & pvt_mask))
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina *remote_pvt_changed = TRUE;
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina}
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosestatic bool
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosekeyword_find(ARRAY_TYPE(const_string) *keywords, const char *name,
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose unsigned int *idx_r)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose{
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose const char *const *names;
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek unsigned int i, count;
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher names = array_get(keywords, &count);
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek for (i = 0; i < count; i++) {
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher if (strcmp(names[i], name) == 0) {
de5fa34860886ad68fba5e739987e16c342e8f14Lukas Slebodnik *idx_r = i;
de5fa34860886ad68fba5e739987e16c342e8f14Lukas Slebodnik return TRUE;
de5fa34860886ad68fba5e739987e16c342e8f14Lukas Slebodnik }
de5fa34860886ad68fba5e739987e16c342e8f14Lukas Slebodnik }
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek return FALSE;
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek}
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek
de5fa34860886ad68fba5e739987e16c342e8f14Lukas Slebodnikstatic void keywords_append(ARRAY_TYPE(const_string) *dest,
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek const ARRAY_TYPE(const_string) *keywords,
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt uint32_t bits, unsigned int start_idx)
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher{
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt const char *const *namep;
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek unsigned int i;
65ce66c43141f7e5c8482a8f8e7e217a23791588Petr Cech
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher for (i = 0; i < 32; i++) {
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek if ((bits & (1U << i)) == 0)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik continue;
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik namep = array_idx(keywords, start_idx+i);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose array_append(dest, namep, 1);
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bose }
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek}
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bosestatic void
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnikmerge_keywords(struct mail *mail, const ARRAY_TYPE(const_string) *local_changes,
8babbeee01e67893af4828ddfc922ecac0be4197Pavel Reichl const ARRAY_TYPE(const_string) *remote_changes,
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose bool prefer_remote,
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik bool *remote_changed, bool *remote_pvt_changed)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik{
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik /* local_changes and remote_changes are assumed to have no
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik duplicates names */
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose uint32_t *local_add, *local_remove, *local_final;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose uint32_t *remote_add, *remote_remove, *remote_final;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose uint32_t *change_add, *change_remove;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose ARRAY_TYPE(const_string) all_keywords, add_keywords, remove_keywords;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt const char *const *changes, *name, *const *local_keywords;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt struct mail_keywords *kw;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose unsigned int i, count, name_idx, array_size;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik
9c88f837ffacf6548c13825589b327de1a5525f3Sumit Bose local_keywords = mail_get_keywords(mail);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik /* we'll assign a common index for each keyword name and place
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik the changes to separate bit arrays. */
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose if (array_is_created(remote_changes))
e0c86d21388bffe2e3919e780780c40d96186abbJakub Hrozek changes = array_get(remote_changes, &count);
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose else {
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose changes = NULL;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose count = 0;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose }
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose array_size = str_array_length(local_keywords) + count;
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose if (array_is_created(local_changes))
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose array_size += array_count(local_changes);
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose if (array_size == 0) {
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose /* this message has no keywords */
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose return;
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose }
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose t_array_init(&all_keywords, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose t_array_init(&add_keywords, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose t_array_init(&remove_keywords, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose /* @UNSAFE: create large enough arrays to fit all keyword indexes. */
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose array_size = (array_size+31)/32;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose local_add = t_new(uint32_t, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose local_remove = t_new(uint32_t, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose local_final = t_new(uint32_t, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose remote_add = t_new(uint32_t, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose remote_remove = t_new(uint32_t, array_size);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose remote_final = t_new(uint32_t, array_size);
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose change_add = t_new(uint32_t, array_size);
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose change_remove = t_new(uint32_t, array_size);
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose /* get remote changes */
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose for (i = 0; i < count; i++) {
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose name = changes[i]+1;
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose name_idx = array_count(&all_keywords);
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose array_append(&all_keywords, &name, 1);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose switch (changes[i][0]) {
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose case KEYWORD_CHANGE_ADD:
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose remote_add[name_idx/32] |= 1U << (name_idx%32);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose break;
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose case KEYWORD_CHANGE_REMOVE:
1270ffe9f3809f2fd488ef4a320d344ae107ab87Sumit Bose remote_remove[name_idx/32] |= 1U << (name_idx%32);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose break;
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose case KEYWORD_CHANGE_FINAL:
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose remote_final[name_idx/32] |= 1U << (name_idx%32);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher break;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina case KEYWORD_CHANGE_ADD_AND_FINAL:
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina remote_add[name_idx/32] |= 1U << (name_idx%32);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina remote_final[name_idx/32] |= 1U << (name_idx%32);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina break;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina /* get local changes. use existing indexes for names when they exist. */
0bb98b7700b1b61f5b0a20b93279d5c2c391007fPavel Březina if (array_is_created(local_changes))
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina changes = array_get(local_changes, &count);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina else {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina changes = NULL;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina count = 0;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina for (i = 0; i < count; i++) {
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina name = changes[i]+1;
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina if (!keyword_find(&all_keywords, name, &name_idx)) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina name_idx = array_count(&all_keywords);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina array_append(&all_keywords, &name, 1);
36e262020c80479baa09b2c4c8dd045c7a0f32a1Pavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina switch (changes[i][0]) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina case KEYWORD_CHANGE_ADD:
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina case KEYWORD_CHANGE_ADD_AND_FINAL:
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina local_add[name_idx/32] |= 1U << (name_idx%32);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina break;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina case KEYWORD_CHANGE_REMOVE:
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina local_remove[name_idx/32] |= 1U << (name_idx%32);
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek break;
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek case KEYWORD_CHANGE_FINAL:
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek break;
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek for (i = 0; local_keywords[i] != NULL; i++) {
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek name = local_keywords[i];
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek if (!keyword_find(&all_keywords, name, &name_idx)) {
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek name_idx = array_count(&all_keywords);
6dcbfe52d5e64205c0d922f3e89add066b42c496Jakub Hrozek array_append(&all_keywords, &name, 1);
6dcbfe52d5e64205c0d922f3e89add066b42c496Jakub Hrozek }
8c829226ce0cf98c35ffce39a66f9645cff65767Jakub Hrozek local_final[name_idx/32] |= 1U << (name_idx%32);
8c829226ce0cf98c35ffce39a66f9645cff65767Jakub Hrozek }
8c829226ce0cf98c35ffce39a66f9645cff65767Jakub Hrozek i_assert(array_count(&all_keywords) <= array_size*32);
8c829226ce0cf98c35ffce39a66f9645cff65767Jakub Hrozek array_size = (array_count(&all_keywords)+31) / 32;
41291f19dbc5bf14f20729959b852fa605fcc02dJakub Hrozek
41291f19dbc5bf14f20729959b852fa605fcc02dJakub Hrozek /* merge keywords */
c23ea7772113a163139a7b7669303e9e80dc1d09Jakub Hrozek for (i = 0; i < array_size; i++) {
41291f19dbc5bf14f20729959b852fa605fcc02dJakub Hrozek merge_flags(local_final[i], local_add[i], local_remove[i],
41291f19dbc5bf14f20729959b852fa605fcc02dJakub Hrozek remote_final[i], remote_add[i], remote_remove[i],
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek 0, prefer_remote, prefer_remote,
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek &change_add[i], &change_remove[i],
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek remote_changed, remote_pvt_changed);
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek if (change_add[i] != 0) {
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek keywords_append(&add_keywords, &all_keywords,
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek change_add[i], i*32);
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek if (change_remove[i] != 0) {
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek keywords_append(&remove_keywords, &all_keywords,
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek change_remove[i], i*32);
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek /* apply changes */
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek if (array_count(&add_keywords) > 0) {
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek array_append_zero(&add_keywords);
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek kw = mailbox_keywords_create_valid(mail->box,
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek array_idx(&add_keywords, 0));
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek mail_update_keywords(mail, MODIFY_ADD, kw);
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek mailbox_keywords_unref(&kw);
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek if (array_count(&remove_keywords) > 0) {
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek array_append_zero(&remove_keywords);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter kw = mailbox_keywords_create_valid(mail->box,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter array_idx(&remove_keywords, 0));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter mail_update_keywords(mail, MODIFY_REMOVE, kw);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter mailbox_keywords_unref(&kw);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
769347ad4d35d43488eb98f980143495b0db415dStef Walterstatic void
769347ad4d35d43488eb98f980143495b0db415dStef Walterdsync_mailbox_import_replace_flags(struct mail *mail,
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek const struct dsync_mail_change *change)
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina{
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek ARRAY_TYPE(const_string) keywords;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter struct mail_keywords *kw;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *const *changes, *name;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter unsigned int i, count;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (array_is_created(&change->keyword_changes))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter changes = array_get(&change->keyword_changes, &count);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter else {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter changes = NULL;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter count = 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter t_array_init(&keywords, count+1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (i = 0; i < count; i++) {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter switch (changes[i][0]) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case KEYWORD_CHANGE_ADD:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case KEYWORD_CHANGE_FINAL:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case KEYWORD_CHANGE_ADD_AND_FINAL:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter name = changes[i]+1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter array_append(&keywords, &name, 1);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter case KEYWORD_CHANGE_REMOVE:
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter break;
29c5542feb4c45865ea61be97e0e84a1d1f04918Jakub Hrozek }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append_zero(&keywords);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher kw = mailbox_keywords_create_valid(mail->box, array_idx(&keywords, 0));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_update_keywords(mail, MODIFY_REPLACE, kw);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mailbox_keywords_unref(&kw);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos mail_update_flags(mail, MODIFY_REPLACE,
769347ad4d35d43488eb98f980143495b0db415dStef Walter change->add_flags | change->final_flags);
d2d8f342cd5e90bb9fd947c448492225f959aa86Pavel Březina if (mail_get_modseq(mail) < change->modseq)
d2d8f342cd5e90bb9fd947c448492225f959aa86Pavel Březina mail_update_modseq(mail, change->modseq);
d2d8f342cd5e90bb9fd947c448492225f959aa86Pavel Březina if (mail_get_pvt_modseq(mail) < change->pvt_modseq)
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina mail_update_pvt_modseq(mail, change->pvt_modseq);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnikstatic void
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherdsync_mailbox_import_flag_change(struct dsync_mailbox_importer *importer,
e369fc08906383e6d5c39832f31bb6600a33f887Simo Sorce const struct dsync_mail_change *change)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const struct dsync_mail_change *local_change;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_flags local_add, local_remove;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t change_add, change_remove;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint64_t new_modseq;
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher ARRAY_TYPE(const_string) local_keyword_changes = ARRAY_INIT;
8c3a4809b3420657289b42f028a1c9019b112991Stephen Gallagher struct mail *mail;
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce bool prefer_remote, prefer_pvt_remote;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool remote_changed = FALSE, remote_pvt_changed = FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert((change->add_flags & change->remove_flags) == 0);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
f427b36b0cecc426856ab3f77a9c684ac355659dSumit Bose if (importer->cur_mail != NULL &&
1a45124f3f300f9afdcb08eab0938e5e7d0534d9Sumit Bose importer->cur_mail->uid == change->uid) {
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce if (!dsync_check_cur_guid(importer, change))
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail = importer->cur_mail;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!dsync_import_set_mail(importer, change))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail = importer->mail;
a8d887323f83984679a7d9b827a70146656bb7b2Sumit Bose }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagher if (importer->revert_local_changes) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* dsync backup: just make the local look like remote. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dsync_mailbox_import_replace_flags(mail, change);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
300c772767c1b12077cac1d148ac89738b058f97Jan Zeleny
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek local_change = hash_table_lookup(importer->local_changes,
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce POINTER_CAST(change->uid));
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek if (local_change == NULL) {
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek local_add = local_remove = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina local_add = local_change->add_flags;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina local_remove = local_change->remove_flags;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina local_keyword_changes = local_change->keyword_changes;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina }
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (mail_get_modseq(mail) < change->modseq)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina prefer_remote = TRUE;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina else if (mail_get_modseq(mail) > change->modseq)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina prefer_remote = FALSE;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina else {
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce /* identical modseq, we'll just have to pick one.
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik Note that both brains need to pick the same one, otherwise
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina they become unsynced. */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina prefer_remote = !importer->master_brain;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek }
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if (mail_get_pvt_modseq(mail) < change->pvt_modseq)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek prefer_pvt_remote = TRUE;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek else if (mail_get_pvt_modseq(mail) > change->pvt_modseq)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek prefer_pvt_remote = FALSE;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek else
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek prefer_pvt_remote = !importer->master_brain;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce /* merge flags */
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik merge_flags(mail_get_flags(mail), local_add, local_remove,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek change->final_flags, change->add_flags, change->remove_flags,
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek mailbox_get_private_flags_mask(mail->box),
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta prefer_remote, prefer_pvt_remote,
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta &change_add, &change_remove,
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta &remote_changed, &remote_pvt_changed);
b42b5d5aaf4da165582e73ad985fdff6e34e61e4Jakub Hrozek
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta if (change_add != 0)
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose mail_update_flags(mail, MODIFY_ADD, change_add);
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose if (change_remove != 0)
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta mail_update_flags(mail, MODIFY_REMOVE, change_remove);
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose /* merge keywords */
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce merge_keywords(mail, &local_keyword_changes, &change->keyword_changes,
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose prefer_remote, &remote_changed, &remote_pvt_changed);
4de84af23db74e13e867985c9093f394c9fa8d51Sumit Bose
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta /* update modseqs. try to anticipate when we have to increase modseq
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta to get it closer to what remote has (although we can't guess it
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose exactly correctly) */
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose new_modseq = change->modseq;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (remote_changed && new_modseq <= importer->remote_highest_modseq)
d0d7de66c9494621c1bc12384e41e5e38a77fbebSumit Bose new_modseq = importer->remote_highest_modseq+1;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (mail_get_modseq(mail) < new_modseq)
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose mail_update_modseq(mail, new_modseq);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose new_modseq = change->pvt_modseq;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (remote_pvt_changed && new_modseq <= importer->remote_highest_pvt_modseq)
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose new_modseq = importer->remote_highest_pvt_modseq+1;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (mail_get_pvt_modseq(mail) < new_modseq)
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose mail_update_pvt_modseq(mail, new_modseq);
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce}
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikstatic bool
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bosedsync_mail_change_have_keyword(const struct dsync_mail_change *change,
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek const char *keyword)
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek{
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek const char *const *strp;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek if (!array_is_created(&change->keyword_changes))
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina return FALSE;
2b7ef850846029641cc59560c2d8d4ab7254dda5Pavel Březina
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek array_foreach(&change->keyword_changes, strp) {
590582be38cdbfde387fcc57df92903d48c5a083Jakub Hrozek switch ((*strp)[0]) {
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina case KEYWORD_CHANGE_FINAL:
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina case KEYWORD_CHANGE_ADD_AND_FINAL:
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina if (strcasecmp((*strp)+1, keyword) == 0)
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina return TRUE;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek break;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek default:
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek break;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek }
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek }
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce return FALSE;
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose}
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bosestatic bool
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozekdsync_mailbox_import_want_change(struct dsync_mailbox_importer *importer,
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek const struct dsync_mail_change *change,
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek const char **result_r)
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek{
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina if (importer->sync_since_timestamp > 0) {
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina i_assert(change->received_timestamp > 0);
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina if (change->received_timestamp < importer->sync_since_timestamp) {
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina /* mail has too old timestamp - skip it */
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina *result_r = "Ignoring missing local mail with too old timestamp";
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek return FALSE;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (importer->sync_until_timestamp > 0) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce i_assert(change->received_timestamp > 0);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (change->received_timestamp > importer->sync_until_timestamp) {
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce /* mail has too new timestamp - skip it */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce *result_r = "Ignoring missing local mail with too new timestamp";
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce return FALSE;
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce if (importer->sync_max_size > 0) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce i_assert(change->virtual_size != (uoff_t)-1);
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (change->virtual_size < importer->sync_max_size) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce /* mail is too large - skip it */
1dd679584241a0f9b29072c7eed1c5c5e4a577e4Simo Sorce *result_r = "Ignoring missing local mail with too large size";
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce return FALSE;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce }
8f2a34cc6964a1f80a1434e05315a7ae0bb5774eSimo Sorce if (importer->sync_flag != 0) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce bool have_flag = (change->final_flags & importer->sync_flag) != 0;
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce if (have_flag && importer->sync_flag_dontwant) {
a8d1a344e580f29699aed9b88d87fc3c6f5d113bSimo Sorce *result_r = "Ignoring missing local mail that doesn't have wanted flags";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
376eaf187c13c2a1eaea0ffbdd970b6b563ab74cPetr Cech if (!have_flag && !importer->sync_flag_dontwant) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Ignoring missing local mail that has unwanted flags";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
0429e21a45aa26c133cb4d8285a60446a0611e44Pavel Březina }
3b99f7a97553a0a357d50abe507d4f0060c4eceaPavel Březina if (importer->sync_keyword != NULL) {
38b2bd97e41388995594126ea4e6b7c55ea0eb5cPavel Březina bool have_kw = dsync_mail_change_have_keyword(change, importer->sync_keyword);
769347ad4d35d43488eb98f980143495b0db415dStef Walter
769347ad4d35d43488eb98f980143495b0db415dStef Walter if (have_kw && importer->sync_flag_dontwant) {
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina *result_r = "Ignoring missing local mail that doesn't have wanted keywords";
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina return FALSE;
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina }
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina if (!have_kw && !importer->sync_flag_dontwant) {
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina *result_r = "Ignoring missing local mail that has unwanted keywords";
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina return FALSE;
586fa3571753ab4a607d40fc31503fc0e8effd70Pavel Březina }
bf83a0faacf16196ab9bd37dcf6190b4209ccaf7Pavel Březina }
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina return TRUE;
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina}
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březina
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březinastatic void
d3dee2a07f1a8ee9ae6f94e149ced754ef76c248Pavel Březinadsync_mailbox_import_save(struct dsync_mailbox_importer *importer,
a1bf79449204ce9a5392b9d09b953a6bdf53a122Pavel Březina const struct dsync_mail_change *change)
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina{
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina struct dsync_mail_change *save;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina const char *result;
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina i_assert(change->guid != NULL);
dea636af4d1902a081ee891f1b19ee2f8729d759Pavel Březina
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (change->uid == importer->last_common_uid) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher /* we've already verified that the GUID matches.
ccf340e56364851f2e5b75e52d3d63701b662954Lukas Slebodnik apply flag changes if there are any. */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher i_assert(!importer->last_common_uid_found);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher dsync_mailbox_import_flag_change(importer, change);
2db6afe70eee2bbc22aa657a6b6609a9f3eb5d4cSimo Sorce return;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!dsync_mailbox_import_want_change(importer, change, &result))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
2db6afe70eee2bbc22aa657a6b6609a9f3eb5d4cSimo Sorce
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher save = p_new(importer->pool, struct dsync_mail_change, 1);
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek dsync_mail_change_dup(importer->pool, change, save);
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek
52e0894fd65bff4715c88330eb62b28e1635228fStephen Gallagher if (importer->last_common_uid_found) {
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher /* this is a new mail. its UID may or may not conflict with
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek an existing local mail, we'll figure it out later. */
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek i_assert(change->uid > importer->last_common_uid);
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek dsync_mailbox_save(importer, save);
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* the local mail is expunged. we'll decide later if we want
8a07521b413a3b5879f824e1872c5770c92ee5c0Stephen Gallagher to save this mail locally or expunge it form remote. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(change->uid > importer->last_common_uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(importer->cur_mail == NULL ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher change->uid < importer->cur_mail->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append(&importer->maybe_saves, &save, 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagherdsync_mailbox_import_expunge(struct dsync_mailbox_importer *importer,
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher const struct dsync_mail_change *change)
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher{
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher if (importer->last_common_uid_found) {
59744cff6edb106ae799b2321cb8731edadf409aStephen Gallagher /* expunge the message, unless its GUID unexpectedly doesn't
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher match */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(change->uid <= importer->last_common_uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (dsync_import_set_mail(importer, change))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mail_expunge(importer->mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (importer->cur_mail == NULL ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher change->uid < importer->cur_mail->uid) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* already expunged locally, we can ignore this.
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik uid=last_common_uid if we managed to verify from
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek transaction log that the GUIDs match */
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek i_assert(change->uid >= importer->last_common_uid);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek } else if (change->uid == importer->last_common_uid) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* already verified that the GUID matches */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(importer->cur_mail->uid == change->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (dsync_check_cur_guid(importer, change))
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek mail_expunge(importer->cur_mail);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* we don't know yet if we should expunge this
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt message or not. queue it until we do. */
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek i_assert(change->uid > importer->last_common_uid);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek seq_range_array_add(&importer->maybe_expunge_uids, change->uid);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek }
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce}
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdsync_mailbox_rewind_search(struct dsync_mailbox_importer *importer)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* If there are local mails after last_common_uid which we skipped
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while trying to match the next message, we need to now go back */
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (importer->cur_mail != NULL &&
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik importer->cur_mail->uid <= importer->last_common_uid+1)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_mail = NULL;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek importer->cur_guid = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_hdr_hash = NULL;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik importer->next_local_seq = 0;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
a9eff330a7fbd231e8cc28a6828a1e5014ddb0d2Michal Zidek (void)mailbox_search_deinit(&importer->search_ctx);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt dsync_mailbox_import_search_init(importer);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozekdsync_mailbox_common_uid_found(struct dsync_mailbox_importer *importer)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik struct dsync_mail_change *const *saves;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt struct seq_range_iter iter;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek unsigned int n, i, count;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek uint32_t uid;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt if (importer->debug) T_BEGIN {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher string_t *expunges = t_str_new(64);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imap_write_seq_range(expunges, &importer->maybe_expunge_uids);
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek imp_debug(importer, "Last common UID=%u. Delayed expunges=%s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->last_common_uid, str_c(expunges));
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik } T_END;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek importer->last_common_uid_found = TRUE;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt dsync_mailbox_rewind_search(importer);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* expunge the messages whose expunge-decision we delayed previously */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher seq_range_array_iter_init(&iter, &importer->maybe_expunge_uids); n = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while (seq_range_array_iter_nth(&iter, n++, &uid)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (uid > importer->last_common_uid) {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* we expunge messages only up to last_common_uid,
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik ignore the rest */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny }
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek if (mail_set_uid(importer->mail, uid))
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny mail_expunge(importer->mail);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek /* handle pending saves */
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt saves = array_get(&importer->maybe_saves, &count);
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny for (i = 0; i < count; i++) {
f1828234a850dd28465425248a83a993f262918fPavel Březina if (saves[i]->uid > importer->last_common_uid) {
f1828234a850dd28465425248a83a993f262918fPavel Březina imp_debug(importer, "Delayed save UID=%u: Save",
f1828234a850dd28465425248a83a993f262918fPavel Březina saves[i]->uid);
f1828234a850dd28465425248a83a993f262918fPavel Březina dsync_mailbox_save(importer, saves[i]);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik } else {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik imp_debug(importer, "Delayed save UID=%u: Ignore",
f1828234a850dd28465425248a83a993f262918fPavel Březina saves[i]->uid);
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay }
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay }
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay}
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikstatic int
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikdsync_mailbox_import_match_msg(struct dsync_mailbox_importer *importer,
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay const struct dsync_mail_change *change,
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek const char **result_r)
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek{
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek const char *hdr_hash, *cmp_guid;
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek if (*change->guid != '\0' && *importer->cur_guid != '\0') {
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek /* we have GUIDs, verify them */
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek if (dsync_mail_change_guid_equals(importer, change,
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek importer->cur_guid, &cmp_guid)) {
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek *result_r = "GUIDs match";
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina return 1;
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina } else {
23fb01bf67a6058fb508da6d81515e8b18634bebPavel Březina *result_r = t_strdup_printf("GUIDs don't match (%s vs %s)",
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina importer->cur_guid, cmp_guid);
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina return 0;
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina }
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina }
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina /* verify hdr_hash if it exists */
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina if (change->hdr_hash == NULL) {
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina i_assert(*importer->cur_guid == '\0');
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina if (change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE) {
b69cb1787209e85cc246eb9a944242689bfe0c46Pavel Březina /* the message was already expunged, so we don't know
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina its header. return "unknown". */
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina *result_r = "Unknown match for expunge";
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return -1;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina i_error("Mailbox %s: GUIDs not supported, "
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina "sync with header hashes instead",
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina mailbox_get_vname(importer->box));
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina importer->mail_error = MAIL_ERROR_TEMP;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina importer->failed = TRUE;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina *result_r = "Error, invalid parameters";
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return -1;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina if (dsync_mail_get_hdr_hash(importer->cur_mail,
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina importer->hdr_hash_version, &hdr_hash) < 0) {
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina dsync_mail_error(importer, importer->cur_mail, "hdr-stream");
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina *result_r = "Error fetching header stream";
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina return -1;
e157b9f6cb370e1b94bcac2044d26ad66d640fbaPavel Březina }
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina if (importer->empty_hdr_workaround &&
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina (dsync_mail_hdr_hash_is_empty(change->hdr_hash) ||
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina dsync_mail_hdr_hash_is_empty(hdr_hash))) {
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina *result_r = "Empty headers found with workaround enabled - assuming a match";
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina return 1;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek } else if (strcmp(change->hdr_hash, hdr_hash) == 0) {
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina *result_r = "Headers hashes match";
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt return 1;
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina } else {
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina *result_r = t_strdup_printf("Headers hashes don't match (%s vs %s)",
558998ce664055a75595371118f818084d8f2b23Jan Cholasta change->hdr_hash, hdr_hash);
558998ce664055a75595371118f818084d8f2b23Jan Cholasta return 0;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta }
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta}
558998ce664055a75595371118f818084d8f2b23Jan Cholasta
558998ce664055a75595371118f818084d8f2b23Jan Cholastastatic bool
558998ce664055a75595371118f818084d8f2b23Jan Cholastadsync_mailbox_find_common_expunged_uid(struct dsync_mailbox_importer *importer,
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt const struct dsync_mail_change *change,
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt const char **result_r)
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta{
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta const struct dsync_mail_change *local_change;
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta if (*change->guid == '\0') {
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* remote doesn't support GUIDs, can't verify expunge */
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta *result_r = "GUIDs not supported, can't verify expunge";
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta return FALSE;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt }
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
558998ce664055a75595371118f818084d8f2b23Jan Cholasta /* local message is expunged. see if we can find its GUID from
558998ce664055a75595371118f818084d8f2b23Jan Cholasta transaction log and check if the GUIDs match. The GUID in
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher log is a 128bit GUID, so we may need to convert the remote's
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher GUID string to 128bit GUID first. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher local_change = hash_table_lookup(importer->local_changes,
6e973aa578a692b2e7597811dfdfdb1a442c85f8Nikolai Kondrashov POINTER_CAST(change->uid));
62b20154899f847e760d6dfbae6a32fb45b448deLukas Slebodnik if (local_change == NULL || local_change->guid == NULL) {
cbff3fcdce5b0377a62fbe74f32e476efbf7ca9cNikolai Kondrashov *result_r = "Expunged local mail's GUID not found";
6e973aa578a692b2e7597811dfdfdb1a442c85f8Nikolai Kondrashov return FALSE;
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose }
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek i_assert(local_change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE);
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose if (dsync_mail_change_guid_equals(importer, local_change,
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose change->guid, NULL)) {
f74d7744f1b12fe0492eadfc8cf30afcb4092e40Lukas Slebodnik importer->last_common_uid = change->uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Expunged local mail's GUID matches remote";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (change->type != DSYNC_MAIL_CHANGE_TYPE_EXPUNGE) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dsync_mailbox_common_uid_found(importer);
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik *result_r = "Expunged local mail's GUID doesn't match remote GUID";
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik } else {
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik /* GUID mismatch for two expunged mails. dsync can't update
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher GUIDs for already expunged messages, so we can't immediately
221619d8e8d7cf269c55482e5f466f6511ed35adLukas Slebodnik determine that the rest of the messages are a mismatch. so
25c394fc9d09aa7f58700e67b942aba86505934aLukas Slebodnik for now we'll just skip over this pair. */
af820c9fc6aa1768e2e6b0df78fb489dbb1b28d0Pavel Březina *result_r = "Expunged mails' GUIDs don't match - delaying decision";
af820c9fc6aa1768e2e6b0df78fb489dbb1b28d0Pavel Březina /* NOTE: the return value here doesn't matter, because the only
af820c9fc6aa1768e2e6b0df78fb489dbb1b28d0Pavel Březina caller that checks for it never reaches this code path */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
f74d7744f1b12fe0492eadfc8cf30afcb4092e40Lukas Slebodnikdsync_mailbox_revert_missing(struct dsync_mailbox_importer *importer,
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik const struct dsync_mail_change *change)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik{
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik i_assert(importer->revert_local_changes);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik /* mail exists on remote, but not locally. we'll need to
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose insert this mail back, which means deleting the whole
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose mailbox and resyncing. */
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose i_warning("Deleting mailbox '%s': UID=%u GUID=%s is missing locally",
1d1a0a019d8d4d9ab0f51ada03604cd2cada287eSumit Bose mailbox_get_vname(importer->box),
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik change->uid, change->guid);
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik importer->delete_mailbox = TRUE;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce importer->mail_error = MAIL_ERROR_TEMP;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce importer->failed = TRUE;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce}
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorcestatic void
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorcedsync_mailbox_find_common_uid(struct dsync_mailbox_importer *importer,
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce const struct dsync_mail_change *change,
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce const char **result_r)
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce{
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce int ret;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce i_assert(change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE ||
1116fbbf0e50827841a6bafd80c027c3d3548c1fLukas Slebodnik ((change->received_timestamp > 0 ||
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce (importer->sync_since_timestamp == 0 &&
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce importer->sync_until_timestamp == 0)) &&
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce (change->virtual_size != (uoff_t)-1 || importer->sync_max_size == 0)));
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce /* try to find the matching local mail */
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik if (!importer_next_mail(importer, change->uid)) {
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik /* no more local mails. we can still try to match
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik expunged mails though. */
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik if (change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE) {
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik /* mail doesn't exist remotely either, don't bother
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik looking it up locally. */
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik *result_r = "Expunged mail not found locally";
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik return;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik }
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik i_assert(change->guid != NULL);
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik if (!dsync_mailbox_import_want_change(importer, change, result_r))
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik ;
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik else if (importer->local_uid_next <= change->uid) {
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik dsync_mailbox_common_uid_found(importer);
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik *result_r = "Mail's UID is above local UIDNEXT";
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik } else if (importer->revert_local_changes) {
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik dsync_mailbox_revert_missing(importer, change);
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik *result_r = "Reverting local change by deleting mailbox";
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce } else if (!dsync_mailbox_find_common_expunged_uid(importer, change, result_r)) {
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce /* it's unknown if this mail existed locally and was
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce expunged. since we don't want to lose any mails,
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce assume that we need to preserve the mail. use the
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce last message with a matching GUID as the last common
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce UID. */
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce dsync_mailbox_common_uid_found(importer);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce }
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce *result_r = t_strdup_printf("%s - No more local mails found", *result_r);
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek return;
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek }
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek if (change->guid == NULL) {
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek /* we can't know if this UID matches */
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek i_assert(change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE);
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek *result_r = "Expunged mail has no GUID, can't verify it";
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek return;
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek }
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek if (importer->cur_mail->uid == change->uid) {
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek /* we have a matching local UID. check GUID to see if it's
4b39208286ca0351ee76d4e64e077e7ad5ca8568Jakub Hrozek really the same mail or not */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((ret = dsync_mailbox_import_match_msg(importer, change, result_r)) < 0) {
16c351625346b3193e1762027e5215ab76042127Sumit Bose /* unknown */
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek return;
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek }
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek if (ret > 0) {
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek importer->last_common_uid = change->uid;
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek } else if (!importer->revert_local_changes) {
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek /* mismatch - found the first non-common UID */
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek dsync_mailbox_common_uid_found(importer);
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek } else {
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek /* mismatch and we want to revert local changes -
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik need to delete the mailbox. */
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek dsync_mailbox_revert_existing_uid(importer, change->uid, *result_r);
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* mail exists remotely, but doesn't exist locally. */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!dsync_mailbox_import_want_change(importer, change, result_r))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (importer->revert_local_changes &&
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher change->type != DSYNC_MAIL_CHANGE_TYPE_EXPUNGE) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dsync_mailbox_revert_missing(importer, change);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = "Reverting local change by deleting mailbox";
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher (void)dsync_mailbox_find_common_expunged_uid(importer, change, result_r);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r = t_strdup_printf("%s (next local mail UID=%u)",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *result_r, importer->cur_mail == NULL ? 0 : importer->cur_mail->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint dsync_mailbox_import_change(struct dsync_mailbox_importer *importer,
291a6c8af9759e41cec6f332cb72606ca90768c3Pavel Březina const struct dsync_mail_change *change)
5843ad321944a028f6dee7e1fd4f9381c4953d07Sumit Bose{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *result;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(!importer->new_uids_assigned);
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek i_assert(importer->prev_uid < change->uid);
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek importer->prev_uid = change->uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (importer->failed)
22091abbe7b4a5667f62603dfd875e9ec6adf789Alexey Shabalin return -1;
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik if (importer->require_full_resync)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!importer->last_common_uid_found) {
c8b8901b05da9e31dba320f305ec20301e928cfbSumit Bose result = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dsync_mailbox_find_common_uid(importer, change, &result);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik i_assert(result != NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher result = "New mail";
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imp_debug(importer, "Import change type=%s GUID=%s UID=%u hdr_hash=%s result=%s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dsync_mail_change_type_names[change->type],
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher change->guid != NULL ? change->guid : "<unknown>", change->uid,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher change->hdr_hash != NULL ? change->hdr_hash : "", result);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (importer->failed)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (importer->require_full_resync)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (importer->last_common_uid_found) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* a) uid <= last_common_uid for flag changes and expunges.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher this happens only when last_common_uid was originally given
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher as parameter to importer.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher when we're finding the last_common_uid ourself,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uid>last_common_uid always in here, because
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher last_common_uid_found=TRUE only after we find the first
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher mismatch.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher b) uid > last_common_uid for i) new messages, ii) expunges
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher that were sent "just in case" */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (change->uid <= importer->last_common_uid) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(change->type != DSYNC_MAIL_CHANGE_TYPE_SAVE);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE) {
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek /* ignore */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(change->type == DSYNC_MAIL_CHANGE_TYPE_SAVE);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* a) uid < last_common_uid can never happen */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(change->uid >= importer->last_common_uid);
22d381367c27910fe82f476a76b9f4ede555e35aLukas Slebodnik /* b) uid = last_common_uid if we've verified that the
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik messages' GUIDs match so far.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c) uid > last_common_uid: i) TYPE_EXPUNGE change has
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher GUID=NULL, so we couldn't verify yet if it matches our
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher local message, ii) local message is expunged and we couldn't
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher find its GUID */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (change->uid > importer->last_common_uid) {
2de495aed26bf75a750a76ca73b9f85d341fe1c5Pavel Březina i_assert(change->type == DSYNC_MAIL_CHANGE_TYPE_EXPUNGE ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->cur_mail == NULL ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher change->uid < importer->cur_mail->uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher switch (change->type) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case DSYNC_MAIL_CHANGE_TYPE_SAVE:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dsync_mailbox_import_save(importer, change);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik case DSYNC_MAIL_CHANGE_TYPE_EXPUNGE:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher dsync_mailbox_import_expunge(importer, change);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher case DSYNC_MAIL_CHANGE_TYPE_FLAG_CHANGE:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(importer->last_common_uid_found);
e3c06950bdb0bee6df603b101b30b75ef38439a4Lukas Slebodnik dsync_mailbox_import_flag_change(importer, change);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher break;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return importer->failed ? -1 : 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherimporter_new_mail_final_uid_cmp(struct importer_new_mail *const *newmail1,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct importer_new_mail *const *newmail2)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((*newmail1)->final_uid < (*newmail2)->final_uid)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
e3c06950bdb0bee6df603b101b30b75ef38439a4Lukas Slebodnik if ((*newmail1)->final_uid > (*newmail2)->final_uid)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdsync_mailbox_import_assign_new_uids(struct dsync_mailbox_importer *importer)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct importer_new_mail *newmail, *const *newmailp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t common_uid_next, new_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher common_uid_next = I_MAX(importer->local_uid_next,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->remote_uid_next);
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek array_foreach_modifiable(&importer->newmails, newmailp) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher newmail = *newmailp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (newmail->skip) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* already assigned */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(newmail->final_uid != 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher continue;
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce }
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* figure out what UID to use for the mail */
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (newmail->uid_is_usable) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* keep the UID */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher new_uid = newmail->final_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (newmail->link != NULL &&
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce newmail->link->uid_is_usable) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we can use the linked message's UID and expunge
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher this mail */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher new_uid = newmail->link->final_uid;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i_assert(!importer->revert_local_changes);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher new_uid = common_uid_next++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imp_debug(importer, "UID %u isn't usable, assigning new UID %u",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher newmail->final_uid, new_uid);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik newmail->final_uid = new_uid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (newmail->link != NULL && newmail->link != newmail) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* skip processing the linked mail */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher newmail->link->skip = TRUE;
35872dc24058c5e8028cb4082fd405a27835dcd1Jakub Hrozek }
fcb8e3f1f49bb34c409d8dbd75889eb72be05517Jakub Hrozek }
fcb8e3f1f49bb34c409d8dbd75889eb72be05517Jakub Hrozek importer->last_common_uid = common_uid_next-1;
fb83de0699b16e7d8eca803305e2112795807b4cJakub Hrozek importer->new_uids_assigned = TRUE;
f7ea0b1d46197275c87bdc73a6e38a6fd7f855eePavel Březina /* Sort the newmails by their final_uid. This is used for tracking
9e6f8d1c66b4b3543bab67d807bd26f1d6256c75Pavel Březina whether an intermediate commit is allowed. */
676bf6dda60776d9db79dad1c2506c0e57bb5503Pavel Březina array_sort(&importer->newmails, importer_new_mail_final_uid_cmp);
291a6c8af9759e41cec6f332cb72606ca90768c3Pavel Březina}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
fcb8e3f1f49bb34c409d8dbd75889eb72be05517Jakub Hrozekstatic int
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdsync_mailbox_import_local_uid(struct dsync_mailbox_importer *importer,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail *mail, uint32_t uid, const char *guid,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct dsync_mail *dmail_r)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *error_field, *errstr;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher enum mail_error error;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
fb83de0699b16e7d8eca803305e2112795807b4cJakub Hrozek if (!mail_set_uid(mail, uid))
c51f7a064b0d7ef86110bdeb6dc09fa6c08be7d3Jakub Hrozek return 0;
d12c95d840ed5de7f34e21002943c48e711a33f4Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* NOTE: Errors are logged, but they don't cause the entire import
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher to fail. */
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (dsync_mail_fill(mail, TRUE, dmail_r, &error_field) < 0) {
f7ea0b1d46197275c87bdc73a6e38a6fd7f855eePavel Březina errstr = mailbox_get_last_internal_error(mail->box, &error);
9e6f8d1c66b4b3543bab67d807bd26f1d6256c75Pavel Březina if (error == MAIL_ERROR_EXPUNGED)
291a6c8af9759e41cec6f332cb72606ca90768c3Pavel Březina return 0;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher i_error("Mailbox %s: Can't lookup %s for UID=%u: %s",
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher mailbox_get_vname(importer->box),
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher error_field, uid, errstr);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher return -1;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (*guid != '\0' && strcmp(guid, dmail_r->guid) != 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher dsync_import_unexpected_state(importer, t_strdup_printf(
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher "Unexpected GUID mismatch (3) for UID=%u: %s != %s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uid, dmail_r->guid, guid));
5a5c5cdeb92f4012fc75fd717bfea06598f68f12Pavel Reichl return -1;
5a5c5cdeb92f4012fc75fd717bfea06598f68f12Pavel Reichl }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
5a5c5cdeb92f4012fc75fd717bfea06598f68f12Pavel Reichl
5a5c5cdeb92f4012fc75fd717bfea06598f68f12Pavel Reichlstatic void
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherdsync_mailbox_import_saved_uid(struct dsync_mailbox_importer *importer,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher uint32_t uid)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik i_assert(importer->search_ctx == NULL);
5a5c5cdeb92f4012fc75fd717bfea06598f68f12Pavel Reichl
5a5c5cdeb92f4012fc75fd717bfea06598f68f12Pavel Reichl if (importer->highest_wanted_uid < uid)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher importer->highest_wanted_uid = uid;
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter array_append(&importer->wanted_uids, &uid, 1);
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter}
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walterstatic void
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walterdsync_mailbox_import_update_first_saved(struct dsync_mailbox_importer *importer)
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter{
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter struct importer_new_mail *const *newmails;
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter unsigned int count;
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter newmails = array_get(&importer->newmails, &count);
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter while (importer->first_unsaved_idx < count) {
fe60346714a73ac3987f786731389320633dd245Pavel Březina if (!newmails[importer->first_unsaved_idx]->saved)
2de495aed26bf75a750a76ca73b9f85d341fe1c5Pavel Březina break;
2de495aed26bf75a750a76ca73b9f85d341fe1c5Pavel Březina importer->first_unsaved_idx++;
fe60346714a73ac3987f786731389320633dd245Pavel Březina }
fe60346714a73ac3987f786731389320633dd245Pavel Březina}
fe60346714a73ac3987f786731389320633dd245Pavel Březina
fe60346714a73ac3987f786731389320633dd245Pavel Březinastatic void
fe60346714a73ac3987f786731389320633dd245Pavel Březinadsync_mailbox_import_saved_newmail(struct dsync_mailbox_importer *importer,
fe60346714a73ac3987f786731389320633dd245Pavel Březina struct importer_new_mail *newmail)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik{
fe60346714a73ac3987f786731389320633dd245Pavel Březina dsync_mailbox_import_saved_uid(importer, newmail->final_uid);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek newmail->saved = TRUE;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek dsync_mailbox_import_update_first_saved(importer);
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek importer->saves_since_commit++;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek /* we can commit only if all the upcoming mails will have UIDs that
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek are larger than we're committing.
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
8f61739e0de45ce2ee3be436fc91ef12a1a1c4f3Lukas Slebodnik Note that if any existing UIDs have been changed, the new UID is
8f61739e0de45ce2ee3be436fc91ef12a1a1c4f3Lukas Slebodnik usually higher than anything that is being saved so we can't do
8f61739e0de45ce2ee3be436fc91ef12a1a1c4f3Lukas Slebodnik an intermediate commit. It's too much extra work to try to handle
8f61739e0de45ce2ee3be436fc91ef12a1a1c4f3Lukas Slebodnik that situation. So here this never happens, because then
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek array_count(wanted_uids) is always higher than first_unsaved_idx. */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (importer->saves_since_commit >= importer->commit_msgs_interval &&
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher importer->first_unsaved_idx == array_count(&importer->wanted_uids)) {
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (dsync_mailbox_import_commit(importer, FALSE) < 0)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher importer->failed = TRUE;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher importer->saves_since_commit = 0;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher }
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher}
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherstatic bool
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagherdsync_msg_change_uid(struct dsync_mailbox_importer *importer,
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher uint32_t old_uid, uint32_t new_uid)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher{
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose struct mail_save_context *save_ctx;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose IMPORTER_DEBUG_CHANGE(importer);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (!mail_set_uid(importer->mail, old_uid))
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose return FALSE;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose save_ctx = mailbox_save_alloc(importer->ext_trans);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose mailbox_save_copy_flags(save_ctx, importer->mail);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose mailbox_save_set_uid(save_ctx, new_uid);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (mailbox_move(&save_ctx, importer->mail) < 0)
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose return FALSE;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose dsync_mailbox_import_saved_uid(importer, new_uid);
e7ccfb139388c947ec2dee16cfe3005f5643b90dPetr Cech return TRUE;
56c9f8731173eae841a05f31bb03d311076a8485Petr Cech}
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bosestatic bool
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březinadsync_mailbox_import_change_uid(struct dsync_mailbox_importer *importer,
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březina ARRAY_TYPE(seq_range) *unwanted_uids,
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březina uint32_t wanted_uid)
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose{
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose const struct seq_range *range;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose unsigned int count, n;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose struct seq_range_iter iter;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose uint32_t uid;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* optimize by first trying to use the latest UID */
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce range = array_get(unwanted_uids, &count);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (count == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return FALSE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (dsync_msg_change_uid(importer, range[count-1].seq2, wanted_uid)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher seq_range_array_remove(unwanted_uids, range[count-1].seq2);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mailbox_get_last_mail_error(importer->box) == MAIL_ERROR_EXPUNGED)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher seq_range_array_remove(unwanted_uids, range[count-1].seq2);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* now try to use any of them by iterating through them. (would be
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek easier&faster to just iterate backwards, but probably too much
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek trouble to add such API) */
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek n = 0; seq_range_array_iter_init(&iter, unwanted_uids);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek while (seq_range_array_iter_nth(&iter, n++, &uid)) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (dsync_msg_change_uid(importer, uid, wanted_uid)) {
291a6c8af9759e41cec6f332cb72606ca90768c3Pavel Březina seq_range_array_remove(unwanted_uids, uid);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return TRUE;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (mailbox_get_last_mail_error(importer->box) == MAIL_ERROR_EXPUNGED)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek seq_range_array_remove(unwanted_uids, uid);
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek }
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek return FALSE;
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic bool
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekdsync_mailbox_import_try_local(struct dsync_mailbox_importer *importer,
22091abbe7b4a5667f62603dfd875e9ec6adf789Alexey Shabalin struct importer_new_mail *all_newmails,
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik ARRAY_TYPE(seq_range) *local_uids,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek ARRAY_TYPE(seq_range) *wanted_uids)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek ARRAY_TYPE(seq_range) assigned_uids, unwanted_uids;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek struct seq_range_iter local_iter, wanted_iter;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek unsigned int local_n, wanted_n;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik uint32_t local_uid, wanted_uid;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek struct importer_new_mail *mail;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek struct dsync_mail dmail;
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek if (array_count(local_uids) == 0)
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter return FALSE;
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter local_n = wanted_n = 0;
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter seq_range_array_iter_init(&local_iter, local_uids);
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter seq_range_array_iter_init(&wanted_iter, wanted_uids);
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter /* wanted_uids contains UIDs that need to exist at the end. those that
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter don't already exist in local_uids have a higher UID than any
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter existing local UID */
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter t_array_init(&assigned_uids, array_count(wanted_uids));
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter t_array_init(&unwanted_uids, 8);
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina while (seq_range_array_iter_nth(&local_iter, local_n++, &local_uid)) {
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina if (seq_range_array_iter_nth(&wanted_iter, wanted_n,
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina &wanted_uid)) {
7ac503a73a26abe49f9f7d175c74df705380898dPavel Březina if (local_uid == wanted_uid) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* we have exactly the UID we want. keep it. */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter seq_range_array_add(&assigned_uids, wanted_uid);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter wanted_n++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter continue;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter i_assert(local_uid < wanted_uid);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek /* we no longer want this local UID. */
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek seq_range_array_add(&unwanted_uids, local_uid);
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina }
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina /* reuse as many existing messages as possible by changing their UIDs */
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina while (seq_range_array_iter_nth(&wanted_iter, wanted_n, &wanted_uid)) {
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina if (!dsync_mailbox_import_change_uid(importer, &unwanted_uids,
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina wanted_uid))
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina break;
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina seq_range_array_add(&assigned_uids, wanted_uid);
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina wanted_n++;
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina }
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina /* expunge all unwanted messages */
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina local_n = 0; seq_range_array_iter_init(&local_iter, &unwanted_uids);
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina while (seq_range_array_iter_nth(&local_iter, local_n++, &local_uid)) {
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina IMPORTER_DEBUG_CHANGE(importer);
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina if (mail_set_uid(importer->mail, local_uid))
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina mail_expunge(importer->mail);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek }
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek /* mark mails whose UIDs we got to be skipped over later */
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek for (mail = all_newmails; mail != NULL; mail = mail->next) {
c440c424443517b12afa8d56f989d92ca6ba56a3Jakub Hrozek if (!mail->skip &&
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek seq_range_exists(&assigned_uids, mail->final_uid))
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek mail->skip = TRUE;
e7ccfb139388c947ec2dee16cfe3005f5643b90dPetr Cech }
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (!seq_range_array_iter_nth(&wanted_iter, wanted_n, &wanted_uid)) {
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březina /* we've assigned all wanted UIDs */
83a79d93035c2d75a1941f3b54426119174044a0Pavel Březina return TRUE;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek /* try to find one existing message that we can use to copy to the
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina other instances */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce local_n = 0; seq_range_array_iter_init(&local_iter, local_uids);
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina while (seq_range_array_iter_nth(&local_iter, local_n++, &local_uid)) {
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina if (dsync_mailbox_import_local_uid(importer, importer->mail,
f7ea0b1d46197275c87bdc73a6e38a6fd7f855eePavel Březina local_uid, all_newmails->guid,
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina &dmail) > 0) {
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina if (dsync_mailbox_save_newmails(importer, &dmail,
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina all_newmails, FALSE))
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina return TRUE;
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina }
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina }
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina return FALSE;
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina}
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozekstatic bool
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozekdsync_mailbox_import_try_virtual_all(struct dsync_mailbox_importer *importer,
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek struct importer_new_mail *all_newmails)
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek{
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek struct dsync_mail dmail;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (all_newmails->virtual_all_uid == 0)
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek return FALSE;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (dsync_mailbox_import_local_uid(importer, importer->virtual_mail,
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek all_newmails->virtual_all_uid,
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek all_newmails->guid, &dmail) > 0) {
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (dsync_mailbox_save_newmails(importer, &dmail,
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek all_newmails, FALSE))
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek return TRUE;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek }
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek return FALSE;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek}
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozekstatic bool
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozekdsync_mailbox_import_handle_mail(struct dsync_mailbox_importer *importer,
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek struct importer_new_mail *all_newmails)
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek{
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek ARRAY_TYPE(seq_range) local_uids, wanted_uids;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek struct dsync_mail_request *request;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek struct importer_new_mail *mail;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek const char *request_guid = NULL;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek uint32_t request_uid = 0;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek i_assert(all_newmails != NULL);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek /* get the list of the current local UIDs and the wanted UIDs.
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek find the first remote instance that we can request in case there are
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek no local instances */
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek t_array_init(&local_uids, 8);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek t_array_init(&wanted_uids, 8);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek for (mail = all_newmails; mail != NULL; mail = mail->next) {
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (mail->uid_in_local)
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek seq_range_array_add(&local_uids, mail->local_uid);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek else if (request_guid == NULL) {
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (*mail->guid != '\0')
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek request_guid = mail->guid;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek request_uid = mail->remote_uid;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek i_assert(request_uid != 0);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek }
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (!mail->skip)
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek seq_range_array_add(&wanted_uids, mail->final_uid);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek }
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek i_assert(array_count(&wanted_uids) > 0);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (!dsync_mailbox_import_try_local(importer, all_newmails,
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek &local_uids, &wanted_uids) &&
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek !dsync_mailbox_import_try_virtual_all(importer, all_newmails)) {
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek /* no local instance. request from remote */
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek IMPORTER_DEBUG_CHANGE(importer);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek if (importer->want_mail_requests) {
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek request = array_append_space(&importer->mail_requests);
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek request->guid = request_guid;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek request->uid = request_uid;
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek }
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek return FALSE;
ea422c7061072c125eb53b40d7f3ca444d886913Sumit Bose }
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek /* successfully handled all the mails locally */
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek importer->import_pos++;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek return TRUE;
56c9f8731173eae841a05f31bb03d311076a8485Petr Cech}
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozekstatic void
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozekdsync_mailbox_import_find_virtual_uids(struct dsync_mailbox_importer *importer)
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek{
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek struct mail_search_context *search_ctx;
56c9f8731173eae841a05f31bb03d311076a8485Petr Cech struct mail_search_args *search_args;
56c9f8731173eae841a05f31bb03d311076a8485Petr Cech struct importer_new_mail *newmail;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek struct mail *mail;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek const char *guid;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek if (mailbox_sync(importer->virtual_all_box, 0) < 0) {
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce i_error("Couldn't sync \\All mailbox '%s': %s",
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek mailbox_get_vname(importer->virtual_all_box),
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek mailbox_get_last_internal_error(importer->virtual_all_box, NULL));
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek return;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek }
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek search_args = mail_search_build_init();
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek mail_search_build_add_all(search_args);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek importer->virtual_trans =
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek mailbox_transaction_begin(importer->virtual_all_box,
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek importer->transaction_flags);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek search_ctx = mailbox_search_init(importer->virtual_trans, search_args,
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek NULL, MAIL_FETCH_GUID, NULL);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek mail_search_args_unref(&search_args);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek while (mailbox_search_next(search_ctx, &mail)) {
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) < 0) {
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek /* ignore errors */
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek continue;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek }
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek newmail = hash_table_lookup(importer->import_guids, guid);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek if (newmail != NULL && newmail->virtual_all_uid == 0)
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek newmail->virtual_all_uid = mail->uid;
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh }
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh if (mailbox_search_deinit(&search_ctx) < 0) {
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh i_error("Couldn't search \\All mailbox '%s': %s",
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh mailbox_get_vname(importer->virtual_all_box),
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh mailbox_get_last_internal_error(importer->virtual_all_box, NULL));
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh }
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh importer->virtual_mail = mail_alloc(importer->virtual_trans, 0, NULL);
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce}
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singhstatic void
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singhdsync_mailbox_import_handle_local_mails(struct dsync_mailbox_importer *importer)
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh{
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh struct hash_iterate_context *iter;
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce const char *key;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik void *key2;
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh struct importer_new_mail *mail;
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh if (importer->virtual_all_box != NULL &&
25255e4d0e1517a5d443e8fee22e91862e255702Abhishek Singh hash_table_count(importer->import_guids) > 0) {
25255e4d0e1517a5d443e8fee22e91862e255702Abhishek Singh /* find UIDs in \All mailbox for all wanted GUIDs. */
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh dsync_mailbox_import_find_virtual_uids(importer);
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh }
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh iter = hash_table_iterate_init(importer->import_guids);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek while (hash_table_iterate(iter, importer->import_guids, &key, &mail)) {
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha T_BEGIN {
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha if (dsync_mailbox_import_handle_mail(importer, mail))
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha hash_table_remove(importer->import_guids, key);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha } T_END;
9face844e3063b61ab19e1d82bbf3d9f9de76ac7Petr Cech }
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha hash_table_iterate_deinit(&iter);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha iter = hash_table_iterate_init(importer->import_uids);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha while (hash_table_iterate(iter, importer->import_uids, &key2, &mail)) {
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha T_BEGIN {
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha if (dsync_mailbox_import_handle_mail(importer, mail))
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha hash_table_remove(importer->import_uids, key2);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha } T_END;
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce }
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha hash_table_iterate_deinit(&iter);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha}
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jhaint dsync_mailbox_import_changes_finish(struct dsync_mailbox_importer *importer)
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha{
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha i_assert(!importer->new_uids_assigned);
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha
bc052ea17d858c19f9cb9c9e2bc602e754f68831Sumit Bose if (!importer->last_common_uid_found) {
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha /* handle pending expunges and flag updates */
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha dsync_mailbox_common_uid_found(importer);
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha }
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha /* skip common local mails */
80b5dbe123ec94c5a8fcb99f9a4953c1513deb58Sumit Bose (void)importer_next_mail(importer, importer->last_common_uid+1);
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha /* if there are any local mails left, add them to newmails list */
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha while (importer->cur_mail != NULL && !importer->failed)
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha (void)dsync_mailbox_try_save(importer, NULL);
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha if (importer->search_ctx != NULL) {
80b5dbe123ec94c5a8fcb99f9a4953c1513deb58Sumit Bose if (mailbox_search_deinit(&importer->search_ctx) < 0) {
80b5dbe123ec94c5a8fcb99f9a4953c1513deb58Sumit Bose i_error("Mailbox %s: Search failed: %s",
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha mailbox_get_vname(importer->box),
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha mailbox_get_last_internal_error(importer->box,
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik &importer->mail_error));
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik importer->failed = TRUE;
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik }
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik }
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik importer->import_count = hash_table_count(importer->import_guids) +
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik hash_table_count(importer->import_uids);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik dsync_mailbox_import_assign_new_uids(importer);
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik /* save mails from local sources where possible,
16c351625346b3193e1762027e5215ab76042127Sumit Bose request the rest from remote */
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek if (!importer->failed)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek dsync_mailbox_import_handle_local_mails(importer);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return importer->failed ? -1 : 0;
d43c9d18fb263b1ea4071b20e93ce4994583f62fJakub Hrozek}
04868f1573f4b26ef34610b6d7069172f93bd8abJakub Hrozek
04868f1573f4b26ef34610b6d7069172f93bd8abJakub Hrozekconst struct dsync_mail_request *
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekdsync_mailbox_import_next_request(struct dsync_mailbox_importer *importer)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek{
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const struct dsync_mail_request *requests;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek unsigned int count;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek requests = array_get(&importer->mail_requests, &count);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (importer->mail_request_idx == count)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return NULL;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return &requests[importer->mail_request_idx++];
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek}
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikstatic const char *const *
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikdsync_mailbox_get_final_keywords(const struct dsync_mail_change *change)
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek{
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek ARRAY_TYPE(const_string) keywords;
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek const char *const *changes;
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek unsigned int i, count;
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek if (!array_is_created(&change->keyword_changes))
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek return NULL;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik changes = array_get(&change->keyword_changes, &count);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik t_array_init(&keywords, count);
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek for (i = 0; i < count; i++) {
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek if (changes[i][0] == KEYWORD_CHANGE_ADD ||
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek changes[i][0] == KEYWORD_CHANGE_ADD_AND_FINAL) {
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek const char *name = changes[i]+1;
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek array_append(&keywords, &name, 1);
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek }
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek }
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek if (array_count(&keywords) == 0)
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek return NULL;
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek array_append_zero(&keywords);
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek return array_idx(&keywords, 0);
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek}
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozekstatic void
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozekdsync_mailbox_save_set_metadata(struct dsync_mailbox_importer *importer,
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek struct mail_save_context *save_ctx,
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek const struct dsync_mail_change *change)
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek{
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek const char *const *keyword_names;
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek struct mail_keywords *keywords;
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek
3432a503c714732407ea18b2dd32f4f432a6c545Jakub Hrozek keyword_names = dsync_mailbox_get_final_keywords(change);
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina keywords = keyword_names == NULL ? NULL :
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose mailbox_keywords_create_valid(importer->box,
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose keyword_names);
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose mailbox_save_set_flags(save_ctx, change->final_flags, keywords);
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose if (keywords != NULL)
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose mailbox_keywords_unref(&keywords);
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose
221619d8e8d7cf269c55482e5f466f6511ed35adLukas Slebodnik if (change->modseq > 1) {
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose (void)mailbox_enable(importer->box, MAILBOX_FEATURE_CONDSTORE);
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose mailbox_save_set_min_modseq(save_ctx, change->modseq);
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose }
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose /* FIXME: if there already are private flags, they get lost because
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose saving can't handle updating private index. they get added on the
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose next sync though. if this is fixed here, set min_pvt_modseq also. */
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose}
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose
f69f3581658351003a6d9245045e41d0efb85022Sumit Bosestatic int
f69f3581658351003a6d9245045e41d0efb85022Sumit Bosedsync_msg_try_copy(struct dsync_mailbox_importer *importer,
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose struct mail_save_context **save_ctx_p,
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose struct importer_new_mail **all_newmails_forcopy)
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose{
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose struct importer_new_mail *inst;
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose for (inst = *all_newmails_forcopy; inst != NULL; inst = inst->next) {
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose if (inst->uid_in_local && !inst->copy_failed &&
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose mail_set_uid(importer->mail, inst->local_uid)) {
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose if (mailbox_copy(save_ctx_p, importer->mail) < 0) {
b5f61c9b3f5ea79bf319c18ff59394070c04d607Pavel Reichl inst->copy_failed = TRUE;
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik return -1;
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik }
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik *all_newmails_forcopy = inst;
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose return 1;
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose }
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose }
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose *all_newmails_forcopy = NULL;
221619d8e8d7cf269c55482e5f466f6511ed35adLukas Slebodnik return 0;
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose}
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozekstatic void
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichldsync_mailbox_save_set_nonminimal(struct mail_save_context *save_ctx,
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl const struct dsync_mail *mail)
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl{
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl if (mail->pop3_uidl != NULL && *mail->pop3_uidl != '\0')
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik mailbox_save_set_pop3_uidl(save_ctx, mail->pop3_uidl);
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl if (mail->pop3_order > 0)
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl mailbox_save_set_pop3_order(save_ctx, mail->pop3_order);
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik mailbox_save_set_received_date(save_ctx, mail->received_date, 0);
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik}
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichlstatic struct mail_save_context *
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichldsync_mailbox_save_init(struct dsync_mailbox_importer *importer,
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl const struct dsync_mail *mail,
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl struct importer_new_mail *newmail)
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl{
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl struct mail_save_context *save_ctx;
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik save_ctx = mailbox_save_alloc(importer->ext_trans);
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl mailbox_save_set_uid(save_ctx, newmail->final_uid);
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl if (*mail->guid != '\0')
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik mailbox_save_set_guid(save_ctx, mail->guid);
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl if (mail->saved_date != 0)
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl mailbox_save_set_save_date(save_ctx, mail->saved_date);
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek dsync_mailbox_save_set_metadata(importer, save_ctx, newmail->change);
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek if (!mail->minimal_fields)
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek dsync_mailbox_save_set_nonminimal(save_ctx, mail);
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek return save_ctx;
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek}
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek
338af078fcc18126df939f20182acea7a646b7c8Michal Zidekstatic bool
338af078fcc18126df939f20182acea7a646b7c8Michal Zidekdsync_mailbox_save_body(struct dsync_mailbox_importer *importer,
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek const struct dsync_mail *mail,
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek struct importer_new_mail *newmail,
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek struct importer_new_mail **all_newmails_forcopy,
338af078fcc18126df939f20182acea7a646b7c8Michal Zidek bool remote_mail)
e2e334b2f51118cb14c7391c4e4e44ff247ef638Pavel Reichl{
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl struct mail_save_context *save_ctx;
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl struct istream *input;
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl ssize_t ret;
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl bool save_failed = FALSE;
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl /* try to save the mail by copying an existing mail */
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik save_ctx = dsync_mailbox_save_init(importer, mail, newmail);
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl if ((ret = dsync_msg_try_copy(importer, &save_ctx, all_newmails_forcopy)) < 0) {
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl if (save_ctx == NULL)
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik save_ctx = dsync_mailbox_save_init(importer, mail, newmail);
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl }
50b8a36b0932a510e825ed1ad8103f81ead2b7d8Pavel Reichl if (ret <= 0 && mail->input_mail != NULL) {
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek /* copy using the source mail */
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek i_assert(mail->input_mail->uid == mail->input_mail_uid);
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek if (mailbox_copy(&save_ctx, mail->input_mail) == 0)
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek ret = 1;
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik else {
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik ret = -1;
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik save_ctx = dsync_mailbox_save_init(importer, mail, newmail);
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek }
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik }
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik if (ret > 0) {
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik i_assert(save_ctx == NULL);
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik dsync_mailbox_import_saved_newmail(importer, newmail);
0352c371e743d8dae996123f658b5d32c677614eYassir Elley return TRUE;
0352c371e743d8dae996123f658b5d32c677614eYassir Elley }
0352c371e743d8dae996123f658b5d32c677614eYassir Elley /* fallback to saving from remote stream */
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (!remote_mail) {
0352c371e743d8dae996123f658b5d32c677614eYassir Elley /* the mail isn't remote yet. we were just trying to copy a
0352c371e743d8dae996123f658b5d32c677614eYassir Elley local mail to avoid downloading the remote mail. */
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik mailbox_save_cancel(&save_ctx);
0352c371e743d8dae996123f658b5d32c677614eYassir Elley return FALSE;
0352c371e743d8dae996123f658b5d32c677614eYassir Elley }
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (mail->minimal_fields) {
0352c371e743d8dae996123f658b5d32c677614eYassir Elley struct dsync_mail mail2;
0352c371e743d8dae996123f658b5d32c677614eYassir Elley const char *error_field;
0352c371e743d8dae996123f658b5d32c677614eYassir Elley
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek i_assert(mail->input_mail != NULL);
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik if (dsync_mail_fill_nonminimal(mail->input_mail, &mail2,
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik &error_field) < 0) {
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik i_error("Mailbox %s: Failed to read mail %s uid=%u: %s",
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik mailbox_get_vname(importer->box),
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek error_field, mail->uid,
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek mailbox_get_last_internal_error(importer->box,
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek &importer->mail_error));
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek importer->failed = TRUE;
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek mailbox_save_cancel(&save_ctx);
9e6f8d1c66b4b3543bab67d807bd26f1d6256c75Pavel Březina return TRUE;
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose }
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose dsync_mailbox_save_set_nonminimal(save_ctx, &mail2);
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose input = mail2.input;
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose } else {
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose input = mail->input;
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose }
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek if (input == NULL) {
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek /* it was just expunged in remote, skip it */
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek mailbox_save_cancel(&save_ctx);
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek return TRUE;
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek }
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek i_stream_seek(input, 0);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek if (mailbox_save_begin(&save_ctx, input) < 0) {
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek i_error("Mailbox %s: Saving failed: %s",
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose mailbox_get_vname(importer->box),
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose mailbox_get_last_internal_error(importer->box,
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek &importer->mail_error));
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek importer->failed = TRUE;
63b8e826f62d2e8930c872de7d4cc8b5bc15d4a4Sumit Bose return TRUE;
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek }
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek while ((ret = i_stream_read(input)) > 0 || ret == -2) {
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik if (mailbox_save_continue(save_ctx) < 0) {
51b5e1475b3e0b7acac34ed382cfaca8411883a4Jakub Hrozek save_failed = TRUE;
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek ret = -1;
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek break;
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek }
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek }
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek i_assert(ret == -1);
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek if (input->stream_errno != 0) {
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek i_error("Mailbox %s: read(msg input) failed: %s",
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek mailbox_get_vname(importer->box),
5c36e1f8901a4baff2b51d81d87c2b577f84fef6Lukas Slebodnik i_stream_get_error(input));
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek mailbox_save_cancel(&save_ctx);
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek importer->mail_error = MAIL_ERROR_TEMP;
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek importer->failed = TRUE;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek } else if (save_failed) {
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek i_error("Mailbox %s: Saving failed: %s",
fb83de0699b16e7d8eca803305e2112795807b4cJakub Hrozek mailbox_get_vname(importer->box),
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek mailbox_get_last_internal_error(importer->box,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek &importer->mail_error));
f7ea0b1d46197275c87bdc73a6e38a6fd7f855eePavel Březina mailbox_save_cancel(&save_ctx);
676bf6dda60776d9db79dad1c2506c0e57bb5503Pavel Březina importer->failed = TRUE;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } else {
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek i_assert(input->eof);
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek if (mailbox_save_finish(&save_ctx) < 0) {
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek i_error("Mailbox %s: Saving failed: %s",
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek mailbox_get_vname(importer->box),
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek mailbox_get_last_internal_error(importer->box,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek &importer->mail_error));
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek importer->failed = TRUE;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek } else {
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek dsync_mailbox_import_saved_newmail(importer, newmail);
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek }
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek }
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek return TRUE;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek}
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozekstatic bool dsync_mailbox_save_newmails(struct dsync_mailbox_importer *importer,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek const struct dsync_mail *mail,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek struct importer_new_mail *all_newmails,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek bool remote_mail)
fb83de0699b16e7d8eca803305e2112795807b4cJakub Hrozek{
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek struct importer_new_mail *newmail, *all_newmails_forcopy;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek bool ret = TRUE;
842f83f8db513214241a0fea076ac160b180e1ddLukas Slebodnik
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek /* if all_newmails list is large, avoid scanning through the
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek uninteresting ones for each newmail */
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek all_newmails_forcopy = all_newmails;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek /* save all instances of the message */
2dcf7b9b65df21f2aee6cdf051a7fbdef6dfe034Jakub Hrozek for (newmail = all_newmails; newmail != NULL && ret; newmail = newmail->next) {
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (!newmail->skip) T_BEGIN {
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (!dsync_mailbox_save_body(importer, mail, newmail,
3fe339bcba0e211cc666bb3afe34e5c8fce85f4fJakub Hrozek &all_newmails_forcopy,
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose remote_mail))
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose ret = FALSE;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek } T_END;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek }
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek return ret;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek}
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozekint dsync_mailbox_import_mail(struct dsync_mailbox_importer *importer,
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce const struct dsync_mail *mail)
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek{
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina struct importer_new_mail *all_newmails;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina i_assert(mail->input == NULL || mail->input->seekable);
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina i_assert(importer->new_uids_assigned);
0bb98b7700b1b61f5b0a20b93279d5c2c391007fPavel Březina
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina if (importer->failed)
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina return -1;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina if (importer->require_full_resync)
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina return 0;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina imp_debug(importer, "Import mail body for GUID=%s UID=%u",
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina mail->guid, mail->uid);
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina all_newmails = *mail->guid != '\0' ?
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina hash_table_lookup(importer->import_guids, mail->guid) :
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina hash_table_lookup(importer->import_uids, POINTER_CAST(mail->uid));
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina if (all_newmails == NULL) {
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina if (importer->want_mail_requests) {
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina i_error("Mailbox %s: Remote sent unwanted message body for "
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina "GUID=%s UID=%u",
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina mailbox_get_vname(importer->box),
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina mail->guid, mail->uid);
770dc892f867639f36f84455d65be6287935a529Jakub Hrozek } else {
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek imp_debug(importer, "Skip unwanted mail body for "
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek "GUID=%s UID=%u", mail->guid, mail->uid);
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek }
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek return 0;
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek }
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek if (*mail->guid != '\0')
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek hash_table_remove(importer->import_guids, mail->guid);
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek else {
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek hash_table_remove(importer->import_uids,
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek POINTER_CAST(mail->uid));
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek }
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek importer->import_pos++;
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek if (!dsync_mailbox_save_newmails(importer, mail, all_newmails, TRUE))
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek i_unreached();
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek return importer->failed ? -1 : 0;
6ea6662287147308b81b9c9f2f1f3c992d01bc50Jakub Hrozek}
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozekstatic int
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozekreassign_uids_in_seq_range(struct dsync_mailbox_importer *importer,
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek const ARRAY_TYPE(seq_range) *unwanted_uids)
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek{
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek struct mailbox *box = importer->box;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek const enum mailbox_transaction_flags trans_flags =
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek importer->transaction_flags |
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek MAILBOX_TRANSACTION_FLAG_EXTERNAL |
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek struct mailbox_transaction_context *trans;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek struct mail_search_args *search_args;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek struct mail_search_arg *arg;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek struct mail_search_context *search_ctx;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek struct mail_save_context *save_ctx;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek struct mail *mail;
d36f4db9bb5efc63b94190cca25adb08ee56971cJakub Hrozek unsigned int renumber_count = 0;
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek int ret = 1;
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek if (array_count(unwanted_uids) == 0)
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek return 1;
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek if (importer->debug) T_BEGIN {
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek string_t *str = t_str_new(256);
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek imap_write_seq_range(str, unwanted_uids);
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek imp_debug(importer, "Reassign UIDs: %s", str_c(str));
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek } T_END;
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek search_args = mail_search_build_init();
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek arg = mail_search_build_add(search_args, SEARCH_UIDSET);
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek p_array_init(&arg->value.seqset, search_args->pool,
526a15438525417cd701f837d7085b7f8c8a6325Jakub Hrozek array_count(unwanted_uids));
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech array_append_array(&arg->value.seqset, unwanted_uids);
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech trans = mailbox_transaction_begin(box, trans_flags);
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech search_ctx = mailbox_search_init(trans, search_args, NULL, 0, NULL);
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech mail_search_args_unref(&search_args);
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech while (mailbox_search_next(search_ctx, &mail)) {
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech save_ctx = mailbox_save_alloc(trans);
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech mailbox_save_copy_flags(save_ctx, mail);
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech if (mailbox_move(&save_ctx, mail) < 0) {
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech i_error("Mailbox %s: Couldn't move mail within mailbox: %s",
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech mailbox_get_vname(box),
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech mailbox_get_last_internal_error(box, &importer->mail_error));
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech ret = -1;
27a7dedb0ee4d4b51ca4c196aa894ad30cb3e821Petr Cech } else if (ret > 0) {
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose ret = 0;
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose }
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose renumber_count++;
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose }
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose if (mailbox_search_deinit(&search_ctx) < 0) {
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose i_error("Mailbox %s: mail search failed: %s",
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose mailbox_get_vname(box),
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose mailbox_get_last_internal_error(box, &importer->mail_error));
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose ret = -1;
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose }
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose if (mailbox_transaction_commit(&trans) < 0) {
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose i_error("Mailbox %s: UID reassign commit failed: %s",
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose mailbox_get_vname(box),
1d93029624d708119bbf803e6647a2cbb271f001Sumit Bose mailbox_get_last_internal_error(box, &importer->mail_error));
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina ret = -1;
d43c9d18fb263b1ea4071b20e93ce4994583f62fJakub Hrozek }
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina if (ret == 0) {
3b99f7a97553a0a357d50abe507d4f0060c4eceaPavel Březina imp_debug(importer, "Mailbox %s: Change during sync: "
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina "Renumbered %u of %u unwanted UIDs",
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina mailbox_get_vname(box),
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina renumber_count, array_count(unwanted_uids));
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina }
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina return ret;
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina}
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březinastatic int
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březinareassign_unwanted_uids(struct dsync_mailbox_importer *importer,
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina const char **changes_during_sync_r)
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina{
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina ARRAY_TYPE(seq_range) unwanted_uids;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose const uint32_t *wanted_uids, *saved_uids;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose uint32_t highest_seen_uid;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose unsigned int i, wanted_count, saved_count;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose int ret = 0;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose wanted_uids = array_get(&importer->wanted_uids, &wanted_count);
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose saved_uids = array_get(&importer->saved_uids, &saved_count);
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose i_assert(wanted_count == saved_count);
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if (wanted_count == 0)
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose return 0;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose /* wanted_uids contains the UIDs we tried to save mails with.
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if nothing changed during dsync, we should have the expected UIDs
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose (saved_uids) and all is well.
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if any new messages got inserted during dsync, we'll need to fix up
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose the UIDs and let the next dsync fix up the other side. for example:
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose remote uids = 5,7,9 = wanted_uids
b1a822a16e3ef97e31d167f9e97efec06fc121dcJakub Hrozek remote uidnext = 12
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose locally added new uid=5 ->
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose saved_uids = 10,7,9
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose we'll now need to reassign UIDs 5 and 10. to be fully future-proof
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose we'll reassign all UIDs between [original local uidnext .. highest
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose UID we think we know] that aren't in saved_uids. */
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose /* create uidset for the list of UIDs we don't want to exist */
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose t_array_init(&unwanted_uids, 8);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose highest_seen_uid = I_MAX(importer->remote_uid_next-1,
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose importer->highest_wanted_uid);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose i_assert(importer->local_uid_next <= highest_seen_uid);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose seq_range_array_add_range(&unwanted_uids,
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose importer->local_uid_next, highest_seen_uid);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose for (i = 0; i < wanted_count; i++) {
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose i_assert(i < wanted_count);
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek if (saved_uids[i] == wanted_uids[i])
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek seq_range_array_remove(&unwanted_uids, saved_uids[i]);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek }
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek ret = reassign_uids_in_seq_range(importer, &unwanted_uids);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek if (ret == 0) {
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek *changes_during_sync_r = t_strdup_printf(
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek "%u UIDs changed due to UID conflicts",
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek seq_range_count(&unwanted_uids));
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek /* conflicting changes during sync, revert our last-common-uid
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik back to a safe value. */
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik importer->last_common_uid = importer->local_uid_next - 1;
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik }
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik return ret < 0 ? -1 : 0;
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik}
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozekstatic int
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozekdsync_mailbox_import_commit(struct dsync_mailbox_importer *importer, bool final)
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek{
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek struct mail_transaction_commit_changes changes;
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek struct seq_range_iter iter;
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek uint32_t uid;
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek unsigned int n;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek int ret = importer->failed ? -1 : 0;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek mail_free(&importer->mail);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek mail_free(&importer->ext_mail);
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik /* commit saves */
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek if (mailbox_transaction_commit_get_changes(&importer->ext_trans,
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek &changes) < 0) {
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek i_error("Mailbox %s: Save commit failed: %s",
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina mailbox_get_vname(importer->box),
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina mailbox_get_last_internal_error(importer->box, &importer->mail_error));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* removed wanted_uids that weren't actually saved */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina array_delete(&importer->wanted_uids,
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina array_count(&importer->saved_uids),
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina array_count(&importer->wanted_uids) -
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina array_count(&importer->saved_uids));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina mailbox_transaction_rollback(&importer->trans);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ret = -1;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina } else {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina /* remember the UIDs that were successfully saved */
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (importer->debug) T_BEGIN {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina string_t *str = t_str_new(256);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina imap_write_seq_range(str, &changes.saved_uids);
e5911e72198df96ec7cfe486ff66363c2297a5f7Simo Sorce imp_debug(importer, "Saved UIDs: %s", str_c(str));
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina } T_END;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina seq_range_array_iter_init(&iter, &changes.saved_uids); n = 0;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (seq_range_array_iter_nth(&iter, n++, &uid))
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina array_append(&importer->saved_uids, &uid, 1);
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina pool_unref(&changes.pool);
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina /* commit flag changes and expunges */
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina if (mailbox_transaction_commit(&importer->trans) < 0) {
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina i_error("Mailbox %s: Commit failed: %s",
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina mailbox_get_vname(importer->box),
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina mailbox_get_last_internal_error(importer->box,
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina &importer->mail_error));
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina ret = -1;
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina }
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina }
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek if (!final)
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek dsync_mailbox_import_transaction_begin(importer);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek return ret;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek}
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozekstatic int dsync_mailbox_import_finish(struct dsync_mailbox_importer *importer,
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek const char **changes_during_sync_r)
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek{
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek struct mailbox_update update;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek int ret;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek ret = dsync_mailbox_import_commit(importer, TRUE);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek if (ret == 0) {
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek /* update mailbox metadata if we successfully saved
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek everything. */
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek i_zero(&update);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek update.min_next_uid = importer->remote_uid_next;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek update.min_first_recent_uid =
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek I_MIN(importer->last_common_uid+1,
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek importer->remote_first_recent_uid);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek update.min_highest_modseq = importer->remote_highest_modseq;
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek update.min_highest_pvt_modseq = importer->remote_highest_pvt_modseq;
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek imp_debug(importer, "Finish update: min_next_uid=%u "
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek "min_first_recent_uid=%u min_highest_modseq=%llu "
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek "min_highest_pvt_modseq=%llu",
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek update.min_next_uid, update.min_first_recent_uid,
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek (unsigned long long)update.min_highest_modseq,
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek (unsigned long long)update.min_highest_pvt_modseq);
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek if (mailbox_update(importer->box, &update) < 0) {
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek i_error("Mailbox %s: Update failed: %s",
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek mailbox_get_vname(importer->box),
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek mailbox_get_last_internal_error(importer->box,
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek &importer->mail_error));
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek ret = -1;
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek }
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek }
8df69bbc58c2f4d3f0b34be9756d9ddf24b1db6dJakub Hrozek
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek /* sync mailbox to finish flag changes and expunges. */
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek if (mailbox_sync(importer->box, 0) < 0) {
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek i_error("Mailbox %s: Sync failed: %s",
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek mailbox_get_vname(importer->box),
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek mailbox_get_last_internal_error(importer->box,
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek &importer->mail_error));
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek ret = -1;
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek }
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek if (ret == 0) {
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek /* give new UIDs to messages that got saved with unwanted UIDs.
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek do it only if the whole transaction succeeded. */
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek if (reassign_unwanted_uids(importer, changes_during_sync_r) < 0)
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek ret = -1;
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek }
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek return ret;
89ddc9ed474e9ac2b1e7bccb0a58610babf26cf8Jakub Hrozek}
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozekstatic void
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozekdsync_mailbox_import_check_missing_guid_imports(struct dsync_mailbox_importer *importer)
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek{
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek struct hash_iterate_context *iter;
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek const char *key;
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek struct importer_new_mail *mail;
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek
676bf6dda60776d9db79dad1c2506c0e57bb5503Pavel Březina iter = hash_table_iterate_init(importer->import_guids);
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek while (hash_table_iterate(iter, importer->import_guids, &key, &mail)) {
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek for (; mail != NULL; mail = mail->next) {
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek if (mail->skip)
bee2f31ca5d151b7fe35c509fe7eae24ca4f4451Lukas Slebodnik continue;
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek i_error("Mailbox %s: Remote didn't send mail GUID=%s (UID=%u)",
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek mailbox_get_vname(importer->box),
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozek mail->guid, mail->remote_uid);
323943605c88838f1f86a72f891eb28600bb34e2Lukas Slebodnik importer->mail_error = MAIL_ERROR_TEMP;
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek importer->failed = TRUE;
db5f9ab3feb85aa444eab20428ca2b98801b6783Jakub Hrozek }
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek }
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek hash_table_iterate_deinit(&iter);
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek}
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek
64ea4127f463798410a2c20e0261c6b15f60257fJakub Hrozekstatic void
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozekdsync_mailbox_import_check_missing_uid_imports(struct dsync_mailbox_importer *importer)
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek{
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek struct hash_iterate_context *iter;
a801d42c4637bbdf9664d0d8b913ffcab81b904eLukas Slebodnik void *key;
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek struct importer_new_mail *mail;
802909e59daa52c734dbe7f8fa13b0ee23e3e576Lukas Slebodnik
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek iter = hash_table_iterate_init(importer->import_uids);
f4025ea817b3467be1c2e6092014a11fe4547c0dJakub Hrozek while (hash_table_iterate(iter, importer->import_uids, &key, &mail)) {
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech for (; mail != NULL; mail = mail->next) {
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech if (mail->skip)
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech continue;
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech i_error("Mailbox %s: Remote didn't send mail UID=%u",
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech mailbox_get_vname(importer->box),
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech mail->remote_uid);
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech importer->mail_error = MAIL_ERROR_TEMP;
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech importer->failed = TRUE;
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech }
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech }
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech hash_table_iterate_deinit(&iter);
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech}
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cechint dsync_mailbox_import_deinit(struct dsync_mailbox_importer **_importer,
b590f44c06158485357d69cc5b24d5af05f1bb95Petr Cech bool success,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek uint32_t *last_common_uid_r,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek uint64_t *last_common_modseq_r,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek uint64_t *last_common_pvt_modseq_r,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek uint32_t *last_messages_count_r,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek const char **changes_during_sync_r,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek bool *require_full_resync_r,
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek enum mail_error *error_r)
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek{
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct dsync_mailbox_importer *importer = *_importer;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek struct mailbox_status status;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek int ret;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek *_importer = NULL;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek *changes_during_sync_r = NULL;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek *require_full_resync_r = importer->require_full_resync;
01ec08efd0e166ac6f390f8627c6d08dcc63ccc4Jakub Hrozek
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if ((!success || importer->require_full_resync) && !importer->failed) {
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose importer->mail_error = MAIL_ERROR_TEMP;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose importer->failed = TRUE;
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose }
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if (!importer->new_uids_assigned && !importer->failed)
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose dsync_mailbox_import_assign_new_uids(importer);
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if (!importer->failed) {
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose dsync_mailbox_import_check_missing_guid_imports(importer);
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose dsync_mailbox_import_check_missing_uid_imports(importer);
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose }
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if (importer->search_ctx != NULL) {
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose if (mailbox_search_deinit(&importer->search_ctx) < 0) {
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose i_error("Mailbox %s: Search failed: %s",
bf01e8179cbb2be476805340636098deda7e1366Sumit Bose mailbox_get_vname(importer->box),
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek mailbox_get_last_internal_error(importer->box,
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek &importer->mail_error));
71493344f59002272c2cc069daa3b6147e9cb0c3Lukas Slebodnik importer->failed = TRUE;
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek }
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek }
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek if (dsync_mailbox_import_finish(importer, changes_during_sync_r) < 0)
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek importer->failed = TRUE;
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek if (importer->virtual_mail != NULL)
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek mail_free(&importer->virtual_mail);
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek if (importer->virtual_trans != NULL)
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek (void)mailbox_transaction_commit(&importer->virtual_trans);
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek hash_table_destroy(&importer->import_guids);
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek hash_table_destroy(&importer->import_uids);
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek array_free(&importer->maybe_expunge_uids);
71493344f59002272c2cc069daa3b6147e9cb0c3Lukas Slebodnik array_free(&importer->maybe_saves);
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek array_free(&importer->wanted_uids);
73ec8fdfddb2d4bf99977f758eec80e1b1ee8542Lukas Slebodnik array_free(&importer->saved_uids);
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek array_free(&importer->newmails);
71493344f59002272c2cc069daa3b6147e9cb0c3Lukas Slebodnik if (array_is_created(&importer->mail_requests))
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek array_free(&importer->mail_requests);
99c5f2f6ba0af6ce52be0d82ec2794bacc215742Jakub Hrozek
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina *last_common_uid_r = importer->last_common_uid;
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina if (*changes_during_sync_r == NULL) {
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina *last_common_modseq_r = importer->remote_highest_modseq;
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina *last_common_pvt_modseq_r = importer->remote_highest_pvt_modseq;
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina } else {
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina /* local changes occurred during dsync. we exported changes up
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina to local_initial_highestmodseq, so all of the changes have
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina happened after it. we want the next run to see those changes,
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina so return it as the last common modseq */
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina *last_common_modseq_r = importer->local_initial_highestmodseq;
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina *last_common_pvt_modseq_r = importer->local_initial_highestpvtmodseq;
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina }
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina if (importer->delete_mailbox) {
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina if (mailbox_delete(importer->box) < 0) {
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina i_error("Couldn't delete mailbox %s: %s",
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina mailbox_get_vname(importer->box),
b9d83e10cec267ae11fee64a30f42a12bbf7abe4Pavel Březina mailbox_get_last_internal_error(importer->box,
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl &importer->mail_error));
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl importer->failed = TRUE;
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl }
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl *last_messages_count_r = 0;
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl } else {
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl mailbox_get_open_status(importer->box, STATUS_MESSAGES, &status);
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl *last_messages_count_r = status.messages;
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl }
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl i_assert(importer->failed == (importer->mail_error != 0));
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl ret = importer->failed ? -1 : 0;
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl *error_r = importer->mail_error;
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl pool_unref(&importer->pool);
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl return ret;
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl}
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichlconst char *dsync_mailbox_import_get_proctitle(struct dsync_mailbox_importer *importer)
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl{
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl if (importer->search_ctx != NULL)
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl return "";
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl return t_strdup_printf("%u/%u", importer->import_pos,
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl importer->import_count);
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl}
49c467733ca65c9b77b9c33f38cdc223a99562e1Pavel Reichl