Patch by Mark Washenberger / Rackspace.
--HG--
branch : HEAD
src/plugins/listescape/Makefile
src/plugins/mail-log/Makefile
src/plugins/mbox-snarf/Makefile
+src/plugins/notify/Makefile
src/plugins/quota/Makefile
src/plugins/imap-quota/Makefile
src/plugins/trash/Makefile
listescape \
mail-log \
mbox-snarf \
+ notify \
quota \
imap-quota \
trash \
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/lib \
+ -I$(top_srcdir)/src/lib-mail \
+ -I$(top_srcdir)/src/lib-imap \
+ -I$(top_srcdir)/src/lib-index \
+ -I$(top_srcdir)/src/lib-storage \
+ -I$(top_srcdir)/src/lib-storage/index \
+ -I$(top_srcdir)/src/lib-storage/index/maildir
+
+lib15_notify_plugin_la_LDFLAGS = -module -avoid-version
+
+module_LTLIBRARIES = \
+ lib15_notify_plugin.la
+
+lib15_notify_plugin_la_SOURCES = \
+ notify-plugin.c \
+ notify-noop.c \
+ notify-storage.c
+
+noinst_HEADERS = \
+ notify-plugin.h
+ notify-plugin-private.h
+
+install-exec-local:
+ for d in imap pop3 lda; do \
+ $(mkdir_p) $(DESTDIR)$(moduledir)/$$d; \
+ rm -f $(DESTDIR)$(moduledir)/$$d/lib15_notify_plugin$(MODULE_SUFFIX); \
+ $(LN_S) ../lib15_notify_plugin$(MODULE_SUFFIX) $(DESTDIR)$(moduledir)/$$d; \
+ done
--- /dev/null
+#include "lib.h"
+#include "mail-types.h"
+#include "notify-plugin.h"
+
+void notify_noop_mail_transaction_begin(struct mailbox_transaction_context *t ATTR_UNUSED) {}
+void notify_noop_mail_save(void *txn ATTR_UNUSED,
+ struct mail *mail ATTR_UNUSED) {}
+void notify_noop_mail_copy(void *txn ATTR_UNUSED,
+ struct mail *src ATTR_UNUSED,
+ struct mail *dst ATTR_UNUSED) {}
+void notify_noop_mail_expunge(void *txn ATTR_UNUSED,
+ struct mail *mail ATTR_UNUSED) {}
+void notify_noop_mail_update_flags(void *txn ATTR_UNUSED,
+ struct mail *mail ATTR_UNUSED,
+ enum mail_flags old_flags ATTR_UNUSED) {}
+void notify_noop_mail_update_keywords(void *txn ATTR_UNUSED,
+ struct mail *mail ATTR_UNUSED,
+ const char *const *old_keywords ATTR_UNUSED) {}
+void notify_noop_mail_transaction_commit(void *txn ATTR_UNUSED,
+ struct mail_transaction_commit_changes *changes ATTR_UNUSED) {}
+void notify_noop_mail_transaction_rollback(void *txn ATTR_UNUSED) {}
+void *notify_noop_mailbox_delete_begin(struct mailbox_list *list ATTR_UNUSED,
+ const char *name ATTR_UNUSED) { return NULL; }
+void notify_noop_mailbox_delete_commit(void *txn ATTR_UNUSED,
+ struct mailbox_list *list ATTR_UNUSED,
+ const char *name ATTR_UNUSED) {}
+void notify_noop_mailbox_delete_rollback(void *txn ATTR_UNUSED) {}
+void notify_noop_mailbox_rename(struct mailbox_list *oldlist ATTR_UNUSED,
+ const char *oldname ATTR_UNUSED,
+ struct mailbox_list *newlist ATTR_UNUSED,
+ const char *newname ATTR_UNUSED,
+ bool rename_children ATTR_UNUSED) {}
--- /dev/null
+#ifndef NOTIFY_PLUGIN_PRIVATE_H
+#define NOTIFY_PLUGIN_PRIVATE_H
+
+#include "notify-plugin.h"
+
+void notify_contexts_mail_transaction_begin(struct mailbox_transaction_context *t);
+void notify_contexts_mail_save(struct mail *mail);
+void notify_contexts_mail_copy(struct mail *src, struct mail *dst);
+void notify_contexts_mail_expunge(struct mail *mail);
+void notify_contexts_mail_update_flags(struct mail *mail,
+ enum mail_flags old_flags);
+void notify_contexts_mail_update_keywords(struct mail *mail,
+ const char *const *old_keywords);
+void notify_contexts_mail_transaction_commit(struct mailbox_transaction_context *t,
+ struct mail_transaction_commit_changes *changes);
+void notify_contexts_mail_transaction_rollback(struct mailbox_transaction_context *t);
+void notify_contexts_mailbox_delete_begin(struct mailbox_list *list,
+ const char *name);
+void notify_contexts_mailbox_delete_commit(struct mailbox_list *list,
+ const char *name);
+void notify_contexts_mailbox_delete_rollback(void);
+void notify_contexts_mailbox_rename(struct mailbox_list *oldlist,
+ const char *oldname,
+ struct mailbox_list *newlist,
+ const char *newname, bool rename_children);
+
+void notify_plugin_init_storage(void);
+void notify_plugin_deinit_storage(void);
+
+#endif
--- /dev/null
+#include "lib.h"
+#include "llist.h"
+#include "mail-storage.h"
+#include "notify-plugin-private.h"
+
+#include <stdlib.h>
+
+struct notify_mail_txn {
+ struct notify_mail_txn *prev, *next;
+ struct mailbox_transaction_context *parent_mailbox_txn;
+ struct mail *tmp_mail;
+ void *txn;
+};
+
+struct notify_context {
+ struct notify_context *prev, *next;
+ struct notify_vfuncs v;
+ struct notify_mail_txn *mail_txn_list;
+ void *mailbox_delete_txn;
+};
+
+static struct notify_context *ctx_list = NULL;
+
+static struct notify_mail_txn *
+notify_context_find_mail_txn(struct notify_context *ctx,
+ struct mailbox_transaction_context *t)
+{
+ struct notify_mail_txn *mail_txn = ctx->mail_txn_list;
+
+ for (; mail_txn != NULL; mail_txn = mail_txn->next) {
+ if (mail_txn->parent_mailbox_txn == t)
+ return mail_txn;
+ }
+ i_panic("no notify_mail_txn found");
+}
+
+void notify_contexts_mail_transaction_begin(struct mailbox_transaction_context *t)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = i_new(struct notify_mail_txn, 1);
+ mail_txn->parent_mailbox_txn = t;
+ mail_txn->txn = ctx->v.mail_transaction_begin(t);
+ DLLIST_PREPEND(&ctx->mail_txn_list, mail_txn);
+ }
+}
+
+void notify_contexts_mail_save(struct mail *mail)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = notify_context_find_mail_txn(ctx, mail->transaction);
+ ctx->v.mail_save(mail_txn->txn, mail);
+ }
+}
+
+void notify_contexts_mail_copy(struct mail *src, struct mail *dst)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = notify_context_find_mail_txn(ctx, dst->transaction);
+ ctx->v.mail_copy(mail_txn->txn, src, dst);
+ }
+}
+
+void notify_contexts_mail_expunge(struct mail *mail)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = notify_context_find_mail_txn(ctx, mail->transaction);
+ ctx->v.mail_expunge(mail_txn->txn, mail);
+ }
+}
+
+void notify_contexts_mail_update_flags(struct mail *mail,
+ enum mail_flags old_flags)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = notify_context_find_mail_txn(ctx, mail->transaction);
+ ctx->v.mail_update_flags(mail_txn->txn, mail, old_flags);
+ }
+}
+
+void notify_contexts_mail_update_keywords(struct mail *mail,
+ const char *const *old_keywords)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = notify_context_find_mail_txn(ctx, mail->transaction);
+ ctx->v.mail_update_keywords(mail_txn->txn, mail, old_keywords);
+ }
+}
+
+void notify_contexts_mail_transaction_commit(struct mailbox_transaction_context *t,
+ struct mail_transaction_commit_changes *changes)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = notify_context_find_mail_txn(ctx, t);
+ ctx->v.mail_transaction_commit(mail_txn->txn, changes);
+ DLLIST_REMOVE(&ctx->mail_txn_list, mail_txn);
+ i_free(mail_txn);
+ }
+}
+
+void notify_contexts_mail_transaction_rollback(struct mailbox_transaction_context *t)
+{
+ struct notify_context *ctx;
+ struct notify_mail_txn *mail_txn;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ mail_txn = notify_context_find_mail_txn(ctx, t);
+ ctx->v.mail_transaction_rollback(mail_txn->txn);
+ DLLIST_REMOVE(&ctx->mail_txn_list, mail_txn);
+ i_free(mail_txn);
+ }
+}
+
+void notify_contexts_mailbox_delete_begin(struct mailbox_list *list,
+ const char *name)
+{
+ struct notify_context *ctx;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ ctx->mailbox_delete_txn =
+ ctx->v.mailbox_delete_begin(list, name);
+ }
+}
+
+void notify_contexts_mailbox_delete_commit(struct mailbox_list *list,
+ const char *name)
+{
+ struct notify_context *ctx;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ ctx->v.mailbox_delete_commit(ctx->mailbox_delete_txn,
+ list, name);
+ ctx->mailbox_delete_txn = NULL;
+ }
+}
+
+void notify_contexts_mailbox_delete_rollback(void)
+{
+ struct notify_context *ctx;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ ctx->v.mailbox_delete_rollback(ctx->mailbox_delete_txn);
+ ctx->mailbox_delete_txn = NULL;
+ }
+}
+
+void notify_contexts_mailbox_rename(struct mailbox_list *oldlist,
+ const char *oldname,
+ struct mailbox_list *newlist,
+ const char *newname, bool rename_children)
+{
+ struct notify_context *ctx;
+
+ for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) {
+ ctx->v.mailbox_rename(oldlist, oldname, newlist, newname,
+ rename_children);
+ }
+}
+
+struct notify_context *
+notify_register(const struct notify_vfuncs *v)
+{
+ struct notify_context *ctx;
+
+ ctx = i_new(struct notify_context, 1);
+ ctx->v = *v;
+ DLLIST_PREPEND(&ctx_list, ctx);
+ return ctx;
+}
+
+void notify_unregister(struct notify_context *ctx)
+{
+ struct notify_mail_txn *mail_txn = ctx->mail_txn_list;
+
+ for (; mail_txn != NULL; mail_txn = mail_txn->next)
+ ctx->v.mail_transaction_rollback(mail_txn->txn);
+ ctx->v.mailbox_delete_rollback(ctx->mailbox_delete_txn);
+ DLLIST_REMOVE(&ctx_list, ctx);
+ i_free(ctx);
+}
+
+void notify_plugin_init(void)
+{
+ notify_plugin_init_storage();
+}
+
+void notify_plugin_deinit(void)
+{
+ notify_plugin_deinit_storage();
+}
--- /dev/null
+#ifndef NOTIFY_PLUGIN_H
+#define NOTIFY_PLUGIN_H
+
+enum mail_flags;
+struct mail;
+struct mail_transaction_commit_changes;
+struct mail_storage;
+struct mailbox_transaction_context;
+struct mailbox_list;
+struct notify_context;
+
+struct notify_vfuncs {
+ void *(*mail_transaction_begin)(struct mailbox_transaction_context *t);
+ void (*mail_save)(void *txn, struct mail *mail);
+ void (*mail_copy)(void *txn, struct mail *src, struct mail *dst);
+ void (*mail_expunge)(void *txn, struct mail *mail);
+ void (*mail_update_flags)(void *txn, struct mail *mail,
+ enum mail_flags old_flags);
+ void (*mail_update_keywords)(void *txn, struct mail *mail,
+ const char *const *old_keywords);
+ void (*mail_transaction_commit)(void *txn,
+ struct mail_transaction_commit_changes *changes);
+ void (*mail_transaction_rollback)(void *txn);
+ void *(*mailbox_delete_begin)(struct mailbox_list *list,
+ const char *name);
+ void (*mailbox_delete_commit)(void *txn, struct mailbox_list *list,
+ const char *name);
+ void (*mailbox_delete_rollback)(void *txn);
+ void (*mailbox_rename)(struct mailbox_list *oldlist,
+ const char *oldname,
+ struct mailbox_list *newlist,
+ const char *newname, bool rename_children);
+};
+
+void notify_noop_mail_transaction_begin(struct mailbox_transaction_context *t);
+void notify_noop_mail_save(void *txn, struct mail *mail);
+void notify_noop_mail_copy(void *txn, struct mail *src, struct mail *dst);
+void notify_noop_mail_expunge(void *txn, struct mail *mail);
+void notify_noop_mail_update_flags(void *txn, struct mail *mail,
+ enum mail_flags old_flags);
+void notify_noop_mail_update_keywords(void *txn, struct mail *mail,
+ const char *const *old_keywords);
+void notify_noop_mail_transaction_commit(void *txn,
+ struct mail_transaction_commit_changes *changes);
+void notify_noop_mail_transaction_rollback(void *txn);
+void *notify_noop_mailbox_delete_begin(struct mailbox_list *list,
+ const char *name);
+void notify_noop_mailbox_delete_commit(void *txn, struct mailbox_list *list,
+ const char *name);
+void notify_noop_mailbox_delete_rollback(void *txn);
+void notify_noop_mailbox_rename(struct mailbox_list *oldlist,
+ const char *oldname,
+ struct mailbox_list *newlist,
+ const char *newname, bool rename_children);
+
+struct notify_context *
+notify_register(const struct notify_vfuncs *vfuncs);
+void notify_unregister(struct notify_context *ctx);
+
+void notify_plugin_init(void);
+void notify_plugin_deinit(void);
+
+#endif
--- /dev/null
+#include "lib.h"
+#include "array.h"
+#include "mail-storage-private.h"
+#include "mailbox-list-private.h"
+#include "notify-plugin-private.h"
+
+#define NOTIFY_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, notify_storage_module)
+#define NOTIFY_MAIL_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, notify_mail_module)
+#define NOTIFY_LIST_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, notify_mailbox_list_module)
+
+struct notify_transaction_context {
+ union mailbox_transaction_module_context module_ctx;
+ struct mail *tmp_mail;
+ bool save_hack;
+};
+
+static MODULE_CONTEXT_DEFINE_INIT(notify_storage_module,
+ &mail_storage_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(notify_mail_module,
+ &mail_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(notify_mailbox_list_module,
+ &mailbox_list_module_register);
+
+static void (*notify_next_hook_mail_storage_created)
+ (struct mail_storage *storage);
+static void (*notify_next_hook_mailbox_list_created)
+ (struct mailbox_list *list);
+
+static void
+notify_mail_expunge(struct mail *_mail)
+{
+ struct mail_private *mail = (struct mail_private *)_mail;
+ union mail_module_context *lmail = NOTIFY_MAIL_CONTEXT(mail);
+
+ notify_contexts_mail_expunge(_mail);
+ lmail->super.expunge(_mail);
+}
+
+static void
+notify_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
+ enum mail_flags flags)
+{
+ struct mail_private *mail = (struct mail_private *)_mail;
+ union mail_module_context *lmail = NOTIFY_MAIL_CONTEXT(mail);
+ enum mail_flags old_flags, new_flags;
+
+ old_flags = mail_get_flags(_mail);
+ lmail->super.update_flags(_mail, modify_type, flags);
+ new_flags = mail_get_flags(_mail);
+
+ if ((old_flags ^ new_flags) == 0)
+ return;
+
+ notify_contexts_mail_update_flags(_mail, old_flags);
+}
+
+static void
+notify_mail_update_keywords(struct mail *_mail, enum modify_type modify_type,
+ struct mail_keywords *keywords)
+{
+ struct mail_private *mail = (struct mail_private *)_mail;
+ union mail_module_context *lmail = NOTIFY_MAIL_CONTEXT(mail);
+ const char *const *old_keywords, *const *new_keywords;
+ unsigned int i;
+
+ old_keywords = mail_get_keywords(_mail);
+ lmail->super.update_keywords(_mail, modify_type, keywords);
+ new_keywords = mail_get_keywords(_mail);
+
+ for (i = 0; old_keywords[i] != NULL && new_keywords[i] != NULL; i++) {
+ if (strcmp(old_keywords[i], new_keywords[i]) != 0)
+ break;
+ }
+
+ if (old_keywords[i] == NULL && new_keywords[i] == NULL)
+ return;
+
+ notify_contexts_mail_update_keywords(_mail, old_keywords);
+}
+
+static struct mail *
+notify_mail_alloc(struct mailbox_transaction_context *t,
+ enum mail_fetch_field wanted_fields,
+ struct mailbox_header_lookup_ctx *wanted_headers)
+{
+ union mailbox_module_context *lbox = NOTIFY_CONTEXT(t->box);
+ union mail_module_context *lmail;
+ struct mail *_mail;
+ struct mail_private *mail;
+
+ _mail = lbox->super.mail_alloc(t, wanted_fields, wanted_headers);
+ mail = (struct mail_private *)_mail;
+
+ lmail = p_new(mail->pool, union mail_module_context, 1);
+ lmail->super = mail->v;
+
+ mail->v.expunge = notify_mail_expunge;
+ mail->v.update_flags = notify_mail_update_flags;
+ mail->v.update_keywords = notify_mail_update_keywords;
+ MODULE_CONTEXT_SET_SELF(mail, notify_mail_module, lmail);
+ return _mail;
+}
+
+static int
+notify_copy(struct mail_save_context *ctx, struct mail *mail)
+{
+ struct notify_transaction_context *lt =
+ NOTIFY_CONTEXT(ctx->transaction);
+ union mailbox_module_context *lbox =
+ NOTIFY_CONTEXT(ctx->transaction->box);
+ int ret;
+
+ if (ctx->dest_mail == NULL) {
+ if (lt->tmp_mail == NULL)
+ lt->tmp_mail = mail_alloc(ctx->transaction, 0, NULL);
+ ctx->dest_mail = lt->tmp_mail;
+ }
+
+ lt->save_hack = TRUE;
+ ret = lbox->super.copy(ctx, mail);
+ lt->save_hack = FALSE;
+
+ if (ret == 0)
+ notify_contexts_mail_copy(mail, ctx->dest_mail);
+ return ret;
+}
+
+static int
+notify_save_begin(struct mail_save_context *ctx, struct istream *input)
+{
+ struct notify_transaction_context *lt =
+ NOTIFY_CONTEXT(ctx->transaction);
+ union mailbox_module_context *lbox =
+ NOTIFY_CONTEXT(ctx->transaction->box);
+
+ if (ctx->dest_mail == NULL) {
+ if (lt->tmp_mail == NULL)
+ lt->tmp_mail = mail_alloc(ctx->transaction, 0, NULL);
+ ctx->dest_mail = lt->tmp_mail;
+ }
+ return lbox->super.save_begin(ctx, input);
+}
+
+static int
+notify_save_finish(struct mail_save_context *ctx)
+{
+ struct notify_transaction_context *lt =
+ NOTIFY_CONTEXT(ctx->transaction);
+ union mailbox_module_context *lbox =
+ NOTIFY_CONTEXT(ctx->transaction->box);
+
+ if (lbox->super.save_finish(ctx) < 0)
+ return -1;
+ if (!lt->save_hack)
+ notify_contexts_mail_save(ctx->dest_mail);
+ return 0;
+}
+
+static struct mailbox_transaction_context *
+notify_transaction_begin(struct mailbox *box,
+ enum mailbox_transaction_flags flags)
+{
+ union mailbox_module_context *lbox = NOTIFY_CONTEXT(box);
+ struct mailbox_transaction_context *t;
+ struct notify_transaction_context *lt;
+
+ t = lbox->super.transaction_begin(box, flags);
+
+ lt = i_new(struct notify_transaction_context, 1);
+ MODULE_CONTEXT_SET(t, notify_storage_module, lt);
+
+ notify_contexts_mail_transaction_begin(t);
+ return t;
+}
+
+static int
+notify_transaction_commit(struct mailbox_transaction_context *t,
+ struct mail_transaction_commit_changes *changes_r)
+{
+ struct notify_transaction_context *lt = NOTIFY_CONTEXT(t);
+ union mailbox_module_context *lbox = NOTIFY_CONTEXT(t->box);
+
+ if (lt->tmp_mail != NULL)
+ mail_free(<->tmp_mail);
+ i_free(lt);
+
+ if ((lbox->super.transaction_commit(t, changes_r)) < 0) {
+ notify_contexts_mail_transaction_rollback(t);
+ return -1;
+ }
+
+ notify_contexts_mail_transaction_commit(t, changes_r);
+ return 0;
+}
+
+static void
+notify_transaction_rollback(struct mailbox_transaction_context *t)
+{
+ struct notify_transaction_context *lt = NOTIFY_CONTEXT(t);
+ union mailbox_module_context *lbox = NOTIFY_CONTEXT(t->box);
+
+ if (lt->tmp_mail != NULL)
+ mail_free(<->tmp_mail);
+ i_free(lt);
+
+ notify_contexts_mail_transaction_rollback(t);
+ lbox->super.transaction_rollback(t);
+}
+
+static struct mailbox *
+notify_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
+ const char *name, struct istream *input,
+ enum mailbox_flags flags)
+{
+ union mail_storage_module_context *lstorage = NOTIFY_CONTEXT(storage);
+ struct mailbox *box;
+ union mailbox_module_context *lbox;
+
+ box = lstorage->super.mailbox_alloc(storage, list, name, input, flags);
+
+ lbox = p_new(box->pool, union mailbox_module_context, 1);
+ lbox->super = box->v;
+
+ box->v.mail_alloc = notify_mail_alloc;
+ box->v.copy = notify_copy;
+ box->v.save_begin = notify_save_begin;
+ box->v.save_finish = notify_save_finish;
+ box->v.transaction_begin = notify_transaction_begin;
+ box->v.transaction_commit = notify_transaction_commit;
+ box->v.transaction_rollback = notify_transaction_rollback;
+ MODULE_CONTEXT_SET_SELF(box, notify_storage_module, lbox);
+ return box;
+}
+
+static int
+notify_mailbox_list_delete(struct mailbox_list *list, const char *name)
+{
+ union mailbox_list_module_context *llist = NOTIFY_LIST_CONTEXT(list);
+
+ notify_contexts_mailbox_delete_begin(list, name);
+ if (llist->super.delete_mailbox(list, name) < 0) {
+ notify_contexts_mailbox_delete_rollback();
+ return -1;
+ }
+ notify_contexts_mailbox_delete_commit(list, name);
+ return 0;
+}
+
+static int
+notify_mailbox_list_rename(struct mailbox_list *oldlist, const char *oldname,
+ struct mailbox_list *newlist, const char *newname,
+ bool rename_children)
+{
+ union mailbox_list_module_context *oldllist =
+ NOTIFY_LIST_CONTEXT(oldlist);
+
+ if (oldllist->super.rename_mailbox(oldlist, oldname, newlist, newname,
+ rename_children) < 0)
+ return -1;
+
+ notify_contexts_mailbox_rename(oldlist, oldname, newlist, newname,
+ rename_children);
+ return 0;
+}
+
+static void notify_mail_storage_created(struct mail_storage *storage)
+{
+ union mail_storage_module_context *lstorage;
+
+ lstorage = p_new(storage->pool, union mail_storage_module_context, 1);
+ lstorage->super = storage->v;
+ storage->v.mailbox_alloc = notify_mailbox_alloc;
+
+ MODULE_CONTEXT_SET_SELF(storage, notify_storage_module, lstorage);
+
+ if (notify_next_hook_mail_storage_created != NULL)
+ notify_next_hook_mail_storage_created(storage);
+}
+
+static void notify_mailbox_list_created(struct mailbox_list *list)
+{
+ union mailbox_list_module_context *llist;
+
+ llist = p_new(list->pool, union mailbox_list_module_context, 1);
+ llist->super = list->v;
+ list->v.delete_mailbox = notify_mailbox_list_delete;
+ list->v.rename_mailbox = notify_mailbox_list_rename;
+
+ MODULE_CONTEXT_SET_SELF(list, notify_mailbox_list_module, llist);
+
+ if (notify_next_hook_mailbox_list_created != NULL)
+ notify_next_hook_mailbox_list_created(list);
+}
+
+void notify_plugin_init_storage(void)
+{
+ notify_next_hook_mail_storage_created = hook_mail_storage_created;
+ hook_mail_storage_created = notify_mail_storage_created;
+
+ notify_next_hook_mailbox_list_created = hook_mailbox_list_created;
+ hook_mailbox_list_created = notify_mailbox_list_created;
+}
+
+void notify_plugin_deinit_storage(void)
+{
+ hook_mail_storage_created = notify_next_hook_mail_storage_created;
+ hook_mailbox_list_created = notify_next_hook_mailbox_list_created;
+}