summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/plugins/include/ext-include-variables.c
diff options
context:
space:
mode:
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.c254
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);
+}
+
+
+