From ea0e6b494daa8a52ebf05aff6cf63a2143fe4ab4 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Tue, 29 Jul 2008 11:30:15 +0200 Subject: [PATCH] Variables: resolved issues in the scope implementation. --- TODO | 2 - .../plugins/include/ext-include-common.c | 9 +++ .../plugins/variables/ext-variables-common.c | 60 ++++++++++++++++++- .../plugins/variables/sieve-ext-variables.h | 5 ++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index 07a50b0ea..a42d94485 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,4 @@ Next (in order of descending priority/precedence): -* Resolve problems in variables extension: scope uses hash the wrong way. - * Full standards compliance review for the engine and all fully implemented sieve extensions. Issues discovered so far: - :matches : match values must only be changed when the test diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index a987d9ae4..bb02e59c4 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -94,10 +94,16 @@ static void ext_include_ast_free struct sieve_script **scripts; unsigned int count, i; + /* Unreference included scripts */ scripts = array_get_modifiable(&actx->included_scripts, &count); for ( i = 0; i < count; i++ ) { sieve_script_unref(&scripts[i]); } + + /* Unreference variable scopes */ + sieve_variable_scope_unref(&actx->import_vars); + if ( actx->global_vars != NULL ) + sieve_variable_scope_unref(&actx->global_vars); } static const struct sieve_ast_extension include_ast_extension = { @@ -120,6 +126,9 @@ struct ext_include_ast_context *ext_include_create_ast_context (struct ext_include_ast_context *) sieve_ast_extension_get_context(parent, &include_extension); actx->global_vars = ( parent_ctx == NULL ? NULL : parent_ctx->global_vars ); + + if ( actx->global_vars != NULL ) + sieve_variable_scope_ref(actx->global_vars); } sieve_ast_extension_register(ast, &include_ast_extension, (void *) actx); diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c index 028b8e08f..1459f07e4 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-common.c +++ b/src/lib-sieve/plugins/variables/ext-variables-common.c @@ -42,6 +42,8 @@ const unsigned int default_set_modifiers_count = struct sieve_variable_scope { pool_t pool; + int refcount; + const struct sieve_extension *ext; unsigned int next_index; @@ -55,13 +57,31 @@ struct sieve_variable_scope *sieve_variable_scope_create scope = p_new(pool, struct sieve_variable_scope, 1); scope->pool = pool; + scope->refcount = 1; + scope->ext = ext; scope->variables = hash_create - (pool, pool, 0, strcase_hash, (hash_cmp_callback_t *)strcasecmp); + (default_pool, pool, 0, strcase_hash, (hash_cmp_callback_t *)strcasecmp); return scope; } +void sieve_variable_scope_ref(struct sieve_variable_scope *scope) +{ + scope->refcount++; +} + +void sieve_variable_scope_unref(struct sieve_variable_scope **scope) +{ + i_assert((*scope)->refcount > 0); + + if (--(*scope)->refcount != 0) + return; + + hash_destroy(&(*scope)->variables); + *scope = NULL; +} + struct sieve_variable *sieve_variable_scope_declare (struct sieve_variable_scope *scope, const char *identifier) { @@ -159,7 +179,41 @@ void sieve_variable_assign str_append_str(varval, value); } -/* Validator context */ +/* + * AST Context + */ + +static void ext_variables_ast_free +(struct sieve_ast *ast ATTR_UNUSED, void *context) +{ + struct sieve_variable_scope *main_scope = + (struct sieve_variable_scope *) context; + + /* Unreference main variable scope */ + sieve_variable_scope_unref(&main_scope); +} + +static const struct sieve_ast_extension variables_ast_extension = { + &variables_extension, + ext_variables_ast_free +}; + +static struct sieve_variable_scope *ext_variables_create_main_scope +(struct sieve_ast *ast) +{ + struct sieve_variable_scope *scope; + pool_t pool = sieve_ast_pool(ast); + + scope = sieve_variable_scope_create(pool, NULL); + + sieve_ast_extension_register(ast, &variables_ast_extension, (void *) scope); + + return scope; +} + +/* + * Validator context + */ static struct ext_variables_validator_context * ext_variables_validator_context_create(struct sieve_validator *valdtr) @@ -170,7 +224,7 @@ ext_variables_validator_context_create(struct sieve_validator *valdtr) ctx = p_new(pool, struct ext_variables_validator_context, 1); ctx->modifiers = sieve_validator_object_registry_create(valdtr); - ctx->main_scope = sieve_variable_scope_create(sieve_ast_pool(ast), NULL); + ctx->main_scope = ext_variables_create_main_scope(ast); sieve_validator_extension_set_context (valdtr, &variables_extension, (void *) ctx); diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h index e554f410e..65068725b 100644 --- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h +++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h @@ -23,6 +23,11 @@ struct sieve_variable_scope; struct sieve_variable_scope *sieve_variable_scope_create (pool_t pool, const struct sieve_extension *ext); +void sieve_variable_scope_ref + (struct sieve_variable_scope *scope); +void sieve_variable_scope_unref + (struct sieve_variable_scope **scope); + struct sieve_variable *sieve_variable_scope_declare (struct sieve_variable_scope *scope, const char *identifier); struct sieve_variable *sieve_variable_scope_import -- GitLab