From 792852f326cc876a8d6477f52eb74db70189b6a1 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sun, 10 Feb 2008 16:41:20 +0100 Subject: [PATCH] Added code support for set modifiers. --- src/lib-sieve/plugins/variables/cmd-set.c | 230 ++++++++++++++++-- .../plugins/variables/ext-variables-common.c | 23 +- .../plugins/variables/ext-variables-common.h | 8 + .../plugins/variables/ext-variables.c | 27 +- .../plugins/variables/sieve-ext-variables.h | 18 ++ 5 files changed, 273 insertions(+), 33 deletions(-) diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c index f3ae9e567..a5d8ac503 100644 --- a/src/lib-sieve/plugins/variables/cmd-set.c +++ b/src/lib-sieve/plugins/variables/cmd-set.c @@ -1,10 +1,15 @@ #include "lib.h" +#include "str.h" +#include "array.h" #include "sieve-common.h" +#include "sieve-extensions-private.h" #include "sieve-code.h" #include "sieve-ast.h" #include "sieve-commands.h" +#include "sieve-binary.h" + #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" @@ -12,6 +17,8 @@ #include "ext-variables-common.h" +#include <ctype.h> + /* Forward declarations */ static bool cmd_set_operation_dump @@ -23,6 +30,8 @@ static bool cmd_set_operation_execute static bool cmd_set_registered (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg); +static bool cmd_set_pre_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd); static bool cmd_set_validate (struct sieve_validator *validator, struct sieve_command_context *cmd); static bool cmd_set_generate @@ -38,7 +47,7 @@ const struct sieve_command cmd_set = { SCT_COMMAND, 2, 0, FALSE, FALSE, cmd_set_registered, - NULL, + cmd_set_pre_validate, cmd_set_validate, cmd_set_generate, NULL @@ -53,6 +62,12 @@ const struct sieve_operation cmd_set_operation = { cmd_set_operation_execute }; +/* Compiler context */ +struct cmd_set_context { + ARRAY_DEFINE(modifiers, struct ext_variables_set_modifier *); + +}; + /* Tag validation */ /* [MODIFIER]: @@ -63,28 +78,28 @@ const struct sieve_operation cmd_set_operation = { */ static bool tag_modifier_is_instance_of -(struct sieve_validator *validator, +(struct sieve_validator *validator ATTR_UNUSED, struct sieve_command_context *cmdctx ATTR_UNUSED, struct sieve_ast_argument *arg) { - return ext_variables_set_modifier_find - (validator, sieve_ast_argument_tag(arg)) != NULL; + arg->context = (void *) ext_variables_set_modifier_find + (validator, sieve_ast_argument_tag(arg)); + + return arg->context != NULL; } static bool tag_modifier_validate (struct sieve_validator *validator, struct sieve_ast_argument **arg, struct sieve_command_context *cmd) { - /* Skip parameter */ - *arg = sieve_ast_argument_next(*arg); + struct ext_variables_set_modifier *smodf = (*arg)->context; + struct cmd_set_context *sctx = (struct cmd_set_context *) cmd->data; + + array_append(&sctx->modifiers, &smodf, 1); + + /* Added to modifier list; self-destruct to prevent duplicate generation */ + *arg = sieve_ast_arguments_detach(*arg, 1); - return TRUE; -} - -static bool tag_modifier_generate -(struct sieve_generator *generator, struct sieve_ast_argument *arg, - struct sieve_command_context *cmd ATTR_UNUSED) -{ return TRUE; } @@ -92,48 +107,74 @@ const struct sieve_argument modifier_tag = { "MODIFIER", tag_modifier_is_instance_of, tag_modifier_validate, - NULL, - tag_modifier_generate + NULL, NULL }; /* Pre-defined modifiers */ +bool mod_upperfirst_modify(string_t *in, string_t *result); +bool mod_lowerfirst_modify(string_t *in, string_t *result); +bool mod_upper_modify(string_t *in, string_t *result); +bool mod_lower_modify(string_t *in, string_t *result); + const struct ext_variables_set_modifier lower_modifier = { "lower", EXT_VARIABLES_SET_MODIFIER_LOWER, - 40 + 40, + NULL }; const struct ext_variables_set_modifier upper_modifier = { "upper", EXT_VARIABLES_SET_MODIFIER_UPPER, - 40 + 40, + NULL }; const struct ext_variables_set_modifier lowerfirst_modifier = { "lowerfirst", EXT_VARIABLES_SET_MODIFIER_LOWERFIRST, - 30 + 30, + NULL }; const struct ext_variables_set_modifier upperfirst_modifier = { "upperfirst", EXT_VARIABLES_SET_MODIFIER_UPPERFIRST, - 30 + 30, + NULL }; const struct ext_variables_set_modifier quotewildcard_modifier = { "quotewildcard", EXT_VARIABLES_SET_MODIFIER_QUOTEWILDCARD, - 20 + 20, + NULL }; const struct ext_variables_set_modifier length_modifier = { "length", EXT_VARIABLES_SET_MODIFIER_LENGTH, - 10 + 10, + NULL +}; + +const struct ext_variables_set_modifier *core_modifiers[] = { + &lower_modifier, + &upper_modifier, + &lowerfirst_modifier, + &upperfirst_modifier, + "ewildcard_modifier, + &length_modifier }; +static struct sieve_extension_obj_registry setmodf_default_reg = + SIEVE_EXT_DEFINE_SET_MODIFIERS(core_modifiers); + +/* Modifier read */ + + + /* Command registration */ static bool cmd_set_registered @@ -146,11 +187,24 @@ static bool cmd_set_registered /* Command validation */ +static bool cmd_set_pre_validate + (struct sieve_validator *validator, struct sieve_command_context *cmd) +{ + pool_t pool = sieve_command_pool(cmd); + struct cmd_set_context *sctx = p_new(pool, struct cmd_set_context, 1); + + p_array_init(&sctx->modifiers, pool, 2); + + cmd->data = (void *) sctx; + + return TRUE; +} + static bool cmd_set_validate(struct sieve_validator *validator, struct sieve_command_context *cmd) -{ +{ struct sieve_ast_argument *arg = cmd->first_positional; - + if ( !sieve_validate_positional_argument (validator, cmd, arg, "name", 1, SAAT_STRING) ) { return FALSE; @@ -175,9 +229,22 @@ static bool cmd_set_validate(struct sieve_validator *validator, static bool cmd_set_generate (struct sieve_generator *generator, struct sieve_command_context *ctx) { + struct sieve_binary *sbin = sieve_generator_get_binary(generator); + struct cmd_set_context *sctx = (struct cmd_set_context *) ctx->data; + unsigned int i; + sieve_generator_emit_operation_ext (generator, &cmd_set_operation, ext_variables_my_id); + /* Generate modifiers */ + sieve_binary_emit_byte(sbin, array_count(&sctx->modifiers)); + for ( i = 0; i < array_count(&sctx->modifiers); i++ ) { + struct ext_variables_set_modifier * const * smodf = + array_idx(&sctx->modifiers, i); + + sieve_binary_emit_byte(sbin, (*smodf)->code); + } + /* Generate arguments */ if ( !sieve_generate_arguments(generator, ctx, NULL) ) return FALSE; @@ -185,6 +252,34 @@ static bool cmd_set_generate return TRUE; } +/* + * Modifier access + */ + +static const struct sieve_extension_obj_registry * + cmd_set_modifier_registry_get +(struct sieve_binary *sbin, unsigned int ext_index) +{ + int ext_id = -1; + const struct sieve_variables_extension *ext; + + if ( sieve_binary_extension_get_by_index(sbin, ext_index, &ext_id) == NULL ) + return NULL; + + if ( (ext=sieve_variables_extension_get(sbin, ext_id)) == NULL ) + return NULL; + + return &(ext->set_modifiers); +} + +static const struct ext_variables_set_modifier *cmd_set_modifier_read + (struct sieve_binary *sbin, sieve_size_t *address) +{ + return sieve_extension_read_obj + (struct ext_variables_set_modifier, sbin, address, &setmodf_default_reg, + cmd_set_modifier_registry_get); +} + /* * Code dump */ @@ -193,9 +288,24 @@ static bool cmd_set_operation_dump (const struct sieve_operation *op ATTR_UNUSED, const struct sieve_dumptime_env *denv, sieve_size_t *address) { + unsigned int mdfs, i; + sieve_code_dumpf(denv, "SET"); sieve_code_descend(denv); - + + if ( !sieve_binary_read_byte(denv->sbin, address, &mdfs) ) + return FALSE; + + for ( i = 0; i < mdfs; i++ ) { + const struct ext_variables_set_modifier *modf = + cmd_set_modifier_read(denv->sbin, address); + + if ( modf == NULL ) + return FALSE; + + sieve_code_dumpf(denv, "MOD: %s", modf->identifier); + } + return sieve_opr_string_dump(denv, address) && sieve_opr_string_dump(denv, address); @@ -210,13 +320,24 @@ static bool cmd_set_operation_execute const struct sieve_runtime_env *renv, sieve_size_t *address) { struct sieve_variable_storage *storage; - unsigned int var_index; + unsigned int var_index, mdfs, i; string_t *value; printf(">> SET\n"); - if ( !ext_variables_opr_variable_read(renv, address, &storage, &var_index) ) + if ( !sieve_binary_read_byte(renv->sbin, address, &mdfs) ) return FALSE; + + for ( i = 0; i < mdfs; i++ ) { + const struct ext_variables_set_modifier *modf = + cmd_set_modifier_read(renv->sbin, address); + + if ( modf == NULL ) + return FALSE; + } + + if ( !ext_variables_opr_variable_read(renv, address, &storage, &var_index) ) + return FALSE; if ( !sieve_opr_string_read(renv, address, &value) ) return FALSE; @@ -226,7 +347,64 @@ static bool cmd_set_operation_execute return TRUE; } +/* Pre-defined modifier implementation */ + +bool mod_upperfirst_modify(string_t *in, string_t *result) +{ + char *content; + + if ( in != NULL ) + str_append_str(result, in); + + content = str_c_modifiable(result); + content[0] = toupper(content[0]); + + return TRUE; +} + +bool mod_lowerfirst_modify(string_t *in, string_t *result) +{ + char *content; + + if ( in != NULL ) + str_append_str(result, in); + + content = str_c_modifiable(result); + content[0] = tolower(content[0]); + + return TRUE; +} +bool mod_upper_modify(string_t *in, string_t *result) +{ + unsigned int i; + char *content; + + if ( in != NULL ) + str_append_str(result, in); + + content = str_c_modifiable(result); + for ( i = 0; i < str_len(result); i++ ) { + content[i] = toupper(content[i]); + } + + return TRUE; +} +bool mod_lower_modify(string_t *in, string_t *result) +{ + unsigned int i; + char *content; + + if ( in != NULL ) + str_append_str(result, in); + + content = str_c_modifiable(result); + for ( i = 0; i < str_len(result); i++ ) { + content[i] = toupper(content[i]); + } + + return TRUE; +} diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c index ba39f72a4..99f27becc 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-common.c +++ b/src/lib-sieve/plugins/variables/ext-variables-common.c @@ -3,9 +3,11 @@ #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" @@ -32,6 +34,25 @@ const struct ext_variables_set_modifier *default_set_modifiers[] = { const unsigned int default_set_modifiers_count = N_ELEMENTS(default_set_modifiers); + +/* + * Binary context + */ + +const struct sieve_variables_extension * + sieve_variables_extension_get(struct sieve_binary *sbin, int ext_id) +{ + return (const struct sieve_variables_extension *) + sieve_binary_registry_get_object(sbin, ext_variables_my_id, ext_id); +} + +void sieve_variables_extension_set + (struct sieve_binary *sbin, int ext_id, + const struct sieve_variables_extension *ext) +{ + sieve_binary_registry_set_object + (sbin, ext_variables_my_id, ext_id, (const void *) ext); +} /* Variable scope */ @@ -515,7 +536,7 @@ static bool opr_variable_dump sieve_size_t index = 0; if (sieve_binary_read_integer(denv->sbin, address, &index) ) { - sieve_code_dumpf(denv, "VARIABLE: %ld [?]", (long) index); + sieve_code_dumpf(denv, "VAR: %ld", (long) index); return TRUE; } diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h index 7e9db1f19..aac6dcacf 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-common.h +++ b/src/lib-sieve/plugins/variables/ext-variables-common.h @@ -40,11 +40,15 @@ struct ext_variables_set_modifier { int code; unsigned int precedence; + + bool (*modify)(string_t *in, string_t *result); }; const struct ext_variables_set_modifier *ext_variables_set_modifier_find (struct sieve_validator *validator, const char *identifier); +extern const struct ext_variables_set_modifier *core_modifiers[]; + /* Arguments */ extern const struct sieve_argument variable_string_argument; @@ -68,6 +72,10 @@ struct sieve_variable *ext_variables_validator_get_variable struct sieve_variable_storage *ext_variables_interpreter_get_storage (struct sieve_interpreter *interp); + +/* Extensions */ +const struct sieve_variables_extension * + sieve_variables_extension_get(struct sieve_binary *sbin, int ext_id); #endif /* __EXT_VARIABLES_COMMON_H */ diff --git a/src/lib-sieve/plugins/variables/ext-variables.c b/src/lib-sieve/plugins/variables/ext-variables.c index 0b3828892..bb3e793d8 100644 --- a/src/lib-sieve/plugins/variables/ext-variables.c +++ b/src/lib-sieve/plugins/variables/ext-variables.c @@ -3,7 +3,7 @@ * * Authors: Stephan Bosch * Specification: draft-ietf-sieve-variables-08.txt - * Implementation: skeleton + * Implementation: basic variables support * Status: under development * */ @@ -14,6 +14,8 @@ #include "sieve-extensions.h" #include "sieve-commands.h" +#include "sieve-binary.h" + #include "sieve-validator.h" #include "ext-variables-common.h" @@ -24,6 +26,7 @@ static bool ext_variables_load(int ext_id); static bool ext_variables_validator_load(struct sieve_validator *validator); +static bool ext_variables_binary_load(struct sieve_binary *sbin); static bool ext_variables_interpreter_load(struct sieve_interpreter *interp); /* Commands */ @@ -37,7 +40,8 @@ extern const struct sieve_operation cmd_set_operation; extern const struct sieve_operation tst_string_operation; const struct sieve_operation *ext_variables_operations[] = { - &cmd_set_operation, &tst_string_operation + &cmd_set_operation, + &tst_string_operation }; /* Operands */ @@ -45,11 +49,11 @@ const struct sieve_operation *ext_variables_operations[] = { extern const struct sieve_operand variable_operand; extern const struct sieve_operand variable_string_operand; -const struct sieve_operation *ext_variables_operands[] = { - &variable_operand, &variable_string_operand +const struct sieve_operand *ext_variables_operands[] = { + &variable_operand, + &variable_string_operand }; - /* Extension definitions */ int ext_variables_my_id; @@ -58,7 +62,8 @@ struct sieve_extension variables_extension = { "variables", ext_variables_load, ext_variables_validator_load, - NULL, NULL, + NULL, + ext_variables_binary_load, ext_variables_interpreter_load, SIEVE_EXT_DEFINE_OPERATIONS(ext_variables_operations), SIEVE_EXT_DEFINE_OPERANDS(ext_variables_operands) @@ -86,6 +91,16 @@ static bool ext_variables_validator_load return TRUE; } +/* Load extension intro binary */ + +static bool ext_variables_binary_load + (struct sieve_binary *sbin) +{ + sieve_binary_registry_init(sbin, ext_variables_my_id); + + return TRUE; +} + /* Load extension into interpreter */ static bool ext_variables_interpreter_load diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h index db9903c1a..db95aed75 100644 --- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h +++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h @@ -1,6 +1,9 @@ #ifndef __SIEVE_EXT_VARIABLES_H #define __SIEVE_EXT_VARIABLES_H +#include "sieve-common.h" +#include "sieve-extensions.h" + /* Public interface for other extensions to use */ struct sieve_variable { @@ -24,4 +27,19 @@ void sieve_variable_assign (struct sieve_variable_storage *storage, unsigned int index, const string_t *value); +/* Extensions */ + +struct sieve_variables_extension { + const struct sieve_extension *extension; + + struct sieve_extension_obj_registry set_modifiers; +}; + +#define SIEVE_EXT_DEFINE_SET_MODIFIER(OP) SIEVE_EXT_DEFINE_OBJECT(OP) +#define SIEVE_EXT_DEFINE_SET_MODIFIERS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) + +void sieve_variables_extension_set + (struct sieve_binary *sbin, int ext_id, + const struct sieve_variables_extension *ext); + #endif /* __SIEVE_EXT_VARIABLES_H */ -- GitLab