Mercurial > dovecot > core-2.2
view src/plugins/push-notification/push-notification-plugin.c @ 21390:2e2563132d5f
Updated copyright notices to include the year 2017.
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Wed, 11 Jan 2017 02:51:13 +0100 |
parents | 0f22db71df7a |
children | 7fa4ccc9a738 |
line wrap: on
line source
/* Copyright (c) 2015-2017 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "mail-namespace.h" #include "mail-storage.h" #include "mail-storage-private.h" #include "notify-plugin.h" #include "str.h" #include "push-notification-drivers.h" #include "push-notification-events.h" #include "push-notification-events-rfc5423.h" #include "push-notification-plugin.h" #include "push-notification-triggers.h" #include "push-notification-txn-mbox.h" #include "push-notification-txn-msg.h" #define PUSH_NOTIFICATION_CONFIG "push_notification_driver" #define PUSH_NOTIFICATION_CONFIG_OLD "push_notification_backend" #define PUSH_NOTIFICATION_USER_CONTEXT(obj) \ MODULE_CONTEXT(obj, push_notification_user_module) static MODULE_CONTEXT_DEFINE_INIT(push_notification_user_module, &mail_user_module_register); static void push_notification_transaction_init(struct push_notification_txn *ptxn) { struct push_notification_driver_txn *dtxn; struct push_notification_driver_user **duser; struct mail_storage *storage; if (ptxn->initialized) { return; } ptxn->initialized = TRUE; storage = mailbox_get_storage(ptxn->mbox); if (storage->user->autocreated && (strcmp(storage->name, "raw") == 0)) { /* no notifications for autocreated raw users */ return; } array_foreach_modifiable(&ptxn->puser->driverlist->drivers, duser) { dtxn = p_new(ptxn->pool, struct push_notification_driver_txn, 1); dtxn->duser = *duser; dtxn->ptxn = ptxn; if ((dtxn->duser->driver->v.begin_txn == NULL) || dtxn->duser->driver->v.begin_txn(dtxn)) { array_append(&ptxn->drivers, &dtxn, 1); } } } static struct push_notification_txn * push_notification_transaction_create(struct mailbox *box, struct mailbox_transaction_context *t) { pool_t pool; struct push_notification_txn *ptxn; struct mail_storage *storage; pool = pool_alloconly_create("push notification transaction", 2048); ptxn = p_new(pool, struct push_notification_txn, 1); ptxn->mbox = box; storage = mailbox_get_storage(box); ptxn->muser = mail_storage_get_user(storage); ptxn->pool = pool; ptxn->puser = PUSH_NOTIFICATION_USER_CONTEXT(ptxn->muser); ptxn->t = t; ptxn->trigger = PUSH_NOTIFICATION_EVENT_TRIGGER_NONE; p_array_init(&ptxn->drivers, pool, 4); return ptxn; } static void push_notification_transaction_end (struct push_notification_txn *ptxn, bool success) { struct push_notification_driver_txn **dtxn; if (ptxn->initialized) { array_foreach_modifiable(&ptxn->drivers, dtxn) { if ((*dtxn)->duser->driver->v.end_txn != NULL) { (*dtxn)->duser->driver->v.end_txn(*dtxn, success); } } } pool_unref(&ptxn->pool); } static void push_notification_transaction_commit (void *txn, struct mail_transaction_commit_changes *changes) { struct push_notification_txn *ptxn = (struct push_notification_txn *)txn; if (changes == NULL) { push_notification_txn_mbox_end(ptxn); } else { push_notification_txn_msg_end(ptxn, changes); } push_notification_transaction_end(ptxn, TRUE); } static void push_notification_mailbox_create(struct mailbox *box) { struct push_notification_txn *ptxn; ptxn = push_notification_transaction_create(box, NULL); push_notification_trigger_mbox_create(ptxn, box, NULL); push_notification_transaction_commit(ptxn, NULL); } static void push_notification_mailbox_delete(void *txn ATTR_UNUSED, struct mailbox *box) { struct push_notification_txn *ptxn; ptxn = push_notification_transaction_create(box, NULL); push_notification_trigger_mbox_delete(ptxn, box, NULL); push_notification_transaction_commit(ptxn, NULL); } static void push_notification_mailbox_rename(struct mailbox *src, struct mailbox *dest) { struct push_notification_txn *ptxn; ptxn = push_notification_transaction_create(dest, NULL); push_notification_trigger_mbox_rename(ptxn, src, dest, NULL); push_notification_transaction_commit(ptxn, NULL); } static void push_notification_mailbox_subscribe(struct mailbox *box, bool subscribed) { struct push_notification_txn *ptxn; ptxn = push_notification_transaction_create(box, NULL); push_notification_trigger_mbox_subscribe(ptxn, box, subscribed, NULL); push_notification_transaction_commit(ptxn, NULL); } static void push_notification_mail_save(void *txn, struct mail *mail) { struct push_notification_txn *ptxn = txn; push_notification_transaction_init(ptxn); /* POST_SESSION means MTA delivery. */ if (mail->box->flags & MAILBOX_FLAG_POST_SESSION) { push_notification_trigger_msg_save_new(ptxn, mail, NULL); } else { push_notification_trigger_msg_save_append(ptxn, mail, NULL); } } static void push_notification_mail_copy(void *txn, struct mail *src ATTR_UNUSED, struct mail *dest) { push_notification_mail_save(txn, dest); } static void push_notification_mail_expunge(void *txn, struct mail *mail) { struct push_notification_txn *ptxn = txn; push_notification_transaction_init(ptxn); push_notification_trigger_msg_save_expunge(txn, mail, NULL); } static void push_notification_mail_update_flags(void *txn, struct mail *mail, enum mail_flags old_flags) { struct push_notification_txn *ptxn = txn; push_notification_transaction_init(ptxn); push_notification_trigger_msg_flag_change(txn, mail, NULL, old_flags); } static void push_notification_mail_update_keywords(void *txn, struct mail *mail, const char *const *old_keywords) { struct push_notification_txn *ptxn = txn; push_notification_transaction_init(ptxn); push_notification_trigger_msg_keyword_change(txn, mail, NULL, old_keywords); } static void * push_notification_transaction_begin(struct mailbox_transaction_context *t) { return push_notification_transaction_create(mailbox_transaction_get_mailbox(t), t); } static void push_notification_transaction_rollback(void *txn) { struct push_notification_txn *ptxn = txn; push_notification_transaction_end(ptxn, FALSE); } static void push_notification_config_init(const char *config_name, struct mail_user *user, struct push_notification_driver_list *dlist) { struct push_notification_driver_user *duser; const char *env; unsigned int i; string_t *root_name; root_name = t_str_new(32); str_append(root_name, config_name); for (i = 2;; i++) { env = mail_user_plugin_getenv(user, str_c(root_name)); if ((env == NULL) || (*env == '\0')) { break; } if (push_notification_driver_init(user, env, user->pool, &duser) < 0) { break; } // Add driver. array_append(&dlist->drivers, &duser, 1); str_truncate(root_name, strlen(config_name)); str_printfa(root_name, "%d", i); } } static struct push_notification_driver_list * push_notification_driver_list_init(struct mail_user *user) { struct push_notification_driver_list *dlist; dlist = p_new(user->pool, struct push_notification_driver_list, 1); p_array_init(&dlist->drivers, user->pool, 4); push_notification_config_init(PUSH_NOTIFICATION_CONFIG, user, dlist); if (array_is_empty(&dlist->drivers)) { /* Support old configuration (it was available at time initial OX * driver was first released). */ push_notification_config_init(PUSH_NOTIFICATION_CONFIG_OLD, user, dlist); } return dlist; } static void push_notification_user_deinit(struct mail_user *user) { struct push_notification_user *puser = PUSH_NOTIFICATION_USER_CONTEXT(user); struct push_notification_driver_list *dlist = puser->driverlist; struct push_notification_driver_user **duser; array_foreach_modifiable(&dlist->drivers, duser) { if ((*duser)->driver->v.deinit != NULL) { (*duser)->driver->v.deinit(*duser); } if ((*duser)->driver->v.cleanup != NULL) { (*duser)->driver->v.cleanup(); } } puser->module_ctx.super.deinit(user); } static void push_notification_user_created(struct mail_user *user) { struct mail_user_vfuncs *v = user->vlast; struct push_notification_user *puser; puser = p_new(user->pool, struct push_notification_user, 1); puser->module_ctx.super = *v; user->vlast = &puser->module_ctx.super; v->deinit = push_notification_user_deinit; puser->driverlist = push_notification_driver_list_init(user); MODULE_CONTEXT_SET(user, push_notification_user_module, puser); } /* Plugin interface. */ const char *push_notification_plugin_version = DOVECOT_ABI_VERSION; const char *push_notification_plugin_dependencies[] = { "notify", NULL }; extern struct push_notification_driver push_notification_driver_dlog; extern struct push_notification_driver push_notification_driver_ox; static struct notify_context *push_notification_ctx; static const struct notify_vfuncs push_notification_vfuncs = { /* Mailbox Events */ .mailbox_create = push_notification_mailbox_create, .mailbox_delete_commit = push_notification_mailbox_delete, .mailbox_rename = push_notification_mailbox_rename, .mailbox_set_subscribed = push_notification_mailbox_subscribe, /* Mail Events */ .mail_copy = push_notification_mail_copy, .mail_save = push_notification_mail_save, .mail_expunge = push_notification_mail_expunge, .mail_update_flags = push_notification_mail_update_flags, .mail_update_keywords = push_notification_mail_update_keywords, .mail_transaction_begin = push_notification_transaction_begin, .mail_transaction_commit = push_notification_transaction_commit, .mail_transaction_rollback = push_notification_transaction_rollback }; static struct mail_storage_hooks push_notification_storage_hooks = { .mail_user_created = push_notification_user_created }; void push_notification_plugin_init(struct module *module) { push_notification_ctx = notify_register(&push_notification_vfuncs); mail_storage_hooks_add(module, &push_notification_storage_hooks); push_notification_driver_register(&push_notification_driver_dlog); push_notification_driver_register(&push_notification_driver_ox); push_notification_event_register_rfc5423_events(); } void push_notification_plugin_deinit(void) { push_notification_driver_unregister(&push_notification_driver_dlog); push_notification_driver_unregister(&push_notification_driver_ox); push_notification_event_unregister_rfc5423_events(); mail_storage_hooks_remove(&push_notification_storage_hooks); notify_unregister(push_notification_ctx); }