summaryrefslogtreecommitdiffstats
path: root/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c
diff options
context:
space:
mode:
Diffstat (limited to 'pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c')
-rw-r--r--pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c
new file mode 100644
index 0000000..1466ee7
--- /dev/null
+++ b/pigeonhole/src/lib-sieve/plugins/vnd.dovecot/environment/ext-vnd-environment-variables.c
@@ -0,0 +1,206 @@
+/* Copyright (c) 2015-2018 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "str.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 "ext-vnd-environment-common.h"
+
+static bool vnspc_vnd_environment_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);
+static bool vnspc_vnd_environment_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 bool vnspc_vnd_environment_dump_variable
+ (const struct sieve_dumptime_env *denv,
+ const struct sieve_variables_namespace *nspc,
+ const struct sieve_operand *oprnd, sieve_size_t *address);
+static int vnspc_vnd_environment_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
+environment_namespace = {
+ SIEVE_OBJECT("env", &environment_namespace_operand, 0),
+ .validate = vnspc_vnd_environment_validate,
+ .generate = vnspc_vnd_environment_generate,
+ .dump_variable = vnspc_vnd_environment_dump_variable,
+ .read_variable = vnspc_vnd_environment_read_variable
+};
+
+static bool vnspc_vnd_environment_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_elements;
+ unsigned int i, count;
+ const char *variable;
+ string_t *name;
+
+ /* Compose environment name from parsed variable name */
+ name = t_str_new(64);
+ name_elements = array_get(var_name, &count);
+ i_assert(count > 1);
+ for (i = 1; i < count; i++) {
+ if ( name_elements[i].num_variable >= 0 ) {
+ sieve_argument_validate_error(valdtr, arg,
+ "vnd.dovecot.environment: invalid variable name within "
+ "env namespace `env.%d': "
+ "encountered numeric variable name",
+ name_elements[i].num_variable);
+ return FALSE;
+ }
+ if (str_len(name) > 0)
+ str_append_c(name, '.');
+ str_append_str(name, name_elements[i].identifier);
+ }
+
+ variable = str_c(name);
+
+ if ( assignment ) {
+ sieve_argument_validate_error(valdtr, arg,
+ "vnd.dovecot.environment: cannot assign to environment "
+ "variable `env.%s'", variable);
+ return FALSE;
+ }
+
+ *var_data = (void *) p_strdup(sieve_ast_pool(ast), variable);
+ return TRUE;
+}
+
+static bool vnspc_vnd_environment_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;
+ struct ext_vnd_environment_context *ext_data;
+
+ if ( this_ext == NULL )
+ return FALSE;
+
+ ext_data = (struct ext_vnd_environment_context *) this_ext->context;
+
+ sieve_variables_opr_namespace_variable_emit
+ (cgenv->sblock, ext_data->var_ext, this_ext, &environment_namespace);
+ sieve_binary_emit_cstring(cgenv->sblock, variable);
+
+ return TRUE;
+}
+
+static bool vnspc_vnd_environment_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 ${env.%s}",
+ oprnd->field_name, str_c(var_name));
+ else
+ sieve_code_dumpf(denv, "VAR ${env.%s}",
+ str_c(var_name));
+
+ return TRUE;
+}
+
+static int vnspc_vnd_environment_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)
+{
+ const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc);
+ struct ext_vnd_environment_context *ectx =
+ (struct ext_vnd_environment_context *) this_ext->context;
+ string_t *var_name;
+ const char *ext_value;
+
+ if ( !sieve_binary_read_string(renv->sblock, address, &var_name) ) {
+ sieve_runtime_trace_operand_error(renv, oprnd,
+ "environment variable operand corrupt: invalid name");
+ return SIEVE_EXEC_BIN_CORRUPT;
+ }
+
+ if ( str_r != NULL ) {
+ const char *vname = str_c(var_name);
+
+ ext_value = ext_environment_item_get_value
+ (ectx->env_ext, renv, vname);
+
+ if ( ext_value == NULL && strchr(vname, '_') != NULL) {
+ char *p, *aname;
+
+ /* Try again with '_' replaced with '-' */
+ aname = t_strdup_noconst(vname);
+ for (p = aname; *p != '\0'; p++) {
+ if (*p == '_')
+ *p = '-';
+ }
+ ext_value = ext_environment_item_get_value
+ (ectx->env_ext, renv, aname);
+ }
+
+ if ( ext_value == NULL ) {
+ *str_r = t_str_new_const("", 0);
+ return SIEVE_EXEC_OK;
+ }
+
+ *str_r = t_str_new_const(ext_value, strlen(ext_value));
+ }
+ return SIEVE_EXEC_OK;
+}
+
+/*
+ * Namespace registration
+ */
+
+static const struct sieve_extension_objects environment_namespaces =
+ SIEVE_VARIABLES_DEFINE_NAMESPACE(environment_namespace);
+
+const struct sieve_operand_def environment_namespace_operand = {
+ .name = "env-namespace",
+ .ext_def = &vnd_environment_extension,
+ .class = &sieve_variables_namespace_operand_class,
+ .interface = &environment_namespaces
+};
+
+void ext_environment_variables_init
+(const struct sieve_extension *this_ext, struct sieve_validator *valdtr)
+{
+ struct ext_vnd_environment_context *ext_data =
+ (struct ext_vnd_environment_context *) this_ext->context;
+
+ sieve_variables_namespace_register
+ (ext_data->var_ext, valdtr, this_ext, &environment_namespace);
+}