mailbox-alias-plugin.c revision d4002fe1f64d25a792f76fb102ef7dc519cd4e24
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#include "lib.h"
46552a931924c2d743f045e95b08c3ce6beda91aTimo Sirainen#include "str.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "mail-storage-hooks.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "mail-storage-private.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "mailbox-list-private.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "mailbox-alias-plugin.h"
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#define MAILBOX_ALIAS_USER_CONTEXT(obj) \
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_user_module)
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen#define MAILBOX_ALIAS_CONTEXT(obj) \
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_storage_module)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#define MAILBOX_ALIAS_LIST_CONTEXT(obj) \
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_mailbox_list_module)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstruct mailbox_alias {
53dfcefa9440a49d703e49193819a79be99c9ba6Timo Sirainen const char *old_vname, *new_vname;
f0d93763f210ecdb85a115fdd0210a16cfc5ff5cTimo Sirainen};
53dfcefa9440a49d703e49193819a79be99c9ba6Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstruct mailbox_alias_user {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen union mail_user_module_context module_ctx;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen ARRAY(struct mailbox_alias) aliases;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen};
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstruct mailbox_alias_mailbox_list {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen union mailbox_list_module_context module_ctx;
2e78f05b11df23ec2731afaf8f19d5b5240cb29fTimo Sirainen};
2e78f05b11df23ec2731afaf8f19d5b5240cb29fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstruct mailbox_alias_mailbox {
d1e7425048c61d71f41f737ba947687198842dc2Timo Sirainen union mailbox_module_context module_ctx;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen};
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenenum mailbox_symlink_existence {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_SYMLINK,
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen};
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_user_module,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen &mail_user_module_register);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_storage_module,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen &mail_storage_module_register);
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_mailbox_list_module,
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen &mailbox_list_module_register);
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenconst char *mailbox_alias_plugin_version = DOVECOT_ABI_VERSION;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic const char *
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenmailbox_alias_find_new(struct mail_user *user, const char *new_vname)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_user *auser = MAILBOX_ALIAS_USER_CONTEXT(user);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const struct mailbox_alias *alias;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen array_foreach(&auser->aliases, alias) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (strcmp(alias->new_vname, new_vname) == 0)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return alias->old_vname;
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return NULL;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int mailbox_symlink_exists(struct mailbox_list *list, const char *vname,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen enum mailbox_symlink_existence *existence_r)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox_list *alist =
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(list);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct stat st;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *symlink_name, *symlink_path;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen symlink_name = alist->module_ctx.super.get_storage_name(list, vname);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = mailbox_list_get_path(list, symlink_name,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR, &symlink_path);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ret < 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_assert(ret > 0);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (lstat(symlink_path, &st) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (errno == ENOENT) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mailbox_list_set_critical(list,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "lstat(%s) failed: %m", symlink_path);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen if (S_ISLNK(st.st_mode))
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_SYMLINK;
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen else
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int mailbox_is_alias_symlink(struct mailbox *box)
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen{
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen enum mailbox_symlink_existence existence;
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mailbox_symlink_exists(box->list, box->vname, &existence) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK ? 1 : 0;
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen}
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen
6303191abcb37164f435ccdc56e9dbddf1288851Timo Sirainenstatic int
6303191abcb37164f435ccdc56e9dbddf1288851Timo Sirainenmailbox_has_aliases(struct mailbox_list *list, const char *old_vname)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen{
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen struct mailbox_alias_user *auser =
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen MAILBOX_ALIAS_USER_CONTEXT(list->ns->user);
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen const struct mailbox_alias *alias;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen enum mailbox_symlink_existence existence;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int ret = 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen array_foreach(&auser->aliases, alias) {
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen if (strcmp(alias->old_vname, old_vname) == 0) {
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen if (mailbox_symlink_exists(list, alias->new_vname,
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen &existence) < 0)
5a250816ffc4cc5db203f9410ea99b6601c7b91aTimo Sirainen ret = -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen else if (existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK)
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen return 1;
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen }
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen }
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen return ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volkmailbox_alias_create_symlink(struct mailbox *box,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *old_name, const char *new_name)
2e2a1d720ed53490e8e5c5031e773d395bd5683dTimo Sirainen{
5a250816ffc4cc5db203f9410ea99b6601c7b91aTimo Sirainen const char *old_path, *new_path, *fname;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = mailbox_list_get_path(box->list, old_name,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR, &old_path);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ret > 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = mailbox_list_get_path(box->list, new_name,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen &new_path);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ret < 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ret == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "Mailbox aliases not supported by storage");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen fname = strrchr(old_path, '/');
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_assert(fname != NULL);
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen fname++;
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen i_assert(strncmp(new_path, old_path, fname-old_path) == 0);
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen if (symlink(fname, new_path) < 0) {
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen if (errno == EEXIST) {
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen "Mailbox already exists");
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen return -1;
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mailbox_set_critical(box,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "symlink(%s, %s) failed: %m", fname, new_path);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic const char *
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenmailbox_alias_get_storage_name(struct mailbox_list *list, const char *vname)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox_list *alist =
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(list);
ec23e16ed879e289d12c6e1a5f9745dd3979004aTimo Sirainen const char *old_vname;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen enum mailbox_symlink_existence existence;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* access the old mailbox so that e.g. full text search won't
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen index the mailbox twice. this also means that deletion must be
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen careful to delete the symlink, box->name. */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen old_vname = mailbox_alias_find_new(list->ns->user, vname);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (old_vname != NULL &&
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen mailbox_symlink_exists(list, vname, &existence) == 0 &&
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen existence != MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen vname = old_vname;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return alist->module_ctx.super.get_storage_name(list, vname);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenmailbox_alias_create(struct mailbox *box, const struct mailbox_update *update,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen bool directory)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox_list *alist =
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(box->list);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *symlink_name;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = abox->module_ctx.super.create_box(box, update, directory);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ret < 0 && mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* all the code so far has actually only created the original
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen mailbox. now we'll create the symlink if it's missing. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen symlink_name = alist->module_ctx.super.
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_storage_name(box->list, box->vname);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen return mailbox_alias_create_symlink(box, box->name, symlink_name);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int mailbox_alias_delete(struct mailbox *box)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox_list *alist =
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(box->list);
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen const char *symlink_name;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen ret = mailbox_has_aliases(box->list, box->vname);
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen if (ret < 0)
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen return -1;
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen if (ret > 0) {
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen "Can't delete mailbox while it has aliases");
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((ret = mailbox_is_alias_symlink(box)) < 0)
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ret > 0) {
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen /* we're deleting an alias mailbox. we'll need to handle this
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen explicitly since box->name points to the original mailbox */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen symlink_name = alist->module_ctx.super.
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_storage_name(box->list, box->vname);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (mailbox_list_delete_symlink(box->list, symlink_name) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return abox->module_ctx.super.delete_box(box);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(src);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((ret = mailbox_is_alias_symlink(src)) < 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen else if (ret > 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "Can't rename alias mailboxes");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((ret = mailbox_is_alias_symlink(dest)) < 0)
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen return -1;
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen else if (ret > 0) {
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen "Can't rename to mailbox alias");
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen return -1;
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen }
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen ret = mailbox_has_aliases(src->list, src->vname);
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen if (ret < 0)
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen return -1;
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen if (ret > 0) {
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "Can't rename mailbox while it has aliases");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return -1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen return abox->module_ctx.super.rename_box(src, dest);
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen}
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void mailbox_alias_mail_user_created(struct mail_user *user)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mail_user_vfuncs *v = user->vlast;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_user *auser;
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen struct mailbox_alias *alias;
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen string_t *oldkey, *newkey;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *old_vname, *new_vname;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen unsigned int i;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen auser = p_new(user->pool, struct mailbox_alias_user, 1);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen auser->module_ctx.super = *v;
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen user->vlast = &auser->module_ctx.super;
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen p_array_init(&auser->aliases, user->pool, 8);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen oldkey = t_str_new(32);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen newkey = t_str_new(32);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen str_append(oldkey, "mailbox_alias_old");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_append(newkey, "mailbox_alias_new");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (i = 2;; i++) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen old_vname = mail_user_plugin_getenv(user, str_c(oldkey));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen new_vname = mail_user_plugin_getenv(user, str_c(newkey));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (old_vname == NULL || new_vname == NULL)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen break;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen alias = array_append_space(&auser->aliases);
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen alias->old_vname = old_vname;
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen alias->new_vname = new_vname;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen str_truncate(oldkey, 0);
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen str_truncate(newkey, 0);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen str_printfa(oldkey, "mailbox_alias_old%u", i);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen str_printfa(newkey, "mailbox_alias_new%u", i);
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen }
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen MODULE_CONTEXT_SET(user, mailbox_alias_user_module, auser);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen}
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainenstatic void mailbox_alias_mailbox_list_created(struct mailbox_list *list)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen{
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen struct mailbox_list_vfuncs *v = list->vlast;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen struct mailbox_alias_mailbox_list *alist;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen alist = p_new(list->pool, struct mailbox_alias_mailbox_list, 1);
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen alist->module_ctx.super = *v;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen list->vlast = &alist->module_ctx.super;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen v->get_storage_name = mailbox_alias_get_storage_name;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MODULE_CONTEXT_SET(list, mailbox_alias_mailbox_list_module, alist);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void mailbox_alias_mailbox_allocated(struct mailbox *box)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_vfuncs *v = box->vlast;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mailbox_alias_mailbox *abox;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen abox = p_new(box->pool, struct mailbox_alias_mailbox, 1);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen abox->module_ctx.super = *v;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen box->vlast = &abox->module_ctx.super;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen v->create_box = mailbox_alias_create;
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen v->delete_box = mailbox_alias_delete;
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen v->rename_box = mailbox_alias_rename;
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen MODULE_CONTEXT_SET(box, mailbox_alias_storage_module, abox);
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen}
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainenstatic struct mail_storage_hooks mailbox_alias_mail_storage_hooks = {
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen .mail_user_created = mailbox_alias_mail_user_created,
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen .mailbox_list_created = mailbox_alias_mailbox_list_created,
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen .mailbox_allocated = mailbox_alias_mailbox_allocated
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen};
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainenvoid mailbox_alias_plugin_init(struct module *module)
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen{
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen mail_storage_hooks_add(module, &mailbox_alias_mail_storage_hooks);
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen}
f0d93763f210ecdb85a115fdd0210a16cfc5ff5cTimo Sirainen
f0d93763f210ecdb85a115fdd0210a16cfc5ff5cTimo Sirainenvoid mailbox_alias_plugin_deinit(void)
6303191abcb37164f435ccdc56e9dbddf1288851Timo Sirainen{
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen mail_storage_hooks_remove(&mailbox_alias_mail_storage_hooks);
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen}
2ef0e8ee48c9683f7bd6698798efa3328e4322d1Timo Sirainen