bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "lib.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "array.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "hash.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "mail-user.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "push-notification-drivers.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "push-notification-events.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic ARRAY(const struct push_notification_driver *) push_notification_drivers;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic bool
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzpush_notification_driver_find(const char *name, unsigned int *idx_r)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz unsigned int count, i;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct push_notification_driver *const *drivers;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz drivers = array_get(&push_notification_drivers, &count);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz for (i = 0; i < count; i++) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (strcasecmp(drivers[i]->name, name) == 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz *idx_r = i;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return TRUE;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return FALSE;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic const struct push_notification_driver *
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzpush_notification_driver_find_class(const char *driver)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct push_notification_driver *const *class_p;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz unsigned int idx;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!push_notification_driver_find(driver, &idx)) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return NULL;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz class_p = array_idx(&push_notification_drivers, idx);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return *class_p;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic struct push_notification_driver_config *
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzpush_notification_driver_parse_config(const char *p)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const char **args, *key, *p2, *value;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct push_notification_driver_config *config;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz config = t_new(struct push_notification_driver_config, 1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz config->raw_config = p;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz hash_table_create(&config->config, unsafe_data_stack_pool, 0,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz str_hash, strcmp);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (p == NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return config;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz args = t_strsplit_spaces(p, " ");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz for (; *args != NULL; args++) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz p2 = strchr(*args, '=');
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (p2 != NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz key = t_strdup_until(*args, p2);
fe1fb4c867cd78b1d20fa59f8e656fef257ec00bTimo Sirainen value = t_strdup(p2 + 1);
fe1fb4c867cd78b1d20fa59f8e656fef257ec00bTimo Sirainen } else {
fe1fb4c867cd78b1d20fa59f8e656fef257ec00bTimo Sirainen key = *args;
fe1fb4c867cd78b1d20fa59f8e656fef257ec00bTimo Sirainen value = "";
fe1fb4c867cd78b1d20fa59f8e656fef257ec00bTimo Sirainen }
c224fff79d18480a65e9b4504b891b8ea176f5b1Timo Sirainen hash_table_update(config->config, key, value);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return config;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzint
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzpush_notification_driver_init(struct mail_user *user, const char *config_in,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz pool_t pool,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct push_notification_driver_user **duser_r)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz void *context = NULL;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct push_notification_driver *driver;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const char *driver_name, *error_r, *p;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct push_notification_driver_user *duser;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz int ret;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* <driver>[:<driver config>] */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz p = strchr(config_in, ':');
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (p == NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz driver_name = config_in;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz } else {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz driver_name = t_strdup_until(config_in, p);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz driver = push_notification_driver_find_class(driver_name);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (driver == NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_error("Unknown push notification driver: %s", driver_name);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return -1;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (driver->v.init != NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz T_BEGIN {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct push_notification_driver_config *config;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz config = push_notification_driver_parse_config(
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz (p == NULL) ? p : p + 1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz ret = driver->v.init(config, user, pool, &context, &error_r);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz hash_table_destroy(&config->config);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz } T_END;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (ret < 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_error("%s: %s", driver_name, error_r);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return -1;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz duser = p_new(pool, struct push_notification_driver_user, 1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz duser->context = context;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz duser->driver = driver;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz *duser_r = duser;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return 0;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzvoid push_notification_driver_cleanup_all(void)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct push_notification_driver *const *driver;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* Loop through driver list and perform global cleanup tasks. We may not
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz * have used all drivers in this plugin/worker, but the cleanup hooks are
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz * designed to ignore these unused drivers. */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz array_foreach(&push_notification_drivers, driver) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if ((*driver)->v.cleanup != NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz (*driver)->v.cleanup();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzvoid ATTR_FORMAT(3, 4)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzpush_notification_driver_debug(const char *label, struct mail_user *user,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const char *fmt, ...)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz va_list args;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (user->mail_debug) T_BEGIN {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz va_start(args, fmt);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_debug("%s%s", label, t_strdup_vprintf(fmt, args));
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz va_end(args);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz } T_END;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzvoid push_notification_driver_register
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz(const struct push_notification_driver *driver)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz unsigned int idx;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!array_is_created(&push_notification_drivers)) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_array_init(&push_notification_drivers, 4);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (push_notification_driver_find(driver->name, &idx)) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_panic("push_notification_driver_register(%s): duplicate driver",
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz driver->name);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz array_append(&push_notification_drivers, &driver, 1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzvoid push_notification_driver_unregister
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz(const struct push_notification_driver *driver)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz unsigned int idx;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!push_notification_driver_find(driver->name, &idx)) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_panic("push_notification_driver_register(%s): unknown driver",
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz driver->name);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (array_is_created(&push_notification_drivers)) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz array_delete(&push_notification_drivers, idx, 1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (array_is_empty(&push_notification_drivers)) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz array_free(&push_notification_drivers);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
9366a287ae1bafa03f815e6f17d0c3891368e263Timo Sirainen}