/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file */ #include "lib.h" #include "sieve-common.h" #include "sieve-ast.h" #include "sieve-binary.h" #include "sieve-code.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 "testsuite-common.h" #include "testsuite-variables.h" /* * */ static const struct sieve_extension *testsuite_ext_variables = NULL; /* * */ bool testsuite_varnamespace_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 testsuite_varnamespace_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); bool testsuite_varnamespace_dump_variable (const struct sieve_dumptime_env *denv, const struct sieve_variables_namespace *nspc, const struct sieve_operand *oprnd, sieve_size_t *address); int testsuite_varnamespace_read_variable (const struct sieve_runtime_env *renv, const struct sieve_variables_namespace *nspc, const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str_r); static const struct sieve_variables_namespace_def testsuite_namespace = { SIEVE_OBJECT("tst", &testsuite_namespace_operand, 0), testsuite_varnamespace_validate, testsuite_varnamespace_generate, testsuite_varnamespace_dump_variable, testsuite_varnamespace_read_variable }; bool testsuite_varnamespace_validate (struct sieve_validator *valdtr, const struct sieve_variables_namespace *nspc ATTR_UNUSED, struct sieve_ast_argument *arg, struct sieve_command *cmd ATTR_UNUSED, ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, bool assignment) { struct sieve_ast *ast = arg->ast; const struct sieve_variable_name *name_element; const char *variable; /* Check variable name */ if ( array_count(var_name) != 2 ) { sieve_argument_validate_error(valdtr, arg, "testsuite: invalid variable name within testsuite 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, "testsuite: invalid variable name within testsuite namespace 'tst.%d': " "encountered numeric variable name", name_element->num_variable); return FALSE; } variable = str_c(name_element->identifier); if ( assignment ) { sieve_argument_validate_error(valdtr, arg, "testsuite: cannot assign to testsuite variable 'tst.%s'", variable); return FALSE; } *var_data = (void *) p_strdup(sieve_ast_pool(ast), variable); return TRUE; } bool testsuite_varnamespace_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); const char *variable = (const char *) var_data; if ( this_ext == NULL ) return FALSE; sieve_variables_opr_namespace_variable_emit (cgenv->sblock, testsuite_ext_variables, this_ext, &testsuite_namespace); sieve_binary_emit_cstring(cgenv->sblock, variable); return TRUE; } bool testsuite_varnamespace_dump_variable (const struct sieve_dumptime_env *denv, const struct sieve_variables_namespace *nspc ATTR_UNUSED, const struct sieve_operand *oprnd, sieve_size_t *address) { string_t *var_name; if ( !sieve_binary_read_string(denv->sblock, address, &var_name) ) return FALSE; if ( oprnd->field_name != NULL ) sieve_code_dumpf(denv, "%s: VAR ${tst.%s}", oprnd->field_name, str_c(var_name)); else sieve_code_dumpf(denv, "VAR ${tst.%s}", str_c(var_name)); return TRUE; } int testsuite_varnamespace_read_variable (const struct sieve_runtime_env *renv, const struct sieve_variables_namespace *nspc ATTR_UNUSED, const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str_r) { string_t *var_name; if ( !sieve_binary_read_string(renv->sblock, address, &var_name) ) { sieve_runtime_trace_operand_error(renv, oprnd, "testsuite variable operand corrupt: invalid name"); return SIEVE_EXEC_BIN_CORRUPT; } if ( str_r != NULL ) { if ( strcmp(str_c(var_name), "path") == 0 ) *str_r = t_str_new_const(testsuite_test_path, strlen(testsuite_test_path)); else *str_r = NULL; } return SIEVE_EXEC_OK; } /* * Namespace registration */ static const struct sieve_extension_objects testsuite_namespaces = SIEVE_VARIABLES_DEFINE_NAMESPACE(testsuite_namespace); const struct sieve_operand_def testsuite_namespace_operand = { .name = "testsuite-namespace", .ext_def = &testsuite_extension, .code = TESTSUITE_OPERAND_NAMESPACE, .class = &sieve_variables_namespace_operand_class, .interface = &testsuite_namespaces }; void testsuite_variables_init (const struct sieve_extension *this_ext, struct sieve_validator *valdtr) { testsuite_ext_variables = sieve_ext_variables_get_extension(this_ext->svinst); sieve_variables_namespace_register (testsuite_ext_variables, valdtr, this_ext, &testsuite_namespace); }