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

#include "lib.h"
#include "array.h"
#include "llist.h"
#include "module-dir.h"
#include "mail-user.h"
#include "mail-namespace.h"
#include "mail-storage-private.h"
#include "mailbox-list-private.h"

struct mail_storage_module_hooks {
	struct module *module;
	const struct mail_storage_hooks *hooks;
	bool forced;
};

struct hook_stack {
	struct hook_stack *prev, *next;

	/* Pointer to vfuncs struct. This assumes that a struct containing
	   function pointers equals to an array of function pointers. Not
	   ANSI-C, but should work in all OSes supported by Dovecot. Much
	   easier anyway than doing this work manually.. */
	void (**vfuncs)();
	/* nonzero in the areas where vfuncs has been changed */
	void (**mask)();
};

struct hook_build_context {
	pool_t pool;
	/* size of the vfuncs struct */
	size_t size;
	/* number of function pointers in the struct */
	unsigned int count;

	struct hook_stack *head, *tail;
};

static ARRAY(struct mail_storage_module_hooks) module_hooks = ARRAY_INIT;
static ARRAY(const struct mail_storage_hooks *) internal_hooks = ARRAY_INIT;

void mail_storage_hooks_init(void)
{
	if (!array_is_created(&module_hooks))
		i_array_init(&module_hooks, 32);
	i_array_init(&internal_hooks, 8);
}

void mail_storage_hooks_deinit(void)
{
	array_free(&internal_hooks);
	array_free(&module_hooks);
}

void mail_storage_hooks_add(struct module *module,
			    const struct mail_storage_hooks *hooks)
{
	struct mail_storage_module_hooks new_hook;

	memset(&new_hook, 0, sizeof(new_hook));
	new_hook.module = module;
	new_hook.hooks = hooks;

	/* allow adding hooks before mail_storage_hooks_init() */
	if (!array_is_created(&module_hooks))
		i_array_init(&module_hooks, 32);
	array_append(&module_hooks, &new_hook, 1);
}

void mail_storage_hooks_add_forced(struct module *module,
				   const struct mail_storage_hooks *hooks)
{
	struct mail_storage_module_hooks *hook;

	mail_storage_hooks_add(module, hooks);
	hook = array_idx_modifiable(&module_hooks,
				    array_count(&module_hooks)-1);
	hook->forced = TRUE;
}

void mail_storage_hooks_remove(const struct mail_storage_hooks *hooks)
{
	const struct mail_storage_module_hooks *module_hook;
	unsigned int idx = UINT_MAX;

	array_foreach(&module_hooks, module_hook) {
		if (module_hook->hooks == hooks) {
			idx = array_foreach_idx(&module_hooks, module_hook);
			break;
		}
	}
	i_assert(idx != UINT_MAX);

	array_delete(&module_hooks, idx, 1);
}

void mail_storage_hooks_add_internal(const struct mail_storage_hooks *hooks)
{
	array_append(&internal_hooks, &hooks, 1);
}

void mail_storage_hooks_remove_internal(const struct mail_storage_hooks *hooks)
{
	const struct mail_storage_hooks *const *old_hooks;
	unsigned int idx = UINT_MAX;

	array_foreach(&internal_hooks, old_hooks) {
		if (*old_hooks == hooks) {
			idx = array_foreach_idx(&internal_hooks, old_hooks);
			break;
		}
	}
	i_assert(idx != UINT_MAX);

	array_delete(&internal_hooks, idx, 1);
}

static int
mail_storage_module_hooks_cmp(const struct mail_storage_module_hooks *h1,
			      const struct mail_storage_module_hooks *h2)
{
	const char *s1 = h1->module->path, *s2 = h2->module->path;
	const char *p;

	p = strrchr(s1, '/');
	if (p != NULL) s1 = p+1;
	p = strrchr(s2, '/');
	if (p != NULL) s2 = p+1;

	if (strncmp(s1, "lib", 3) == 0)
		s1 += 3;
	if (strncmp(s2, "lib", 3) == 0)
		s2 += 3;

	return strcmp(s1, s2);
}

static void mail_user_add_plugin_hooks(struct mail_user *user)
{
	const struct mail_storage_module_hooks *module_hook;
	ARRAY(struct mail_storage_module_hooks) tmp_hooks;
	const char *const *plugins, *name;

	/* first get all hooks wanted by the user */
	t_array_init(&tmp_hooks, array_count(&module_hooks));
	plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
	array_foreach(&module_hooks, module_hook) {
		name = module_get_plugin_name(module_hook->module);
		if (str_array_find(plugins, name) || module_hook->forced)
			array_append(&tmp_hooks, module_hook, 1);
	}

	/* next we have to sort them by the modules' priority (based on name) */
	array_sort(&tmp_hooks, mail_storage_module_hooks_cmp);

	/* now that we have them in order, save them to user's hooks */
	p_array_init(&user->hooks, user->pool,
		     array_count(&tmp_hooks) + array_count(&internal_hooks));
	array_foreach(&tmp_hooks, module_hook)
		array_append(&user->hooks, &module_hook->hooks, 1);
	array_append_array(&user->hooks, &internal_hooks);
}

static void hook_build_append(struct hook_build_context *ctx, void (**vfuncs)())<commit_msg>lib-storage: If hook is forced, don't bother checking if it's in user's mail_plugins.<commit_after>/* Copyright (c) 2009-2013 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "array.h"
#include "llist.h"
#include "module-dir.h"
#include "mail-user.h"
#include "mail-namespace.h"
#include "mail-storage-private.h"
#include "mailbox-list-private.h"

struct mail_storage_module_hooks {
	struct module *module;
	const struct mail_storage_hooks *hooks;
	bool forced;
};

struct hook_stack {
	struct hook_stack *prev, *next;

	/* Pointer to vfuncs struct. This assumes that a struct containing
	   function pointers equals to an array of function pointers. Not
	   ANSI-C, but should work in all OSes supported by Dovecot. Much
	   easier anyway than doing this work manually.. */
	void (**vfuncs)();
	/* nonzero in the areas where vfuncs has been changed */
	void (**mask)();
};

struct hook_build_context {
	pool_t pool;
	/* size of the vfuncs struct */
	size_t size;
	/* number of function pointers in the struct */
	unsigned int count;

	struct hook_stack *head, *tail;
};

static ARRAY(struct mail_storage_module_hooks) module_hooks = ARRAY_INIT;
static ARRAY(const struct mail_storage_hooks *) internal_hooks = ARRAY_INIT;

void mail_storage_hooks_init(void)
{
	if (!array_is_created(&module_hooks))
		i_array_init(&module_hooks, 32);
	i_array_init(&internal_hooks, 8);
}

void mail_storage_hooks_deinit(void)
{
	array_free(&internal_hooks);
	array_free(&module_hooks);
}

void mail_storage_hooks_add(struct module *module,
			    const struct mail_storage_hooks *hooks)
{
	struct mail_storage_module_hooks new_hook;

	memset(&new_hook, 0, sizeof(new_hook));
	new_hook.module = module;
	new_hook.hooks = hooks;

	/* allow adding hooks before mail_storage_hooks_init() */
	if (!array_is_created(&module_hooks))
		i_array_init(&module_hooks, 32);
	array_append(&module_hooks, &new_hook, 1);
}

void mail_storage_hooks_add_forced(struct module *module,
				   const struct mail_storage_hooks *hooks)
{
	struct mail_storage_module_hooks *hook;

	mail_storage_hooks_add(module, hooks);
	hook = array_idx_modifiable(&module_hooks,
				    array_count(&module_hooks)-1);
	hook->forced = TRUE;
}

void mail_storage_hooks_remove(const struct mail_storage_hooks *hooks)
{
	const struct mail_storage_module_hooks *module_hook;
	unsigned int idx = UINT_MAX;

	array_foreach(&module_hooks, module_hook) {
		if (module_hook->hooks == hooks) {
			idx = array_foreach_idx(&module_hooks, module_hook);
			break;
		}
	}
	i_assert(idx != UINT_MAX);

	array_delete(&module_hooks, idx, 1);
}

void mail_storage_hooks_add_internal(const struct mail_storage_hooks *hooks)
{
	array_append(&internal_hooks, &hooks, 1);
}

void mail_storage_hooks_remove_internal(const struct mail_storage_hooks *hooks)
{
	const struct mail_storage_hooks *const *old_hooks;
	unsigned int idx = UINT_MAX;

	array_foreach(&internal_hooks, old_hooks) {
		if (*old_hooks == hooks) {
			idx = array_foreach_idx(&internal_hooks, old_hooks);
			break;
		}
	}
	i_assert(idx != UINT_MAX);

	array_delete(&internal_hooks, idx, 1);
}

static int
mail_storage_module_hooks_cmp(const struct mail_storage_module_hooks *h1,
			      const struct mail_storage_module_hooks *h2)
{
	const char *s1 = h1->module->path, *s2 = h2->module->path;
	const char *p;

	p = strrchr(s1, '/');
	if (p != NULL) s1 = p+1;
	p = strrchr(s2, '/');
	if (p != NULL) s2 = p+1;

	if (strncmp(s1, "lib", 3) == 0)
		s1 += 3;
	if (strncmp(s2, "lib", 3) == 0)
		s2 += 3;

	return strcmp(s1, s2);
}

static void mail_user_add_plugin_hooks(struct mail_user *user)
{
	const struct mail_storage_module_hooks *module_hook;
	ARRAY(struct mail_storage_module_hooks) tmp_hooks;
	const char *const *plugins, *name;

	/* first get all hooks wanted by the user */
	t_array_init(&tmp_hooks, array_count(&module_hooks));
	plugins = t_strsplit_spaces(user->set->mail_plugins, ", ");
	array_foreach(&module_hooks, module_hook) {
		if (!module_hook->forced) {
			name = module_get_plugin_name(module_hook->module);
			if (!str_array_find(plugins, name))
				continue;
		}
		array_append(&tmp_hooks, module_hook, 1);
	}

	/* next we have to sort them by the modules' priority (based on name) */
	array_sort(&tmp_hooks, mail_storage_module_hooks_cmp);

	/* now that we have them in order, save them to user's hooks */
	p_array_init(&user->hooks, user->pool,
		     array_count(&tmp_hooks) + array_count(&internal_hooks));
	array_foreach(&tmp_hooks, module_hook)
		array_append(&user->hooks, &module_hook->hooks, 1);
	array_append_array(&user->hooks, &internal_hooks);
}

static void hook_build_append(struct hook_build_context *ctx, void (**vfuncs)())
{'fraction_non_alphanumeric': 0.11739271430115664, 'fraction_numerical': 0.009728677980758837, 'mean_word_length': 5.341329677861549, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, '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': '804936', 'n_tokens_mistral': 3376, 'n_tokens_neox': 3344, 'n_words': 791}