<commit_before>/* Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "mail-namespace.h"
#include "doveadm-settings.h"
#include "dsync-ibc.h"
#include "dsync-mailbox-tree.h"
#include "dsync-brain-private.h"

#include <ctype.h>

static void dsync_brain_check_namespaces(struct dsync_brain *brain)
{
	struct mail_namespace *ns, *first_ns = NULL;
	char sep;

	i_assert(brain->hierarchy_sep == '\0');

	if (brain->sync_ns != NULL) {
		brain->hierarchy_sep = mail_namespace_get_sep(brain->sync_ns);
		return;
	}

	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
		if (!dsync_brain_want_namespace(brain, ns))
			continue;

		sep = mail_namespace_get_sep(ns);
		if (first_ns == NULL) {
			brain->hierarchy_sep = sep;
			first_ns = ns;
		} else if (brain->hierarchy_sep != sep) {
			i_fatal("Synced namespaces have conflicting separators "
				"('%c' for prefix=\"%s\", '%c' for prefix=\"%s\")",
				brain->hierarchy_sep, first_ns->prefix,
				sep, ns->prefix);
		}
	}
	if (brain->hierarchy_sep != '\0')
		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)");
}

void dsync_brain_mailbox_trees_init(struct dsync_brain *brain)
{
	struct mail_namespace *ns;

	dsync_brain_check_namespaces(brain);

	brain->local_mailbox_tree =
		dsync_mailbox_tree_init(brain->hierarchy_sep,
					doveadm_settings->dsync_alt_char[0]);
	/* we'll convert remote mailbox names to use our own separator */
	brain->remote_mailbox_tree =
		dsync_mailbox_tree_init(brain->hierarchy_sep,
					doveadm_settings->dsync_alt_char[0]);

	/* fill the local mailbox tree */
	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
		if (!dsync_brain_want_namespace(brain, ns))
			continue;
		if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, ns,
					    brain->sync_box,
					    brain->sync_box_guid,
					    brain->exclude_mailboxes) < 0)
			brain->failed = TRUE;
	}

	brain->local_tree_iter =
		dsync_mailbox_tree_iter_init(brain->local_mailbox_tree);
}

void dsync_brain_send_mailbox_tree(struct dsync_brain *brain)
{
	struct dsync_mailbox_node *node;
	enum dsync_ibc_send_ret ret;
	const char *full_name;
	char sep[2];

	sep[0] = brain->hierarchy_sep; sep[1] = '\0';
	while (dsync_mailbox_tree_iter_next(brain->local_tree_iter,
					    &full_name, &node)) {
		T_BEGIN {
			const char *const *parts;

			parts = t_strsplit(full_name, sep);
			ret = dsync_ibc_send_mailbox_tree_node(brain->ibc,
							       parts, node);
		} T_END;
		if (ret == DSYNC_IBC_SEND_RET_FULL)
			return;
	}
	dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter);
	dsync_ibc_send_end_of_list(brain->ibc, DSYNC_IBC_EOL_MAILBOX_TREE);

	brain->state = DSYNC_STATE_SEND_MAILBOX_TREE_DELETES;
}

void dsync_brain_send_mailbox_tree_deletes(struct dsync_brain *brain)
{
	const struct dsync_mailbox_delete *deletes;
	unsigned int count;

	deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
						 &count);
	dsync_ibc_send_mailbox_deletes(brain->ibc, deletes, count,
				       brain->hierarchy_sep);

	brain->state = DSYNC_STATE_RECV_MAILBOX_TREE;
}

static bool
dsync_namespace_match_parts(struct mail_namespace *ns,
			    const char *const *name_parts)
{
	const char *part, *prefix = ns->prefix;
	unsigned int part_len;
	char ns_sep = mail_namespace_get_sep(ns);

	if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
	    strcmp(name_parts[0], "INBOX") == 0 && name_parts[1] == NULL)
		return TRUE;

	for (; *name_parts != NULL && *prefix != '\0'; name_parts++) {
		part = *name_parts;
		part_len = strlen(part);

		if (strncmp(prefix, part, part_len) != 0)
			return FALSE;
		if (prefix[part_len] != ns_sep)
			return FALSE;
		prefix += part_len + 1;
	}
	return *name_parts != NULL;
}

static struct mail_namespace *
dsync_find_namespace(struct dsync_brain *brain, const char *const *name_parts)
{
	struct mail_namespace *ns, *best_ns = NULL;

	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
		if (!dsync_brain_want_namespace(brain, ns))
			continue;<commit_msg>dsync: Fixed matching namespace for the namespace prefix itself.<commit_after>/* Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "mail-namespace.h"
#include "doveadm-settings.h"
#include "dsync-ibc.h"
#include "dsync-mailbox-tree.h"
#include "dsync-brain-private.h"

#include <ctype.h>

static void dsync_brain_check_namespaces(struct dsync_brain *brain)
{
	struct mail_namespace *ns, *first_ns = NULL;
	char sep;

	i_assert(brain->hierarchy_sep == '\0');

	if (brain->sync_ns != NULL) {
		brain->hierarchy_sep = mail_namespace_get_sep(brain->sync_ns);
		return;
	}

	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
		if (!dsync_brain_want_namespace(brain, ns))
			continue;

		sep = mail_namespace_get_sep(ns);
		if (first_ns == NULL) {
			brain->hierarchy_sep = sep;
			first_ns = ns;
		} else if (brain->hierarchy_sep != sep) {
			i_fatal("Synced namespaces have conflicting separators "
				"('%c' for prefix=\"%s\", '%c' for prefix=\"%s\")",
				brain->hierarchy_sep, first_ns->prefix,
				sep, ns->prefix);
		}
	}
	if (brain->hierarchy_sep != '\0')
		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)");
}

void dsync_brain_mailbox_trees_init(struct dsync_brain *brain)
{
	struct mail_namespace *ns;

	dsync_brain_check_namespaces(brain);

	brain->local_mailbox_tree =
		dsync_mailbox_tree_init(brain->hierarchy_sep,
					doveadm_settings->dsync_alt_char[0]);
	/* we'll convert remote mailbox names to use our own separator */
	brain->remote_mailbox_tree =
		dsync_mailbox_tree_init(brain->hierarchy_sep,
					doveadm_settings->dsync_alt_char[0]);

	/* fill the local mailbox tree */
	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
		if (!dsync_brain_want_namespace(brain, ns))
			continue;
		if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, ns,
					    brain->sync_box,
					    brain->sync_box_guid,
					    brain->exclude_mailboxes) < 0)
			brain->failed = TRUE;
	}

	brain->local_tree_iter =
		dsync_mailbox_tree_iter_init(brain->local_mailbox_tree);
}

void dsync_brain_send_mailbox_tree(struct dsync_brain *brain)
{
	struct dsync_mailbox_node *node;
	enum dsync_ibc_send_ret ret;
	const char *full_name;
	char sep[2];

	sep[0] = brain->hierarchy_sep; sep[1] = '\0';
	while (dsync_mailbox_tree_iter_next(brain->local_tree_iter,
					    &full_name, &node)) {
		T_BEGIN {
			const char *const *parts;

			parts = t_strsplit(full_name, sep);
			ret = dsync_ibc_send_mailbox_tree_node(brain->ibc,
							       parts, node);
		} T_END;
		if (ret == DSYNC_IBC_SEND_RET_FULL)
			return;
	}
	dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter);
	dsync_ibc_send_end_of_list(brain->ibc, DSYNC_IBC_EOL_MAILBOX_TREE);

	brain->state = DSYNC_STATE_SEND_MAILBOX_TREE_DELETES;
}

void dsync_brain_send_mailbox_tree_deletes(struct dsync_brain *brain)
{
	const struct dsync_mailbox_delete *deletes;
	unsigned int count;

	deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
						 &count);
	dsync_ibc_send_mailbox_deletes(brain->ibc, deletes, count,
				       brain->hierarchy_sep);

	brain->state = DSYNC_STATE_RECV_MAILBOX_TREE;
}

static bool
dsync_namespace_match_parts(struct mail_namespace *ns,
			    const char *const *name_parts)
{
	const char *part, *prefix = ns->prefix;
	unsigned int part_len;
	char ns_sep = mail_namespace_get_sep(ns);

	if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
	    strcmp(name_parts[0], "INBOX") == 0 && name_parts[1] == NULL)
		return TRUE;

	for (; *name_parts != NULL && *prefix != '\0'; name_parts++) {
		part = *name_parts;
		part_len = strlen(part);

		if (strncmp(prefix, part, part_len) != 0)
			return FALSE;
		if (prefix[part_len] != ns_sep)
			return FALSE;
		prefix += part_len + 1;
	}
	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 *
dsync_find_namespace(struct dsync_brain *brain, const char *const *name_parts)
{
	struct mail_namespace *ns, *best_ns = NULL;

	for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
		if (!dsync_brain_want_namespace(brain, ns))
			continue;
{'fraction_non_alphanumeric': 0.12767450017537707, 'fraction_numerical': 0.005728983982228458, 'mean_word_length': 4.6018336607727575, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2757069', 'n_tokens_mistral': 3579, 'n_tokens_neox': 3182, 'n_words': 652}