diff --git a/sieve/tests/address-part.sieve b/sieve/tests/address-part.sieve new file mode 100644 index 0000000000000000000000000000000000000000..cd25bf9851686ccb4480dfab383ef313fb082b79 --- /dev/null +++ b/sieve/tests/address-part.sieve @@ -0,0 +1,10 @@ +if address :comparator "i;ascii-casemap" :localpart "from" "STEPHAN" { + discard; + + if address :domain :comparator "i;octet" "from" "drunksnipers.com" { + keep; + } + stop; +} + +keep; diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index 66fa6e8938d8a48ef8975afca4210a4c2a8b0c4a..70698ceac607ca9bb5ac97ac385536294d39215b 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -154,6 +154,7 @@ static bool ext_envelope_opcode_dump case OPT_MATCH_TYPE: break; case OPT_ADDRESS_PART: + sieve_opr_address_part_dump(sbin, address); break; default: return FALSE; diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c index 84ba69530180895aaadd90c8b008aad1a7fa2c02..547d5f35cc37f43bf85183256dacf1c5a00c6c3f 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -20,12 +20,10 @@ * Predeclarations */ -static struct sieve_interpreter_registry *addrp_registry = NULL; - static void opr_address_part_emit (struct sieve_binary *sbin, unsigned int code); static void opr_address_part_emit_ext - (struct sieve_binary *sbin, const struct sieve_extension *ext); + (struct sieve_binary *sbin, int ext_id); /* * Comparator 'extension' @@ -110,13 +108,32 @@ static bool addrp_validator_load(struct sieve_validator *validator) return TRUE; } +void sieve_address_parts_link_tags + (struct sieve_validator *validator, + struct sieve_command_registration *cmd_reg, + unsigned int id_code) +{ + struct addrp_validator_context *ctx = get_validator_context(validator); + struct hash_iterate_context *itx = hash_iterate_init(ctx->address_parts); + void *key; + void *addrp; + + while ( hash_iterate(itx, &key, &addrp) ) { + sieve_validator_register_tag + (validator, cmd_reg, ((struct sieve_address_part *) addrp)->tag, id_code); + } + + hash_iterate_deinit(&itx); +} /* * Address-part operand */ -struct sieve_operand_class address_part_class = { "address-part", NULL }; -struct sieve_operand address_part_operand = { "address-part", &address_part_class, FALSE }; +struct sieve_operand_class address_part_class = + { "address-part", NULL }; +struct sieve_operand address_part_operand = + { "address-part", &address_part_class, FALSE }; /* * Address-part tag @@ -154,38 +171,16 @@ static bool tag_address_part_validate return TRUE; } -const struct sieve_argument address_localpart_tag = - { "localpart", tag_address_part_validate, NULL }; -const struct sieve_argument address_domain_tag = - { "domain", tag_address_part_validate, NULL }; -const struct sieve_argument address_all_tag = - { "all", tag_address_part_validate, NULL }; - -/* Address part validation */ - -void sieve_address_parts_link_tags - (struct sieve_validator *validator, - struct sieve_command_registration *cmd_reg, - unsigned int id_code) -{ - 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); -} - /* Code generation */ -static void opr_address_parts_emit +static void opr_address_part_emit (struct sieve_binary *sbin, unsigned int code) { (void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_ADDRESS_PART); (void) sieve_binary_emit_byte(sbin, code); } -static void opr_address_parts_emit_ext +static void opr_address_part_emit_ext (struct sieve_binary *sbin, int ext_id) { unsigned char cmp_code = SIEVE_ADDRESS_PART_CUSTOM + @@ -228,7 +223,8 @@ const struct sieve_address_part *sieve_opr_address_part_read bool sieve_opr_address_part_dump(struct sieve_binary *sbin, sieve_size_t *address) { sieve_size_t pc = *address; - const struct sieve_address_part *addrp = sieve_opr_address_part_read(sbin, address); + const struct sieve_address_part *addrp = + sieve_opr_address_part_read(sbin, address); if ( addrp == NULL ) return FALSE; @@ -243,7 +239,8 @@ static bool tag_address_part_generate struct sieve_command_context *cmd ATTR_UNUSED) { struct sieve_binary *sbin = sieve_generator_get_binary(generator); - struct sieve_address_part *addrp = (struct sieve_address_part *) (*arg)->context; + struct sieve_address_part *addrp = + (struct sieve_address_part *) (*arg)->context; if ( addrp->extension == NULL ) { if ( addrp->code < SIEVE_ADDRESS_PART_CUSTOM ) @@ -262,22 +259,32 @@ static bool tag_address_part_generate /* * Core address-part modifiers */ + +const struct sieve_argument address_localpart_tag = + { "localpart", tag_address_part_validate, tag_address_part_generate }; +const struct sieve_argument address_domain_tag = + { "domain", tag_address_part_validate, tag_address_part_generate }; +const struct sieve_argument address_all_tag = + { "all", tag_address_part_validate, tag_address_part_generate }; const struct sieve_address_part all_address_part = { "all", + &address_all_tag, SIEVE_ADDRESS_PART_ALL, NULL }; const struct sieve_address_part local_address_part = { "localpart", + &address_localpart_tag, SIEVE_ADDRESS_PART_LOCAL, NULL }; const struct sieve_address_part domain_address_part = { "domain", - SIEVE_ADDRESS_PART_LOCAL, + &address_domain_tag, + SIEVE_ADDRESS_PART_DOMAIN, NULL }; diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h index a89b67e0dfe601ec42923d882aa172e0f82f450b..233edf1e19c10b7e3a095bd9592c80f75b35ad76 100644 --- a/src/lib-sieve/sieve-address-parts.h +++ b/src/lib-sieve/sieve-address-parts.h @@ -10,6 +10,7 @@ enum sieve_address_part_code { struct sieve_address_part { const char *identifier; + const struct sieve_argument *tag; enum sieve_address_part_code code; const struct sieve_extension *extension; diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index 2cab25d84b1c6fa057f229f52416effe7445aedf..af601d01a9091e13b9fb5d832087c61f2777e508 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -92,7 +92,7 @@ inline sieve_size_t sieve_coded_stringlist_get_current_offset(struct sieve_coded inline sieve_size_t sieve_operand_emit_code (struct sieve_binary *sbin, int operand) { - unsigned char op = operand & SIEVE_OPERAND_CORE_MASK; + unsigned char op = operand; return sieve_binary_emit_byte(sbin, op); } @@ -103,7 +103,7 @@ const struct sieve_operand *sieve_operand_read unsigned int operand; if ( sieve_binary_read_byte(sbin, address, &operand) ) { - if ( operand < SIEVE_OPERAND_EXT_OFFSET ) { + if ( operand < SIEVE_OPERAND_CUSTOM ) { if ( operand < sieve_operand_count ) return sieve_operands[operand]; else @@ -112,7 +112,7 @@ const struct sieve_operand *sieve_operand_read int ext_id = -1; const struct sieve_extension *ext = sieve_binary_extension_get_by_index - (sbin, operand - SIEVE_OPERAND_EXT_OFFSET, &ext_id); + (sbin, operand - SIEVE_OPERAND_CUSTOM, &ext_id); if ( ext != NULL ) return ext->operand; @@ -219,13 +219,16 @@ const struct sieve_operand stringlist_operand = /* Core operands */ extern struct sieve_operand comparator_operand; +extern struct sieve_operand address_part_operand; const struct sieve_operand *sieve_operands[] = { NULL, /* SIEVE_OPERAND_OPTIONAL */ &number_operand, &string_operand, &stringlist_operand, - &comparator_operand + &comparator_operand, + NULL, + &address_part_operand }; const unsigned int sieve_operand_count = @@ -549,7 +552,7 @@ static struct sieve_coded_stringlist *opr_stringlist_read inline sieve_size_t sieve_operation_emit_code (struct sieve_binary *sbin, int opcode) { - unsigned char op = opcode & SIEVE_OPCODE_CORE_MASK; + unsigned char op = opcode; return sieve_binary_emit_byte(sbin, op); } @@ -557,7 +560,7 @@ inline sieve_size_t sieve_operation_emit_code inline sieve_size_t sieve_operation_emit_code_ext (struct sieve_binary *sbin, int ext_id) { - unsigned char op = SIEVE_OPCODE_EXT_OFFSET + + unsigned char op = SIEVE_OPCODE_CUSTOM + sieve_binary_extension_get_index(sbin, ext_id); return sieve_binary_emit_byte(sbin, op); @@ -569,7 +572,7 @@ const struct sieve_opcode *sieve_operation_read unsigned int opcode; if ( sieve_binary_read_byte(sbin, address, &opcode) ) { - if ( opcode < SIEVE_OPCODE_EXT_OFFSET ) { + if ( opcode < SIEVE_OPCODE_CUSTOM ) { if ( opcode < sieve_opcode_count ) return sieve_opcodes[opcode]; else @@ -578,7 +581,7 @@ const struct sieve_opcode *sieve_operation_read int ext_id = -1; const struct sieve_extension *ext = sieve_binary_extension_get_by_index - (sbin, opcode - SIEVE_OPCODE_EXT_OFFSET, &ext_id); + (sbin, opcode - SIEVE_OPCODE_CUSTOM, &ext_id); if ( ext != NULL ) return ext->opcode; diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h index b2df9bb8347043e99666ba968a4435ab3f9f88dc..dae9d6d41f0fb854cf08b6792a6187597ca15230 100644 --- a/src/lib-sieve/sieve-code.h +++ b/src/lib-sieve/sieve-code.h @@ -62,7 +62,9 @@ enum sieve_core_operand { SIEVE_OPERAND_STRING_LIST, SIEVE_OPERAND_COMPARATOR, SIEVE_OPERAND_MATCH_TYPE, - SIEVE_OPERAND_ADDRESS_PART + SIEVE_OPERAND_ADDRESS_PART, + + SIEVE_OPERAND_CUSTOM }; extern const struct sieve_operand *sieve_operands[]; @@ -116,7 +118,9 @@ enum sieve_core_operation { SIEVE_OPCODE_HEADER, SIEVE_OPCODE_EXISTS, SIEVE_OPCODE_SIZEOVER, - SIEVE_OPCODE_SIZEUNDER + SIEVE_OPCODE_SIZEUNDER, + + SIEVE_OPCODE_CUSTOM }; extern const struct sieve_opcode *sieve_opcodes[]; @@ -131,9 +135,4 @@ const struct sieve_opcode *sieve_operation_read /* Core operands */ -#define SIEVE_OPCODE_CORE_MASK 0x1F -#define SIEVE_OPCODE_EXT_OFFSET (SIEVE_OPCODE_CORE_MASK + 1) -#define SIEVE_OPERAND_CORE_MASK 0x1F -#define SIEVE_OPERAND_EXT_OFFSET (SIEVE_OPCODE_CORE_MASK + 1) - #endif diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index 5984d9126657a47c30ecf13b2b9ecad465227edd..e870f4c241ad83ce82d817d9d33ccdb4f2a1d4d3 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -67,18 +67,21 @@ struct sieve_validator *sieve_validator_create(struct sieve_ast *ast, struct sie validator->ast = ast; sieve_ast_ref(ast); + + /* Setup storage for extension contexts */ + array_create(&validator->ext_contexts, pool, sizeof(void *), + 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); + /* Setup command registry */ validator->commands = hash_create (pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); sieve_validator_register_core_commands(validator); sieve_validator_register_core_tests(validator); - array_create(&validator->ext_contexts, pool, sizeof(void *), - sieve_extensions_get_count()); - - (void)comparator_extension.validator_load(validator); - (void)address_part_extension.validator_load(validator); return validator; } diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c index a767e73653733450440ed86f206ad8f0298c6d1b..486e9fa9625ab54ffb3112987fb7b6d64d137edc 100644 --- a/src/lib-sieve/tst-address.c +++ b/src/lib-sieve/tst-address.c @@ -5,6 +5,7 @@ #include "sieve-comparators.h" #include "sieve-address-parts.h" + #include "sieve-validator.h" #include "sieve-generator.h" #include "sieve-interpreter.h" @@ -106,11 +107,14 @@ static bool tst_address_opcode_dump while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) { switch ( opt_code ) { case OPT_COMPARATOR: - sieve_opr_comparator_dump(sbin, address); + if ( !sieve_opr_comparator_dump(sbin, address) ) + return FALSE; break; case OPT_MATCH_TYPE: break; case OPT_ADDRESS_PART: + if ( !sieve_opr_address_part_dump(sbin, address) ) + return FALSE; break; default: return FALSE; @@ -131,6 +135,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_address_part *addrp = &all_address_part; unsigned int opt_code; struct sieve_coded_stringlist *hdr_list; struct sieve_coded_stringlist *key_list; @@ -144,11 +149,14 @@ static bool tst_address_opcode_execute while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) { switch ( opt_code ) { case OPT_COMPARATOR: - cmp = sieve_opr_comparator_read(sbin, address); + if ( (cmp = sieve_opr_comparator_read(sbin, address)) == NULL ) + return FALSE; break; case OPT_MATCH_TYPE: break; case OPT_ADDRESS_PART: + if ( (addrp = sieve_opr_address_part_read(sbin, address)) == NULL ) + return FALSE; break; default: return FALSE; @@ -161,14 +169,12 @@ static bool tst_address_opcode_execute /* Read header-list */ if ( (hdr_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) { t_pop(); - printf("HDR_LIST FAILED\n"); return FALSE; } /* Read key-list */ if ( (key_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) { t_pop(); - printf("KEY_LIST FAILED\n"); return FALSE; }