mailbox-alias-plugin.c revision fca7aa88ab19375aba5a8fd9d4100ea885dccb68
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_user_module)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_storage_module)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_mailbox_list_module)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_user_module,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_storage_module,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_mailbox_list_module,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenconst char *mailbox_alias_plugin_version = DOVECOT_VERSION;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic const char *
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenmailbox_alias_find_new(struct mail_user *user, const char *new_vname)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen struct mailbox_alias_user *auser = MAILBOX_ALIAS_USER_CONTEXT(user);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic int mailbox_symlink_exists(struct mailbox_list *list, const char *vname,
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainen symlink_name = alist->module_ctx.super.get_storage_name(list, vname);
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainen symlink_path = mailbox_list_get_path(list, symlink_name,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_SYMLINK;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic int mailbox_is_alias_symlink(struct mailbox *box)
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
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 existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK ? 1 : 0;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenmailbox_has_aliases(struct mailbox_list *list, const char *old_vname)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (strcmp(alias->old_vname, old_vname) == 0) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (mailbox_symlink_exists(list, alias->new_vname,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenmailbox_alias_create_symlink(struct mailbox *box,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen old_path = mailbox_list_get_path(box->list, old_name,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen new_path = mailbox_list_get_path(box->list, new_name,
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen i_assert(strncmp(new_path, old_path, fname-old_path) == 0);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen "Mailbox already exists");
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen "symlink(%s, %s) failed: %m", fname, new_path);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenstatic const char *
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenmailbox_alias_get_storage_name(struct mailbox_list *list, const char *vname)
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 mailbox_symlink_exists(list, vname, &existence) == 0 &&
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen existence != MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return alist->module_ctx.super.get_storage_name(list, vname);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenmailbox_alias_create(struct mailbox *box, const struct mailbox_update *update,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
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 if (ret < 0 && mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
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. */
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen return mailbox_alias_create_symlink(box, box->name, symlink_name);
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainenstatic int mailbox_alias_delete(struct mailbox *box)
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen ret = mailbox_has_aliases(box->list, box->vname);
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen "Can't delete mailbox while it has aliases");
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 if (mailbox_list_delete_symlink(box->list, symlink_name) < 0) {
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen return abox->module_ctx.super.delete_box(box);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenstatic int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest)
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(src);
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen "Can't rename alias mailboxes");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "Can't rename to mailbox alias");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen ret = mailbox_has_aliases(src->list, src->vname);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "Can't rename mailbox while it has aliases");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen return abox->module_ctx.super.rename_box(src, dest);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainenstatic void mailbox_alias_mail_user_created(struct mail_user *user)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen unsigned int i;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen auser = p_new(user->pool, struct mailbox_alias_user, 1);
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));
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen str_printfa(oldkey, "mailbox_alias_old%u", i);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen str_printfa(newkey, "mailbox_alias_new%u", i);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MODULE_CONTEXT_SET(user, mailbox_alias_user_module, auser);
b3f4c31f1533e25380f49f77d5bb1251bf43db2aTimo Sirainenstatic void mailbox_alias_mailbox_list_created(struct mailbox_list *list)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen alist = p_new(list->pool, struct mailbox_alias_mailbox_list, 1);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen v->get_storage_name = mailbox_alias_get_storage_name;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MODULE_CONTEXT_SET(list, mailbox_alias_mailbox_list_module, alist);
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainenstatic void mailbox_alias_mailbox_allocated(struct mailbox *box)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen abox = p_new(box->pool, struct mailbox_alias_mailbox, 1);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen MODULE_CONTEXT_SET(box, mailbox_alias_storage_module, abox);
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
void mailbox_alias_plugin_deinit(void)