diff options
Diffstat (limited to 'src/plugins/notify/notify-plugin.c')
-rw-r--r-- | src/plugins/notify/notify-plugin.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/src/plugins/notify/notify-plugin.c b/src/plugins/notify/notify-plugin.c new file mode 100644 index 0000000..e9ff9bb --- /dev/null +++ b/src/plugins/notify/notify-plugin.c @@ -0,0 +1,265 @@ +/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "llist.h" +#include "mail-storage.h" +#include "notify-plugin-private.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; +}; + +const char *notify_plugin_version = DOVECOT_ABI_VERSION; +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 == NULL ? NULL : + 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) { + if (ctx->v.mail_save == NULL) + continue; + 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) { + if (ctx->v.mail_copy == NULL) + continue; + 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) { + if (ctx->v.mail_expunge == NULL) + continue; + 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; + + if (mail->saving) + return; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + if (ctx->v.mail_update_flags == NULL) + continue; + 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; + + if (mail->saving) + return; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + if (ctx->v.mail_update_keywords == NULL) + continue; + 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); + if (ctx->v.mail_transaction_commit != NULL) + 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); + if (ctx->v.mail_transaction_rollback != NULL) + ctx->v.mail_transaction_rollback(mail_txn->txn); + DLLIST_REMOVE(&ctx->mail_txn_list, mail_txn); + i_free(mail_txn); + } +} + +void notify_contexts_mailbox_create(struct mailbox *box) +{ + struct notify_context *ctx; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + if (ctx->v.mailbox_create != NULL) + ctx->v.mailbox_create(box); + } +} + +void notify_contexts_mailbox_update(struct mailbox *box) +{ + struct notify_context *ctx; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + if (ctx->v.mailbox_update != NULL) + ctx->v.mailbox_update(box); + } +} + +void notify_contexts_mailbox_delete_begin(struct mailbox *box) +{ + struct notify_context *ctx; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + ctx->mailbox_delete_txn = + ctx->v.mailbox_delete_begin == NULL ? NULL : + ctx->v.mailbox_delete_begin(box); + } +} + +void notify_contexts_mailbox_delete_commit(struct mailbox *box) +{ + struct notify_context *ctx; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + if (ctx->v.mailbox_delete_commit != NULL) { + ctx->v.mailbox_delete_commit(ctx->mailbox_delete_txn, + box); + } + 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) { + if (ctx->v.mailbox_delete_rollback != NULL) + ctx->v.mailbox_delete_rollback(ctx->mailbox_delete_txn); + ctx->mailbox_delete_txn = NULL; + } +} + +void notify_contexts_mailbox_rename(struct mailbox *src, struct mailbox *dest) +{ + struct notify_context *ctx; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + if (ctx->v.mailbox_rename != NULL) + ctx->v.mailbox_rename(src, dest); + } +} + +void notify_contexts_mailbox_set_subscribed(struct mailbox *box, + bool subscribed) +{ + struct notify_context *ctx; + + for (ctx = ctx_list; ctx != NULL; ctx = ctx->next) { + if (ctx->v.mailbox_set_subscribed != NULL) + ctx->v.mailbox_set_subscribed(box, subscribed); + } +} + +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) { + if (ctx->v.mail_transaction_rollback != NULL) + ctx->v.mail_transaction_rollback(mail_txn->txn); + } + if (ctx->mailbox_delete_txn != NULL && + ctx->v.mailbox_delete_rollback != NULL) + ctx->v.mailbox_delete_rollback(ctx->mailbox_delete_txn); + DLLIST_REMOVE(&ctx_list, ctx); + i_free(ctx); +} + +void notify_plugin_init(struct module *module) +{ + notify_plugin_init_storage(module); +} + +void notify_plugin_deinit(void) +{ + notify_plugin_deinit_storage(); +} |