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