+ - dict pooling
- config rewrite
- - deliver: plugin var expanding
- - master: expands only known vars, not all_settings.. should it expand
- anything after all? use the 1/0 prefix to mark which vars have been
- expanded (config vs userdb)?
- go through mail-process.c. nfs test?
- support !include and !include_try
- - check plugins to make sure they're using only internal getenv()s,
- especially fix DEBUG env checks
- add back all setting verification code from master
- - put plugin settings to some plugins array, not envs, var expand
+ - plugins:
+ - backwards compatibility so userdb can continue returning quota_* etc?
+ - acl: master_user, acl_groups are now plugin envs..
- proxying: support fallbacking to local (or other?) server if the first
one is down
user_attrs {
#include "mail-user.h"
-struct mail_storage_root_settings;
-
enum namespace_type {
NAMESPACE_PRIVATE,
NAMESPACE_SHARED,
DEF(SET_UINT, umask),
DEFLIST(namespaces, "namespace", &mail_namespace_setting_parser_info),
+ { SET_STRLIST, "plugin", offsetof(struct mail_user_settings, plugin_envs), NULL },
SETTING_DEFINE_LIST_END
};
static struct mail_user_settings mail_user_default_settings = {
MEMBER(umask) 0077,
- MEMBER(namespaces) ARRAY_INIT
+ MEMBER(namespaces) ARRAY_INIT,
+ MEMBER(plugin_envs) ARRAY_INIT
};
struct setting_parser_info mail_user_setting_parser_info = {
unsigned int umask;
ARRAY_DEFINE(namespaces, struct mail_namespace_settings *);
+ ARRAY_DEFINE(plugin_envs, const char *);
};
extern struct setting_parser_info mail_user_setting_parser_info;
#include "array.h"
#include "hostpid.h"
#include "network.h"
+#include "str.h"
#include "var-expand.h"
#include "settings-parser.h"
#include "auth-master.h"
return user;
}
+static int
+mail_user_expand_plugins_envs(struct mail_user *user, const char **error_r)
+{
+ const char **envs, *home;
+ string_t *str;
+ unsigned int i, count;
+
+ if (!array_is_created(&user->set->plugin_envs))
+ return 0;
+
+ str = t_str_new(256);
+ envs = array_get_modifiable(&user->set->plugin_envs, &count);
+ i_assert((count % 2) == 0);
+ for (i = 0; i < count; i += 2) {
+ if (user->_home == NULL &&
+ var_has_key(envs[i+1], 'h', "home") &&
+ mail_user_get_home(user, &home) <= 0) {
+ *error_r = t_strdup_printf(
+ "userdb didn't return a home directory, "
+ "but plugin setting %s used it (%%h): %s",
+ envs[i], envs[i+1]);
+ return -1;
+ }
+ str_truncate(str, 0);
+ var_expand(str, envs[i+1], mail_user_var_expand_table(user));
+ envs[i+1] = p_strdup(user->pool, str_c(str));
+ }
+ return 0;
+}
+
int mail_user_init(struct mail_user *user, const char **error_r)
{
+ const struct mail_storage_settings *mail_set;
const char *home, *key, *value;
if (user->_home == NULL &&
settings_var_expand(&mail_user_setting_parser_info, user->set,
user->pool, mail_user_var_expand_table(user));
+ if (mail_user_expand_plugins_envs(user, error_r) < 0)
+ return -1;
+
+ mail_set = mail_user_set_get_driver_settings(user->set, "MAIL");
+ user->mail_debug = mail_set->mail_debug;
user->initialized = TRUE;
if (hook_mail_user_created != NULL)
return ret;
}
+const char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
+{
+ const char *const *envs;
+ unsigned int i, count, name_len = strlen(name);
+
+ if (!array_is_created(&user->set->plugin_envs))
+ return NULL;
+
+ envs = array_get(&user->set->plugin_envs, &count);
+ for (i = 0; i < count; i++) {
+ if (strncmp(envs[i], name, name_len) == 0 &&
+ envs[i][name_len] == '=')
+ return envs[i] + name_len + 1;
+ }
+ return NULL;
+}
+
int mail_user_try_home_expand(struct mail_user *user, const char **pathp)
{
const char *home, *path = *pathp;
#ifndef MAIL_USER_H
#define MAIL_USER_H
+#include "mail-storage-settings.h"
+
struct mail_user;
struct mail_user_vfuncs {
unsigned int admin:1;
/* mail_user_init() has been called */
unsigned int initialized:1;
+ /* Shortcut to mail_storage_settings.mail_debug */
+ unsigned int mail_debug:1;
};
struct mail_user_module_register {
successfully, 0 if there is no home directory (either user doesn't exist or
has no home directory) or -1 if lookup failed. */
int mail_user_get_home(struct mail_user *user, const char **home_r);
+/* If name exists in plugin_envs, return its value. */
+const char *mail_user_plugin_getenv(struct mail_user *user, const char *name);
/* Add more namespaces to user's namespaces. The ->next pointers may be
changed, so the namespaces pointer will be updated to user->namespaces. */
return list->ns;
}
+struct mail_user *
+mailbox_list_get_user(const struct mailbox_list *list)
+{
+ return list->ns->user;
+}
+
void mailbox_list_get_permissions(struct mailbox_list *list,
mode_t *mode_r, gid_t *gid_r)
{
mailbox_list_get_flags(const struct mailbox_list *list) ATTR_PURE;
struct mail_namespace *
mailbox_list_get_namespace(const struct mailbox_list *list) ATTR_PURE;
+struct mail_user *
+mailbox_list_get_user(const struct mailbox_list *list) ATTR_PURE;
/* Returns the mode and GID that should be used when creating new global files
to the mailbox list root directories. (gid_t)-1 is returned if it's not
return tab;
}
-static bool
-has_missing_used_home(const char *str, const struct var_expand_table *table)
+static void mail_process_set_environment(struct master_settings *set)
{
- i_assert(table[VAR_EXPAND_HOME_IDX].key == 'h');
-
- return table[VAR_EXPAND_HOME_IDX].value == NULL &&
- var_has_key(str, 'h', "home");
-}
-
-static void
-mail_process_set_environment(struct master_settings *set,
- const struct var_expand_table *table,
- string_t *expanded_vars)
-{
-
- const char **envs;
- string_t *str;
- unsigned int i, count;
-
- str_append(expanded_vars, "VARS_EXPANDED=");
-
/* we don't know all the settings, so since we can't expand all of
them just let the mail process expand all of them internally.
except for plugin settings - we know all of them so expand them. */
master_settings_export_to_env(set);
(void)umask(set->umask);
-
- if (array_is_created(&set->plugin_envs))
- envs = array_get_modifiable(&set->plugin_envs, &count);
- else {
- count = 0;
- envs = NULL;
- }
- str = t_str_new(256);
- i_assert((count % 2) == 0);
- for (i = 0; i < count; i += 2) {
- if (has_missing_used_home(envs[i+1], table)) {
- i_error("userdb didn't return a home directory, "
- "but it's used in plugin setting %s: %s",
- envs[i], envs[i+1]);
- }
- str_truncate(str, 0);
- var_expand(str, envs[i+1], table);
- env_put(t_strconcat(t_str_ucase(envs[i]), "=", str_c(str), NULL));
-
- str_append(expanded_vars, envs[i]);
- str_append_c(expanded_vars, ' ');
- }
}
void mail_process_exec(const char *protocol, const char **args)
const struct var_expand_table *var_expand_table;
struct master_settings *set;
const char *executable;
- string_t *expanded_vars;
if (strcmp(protocol, "ext") == 0) {
/* external binary. section contains path for it. */
env_put(str_c(str));
}
- expanded_vars = t_str_new(128);
- mail_process_set_environment(set, var_expand_table, expanded_vars);
- env_put(str_c(expanded_vars));
-
+ mail_process_set_environment(set);
if (args == NULL)
client_process_exec(executable, "");
else
i_fatal("chdir(/tmp) failed: %m");
}
- expanded_vars = t_str_new(128);
- mail_process_set_environment(set, var_expand_table, expanded_vars);
+ mail_process_set_environment(set);
/* extra args. uppercase key value. */
+ expanded_vars = t_str_new(128);
+ str_append(expanded_vars, "VARS_EXPANDED=");
args = array_get(&extra_args, &count);
for (i = 0; i < count; i++) {
if (*args[i] == '=') {
unsigned int i, count;
sets = array_get(&set->all_settings, &count);
- for (i = 0; i < count; i++) {
- if (strncmp(sets[i], "plugin/", 7) != 0)
- env_put(sets[i]);
- }
+ for (i = 0; i < count; i++)
+ env_put(sets[i]);
}
void master_settings_init(void)
#include "lib.h"
#include "hash.h"
+#include "mail-storage-settings.h"
+#include "mailbox-list.h"
+#include "mail-user.h"
#include "acl-cache.h"
#include "acl-api-private.h"
const char *acl_username, const char *const *groups,
bool owner)
{
+ struct mail_user *user = mailbox_list_get_user(list);
struct acl_backend *backend;
unsigned int i, group_count;
- bool debug;
- debug = getenv("DEBUG") != NULL;
- if (debug) {
+ if (user->mail_debug) {
i_info("acl: initializing backend with data: %s", data);
i_info("acl: acl username = %s", acl_username);
i_info("acl: owner = %d", owner);
i_fatal("Unknown ACL backend: %s", t_strcut(data, ':'));
backend = acl_backend_vfile.alloc();
- backend->debug = debug;
+ backend->debug = user->mail_debug;
backend->v = acl_backend_vfile;
backend->list = list;
backend->username = p_strdup(backend->pool, acl_username);
struct acl_lookup_dict {
struct mail_user *user;
+ struct dict *dict;
};
struct acl_lookup_dict_iter {
unsigned int failed:1;
};
-static struct dict *acl_dict;
-
-void acl_lookup_dicts_init(void)
-{
- const char *uri;
-
- uri = getenv("ACL_SHARED_DICT");
- if (uri == NULL) {
- if (getenv("DEBUG") != NULL) {
- i_info("acl: No acl_shared_dict setting - "
- "shared mailbox listing is disabled");
- }
- return;
- }
-
- acl_dict = dict_init(uri, DICT_DATA_TYPE_STRING, "");
- if (acl_dict == NULL)
- i_fatal("acl: dict_init(%s) failed", uri);
-}
-
-void acl_lookup_dicts_deinit(void)
-{
- if (acl_dict != NULL)
- dict_deinit(&acl_dict);
-}
-
struct acl_lookup_dict *acl_lookup_dict_init(struct mail_user *user)
{
struct acl_lookup_dict *dict;
+ const char *uri;
dict = i_new(struct acl_lookup_dict, 1);
dict->user = user;
+
+ uri = mail_user_plugin_getenv(user, "acl_shared_dict");
+ if (uri != NULL) {
+ dict->dict = dict_init(uri, DICT_DATA_TYPE_STRING, "");
+ if (dict->dict == NULL)
+ i_error("acl: dict_init(%s) failed", uri);
+ } else if (user->mail_debug) {
+ i_info("acl: No acl_shared_dict setting - "
+ "shared mailbox listing is disabled");
+ }
return dict;
}
struct acl_lookup_dict *dict = *_dict;
*_dict = NULL;
+ if (dict->dict != NULL)
+ dict_deinit(&dict->dict);
i_free(dict);
}
t_array_init(&old_ids_arr, 128);
prefix = DICT_PATH_SHARED DICT_SHARED_BOXES_PATH;
prefix_len = strlen(prefix);
- iter = dict_iterate_init(acl_dict, prefix, DICT_ITERATE_FLAG_RECURSE);
+ iter = dict_iterate_init(dict->dict, prefix, DICT_ITERATE_FLAG_RECURSE);
while ((ret = dict_iterate(iter, &key, &value)) > 0) {
/* prefix/$dest/$source */
key += prefix_len;
path = t_str_new(256);
str_append(path, prefix);
- dt = dict_transaction_begin(acl_dict);
+ dt = dict_transaction_begin(dict->dict);
new_ids = array_get(new_ids_arr, &new_count);
for (newi = oldi = 0; newi < new_count || oldi < old_count; ) {
ret = newi == new_count ? 1 :
unsigned int i, dest, count;
int ret = 0;
- if (acl_dict == NULL)
+ if (dict->dict == NULL)
return 0;
/* get all ACL identifiers with a positive lookup right */
DICT_SHARED_BOXES_PATH, *idp, "/", NULL);
iter->prefix_len = strlen(iter->prefix);
- iter->dict_iter = dict_iterate_init(acl_dict, iter->prefix,
+ iter->dict_iter = dict_iterate_init(iter->dict->dict, iter->prefix,
DICT_ITERATE_FLAG_RECURSE);
}
/* iterate through all identifiers that match us, start with the
first one */
- if (acl_dict != NULL)
+ if (dict->dict != NULL)
acl_lookup_dict_iterate_start(iter);
return iter;
}
#ifndef ACL_LOOKUP_DICT_H
#define ACL_LOOKUP_DICT_H
-void acl_lookup_dicts_init(void);
-void acl_lookup_dicts_deinit(void);
-
struct acl_lookup_dict *acl_lookup_dict_init(struct mail_user *user);
void acl_lookup_dict_deinit(struct acl_lookup_dict **dict);
void acl_mailbox_list_created(struct mailbox_list *list)
{
- if ((list->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0) {
+ struct acl_user *auser = ACL_USER_CONTEXT(list->ns->user);
+
+ if (auser == NULL) {
+ /* ACLs disabled for this user */
+ } else if ((list->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0) {
/* no ACL checks for internal namespaces (deliver, shared) */
if (list->ns->type == NAMESPACE_SHARED)
acl_mailbox_list_init_shared(list);
#include "lib.h"
#include "mailbox-list-private.h"
#include "acl-api.h"
-#include "acl-lookup-dict.h"
#include "acl-plugin.h"
#include <stdlib.h>
void acl_plugin_init(void)
{
- if (getenv("ACL") != NULL) {
- acl_next_hook_mail_storage_created =
- hook_mail_storage_created;
- hook_mail_storage_created = acl_mail_storage_created;
-
- acl_next_hook_mailbox_list_created = hook_mailbox_list_created;
- hook_mailbox_list_created = acl_mailbox_list_created;
-
- acl_next_hook_mail_user_created = hook_mail_user_created;
- hook_mail_user_created = acl_mail_user_created;
-
- acl_lookup_dicts_init();
- } else {
- if (getenv("DEBUG") != NULL)
- i_info("acl: No acl setting - ACLs are disabled");
- }
+ acl_next_hook_mail_storage_created = hook_mail_storage_created;
+ hook_mail_storage_created = acl_mail_storage_created;
+
+ acl_next_hook_mailbox_list_created = hook_mailbox_list_created;
+ hook_mailbox_list_created = acl_mailbox_list_created;
+
+ acl_next_hook_mail_user_created = hook_mail_user_created;
+ hook_mail_user_created = acl_mail_user_created;
}
void acl_plugin_deinit(void)
{
- if (acl_next_hook_mail_storage_created != NULL) {
- acl_lookup_dicts_deinit();
- hook_mail_storage_created = acl_next_hook_mail_storage_created;
- hook_mailbox_list_created = acl_next_hook_mailbox_list_created;
- hook_mail_user_created = acl_next_hook_mail_user_created;
- }
+ hook_mail_storage_created = acl_next_hook_mail_storage_created;
+ hook_mailbox_list_created = acl_next_hook_mailbox_list_created;
+ hook_mail_user_created = acl_next_hook_mail_user_created;
}
void acl_mail_storage_created(struct mail_storage *storage)
{
+ struct acl_user *auser = ACL_USER_CONTEXT(storage->ns->user);
struct acl_mail_storage *astorage;
struct acl_backend *backend;
- if ((storage->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0) {
+ if (auser == NULL) {
+ /* ACLs disabled for this user */
+ } else if ((storage->ns->flags & NAMESPACE_FLAG_INTERNAL) != 0) {
/* no ACL checks for internal namespaces (deliver) */
- return;
- }
-
- astorage = p_new(storage->pool, struct acl_mail_storage, 1);
- astorage->module_ctx.super = storage->v;
- storage->v.destroy = acl_storage_destroy;
- storage->v.mailbox_open = acl_mailbox_open;
- storage->v.mailbox_create = acl_mailbox_create;
+ } else {
+ astorage = p_new(storage->pool, struct acl_mail_storage, 1);
+ astorage->module_ctx.super = storage->v;
+ storage->v.destroy = acl_storage_destroy;
+ storage->v.mailbox_open = acl_mailbox_open;
+ storage->v.mailbox_create = acl_mailbox_create;
- backend = acl_mailbox_list_get_backend(mail_storage_get_list(storage));
- acl_storage_rights_ctx_init(&astorage->rights, backend);
+ backend = acl_mailbox_list_get_backend(mail_storage_get_list(storage));
+ acl_storage_rights_ctx_init(&astorage->rights, backend);
- MODULE_CONTEXT_SET(storage, acl_storage_module, astorage);
+ MODULE_CONTEXT_SET(storage, acl_storage_module, astorage);
+ }
if (acl_next_hook_mail_storage_created != NULL)
acl_next_hook_mail_storage_created(storage);
auser->module_ctx.super.deinit(user);
}
-void acl_mail_user_created(struct mail_user *user)
+static void acl_mail_user_create(struct mail_user *user, const char *env)
{
struct acl_user *auser;
- const char *env;
auser = p_new(user->pool, struct acl_user, 1);
auser->module_ctx.super = user->v;
user->v.deinit = acl_user_deinit;
auser->acl_lookup_dict = acl_lookup_dict_init(user);
- auser->acl_env = getenv("ACL");
- i_assert(auser->acl_env != NULL);
- auser->master_user = getenv("MASTER_USER");
+ auser->acl_env = env;
+ auser->master_user = mail_user_plugin_getenv(user, "master_user");
- env = getenv("ACL_GROUPS");
+ env = mail_user_plugin_getenv(user, "acl_groups");
if (env != NULL) {
auser->groups =
(const char *const *)p_strsplit(user->pool, env, ",");
}
MODULE_CONTEXT_SET(user, acl_user_module, auser);
+}
+
+void acl_mail_user_created(struct mail_user *user)
+{
+ const char *env;
+
+ env = mail_user_plugin_getenv(user, "acl");
+ if (env != NULL)
+ acl_mail_user_create(user, env);
+ else {
+ if (user->mail_debug)
+ i_info("acl: No acl setting - ACLs are disabled");
+ }
if (acl_next_hook_mail_user_created != NULL)
acl_next_hook_mail_user_created(user);
ns = mail_namespace_find(namespaces, &name);
if (ns == NULL) {
- if (getenv("DEBUG") != NULL)
+ if (namespaces->mail_set->mail_debug)
i_info("autocreate: No namespace found for %s", name);
return;
}
if (mail_storage_mailbox_create(ns->storage, name, FALSE) < 0) {
str = mail_storage_get_last_error(ns->storage, &error);
- if (error != MAIL_ERROR_EXISTS && getenv("DEBUG") != NULL) {
+ if (error != MAIL_ERROR_EXISTS && ns->mail_set->mail_debug) {
i_info("autocreate: Failed to create mailbox %s: %s",
name, str);
}
static void autocreate_mailboxes(struct mail_namespace *namespaces)
{
+ struct mail_user *user = namespaces->user;
char env_name[20];
const char *name;
unsigned int i;
i = 1;
- name = getenv("AUTOCREATE");
+ name = mail_user_plugin_getenv(user, "autocreate");
while (name != NULL) {
autocreate_mailbox(namespaces, name);
- i_snprintf(env_name, sizeof(env_name), "AUTOCREATE%d", ++i);
- name = getenv(env_name);
+ i_snprintf(env_name, sizeof(env_name), "autocreate%d", ++i);
+ name = mail_user_plugin_getenv(user, env_name);
}
}
static void autosubscribe_mailboxes(struct mail_namespace *namespaces)
{
+ struct mail_user *user = namespaces->user;
struct mail_namespace *ns;
char env_name[20];
const char *name;
unsigned int i;
i = 1;
- name = getenv("AUTOSUBSCRIBE");
+ name = mail_user_plugin_getenv(user, "autosubscribe");
while (name != NULL) {
ns = mail_namespace_find(namespaces, &name);
if (ns != NULL)
(void)mailbox_list_set_subscribed(ns->list, name, TRUE);
- i_snprintf(env_name, sizeof(env_name), "AUTOSUBSCRIBE%d", ++i);
- name = getenv(env_name);
+ i_snprintf(env_name, sizeof(env_name), "autosubscribe%d", ++i);
+ name = mail_user_plugin_getenv(user, env_name);
}
}
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
+ -I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-index \
-I$(top_srcdir)/src/lib-storage \
- -I$(top_srcdir)/src/lib-storage/index
+ -I$(top_srcdir)/src/lib-storage/index \
+ -DPKG_RUNDIR=\""$(rundir)"\"
lib20_convert_plugin_la_LDFLAGS = -module -avoid-version
convert-plugin.c
noinst_HEADERS = \
+ convert-settings.h \
convert-storage.h \
convert-plugin.h
pkglibexec_PROGRAMS = convert-tool
convert_tool_SOURCES = \
+ convert-settings.c \
convert-tool.c
common_objects = \
convert-storage.lo
-libs = $(STORAGE_LIBS)
+libs = $(STORAGE_LIBS) \
+ $(top_builddir)/src/lib-settings/libsettings.a
convert_tool_LDADD = \
$(common_objects) \
const char *convert_mail)
{
const char *str;
- struct convert_settings set;
+ struct convert_plugin_settings set;
memset(&set, 0, sizeof(set));
if (mail_user_get_home(namespaces->user, &str) <= 0)
i_fatal("convert plugin: HOME unset");
set.skip_broken_mailboxes =
- getenv("CONVERT_SKIP_BROKEN_MAILBOXES") != NULL;
- set.skip_dotdirs = getenv("CONVERT_SKIP_DOTDIRS") != NULL;
+ mail_user_plugin_getenv(namespaces->user,
+ "convert_skip_broken_mailboxes") != NULL;
+ set.skip_dotdirs =
+ mail_user_plugin_getenv(namespaces->user,
+ "convert_skip_dotdirs") != NULL;
- str = getenv("CONVERT_ALT_HIERARCHY_CHAR");
+ str = mail_user_plugin_getenv(namespaces->user,
+ "convert_alt_hierarchy_char");
set.alt_hierarchy_char = str != NULL && *str != '\0' ? *str : '_';
if (convert_storage(convert_mail, namespaces, &set) < 0)
{
const char *convert_mail;
- convert_mail = getenv("CONVERT_MAIL");
+ convert_mail = mail_user_plugin_getenv(namespaces->user,
+ "convert_mail");
if (convert_mail != NULL)
convert_mail_storage(namespaces, convert_mail);
- else if (getenv("DEBUG") != NULL)
+ else if (namespaces->user->mail_debug)
i_info("convert: No convert_mail setting - plugin disabled");
if (convert_next_hook_mail_namespaces_created != NULL)
--- /dev/null
+/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "settings-parser.h"
+#include "mail-storage-settings.h"
+#include "convert-settings.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#undef DEF
+#define DEF(type, name) \
+ { type, #name, offsetof(struct convert_settings, name), NULL }
+
+static struct setting_define convert_setting_defines[] = {
+ DEF(SET_STR, auth_socket_path),
+ { SET_STRLIST, "plugin", offsetof(struct convert_settings, plugin_envs), NULL },
+
+ SETTING_DEFINE_LIST_END
+};
+
+static struct convert_settings convert_default_settings = {
+ MEMBER(auth_socket_path) PKG_RUNDIR"/auth-master"
+};
+
+struct setting_parser_info convert_setting_parser_info = {
+ MEMBER(defines) convert_setting_defines,
+ MEMBER(defaults) &convert_default_settings,
+
+ MEMBER(parent) NULL,
+ MEMBER(parent_offset) (size_t)-1,
+ MEMBER(type_offset) (size_t)-1,
+ MEMBER(struct_size) sizeof(struct convert_settings)
+};
+
+static pool_t settings_pool = NULL;
+
+void convert_settings_read(const struct convert_settings **set_r,
+ const struct mail_user_settings **user_set_r)
+{
+ static const struct setting_parser_info *roots[] = {
+ &convert_setting_parser_info,
+ &mail_user_setting_parser_info
+ };
+ struct setting_parser_context *parser;
+ const char *const *expanded;
+ void **sets;
+
+ if (settings_pool == NULL)
+ settings_pool = pool_alloconly_create("convert settings", 1024);
+ else
+ p_clear(settings_pool);
+
+ mail_storage_namespace_defines_init(settings_pool);
+
+ parser = settings_parser_init_list(settings_pool,
+ roots, N_ELEMENTS(roots),
+ SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
+
+ if (settings_parse_environ(parser) < 0) {
+ i_fatal("Error reading configuration: %s",
+ settings_parser_get_error(parser));
+ }
+
+ expanded = t_strsplit(getenv("VARS_EXPANDED"), " ");
+ settings_parse_set_keys_expandeded(parser, settings_pool, expanded);
+
+ sets = settings_parser_get_list(parser);
+ *set_r = sets[0];
+ *user_set_r = sets[1];
+ settings_parser_deinit(&parser);
+}
--- /dev/null
+#ifndef CONVERT_SETTINGS_H
+#define CONVERT_SETTINGS_H
+
+struct mail_user_settings;
+
+struct convert_settings {
+ const char *auth_socket_path;
+
+ ARRAY_DEFINE(plugin_envs, const char *);
+};
+
+void convert_settings_read(const struct convert_settings **set_r,
+ const struct mail_user_settings **user_set_r);
+
+#endif
static const char *
mailbox_name_convert(struct mail_storage *dest_storage,
struct mail_storage *source_storage,
- const struct convert_settings *set, const char *name)
+ const struct convert_plugin_settings *set,
+ const char *name)
{
char *dest_name, *p, src_sep, dest_sep;
struct mail_storage *dest_storage,
const struct mailbox_info *info,
struct dotlock *dotlock,
- const struct convert_settings *set)
+ const struct convert_plugin_settings *set)
{
const char *name, *dest_name, *error;
struct mailbox *srcbox, *destbox;
static int mailbox_list_copy(struct mail_storage *source_storage,
struct mail_namespace *dest_namespaces,
struct dotlock *dotlock,
- const struct convert_settings *set)
+ const struct convert_plugin_settings *set)
{
struct mailbox_list_iterate_context *iter;
struct mail_namespace *dest_ns;
static int
mailbox_list_copy_subscriptions(struct mail_storage *source_storage,
struct mail_namespace *dest_namespaces,
- const struct convert_settings *set)
+ const struct convert_plugin_settings *set)
{
struct mailbox_list_iterate_context *iter;
struct mail_namespace *dest_ns;
int convert_storage(const char *source_data,
struct mail_namespace *dest_namespaces,
- const struct convert_settings *set)
+ const struct convert_plugin_settings *set)
{
struct mail_user *user = dest_namespaces->user;
- struct mail_namespace *source_ns, *dest_inbox_ns;
+ struct mail_namespace *source_ns;
struct dotlock *dotlock;
- enum mail_storage_flags src_flags;
- enum file_lock_method lock_method;
+ struct mail_namespace_settings ns_set;
const char *home, *path, *error;
int ret;
+ memset(&ns_set, 0, sizeof(ns_set));
+ ns_set.location = source_data;
+
source_ns = mail_namespaces_init_empty(user);
- dest_inbox_ns = mail_namespace_find_inbox(dest_namespaces);
- src_flags = dest_inbox_ns->storage->flags;
- lock_method = dest_inbox_ns->storage->lock_method;
+ source_ns->set = &ns_set;
- src_flags |= MAIL_STORAGE_FLAG_NO_AUTOCREATE;
- if (mail_storage_create(source_ns, NULL, source_data,
- src_flags, lock_method, &error) < 0) {
+ if (mail_storage_create(source_ns, NULL,
+ MAIL_STORAGE_FLAG_NO_AUTOCREATE, &error) < 0) {
/* No need for conversion. */
return 0;
}
i_unreached();
path = t_strconcat(home, "/"CONVERT_LOCK_FILENAME, NULL);
dotlock_settings.use_excl_lock =
- (source_ns->storage->flags &
- MAIL_STORAGE_FLAG_DOTLOCK_USE_EXCL) != 0;
+ source_ns->storage->set->dotlock_use_excl;
dotlock_settings.nfs_flush =
- (source_ns->storage->flags &
- MAIL_STORAGE_FLAG_NFS_FLUSH_STORAGE) != 0;
+ source_ns->storage->set->mail_nfs_storage;
ret = file_dotlock_create(&dotlock_settings, path, 0, &dotlock);
if (ret <= 0) {
if (ret == 0)
/* just in case if another process just had converted the mailbox,
reopen the source storage */
mail_storage_destroy(&source_ns->storage);
- if (mail_storage_create(source_ns, NULL, source_data,
- src_flags, lock_method, &error) < 0) {
+ if (mail_storage_create(source_ns, NULL,
+ MAIL_STORAGE_FLAG_NO_AUTOCREATE, &error) < 0) {
/* No need for conversion anymore. */
file_dotlock_delete(&dotlock);
return 0;
struct mail_namespace;
-struct convert_settings {
+struct convert_plugin_settings {
bool skip_broken_mailboxes;
bool skip_dotdirs;
char alt_hierarchy_char;
int convert_storage(const char *source_data,
struct mail_namespace *dest_namespaces,
- const struct convert_settings *set);
+ const struct convert_plugin_settings *set);
#endif
#include "lib-signals.h"
#include "mail-namespace.h"
#include "mail-storage-private.h"
+#include "convert-settings.h"
#include "convert-storage.h"
#include <stdlib.h>
int main(int argc, const char *argv[])
{
struct ioloop *ioloop;
- struct convert_settings set;
struct mail_user *user;
+ const struct convert_settings *set;
+ const struct mail_user_settings *user_set;
+ const struct mail_storage_settings *mail_set;
+ struct convert_plugin_settings set2;
struct mail_namespace *dest_ns;
- enum mail_storage_flags dest_flags;
- enum file_lock_method lock_method;
+ struct mail_namespace_settings ns_set;
const char *error;
int i, ret = 0;
lib_init();
lib_signals_init();
random_init();
- mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL);
mail_storage_init();
mail_storage_register_all();
mailbox_list_register_all();
+ convert_settings_read(&set, &user_set);
+ mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
+ mail_users_init(set->auth_socket_path, mail_set->mail_debug);
+
if (argc <= 4)
i_fatal(USAGE_STRING);
ioloop = io_loop_create();
- memset(&set, 0, sizeof(set));
+ memset(&set2, 0, sizeof(set2));
for (i = 5; i < argc; i++) {
if (strcmp(argv[i], "skip_broken_mailboxes") != 0)
- set.skip_broken_mailboxes = TRUE;
+ set2.skip_broken_mailboxes = TRUE;
else if (strcmp(argv[i], "skip_dotdirs") != 0)
- set.skip_dotdirs = TRUE;
+ set2.skip_dotdirs = TRUE;
else if (strncmp(argv[i], "alt_hierarchy_char=", 19) != 0)
- set.alt_hierarchy_char = argv[i][19];
+ set2.alt_hierarchy_char = argv[i][19];
}
- mail_storage_parse_env(&dest_flags, &lock_method);
- user = mail_user_init(argv[1]);
+ user = mail_user_alloc(argv[1], user_set);
mail_user_set_home(user, argv[2]);
+ mail_user_set_vars(user, geteuid(), "convert", NULL, NULL);
+ if (mail_user_init(user, &error) < 0)
+ i_fatal("Mail user initialization failed: %s", error);
+
+ memset(&ns_set, 0, sizeof(ns_set));
+ ns_set.location = argv[4];
+
dest_ns = mail_namespaces_init_empty(user);
+ dest_ns->set = &ns_set;
- if (mail_storage_create(dest_ns, NULL, argv[4],
- dest_flags, lock_method, &error) < 0) {
+ if (mail_storage_create(dest_ns, NULL, 0, &error) < 0) {
i_fatal("Failed to create destination "
"mail storage with data '%s': %s", argv[4], error);
}
- ret = convert_storage(argv[3], dest_ns, &set);
+ ret = convert_storage(argv[3], dest_ns, &set2);
if (ret > 0)
i_info("Successfully converted");
else if (ret == 0)
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-auth \
+ -I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-dict \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
noinst_HEADERS = \
auth-client.h \
expire-env.h \
- expire-plugin.h
+ expire-plugin.h \
+ expire-settings.h
pkglibexec_PROGRAMS = expire-tool
expire_tool_SOURCES = \
auth-client.c \
+ expire-settings.c \
expire-tool.c
libs = \
$(STORAGE_LIBS) \
+ $(top_builddir)/src/lib-settings/libsettings.a \
$(top_builddir)/src/lib-dict/libdict.a
expire_tool_LDADD = \
MODULE_CONTEXT(obj, expire_storage_module)
#define EXPIRE_MAIL_CONTEXT(obj) \
MODULE_CONTEXT(obj, expire_mail_module)
+#define EXPIRE_USER_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, expire_mail_user_module)
+
+struct expire_mail_user {
+ union mail_user_module_context module_ctx;
-struct expire {
struct dict *db;
struct expire_env *env;
-
- void (*next_hook_mail_storage_created)(struct mail_storage *storage);
};
struct expire_mailbox {
const char *expire_plugin_version = PACKAGE_VERSION;
-static struct expire expire;
+static void (*next_hook_mail_storage_created)(struct mail_storage *storage);
+static void (*next_hook_mail_user_created)(struct mail_user *user);
+
static MODULE_CONTEXT_DEFINE_INIT(expire_storage_module,
&mail_storage_module_register);
static MODULE_CONTEXT_DEFINE_INIT(expire_mail_module, &mail_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(expire_mail_user_module,
+ &mail_user_module_register);
static struct mailbox_transaction_context *
expire_mailbox_transaction_begin(struct mailbox *box,
uint32_t *first_saved_uid_r,
uint32_t *last_saved_uid_r)
{
+ struct expire_mail_user *euser =
+ EXPIRE_USER_CONTEXT(t->box->storage->ns->user);
struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
struct mailbox *box = t->box;
if (!xt->first_expunged && xt->saves) {
/* saved new mails. dict needs to be updated only if
this is the first mail in the database */
- ret = dict_lookup(expire.db, pool_datastack_create(),
+ ret = dict_lookup(euser->db, pool_datastack_create(),
key, &value);
update_dict = ret == 0 ||
(ret > 0 && strtoul(value, NULL, 10) == 0);
if (update_dict) {
struct dict_transaction_context *dctx;
- dctx = dict_transaction_begin(expire.db);
+ dctx = dict_transaction_begin(euser->db);
if (new_stamp == 0) {
/* everything expunged */
dict_unset(dctx, key);
expire_mailbox_open(struct mail_storage *storage, const char *name,
struct istream *input, enum mailbox_open_flags flags)
{
+ struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->ns->user);
union mail_storage_module_context *xpr_storage =
EXPIRE_CONTEXT(storage);
struct mailbox *box;
vname = t_str_new(128);
(void)mail_namespace_get_vname(storage->ns, vname, name);
- secs = expire_box_find_min_secs(expire.env, str_c(vname),
+ secs = expire_box_find_min_secs(euser->env, str_c(vname),
&altmove);
if (secs != 0)
mailbox_expire_hook(box, secs, altmove);
static void expire_mail_storage_created(struct mail_storage *storage)
{
+ struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(storage->ns->user);
union mail_storage_module_context *xpr_storage;
- xpr_storage =
- p_new(storage->pool, union mail_storage_module_context, 1);
- xpr_storage->super = storage->v;
- storage->v.mailbox_open = expire_mailbox_open;
+ if (euser != NULL) {
+ xpr_storage = p_new(storage->pool,
+ union mail_storage_module_context, 1);
+ xpr_storage->super = storage->v;
+ storage->v.mailbox_open = expire_mailbox_open;
- MODULE_CONTEXT_SET_SELF(storage, expire_storage_module, xpr_storage);
+ MODULE_CONTEXT_SET_SELF(storage, expire_storage_module,
+ xpr_storage);
+ }
- if (expire.next_hook_mail_storage_created != NULL)
- expire.next_hook_mail_storage_created(storage);
+ if (next_hook_mail_storage_created != NULL)
+ next_hook_mail_storage_created(storage);
}
-void expire_plugin_init(void)
+static void expire_mail_user_deinit(struct mail_user *user)
{
- const char *expunge_env, *altmove_env, *dict_uri;
+ struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(user);
+
+ dict_deinit(&euser->db);
+ expire_env_deinit(euser->env);
- expunge_env = getenv("EXPIRE");
- altmove_env = getenv("EXPIRE_ALTMOVE");
- if (expunge_env != NULL || altmove_env != NULL) {
- dict_uri = getenv("EXPIRE_DICT");
- if (dict_uri == NULL)
- i_fatal("expire plugin: expire_dict setting missing");
+ euser->module_ctx.super.deinit(user);
+}
+
+static void expire_mail_user_created(struct mail_user *user)
+{
+ struct expire_mail_user *euser;
+ const char *expunge_env, *altmove_env, *dict_uri;
- expire.env = expire_env_init(expunge_env, altmove_env);
+ expunge_env = mail_user_plugin_getenv(user, "expire");
+ altmove_env = mail_user_plugin_getenv(user, "expire_altmove");
+ dict_uri = mail_user_plugin_getenv(user, "expire_dict");
+ if (expunge_env == NULL && altmove_env == NULL) {
+ if (user->mail_debug) {
+ i_info("expire: No expire or expire_altmove settings - "
+ "plugin disabled");
+ }
+ } else if (dict_uri == NULL) {
+ i_error("expire plugin: expire_dict setting missing");
+ } else {
+ euser = p_new(user->pool, struct expire_mail_user, 1);
+ euser->module_ctx.super = user->v;
+ user->v.deinit = expire_mail_user_deinit;
+
+ euser->env = expire_env_init(expunge_env, altmove_env);
/* we're using only shared dictionary, the username
doesn't matter. */
- expire.db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "");
- if (expire.db == NULL)
- i_fatal("expire plugin: dict_init() failed");
-
- expire.next_hook_mail_storage_created =
- hook_mail_storage_created;
- hook_mail_storage_created = expire_mail_storage_created;
- } else if (getenv("DEBUG") != NULL) {
- i_info("expire: No expire or expire_altmove settings - "
- "plugin disabled");
+ euser->db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "");
+ if (euser->db == NULL)
+ i_error("expire plugin: dict_init(%s) failed", dict_uri);
+ else
+ MODULE_CONTEXT_SET(user, expire_mail_user_module, euser);
}
+
+ if (next_hook_mail_user_created != NULL)
+ next_hook_mail_user_created(user);
}
-void expire_plugin_deinit(void)
+void expire_plugin_init(void)
{
- if (expire.db != NULL) {
- hook_mail_storage_created =
- expire.next_hook_mail_storage_created;
+ next_hook_mail_storage_created = hook_mail_storage_created;
+ hook_mail_storage_created = expire_mail_storage_created;
- dict_deinit(&expire.db);
- expire_env_deinit(expire.env);
- }
+ next_hook_mail_user_created = hook_mail_user_created;
+ hook_mail_user_created = expire_mail_user_created;
+}
+
+void expire_plugin_deinit(void)
+{
+ hook_mail_storage_created = next_hook_mail_storage_created;
+ hook_mail_user_created = next_hook_mail_user_created;
}
--- /dev/null
+/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "settings-parser.h"
+#include "mail-storage-settings.h"
+#include "expire-settings.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#undef DEF
+#define DEF(type, name) \
+ { type, #name, offsetof(struct expire_settings, name), NULL }
+
+static struct setting_define expire_setting_defines[] = {
+ DEF(SET_STR, auth_socket_path),
+ { SET_STRLIST, "plugin", offsetof(struct expire_settings, plugin_envs), NULL },
+
+ SETTING_DEFINE_LIST_END
+};
+
+static struct expire_settings expire_default_settings = {
+ MEMBER(auth_socket_path) PKG_RUNDIR"/auth-master"
+};
+
+struct setting_parser_info expire_setting_parser_info = {
+ MEMBER(defines) expire_setting_defines,
+ MEMBER(defaults) &expire_default_settings,
+
+ MEMBER(parent) NULL,
+ MEMBER(parent_offset) (size_t)-1,
+ MEMBER(type_offset) (size_t)-1,
+ MEMBER(struct_size) sizeof(struct expire_settings)
+};
+
+static pool_t settings_pool = NULL;
+
+void expire_settings_read(const struct expire_settings **set_r,
+ const struct mail_user_settings **user_set_r)
+{
+ static const struct setting_parser_info *roots[] = {
+ &expire_setting_parser_info,
+ &mail_user_setting_parser_info
+ };
+ struct setting_parser_context *parser;
+ const char *const *expanded;
+ void **sets;
+
+ if (settings_pool == NULL)
+ settings_pool = pool_alloconly_create("expire settings", 1024);
+ else
+ p_clear(settings_pool);
+
+ mail_storage_namespace_defines_init(settings_pool);
+
+ parser = settings_parser_init_list(settings_pool,
+ roots, N_ELEMENTS(roots),
+ SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
+
+ if (settings_parse_environ(parser) < 0) {
+ i_fatal("Error reading configuration: %s",
+ settings_parser_get_error(parser));
+ }
+
+ expanded = t_strsplit(getenv("VARS_EXPANDED"), " ");
+ settings_parse_set_keys_expandeded(parser, settings_pool, expanded);
+
+ sets = settings_parser_get_list(parser);
+ *set_r = sets[0];
+ *user_set_r = sets[1];
+ settings_parser_deinit(&parser);
+}
--- /dev/null
+#ifndef CONVERT_SETTINGS_H
+#define CONVERT_SETTINGS_H
+
+struct mail_user_settings;
+
+struct expire_settings {
+ const char *auth_socket_path;
+
+ ARRAY_DEFINE(plugin_envs, const char *);
+};
+
+void expire_settings_read(const struct expire_settings **set_r,
+ const struct mail_user_settings **user_set_r);
+
+#endif
#include "auth-client.h"
#include "auth-master.h"
#include "expire-env.h"
+#include "expire-settings.h"
#include <stdlib.h>
dynamic object.. */
#include "expire-env.c"
-#define DEFAULT_AUTH_SOCKET_PATH PKG_RUNDIR"/auth-master"
-
struct expire_context {
struct auth_master_connection *auth_conn;
char *user;
struct mail_user *mail_user;
+ const struct expire_settings *set;
bool testrun;
};
static int user_init(struct expire_context *ctx, const char *user)
{
+ const struct mail_user_settings *user_set;
+ const char *error;
int ret;
env_clean();
return 0;
}
- ctx->mail_user = mail_user_init(user);
+ expire_settings_read(&ctx->set, &user_set);
+
+ ctx->mail_user = mail_user_alloc(user, user_set);
mail_user_set_home(ctx->mail_user, getenv("HOME"));
- if (mail_namespaces_init(ctx->mail_user) < 0)
+ mail_user_set_vars(ctx->mail_user, geteuid(), "expire", NULL, NULL);
+ if (mail_user_init(ctx->mail_user, &error) < 0) {
+ i_error("Mail user initialization failed: %s", error);
+ return -1;
+ }
+ if (mail_namespaces_init(ctx->mail_user, &error) < 0) {
+ i_error("Namespace initialization failed: %s", error);
return -1;
+ }
return 1;
}
return ret < 0 ? -1 : 0;
}
+static const char *expire_getenv(struct expire_context *ctx, const char *name)
+{
+ const char *const *envs;
+ unsigned int i, count, name_len = strlen(name);
+
+ if (!array_is_created(&ctx->set->plugin_envs))
+ return NULL;
+
+ envs = array_get(&ctx->set->plugin_envs, &count);
+ for (i = 0; i < count; i++) {
+ if (strncmp(envs[i], name, name_len) == 0 &&
+ envs[i][name_len] == '=')
+ return envs[i] + name_len + 1;
+ }
+ return NULL;
+}
+
static void expire_run(bool testrun)
{
struct expire_context ctx;
struct dict *dict = NULL;
struct dict_transaction_context *trans;
+ const struct mail_user_settings *user_set;
+ const struct mail_storage_settings *mail_set;
struct dict_iterate_context *iter;
struct expire_env *env;
time_t oldest;
unsigned int expunge_secs, altmove_secs;
- const char *auth_socket, *p, *key, *value;
+ const char *p, *key, *value;
const char *userp, *mailbox;
int ret;
dict_drivers_register_builtin();
- mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL);
mail_storage_init();
mail_storage_register_all();
mailbox_list_register_all();
- if (getenv("EXPIRE") == NULL && getenv("EXPIRE_ALTMOVE") == NULL)
+ memset(&ctx, 0, sizeof(ctx));
+ expire_settings_read(&ctx.set, &user_set);
+ mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
+ mail_users_init(ctx.set->auth_socket_path, mail_set->mail_debug);
+
+ if (expire_getenv(&ctx, "EXPIRE") == NULL &&
+ expire_getenv(&ctx, "EXPIRE_ALTMOVE") == NULL)
i_fatal("expire and expire_altmove settings not set");
- if (getenv("EXPIRE_DICT") == NULL)
+ if (expire_getenv(&ctx, "EXPIRE_DICT") == NULL)
i_fatal("expire_dict setting not set");
- auth_socket = getenv("AUTH_SOCKET_PATH");
- if (auth_socket == NULL)
- auth_socket = DEFAULT_AUTH_SOCKET_PATH;
-
- memset(&ctx, 0, sizeof(ctx));
ctx.testrun = testrun;
- ctx.auth_conn = auth_master_init(auth_socket, getenv("DEBUG") != NULL);
- env = expire_env_init(getenv("EXPIRE"), getenv("EXPIRE_ALTMOVE"));
- dict = dict_init(getenv("EXPIRE_DICT"), DICT_DATA_TYPE_UINT32, "");
+ ctx.auth_conn = auth_master_init(ctx.set->auth_socket_path,
+ mail_set->mail_debug);
+ env = expire_env_init(expire_getenv(&ctx, "EXPIRE"),
+ expire_getenv(&ctx, "EXPIRE_ALTMOVE"));
+ dict = dict_init(expire_getenv(&ctx, "EXPIRE_DICT"),
+ DICT_DATA_TYPE_UINT32, "");
if (dict == NULL)
i_fatal("dict_init() failed");
static struct fts_backend *
fts_backend_solr_init(struct mailbox *box)
{
- const struct fts_solr_settings *set = &fts_solr_settings;
+ struct fts_solr_user *fuser =
+ FTS_SOLR_USER_CONTEXT(box->storage->ns->user);
+ const struct fts_solr_settings *set = &fuser->set;
struct solr_fts_backend *backend;
struct mail_namespace *ns = box->storage->ns;
const char *str;
solr_conn = solr_connection_init(set->url, set->debug);
backend = i_new(struct solr_fts_backend, 1);
- str = fts_solr_settings.default_ns_prefix;
- if (str != NULL) {
+ if (set->default_ns_prefix != NULL) {
backend->default_ns =
- mail_namespace_find_prefix(ns->user->namespaces, str);
+ mail_namespace_find_prefix(ns->user->namespaces,
+ set->default_ns_prefix);
if (backend->default_ns == NULL) {
i_fatal("fts_solr: default_ns setting points to "
"nonexisting namespace");
/* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "array.h"
+#include "mail-user.h"
#include "fts-solr-plugin.h"
#include <stdlib.h>
const char *fts_solr_plugin_version = PACKAGE_VERSION;
-struct fts_solr_settings fts_solr_settings;
-static void fts_solr_plugin_init_settings(const char *str)
+static void (*fts_solr_next_hook_mail_user_created)(struct mail_user *user);
+struct fts_solr_user_module fts_solr_user_module =
+ MODULE_CONTEXT_INIT(&mail_user_module_register);
+
+static int
+fts_solr_plugin_init_settings(struct mail_user *user,
+ struct fts_solr_settings *set, const char *str)
{
- struct fts_solr_settings *set = &fts_solr_settings;
const char *const *tmp;
if (str == NULL)
for (tmp = t_strsplit_spaces(str, " "); *tmp != NULL; tmp++) {
if (strncmp(*tmp, "url=", 4) == 0) {
- i_free(set->url);
- set->url = i_strdup(*tmp + 4);
+ set->url = p_strdup(user->pool, *tmp + 4);
} else if (strcmp(*tmp, "debug") == 0) {
set->debug = TRUE;
} else if (strcmp(*tmp, "break-imap-search") == 0) {
set->substring_search = TRUE;
} else if (strcmp(*tmp, "default_ns=") == 0) {
- i_free(set->default_ns_prefix);
- set->default_ns_prefix = i_strdup(*tmp + 11);
+ set->default_ns_prefix =
+ p_strdup(user->pool, *tmp + 11);
} else {
- i_fatal("fts_solr: Invalid setting: %s", *tmp);
+ i_error("fts_solr: Invalid setting: %s", *tmp);
+ return -1;
}
}
- if (set->url == NULL)
- i_fatal("fts_solr: url setting missing");
+ if (set->url == NULL) {
+ i_error("fts_solr: url setting missing");
+ return -1;
+ }
+ return 0;
+}
+
+static void fts_solr_mail_user_create(struct mail_user *user, const char *env)
+{
+ struct fts_solr_user *fuser;
+
+ fuser = p_new(user->pool, struct fts_solr_user, 1);
+ fuser->module_ctx.super = user->v;
+ if (fts_solr_plugin_init_settings(user, &fuser->set, env) < 0) {
+ /* invalid settings, disabling */
+ return;
+ }
+
+ MODULE_CONTEXT_SET(user, fts_solr_user_module, fuser);
+}
+
+static void fts_solr_mail_user_created(struct mail_user *user)
+{
+ const char *env;
+
+ env = mail_user_plugin_getenv(user, "fts_solr");
+ if (env != NULL)
+ fts_solr_mail_user_create(user, env);
+
+ if (fts_solr_next_hook_mail_user_created != NULL)
+ fts_solr_next_hook_mail_user_created(user);
}
void fts_solr_plugin_init(void)
{
- fts_solr_plugin_init_settings(getenv("FTS_SOLR"));
fts_backend_register(&fts_backend_solr);
+
+ fts_solr_next_hook_mail_user_created = hook_mail_user_created;
+ hook_mail_user_created = fts_solr_mail_user_created;
}
void fts_solr_plugin_deinit(void)
{
- i_free(fts_solr_settings.url);
fts_backend_unregister(fts_backend_solr.name);
+ hook_mail_user_created = fts_solr_next_hook_mail_user_created;
}
#ifndef FTS_SOLR_PLUGIN_H
#define FTS_SOLR_PLUGIN_H
+#include "module-context.h"
#include "fts-api-private.h"
+#define FTS_SOLR_USER_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, fts_solr_user_module)
+
struct fts_solr_settings {
- char *url, *default_ns_prefix;
+ const char *url, *default_ns_prefix;
bool debug;
bool substring_search;
};
-extern struct fts_solr_settings fts_solr_settings;
+struct fts_solr_user {
+ union mail_user_module_context module_ctx;
+ struct fts_solr_settings set;
+};
+
extern struct fts_backend fts_backend_solr;
+extern MODULE_CONTEXT_DEFINE(fts_solr_user_module, &mail_user_module_register);
void fts_solr_plugin_init(void);
void fts_solr_plugin_deinit(void);
#include "lib.h"
#include "array.h"
+#include "mail-user.h"
+#include "mail-namespace.h"
#include "mail-storage-private.h"
#include "mail-search-build.h"
#include "squat-trie.h"
}
mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
- if (storage->set->mmap_disable || storage->set->mmap_no_write)
+ if (storage->set->mmap_disable)
flags |= SQUAT_INDEX_FLAG_MMAP_DISABLE;
if (storage->set->mail_nfs_index)
flags |= SQUAT_INDEX_FLAG_NFS_FLUSH;
flags, box->file_create_mode,
box->file_create_gid);
- env = getenv("FTS_SQUAT");
+ env = mail_user_plugin_getenv(box->storage->ns->user, "fts_squat");
if (env != NULL)
fts_backend_squat_set(backend, env);
return &backend->backend;
void fts_plugin_init(void)
{
- if (getenv("FTS") != NULL) {
- fts_next_hook_mailbox_opened = hook_mailbox_opened;
- hook_mailbox_opened = fts_mailbox_opened;
- } else if (getenv("DEBUG") != NULL)
- i_info("fts: No fts setting - plugin disabled");
+ fts_next_hook_mailbox_opened = hook_mailbox_opened;
+ hook_mailbox_opened = fts_mailbox_opened;
}
void fts_plugin_deinit(void)
{
- if (hook_mailbox_opened == fts_mailbox_opened)
- hook_mailbox_opened = fts_next_hook_mailbox_opened;
+ hook_mailbox_opened = fts_next_hook_mailbox_opened;
}
{
const char *env;
- env = getenv("FTS");
- i_assert(env != NULL);
- fts_mailbox_init(box, env);
+ env = mail_user_plugin_getenv(box->storage->ns->user, "fts");
+ if (env != NULL)
+ fts_mailbox_init(box, env);
if (fts_next_hook_mailbox_opened != NULL)
fts_next_hook_mailbox_opened(box);
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
+ -I$(top_srcdir)/src/lib-index \
-I$(top_srcdir)/src/lib-storage \
-I$(top_srcdir)/src/imap \
-I$(top_srcdir)/src/plugins/acl
#include "mail-namespace.h"
#include "acl-api.h"
#include "acl-storage.h"
+#include "acl-plugin.h"
#include "imap-acl-plugin.h"
#include <stdlib.h>
const char *imap_acl_plugin_version = PACKAGE_VERSION;
static void (*next_hook_client_created)(struct client **client);
-static bool acl_anyone_allow = FALSE;
static struct mailbox *
acl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
struct mailbox *box;
int ret;
+ if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
+ client_send_command_error(cmd, "ACLs disabled.");
+ return NULL;
+ }
+
storage = client_find_storage(cmd, &name);
if (storage == NULL)
return NULL;
return TRUE;
}
+ if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
+ client_send_command_error(cmd, "ACLs disabled.");
+ return TRUE;
+ }
+
real_mailbox = mailbox;
storage = client_find_storage(cmd, &real_mailbox);
if (storage == NULL)
return 0;
}
+static bool acl_anyone_allow(struct mail_user *user)
+{
+ const char *env;
+
+ env = mail_user_plugin_getenv(user, "acl_anyone");
+ return env != NULL && strcmp(env, "allow") == 0;
+}
+
static int
-imap_acl_identifier_parse(const char *id, struct acl_rights *rights,
+imap_acl_identifier_parse(struct client_command_context *cmd,
+ const char *id, struct acl_rights *rights,
bool check_anyone, const char **error_r)
{
+ struct mail_user *user = cmd->client->user;
+
if (strncmp(id, IMAP_ACL_GLOBAL_PREFIX,
strlen(IMAP_ACL_GLOBAL_PREFIX)) == 0) {
*error_r = t_strdup_printf("Global ACLs can't be modified: %s",
}
if (strcmp(id, IMAP_ACL_ANYONE) == 0) {
- if (!acl_anyone_allow && check_anyone) {
+ if (check_anyone && !acl_anyone_allow(user)) {
*error_r = "'anyone' identifier is disallowed";
return -1;
}
rights->id_type = ACL_ID_ANYONE;
} else if (strcmp(id, IMAP_ACL_AUTHENTICATED) == 0) {
- if (!acl_anyone_allow && check_anyone) {
+ if (check_anyone && !acl_anyone_allow(user)) {
*error_r = "'authenticated' identifier is disallowed";
return -1;
}
break;
}
- if (imap_acl_identifier_parse(identifier, &update.rights,
+ if (imap_acl_identifier_parse(cmd, identifier, &update.rights,
TRUE, &error) < 0) {
client_send_command_error(cmd, error);
return TRUE;
identifier++;
}
- if (imap_acl_identifier_parse(identifier, &update.rights,
+ if (imap_acl_identifier_parse(cmd, identifier, &update.rights,
FALSE, &error) < 0) {
client_send_command_error(cmd, error);
return TRUE;
void imap_acl_plugin_init(void)
{
- const char *env;
-
- if (getenv("ACL") == NULL)
- return;
-
- env = getenv("ACL_ANYONE");
- if (env != NULL)
- acl_anyone_allow = strcmp(env, "allow") == 0;
-
command_register("LISTRIGHTS", cmd_listrights, 0);
command_register("GETACL", cmd_getacl, 0);
command_register("MYRIGHTS", cmd_myrights, 0);
void imap_acl_plugin_deinit(void)
{
- if (getenv("ACL") == NULL)
- return;
-
command_unregister("GETACL");
command_unregister("MYRIGHTS");
command_unregister("SETACL");
static bool cmd_getquotaroot(struct client_command_context *cmd)
{
struct client *client = cmd->client;
+ struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
struct mail_storage *storage;
struct mail_namespace *ns;
struct mailbox *box;
}
ns = mail_storage_get_namespace(storage);
- if (quota_set == NULL || ns->owner == NULL) {
+ if (quser == NULL || ns->owner == NULL) {
mailbox_close(&box);
client_send_tagline(cmd, "OK No quota.");
return TRUE;
if (!client_read_string_args(cmd, 1, &root_name))
return FALSE;
- if (quota_set == NULL) {
- client_send_tagline(cmd, "OK No quota.");
- return TRUE;
- }
-
root = quota_root_lookup(cmd->client->user, root_name);
if (root == NULL && cmd->client->user->admin) {
/* we're an admin. see if there's a quota root for another
return TRUE;
}
- if (quota_set == NULL) {
- client_send_tagline(cmd, "OK No quota.");
- return TRUE;
- }
-
root = quota_root_lookup(cmd->client->user, root_name);
if (root == NULL) {
client_send_tagline(cmd, "NO Quota root doesn't exist.");
union mail_user_module_context module_ctx;
struct mail_namespace *lazy_ns[LAZY_NAMESPACE_COUNT];
+ const char *env;
};
struct lazy_expunge_mailbox_list {
static void lazy_expunge_mail_storage_init(struct mail_storage *storage)
{
+ struct lazy_expunge_mail_user *luser =
+ LAZY_EXPUNGE_USER_CONTEXT(storage->ns->user);
struct lazy_expunge_mailbox_list *llist =
LAZY_EXPUNGE_LIST_CONTEXT(storage->list);
struct lazy_expunge_mail_storage *lstorage;
const char *const *p;
unsigned int i;
+ if (llist == NULL)
+ return;
+
/* if this is one of our internal storages, mark it as such before
quota plugin sees it */
- p = t_strsplit_spaces(getenv("LAZY_EXPUNGE"), " ");
+ p = t_strsplit_spaces(luser->env, " ");
for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
if (strcmp(storage->ns->prefix, *p) == 0) {
storage->ns->flags |= NAMESPACE_FLAG_INTERNAL;
static void lazy_expunge_mailbox_list_created(struct mailbox_list *list)
{
+ struct lazy_expunge_mail_user *luser =
+ LAZY_EXPUNGE_USER_CONTEXT(list->ns->user);
struct lazy_expunge_mailbox_list *llist;
- if (lazy_expunge_next_hook_mailbox_list_created != NULL)
- lazy_expunge_next_hook_mailbox_list_created(list);
+ if (luser != NULL) {
+ llist = p_new(list->pool, struct lazy_expunge_mailbox_list, 1);
+ llist->module_ctx.super = list->v;
+ list->v.delete_mailbox = lazy_expunge_mailbox_list_delete;
- llist = p_new(list->pool, struct lazy_expunge_mailbox_list, 1);
- llist->module_ctx.super = list->v;
- list->v.delete_mailbox = lazy_expunge_mailbox_list_delete;
+ MODULE_CONTEXT_SET(list, lazy_expunge_mailbox_list_module,
+ llist);
+ }
- MODULE_CONTEXT_SET(list, lazy_expunge_mailbox_list_module, llist);
+ if (lazy_expunge_next_hook_mailbox_list_created != NULL)
+ lazy_expunge_next_hook_mailbox_list_created(list);
}
static void
const char *const *p;
int i;
- p = t_strsplit_spaces(getenv("LAZY_EXPUNGE"), " ");
+ if (luser == NULL)
+ return;
+
+ p = t_strsplit_spaces(luser->env, " ");
for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
const char *name = *p;
static void lazy_expunge_mail_user_created(struct mail_user *user)
{
struct lazy_expunge_mail_user *luser;
-
- luser = p_new(user->pool, struct lazy_expunge_mail_user, 1);
- luser->module_ctx.super = user->v;
-
- MODULE_CONTEXT_SET(user, lazy_expunge_mail_user_module, luser);
+ const char *env;
+
+ env = mail_user_plugin_getenv(user, "lazy_expunge");
+ if (env != NULL) {
+ luser = p_new(user->pool, struct lazy_expunge_mail_user, 1);
+ luser->module_ctx.super = user->v;
+ luser->env = env;
+
+ MODULE_CONTEXT_SET(user, lazy_expunge_mail_user_module, luser);
+ } else if (user->mail_debug) {
+ i_info("lazy_expunge: No lazy_expunge setting - "
+ "plugin disabled");
+ }
if (lazy_expunge_next_hook_mail_user_created != NULL)
lazy_expunge_next_hook_mail_user_created(user);
void lazy_expunge_plugin_init(void)
{
- if (getenv("LAZY_EXPUNGE") == NULL) {
- if (getenv("DEBUG") != NULL) {
- i_info("lazy_expunge: No lazy_expunge setting - "
- "plugin disabled");
- }
- return;
- }
-
lazy_expunge_next_hook_mail_namespaces_created =
hook_mail_namespaces_created;
hook_mail_namespaces_created =
void lazy_expunge_plugin_deinit(void)
{
- if (getenv("LAZY_EXPUNGE") != NULL)
- return;
-
hook_mail_namespaces_created =
lazy_expunge_hook_mail_namespaces_created;
hook_mail_storage_created = lazy_expunge_next_hook_mail_storage_created;
union mailbox_list_module_context module_ctx;
struct mailbox_info info;
string_t *list_name;
+ char escape_char;
bool name_escaped;
};
(struct mailbox_list *list);
static void (*listescape_next_hook_mail_namespaces_created)
(struct mail_namespace *namespaces);
-static char escape_char = DEFAULT_ESCAPE_CHAR;
static MODULE_CONTEXT_DEFINE_INIT(listescape_storage_module,
&mail_storage_module_register);
static const char *list_escape(struct mail_namespace *ns,
const char *str, bool change_sep)
{
+ struct listescape_mailbox_list *mlist =
+ LIST_ESCAPE_LIST_CONTEXT(ns->list);
string_t *esc = t_str_new(64);
if (*str == '~') {
- str_printfa(esc, "%c%02x", escape_char, *str);
+ str_printfa(esc, "%c%02x", mlist->escape_char, *str);
str++;
}
for (; *str != '\0'; str++) {
if (*str == ns->sep && change_sep)
str_append_c(esc, ns->list->hierarchy_sep);
else if (*str == ns->list->hierarchy_sep ||
- *str == escape_char || *str == '/')
- str_printfa(esc, "%c%02x", escape_char, *str);
+ *str == mlist->escape_char || *str == '/')
+ str_printfa(esc, "%c%02x", mlist->escape_char, *str);
else
str_append_c(esc, *str);
}
static void list_unescape_str(struct mail_namespace *ns,
const char *str, string_t *dest)
{
+ struct listescape_mailbox_list *mlist =
+ LIST_ESCAPE_LIST_CONTEXT(ns->list);
unsigned int num;
for (; *str != '\0'; str++) {
- if (*str == escape_char &&
+ if (*str == mlist->escape_char &&
i_isxdigit(str[1]) && i_isxdigit(str[2])) {
if (str[1] >= '0' && str[1] <= '9')
num = str[1] - '0';
static void listescape_mailbox_list_created(struct mailbox_list *list)
{
struct listescape_mailbox_list *mlist;
+ const char *env;
if (listescape_next_hook_mailbox_list_created != NULL)
listescape_next_hook_mailbox_list_created(list);
list->v.is_valid_existing_name = listescape_is_valid_existing_name;
list->v.is_valid_create_name = listescape_is_valid_create_name;
+ env = mail_user_plugin_getenv(list->ns->user, "listescape_char");
+ mlist->escape_char = env != NULL && *env != '\0' ?
+ env[0] : DEFAULT_ESCAPE_CHAR;
+
MODULE_CONTEXT_SET(list, listescape_list_module, mlist);
}
void listescape_plugin_init(void)
{
- const char *env;
-
- env = getenv("LISTESCAPE_CHAR");
- if (env != NULL && *env != '\0')
- escape_char = env[0];
-
listescape_next_hook_mail_storage_created = hook_mail_storage_created;
hook_mail_storage_created = listescape_mail_storage_created;
#include "imap-util.h"
#include "mail-storage-private.h"
#include "mailbox-list-private.h"
+#include "mail-user.h"
#include "mail-log-plugin.h"
#include <stdlib.h>
MODULE_CONTEXT(obj, mail_log_mail_module)
#define MAIL_LOG_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, mail_log_mailbox_list_module)
+#define MAIL_LOG_USER_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, mail_log_mail_user_module)
enum mail_log_field {
MAIL_LOG_FIELD_UID = 0x01,
NULL
};
-struct mail_log_settings {
+struct mail_log_user {
+ union mail_user_module_context module_ctx;
+
enum mail_log_field fields;
enum mail_log_event events;
const char *mail_log_plugin_version = PACKAGE_VERSION;
-static struct mail_log_settings mail_log_set;
-
static void (*mail_log_next_hook_mail_storage_created)
(struct mail_storage *storage);
static void (*mail_log_next_hook_mailbox_list_created)
(struct mailbox_list *list);
+static void (*mail_log_next_hook_mail_user_created)(struct mail_user *user);
static MODULE_CONTEXT_DEFINE_INIT(mail_log_storage_module,
&mail_storage_module_register);
static MODULE_CONTEXT_DEFINE_INIT(mail_log_mail_module, &mail_module_register);
static MODULE_CONTEXT_DEFINE_INIT(mail_log_mailbox_list_module,
&mailbox_list_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(mail_log_mail_user_module,
+ &mail_user_module_register);
static enum mail_log_field mail_log_field_find(const char *name)
{
struct mail *mail, enum mail_log_event event,
const char *data)
{
+ struct mail_log_user *muser =
+ MAIL_LOG_USER_CONTEXT(mail->box->storage->ns->user);
struct mail_log_group_changes *group;
uoff_t size;
group = mail_log_action_get_group(lt, event, data);
- if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0) {
+ if ((muser->fields & MAIL_LOG_FIELD_UID) != 0) {
if (!array_is_created(&group->uids))
p_array_init(&group->uids, lt->pool, 32);
seq_range_array_add(&group->uids, 0, mail->uid);
}
- if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
+ if ((muser->fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
(event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
if (mail_get_physical_size(mail, &size) == 0)
group->psize_total += size;
}
- if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
+ if ((muser->fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
(event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
if (mail_get_virtual_size(mail, &size) == 0)
group->vsize_total += size;
static void
mail_log_group(struct mailbox *box, const struct mail_log_group_changes *group)
{
+ struct mail_log_user *muser =
+ MAIL_LOG_USER_CONTEXT(box->storage->ns->user);
const struct seq_range *range;
unsigned int i, count;
string_t *str;
str = t_str_new(128);
str_printfa(str, "%s: ", mail_log_event_get_name(group->event));
- if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 &&
+ if ((muser->fields & MAIL_LOG_FIELD_UID) != 0 &&
array_is_created(&group->uids)) {
str_append(str, "uids=");
str_append(str, ", ");
}
- if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
+ if ((muser->fields & MAIL_LOG_FIELD_BOX) != 0)
mail_log_append_mailbox_name(str, box);
if (group->event == MAIL_LOG_EVENT_COPY)
const char *data)
{
struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(dest_trans);
+ struct mail_log_user *muser =
+ MAIL_LOG_USER_CONTEXT(mail->box->storage->ns->user);
uoff_t size;
string_t *str;
- if ((mail_log_set.events & event) == 0)
+ if ((muser->events & event) == 0)
return;
lt->changes++;
- if (mail_log_set.group_events) {
+ if (muser->group_events) {
mail_log_action_add_group(lt, mail, event, data);
return;
}
str = t_str_new(128);
str_printfa(str, "%s: ", mail_log_event_get_name(event));
- if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 && mail->uid != 0)
+ if ((muser->fields & MAIL_LOG_FIELD_UID) != 0 && mail->uid != 0)
str_printfa(str, "uid=%u, ", mail->uid);
- if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
+ if ((muser->fields & MAIL_LOG_FIELD_BOX) != 0)
mail_log_append_mailbox_name(str, mail->box);
- if ((mail_log_set.fields & MAIL_LOG_FIELD_FLAGS) != 0) {
+ if ((muser->fields & MAIL_LOG_FIELD_FLAGS) != 0) {
str_printfa(str, "flags=(");
imap_write_flags(str, mail_get_flags(mail),
mail_get_keywords(mail));
if (event == MAIL_LOG_EVENT_COPY)
str_printfa(str, "dest=%s, ", data);
- if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0)
+ if ((muser->fields & MAIL_LOG_FIELD_MSGID) != 0)
mail_log_add_hdr(mail, str, "msgid", "Message-ID");
- if ((mail_log_set.fields & MAIL_LOG_FIELD_FROM) != 0)
+ if ((muser->fields & MAIL_LOG_FIELD_FROM) != 0)
mail_log_add_hdr(mail, str, "from", "From");
- if ((mail_log_set.fields & MAIL_LOG_FIELD_SUBJECT) != 0)
+ if ((muser->fields & MAIL_LOG_FIELD_SUBJECT) != 0)
mail_log_add_hdr(mail, str, "subject", "Subject");
- if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
+ if ((muser->fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
(event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
if (mail_get_physical_size(mail, &size) == 0)
str_printfa(str, "size=%"PRIuUOFF_T", ", size);
}
- if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
+ if ((muser->fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
(event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
if (mail_get_virtual_size(mail, &size) == 0)
str_printfa(str, "vsize=%"PRIuUOFF_T", ", size);
{
struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
+ struct mail_log_user *muser =
+ MAIL_LOG_USER_CONTEXT(t->box->storage->ns->user);
- if (lt->changes > 0 && mail_log_set.group_events)
+ if (lt->changes > 0 && muser->group_events)
mail_log_group_changes(t->box, lt);
if (lt->tmp_mail != NULL)
mail_free(<->tmp_mail);
{
struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
+ struct mail_log_user *muser =
+ MAIL_LOG_USER_CONTEXT(t->box->storage->ns->user);
- if (lt->changes > 0 && !mail_log_set.group_events) {
+ if (lt->changes > 0 && !muser->group_events) {
i_info("Transaction rolled back: "
"Ignore last %u changes", lt->changes);
}
mail_log_mailbox_list_delete(struct mailbox_list *list, const char *name)
{
union mailbox_list_module_context *llist = MAIL_LOG_LIST_CONTEXT(list);
+ struct mail_log_user *muser = MAIL_LOG_USER_CONTEXT(list->ns->user);
if (llist->super.delete_mailbox(list, name) < 0)
return -1;
- if ((mail_log_set.events & MAIL_LOG_EVENT_MAILBOX_DELETE) == 0)
+ if ((muser->events & MAIL_LOG_EVENT_MAILBOX_DELETE) == 0)
return 0;
i_info("Mailbox deleted: %s", str_sanitize(name, MAILBOX_NAME_LOG_LEN));
const char *newname)
{
union mailbox_list_module_context *llist = MAIL_LOG_LIST_CONTEXT(list);
+ struct mail_log_user *muser = MAIL_LOG_USER_CONTEXT(list->ns->user);
if (llist->super.rename_mailbox(list, oldname, newname) < 0)
return -1;
- if ((mail_log_set.events & MAIL_LOG_EVENT_MAILBOX_RENAME) == 0)
+ if ((muser->events & MAIL_LOG_EVENT_MAILBOX_RENAME) == 0)
return 0;
i_info("Mailbox renamed: %s -> %s",
mail_log_next_hook_mailbox_list_created(list);
}
-static enum mail_log_field mail_log_parse_fields(const char *str)
+static int mail_log_parse_fields(const char *str, enum mail_log_field *fields_r)
{
const char *const *tmp;
static enum mail_log_field field, fields = 0;
for (tmp = t_strsplit_spaces(str, ", "); *tmp != NULL; tmp++) {
field = mail_log_field_find(*tmp);
- if (field == 0)
- i_fatal("Unknown field in mail_log_fields: '%s'", *tmp);
+ if (field == 0) {
+ i_error("Unknown field in mail_log_fields: '%s'", *tmp);
+ return -1;
+ }
fields |= field;
}
- return fields;
+ *fields_r = fields;
+ return 0;
}
-static enum mail_log_event mail_log_parse_events(const char *str)
+static int mail_log_parse_events(const char *str, enum mail_log_event *events_r)
{
const char *const *tmp;
static enum mail_log_event event, events = 0;
for (tmp = t_strsplit_spaces(str, ", "); *tmp != NULL; tmp++) {
event = mail_log_event_find(*tmp);
- if (event == 0)
- i_fatal("Unknown event in mail_log_events: '%s'", *tmp);
+ if (event == 0) {
+ i_error("Unknown event in mail_log_events: '%s'", *tmp);
+ return -1;
+ }
events |= event;
}
- return events;
+ *events_r = events;
+ return 0;
}
-static void mail_log_read_settings(struct mail_log_settings *set)
+static void
+mail_log_read_settings(struct mail_user *user, struct mail_log_user *muser)
{
const char *str;
- memset(set, 0, sizeof(*set));
+ str = mail_user_plugin_getenv(user, "mail_log_fields");
+ if (str == NULL || mail_log_parse_fields(str, &muser->fields) < 0)
+ muser->fields = MAIL_LOG_DEFAULT_FIELDS;
- str = getenv("MAIL_LOG_FIELDS");
- set->fields = str == NULL ? MAIL_LOG_DEFAULT_FIELDS :
- mail_log_parse_fields(str);
+ str = mail_user_plugin_getenv(user, "mail_log_events");
+ if (str == NULL || mail_log_parse_events(str, &muser->events) < 0)
+ muser->events = MAIL_LOG_DEFAULT_EVENTS;
- str = getenv("MAIL_LOG_EVENTS");
- set->events = str == NULL ? MAIL_LOG_DEFAULT_EVENTS :
- mail_log_parse_events(str);
+ muser->group_events =
+ mail_user_plugin_getenv(user, "mail_log_group_events") != NULL;
+}
+
+static void mail_log_mail_user_created(struct mail_user *user)
+{
+ struct mail_log_user *muser;
- set->group_events = getenv("MAIL_LOG_GROUP_EVENTS") != NULL;
+ muser = p_new(user->pool, struct mail_log_user, 1);
+ mail_log_read_settings(user, muser);
+ MODULE_CONTEXT_SET(user, mail_log_mail_user_module, muser);
+
+ if (mail_log_next_hook_mail_user_created != NULL)
+ mail_log_next_hook_mail_user_created(user);
}
void mail_log_plugin_init(void)
{
- mail_log_read_settings(&mail_log_set);
-
mail_log_next_hook_mail_storage_created = hook_mail_storage_created;
hook_mail_storage_created = mail_log_mail_storage_created;
mail_log_next_hook_mailbox_list_created = hook_mailbox_list_created;
hook_mailbox_list_created = mail_log_mailbox_list_created;
+
+ mail_log_next_hook_mail_user_created = hook_mail_user_created;
+ hook_mail_user_created = mail_log_mail_user_created;
}
void mail_log_plugin_deinit(void)
{
hook_mail_storage_created = mail_log_next_hook_mail_storage_created;
hook_mailbox_list_created = mail_log_next_hook_mailbox_list_created;
+ hook_mail_user_created = mail_log_next_hook_mail_user_created;
}
#include "mail-search-build.h"
#include "mail-storage-private.h"
#include "mailbox-list-private.h"
+#include "mail-user.h"
#include "mbox-snarf-plugin.h"
#include <stdlib.h>
/* use ~/mbox as the INBOX */
name = mstorage->snarf_inbox_path;
use_snarfing = TRUE;
- storage->set->mail_full_filesystem_access = TRUE;
+ //FIXME:storage->set->mail_full_filesystem_access = TRUE;
} else if (errno != ENOENT) {
mail_storage_set_critical(storage,
"stat(%s) failed: %m",
return box;
}
-static void mbox_snarf_mail_storage_created(struct mail_storage *storage)
+static void
+mbox_snarf_mail_storage_create(struct mail_storage *storage, const char *path)
{
struct mbox_snarf_mail_storage *mstorage;
- const char *path;
- path = mail_user_home_expand(storage->ns->user, getenv("MBOX_SNARF"));
+ path = mail_user_home_expand(storage->ns->user, path);
mstorage = p_new(storage->pool, struct mbox_snarf_mail_storage, 1);
mstorage->snarf_inbox_path = p_strdup(storage->pool, path);
mstorage->module_ctx.super = storage->v;
storage->v.mailbox_open = mbox_snarf_mailbox_open;
MODULE_CONTEXT_SET(storage, mbox_snarf_storage_module, mstorage);
+}
+
+static void mbox_snarf_mail_storage_created(struct mail_storage *storage)
+{
+ const char *path;
+
+ path = mail_user_plugin_getenv(storage->ns->user, "mbox_snarf");
+ if (path != NULL)
+ mbox_snarf_mail_storage_create(storage, path);
if (mbox_snarf_next_hook_mail_storage_created != NULL)
mbox_snarf_next_hook_mail_storage_created(storage);
void mbox_snarf_plugin_init(void)
{
- const char *path;
-
- path = getenv("MBOX_SNARF");
- if (path != NULL) {
- mbox_snarf_next_hook_mail_storage_created =
- hook_mail_storage_created;
- hook_mail_storage_created = mbox_snarf_mail_storage_created;
- } else if (getenv("DEBUG") != NULL)
- i_info("mbox_snarf: No mbox_snarf setting - plugin disabled");
+ mbox_snarf_next_hook_mail_storage_created = hook_mail_storage_created;
+ hook_mail_storage_created = mbox_snarf_mail_storage_created;
}
void mbox_snarf_plugin_deinit(void)
{
- if (getenv("MBOX_SNARF") != NULL) {
- hook_mail_storage_created =
- mbox_snarf_next_hook_mail_storage_created;
- }
+ hook_mail_storage_created = mbox_snarf_next_hook_mail_storage_created;
}
mode = 0600; dir_mode = 0700;
gid = dir_gid = (gid_t)-1;
storages = array_get(&root->root.quota->storages, &count);
+ i_assert(count > 0);
for (i = 0; i < count; i++) {
if ((storages[i]->ns->flags & NAMESPACE_FLAG_INBOX) != 0) {
mailbox_list_get_permissions(storages[i]->ns->list,
}
}
- dotlock_settings.use_excl_lock = getenv("DOTLOCK_USE_EXCL") != NULL;
- dotlock_settings.nfs_flush = getenv("MAIL_NFS_STORAGE") != NULL;
+ dotlock_settings.use_excl_lock = storages[0]->set->dotlock_use_excl;
+ dotlock_settings.nfs_flush = storages[0]->set->mail_nfs_storage;
fd = file_dotlock_open_mode(&dotlock_settings, path,
DOTLOCK_CREATE_FLAG_NONBLOCK,
mode, (uid_t)-1, gid, &dotlock);
void (*quota_next_hook_mailbox_list_created)(struct mailbox_list *list);
const char *quota_plugin_version = PACKAGE_VERSION;
-struct quota_settings *quota_set;
-
-static void quota_root_add_rules(const char *root_name,
- struct quota_root_settings *root_set)
-{
- const char *rule_name, *rule, *error;
- unsigned int i;
-
- rule_name = t_strconcat(root_name, "_RULE", NULL);
- for (i = 2;; i++) {
- rule = getenv(rule_name);
-
- if (rule == NULL)
- break;
-
- if (quota_root_add_rule(root_set, rule, &error) < 0) {
- i_fatal("Quota root %s: Invalid rule %s: %s",
- root_name, rule, error);
- }
- rule_name = t_strdup_printf("%s_RULE%d", root_name, i);
- }
-}
-
-static void quota_root_add_warning_rules(const char *root_name,
- struct quota_root_settings *root_set)
-{
- const char *rule_name, *rule, *error;
- unsigned int i;
-
- rule_name = t_strconcat(root_name, "_WARNING", NULL);
- for (i = 2;; i++) {
- rule = getenv(rule_name);
-
- if (rule == NULL)
- break;
-
- if (quota_root_add_warning_rule(root_set, rule, &error) < 0) {
- i_fatal("Quota root %s: Invalid warning rule: %s",
- root_name, rule);
- }
- rule_name = t_strdup_printf("%s_WARNING%d", root_name, i);
- }
-}
void quota_plugin_init(void)
{
- struct quota_root_settings *root_set;
- unsigned int i;
- const char *env;
-
- env = getenv("QUOTA");
- if (env == NULL) {
- if (getenv("DEBUG") != NULL)
- i_info("quota: No quota setting - plugin disabled");
- return;
- }
-
- quota_set = quota_settings_init();
-
- root_set = quota_root_settings_init(quota_set, env);
- if (root_set == NULL)
- i_fatal("Couldn't create quota root: %s", env);
- quota_root_add_rules("QUOTA", root_set);
- quota_root_add_warning_rules("QUOTA", root_set);
-
- for (i = 2;; i++) {
- const char *root_name;
-
- root_name = t_strdup_printf("QUOTA%d", i);
- env = getenv(root_name);
-
- if (env == NULL)
- break;
-
- root_set = quota_root_settings_init(quota_set, env);
- if (root_set == NULL)
- i_fatal("Couldn't create quota root: %s", env);
- quota_root_add_rules(root_name, root_set);
- quota_root_add_warning_rules(root_name, root_set);
- }
-
quota_next_hook_mail_user_created = hook_mail_user_created;
hook_mail_user_created = quota_mail_user_created;
void quota_plugin_deinit(void)
{
- if (quota_set != NULL) {
- hook_mail_user_created = quota_next_hook_mail_user_created;
- hook_mail_storage_created =
- quota_next_hook_mail_storage_created;
- hook_mailbox_list_created =
- quota_next_hook_mailbox_list_created;
- quota_settings_deinit("a_set);
- }
+ hook_mail_user_created = quota_next_hook_mail_user_created;
+ hook_mail_storage_created = quota_next_hook_mail_storage_created;
+ hook_mailbox_list_created = quota_next_hook_mailbox_list_created;
}
#ifndef QUOTA_PLUGIN_H
#define QUOTA_PLUGIN_H
+#include "module-context.h"
+
+#define QUOTA_USER_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, quota_user_module)
+
+struct quota_user {
+ union mail_user_module_context module_ctx;
+
+ struct quota *quota;
+};
+
struct mail_storage;
extern void (*quota_next_hook_mail_user_created)(struct mail_user *user);
(struct mail_storage *storage);
extern void (*quota_next_hook_mailbox_list_created)(struct mailbox_list *list);
-extern struct quota_settings *quota_set;
+extern MODULE_CONTEXT_DEFINE(quota_user_module, &mail_user_module_register);
void quota_mail_user_created(struct mail_user *user);
void quota_mail_storage_created(struct mail_storage *storage);
MODULE_CONTEXT(obj, quota_mail_module)
#define QUOTA_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, quota_mailbox_list_module)
-#define QUOTA_USER_CONTEXT(obj) \
- MODULE_CONTEXT(obj, quota_user_module)
-
-struct quota_user {
- union mail_user_module_context module_ctx;
-
- struct quota *quota;
-};
struct quota_mailbox_list {
union mailbox_list_module_context module_ctx;
unsigned int recalculate:1;
};
+struct quota_user_module quota_user_module =
+ MODULE_CONTEXT_INIT(&mail_user_module_register);
+
static MODULE_CONTEXT_DEFINE_INIT(quota_storage_module,
&mail_storage_module_register);
static MODULE_CONTEXT_DEFINE_INIT(quota_mail_module, &mail_module_register);
static MODULE_CONTEXT_DEFINE_INIT(quota_mailbox_list_module,
&mailbox_list_module_register);
-static MODULE_CONTEXT_DEFINE_INIT(quota_user_module,
- &mail_user_module_register);
static void quota_mail_expunge(struct mail *_mail)
{
void quota_mail_user_created(struct mail_user *user)
{
struct quota_user *quser;
-
- quser = p_new(user->pool, struct quota_user, 1);
- quser->module_ctx.super = user->v;
- user->v.deinit = quota_user_deinit;
- quser->quota = quota_init(quota_set, user);
-
- MODULE_CONTEXT_SET(user, quota_user_module, quser);
+ struct quota_settings *set;
+
+ set = quota_user_read_settings(user);
+ if (set != NULL) {
+ quser = p_new(user->pool, struct quota_user, 1);
+ quser->module_ctx.super = user->v;
+ user->v.deinit = quota_user_deinit;
+ quser->quota = quota_init(set, user);
+
+ MODULE_CONTEXT_SET(user, quota_user_module, quser);
+ } else if (user->mail_debug) {
+ i_info("quota: No quota setting - plugin disabled");
+ }
if (quota_next_hook_mail_user_created != NULL)
quota_next_hook_mail_user_created(user);
static int quota_default_test_alloc(struct quota_transaction_context *ctx,
uoff_t size, bool *too_large_r);
-struct quota_settings *quota_settings_init(void)
+static void quota_root_add_rules(struct mail_user *user, const char *root_name,
+ struct quota_root_settings *root_set)
+{
+ const char *rule_name, *rule, *error;
+ unsigned int i;
+
+ rule_name = t_strconcat(root_name, "_rule", NULL);
+ for (i = 2;; i++) {
+ rule = mail_user_plugin_getenv(user, rule_name);
+ if (rule == NULL)
+ break;
+
+ if (quota_root_add_rule(root_set, rule, &error) < 0) {
+ i_fatal("Quota root %s: Invalid rule %s: %s",
+ root_name, rule, error);
+ }
+ rule_name = t_strdup_printf("%s_rule%d", root_name, i);
+ }
+}
+
+static void
+quota_root_add_warning_rules(struct mail_user *user, const char *root_name,
+ struct quota_root_settings *root_set)
+{
+ const char *rule_name, *rule, *error;
+ unsigned int i;
+
+ rule_name = t_strconcat(root_name, "_warning", NULL);
+ for (i = 2;; i++) {
+ rule = mail_user_plugin_getenv(user, rule_name);
+ if (rule == NULL)
+ break;
+
+ if (quota_root_add_warning_rule(root_set, rule, &error) < 0) {
+ i_fatal("Quota root %s: Invalid warning rule: %s",
+ root_name, rule);
+ }
+ rule_name = t_strdup_printf("%s_warning%d", root_name, i);
+ }
+}
+
+struct quota_settings *quota_user_read_settings(struct mail_user *user)
{
struct quota_settings *quota_set;
+ struct quota_root_settings *root_set;
+ char root_name[6 + MAX_INT_STRLEN];
+ const char *env;
+ unsigned int i;
pool_t pool;
pool = pool_alloconly_create("quota settings", 1024);
quota_set = p_new(pool, struct quota_settings, 1);
quota_set->pool = pool;
quota_set->test_alloc = quota_default_test_alloc;
- quota_set->debug = getenv("DEBUG") != NULL;
- quota_set->quota_exceeded_msg = getenv("QUOTA_EXCEEDED_MESSAGE");
+ quota_set->debug = user->mail_debug;
+ quota_set->quota_exceeded_msg =
+ mail_user_plugin_getenv(user, "quota_exceeded_message");
if (quota_set->quota_exceeded_msg == NULL)
quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG;
+
p_array_init("a_set->root_sets, pool, 4);
+ i_strocpy(root_name, "quota", sizeof(root_name));
+ for (i = 2;; i++) {
+ env = mail_user_plugin_getenv(user, root_name);
+ if (env == NULL)
+ break;
+
+ root_set = quota_root_settings_init(quota_set, env);
+ if (root_set == NULL) {
+ i_fatal("Couldn't create quota root %s: %s",
+ root_name, env);
+ }
+ quota_root_add_rules(user, root_name, root_set);
+ quota_root_add_warning_rules(user, root_name, root_set);
+
+ i_snprintf(root_name, sizeof(root_name), "quota%d", i);
+ }
+
return quota_set;
}
struct quota_root_iter;
struct quota_transaction_context;
-struct quota_settings *quota_settings_init(void);
+struct quota_settings *quota_user_read_settings(struct mail_user *user);
void quota_settings_deinit(struct quota_settings **quota_set);
/* Set up a new quota root. */
}
if (size_expunged < size_needed) {
- if (getenv("DEBUG") != NULL) {
+ if (ctx->quota->user->mail_debug) {
i_info("trash plugin: Failed to remove enough messages "
"(needed %llu bytes, expunged only %llu bytes)",
(unsigned long long)size_needed,
for (i = 0; ; i++) {
ret = trash_next_quota_test_alloc(ctx, size, too_large_r);
if (ret != 0 || *too_large_r) {
- if (getenv("DEBUG") != NULL && *too_large_r) {
+ if (ctx->quota->user->mail_debug && *too_large_r) {
i_info("trash plugin: Mail is larger than "
"quota, won't even try to handle");
}
ret = -1;
}
- if (getenv("DEBUG") != NULL) {
+ if (user->mail_debug) {
i_info("trash plugin: Added '%s' with priority %d",
trash->name, trash->priority);
}
trash_hook_mail_namespaces_created(struct mail_namespace *namespaces)
{
struct mail_user *user = namespaces->user;
+ struct quota_user *quser = QUOTA_USER_CONTEXT(user);
struct trash_user *tuser;
const char *env;
- env = getenv("TRASH");
+ env = mail_user_plugin_getenv(user, "trash");
if (env == NULL) {
- if (getenv("DEBUG") != NULL)
+ if (user->mail_debug)
i_info("trash: No trash setting - plugin disabled");
- } else if (quota_set == NULL) {
+ } else if (quser == NULL) {
i_error("trash plugin: quota plugin not initialized");
} else {
tuser = p_new(user->pool, struct trash_user, 1);
MODULE_CONTEXT_SET(user, trash_user_module, tuser);
if (read_configuration(user, env) == 0) {
- trash_next_quota_test_alloc = quota_set->test_alloc;
- quota_set->test_alloc = trash_quota_test_alloc;
+ trash_next_quota_test_alloc =
+ quser->quota->set->test_alloc;
+ quser->quota->set->test_alloc = trash_quota_test_alloc;
}
}
void trash_plugin_deinit(void)
{
hook_mail_namespaces_created = trash_hook_mail_namespaces_created;
- quota_set->test_alloc = trash_next_quota_test_alloc;
}