diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c | |
parent | Initial commit. (diff) | |
download | dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c')
-rw-r--r-- | pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c new file mode 100644 index 0000000..28cd803 --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c @@ -0,0 +1,254 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-script.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "ext-include-common.h" +#include "ext-include-binary.h" +#include "ext-include-variables.h" + +/* + * Variable import-export + */ + +struct sieve_variable *ext_include_variable_import_global +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *variable) +{ + const struct sieve_extension *this_ext = cmd->ext; + struct sieve_ast *ast = cmd->ast_node->ast; + struct ext_include_ast_context *ctx = + ext_include_get_ast_context(this_ext, ast); + struct ext_include_context *ectx = ext_include_get_context(this_ext); + struct sieve_variable_scope *local_scope; + struct sieve_variable_scope *global_scope = ctx->global_vars; + struct sieve_variable *global_var = NULL, *local_var; + + /* Sanity safeguard */ + i_assert ( ctx->global_vars != NULL ); + + if ( !sieve_variable_identifier_is_valid(variable) ) { + sieve_command_validate_error(valdtr, cmd, + "invalid variable identifier '%s'", str_sanitize(variable,80)); + return NULL; + } + + /* Get/Declare the variable in the global scope */ + global_var = sieve_variable_scope_declare(global_scope, variable); + + /* Check whether scope is over its size limit */ + if ( global_var == NULL ) { + sieve_command_validate_error(valdtr, cmd, + "declaration of new global variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(ectx->var_ext)); + return NULL; + } + + /* Import the global variable into the local script scope */ + local_scope = sieve_ext_variables_get_local_scope(ectx->var_ext, valdtr); + + local_var = sieve_variable_scope_get_variable(local_scope, variable); + if ( local_var != NULL && local_var->ext != this_ext ) { + /* FIXME: indicate location of conflicting set statement */ + sieve_command_validate_error(valdtr, cmd, + "declaration of new global variable '%s' conflicts with earlier local " + "use", variable); + return NULL; + } + + return sieve_variable_scope_import(local_scope, global_var); +} + +/* + * Binary symbol table + */ + +bool ext_include_variables_save +(struct sieve_binary_block *sblock, + struct sieve_variable_scope_binary *global_vars, + enum sieve_error *error_r ATTR_UNUSED) +{ + struct sieve_variable_scope *global_scope = + sieve_variable_scope_binary_get(global_vars); + unsigned int count = sieve_variable_scope_size(global_scope); + sieve_size_t jump; + + sieve_binary_emit_unsigned(sblock, count); + + jump = sieve_binary_emit_offset(sblock, 0); + + if ( count > 0 ) { + unsigned int size, i; + struct sieve_variable *const *vars = + sieve_variable_scope_get_variables(global_scope, &size); + + for ( i = 0; i < size; i++ ) { + sieve_binary_emit_cstring(sblock, vars[i]->identifier); + } + } + + sieve_binary_resolve_offset(sblock, jump); + + return TRUE; +} + +bool ext_include_variables_load +(const struct sieve_extension *this_ext, struct sieve_binary_block *sblock, + sieve_size_t *offset, struct sieve_variable_scope_binary **global_vars_r) +{ + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + + /* Sanity assert */ + i_assert( *global_vars_r == NULL ); + + *global_vars_r = sieve_variable_scope_binary_read + (this_ext->svinst, ectx->var_ext, this_ext, sblock, offset); + + return ( *global_vars_r != NULL ); +} + +bool ext_include_variables_dump +(struct sieve_dumptime_env *denv, + struct sieve_variable_scope_binary *global_vars) +{ + struct sieve_variable_scope *global_scope = + sieve_variable_scope_binary_get(global_vars); + unsigned int size; + struct sieve_variable *const *vars; + + i_assert(global_scope != NULL); + + vars = sieve_variable_scope_get_variables(global_scope, &size); + + if ( size > 0 ) { + unsigned int i; + + sieve_binary_dump_sectionf(denv, "Global variables"); + + for ( i = 0; i < size; i++ ) { + sieve_binary_dumpf(denv, "%3d: '%s' \n", i, vars[i]->identifier); + } + } + + return TRUE; +} + +/* + * Global variables namespace + */ + +bool vnspc_global_variables_validate + (struct sieve_validator *valdtr, const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); +bool vnspc_global_variables_generate + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, void *var_data); + +static const struct sieve_variables_namespace_def +global_variables_namespace = { + SIEVE_OBJECT("global", NULL, 0), + .validate = vnspc_global_variables_validate, + .generate = vnspc_global_variables_generate +}; + +bool vnspc_global_variables_validate +(struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment ATTR_UNUSED) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct sieve_ast *ast = arg->ast; + struct ext_include_context *ectx = + ext_include_get_context(this_ext); + struct ext_include_ast_context *ctx = + ext_include_get_ast_context(this_ext, ast); + struct sieve_variable *var = NULL; + const struct sieve_variable_name *name_element; + const char *variable; + + /* Sanity safeguard */ + i_assert ( ctx->global_vars != NULL ); + + /* Check variable name */ + + if ( array_count(var_name) != 2 ) { + sieve_argument_validate_error(valdtr, arg, + "invalid variable name within global namespace: " + "encountered sub-namespace"); + return FALSE; + } + + name_element = array_idx(var_name, 1); + if ( name_element->num_variable >= 0 ) { + sieve_argument_validate_error(valdtr, arg, + "invalid variable name within global namespace: " + "encountered numeric variable name"); + return FALSE; + } + + variable = str_c(name_element->identifier); + + /* Get/Declare the variable in the global scope */ + + var = sieve_variable_scope_declare(ctx->global_vars, variable); + + if ( var == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "(implicit) declaration of new global variable '%s' exceeds the limit " + "(max variables: %u)", variable, + sieve_variables_get_max_scope_size(ectx->var_ext)); + return FALSE; + } + + *var_data = (void *) var; + + return TRUE; +} + +bool vnspc_global_variables_generate +(const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED, void *var_data) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + struct ext_include_context *ectx = ext_include_get_context(this_ext); + struct sieve_variable *var = (struct sieve_variable *) var_data; + + sieve_variables_opr_variable_emit(cgenv->sblock, ectx->var_ext, var); + + return TRUE; +} + +void ext_include_variables_global_namespace_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + struct ext_include_context *ectx = ext_include_get_context(this_ext); + + sieve_variables_namespace_register + (ectx->var_ext, valdtr, this_ext, &global_variables_namespace); +} + + + |