diff --git a/README b/README index 605c65ed5e16eec2b44ebe3ebaddd0d7b97eab23..cb5c197d039c677d5101f755db43d839038df4fc 100644 --- a/README +++ b/README @@ -73,6 +73,8 @@ TODO ---- * Implement match-type execution +* Resolve code duplication amongst comparator, address-part and match-type + support as much as possible. * Produce a fully working interpreter that actually executes actions, currently tests are evaluated and actions just print their occurence. * Give the binary format some more thought, it is currently quite rough and diff --git a/sieve/tests/match-type.sieve b/sieve/tests/match-type.sieve new file mode 100644 index 0000000000000000000000000000000000000000..10e9e659e58e0b02a5fe5e00729faf957fd50d5c --- /dev/null +++ b/sieve/tests/match-type.sieve @@ -0,0 +1,10 @@ +if address :is :comparator "i;octet" :domain "from" "STEPHAN" { + discard; + + if address :contains :domain :comparator "i;octet" "from" "drunksnipers.com" { + keep; + } + stop; +} + +keep; diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am index 7cac3ae3db0c4e446c99d62a5e271699ac145ab3..d9b22f56af0f4ccab6af03cdb771e955f2ee4e55 100644 --- a/src/lib-sieve/Makefile.am +++ b/src/lib-sieve/Makefile.am @@ -38,6 +38,7 @@ libsieve_a_SOURCES = \ sieve-result.c \ sieve-error.c \ sieve-comparators.c \ + sieve-match-types.c \ sieve-address-parts.c \ sieve-commands.c \ sieve-code.c \ @@ -58,6 +59,7 @@ noinst_HEADERS = \ sieve-result.h sieve-error.h \ sieve-comparators.h \ + sieve-match-types.h \ sieve-address-parts.h \ sieve-commands.h \ sieve-code.h \ diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index 82ca3a89ba5feb2fb490e928e6011a2cf26a8f21..12bcae1bae9122df779e76d815479ada1e6ff68a 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -3,6 +3,7 @@ #include "sieve-extensions.h" #include "sieve-commands.h" #include "sieve-comparators.h" +#include "sieve-match-types.h" #include "sieve-address-parts.h" #include "sieve-validator.h" @@ -65,7 +66,7 @@ static bool tst_envelope_registered(struct sieve_validator *validator, struct si /* The order of these is not significant */ sieve_comparators_link_tag(validator, cmd_reg, OPT_COMPARATOR); sieve_address_parts_link_tags(validator, cmd_reg, OPT_ADDRESS_PART); - sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE); + sieve_match_types_link_tags(validator, cmd_reg, OPT_MATCH_TYPE); return TRUE; } @@ -152,6 +153,7 @@ static bool ext_envelope_opcode_dump sieve_opr_comparator_dump(interp, sbin, address); break; case OPT_MATCH_TYPE: + sieve_opr_match_type_dump(interp, sbin, address); break; case OPT_ADDRESS_PART: sieve_opr_address_part_dump(interp, sbin, address); diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c index 2d0fe667fe81c4f233ea8835d70ce2aacdf1ecf9..9dde6c69fa46373276daf0c401d80c38ed290b5e 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -339,7 +339,7 @@ bool sieve_opr_address_part_dump if ( addrp == NULL ) return FALSE; - printf("%08x: ADDRP: %s\n", pc, addrp->identifier); + printf("%08x: ADDRESS-PART: %s\n", pc, addrp->identifier); return TRUE; } diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index af601d01a9091e13b9fb5d832087c61f2777e508..8764bba6f9ecbec46c341798cf37506dce0adecb 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -219,6 +219,7 @@ const struct sieve_operand stringlist_operand = /* Core operands */ extern struct sieve_operand comparator_operand; +extern struct sieve_operand match_type_operand; extern struct sieve_operand address_part_operand; const struct sieve_operand *sieve_operands[] = { @@ -227,7 +228,7 @@ const struct sieve_operand *sieve_operands[] = { &string_operand, &stringlist_operand, &comparator_operand, - NULL, + &match_type_operand, &address_part_operand }; diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c index c153243f29d604fb77be6f730f11177113220353..be3f751e309aa2782ce10648f7c6c9eea948bcc1 100644 --- a/src/lib-sieve/sieve-comparators.c +++ b/src/lib-sieve/sieve-comparators.c @@ -119,7 +119,7 @@ const struct sieve_comparator *sieve_comparator_find if ( ext_id != NULL ) *ext_id = reg->ext_id; - return reg->address_part; + return reg->comparator; } bool cmp_validator_load(struct sieve_validator *validator) @@ -347,7 +347,7 @@ bool sieve_opr_comparator_dump if ( cmp == NULL ) return FALSE; - printf("%08x: CMP: %s\n", pc, cmp->identifier); + printf("%08x: COMPARATOR: %s\n", pc, cmp->identifier); return TRUE; } diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index 40491cbc77f3922da1c97ddad593a5c95bddc7d8..4f4638a75176880d635d43839d552d20350ef68f 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -10,11 +10,19 @@ static void sieve_extensions_init_registry(void); static void sieve_extensions_deinit_registry(void); -/* Core extensions */ +/* Pre-loaded extensions */ extern const struct sieve_extension comparator_extension; +extern const struct sieve_extension match_type_extension; extern const struct sieve_extension address_part_extension; +const struct sieve_extension *sieve_preloaded_extensions[] = { + &comparator_extension, &match_type_extension, &address_part_extension +}; + +const unsigned int sieve_preloaded_extensions_count = + N_ELEMENTS(sieve_preloaded_extensions); + /* Dummy extensions */ static const struct sieve_extension comparator_i_octet_extension = { @@ -40,7 +48,7 @@ extern const struct sieve_extension subaddress_extension; extern const struct sieve_extension comparator_i_ascii_numeric_extension; const struct sieve_extension *sieve_core_extensions[] = { - &comparator_extension, &address_part_extension, + &comparator_extension, &match_type_extension, &address_part_extension, &comparator_i_octet_extension, &comparator_i_ascii_casemap_extension, &fileinto_extension, &reject_extension, &envelope_extension, diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h index 9334747ed625c2e3140d0e1221a3b5075b3a6abb..cd4e155a542e4342ec3a5daee60b3e22aad9ac17 100644 --- a/src/lib-sieve/sieve-extensions.h +++ b/src/lib-sieve/sieve-extensions.h @@ -17,6 +17,9 @@ struct sieve_extension { const struct sieve_operand *operand; }; +extern const struct sieve_extension *sieve_preloaded_extensions[]; +extern const unsigned int sieve_preloaded_extensions_count; + const struct sieve_extension *sieve_extension_acquire(const char *extension); /* Extensions state */ diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index 68035454f7c340ecc17ff6b3924849a1e577fdc5..6a5d4b8a5c076c4e362ef4ad6961820b8e1c76d5 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -33,12 +33,10 @@ struct sieve_interpreter { struct mail *mail; }; -extern struct sieve_extension comparator_extension; -extern struct sieve_extension address_part_extension; - struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary) { - int i; + unsigned int i; + int idx; pool_t pool; struct sieve_interpreter *interp; @@ -53,15 +51,19 @@ struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary) interp->pc = 0; p_array_init(&interp->ext_contexts, pool, 4); - //array_create(&interp->ext_contexts, pool, sizeof(void *), - // sieve_extensions_get_count()); - - (void)comparator_extension.interpreter_load(interp); - (void)address_part_extension.interpreter_load(interp); - for ( i = 0; i < sieve_binary_extensions_count(binary); i++ ) { + /* Pre-load core language features implemented as 'extensions' */ + for ( i = 0; i < sieve_preloaded_extensions_count; i++ ) { + const struct sieve_extension *ext = sieve_preloaded_extensions[i]; + + if ( ext->interpreter_load != NULL ) + (void)ext->interpreter_load(interp); + } + + /* Load other extensions listed in the binary */ + for ( idx = 0; idx < sieve_binary_extensions_count(binary); idx++ ) { const struct sieve_extension *ext = - sieve_binary_extension_get_by_index(binary, i, NULL); + sieve_binary_extension_get_by_index(binary, idx, NULL); if ( ext->interpreter_load != NULL ) ext->interpreter_load(interp); diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c new file mode 100644 index 0000000000000000000000000000000000000000..48e16c3ca421a90f86c2339b36acc29b86d44bfa --- /dev/null +++ b/src/lib-sieve/sieve-match-types.c @@ -0,0 +1,412 @@ +#include <stdio.h> + +#include "lib.h" +#include "compat.h" +#include "mempool.h" +#include "hash.h" +#include "array.h" + +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-binary.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "sieve-match-types.h" + +#include <string.h> + +/* + * Predeclarations + */ + +static void opr_match_type_emit + (struct sieve_binary *sbin, struct sieve_match_type *addrp); +static void opr_match_type_emit_ext + (struct sieve_binary *sbin, struct sieve_match_type *addrp, int ext_id); + +/* + * Address-part 'extension' + */ + +static int ext_my_id = -1; + +static bool mtch_extension_load(int ext_id); +static bool mtch_validator_load(struct sieve_validator *validator); +static bool mtch_interpreter_load(struct sieve_interpreter *interp); + +const struct sieve_extension match_type_extension = { + "@match-type", + mtch_extension_load, + mtch_validator_load, + NULL, + mtch_interpreter_load, + NULL, + NULL +}; + +static bool mtch_extension_load(int ext_id) +{ + ext_my_id = ext_id; + return TRUE; +} + +/* + * Validator context: + * name-based match-type registry. + * + * FIXME: This code will be duplicated across all extensions that introduce + * a registry of some kind in the validator. + */ + +struct mtch_validator_registration { + int ext_id; + const struct sieve_match_type *match_type; +}; + +struct mtch_validator_context { + struct hash_table *registrations; +}; + +static inline struct mtch_validator_context * + get_validator_context(struct sieve_validator *validator) +{ + return (struct mtch_validator_context *) + sieve_validator_extension_get_context(validator, ext_my_id); +} + +static void _sieve_match_type_register + (pool_t pool, struct mtch_validator_context *ctx, + const struct sieve_match_type *addrp, int ext_id) +{ + struct mtch_validator_registration *reg; + + reg = p_new(pool, struct mtch_validator_registration, 1); + reg->match_type = addrp; + reg->ext_id = ext_id; + + hash_insert(ctx->registrations, (void *) addrp->identifier, (void *) reg); +} + +void sieve_match_type_register + (struct sieve_validator *validator, + const struct sieve_match_type *addrp, int ext_id) +{ + pool_t pool = sieve_validator_pool(validator); + struct mtch_validator_context *ctx = get_validator_context(validator); + + _sieve_match_type_register(pool, ctx, addrp, ext_id); +} + +const struct sieve_match_type *sieve_match_type_find + (struct sieve_validator *validator, const char *identifier, + int *ext_id) +{ + struct mtch_validator_context *ctx = get_validator_context(validator); + struct mtch_validator_registration *reg = + (struct mtch_validator_registration *) + hash_lookup(ctx->registrations, identifier); + + if ( reg == NULL ) return NULL; + + if ( ext_id != NULL ) *ext_id = reg->ext_id; + + return reg->match_type; +} + +bool mtch_validator_load(struct sieve_validator *validator) +{ + unsigned int i; + pool_t pool = sieve_validator_pool(validator); + + struct mtch_validator_context *ctx = + p_new(pool, struct mtch_validator_context, 1); + + /* Setup match-type registry */ + ctx->registrations = hash_create + (pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); + + /* Register core match-types */ + for ( i = 0; i < sieve_core_match_types_count; i++ ) { + const struct sieve_match_type *addrp = sieve_core_match_types[i]; + + _sieve_match_type_register(pool, ctx, addrp, -1); + } + + sieve_validator_extension_set_context(validator, ext_my_id, ctx); + + return TRUE; +} + +void sieve_match_types_link_tags + (struct sieve_validator *validator, + struct sieve_command_registration *cmd_reg, unsigned int id_code) +{ + sieve_validator_register_tag + (validator, cmd_reg, &match_type_tag, id_code); +} + +/* + * Interpreter context: + * + * FIXME: This code will be duplicated across all extensions that introduce + * a registry of some kind in the interpreter. + */ + +struct mtch_interpreter_context { + ARRAY_DEFINE(mtch_extensions, + const struct sieve_match_type_extension *); +}; + +static inline struct mtch_interpreter_context * + get_interpreter_context(struct sieve_interpreter *interpreter) +{ + return (struct mtch_interpreter_context *) + sieve_interpreter_extension_get_context(interpreter, ext_my_id); +} + +static const struct sieve_match_type_extension *sieve_match_type_extension_get + (struct sieve_interpreter *interpreter, int ext_id) +{ + struct mtch_interpreter_context *ctx = get_interpreter_context(interpreter); + + if ( (ctx != NULL) && (ext_id > 0) && (ext_id < (int) array_count(&ctx->mtch_extensions)) ) { + const struct sieve_match_type_extension * const *ext; + + ext = array_idx(&ctx->mtch_extensions, (unsigned int) ext_id); + + return *ext; + } + + return NULL; +} + +void sieve_match_type_extension_set + (struct sieve_interpreter *interpreter, int ext_id, + const struct sieve_match_type_extension *ext) +{ + struct mtch_interpreter_context *ctx = get_interpreter_context(interpreter); + + array_idx_set(&ctx->mtch_extensions, (unsigned int) ext_id, &ext); +} + +static bool mtch_interpreter_load(struct sieve_interpreter *interpreter) +{ + pool_t pool = sieve_interpreter_pool(interpreter); + + struct mtch_interpreter_context *ctx = + p_new(pool, struct mtch_interpreter_context, 1); + + /* Setup comparator registry */ + p_array_init(&ctx->mtch_extensions, pool, 4); + + sieve_interpreter_extension_set_context(interpreter, ext_my_id, ctx); + + return TRUE; +} + +/* + * Address-part operand + */ + +struct sieve_operand_class match_type_class = + { "match-type", NULL }; +struct sieve_operand match_type_operand = + { "match-type", &match_type_class, FALSE }; + +/* + * Address-part tag + */ + +static bool tag_match_type_is_instance_of + (struct sieve_validator *validator, const char *tag) +{ + return sieve_match_type_find(validator, tag, NULL) != NULL; +} + +static bool tag_match_type_validate + (struct sieve_validator *validator, + struct sieve_ast_argument **arg, + struct sieve_command_context *cmd) +{ + int ext_id; + const struct sieve_match_type *addrp; + + /* Syntax: + * ":localpart" / ":domain" / ":all" (subject to extension) + */ + + /* Get match_type from registry */ + addrp = sieve_match_type_find + (validator, sieve_ast_argument_tag(*arg), &ext_id); + + /* In theory, addrp can never be NULL, because we must have found it earlier + * to get here. + */ + if ( addrp == NULL ) { + sieve_command_validate_error(validator, cmd, + "unknown match-type modifier '%s' " + "(this error should not occur and is probably a bug)", + sieve_ast_argument_strc(*arg)); + + return FALSE; + } + + /* Store match-type in context */ + (*arg)->context = (void *) addrp; + (*arg)->ext_id = ext_id; + + /* Skip tag */ + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* Code generation */ + +static void opr_match_type_emit + (struct sieve_binary *sbin, struct sieve_match_type *addrp) +{ + (void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_MATCH_TYPE); + (void) sieve_binary_emit_byte(sbin, addrp->code); +} + +static void opr_match_type_emit_ext + (struct sieve_binary *sbin, struct sieve_match_type *addrp, int ext_id) +{ + unsigned char mtch_code = SIEVE_MATCH_TYPE_CUSTOM + + sieve_binary_extension_get_index(sbin, ext_id); + + (void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_MATCH_TYPE); + (void) sieve_binary_emit_byte(sbin, mtch_code); + if ( addrp->extension->match_type == NULL ) + (void) sieve_binary_emit_byte(sbin, addrp->ext_code); +} + +const struct sieve_match_type *sieve_opr_match_type_read + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address) +{ + unsigned int mtch_code; + const struct sieve_operand *operand = sieve_operand_read(sbin, address); + + if ( operand == NULL || operand->class != &match_type_class ) + return NULL; + + if ( sieve_binary_read_byte(sbin, address, &mtch_code) ) { + if ( mtch_code < SIEVE_MATCH_TYPE_CUSTOM ) { + if ( mtch_code < sieve_core_match_types_count ) + return sieve_core_match_types[mtch_code]; + else + return NULL; + } else { + int ext_id = -1; + const struct sieve_match_type_extension *ap_ext; + + if ( sieve_binary_extension_get_by_index(sbin, + mtch_code - SIEVE_MATCH_TYPE_CUSTOM, &ext_id) == NULL ) + return NULL; + + ap_ext = sieve_match_type_extension_get(interpreter, ext_id); + + if ( ap_ext != NULL ) { + unsigned int code; + if ( ap_ext->match_type != NULL ) + return ap_ext->match_type; + + if ( sieve_binary_read_byte(sbin, address, &code) && + ap_ext->get_part != NULL ) + return ap_ext->get_part(code); + } else { + i_info("Unknown match-type modifier %d.", mtch_code); + } + } + } + + return NULL; +} + +bool sieve_opr_match_type_dump + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address) +{ + sieve_size_t pc = *address; + const struct sieve_match_type *addrp = + sieve_opr_match_type_read(interpreter, sbin, address); + + if ( addrp == NULL ) + return FALSE; + + printf("%08x: MATCH-TYPE: %s\n", pc, addrp->identifier); + + return TRUE; +} + +static bool tag_match_type_generate + (struct sieve_generator *generator, struct sieve_ast_argument **arg, + struct sieve_command_context *cmd ATTR_UNUSED) +{ + struct sieve_binary *sbin = sieve_generator_get_binary(generator); + struct sieve_match_type *addrp = + (struct sieve_match_type *) (*arg)->context; + + if ( addrp->extension == NULL ) { + if ( addrp->code < SIEVE_MATCH_TYPE_CUSTOM ) + opr_match_type_emit(sbin, addrp); + else + return FALSE; + } else { + opr_match_type_emit_ext(sbin, addrp, (*arg)->ext_id); + } + + *arg = sieve_ast_argument_next(*arg); + + return TRUE; +} + +/* + * Matching + */ + + +/* + * Core match-type modifiers + */ + +const struct sieve_argument match_type_tag = { + NULL, + tag_match_type_is_instance_of, + tag_match_type_validate, + tag_match_type_generate +}; + +const struct sieve_match_type is_match_type = { + "is", + SIEVE_MATCH_TYPE_IS, + NULL, + 0, +}; + +const struct sieve_match_type contains_match_type = { + "contains", + SIEVE_MATCH_TYPE_CONTAINS, + NULL, + 0, +}; + +const struct sieve_match_type matches_match_type = { + "matches", + SIEVE_MATCH_TYPE_MATCHES, + NULL, + 0, +}; + +const struct sieve_match_type *sieve_core_match_types[] = { + &is_match_type, &contains_match_type, &matches_match_type +}; + +const unsigned int sieve_core_match_types_count = + N_ELEMENTS(sieve_core_match_types); + + diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h new file mode 100644 index 0000000000000000000000000000000000000000..7af63242d94df1a0e49a0078144ea94a3a972253 --- /dev/null +++ b/src/lib-sieve/sieve-match-types.h @@ -0,0 +1,66 @@ +#ifndef __SIEVE_MATCH_TYPES_H +#define __SIEVE_MATCH_TYPES_H + +#include "sieve-common.h" + +enum sieve_match_type_code { + SIEVE_MATCH_TYPE_IS, + SIEVE_MATCH_TYPE_CONTAINS, + SIEVE_MATCH_TYPE_MATCHES, + SIEVE_MATCH_TYPE_CUSTOM +}; + +struct sieve_match_type_extension; + +struct sieve_match_type { + const char *identifier; + + enum sieve_match_type_code code; + + const struct sieve_match_type_extension *extension; + unsigned int ext_code; +}; + +struct sieve_match_type_extension { + const struct sieve_extension *extension; + + /* Either a single match-type in this extension ... */ + const struct sieve_match_type *match_type; + + /* ... or multiple: then the extension must handle emit/read */ + const struct sieve_match_type *(*get_part) + (unsigned int code); +}; + +void sieve_match_types_link_tags + (struct sieve_validator *validator, + struct sieve_command_registration *cmd_reg, + unsigned int id_code); + +void sieve_match_type_register + (struct sieve_validator *validator, + const struct sieve_match_type *addrp, int ext_id); +const struct sieve_match_type *sieve_match_type_find + (struct sieve_validator *validator, const char *identifier, + int *ext_id); +void sieve_match_type_extension_set + (struct sieve_interpreter *interpreter, int ext_id, + const struct sieve_match_type_extension *ext); + +extern const struct sieve_argument match_type_tag; + +extern const struct sieve_match_type is_match_type; +extern const struct sieve_match_type contains_match_type; +extern const struct sieve_match_type matches_match_type; + +extern const struct sieve_match_type *sieve_core_match_types[]; +extern const unsigned int sieve_core_match_types_count; + +const struct sieve_match_type *sieve_opr_match_type_read + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address); +bool sieve_opr_match_type_dump + (struct sieve_interpreter *interpreter, + struct sieve_binary *sbin, sieve_size_t *address); + +#endif /* __SIEVE_MATCH_TYPES_H */ diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index cada9ae852aa1669ca74a365b4469fc30a0b6f25..2c2cd3f39c212608ae8cb0f3cf55af95bd021b13 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -52,11 +52,9 @@ void sieve_validator_error(struct sieve_validator *validator, struct sieve_ast_n va_end(args); } -extern struct sieve_extension comparator_extension; -extern struct sieve_extension address_part_extension; - struct sieve_validator *sieve_validator_create(struct sieve_ast *ast, struct sieve_error_handler *ehandler) { + unsigned int i; pool_t pool; struct sieve_validator *validator; @@ -73,8 +71,12 @@ struct sieve_validator *sieve_validator_create(struct sieve_ast *ast, struct sie sieve_extensions_get_count()); /* Pre-load core language features implemented as 'extensions' */ - (void)comparator_extension.validator_load(validator); - (void)address_part_extension.validator_load(validator); + for ( i = 0; i < sieve_preloaded_extensions_count; i++ ) { + const struct sieve_extension *ext = sieve_preloaded_extensions[i]; + + if ( ext->validator_load != NULL ) + (void)ext->validator_load(validator); + } /* Setup command registry */ validator->commands = hash_create @@ -327,39 +329,6 @@ inline const void *sieve_validator_extension_get_context(struct sieve_validator return array_idx(&validator->ext_contexts, (unsigned int) ext_id); } -/* Match type validation */ - -static bool sieve_validate_match_type_tag - (struct sieve_validator *validator ATTR_UNUSED, - struct sieve_ast_argument **arg, - struct sieve_command_context *cmd ATTR_UNUSED) -{ - /* Syntax: - * ":is" / ":contains" / ":matches" - */ - - /* Not implemented, so delete it */ - *arg = sieve_ast_arguments_delete(*arg, 1); - - return TRUE; -} - -static const struct sieve_argument match_is_tag = - { "is", NULL, sieve_validate_match_type_tag, NULL }; -static const struct sieve_argument match_contains_tag = - { "contains", NULL, sieve_validate_match_type_tag, NULL }; -static const struct sieve_argument match_matches_tag = - { "matches", NULL, sieve_validate_match_type_tag, NULL }; - -void sieve_validator_link_match_type_tags - (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, - unsigned int id_code) -{ - sieve_validator_register_tag(validator, cmd_reg, &match_is_tag, id_code); - sieve_validator_register_tag(validator, cmd_reg, &match_contains_tag, id_code); - sieve_validator_register_tag(validator, cmd_reg, &match_matches_tag, id_code); -} - /* Tag Validation API */ /* Test validation API */ diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c index fcff7543eebfe34534a3229b91b7aadde0a722e4..91b085810bf8d694d37e6a33cfde3508e57d912c 100644 --- a/src/lib-sieve/tst-address.c +++ b/src/lib-sieve/tst-address.c @@ -4,6 +4,7 @@ #include "sieve-commands-private.h" #include "sieve-comparators.h" +#include "sieve-match-types.h" #include "sieve-address-parts.h" #include "sieve-validator.h" @@ -36,7 +37,7 @@ bool tst_address_registered(struct sieve_validator *validator, struct sieve_comm /* The order of these is not significant */ sieve_comparators_link_tag(validator, cmd_reg, OPT_COMPARATOR ); sieve_address_parts_link_tags(validator, cmd_reg, OPT_ADDRESS_PART); - sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE); + sieve_match_types_link_tags(validator, cmd_reg, OPT_MATCH_TYPE); return TRUE; } @@ -111,6 +112,8 @@ static bool tst_address_opcode_dump return FALSE; break; case OPT_MATCH_TYPE: + if ( !sieve_opr_match_type_dump(interp, sbin, address) ) + return FALSE; break; case OPT_ADDRESS_PART: if ( !sieve_opr_address_part_dump(interp, sbin, address) ) @@ -135,6 +138,7 @@ static bool tst_address_opcode_execute struct mail *mail = sieve_interpreter_get_mail(interp); const struct sieve_comparator *cmp = &i_octet_comparator; + const struct sieve_match_type *mtch = &is_match_type; const struct sieve_address_part *addrp = &all_address_part; unsigned int opt_code; struct sieve_coded_stringlist *hdr_list; @@ -153,6 +157,8 @@ static bool tst_address_opcode_execute return FALSE; break; case OPT_MATCH_TYPE: + if ( (mtch = sieve_opr_match_type_read(interp, sbin, address)) == NULL ) + return FALSE; break; case OPT_ADDRESS_PART: if ( (addrp = sieve_opr_address_part_read(interp, sbin, address)) == NULL ) diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c index e06ddb2a26d7c0ea0aa3d51f241fad788b45ee96..a7eb0a950197da13c641ee2a5e18906c0c00ecad 100644 --- a/src/lib-sieve/tst-header.c +++ b/src/lib-sieve/tst-header.c @@ -3,6 +3,7 @@ #include "sieve-commands.h" #include "sieve-commands-private.h" #include "sieve-comparators.h" +#include "sieve-match-types.h" #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" @@ -31,7 +32,7 @@ bool tst_header_registered(struct sieve_validator *validator, struct sieve_comma { /* The order of these is not significant */ sieve_comparators_link_tag(validator, cmd_reg, OPT_COMPARATOR); - sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE); + sieve_match_types_link_tags(validator, cmd_reg, OPT_MATCH_TYPE); return TRUE; } @@ -102,6 +103,7 @@ static bool tst_header_opcode_dump sieve_opr_comparator_dump(interp, sbin, address); break; case OPT_MATCH_TYPE: + sieve_opr_match_type_dump(interp, sbin, address); break; default: return FALSE; @@ -123,6 +125,7 @@ static bool tst_header_opcode_execute unsigned int opt_code; const struct sieve_comparator *cmp = &i_octet_comparator; + const struct sieve_match_type *mtch = &is_match_type; struct sieve_coded_stringlist *hdr_list; struct sieve_coded_stringlist *key_list; string_t *hdr_item; @@ -138,6 +141,7 @@ static bool tst_header_opcode_execute cmp = sieve_opr_comparator_read(interp, sbin, address); break; case OPT_MATCH_TYPE: + mtch = sieve_opr_match_type_read(interp, sbin, address); break; default: return FALSE;