diff --git a/src/lib-sieve/plugins/enotify/ext-enotify-common.c b/src/lib-sieve/plugins/enotify/ext-enotify-common.c index 5e34d842d68c1cc2e5017e26968b03461398e31d..5227f620e5ad134fff37521cbca034805f8bca7c 100644 --- a/src/lib-sieve/plugins/enotify/ext-enotify-common.c +++ b/src/lib-sieve/plugins/enotify/ext-enotify-common.c @@ -66,9 +66,11 @@ static const struct sieve_enotify_method *ext_enotify_method_register const struct sieve_enotify_method_def *nmth_def) { struct sieve_enotify_method *nmth; + int nmth_id = (int) array_count(&ectx->notify_methods); nmth = array_append_space(&ectx->notify_methods); nmth->def = nmth_def; + nmth->id = nmth_id; nmth->svinst = svinst; if ( nmth_def->load != NULL ) @@ -116,6 +118,27 @@ const struct sieve_enotify_method *sieve_enotify_method_register return NULL; } +void sieve_enotify_method_unregister +(const struct sieve_enotify_method *nmth) +{ + struct sieve_instance *svinst = nmth->svinst; + const struct sieve_extension *ntfy_ext = + sieve_extension_get_by_name(svinst, "enotify"); + + if ( ntfy_ext != NULL ) { + struct ext_enotify_context *ectx = + (struct ext_enotify_context *) ntfy_ext->context; + int nmth_id = nmth->id; + + if ( nmth_id >= 0 && nmth_id < (int)array_count(&ectx->notify_methods) ) { + struct sieve_enotify_method *nmth_mod = + array_idx_modifiable(&ectx->notify_methods, nmth_id); + + nmth_mod->def = NULL; + } + } +} + const struct sieve_enotify_method *ext_enotify_method_find (const struct sieve_extension *ntfy_ext, const char *identifier) { @@ -147,13 +170,14 @@ static const char *ext_notify_get_methods_string string_t *result = t_str_new(128); methods = array_get(&ectx->notify_methods, &meth_count); - + if ( meth_count > 0 ) { - str_append(result, methods[0].def->identifier); - - for ( i = 1; i < meth_count; i++ ) { - str_append_c(result, ' '); - str_append(result, methods[i].def->identifier); + for ( i = 0; i < meth_count; i++ ) { + if ( str_len(result) > 0 ) + str_append_c(result, ' '); + + if ( methods[i].def != NULL ) + str_append(result, methods[i].def->identifier); } return str_c(result); diff --git a/src/lib-sieve/plugins/enotify/ext-enotify.c b/src/lib-sieve/plugins/enotify/ext-enotify.c index 3507d593952bd7eebe70b76c66f097e985c260b7..263e54204973c41cd0501f44aee128b3034cf708 100644 --- a/src/lib-sieve/plugins/enotify/ext-enotify.c +++ b/src/lib-sieve/plugins/enotify/ext-enotify.c @@ -71,7 +71,7 @@ static bool ext_enotify_load(const struct sieve_extension *ext, void **context) ext_enotify_methods_init(ext->svinst, ectx); - sieve_extension_capabilities_register(ext->svinst, ext, ¬ify_capabilities); + sieve_extension_capabilities_register(ext, ¬ify_capabilities); return TRUE; } diff --git a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h index 769faa332514e04995049595d99a5b0b5324ad63..e455d7e5b8975c83ff4b02dbab1b38fc5bb13b7c 100644 --- a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h +++ b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h @@ -84,6 +84,7 @@ struct sieve_enotify_method_def { struct sieve_enotify_method { const struct sieve_enotify_method_def *def; + int id; struct sieve_instance *svinst; void *context; @@ -91,7 +92,9 @@ struct sieve_enotify_method { const struct sieve_enotify_method *sieve_enotify_method_register (struct sieve_instance *svinst, - const struct sieve_enotify_method_def *nmth_def); + const struct sieve_enotify_method_def *nmth_def); +void sieve_enotify_method_unregister + (const struct sieve_enotify_method *nmth); /* * Notify method environment diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index fcc8add387da37ee7dcb5d3ca24ef4b233eb98f6..b858903e7793f2551779f8ccaa1298c283678e1b 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -238,6 +238,25 @@ const struct sieve_extension *const *sieve_extensions_get_preloaded * Extension registry */ +static bool _sieve_extension_load(struct sieve_extension *ext) +{ + /* Call load handler */ + if ( ext->def != NULL && ext->def->load != NULL && + !ext->def->load(ext, &ext->context) ) { + sieve_sys_error("failed to load '%s' extension support.", ext->def->name); + return FALSE; + } + + return TRUE; +} + +static void _sieve_extension_unload(struct sieve_extension *ext) +{ + /* Call unload handler */ + if ( ext->def != NULL && ext->def->unload != NULL ) + ext->def->unload(ext); +} + static void sieve_extension_registry_init(struct sieve_instance *svinst) { struct sieve_extension_registry *ext_reg = svinst->ext_reg; @@ -260,8 +279,7 @@ static void sieve_extension_registry_deinit(struct sieve_instance *svinst) while ( hash_table_iterate(itx, &key, &value) ) { struct sieve_extension *ext = (struct sieve_extension *) value; - if ( ext->def != NULL && ext->def->unload != NULL ) - ext->def->unload(ext); + _sieve_extension_unload(ext); } hash_table_iterate_deinit(&itx); @@ -269,18 +287,6 @@ static void sieve_extension_registry_deinit(struct sieve_instance *svinst) hash_table_destroy(&ext_reg->extension_index); } -static bool _sieve_extension_load(struct sieve_extension *ext) -{ - /* Call load handler */ - if ( ext->def != NULL && ext->def->load != NULL && - !ext->def->load(ext, &ext->context) ) { - sieve_sys_error("failed to load '%s' extension support.", ext->def->name); - return FALSE; - } - - return TRUE; -} - bool sieve_extension_reload(const struct sieve_extension *ext) { struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg; @@ -307,7 +313,7 @@ static struct sieve_extension *_sieve_extension_register /* Register extension if it is not registered already */ if ( ext == NULL ) { - int ext_id = array_count(&ext_reg->extensions); + int ext_id = (int)array_count(&ext_reg->extensions); /* Add extension to the registry */ @@ -318,6 +324,12 @@ static struct sieve_extension *_sieve_extension_register hash_table_insert (ext_reg->extension_index, (void *) extdef->name, (void *) ext); + + /* Re-register it if it were previously unregistered + * (not going to happen) + */ + } else if ( ext->def == NULL ) { + ext->def = extdef; } /* Enable extension */ @@ -345,10 +357,26 @@ const struct sieve_extension *sieve_extension_register return _sieve_extension_register(svinst, extdef, load, FALSE); } +void sieve_extension_unregister(const struct sieve_extension *ext) +{ + struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg; + struct sieve_extension *mod_ext; + int ext_id = ext->id; + + if ( ext_id > 0 && ext_id < (int) array_count(&ext_reg->extensions) ) { + mod_ext = array_idx_modifiable(&ext_reg->extensions, ext_id); + + sieve_extension_capabilities_unregister(ext); + _sieve_extension_unload(mod_ext); + mod_ext->loaded = FALSE; + mod_ext->def = NULL; + } +} + const struct sieve_extension *sieve_extension_require (struct sieve_instance *svinst, const struct sieve_extension_def *extdef) { - return _sieve_extension_register(svinst, extdef, TRUE, TRUE); + return _sieve_extension_register(svinst, extdef, TRUE, TRUE); } int sieve_extensions_get_count(struct sieve_instance *svinst) @@ -367,7 +395,7 @@ const struct sieve_extension *sieve_extension_get_by_id if ( ext_id < array_count(&ext_reg->extensions) ) { ext = array_idx(&ext_reg->extensions, ext_id); - if ( ext->enabled ) + if ( ext->def != NULL && ext->enabled ) return ext; } @@ -386,7 +414,7 @@ const struct sieve_extension *sieve_extension_get_by_name ext = (const struct sieve_extension *) hash_table_lookup(ext_reg->extension_index, name); - if ( ext == NULL || !ext->enabled ) + if ( ext == NULL || ext->def == NULL || !ext->enabled ) return NULL; return ext; @@ -406,7 +434,8 @@ const char *sieve_extensions_get_string(struct sieve_instance *svinst) /* Find first listable extension */ while ( i < ext_count && - !( exts[i].enabled && *(exts[i].def->name) != '@' ) ) + !( exts[i].enabled && exts[i].def != NULL && + *(exts[i].def->name) != '@' ) ) i++; if ( i < ext_count ) { @@ -416,7 +445,8 @@ const char *sieve_extensions_get_string(struct sieve_instance *svinst) /* Add others */ for ( ; i < ext_count; i++ ) { - if ( exts[i].enabled && *(exts[i].def->name) != '@' ) { + if ( exts[i].enabled && exts[i].def != NULL && + *(exts[i].def->name) != '@' ) { str_append_c(extstr, ' '); str_append(extstr, exts[i].def->name); } @@ -493,7 +523,7 @@ void sieve_extensions_set_string ext = (const struct sieve_extension *) hash_table_lookup(ext_reg->extension_index, name); - if ( ext == NULL ) { + if ( ext == NULL || ext->def == NULL ) { sieve_sys_warning( "ignored unknown extension '%s' while configuring " "available extensions", name); @@ -550,7 +580,8 @@ void sieve_extensions_set_string /* Perform actual activation/deactivation */ - if ( exts[i].id >= 0 && *(exts[i].def->name) != '@' ) { + if ( exts[i].id >= 0 && exts[i].def != NULL && + *(exts[i].def->name) != '@' ) { if ( disabled && !exts[i].required ) sieve_extension_disable(&exts[i]); else @@ -605,9 +636,10 @@ void sieve_capability_registry_deinit(struct sieve_instance *svinst) } void sieve_extension_capabilities_register -(struct sieve_instance *svinst, const struct sieve_extension *ext, +(const struct sieve_extension *ext, const struct sieve_extension_capabilities *cap) -{ +{ + struct sieve_instance *svinst = ext->svinst; struct sieve_extension_registry *ext_reg = svinst->ext_reg; struct sieve_capability_registration *reg = p_new(svinst->pool, struct sieve_capability_registration, 1); @@ -619,11 +651,29 @@ void sieve_extension_capabilities_register (ext_reg->capabilities_index, (void *) cap->name, (void *) reg); } +void sieve_extension_capabilities_unregister +(const struct sieve_extension *ext) +{ + struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg; + struct hash_iterate_context *hictx; + void *key = NULL, *value = NULL; + + hictx = hash_table_iterate_init(ext_reg->capabilities_index); + while ( hash_table_iterate(hictx, key, value) ) { + struct sieve_capability_registration *reg = + (struct sieve_capability_registration *) value; + + if ( reg->ext == ext ) + hash_table_remove(ext_reg->capabilities_index, key); + } + hash_table_iterate_deinit(&hictx); +} + const char *sieve_extension_capabilities_get_string (struct sieve_instance *svinst, const char *cap_name) { struct sieve_extension_registry *ext_reg = svinst->ext_reg; - const struct sieve_capability_registration *cap_reg = + const struct sieve_capability_registration *cap_reg = (const struct sieve_capability_registration *) hash_table_lookup(ext_reg->capabilities_index, cap_name); const struct sieve_extension_capabilities *cap; diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h index d639de7bd452992fd2cf93b9e5fc3872bbb516db..fc9bc6ac85602fd6621b6475f75ced20274fccb7 100644 --- a/src/lib-sieve/sieve-extensions.h +++ b/src/lib-sieve/sieve-extensions.h @@ -118,6 +118,8 @@ const struct sieve_extension *sieve_extension_require (struct sieve_instance *svinst, const struct sieve_extension_def *extension); bool sieve_extension_reload(const struct sieve_extension *ext); +void sieve_extension_unregister(const struct sieve_extension *ext); + int sieve_extensions_get_count(struct sieve_instance *svinst); const struct sieve_extension *sieve_extension_get_by_id @@ -148,8 +150,11 @@ struct sieve_extension_capabilities { }; void sieve_extension_capabilities_register - (struct sieve_instance *svinst, const struct sieve_extension *ext, + (const struct sieve_extension *ext, const struct sieve_extension_capabilities *cap); +void sieve_extension_capabilities_unregister + (const struct sieve_extension *ext); + const char *sieve_extension_capabilities_get_string (struct sieve_instance *svinst, const char *cap_name); diff --git a/src/lib-sieve/sieve-plugins.c b/src/lib-sieve/sieve-plugins.c index cf80ab5ba08d1b80c6361ee98ee2a2c924c13008..ad37c86e47848922c6afbddf335aa33ed8f926ea 100644 --- a/src/lib-sieve/sieve-plugins.c +++ b/src/lib-sieve/sieve-plugins.c @@ -13,6 +13,9 @@ struct sieve_plugin { struct module *module; + + void *context; + struct sieve_plugin *next; }; @@ -103,7 +106,7 @@ void sieve_plugins_load(struct sieve_instance *svinst, const char *path, const c for (i = 0; module_names[i] != NULL; i++) { struct sieve_plugin *plugin; const char *name = module_names[i]; - void (*load_func)(struct sieve_instance *svinst); + void (*load_func)(struct sieve_instance *svinst, void **context); /* Find the module */ module = sieve_plugin_module_find(name); @@ -129,7 +132,7 @@ void sieve_plugins_load(struct sieve_instance *svinst, const char *path, const c load_func = module_get_symbol (module, t_strdup_printf("%s_load", module->name)); if ( load_func != NULL ) { - load_func(svinst); + load_func(svinst, &plugin->context); } /* Add plugin to the instance */ @@ -159,12 +162,12 @@ void sieve_plugins_unload(struct sieve_instance *svinst) plugin = svinst->plugins; while ( plugin != NULL ) { struct module *module = plugin->module; - void (*unload_func)(struct sieve_instance *svinst); + void (*unload_func)(struct sieve_instance *svinst, void *context); unload_func = module_get_symbol (module, t_strdup_printf("%s_unload", module->name)); if ( unload_func != NULL ) { - unload_func(svinst); + unload_func(svinst, plugin->context); } plugin = plugin->next; diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 76ed25b31e4b81b80d5df165ee81e67fb298a0ae..123b465564b2477fa9ad0acced3825c0e3784801 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -88,10 +88,10 @@ struct sieve_instance *sieve_init void sieve_deinit(struct sieve_instance **svinst) { - sieve_extensions_deinit(*svinst); - sieve_plugins_unload(*svinst); + sieve_extensions_deinit(*svinst); + pool_unref(&(*svinst)->pool); *svinst = NULL;