diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index d958481bbe2c37d143fcfb36fc801e229941994b..beff7de0a4c4b1e482500d584dcf3f7438c4b9ee 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -571,8 +571,8 @@ bool ext_include_execute_include /* Activate and start the top-level included script */ if ( sieve_binary_block_set_active(renv->sbin, block_id, &this_block_id) ) result = ( sieve_interpreter_start - (subinterp, renv->msgdata, renv->scriptenv, renv->result, &interrupted) - == 1 ); + (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, renv->result, + &interrupted) == 1 ); else result = FALSE; @@ -623,8 +623,8 @@ bool ext_include_execute_include curctx->inc_block_id = 0; curctx->returned = FALSE; result = ( sieve_interpreter_start - (subinterp, renv->msgdata, renv->scriptenv, renv->result, - &interrupted) == 1 ); + (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, + renv->result, &interrupted) == 1 ); } else result = FALSE; } else { diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index 02d9ee6cfdf2c2e1901df061d2d5971aad8132aa..1f99af2be8e4358593a69e04daa4fe29fa443f57 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -18,6 +18,79 @@ #include "sieve-interpreter.h" +/* + * Message context + * (might get moved to separate file) + */ + +struct sieve_message_context { + pool_t pool; + int refcount; + + /* Context data for extensions */ + ARRAY_DEFINE(ext_contexts, void *); +}; + +static struct sieve_message_context *sieve_message_context_create(void) +{ + pool_t pool; + struct sieve_message_context *msgctx; + + pool = pool_alloconly_create("sieve_message_context", 1024); + msgctx = p_new(pool, struct sieve_message_context, 1); + msgctx->pool = pool; + msgctx->refcount = 1; + + p_array_init(&msgctx->ext_contexts, pool, 4); + + return msgctx; +} + +static void sieve_message_context_ref(struct sieve_message_context *msgctx) +{ + msgctx->refcount++; +} + +static void sieve_message_context_unref(struct sieve_message_context **msgctx) +{ + i_assert((*msgctx)->refcount > 0); + + if (--(*msgctx)->refcount != 0) + return; + + pool_unref(&((*msgctx)->pool)); + + *msgctx = NULL; +} + +inline void sieve_message_context_extension_set + (struct sieve_message_context *msgctx, int ext_id, void *context) +{ + array_idx_set(&msgctx->ext_contexts, (unsigned int) ext_id, &context); +} + +inline const void *sieve_message_context_extension_get + (struct sieve_message_context *msgctx, int ext_id) +{ + void * const *ctx; + + if ( ext_id < 0 || ext_id >= (int) array_count(&msgctx->ext_contexts) ) + return NULL; + + ctx = array_idx(&msgctx->ext_contexts, (unsigned int) ext_id); + + return *ctx; +} + +inline pool_t sieve_message_context_pool(struct sieve_message_context *msgctx) +{ + return msgctx->pool; +} + +/* + * Interpreter + */ + struct sieve_interpreter { pool_t pool; @@ -84,7 +157,10 @@ struct sieve_interpreter *sieve_interpreter_create void sieve_interpreter_free(struct sieve_interpreter **interp) { sieve_binary_unref(&(*interp)->runenv.sbin); - + + if ( (*interp)->runenv.msgctx != NULL ) + sieve_message_context_unref(&(*interp)->runenv.msgctx); + pool_unref(&((*interp)->pool)); *interp = NULL; @@ -320,13 +396,20 @@ int sieve_interpreter_continue int sieve_interpreter_start (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result *result, - bool *interrupted) + const struct sieve_script_env *senv, struct sieve_message_context *msgctx, + struct sieve_result *result, bool *interrupted) { interp->runenv.msgdata = msgdata; interp->runenv.result = result; interp->runenv.scriptenv = senv; + if ( msgctx == NULL ) + interp->runenv.msgctx = sieve_message_context_create(); + else { + interp->runenv.msgctx = msgctx; + sieve_message_context_ref(msgctx); + } + return sieve_interpreter_continue(interp, interrupted); } @@ -344,7 +427,7 @@ int sieve_interpreter_run sieve_result_ref(*result); } - ret = sieve_interpreter_start(interp, msgdata, senv, *result, NULL); + ret = sieve_interpreter_start(interp, msgdata, senv, NULL, *result, NULL); if ( ret >= 0 && is_topmost ) { ret = sieve_result_execute(*result, msgdata, senv); diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index 4c7c4c29cd890a65e1785d255d47919d9516b4f1..fef5a094f6e1d93f69d299c66b14da6a6d2c9d46 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -8,18 +8,34 @@ #include "sieve-common.h" -/* FIXME: make dumps use some interpreter function */ +/* FIXME: make execution dumps use some interpreter function */ #include <stdio.h> +/* Message context */ + +struct sieve_message_context; + +inline void sieve_message_context_extension_set + (struct sieve_message_context *msgctx, int ext_id, void *context); +inline const void *sieve_message_context_extension_get + (struct sieve_message_context *msgctx, int ext_id); +inline pool_t sieve_message_context_pool + (struct sieve_message_context *msgctx); + +/* Interpreter */ + struct sieve_interpreter; struct sieve_runtime_env { struct sieve_interpreter *interp; + struct sieve_script *script; - struct sieve_binary *sbin; + const struct sieve_script_env *scriptenv; const struct sieve_message_data *msgdata; - const struct sieve_script_env *scriptenv; + struct sieve_message_context *msgctx; + + struct sieve_binary *sbin; struct sieve_result *result; }; @@ -81,8 +97,8 @@ int sieve_interpreter_continue (struct sieve_interpreter *interp, bool *interrupted); int sieve_interpreter_start (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result *result, - bool *interrupted); + const struct sieve_script_env *senv, struct sieve_message_context *msgctx, + struct sieve_result *result, bool *interrupted); int sieve_interpreter_run (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, struct sieve_result **result);