From 4e793fea55d9b308cec82a723f874a85d5cc1e52 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Fri, 9 Nov 2007 01:23:12 +0100 Subject: [PATCH] Started implementation of comparator execution support. --- src/lib-sieve/ext-envelope.c | 2 +- src/lib-sieve/ext-fileinto.c | 2 +- src/lib-sieve/ext-reject.c | 2 +- src/lib-sieve/plugins/vacation/ext-vacation.c | 2 +- src/lib-sieve/sieve-binary.c | 10 +- src/lib-sieve/sieve-binary.h | 4 +- src/lib-sieve/sieve-code.c | 5 +- src/lib-sieve/sieve-comparators.c | 94 +++++++++++++++++-- src/lib-sieve/sieve-comparators.h | 17 +++- src/lib-sieve/sieve-extensions.h | 7 +- src/lib-sieve/sieve-interpreter.c | 73 ++++++++++++-- src/lib-sieve/sieve-interpreter.h | 23 +++-- 12 files changed, 199 insertions(+), 42 deletions(-) diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index c918d2cb0..fae863efe 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -25,7 +25,7 @@ static bool tst_envelope_generate const struct sieve_opcode envelope_opcode = { ext_envelope_opcode_dump, NULL }; const struct sieve_extension envelope_extension = - { "envelope", ext_envelope_validator_load, NULL, &envelope_opcode, NULL }; + { "envelope", ext_envelope_validator_load, NULL, NULL, &envelope_opcode, NULL }; static const struct sieve_command envelope_test = { "envelope", SCT_TEST, tst_envelope_registered, tst_envelope_validate, tst_envelope_generate, NULL }; diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c index f7a0cd40a..fcb23480e 100644 --- a/src/lib-sieve/ext-fileinto.c +++ b/src/lib-sieve/ext-fileinto.c @@ -22,7 +22,7 @@ const struct sieve_opcode fileinto_opcode = { ext_fileinto_opcode_dump, ext_fileinto_opcode_execute }; const struct sieve_extension fileinto_extension = - { "fileinto", ext_fileinto_validator_load, NULL, &fileinto_opcode, NULL }; + { "fileinto", ext_fileinto_validator_load, NULL, NULL, &fileinto_opcode, NULL }; static const struct sieve_command fileinto_command = { "fileinto", SCT_COMMAND, NULL, cmd_fileinto_validate, cmd_fileinto_generate, NULL }; diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c index 6784e977b..de5dd7c8a 100644 --- a/src/lib-sieve/ext-reject.c +++ b/src/lib-sieve/ext-reject.c @@ -22,7 +22,7 @@ struct sieve_opcode reject_opcode = { ext_reject_opcode_dump, NULL }; struct sieve_extension reject_extension = - { "reject", ext_reject_validator_load, ext_reject_generator_load, &reject_opcode, NULL }; + { "reject", ext_reject_validator_load, ext_reject_generator_load, NULL, &reject_opcode, NULL }; static const struct sieve_command reject_command = { "reject", SCT_COMMAND, NULL, cmd_reject_validate, cmd_reject_generate, NULL }; diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c index 50e0a4ecb..da710b1b7 100644 --- a/src/lib-sieve/plugins/vacation/ext-vacation.c +++ b/src/lib-sieve/plugins/vacation/ext-vacation.c @@ -23,7 +23,7 @@ static bool cmd_vacation_generate(struct sieve_generator *generator, struct siev const struct sieve_opcode vacation_opcode = { ext_vacation_opcode_dump, NULL }; const struct sieve_extension vacation_extension = - { "vacation", ext_vacation_validator_load, NULL, &vacation_opcode, NULL}; + { "vacation", ext_vacation_validator_load, NULL, NULL, &vacation_opcode, NULL}; static const struct sieve_command vacation_command = { "vacation", SCT_COMMAND, cmd_vacation_registered, cmd_vacation_validate, cmd_vacation_generate, NULL }; diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index 411b961f3..1097e8227 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -68,7 +68,7 @@ void sieve_binary_commit(struct sieve_binary *binary) /* Extension handling */ -static unsigned int sieve_binary_link_extension(struct sieve_binary *binary, const struct sieve_extension *extension) +static int sieve_binary_link_extension(struct sieve_binary *binary, const struct sieve_extension *extension) { array_append(&(binary->extensions), &extension, 1); @@ -87,7 +87,7 @@ const struct sieve_extension *sieve_binary_get_extension(struct sieve_binary *bi return NULL; } -unsigned int sieve_binary_register_extension +int sieve_binary_register_extension (struct sieve_binary *sbin, const struct sieve_extension *extension) { struct sieve_extension_registration *reg; @@ -101,15 +101,15 @@ unsigned int sieve_binary_register_extension return reg->opcode; } -unsigned int sieve_binary_get_extension_index +int sieve_binary_get_extension_index (struct sieve_binary *sbin, const struct sieve_extension *extension) { struct sieve_extension_registration *reg = (struct sieve_extension_registration *) hash_lookup(sbin->extension_index, extension); if ( reg == NULL ) - return sieve_binary_register_extension(sbin, extension); - + return -1; + return reg->opcode; } diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h index 7b2c7688c..7ddbc6c70 100644 --- a/src/lib-sieve/sieve-binary.h +++ b/src/lib-sieve/sieve-binary.h @@ -18,11 +18,11 @@ void sieve_binary_commit(struct sieve_binary *binary); * Extension handling */ -unsigned int sieve_binary_register_extension +int sieve_binary_register_extension (struct sieve_binary *sbin, const struct sieve_extension *extension); const struct sieve_extension *sieve_binary_get_extension (struct sieve_binary *binary, unsigned int index); -unsigned int sieve_binary_get_extension_index +int sieve_binary_get_extension_index (struct sieve_binary *sbin, const struct sieve_extension *extension); /* diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index 77ff46d32..3d727e01d 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -188,10 +188,13 @@ const struct sieve_operand stringlist_operand = /* Core operands */ +extern struct sieve_operand comparator_operand; + const struct sieve_operand *sieve_operands[] = { &number_operand, &string_operand, - &stringlist_operand + &stringlist_operand, + &comparator_operand }; const unsigned int sieve_operand_count = diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c index cb339969d..09623c04b 100644 --- a/src/lib-sieve/sieve-comparators.c +++ b/src/lib-sieve/sieve-comparators.c @@ -1,9 +1,11 @@ #include "lib.h" #include "compat.h" +#include "sieve-code.h" #include "sieve-binary.h" #include "sieve-validator.h" #include "sieve-generator.h" +#include "sieve-interpreter.h" #include "sieve-comparators.h" @@ -12,10 +14,25 @@ /* * Predeclarations */ + +static struct sieve_interpreter_registry *cmp_registry = NULL; + +static void opr_comparator_emit + (struct sieve_binary *sbin, unsigned int code); +static void opr_comparator_emit_ext + (struct sieve_binary *sbin, const struct sieve_extension *ext); + static int cmp_i_octet_compare(const void *val1, size_t val1_size, const void *val2, size_t val2_size); static int cmp_i_ascii_casemap_compare(const void *val1, size_t val1_size, const void *val2, size_t val2_size); +/* + * Comparator operand + */ + +struct sieve_operand_class comparator_class = { "comparator", NULL }; +struct sieve_operand comparator_operand = { "comparator", &comparator_class }; + /* * Comparator tag */ @@ -68,20 +85,70 @@ static bool tag_comparator_validate return TRUE; } +/* Code generation */ + static void opr_comparator_emit - (struct sieve_generator *generator, struct sieve_comparator *cmp) + (struct sieve_binary *sbin, unsigned int code) { - struct sieve_binary *sbin = sieve_generator_get_binary(generator); - (void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_COMPARATOR); - (void) sieve_binary_emit_byte(sbin, (unsigned char) cmp->code); + (void) sieve_binary_emit_byte(sbin, code); +} + +static void opr_comparator_emit_ext + (struct sieve_binary *sbin, const struct sieve_extension *ext) +{ + unsigned char cmp_code = SIEVE_COMPARATOR_CUSTOM + + sieve_binary_get_extension_index(sbin, ext); + + (void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_COMPARATOR); + (void) sieve_binary_emit_byte(sbin, cmp_code); +} + +const struct sieve_comparator *sieve_opr_comparator_read + (struct sieve_binary *sbin, sieve_size_t *address) +{ + unsigned int cmp_code; + const struct sieve_operand *operand = sieve_operand_read(sbin, address); + + if ( operand == NULL || operand->class != &comparator_class ) + return NULL; + + if ( sieve_binary_read_byte(sbin, address, &cmp_code) ) { + if ( cmp_code < SIEVE_COMPARATOR_CUSTOM ) { + if ( cmp_code < sieve_core_comparators_count ) + return sieve_core_comparators[cmp_code]; + else + return NULL; + } else { + const struct sieve_extension *ext = + sieve_binary_get_extension(sbin, cmp_code - SIEVE_COMPARATOR_CUSTOM); + + if ( ext != NULL ) + return (const struct sieve_comparator *) + sieve_interpreter_registry_get(cmp_registry, ext); + else + return NULL; + } + } + + return NULL; } static bool tag_comparator_generate (struct sieve_generator *generator, struct sieve_ast_argument **arg, struct sieve_command_context *cmd ATTR_UNUSED) { - opr_comparator_emit(generator, (struct sieve_comparator *) (*arg)->context); + struct sieve_binary *sbin = sieve_generator_get_binary(generator); + struct sieve_comparator *cmp = (struct sieve_comparator *) (*arg)->context; + + if ( cmp->extension == NULL ) { + if ( cmp->code < SIEVE_COMPARATOR_CUSTOM ) + opr_comparator_emit(sbin, cmp->code); + else + return FALSE; + } else { + opr_comparator_emit_ext(sbin, cmp->extension); + } *arg = sieve_ast_argument_next(*arg); @@ -93,14 +160,16 @@ static bool tag_comparator_generate */ const struct sieve_comparator i_octet_comparator = { - SCI_I_OCTET, "i;octet", + SIEVE_COMPARATOR_I_OCTET, + NULL, cmp_i_octet_compare }; const struct sieve_comparator i_ascii_casemap_comparator = { - SCI_I_ASCII_CASEMAP, "i;ascii-casemap", + SIEVE_COMPARATOR_I_ASCII_CASEMAP, + NULL, cmp_i_ascii_casemap_compare }; @@ -157,3 +226,14 @@ static int cmp_i_ascii_casemap_compare(const void *val1, size_t val1_size, const return result; } + +/* + * Registry + */ + +void sieve_comparators_init_registry(struct sieve_interpreter *interp) +{ + cmp_registry = sieve_interpreter_registry_init(interp, "comparators"); +} + + diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h index db804dde2..5fd8976b6 100644 --- a/src/lib-sieve/sieve-comparators.h +++ b/src/lib-sieve/sieve-comparators.h @@ -2,16 +2,17 @@ #define __SIEVE_COMPARATORS_H enum sieve_comparator_code { - SCI_I_OCTET, - SCI_I_ASCII_CASEMAP, - - SCI_CUSTOM + SIEVE_COMPARATOR_I_OCTET, + SIEVE_COMPARATOR_I_ASCII_CASEMAP, + SIEVE_COMPARATOR_CUSTOM }; struct sieve_comparator { - enum sieve_comparator_code code; const char *identifier; + enum sieve_comparator_code code; + const struct sieve_extension *extension; + /* Equality, ordering, prefix and substring match */ /* ( output similar to strncmp ) */ @@ -23,5 +24,11 @@ extern const struct sieve_argument comparator_tag; 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); + +void sieve_comparators_init_registry(struct sieve_interpreter *interp); + + #endif /* __SIEVE_COMPARATORS_H */ diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h index e0c71c717..343b2efc7 100644 --- a/src/lib-sieve/sieve-extensions.h +++ b/src/lib-sieve/sieve-extensions.h @@ -1,5 +1,5 @@ -#ifndef __SIEVE_EXTENSIONS_H__ -#define __SIEVE_EXTENSIONS_H__ +#ifndef __SIEVE_EXTENSIONS_H +#define __SIEVE_EXTENSIONS_H #include "lib.h" #include "sieve-common.h" @@ -9,6 +9,7 @@ struct sieve_extension { bool (*validator_load)(struct sieve_validator *validator); bool (*generator_load)(struct sieve_generator *generator); + bool (*interpreter_load)(struct sieve_interpreter *interpreter); const struct sieve_opcode *opcode; const struct sieve_operand *operand; @@ -16,4 +17,4 @@ struct sieve_extension { const struct sieve_extension *sieve_extension_acquire(const char *extension); -#endif /* __SIEVE_EXTENSIONS_H__ */ +#endif /* __SIEVE_EXTENSIONS_H */ diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index 4429c7e07..1ba3a74f7 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -4,6 +4,7 @@ #include "lib.h" #include "mempool.h" #include "array.h" +#include "hash.h" #include "mail-storage.h" #include "sieve-commands-private.h" @@ -18,6 +19,9 @@ struct sieve_interpreter { struct sieve_binary *binary; + /* Object registries */ + struct hash_table *registries; + /* Execution status */ sieve_size_t pc; bool test_result; @@ -30,19 +34,24 @@ struct sieve_interpreter { struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary) { pool_t pool; - struct sieve_interpreter *interpreter; + struct sieve_interpreter *interp; pool = pool_alloconly_create("sieve_interpreter", 4096); - interpreter = p_new(pool, struct sieve_interpreter, 1); - interpreter->pool = pool; + interp = p_new(pool, struct sieve_interpreter, 1); + interp->pool = pool; - interpreter->binary = binary; + interp->binary = binary; sieve_binary_ref(binary); sieve_binary_commit(binary); - interpreter->pc = 0; + interp->pc = 0; + + interp->registries = hash_create(pool, pool, 0, NULL, NULL); - return interpreter; + /* Init core functionalities */ + sieve_comparators_init_registry(interp); + + return interp; } void sieve_interpreter_free(struct sieve_interpreter *interpreter) @@ -51,6 +60,58 @@ void sieve_interpreter_free(struct sieve_interpreter *interpreter) pool_unref(&(interpreter->pool)); } +/* Object registry */ + +struct sieve_interpreter_registry { + struct sieve_interpreter *interpreter; + const char *name; + ARRAY_DEFINE(registered, void); +}; + +struct sieve_interpreter_registry * + sieve_interpreter_registry_init(struct sieve_interpreter *interp, const char *name) +{ + struct sieve_interpreter_registry *reg = (struct sieve_interpreter_registry *) + hash_lookup(interp->registries, name); + + if ( reg == NULL ) { + reg = p_new(interp->pool, struct sieve_interpreter_registry, 1); + reg->interpreter = interp; + reg->name = name; + array_create(®->registered, interp->pool, sizeof(void *), 5); + + hash_insert(interp->registries, (void *) name, (void *) reg); + } + + return reg; +} + +const void *sieve_interpreter_registry_get + (struct sieve_interpreter_registry *reg, const struct sieve_extension *ext) +{ + const void *result; + int index = sieve_binary_get_extension_index(reg->interpreter->binary, ext); + + if ( index < 0 || index > (int) array_count(®->registered) ) + return NULL; + + result = array_idx(®->registered, (unsigned int) index); + + return result; +} + +void sieve_interpreter_registry_set + (struct sieve_interpreter_registry *reg, const struct sieve_extension *ext, const void *obj) +{ + int index = sieve_binary_get_extension_index(reg->interpreter->binary, ext); + + if ( index < 0 || index > (int) array_count(®->registered) ) + return; + + array_idx_set(®->registered, (unsigned int) index, obj); +} + + /* Accessing runtinme environment */ inline struct mail *sieve_interpreter_get_mail(struct sieve_interpreter *interpreter) diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index 73f1171a4..031583349 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -2,12 +2,12 @@ #define __SIEVE_INTERPRETER_H__ #include "lib.h" +#include "array.h" #include "buffer.h" #include "mail-storage.h" #include "sieve-binary.h" - -struct sieve_coded_stringlist; +#include "sieve-code.h" struct sieve_interpreter; @@ -29,17 +29,22 @@ inline bool sieve_interpreter_get_test_result inline struct sieve_binary *sieve_interpreter_get_binary (struct sieve_interpreter *interp); +/* Object registry */ + +struct sieve_interpreter_registry; + +struct sieve_interpreter_registry * + sieve_interpreter_registry_init(struct sieve_interpreter *interp, const char *name); +const void *sieve_interpreter_registry_get + (struct sieve_interpreter_registry *reg, const struct sieve_extension *ext); +void sieve_interpreter_registry_set + (struct sieve_interpreter_registry *reg, const struct sieve_extension *ext, const void *obj); + /* Opcodes and operands */ bool sieve_interpreter_read_offset_operand (struct sieve_interpreter *interpreter, int *offset); -bool sieve_interpreter_read_number_operand - (struct sieve_interpreter *interpreter, sieve_size_t *number); -bool sieve_interpreter_read_string_operand - (struct sieve_interpreter *interpreter, string_t **str); -struct sieve_coded_stringlist *sieve_interpreter_read_stringlist_operand - (struct sieve_interpreter *interpreter); - + /* Stringlist Utility */ bool sieve_stringlist_match -- GitLab