bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "lib.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "str.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mail-namespace.h"
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen#include "dsync-ibc.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "dsync-mailbox-tree.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "dsync-brain-private.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include <ctype.h>
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void dsync_brain_check_namespaces(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_namespace *ns, *first_ns = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen char sep;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(brain->hierarchy_sep == '\0');
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!dsync_brain_want_namespace(brain, ns))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen continue;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen sep = mail_namespace_get_sep(ns);
3605fb862d3d15e3e747b0cd34729d61acbb332cTimo Sirainen if (first_ns == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->hierarchy_sep = sep;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen first_ns = ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (brain->hierarchy_sep != sep) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("Synced namespaces have conflicting separators "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "('%c' for prefix=\"%s\", '%c' for prefix=\"%s\")",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->hierarchy_sep, first_ns->prefix,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen sep, ns->prefix);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (brain->hierarchy_sep != '\0')
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_fatal("All your namespaces have a location setting. "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "Only namespaces with empty location settings are converted. "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "(One namespace should default to mail_location setting)");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid dsync_brain_mailbox_trees_init(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_namespace *ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_brain_check_namespaces(brain);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->local_mailbox_tree =
0219a05495ca78d0ccc2a4d5dcfcf17aa859481fTimo Sirainen dsync_mailbox_tree_init(brain->hierarchy_sep, brain->alt_char);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* we'll convert remote mailbox names to use our own separator */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->remote_mailbox_tree =
0219a05495ca78d0ccc2a4d5dcfcf17aa859481fTimo Sirainen dsync_mailbox_tree_init(brain->hierarchy_sep, brain->alt_char);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* fill the local mailbox tree */
fd32c46c360e61de2c957c3d2241eaacab7b3eecTimo Sirainen for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
fd32c46c360e61de2c957c3d2241eaacab7b3eecTimo Sirainen if (!dsync_brain_want_namespace(brain, ns))
fd32c46c360e61de2c957c3d2241eaacab7b3eecTimo Sirainen continue;
7aa2660e70dc517f91e8a9e0c9732c7e9db25c78Aki Tuomi if (brain->debug)
7aa2660e70dc517f91e8a9e0c9732c7e9db25c78Aki Tuomi i_debug("brain %c: Namespace %s has location %s",
7aa2660e70dc517f91e8a9e0c9732c7e9db25c78Aki Tuomi brain->master_brain ? 'M' : 'S',
7aa2660e70dc517f91e8a9e0c9732c7e9db25c78Aki Tuomi ns->prefix, ns->set->location);
fd32c46c360e61de2c957c3d2241eaacab7b3eecTimo Sirainen if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, ns,
fd32c46c360e61de2c957c3d2241eaacab7b3eecTimo Sirainen brain->sync_box,
fd32c46c360e61de2c957c3d2241eaacab7b3eecTimo Sirainen brain->sync_box_guid,
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen brain->exclude_mailboxes,
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen &brain->mail_error) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->failed = TRUE;
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen break;
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->local_tree_iter =
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_mailbox_tree_iter_init(brain->local_mailbox_tree);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid dsync_brain_send_mailbox_tree(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct dsync_mailbox_node *node;
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen enum dsync_ibc_send_ret ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *full_name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen char sep[2];
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen sep[0] = brain->hierarchy_sep; sep[1] = '\0';
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (dsync_mailbox_tree_iter_next(brain->local_tree_iter,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &full_name, &node)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen T_BEGIN {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *const *parts;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (brain->debug) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen i_debug("brain %c: Local mailbox tree: %s %s",
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen brain->master_brain ? 'M' : 'S', full_name,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen dsync_mailbox_node_to_string(node));
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen }
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen parts = t_strsplit(full_name, sep);
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen ret = dsync_ibc_send_mailbox_tree_node(brain->ibc,
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen parts, node);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } T_END;
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if (ret == DSYNC_IBC_SEND_RET_FULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter);
b8e6e314eb2f9f1fc8ce2999034321bfeb7a2269Timo Sirainen dsync_ibc_send_end_of_list(brain->ibc, DSYNC_IBC_EOL_MAILBOX_TREE);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->state = DSYNC_STATE_SEND_MAILBOX_TREE_DELETES;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenvoid dsync_brain_send_mailbox_tree_deletes(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct dsync_mailbox_delete *deletes;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int count;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &count);
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen dsync_ibc_send_mailbox_deletes(brain->ibc, deletes, count,
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen brain->hierarchy_sep);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->state = DSYNC_STATE_RECV_MAILBOX_TREE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainendsync_namespace_match_parts(struct mail_namespace *ns,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *const *name_parts)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *part, *prefix = ns->prefix;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t part_len;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen char ns_sep = mail_namespace_get_sep(ns);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
ec66a68735096e81df73176231b49179222ad9ceTimo Sirainen if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
ec66a68735096e81df73176231b49179222ad9ceTimo Sirainen strcmp(name_parts[0], "INBOX") == 0 && name_parts[1] == NULL)
ec66a68735096e81df73176231b49179222ad9ceTimo Sirainen return TRUE;
ec66a68735096e81df73176231b49179222ad9ceTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (; *name_parts != NULL && *prefix != '\0'; name_parts++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen part = *name_parts;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen part_len = strlen(part);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strncmp(prefix, part, part_len) != 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (prefix[part_len] != ns_sep)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen prefix += part_len + 1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e16052742970235960af359ce62515b9127c16fdTimo Sirainen if (*name_parts != NULL) {
e16052742970235960af359ce62515b9127c16fdTimo Sirainen /* namespace prefix found with a mailbox */
e16052742970235960af359ce62515b9127c16fdTimo Sirainen return TRUE;
e16052742970235960af359ce62515b9127c16fdTimo Sirainen }
e16052742970235960af359ce62515b9127c16fdTimo Sirainen if (*prefix == '\0') {
e16052742970235960af359ce62515b9127c16fdTimo Sirainen /* namespace prefix itself matched */
e16052742970235960af359ce62515b9127c16fdTimo Sirainen return TRUE;
e16052742970235960af359ce62515b9127c16fdTimo Sirainen }
e16052742970235960af359ce62515b9127c16fdTimo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct mail_namespace *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainendsync_find_namespace(struct dsync_brain *brain, const char *const *name_parts)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_namespace *ns, *best_ns = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!dsync_brain_want_namespace(brain, ns))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen continue;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ns->prefix_len == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* prefix="" is the fallback namespace */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (best_ns == NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen best_ns = ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (dsync_namespace_match_parts(ns, name_parts)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (best_ns == NULL ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen best_ns->prefix_len < ns->prefix_len)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen best_ns = ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return best_ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainenstatic bool
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainendsync_is_valid_name(struct mail_namespace *ns, const char *vname)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen struct mailbox *box;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen bool ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
f771d4d1fd4a4df3271d86f9be00c2fabaa99348Timo Sirainen box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen ret = mailbox_verify_create_name(box) == 0;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen mailbox_free(&box);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainenstatic void
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainendsync_fix_mailbox_name(struct mail_namespace *ns, string_t *vname_str,
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen char alt_char)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen const char *old_vname;
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen char *vname, list_sep = mailbox_list_get_hierarchy_sep(ns->list);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen guid_128_t guid;
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen unsigned int i, start_pos;
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen vname = str_c_modifiable(vname_str);
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (strncmp(vname, ns->prefix, ns->prefix_len) == 0)
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen start_pos = ns->prefix_len;
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen else
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen start_pos = 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen /* replace control chars */
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen for (i = start_pos; vname[i] != '\0'; i++) {
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if ((unsigned char)vname[i] < ' ')
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen vname[i] = alt_char;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen /* make it valid UTF8 */
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (!uni_utf8_str_is_valid(vname)) {
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen old_vname = t_strdup(vname + start_pos);
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen str_truncate(vname_str, start_pos);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (uni_utf8_get_valid_data((const void *)old_vname,
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen strlen(old_vname), vname_str))
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen i_unreached();
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen vname = str_c_modifiable(vname_str);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (dsync_is_valid_name(ns, vname))
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen /* 1) change any real separators to alt separators (this wouldn't
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen be necessary with listescape, but don't bother detecting it) */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (list_sep != mail_namespace_get_sep(ns)) {
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen for (i = start_pos; vname[i] != '\0'; i++) {
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (vname[i] == list_sep)
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen vname[i] = alt_char;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (dsync_is_valid_name(ns, vname))
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen /* 2) '/' characters aren't valid without listescape */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (mail_namespace_get_sep(ns) != '/' && list_sep != '/') {
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen for (i = start_pos; vname[i] != '\0'; i++) {
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (vname[i] == '/')
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen vname[i] = alt_char;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (dsync_is_valid_name(ns, vname))
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen /* 3) probably some reserved name (e.g. dbox-Mails) */
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen str_insert(vname_str, ns->prefix_len, "_");
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen if (dsync_is_valid_name(ns, str_c(vname_str)))
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen /* 4) name is too long? just give up and generate a unique name */
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen guid_128_generate(guid);
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen str_truncate(vname_str, 0);
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen str_append(vname_str, ns->prefix);
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen str_append(vname_str, guid_128_to_string(guid));
a46162e640e660638596a91032905ab9cb27bf04Timo Sirainen i_assert(dsync_is_valid_name(ns, str_c(vname_str)));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainendsync_get_mailbox_name(struct dsync_brain *brain, const char *const *name_parts,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char **name_r, struct mail_namespace **ns_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_namespace *ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *p;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen string_t *vname;
0219a05495ca78d0ccc2a4d5dcfcf17aa859481fTimo Sirainen char ns_sep;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(*name_parts != NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ns = dsync_find_namespace(brain, name_parts);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (ns == NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ns_sep = mail_namespace_get_sep(ns);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* build the mailbox name */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen vname = t_str_new(128);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (; *name_parts != NULL; name_parts++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (p = *name_parts; *p != '\0'; p++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (*p != ns_sep)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_append_c(vname, *p);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else
0219a05495ca78d0ccc2a4d5dcfcf17aa859481fTimo Sirainen str_append_c(vname, brain->alt_char);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_append_c(vname, ns_sep);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_truncate(vname, str_len(vname)-1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
0219a05495ca78d0ccc2a4d5dcfcf17aa859481fTimo Sirainen dsync_fix_mailbox_name(ns, vname, brain->alt_char);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen *name_r = str_c(vname);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen *ns_r = ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void dsync_brain_mailbox_trees_sync(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct dsync_mailbox_tree_sync_ctx *ctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct dsync_mailbox_tree_sync_change *change;
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen enum dsync_mailbox_trees_sync_type sync_type;
be2bc5677a16a3547d5cbfd21c9deedc96a759adTimo Sirainen enum dsync_mailbox_trees_sync_flags sync_flags =
be2bc5677a16a3547d5cbfd21c9deedc96a759adTimo Sirainen (brain->debug ? DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG : 0) |
1a1d00fd04bfcf8436b00b58d527e46b23523c9dTimo Sirainen (brain->master_brain ? DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN : 0) |
1a1d00fd04bfcf8436b00b58d527e46b23523c9dTimo Sirainen (brain->no_mailbox_renames ? DSYNC_MAILBOX_TREES_SYNC_FLAG_NO_RENAMES : 0);
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen
36723cf206a7b64b9d972ab0719bbfaacc9316faTimo Sirainen if (brain->no_backup_overwrite)
36723cf206a7b64b9d972ab0719bbfaacc9316faTimo Sirainen sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;
36723cf206a7b64b9d972ab0719bbfaacc9316faTimo Sirainen else if (brain->backup_send)
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_LOCAL;
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen else if (brain->backup_recv)
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_REMOTE;
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen else
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen sync_type = DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ctx = dsync_mailbox_trees_sync_init(brain->local_mailbox_tree,
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen brain->remote_mailbox_tree,
be2bc5677a16a3547d5cbfd21c9deedc96a759adTimo Sirainen sync_type, sync_flags);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while ((change = dsync_mailbox_trees_sync_next(ctx)) != NULL) {
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen if (dsync_brain_mailbox_tree_sync_change(brain, change,
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen &brain->mail_error) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->failed = TRUE;
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen break;
ce0e25f26d6e67480ee39b5ca0ad634fa60c4605Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
34b0579f1542471947564bf56cfcf51946f57313Timo Sirainen if (dsync_mailbox_trees_sync_deinit(&ctx) < 0)
34b0579f1542471947564bf56cfcf51946f57313Timo Sirainen brain->failed = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool dsync_brain_recv_mailbox_tree(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct dsync_mailbox_node *remote_node;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen struct dsync_mailbox_node *node, *dup_node1, *dup_node2;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *const *parts, *name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_namespace *ns;
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen enum dsync_ibc_recv_ret ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen char sep[2];
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen bool changed = FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen sep[0] = brain->hierarchy_sep; sep[1] = '\0';
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen while ((ret = dsync_ibc_recv_mailbox_tree_node(brain->ibc, &parts,
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen &remote_node)) > 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (dsync_get_mailbox_name(brain, parts, &name, &ns) < 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("Couldn't find namespace for mailbox %s",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen t_strarray_join(parts, sep));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->failed = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (brain->debug) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen i_debug("brain %c: Remote mailbox tree: %s %s",
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen brain->master_brain ? 'M' : 'S',
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen t_strarray_join(parts, sep),
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen dsync_mailbox_node_to_string(remote_node));
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen node = dsync_mailbox_tree_get(brain->remote_mailbox_tree, name);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen node->ns = ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_mailbox_node_copy_data(node, remote_node);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen if (ret != DSYNC_IBC_RECV_RET_FINISHED)
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen return changed;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen if (dsync_mailbox_tree_build_guid_hash(brain->remote_mailbox_tree,
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen &dup_node1, &dup_node2) < 0) {
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen i_error("Remote sent duplicate mailbox GUID %s for mailboxes %s and %s",
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen guid_128_to_string(dup_node1->mailbox_guid),
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen dsync_mailbox_node_get_full_name(brain->remote_mailbox_tree,
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen dup_node1),
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen dsync_mailbox_node_get_full_name(brain->remote_mailbox_tree,
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen dup_node2));
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen brain->failed = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen brain->state = DSYNC_STATE_RECV_MAILBOX_TREE_DELETES;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen return TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainendsync_brain_mailbox_tree_add_delete(struct dsync_mailbox_tree *tree,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct dsync_mailbox_tree *other_tree,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen const struct dsync_mailbox_delete *other_del,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen const struct dsync_mailbox_node **node_r,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen const char **status_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct dsync_mailbox_node *node;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen struct dsync_mailbox_node *other_node, *old_node;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* see if we can find the deletion based on mailbox tree that should
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen still have the mailbox */
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen node = *node_r = dsync_mailbox_tree_find_delete(tree, other_del);
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (node == NULL) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen *status_r = "not found";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen switch (other_del->type) {
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen case DSYNC_MAILBOX_DELETE_TYPE_MAILBOX:
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen /* mailbox is always deleted */
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen break;
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen case DSYNC_MAILBOX_DELETE_TYPE_DIR:
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen if (other_del->timestamp <= node->last_renamed_or_created) {
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen /* we don't want to delete this directory, we already
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen have a newer timestamp for it */
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen *status_r = "keep directory, we have a newer timestamp";
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen return;
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen }
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen break;
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen case DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE:
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen if (other_del->timestamp <= node->last_subscription_change) {
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen /* we don't want to unsubscribe, since we already have
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen a newer subscription timestamp */
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen *status_r = "keep subscription, we have a newer timestamp";
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen return;
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen }
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen break;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* make a node for it in the other mailbox tree */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen name = dsync_mailbox_node_get_full_name(tree, node);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen other_node = dsync_mailbox_tree_get(other_tree, name);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
f5d3670e7e1c0da30a106ee8adef74afec657907Timo Sirainen if (other_node->existence == DSYNC_MAILBOX_NODE_EXISTS &&
f5d3670e7e1c0da30a106ee8adef74afec657907Timo Sirainen (!guid_128_is_empty(other_node->mailbox_guid) ||
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen other_del->type != DSYNC_MAILBOX_DELETE_TYPE_MAILBOX)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* other side has already created a new mailbox or
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen directory with this name, we can't delete it */
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen *status_r = "name has already been recreated";
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* ok, mark the other node deleted */
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen if (other_del->type == DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen memcpy(other_node->mailbox_guid, node->mailbox_guid,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen sizeof(other_node->mailbox_guid));
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen if (other_node->ns != node->ns && other_node->ns != NULL) {
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen /* namespace mismatch for this node. this shouldn't happen
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen normally, but especially during some misconfigurations it's
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen possible that one side has created mailboxes that conflict
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen with another namespace's prefix. since we're here because
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen one of the mailboxes was deleted, we'll just ignore this. */
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen *status_r = "namespace mismatch";
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen return;
22c646fc87e87f33008f55220d60961f98c9eb3eTimo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen other_node->ns = node->ns;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (other_del->type != DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE) {
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen other_node->existence = DSYNC_MAILBOX_NODE_DELETED;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen *status_r = "marked as deleted";
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen } else {
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen other_node->last_subscription_change = other_del->timestamp;
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen other_node->subscribed = FALSE;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen *status_r = "marked as unsubscribed";
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen if (dsync_mailbox_tree_guid_hash_add(other_tree, other_node,
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen &old_node) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_unreached();
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenbool dsync_brain_recv_mailbox_tree_deletes(struct dsync_brain *brain)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen const struct dsync_mailbox_node *node;
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen const char *status;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct dsync_mailbox_delete *deletes;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int i, count;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen char sep;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen if (dsync_ibc_recv_mailbox_deletes(brain->ibc, &deletes, &count,
a85473f7c11c8734bdee9c2cbe4b767f144a18aaTimo Sirainen &sep) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* apply remote's mailbox deletions based on our local tree */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_mailbox_tree_set_remote_sep(brain->local_mailbox_tree, sep);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; i < count; i++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_brain_mailbox_tree_add_delete(brain->local_mailbox_tree,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->remote_mailbox_tree,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen &deletes[i], &node, &status);
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen if (brain->debug) {
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen const char *node_name = node == NULL ? "" :
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen dsync_mailbox_node_get_full_name(brain->local_mailbox_tree, node);
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen i_debug("brain %c: Remote mailbox tree deletion: guid=%s type=%s timestamp=%ld name=%s local update=%s",
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen brain->master_brain ? 'M' : 'S',
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen guid_128_to_string(deletes[i].guid),
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen dsync_mailbox_delete_type_to_string(deletes[i].type),
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen deletes[i].timestamp, node_name, status);
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* apply local mailbox deletions based on remote tree */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen &count);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_mailbox_tree_set_remote_sep(brain->remote_mailbox_tree,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->hierarchy_sep);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; i < count; i++) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_brain_mailbox_tree_add_delete(brain->remote_mailbox_tree,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->local_mailbox_tree,
299451d50b891c83f4f5d921bc22715f24094236Timo Sirainen &deletes[i], &node, &status);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_brain_mailbox_trees_sync(brain);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->state = brain->master_brain ?
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DSYNC_STATE_MASTER_SEND_MAILBOX :
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen DSYNC_STATE_SLAVE_RECV_MAILBOX;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(brain->local_tree_iter == NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen brain->local_tree_iter =
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen dsync_mailbox_tree_iter_init(brain->local_mailbox_tree);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}