/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "mail-namespace.h"
#include "dsync-ibc.h"
#include "dsync-mailbox-tree.h"
#include "dsync-brain-private.h"
#include <ctype.h>
{
char sep;
continue;
i_fatal("Synced namespaces have conflicting separators "
"('%c' for prefix=\"%s\", '%c' for prefix=\"%s\")",
}
}
return;
i_fatal("All your namespaces have a location setting. "
"Only namespaces with empty location settings are converted. "
"(One namespace should default to mail_location setting)");
}
{
/* we'll convert remote mailbox names to use our own separator */
/* fill the local mailbox tree */
continue;
i_debug("brain %c: Namespace %s has location %s",
&brain->mail_error) < 0) {
break;
}
}
}
{
const char *full_name;
T_BEGIN {
const char *const *parts;
i_debug("brain %c: Local mailbox tree: %s %s",
}
} T_END;
if (ret == DSYNC_IBC_SEND_RET_FULL)
return;
}
}
{
unsigned int count;
&count);
}
static bool
const char *const *name_parts)
{
return TRUE;
part = *name_parts;
return FALSE;
return FALSE;
}
if (*name_parts != NULL) {
/* namespace prefix found with a mailbox */
return TRUE;
}
if (*prefix == '\0') {
/* namespace prefix itself matched */
return TRUE;
}
return FALSE;
}
static struct mail_namespace *
{
continue;
if (ns->prefix_len == 0) {
/* prefix="" is the fallback namespace */
}
}
return best_ns;
}
static bool
{
bool ret;
mailbox_free(&box);
return ret;
}
static void
char alt_char)
{
const char *old_vname;
unsigned int i, start_pos;
else
start_pos = 0;
/* replace control chars */
if ((unsigned char)vname[i] < ' ')
}
/* make it valid UTF8 */
if (!uni_utf8_str_is_valid(vname)) {
if (uni_utf8_get_valid_data((const void *)old_vname,
i_unreached();
}
return;
/* 1) change any real separators to alt separators (this wouldn't
be necessary with listescape, but don't bother detecting it) */
}
return;
}
/* 2) '/' characters aren't valid without listescape */
if (vname[i] == '/')
}
return;
}
/* 3) probably some reserved name (e.g. dbox-Mails) */
return;
/* 4) name is too long? just give up and generate a unique name */
str_truncate(vname_str, 0);
}
static int
{
const char *p;
char ns_sep;
return -1;
/* build the mailbox name */
for (p = *name_parts; *p != '\0'; p++) {
if (*p != ns_sep)
str_append_c(vname, *p);
else
}
}
return 0;
}
{
if (brain->no_backup_overwrite)
else if (brain->backup_send)
else if (brain->backup_recv)
else
&brain->mail_error) < 0) {
break;
}
}
if (dsync_mailbox_trees_sync_deinit(&ctx) < 0)
}
{
&remote_node)) > 0) {
i_error("Couldn't find namespace for mailbox %s",
return TRUE;
}
i_debug("brain %c: Remote mailbox tree: %s %s",
}
}
if (ret != DSYNC_IBC_RECV_RET_FINISHED)
return changed;
i_error("Remote sent duplicate mailbox GUID %s for mailboxes %s and %s",
dup_node2));
}
return TRUE;
}
static void
struct dsync_mailbox_tree *other_tree,
const struct dsync_mailbox_delete *other_del,
const struct dsync_mailbox_node **node_r,
const char **status_r)
{
const char *name;
/* see if we can find the deletion based on mailbox tree that should
still have the mailbox */
*status_r = "not found";
return;
}
/* mailbox is always deleted */
break;
/* we don't want to delete this directory, we already
have a newer timestamp for it */
*status_r = "keep directory, we have a newer timestamp";
return;
}
break;
/* we don't want to unsubscribe, since we already have
a newer subscription timestamp */
*status_r = "keep subscription, we have a newer timestamp";
return;
}
break;
}
/* make a node for it in the other mailbox tree */
/* other side has already created a new mailbox or
directory with this name, we can't delete it */
*status_r = "name has already been recreated";
return;
}
/* ok, mark the other node deleted */
sizeof(other_node->mailbox_guid));
}
/* namespace mismatch for this node. this shouldn't happen
normally, but especially during some misconfigurations it's
possible that one side has created mailboxes that conflict
with another namespace's prefix. since we're here because
one of the mailboxes was deleted, we'll just ignore this. */
*status_r = "namespace mismatch";
return;
}
*status_r = "marked as deleted";
} else {
*status_r = "marked as unsubscribed";
}
&old_node) < 0)
i_unreached();
}
{
const char *status;
unsigned int i, count;
char sep;
&sep) == 0)
return FALSE;
/* apply remote's mailbox deletions based on our local tree */
for (i = 0; i < count; i++) {
i_debug("brain %c: Remote mailbox tree deletion: guid=%s type=%s timestamp=%ld name=%s local update=%s",
}
}
/* apply local mailbox deletions based on remote tree */
&count);
for (i = 0; i < count; i++) {
}
return TRUE;
}