From e25f3bafe65f9ada1b8e50915e42baaffa22b362 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sun, 11 Nov 2007 17:19:01 +0100 Subject: [PATCH] Added support for optional operators to the byte code implementation. --- sieve/tests/comparator.sieve | 4 + src/lib-sieve/ext-envelope.c | 34 ++++++++- src/lib-sieve/plugins/vacation/ext-vacation.c | 21 +++-- src/lib-sieve/sieve-ast.c | 2 + src/lib-sieve/sieve-ast.h | 1 + src/lib-sieve/sieve-code.c | 39 ++++++++-- src/lib-sieve/sieve-code.h | 7 ++ src/lib-sieve/sieve-comparators.c | 17 ++++- src/lib-sieve/sieve-comparators.h | 6 ++ src/lib-sieve/sieve-generator.c | 30 ++++++++ src/lib-sieve/sieve-validator.c | 76 +++++++++++++------ src/lib-sieve/sieve-validator.h | 11 ++- src/lib-sieve/tst-address.c | 54 ++++++++++++- src/lib-sieve/tst-header.c | 48 +++++++++++- src/lib-sieve/tst-size.c | 4 +- 15 files changed, 305 insertions(+), 49 deletions(-) diff --git a/sieve/tests/comparator.sieve b/sieve/tests/comparator.sieve index 12de98223..291276ab2 100644 --- a/sieve/tests/comparator.sieve +++ b/sieve/tests/comparator.sieve @@ -1,5 +1,9 @@ if header :is :comparator "i;ascii-casemap" "from" "STEPHAN@drunksnipers.com" { discard; + + if address :is :comparator "i;octet" :domain "from" "drunksnipers.com" { + keep; + } stop; } diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index fae863efe..268ad1154 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -30,13 +30,22 @@ const struct sieve_extension envelope_extension = static const struct sieve_command envelope_test = { "envelope", SCT_TEST, tst_envelope_registered, tst_envelope_validate, tst_envelope_generate, NULL }; +/* Optional arguments */ + +enum tst_envelope_optional { + OPT_END, + OPT_COMPARATOR, + OPT_ADDRESS_PART, + OPT_MATCH_TYPE +}; + /* Command Registration */ static bool tst_envelope_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) { /* The order of these is not significant */ - sieve_validator_link_comparator_tag(validator, cmd_reg); - sieve_validator_link_address_part_tags(validator, cmd_reg); - sieve_validator_link_match_type_tags(validator, cmd_reg); + sieve_validator_link_comparator_tag(validator, cmd_reg, OPT_COMPARATOR); + sieve_validator_link_address_part_tags(validator, cmd_reg, OPT_ADDRESS_PART); + sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE); return TRUE; } @@ -111,8 +120,27 @@ static bool ext_envelope_opcode_dump (struct sieve_interpreter *interp ATTR_UNUSED, struct sieve_binary *sbin, sieve_size_t *address) { + unsigned opt_code; + printf("ENVELOPE\n"); + /* Handle any optional arguments */ + if ( sieve_operand_optional_present(sbin, address) ) { + while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) { + switch ( opt_code ) { + case OPT_COMPARATOR: + sieve_opr_comparator_dump(sbin, address); + break; + case OPT_MATCH_TYPE: + break; + case OPT_ADDRESS_PART: + break; + default: + return FALSE; + } + } + } + return sieve_opr_stringlist_dump(sbin, address) && sieve_opr_stringlist_dump(sbin, address); diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c index da710b1b7..7d9d39dd1 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation.c +++ b/src/lib-sieve/plugins/vacation/ext-vacation.c @@ -183,14 +183,23 @@ static const struct sieve_argument vacation_mime_tag = static const struct sieve_argument vacation_handle_tag = { "handle", cmd_vacation_validate_handle_tag, NULL }; +enum cmd_vacation_optional { + OPT_DAYS, + OPT_SUBJECT, + OPT_FROM, + OPT_ADDRESS, + OPT_MIME, + OPT_HANDLE +}; + static bool cmd_vacation_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) { - sieve_validator_register_tag(validator, cmd_reg, &vacation_days_tag); - sieve_validator_register_tag(validator, cmd_reg, &vacation_subject_tag); - sieve_validator_register_tag(validator, cmd_reg, &vacation_from_tag); - sieve_validator_register_tag(validator, cmd_reg, &vacation_addresses_tag); - sieve_validator_register_tag(validator, cmd_reg, &vacation_mime_tag); - sieve_validator_register_tag(validator, cmd_reg, &vacation_handle_tag); + sieve_validator_register_tag(validator, cmd_reg, &vacation_days_tag, OPT_DAYS); + sieve_validator_register_tag(validator, cmd_reg, &vacation_subject_tag, OPT_SUBJECT); + sieve_validator_register_tag(validator, cmd_reg, &vacation_from_tag, OPT_FROM); + sieve_validator_register_tag(validator, cmd_reg, &vacation_addresses_tag, OPT_ADDRESS); + sieve_validator_register_tag(validator, cmd_reg, &vacation_mime_tag, OPT_MIME); + sieve_validator_register_tag(validator, cmd_reg, &vacation_handle_tag, OPT_HANDLE); return TRUE; } diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c index 3b45748df..b66658ac7 100644 --- a/src/lib-sieve/sieve-ast.c +++ b/src/lib-sieve/sieve-ast.c @@ -149,7 +149,9 @@ static struct sieve_ast_argument *sieve_ast_argument_create arg->source_line = source_line; arg->context = NULL; + arg->argument = NULL; + arg->arg_id_code = 0; return arg; } diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h index 1288e8d44..1d97da134 100644 --- a/src/lib-sieve/sieve-ast.h +++ b/src/lib-sieve/sieve-ast.h @@ -83,6 +83,7 @@ struct sieve_ast_argument { /* Argument associated with this ast element */ const struct sieve_argument *argument; + unsigned int arg_id_code; /* Context data associated with this ast element */ void *context; diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index 3d727e01d..9e2efba0e 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -122,6 +122,34 @@ const struct sieve_operand *sieve_operand_read return NULL; } +bool sieve_operand_optional_present(struct sieve_binary *sbin, sieve_size_t *address) +{ + sieve_size_t tmp_addr = *address; + unsigned int op = -1; + + if ( sieve_binary_read_byte(sbin, &tmp_addr, &op) && (op == SIEVE_OPERAND_OPTIONAL) ) { + *address = tmp_addr; + return TRUE; + } + + return FALSE; +} + +unsigned int sieve_operand_optional_read(struct sieve_binary *sbin, sieve_size_t *address) +{ + unsigned int id = -1; + + if ( sieve_binary_read_byte(sbin, address, &id) ) { + /* No more optionals */ + if ( id == 0 ) + return 0; + + return id; + } + + return -1; +} + /* * Operand definitions */ @@ -140,7 +168,7 @@ const struct sieve_operand_class number_class = { "number", &number_interface }; const struct sieve_operand number_operand = - { "number", &number_class }; + { "@number", &number_class, TRUE }; /* String */ @@ -157,7 +185,7 @@ const struct sieve_operand_class string_class = { "string", &string_interface }; const struct sieve_operand string_operand = - { "string", &string_class }; + { "@string", &string_class, TRUE }; /* String List */ @@ -184,13 +212,14 @@ const struct sieve_operand_class stringlist_class = { "string-list", &stringlist_interface }; const struct sieve_operand stringlist_operand = - { "string-list", &stringlist_class }; + { "@string-list", &stringlist_class, TRUE }; /* Core operands */ extern struct sieve_operand comparator_operand; const struct sieve_operand *sieve_operands[] = { + NULL, /* SIEVE_OPERAND_OPTIONAL */ &number_operand, &string_operand, &stringlist_operand, @@ -499,8 +528,8 @@ static struct sieve_coded_stringlist *opr_stringlist_read end = pc + end_offset; if ( !sieve_binary_read_integer(sbin, address, &length) ) - return NULL; - + return NULL; + strlist = sieve_coded_stringlist_create(sbin, *address, length, end); /* Skip over the string list for now */ diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h index 3259ebd55..e8a50bea4 100644 --- a/src/lib-sieve/sieve-code.h +++ b/src/lib-sieve/sieve-code.h @@ -30,6 +30,8 @@ struct sieve_operand { const char *name; const struct sieve_operand_class *class; + + unsigned int positional:1; }; struct sieve_opr_number_interface { @@ -54,6 +56,7 @@ struct sieve_opr_stringlist_interface { }; enum sieve_core_operand { + SIEVE_OPERAND_OPTIONAL, SIEVE_OPERAND_NUMBER, SIEVE_OPERAND_STRING, SIEVE_OPERAND_STRING_LIST, @@ -70,6 +73,10 @@ inline sieve_size_t sieve_operand_emit_code const struct sieve_operand *sieve_operand_read (struct sieve_binary *sbin, sieve_size_t *address); +bool sieve_operand_optional_present(struct sieve_binary *sbin, sieve_size_t *address); +unsigned int sieve_operand_optional_read + (struct sieve_binary *sbin, sieve_size_t *address); + void sieve_opr_number_emit(struct sieve_binary *sbin, sieve_size_t number); bool sieve_opr_number_dump(struct sieve_binary *sbin, sieve_size_t *address); bool sieve_opr_number_read diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c index 09623c04b..fd93cb72e 100644 --- a/src/lib-sieve/sieve-comparators.c +++ b/src/lib-sieve/sieve-comparators.c @@ -1,3 +1,5 @@ +#include <stdio.h> + #include "lib.h" #include "compat.h" @@ -31,7 +33,7 @@ static int cmp_i_ascii_casemap_compare(const void *val1, size_t val1_size, const */ struct sieve_operand_class comparator_class = { "comparator", NULL }; -struct sieve_operand comparator_operand = { "comparator", &comparator_class }; +struct sieve_operand comparator_operand = { "comparator", &comparator_class, FALSE }; /* * Comparator tag @@ -134,6 +136,19 @@ const struct sieve_comparator *sieve_opr_comparator_read return NULL; } +bool sieve_opr_comparator_dump(struct sieve_binary *sbin, sieve_size_t *address) +{ + sieve_size_t pc = *address; + const struct sieve_comparator *cmp = sieve_opr_comparator_read(sbin, address); + + if ( cmp == NULL ) + return FALSE; + + printf("%08x: CMP: %s\n", pc, cmp->identifier); + + return TRUE; +} + static bool tag_comparator_generate (struct sieve_generator *generator, struct sieve_ast_argument **arg, struct sieve_command_context *cmd ATTR_UNUSED) diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h index 5fd8976b6..77da4c23c 100644 --- a/src/lib-sieve/sieve-comparators.h +++ b/src/lib-sieve/sieve-comparators.h @@ -21,11 +21,17 @@ struct sieve_comparator { extern const struct sieve_argument comparator_tag; + +const struct sieve_comparator i_octet_comparator; +const struct sieve_comparator i_ascii_casemap_comparator; + extern const struct sieve_comparator *sieve_core_comparators[]; extern const unsigned int sieve_core_comparators_count; const struct sieve_comparator *sieve_opr_comparator_read (struct sieve_binary *sbin, sieve_size_t *address); +bool sieve_opr_comparator_dump + (struct sieve_binary *sbin, sieve_size_t *address); void sieve_comparators_init_registry(struct sieve_interpreter *interp); diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c index e8dc10b0f..e23f5606c 100644 --- a/src/lib-sieve/sieve-generator.c +++ b/src/lib-sieve/sieve-generator.c @@ -103,12 +103,42 @@ inline sieve_size_t sieve_generator_emit_opcode_ext bool sieve_generate_arguments(struct sieve_generator *generator, struct sieve_command_context *cmd, struct sieve_ast_argument **last_arg) { + enum { ARG_START, ARG_OPTIONAL, ARG_POSITIONAL } state = ARG_START; struct sieve_ast_argument *arg = sieve_ast_argument_first(cmd->ast_node); /* Parse all arguments with assigned generator function */ + while ( arg != NULL && arg->argument != NULL) { const struct sieve_argument *argument = arg->argument; + switch ( state ) { + case ARG_START: + if ( arg->arg_id_code == 0 ) + state = ARG_POSITIONAL; + else { + /* Mark start of optional operands with 0 operand identifier */ + sieve_binary_emit_byte(generator->binary, SIEVE_OPERAND_OPTIONAL); + + /* Emit argument id for optional operand */ + sieve_binary_emit_byte(generator->binary, arg->arg_id_code); + + state = ARG_OPTIONAL; + } + break; + case ARG_OPTIONAL: + if ( arg->arg_id_code == 0 ) + state = ARG_POSITIONAL; + + /* Emit argument id for optional operand (0 marks the end of the optionals) */ + sieve_binary_emit_byte(generator->binary, arg->arg_id_code); + + break; + case ARG_POSITIONAL: + if ( arg->arg_id_code != 0 ) + return FALSE; + break; + } + /* Call the generation function for the argument */ if ( argument->generate != NULL ) { if ( !argument->generate(generator, &arg, cmd) ) diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index 51e8ef50f..26f6ac524 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -163,7 +163,13 @@ static const struct sieve_command * return ( record == NULL ? NULL : record->command ); } -/* Per-command tag registry */ +/* Per-command tag/argument registry */ + +struct sieve_tag_registration { + const struct sieve_argument *tag; + + unsigned int id_code; +}; static bool _unknown_tag_validate (struct sieve_validator *validator ATTR_UNUSED, @@ -176,36 +182,54 @@ static bool _unknown_tag_validate static const struct sieve_argument _unknown_tag = { "", _unknown_tag_validate, NULL }; -void sieve_validator_register_tag +static void _sieve_validator_register_tag (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, - const struct sieve_argument *tag) + const struct sieve_argument *tag, const char *identifier, unsigned int id_code) { + struct sieve_tag_registration *reg; + + reg = p_new(validator->pool, struct sieve_tag_registration, 1); + reg->tag = tag; + reg->id_code = id_code; + if ( cmd_reg->tags == NULL ) { cmd_reg->tags = hash_create (validator->pool, validator->pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); } - hash_insert(cmd_reg->tags, (void *) tag->identifier, (void *) tag); + hash_insert(cmd_reg->tags, (void *) identifier, (void *) reg); +} + +void sieve_validator_register_tag + (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, + const struct sieve_argument *tag, unsigned int id_code) +{ + _sieve_validator_register_tag(validator, cmd_reg, tag, tag->identifier, id_code); } static void sieve_validator_register_unknown_tag (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, const char *tag) { - if ( cmd_reg->tags == NULL ) { - cmd_reg->tags = hash_create - (validator->pool, validator->pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); - } - - hash_insert(cmd_reg->tags, (void *) tag, (void *) &_unknown_tag); + _sieve_validator_register_tag(validator, cmd_reg, &_unknown_tag, tag, 0); } static const struct sieve_argument *sieve_validator_find_tag - (struct sieve_command_registration *cmd_reg, const char *tag) + (struct sieve_command_registration *cmd_reg, const char *tag, unsigned int *id_code) { + const struct sieve_tag_registration *reg; + + *id_code = 0; + if ( cmd_reg->tags == NULL ) return NULL; - return (struct sieve_argument *) hash_lookup(cmd_reg->tags, tag); + reg = (const struct sieve_tag_registration *) hash_lookup(cmd_reg->tags, tag); + + if ( reg == NULL )return NULL; + + *id_code = reg->id_code; + + return reg->tag; } /* Extension support */ @@ -257,9 +281,10 @@ static void sieve_validator_register_core_comparators(struct sieve_validator *va /* Comparator validation */ void sieve_validator_link_comparator_tag - (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) + (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, + unsigned int id_code) { - sieve_validator_register_tag(validator, cmd_reg, &comparator_tag); + sieve_validator_register_tag(validator, cmd_reg, &comparator_tag, id_code); } /* Match type validation */ @@ -287,11 +312,12 @@ static const struct sieve_argument match_matches_tag = { "matches", sieve_validate_match_type_tag, NULL }; void sieve_validator_link_match_type_tags - (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) + (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, + unsigned int id_code) { - sieve_validator_register_tag(validator, cmd_reg, &match_is_tag); - sieve_validator_register_tag(validator, cmd_reg, &match_contains_tag); - sieve_validator_register_tag(validator, cmd_reg, &match_matches_tag); + 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); } /* Address part validation */ @@ -319,11 +345,12 @@ static const struct sieve_argument address_all_tag = { "all", sieve_validate_address_part_tag, NULL }; void sieve_validator_link_address_part_tags - (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) + (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, + unsigned int id_code) { - sieve_validator_register_tag(validator, cmd_reg, &address_localpart_tag); - sieve_validator_register_tag(validator, cmd_reg, &address_domain_tag); - sieve_validator_register_tag(validator, cmd_reg, &address_all_tag); + sieve_validator_register_tag(validator, cmd_reg, &address_localpart_tag, id_code); + sieve_validator_register_tag(validator, cmd_reg, &address_domain_tag, id_code); + sieve_validator_register_tag(validator, cmd_reg, &address_all_tag, id_code); } /* Tag Validation API */ @@ -361,7 +388,9 @@ bool sieve_validate_command_arguments /* Parse tagged and optional arguments */ while ( sieve_ast_argument_type(arg) == SAAT_TAG ) { - const struct sieve_argument *tag = sieve_validator_find_tag(cmd_reg, sieve_ast_argument_tag(arg)); + unsigned int id_code; + const struct sieve_argument *tag = + sieve_validator_find_tag(cmd_reg, sieve_ast_argument_tag(arg), &id_code); if ( tag == NULL ) { sieve_command_validate_error(validator, cmd, @@ -377,6 +406,7 @@ bool sieve_validate_command_arguments /* Assign the tagged argument type to the ast for later reference (in generator) */ arg->argument = tag; + arg->arg_id_code = id_code; /* Call the validation function for the tag (if present) * Fail if the validation fails. diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h index e3aaf3b80..8103faaf3 100644 --- a/src/lib-sieve/sieve-validator.h +++ b/src/lib-sieve/sieve-validator.h @@ -29,7 +29,7 @@ void sieve_validator_register_command /* Argument registration */ void sieve_validator_register_tag (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, - const struct sieve_argument *argument); + const struct sieve_argument *argument, unsigned int id_code); /* Comparator registration */ void sieve_validator_register_comparator @@ -39,11 +39,14 @@ const struct sieve_comparator *sieve_validator_find_comparator /* Special test arguments */ void sieve_validator_link_comparator_tag - (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg); + (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, + unsigned int id_code); void sieve_validator_link_match_type_tags - (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg); + (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, + unsigned int id_code); void sieve_validator_link_address_part_tags - (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg); + (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, + unsigned int id_code); /* Argument validation */ bool sieve_validate_command_arguments diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c index 1f0b7cb39..6432abfb0 100644 --- a/src/lib-sieve/tst-address.c +++ b/src/lib-sieve/tst-address.c @@ -16,14 +16,23 @@ static bool tst_address_opcode_execute const struct sieve_opcode tst_address_opcode = { tst_address_opcode_dump, tst_address_opcode_execute }; +/* Optional arguments */ + +enum tst_address_optional { + OPT_END, + OPT_COMPARATOR, + OPT_ADDRESS_PART, + OPT_MATCH_TYPE +}; + /* Test registration */ bool tst_address_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) { /* The order of these is not significant */ - sieve_validator_link_comparator_tag(validator, cmd_reg); - sieve_validator_link_address_part_tags(validator, cmd_reg); - sieve_validator_link_match_type_tags(validator, cmd_reg); + sieve_validator_link_comparator_tag(validator, cmd_reg, OPT_COMPARATOR ); + sieve_validator_link_address_part_tags(validator, cmd_reg, OPT_ADDRESS_PART); + sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE); return TRUE; } @@ -85,8 +94,27 @@ static bool tst_address_opcode_dump (struct sieve_interpreter *interp ATTR_UNUSED, struct sieve_binary *sbin, sieve_size_t *address) { + unsigned int opt_code; + printf("ADDRESS\n"); + /* Handle any optional arguments */ + if ( sieve_operand_optional_present(sbin, address) ) { + while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) { + switch ( opt_code ) { + case OPT_COMPARATOR: + sieve_opr_comparator_dump(sbin, address); + break; + case OPT_MATCH_TYPE: + break; + case OPT_ADDRESS_PART: + break; + default: + return FALSE; + } + } + } + return sieve_opr_stringlist_dump(sbin, address) && sieve_opr_stringlist_dump(sbin, address); @@ -98,6 +126,9 @@ static bool tst_address_opcode_execute (struct sieve_interpreter *interp, struct sieve_binary *sbin, sieve_size_t *address) { struct mail *mail = sieve_interpreter_get_mail(interp); + + const struct sieve_comparator *cmp = &i_octet_comparator; + unsigned int opt_code; struct sieve_coded_stringlist *hdr_list; struct sieve_coded_stringlist *key_list; string_t *hdr_item; @@ -105,6 +136,23 @@ static bool tst_address_opcode_execute printf("?? ADDRESS\n"); + /* Handle any optional arguments */ + if ( sieve_operand_optional_present(sbin, address) ) { + while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) { + switch ( opt_code ) { + case OPT_COMPARATOR: + cmp = sieve_opr_comparator_read(sbin, address); + break; + case OPT_MATCH_TYPE: + break; + case OPT_ADDRESS_PART: + break; + default: + return FALSE; + } + } + } + t_push(); /* Read header-list */ diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c index 7183b3e86..91444b351 100644 --- a/src/lib-sieve/tst-header.c +++ b/src/lib-sieve/tst-header.c @@ -2,6 +2,7 @@ #include "sieve-commands.h" #include "sieve-commands-private.h" +#include "sieve-comparators.h" #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" @@ -16,13 +17,21 @@ static bool tst_header_opcode_execute const struct sieve_opcode tst_header_opcode = { tst_header_opcode_dump, tst_header_opcode_execute }; +/* Optional arguments */ + +enum tst_header_optional { + OPT_END, + OPT_COMPARATOR, + OPT_MATCH_TYPE +}; + /* Test registration */ bool tst_header_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) { /* The order of these is not significant */ - sieve_validator_link_comparator_tag(validator, cmd_reg); - sieve_validator_link_match_type_tags(validator, cmd_reg); + sieve_validator_link_comparator_tag(validator, cmd_reg, OPT_COMPARATOR); + sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE); return TRUE; } @@ -81,8 +90,25 @@ static bool tst_header_opcode_dump (struct sieve_interpreter *interp ATTR_UNUSED, struct sieve_binary *sbin, sieve_size_t *address) { + unsigned int opt_code; + printf("HEADER\n"); + /* Handle any optional arguments */ + if ( sieve_operand_optional_present(sbin, address) ) { + while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) { + switch ( opt_code ) { + case OPT_COMPARATOR: + sieve_opr_comparator_dump(sbin, address); + break; + case OPT_MATCH_TYPE: + break; + default: + return FALSE; + } + } + } + return sieve_opr_stringlist_dump(sbin, address) && sieve_opr_stringlist_dump(sbin, address); @@ -94,6 +120,9 @@ static bool tst_header_opcode_execute (struct sieve_interpreter *interp, struct sieve_binary *sbin, sieve_size_t *address) { struct mail *mail = sieve_interpreter_get_mail(interp); + + unsigned int opt_code; + const struct sieve_comparator *cmp = &i_octet_comparator; struct sieve_coded_stringlist *hdr_list; struct sieve_coded_stringlist *key_list; string_t *hdr_item; @@ -101,6 +130,21 @@ static bool tst_header_opcode_execute printf("?? HEADER\n"); + /* Handle any optional arguments */ + if ( sieve_operand_optional_present(sbin, address) ) { + while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) { + switch ( opt_code ) { + case OPT_COMPARATOR: + cmp = sieve_opr_comparator_read(sbin, address); + break; + case OPT_MATCH_TYPE: + break; + default: + return FALSE; + } + } + } + t_push(); /* Read header-list */ diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c index 715ea9667..9c6650707 100644 --- a/src/lib-sieve/tst-size.c +++ b/src/lib-sieve/tst-size.c @@ -83,8 +83,8 @@ static const struct sieve_argument size_under_tag = bool tst_size_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) { - sieve_validator_register_tag(validator, cmd_reg, &size_over_tag); - sieve_validator_register_tag(validator, cmd_reg, &size_under_tag); + sieve_validator_register_tag(validator, cmd_reg, &size_over_tag, 0); + sieve_validator_register_tag(validator, cmd_reg, &size_under_tag, 0); return TRUE; } -- GitLab