From 2c1540a5e4da3b3d9d878f068984ca68fbdad22a Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Mon, 17 Aug 2015 23:34:21 +0200 Subject: [PATCH] lib-sieve: Implemented the vnd.dovecot.environment extension. This adds the vnd.dovecot.default-mailbox and vnd.dovecot.username environment items. It creates the 'env' variables namespace through which all environment items can be accessed directly. This extension is yet to be documented properly. More environment items are under consideration. --- Makefile.am | 2 + configure.ac | 1 + src/lib-sieve/Makefile.am | 1 + .../environment/ext-environment-common.c | 146 +++++++++++------- .../environment/ext-environment-common.h | 7 +- .../plugins/environment/ext-environment.c | 14 +- .../environment/sieve-ext-environment.h | 33 +++- .../plugins/environment/tst-environment.c | 2 +- src/lib-sieve/plugins/vnd.dovecot/Makefile.am | 2 +- src/lib-sieve/sieve-extensions.c | 3 +- 10 files changed, 147 insertions(+), 64 deletions(-) diff --git a/Makefile.am b/Makefile.am index 128ea6544..62ea4386e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -162,6 +162,8 @@ test_cases = \ tests/extensions/metadata/execute.svtest \ tests/extensions/metadata/errors.svtest \ tests/extensions/vnd.dovecot/debug/execute.svtest \ + tests/extensions/vnd.dovecot/environment/basic.svtest \ + tests/extensions/vnd.dovecot/environment/variables.svtest \ tests/deprecated/notify/basic.svtest \ tests/deprecated/notify/mailto.svtest \ tests/deprecated/notify/errors.svtest \ diff --git a/configure.ac b/configure.ac index 0d4783856..97a585c59 100644 --- a/configure.ac +++ b/configure.ac @@ -211,6 +211,7 @@ src/lib-sieve/plugins/duplicate/Makefile src/lib-sieve/plugins/index/Makefile src/lib-sieve/plugins/vnd.dovecot/Makefile src/lib-sieve/plugins/vnd.dovecot/debug/Makefile +src/lib-sieve/plugins/vnd.dovecot/environment/Makefile src/lib-sieve-tool/Makefile src/lib-managesieve/Makefile src/plugins/Makefile diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am index bdc35c80c..98ae11f17 100644 --- a/src/lib-sieve/Makefile.am +++ b/src/lib-sieve/Makefile.am @@ -78,6 +78,7 @@ plugins = \ $(extdir)/index/libsieve_ext_index.la \ $(extdir)/metadata/libsieve_ext_metadata.la \ $(extdir)/vnd.dovecot/debug/libsieve_ext_debug.la \ + $(extdir)/vnd.dovecot/environment/libsieve_ext_vnd_environment.la \ $(unfinished_plugins) libdovecot_sieve_la_DEPENDENCIES = \ diff --git a/src/lib-sieve/plugins/environment/ext-environment-common.c b/src/lib-sieve/plugins/environment/ext-environment-common.c index b8680c1f0..9fd49ba60 100644 --- a/src/lib-sieve/plugins/environment/ext-environment-common.c +++ b/src/lib-sieve/plugins/environment/ext-environment-common.c @@ -6,14 +6,10 @@ #include "sieve-common.h" #include "sieve-extensions.h" +#include "sieve-interpreter.h" #include "ext-environment-common.h" -struct ext_environment_context { - HASH_TABLE(const char *, - const struct sieve_environment_item *) environment_items; -}; - /* * Core environment items */ @@ -30,71 +26,121 @@ static const struct sieve_environment_item *core_env_items[] = { static unsigned int core_env_items_count = N_ELEMENTS(core_env_items); /* - * Registration + * Validator context */ -static void ext_environment_item_register -(struct ext_environment_context *ectx, - const struct sieve_environment_item *item) +struct ext_environment_interpreter_context { + HASH_TABLE(const char *, + const struct sieve_environment_item *) environment_items; + + unsigned int active:1; +}; + +static void ext_environment_interpreter_extension_free + (const struct sieve_extension *ext, struct sieve_interpreter *interp, + void *context); + +struct sieve_interpreter_extension environment_interpreter_extension = { + .ext_def = &environment_extension, + .free = ext_environment_interpreter_extension_free, +}; + +static struct ext_environment_interpreter_context * +ext_environment_interpreter_context_create +(const struct sieve_extension *this_ext, struct sieve_interpreter *interp) { - hash_table_insert(ectx->environment_items, item->name, item); + pool_t pool = sieve_interpreter_pool(interp); + struct ext_environment_interpreter_context *ctx; + + ctx = p_new(pool, struct ext_environment_interpreter_context, 1); + + hash_table_create + (&ctx->environment_items, default_pool, 0, str_hash, strcmp); + + sieve_interpreter_extension_register + (interp, this_ext, &environment_interpreter_extension, (void *)ctx); + return ctx; } -void sieve_ext_environment_item_register -(const struct sieve_extension *ext, const struct sieve_environment_item *item) +static void ext_environment_interpreter_extension_free +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_interpreter *interp ATTR_UNUSED, void *context) { - struct ext_environment_context *ectx = - (struct ext_environment_context *) ext->context; + struct ext_environment_interpreter_context *ctx = + (struct ext_environment_interpreter_context *)context; - ext_environment_item_register(ectx, item); + hash_table_destroy(&ctx->environment_items); } -/* - * Initialization - */ - -bool ext_environment_init -(const struct sieve_extension *ext ATTR_UNUSED, void **context) +static struct ext_environment_interpreter_context * +ext_environment_interpreter_context_get +(const struct sieve_extension *this_ext, struct sieve_interpreter *interp) { - struct ext_environment_context *ectx = - i_new(struct ext_environment_context, 1); + struct ext_environment_interpreter_context *ctx = + (struct ext_environment_interpreter_context *) + sieve_interpreter_extension_get_context(interp, this_ext); + if ( ctx == NULL ) + ctx = ext_environment_interpreter_context_create(this_ext, interp); + + return ctx; +} + +void ext_environment_interpreter_init +(const struct sieve_extension *this_ext, struct sieve_interpreter *interp) +{ + struct ext_environment_interpreter_context *ctx; unsigned int i; - hash_table_create - (&ectx->environment_items, default_pool, 0, str_hash, strcmp); + /* Create our context */ + ctx = ext_environment_interpreter_context_get(this_ext, interp); for ( i = 0; i < core_env_items_count; i++ ) { - ext_environment_item_register(ectx, core_env_items[i]); + const struct sieve_environment_item *item = core_env_items[i]; + hash_table_insert(ctx->environment_items, item->name, item); } - *context = (void *) ectx; - - return TRUE; + ctx->active = TRUE; } -void ext_environment_deinit(const struct sieve_extension *ext) +bool sieve_ext_environment_is_active +(const struct sieve_extension *env_ext, struct sieve_interpreter *interp) { - struct ext_environment_context *ectx = - (struct ext_environment_context *) ext->context; + struct ext_environment_interpreter_context *ctx = + ext_environment_interpreter_context_get(env_ext, interp); - hash_table_destroy(&ectx->environment_items); - i_free(ectx); + return ( ctx != NULL && ctx->active ); } +/* + * Registration + */ + +void sieve_environment_item_register +(const struct sieve_extension *env_ext, struct sieve_interpreter *interp, + const struct sieve_environment_item *item) +{ + struct ext_environment_interpreter_context *ctx; + + i_assert( sieve_extension_is(env_ext, environment_extension) ); + ctx = ext_environment_interpreter_context_get(env_ext, interp); + hash_table_insert(ctx->environment_items, item->name, item); +} /* * Retrieval */ const char *ext_environment_item_get_value -(const struct sieve_extension *ext, const char *name, - const struct sieve_script_env *senv) +(const struct sieve_extension *env_ext, + const struct sieve_runtime_env *renv, const char *name) { - struct ext_environment_context *ectx = - (struct ext_environment_context *) ext->context; + struct ext_environment_interpreter_context *ctx = + ext_environment_interpreter_context_get(env_ext, renv->interp); const struct sieve_environment_item *item = - hash_table_lookup(ectx->environment_items, name); + hash_table_lookup(ctx->environment_items, name); + + i_assert( sieve_extension_is(env_ext, environment_extension) ); if ( item == NULL ) return NULL; @@ -103,7 +149,7 @@ const char *ext_environment_item_get_value return item->value; if ( item->get_value != NULL ) - return item->get_value(ext->svinst, senv); + return item->get_value(renv); return NULL; } @@ -119,10 +165,9 @@ const char *ext_environment_item_get_value */ static const char *envit_domain_get_value -(struct sieve_instance *svinst, - const struct sieve_script_env *senv ATTR_UNUSED) +(const struct sieve_runtime_env *renv) { - return svinst->domainname; + return renv->svinst->domainname; } const struct sieve_environment_item domain_env_item = { @@ -137,10 +182,9 @@ const struct sieve_environment_item domain_env_item = { */ static const char *envit_host_get_value -(struct sieve_instance *svinst, - const struct sieve_script_env *senv ATTR_UNUSED) +(const struct sieve_runtime_env *renv) { - return svinst->hostname; + return renv->svinst->hostname; } const struct sieve_environment_item host_env_item = { @@ -160,10 +204,9 @@ const struct sieve_environment_item host_env_item = { */ static const char *envit_location_get_value -(struct sieve_instance *svinst, - const struct sieve_script_env *senv ATTR_UNUSED) +(const struct sieve_runtime_env *renv) { - switch ( svinst->env_location ) { + switch ( renv->svinst->env_location ) { case SIEVE_ENV_LOCATION_MDA: return "MDA"; case SIEVE_ENV_LOCATION_MTA: @@ -190,10 +233,9 @@ const struct sieve_environment_item location_env_item = { */ static const char *envit_phase_get_value -(struct sieve_instance *svinst, - const struct sieve_script_env *senv ATTR_UNUSED) +(const struct sieve_runtime_env *renv) { - switch ( svinst->delivery_phase ) { + switch ( renv->svinst->delivery_phase ) { case SIEVE_DELIVERY_PHASE_PRE: return "pre"; case SIEVE_DELIVERY_PHASE_DURING: diff --git a/src/lib-sieve/plugins/environment/ext-environment-common.h b/src/lib-sieve/plugins/environment/ext-environment-common.h index eedb6ee7a..9c8fec73a 100644 --- a/src/lib-sieve/plugins/environment/ext-environment-common.h +++ b/src/lib-sieve/plugins/environment/ext-environment-common.h @@ -47,11 +47,10 @@ bool ext_environment_init(const struct sieve_extension *ext, void **context); void ext_environment_deinit(const struct sieve_extension *ext); /* - * Environment item retrieval + * Validator context */ -const char *ext_environment_item_get_value - (const struct sieve_extension *ext, const char *name, - const struct sieve_script_env *senv); +void ext_environment_interpreter_init +(const struct sieve_extension *this_ext, struct sieve_interpreter *interp); #endif /* __EXT_VARIABLES_COMMON_H */ diff --git a/src/lib-sieve/plugins/environment/ext-environment.c b/src/lib-sieve/plugins/environment/ext-environment.c index 8abc65903..e536864c4 100644 --- a/src/lib-sieve/plugins/environment/ext-environment.c +++ b/src/lib-sieve/plugins/environment/ext-environment.c @@ -30,12 +30,14 @@ static bool ext_environment_validator_load (const struct sieve_extension *ext, struct sieve_validator *valdtr); +static bool ext_environment_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, sieve_size_t *address); const struct sieve_extension_def environment_extension = { .name = "environment", - .load = ext_environment_init, - .unload = ext_environment_deinit, .validator_load = ext_environment_validator_load, + .interpreter_load = ext_environment_interpreter_load, SIEVE_EXT_DEFINE_OPERATION(tst_environment_operation) }; @@ -43,7 +45,15 @@ static bool ext_environment_validator_load (const struct sieve_extension *ext, struct sieve_validator *valdtr) { sieve_validator_register_command(valdtr, ext, &tst_environment); + return TRUE; +} +static bool ext_environment_interpreter_load +(const struct sieve_extension *ext, + const struct sieve_runtime_env *renv, + sieve_size_t *address ATTR_UNUSED) +{ + ext_environment_interpreter_init(ext, renv->interp); return TRUE; } diff --git a/src/lib-sieve/plugins/environment/sieve-ext-environment.h b/src/lib-sieve/plugins/environment/sieve-ext-environment.h index a0c3259fe..f5a52e246 100644 --- a/src/lib-sieve/plugins/environment/sieve-ext-environment.h +++ b/src/lib-sieve/plugins/environment/sieve-ext-environment.h @@ -6,16 +6,43 @@ #include "sieve-common.h" +/* + * Environment extension + */ + +/* FIXME: this is not suitable for future plugin support */ + +extern const struct sieve_extension_def environment_extension; + +static inline const struct sieve_extension * +sieve_ext_environment_get_extension +(struct sieve_instance *svinst) +{ + return sieve_extension_register + (svinst, &environment_extension, FALSE); +} + +bool sieve_ext_environment_is_active + (const struct sieve_extension *env_ext, + struct sieve_interpreter *interp); + +/* + * Environment item + */ + struct sieve_environment_item { const char *name; const char *value; const char *(*get_value) - (struct sieve_instance *svinst, const struct sieve_script_env *senv); + (const struct sieve_runtime_env *renv); }; -void sieve_ext_environment_item_register - (const struct sieve_extension *ext, +void sieve_environment_item_register + (const struct sieve_extension *env_ext, struct sieve_interpreter *interp, const struct sieve_environment_item *item); +const char *ext_environment_item_get_value + (const struct sieve_extension *env_ext, + const struct sieve_runtime_env *renv, const char *name); #endif diff --git a/src/lib-sieve/plugins/environment/tst-environment.c b/src/lib-sieve/plugins/environment/tst-environment.c index bb3fef34f..68040291b 100644 --- a/src/lib-sieve/plugins/environment/tst-environment.c +++ b/src/lib-sieve/plugins/environment/tst-environment.c @@ -188,7 +188,7 @@ static int tst_environment_operation_execute sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "environment test"); env_item = ext_environment_item_get_value - (this_ext, str_c(name), renv->scriptenv); + (this_ext, renv, str_c(name)); if ( env_item != NULL ) { /* Construct value list */ diff --git a/src/lib-sieve/plugins/vnd.dovecot/Makefile.am b/src/lib-sieve/plugins/vnd.dovecot/Makefile.am index 3c46867ff..65d394e41 100644 --- a/src/lib-sieve/plugins/vnd.dovecot/Makefile.am +++ b/src/lib-sieve/plugins/vnd.dovecot/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = debug +SUBDIRS = debug environment diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index 2f3cc8df9..c910a4db9 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -139,6 +139,7 @@ extern const struct sieve_extension_def virustest_extension; extern const struct sieve_extension_def editheader_extension; extern const struct sieve_extension_def vnd_debug_extension; +extern const struct sieve_extension_def vnd_environment_extension; const struct sieve_extension_def *sieve_extra_extensions[] = { &vacation_seconds_extension, &spamtest_extension, &spamtestplus_extension, @@ -146,7 +147,7 @@ const struct sieve_extension_def *sieve_extra_extensions[] = { &mboxmetadata_extension, &servermetadata_extension, /* vnd.dovecot. */ - &vnd_debug_extension + &vnd_debug_extension, &vnd_environment_extension }; const unsigned int sieve_extra_extensions_count = -- GitLab