mailbox-alias-plugin.c revision f67c2a7415cbd1a783920cc84ded731dcafa4ffc
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
9e86ad9eb313004cd4c8b5427daeb4c241b57af6Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_user_module)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_storage_module)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_mailbox_list_module)
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_user_module,
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_storage_module,
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_mailbox_list_module,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenconst char *mailbox_alias_plugin_version = DOVECOT_VERSION;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic const char *
48f78a48f2e1cf299026544444666471ae16ad97Timo Sirainenmailbox_alias_find_new(struct mail_user *user, const char *new_vname)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen struct mailbox_alias_user *auser = MAILBOX_ALIAS_USER_CONTEXT(user);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenstatic int mailbox_symlink_exists(struct mailbox_list *list, const char *vname,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen symlink_name = alist->module_ctx.super.get_storage_name(list, vname);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen symlink_path = mailbox_list_get_path(list, symlink_name,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_SYMLINK;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenstatic int mailbox_is_alias_symlink(struct mailbox *box)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (mailbox_symlink_exists(box->list, box->vname, &existence) < 0) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK ? 1 : 0;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenmailbox_has_aliases(struct mailbox_list *list, const char *old_vname)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (strcmp(alias->old_vname, old_vname) == 0) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (mailbox_symlink_exists(list, alias->new_vname,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen else if (existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenmailbox_alias_create_symlink(struct mailbox *box,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen old_path = mailbox_list_get_path(box->list, old_name,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen new_path = mailbox_list_get_path(box->list, new_name,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen i_assert(strncmp(new_path, old_path, fname-old_path) == 0);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen "Mailbox already exists");
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen "symlink(%s, %s) failed: %m", fname, new_path);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic const char *
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainenmailbox_alias_get_storage_name(struct mailbox_list *list, const char *vname)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen /* access the old mailbox so that e.g. full text search won't
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen index the mailbox twice. this also means that deletion must be
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen careful to delete the symlink, box->name. */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen old_vname = mailbox_alias_find_new(list->ns->user, vname);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen mailbox_symlink_exists(list, vname, &existence) == 0 &&
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen existence != MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return alist->module_ctx.super.get_storage_name(list, vname);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenmailbox_alias_create(struct mailbox *box, const struct mailbox_update *update,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen ret = abox->module_ctx.super.create(box, update, directory);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen if (ret < 0 && mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen /* all the code so far has actually only created the original
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mailbox. now we'll create the symlink if it's missing. */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return mailbox_alias_create_symlink(box, box->name, symlink_name);
9e86ad9eb313004cd4c8b5427daeb4c241b57af6Timo Sirainenstatic int mailbox_alias_delete(struct mailbox *box)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen ret = mailbox_has_aliases(box->list, box->vname);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen "Can't delete mailbox while it has aliases");
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen /* we're deleting an alias mailbox. we'll need to handle this
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen explicitly since box->name points to the original mailbox */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (mailbox_list_delete_symlink(box->list, symlink_name) < 0) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest,
c2bb1764c359ce85a7f7f789ead11dd613ff9769Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(src);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen "Can't rename alias mailboxes");
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen "Can't rename to mailbox alias");
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen ret = mailbox_has_aliases(src->list, src->vname);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen "Can't rename mailbox while it has aliases");
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return abox->module_ctx.super.rename(src, dest, rename_children);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mailbox_alias_mail_user_created(struct mail_user *user)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen unsigned int i;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen auser = p_new(user->pool, struct mailbox_alias_user, 1);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen for (i = 2;; i++) {
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen old_vname = mail_user_plugin_getenv(user, str_c(oldkey));
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen new_vname = mail_user_plugin_getenv(user, str_c(newkey));
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen str_printfa(oldkey, "mailbox_alias_old%u", i);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen str_printfa(newkey, "mailbox_alias_new%u", i);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT_SET(user, mailbox_alias_user_module, auser);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mailbox_alias_mailbox_list_created(struct mailbox_list *list)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen alist = p_new(list->pool, struct mailbox_alias_mailbox_list, 1);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen v->get_storage_name = mailbox_alias_get_storage_name;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen MODULE_CONTEXT_SET(list, mailbox_alias_mailbox_list_module, alist);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mailbox_alias_mailbox_allocated(struct mailbox *box)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen abox = p_new(box->pool, struct mailbox_alias_mailbox, 1);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT_SET(box, mailbox_alias_storage_module, abox);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic struct mail_storage_hooks mailbox_alias_mail_storage_hooks = {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen .mail_user_created = mailbox_alias_mail_user_created,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen .mailbox_list_created = mailbox_alias_mailbox_list_created,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen .mailbox_allocated = mailbox_alias_mailbox_allocated
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenvoid mailbox_alias_plugin_init(struct module *module)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_hooks_add(module, &mailbox_alias_mail_storage_hooks);
void mailbox_alias_plugin_deinit(void)