bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
26650f5552a821a4e758baef2e0526432ea9abf7Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, mailbox_alias_user_module)
26650f5552a821a4e758baef2e0526432ea9abf7Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, mailbox_alias_storage_module)
26650f5552a821a4e758baef2e0526432ea9abf7Aki Tuomi MODULE_CONTEXT_REQUIRE(obj, mailbox_alias_mailbox_list_module)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_user_module,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_storage_module,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_mailbox_list_module,
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainenconst char *mailbox_alias_plugin_version = DOVECOT_ABI_VERSION;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic const char *
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenmailbox_alias_find_new(struct mail_user *user, const char *new_vname)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen struct mailbox_alias_user *auser = MAILBOX_ALIAS_USER_CONTEXT(user);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic int mailbox_symlink_exists(struct mailbox_list *list, const char *vname,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen symlink_name = alist->module_ctx.super.get_storage_name(list, vname);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = mailbox_list_get_path(list, symlink_name,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_SYMLINK;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic int mailbox_is_alias_symlink(struct mailbox *box)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
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 existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK ? 1 : 0;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenmailbox_has_aliases(struct mailbox_list *list, const char *old_vname)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if (strcmp(alias->old_vname, old_vname) == 0) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if (mailbox_symlink_exists(list, alias->new_vname,
f67c2a7415cbd1a783920cc84ded731dcafa4ffcTimo Sirainen else if (existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenmailbox_alias_create_symlink(struct mailbox *box,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = mailbox_list_get_path(box->list, old_name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = mailbox_list_get_path(box->list, new_name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen "Mailbox aliases not supported by storage");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen i_assert(strncmp(new_path, old_path, fname-old_path) == 0);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Mailbox already exists");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "symlink(%s, %s) failed: %m", fname, new_path);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic const char *
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenmailbox_alias_get_storage_name(struct mailbox_list *list, const char *vname)
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 mailbox_symlink_exists(list, vname, &existence) == 0 &&
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen existence != MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen return alist->module_ctx.super.get_storage_name(list, vname);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenmailbox_alias_create(struct mailbox *box, const struct mailbox_update *update,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
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 if (ret < 0 && mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
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 return mailbox_alias_create_symlink(box, box->name, symlink_name);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic int mailbox_alias_delete(struct mailbox *box)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen ret = mailbox_has_aliases(box->list, box->vname);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Can't delete mailbox while it has aliases");
e9fdf11b707cbff4686d742a74c261eda4a4a92aTimo Sirainen if ((ret = mailbox_is_alias_symlink(box)) < 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 if (mailbox_list_delete_symlink(box->list, symlink_name) < 0) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen mail_storage_copy_list_error(box->storage, box->list);
fca7aa88ab19375aba5a8fd9d4100ea885dccb68Timo Sirainen return abox->module_ctx.super.delete_box(box);
fca7aa88ab19375aba5a8fd9d4100ea885dccb68Timo Sirainenstatic int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(src);
e9fdf11b707cbff4686d742a74c261eda4a4a92aTimo Sirainen if ((ret = mailbox_is_alias_symlink(src)) < 0)
e9fdf11b707cbff4686d742a74c261eda4a4a92aTimo Sirainen else if (ret > 0) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Can't rename alias mailboxes");
e9fdf11b707cbff4686d742a74c261eda4a4a92aTimo Sirainen if ((ret = mailbox_is_alias_symlink(dest)) < 0)
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 ret = mailbox_has_aliases(src->list, src->vname);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Can't rename mailbox while it has aliases");
fca7aa88ab19375aba5a8fd9d4100ea885dccb68Timo Sirainen return abox->module_ctx.super.rename_box(src, dest);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic void mailbox_alias_mail_user_created(struct mail_user *user)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen unsigned int i;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen auser = p_new(user->pool, struct mailbox_alias_user, 1);
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 str_printfa(oldkey, "mailbox_alias_old%u", i);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen str_printfa(newkey, "mailbox_alias_new%u", i);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen MODULE_CONTEXT_SET(user, mailbox_alias_user_module, auser);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic void mailbox_alias_mailbox_list_created(struct mailbox_list *list)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen alist = p_new(list->pool, struct mailbox_alias_mailbox_list, 1);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen v->get_storage_name = mailbox_alias_get_storage_name;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen MODULE_CONTEXT_SET(list, mailbox_alias_mailbox_list_module, alist);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic void mailbox_alias_mailbox_allocated(struct mailbox *box)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen abox = p_new(box->pool, struct mailbox_alias_mailbox, 1);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen MODULE_CONTEXT_SET(box, mailbox_alias_storage_module, abox);
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 Sirainenvoid mailbox_alias_plugin_init(struct module *module)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen mail_storage_hooks_add(module, &mailbox_alias_mail_storage_hooks);