mailbox-alias-plugin.c revision fca7aa88ab19375aba5a8fd9d4100ea885dccb68
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#include "lib.h"
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#include "str.h"
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#include "mail-storage-hooks.h"
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#include "mail-storage-private.h"
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#include "mailbox-list-private.h"
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen#include "mailbox-alias-plugin.h"
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#define MAILBOX_ALIAS_USER_CONTEXT(obj) \
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_user_module)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen#define MAILBOX_ALIAS_CONTEXT(obj) \
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_storage_module)
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen#define MAILBOX_ALIAS_LIST_CONTEXT(obj) \
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_mailbox_list_module)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstruct mailbox_alias {
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen const char *old_vname, *new_vname;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen};
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainenstruct mailbox_alias_user {
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen union mail_user_module_context module_ctx;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen ARRAY(struct mailbox_alias) aliases;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen};
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstruct mailbox_alias_mailbox_list {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen union mailbox_list_module_context module_ctx;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen};
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstruct mailbox_alias_mailbox {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen union mailbox_module_context module_ctx;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen};
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenenum mailbox_symlink_existence {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_SYMLINK,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen};
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_user_module,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen &mail_user_module_register);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_storage_module,
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen &mail_storage_module_register);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_mailbox_list_module,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen &mailbox_list_module_register);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenconst char *mailbox_alias_plugin_version = DOVECOT_VERSION;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic const char *
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenmailbox_alias_find_new(struct mail_user *user, const char *new_vname)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen{
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen struct mailbox_alias_user *auser = MAILBOX_ALIAS_USER_CONTEXT(user);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen const struct mailbox_alias *alias;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen array_foreach(&auser->aliases, alias) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (strcmp(alias->new_vname, new_vname) == 0)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return alias->old_vname;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return NULL;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen}
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic int mailbox_symlink_exists(struct mailbox_list *list, const char *vname,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen enum mailbox_symlink_existence *existence_r)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen{
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen struct mailbox_alias_mailbox_list *alist =
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(list);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen struct stat st;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen const char *symlink_name, *symlink_path;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainen symlink_name = alist->module_ctx.super.get_storage_name(list, vname);
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainen symlink_path = mailbox_list_get_path(list, symlink_name,
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainen MAILBOX_LIST_PATH_TYPE_DIR);
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen if (lstat(symlink_path, &st) < 0) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (errno == ENOENT) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return 0;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mailbox_list_set_critical(list,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "lstat(%s) failed: %m", symlink_path);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return -1;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (S_ISLNK(st.st_mode))
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_SYMLINK;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen else
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return 0;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen}
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic int mailbox_is_alias_symlink(struct mailbox *box)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen{
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen enum mailbox_symlink_existence existence;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return 0;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (mailbox_symlink_exists(box->list, box->vname, &existence) < 0) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return -1;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK ? 1 : 0;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen}
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic int
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenmailbox_has_aliases(struct mailbox_list *list, const char *old_vname)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen{
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct mailbox_alias_user *auser =
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MAILBOX_ALIAS_USER_CONTEXT(list->ns->user);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen const struct mailbox_alias *alias;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen enum mailbox_symlink_existence existence;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen int ret = 0;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen array_foreach(&auser->aliases, alias) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (strcmp(alias->old_vname, old_vname) == 0) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (mailbox_symlink_exists(list, alias->new_vname,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen &existence) < 0)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen ret = -1;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return 1;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return ret;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen}
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic int
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenmailbox_alias_create_symlink(struct mailbox *box,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen const char *old_name, const char *new_name)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen{
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen const char *old_path, *new_path, *fname;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen old_path = mailbox_list_get_path(box->list, old_name,
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen new_path = mailbox_list_get_path(box->list, new_name,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MAILBOX_LIST_PATH_TYPE_DIR);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen fname = strrchr(old_path, '/');
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen i_assert(fname != NULL);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen fname++;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen i_assert(strncmp(new_path, old_path, fname-old_path) == 0);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (symlink(fname, new_path) < 0) {
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (errno == EEXIST) {
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen "Mailbox already exists");
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return -1;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen }
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen mail_storage_set_critical(box->storage,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen "symlink(%s, %s) failed: %m", fname, new_path);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return -1;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen }
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return 0;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen}
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenstatic const char *
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenmailbox_alias_get_storage_name(struct mailbox_list *list, const char *vname)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen{
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct mailbox_alias_mailbox_list *alist =
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(list);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen const char *old_vname;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen enum mailbox_symlink_existence existence;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen /* access the old mailbox so that e.g. full text search won't
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen index the mailbox twice. this also means that deletion must be
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen careful to delete the symlink, box->name. */
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen old_vname = mailbox_alias_find_new(list->ns->user, vname);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (old_vname != NULL &&
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen mailbox_symlink_exists(list, vname, &existence) == 0 &&
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen existence != MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen vname = old_vname;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return alist->module_ctx.super.get_storage_name(list, vname);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen}
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenstatic int
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenmailbox_alias_create(struct mailbox *box, const struct mailbox_update *update,
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen bool directory)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen{
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen struct mailbox_alias_mailbox_list *alist =
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(box->list);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen const char *symlink_name;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen int ret;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen ret = abox->module_ctx.super.create_box(box, update, directory);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen return ret;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (ret < 0 && mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return ret;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainen /* all the code so far has actually only created the original
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen mailbox. now we'll create the symlink if it's missing. */
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen symlink_name = alist->module_ctx.super.
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen get_storage_name(box->list, box->vname);
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen return mailbox_alias_create_symlink(box, box->name, symlink_name);
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen}
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainenstatic int mailbox_alias_delete(struct mailbox *box)
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen{
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen struct mailbox_alias_mailbox_list *alist =
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(box->list);
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen const char *symlink_name;
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen int ret;
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen ret = mailbox_has_aliases(box->list, box->vname);
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen if (ret < 0)
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen return -1;
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen if (ret > 0) {
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen "Can't delete mailbox while it has aliases");
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen return -1;
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen }
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen if (mailbox_is_alias_symlink(box)) {
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen /* we're deleting an alias mailbox. we'll need to handle this
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen explicitly since box->name points to the original mailbox */
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen symlink_name = alist->module_ctx.super.
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen get_storage_name(box->list, box->vname);
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen if (mailbox_list_delete_symlink(box->list, symlink_name) < 0) {
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return -1;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen }
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen return 0;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen }
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen return abox->module_ctx.super.delete_box(box);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen}
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenstatic int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest)
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen{
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(src);
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen int ret;
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen if (mailbox_is_alias_symlink(src)) {
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen "Can't rename alias mailboxes");
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen return -1;
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (mailbox_is_alias_symlink(dest)) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "Can't rename to mailbox alias");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return -1;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen ret = mailbox_has_aliases(src->list, src->vname);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (ret < 0)
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen return -1;
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen if (ret > 0) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "Can't rename mailbox while it has aliases");
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return -1;
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen }
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return abox->module_ctx.super.rename_box(src, dest);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen}
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenstatic void mailbox_alias_mail_user_created(struct mail_user *user)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen{
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen struct mail_user_vfuncs *v = user->vlast;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen struct mailbox_alias_user *auser;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen struct mailbox_alias *alias;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen string_t *oldkey, *newkey;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen const char *old_vname, *new_vname;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen unsigned int i;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen auser = p_new(user->pool, struct mailbox_alias_user, 1);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen auser->module_ctx.super = *v;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen user->vlast = &auser->module_ctx.super;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen p_array_init(&auser->aliases, user->pool, 8);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen oldkey = t_str_new(32);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen newkey = t_str_new(32);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen str_append(oldkey, "mailbox_alias_old");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen str_append(newkey, "mailbox_alias_new");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (i = 2;; i++) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen old_vname = mail_user_plugin_getenv(user, str_c(oldkey));
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen new_vname = mail_user_plugin_getenv(user, str_c(newkey));
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (old_vname == NULL || new_vname == NULL)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen break;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen alias = array_append_space(&auser->aliases);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen alias->old_vname = old_vname;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen alias->new_vname = new_vname;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen str_truncate(oldkey, 0);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen str_truncate(newkey, 0);
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen str_printfa(oldkey, "mailbox_alias_old%u", i);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen str_printfa(newkey, "mailbox_alias_new%u", i);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen }
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MODULE_CONTEXT_SET(user, mailbox_alias_user_module, auser);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen}
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
b3f4c31f1533e25380f49f77d5bb1251bf43db2aTimo Sirainenstatic void mailbox_alias_mailbox_list_created(struct mailbox_list *list)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen{
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen struct mailbox_list_vfuncs *v = list->vlast;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct mailbox_alias_mailbox_list *alist;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen alist = p_new(list->pool, struct mailbox_alias_mailbox_list, 1);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen alist->module_ctx.super = *v;
c096257fbdaf4b9fcf8eb97aae94afdbb4e71ed4Timo Sirainen list->vlast = &alist->module_ctx.super;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen v->get_storage_name = mailbox_alias_get_storage_name;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MODULE_CONTEXT_SET(list, mailbox_alias_mailbox_list_module, alist);
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen}
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainenstatic void mailbox_alias_mailbox_allocated(struct mailbox *box)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen{
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen struct mailbox_vfuncs *v = box->vlast;
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen struct mailbox_alias_mailbox *abox;
c096257fbdaf4b9fcf8eb97aae94afdbb4e71ed4Timo Sirainen
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen abox = p_new(box->pool, struct mailbox_alias_mailbox, 1);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen abox->module_ctx.super = *v;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen box->vlast = &abox->module_ctx.super;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen v->create_box = mailbox_alias_create;
c096257fbdaf4b9fcf8eb97aae94afdbb4e71ed4Timo Sirainen v->delete_box = mailbox_alias_delete;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen v->rename_box = mailbox_alias_rename;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen MODULE_CONTEXT_SET(box, mailbox_alias_storage_module, abox);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen}
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic struct mail_storage_hooks mailbox_alias_mail_storage_hooks = {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen .mail_user_created = mailbox_alias_mail_user_created,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen .mailbox_list_created = mailbox_alias_mailbox_list_created,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen .mailbox_allocated = mailbox_alias_mailbox_allocated
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen};
void mailbox_alias_plugin_init(struct module *module)
{
mail_storage_hooks_add(module, &mailbox_alias_mail_storage_hooks);
}
void mailbox_alias_plugin_deinit(void)
{
mail_storage_hooks_remove(&mailbox_alias_mail_storage_hooks);
}