diff --git a/Makefile.am b/Makefile.am index 128ea65443dc2af3667a07d5b0bfaa874a285ac3..62ea4386efe88ecc866ca420a998d82c09489801 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 0d478385679573d56bb429e2a4911b88df4b675d..97a585c596afd71fe213aff57c545362f13870ad 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 bdc35c80c4978c5a2d275aaf8ae076c07efa68d2..98ae11f178897b31dc4a646659179a3ae7796564 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 b8680c1f000bc91ddd7128b9eb5ac68ea3225ef4..9fd49ba6011b069013ff50e701c70b7707bd0e88 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 eedb6ee7a0ea9dad479bfa2ada027ac90f10e1d6..9c8fec73a6494d6e4a43f24cccc1baf7074f0f2f 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 8abc659032565417cedb29fb5edb68036f6cfd2c..e536864c43dcc212c990f039d97f417c74406fef 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 a0c3259fe5340d97fb09ffd2ab6811cbd30c00fb..f5a52e2460bd211ed6cb75d365c75da2f741efd6 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 bb3fef34f42e7846c0e7e1bf0d78e78fe70e3450..68040291bcc5883301044f6c532c18369810a771 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 3c46867ff1f7b519e0efb9b24c05204041061084..65d394e41964b56fc01ac882b6c1d5fc8f01c4a8 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 2f3cc8df9906954ff18c097b747ccf4ef91506c2..c910a4db940a51deaf80023fcb5583da16b7511d 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 =