diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /pigeonhole/src/testsuite/testsuite-objects.c | |
parent | Initial commit. (diff) | |
download | dovecot-upstream.tar.xz dovecot-upstream.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pigeonhole/src/testsuite/testsuite-objects.c')
-rw-r--r-- | pigeonhole/src/testsuite/testsuite-objects.c | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/pigeonhole/src/testsuite/testsuite-objects.c b/pigeonhole/src/testsuite/testsuite-objects.c new file mode 100644 index 0000000..4c09c85 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-objects.c @@ -0,0 +1,369 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "string.h" +#include "ostream.h" +#include "hash.h" +#include "mail-storage.h" + +#include "sieve.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-extensions.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-binary.h" +#include "sieve-dump.h" + +#include "testsuite-common.h" +#include "testsuite-objects.h" +#include "testsuite-message.h" + +/* + * Testsuite core objects + */ + +enum testsuite_object_code { + TESTSUITE_OBJECT_MESSAGE, + TESTSUITE_OBJECT_ENVELOPE +}; + +const struct testsuite_object_def *testsuite_core_objects[] = { + &message_testsuite_object, &envelope_testsuite_object +}; + +const unsigned int testsuite_core_objects_count = + N_ELEMENTS(testsuite_core_objects); + +/* + * Testsuite object registry + */ + +static inline struct sieve_validator_object_registry *_get_object_registry +(struct sieve_validator *valdtr) +{ + struct testsuite_validator_context *ctx = + testsuite_validator_context_get(valdtr); + + return ctx->object_registrations; +} + +void testsuite_object_register +(struct sieve_validator *valdtr, const struct sieve_extension *ext, + const struct testsuite_object_def *tobj_def) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + + sieve_validator_object_registry_add(regs, ext, &tobj_def->obj_def); +} + +static const struct testsuite_object *testsuite_object_create +(struct sieve_validator *valdtr, struct sieve_command *cmd, + const char *identifier) +{ + struct sieve_validator_object_registry *regs = _get_object_registry(valdtr); + struct sieve_object object; + struct testsuite_object *tobj; + + if ( !sieve_validator_object_registry_find(regs, identifier, &object) ) + return NULL; + + tobj = p_new(sieve_command_pool(cmd), struct testsuite_object, 1); + tobj->object = object; + tobj->def = (const struct testsuite_object_def *) object.def; + + return tobj; +} + +void testsuite_register_core_objects +(struct testsuite_validator_context *ctx) +{ + struct sieve_validator_object_registry *regs = ctx->object_registrations; + unsigned int i; + + /* Register core testsuite objects */ + for ( i = 0; i < testsuite_core_objects_count; i++ ) { + const struct testsuite_object_def *tobj_def = testsuite_core_objects[i]; + + sieve_validator_object_registry_add + (regs, testsuite_ext, &tobj_def->obj_def); + } +} + +/* + * Testsuite object code + */ + +const struct sieve_operand_class sieve_testsuite_object_operand_class = + { "testsuite object" }; + +static const struct sieve_extension_objects core_testsuite_objects = + SIEVE_EXT_DEFINE_OBJECTS(testsuite_core_objects); + +const struct sieve_operand_def testsuite_object_operand = { + .name = "testsuite-object", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERAND_OBJECT, + .class = &sieve_testsuite_object_operand_class, + .interface = &core_testsuite_objects +}; + +static void testsuite_object_emit +(struct sieve_binary_block *sblock, const struct testsuite_object *tobj, + int member_id) +{ + sieve_opr_object_emit(sblock, tobj->object.ext, tobj->object.def); + + if ( tobj->def != NULL && tobj->def->get_member_id != NULL ) { + (void) sieve_binary_emit_byte(sblock, (unsigned char) member_id); + } +} + +bool testsuite_object_read +(struct sieve_binary_block *sblock, sieve_size_t *address, + struct testsuite_object *tobj) +{ + struct sieve_operand oprnd; + + if ( !sieve_operand_read(sblock, address, NULL, &oprnd) ) + return FALSE; + + if ( !sieve_opr_object_read_data + (sblock, &oprnd, &sieve_testsuite_object_operand_class, address, + &tobj->object) ) + return FALSE; + + tobj->def = (const struct testsuite_object_def *) tobj->object.def; + i_assert(tobj->def != NULL); + return TRUE; +} + +bool testsuite_object_read_member +(struct sieve_binary_block *sblock, sieve_size_t *address, + struct testsuite_object *tobj, int *member_id_r) +{ + if ( !testsuite_object_read(sblock, address, tobj) ) + return FALSE; + + *member_id_r = -1; + if ( tobj->def->get_member_id != NULL ) { + if ( !sieve_binary_read_code(sblock, address, member_id_r) ) + return FALSE; + } + + return TRUE; +} + +const char *testsuite_object_member_name +(const struct testsuite_object *object, int member_id) +{ + const struct testsuite_object_def *obj_def = object->def; + const char *member = NULL; + + if ( obj_def->get_member_id != NULL ) { + if ( obj_def->get_member_name != NULL ) + member = obj_def->get_member_name(member_id); + } else + return obj_def->obj_def.identifier; + + if ( member == NULL ) + return t_strdup_printf("%s.%d", obj_def->obj_def.identifier, member_id); + + return t_strdup_printf("%s.%s", obj_def->obj_def.identifier, member); +} + +bool testsuite_object_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + struct testsuite_object object; + int member_id; + + sieve_code_mark(denv); + + if ( !testsuite_object_read_member + (denv->sblock, address, &object, &member_id) ) + return FALSE; + + sieve_code_dumpf(denv, "%s: %s", + sieve_testsuite_object_operand_class.name, + testsuite_object_member_name(&object, member_id)); + + return TRUE; +} + +/* + * Testsuite object argument + */ + +static bool arg_testsuite_object_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd); + +const struct sieve_argument_def testsuite_object_argument = { + .identifier = "testsuite-object", + .generate = arg_testsuite_object_generate +}; + +struct testsuite_object_argctx { + const struct testsuite_object *object; + int member; +}; + +bool testsuite_object_argument_activate +(struct sieve_validator *valdtr, struct sieve_ast_argument *arg, + struct sieve_command *cmd) +{ + const char *objname = sieve_ast_argument_strc(arg); + const struct testsuite_object *tobj; + int member_id; + const char *member; + struct testsuite_object_argctx *ctx; + + /* Parse the object specifier */ + + member = strchr(objname, '.'); + if ( member != NULL ) { + objname = t_strdup_until(objname, member); + member++; + } + + /* Find the object */ + + tobj = testsuite_object_create(valdtr, cmd, objname); + if ( tobj == NULL ) { + sieve_argument_validate_error(valdtr, arg, + "unknown testsuite object '%s'", objname); + return FALSE; + } + + /* Find the object member */ + + member_id = -1; + if ( member != NULL ) { + if ( tobj->def == NULL || tobj->def->get_member_id == NULL || + (member_id=tobj->def->get_member_id(member)) == -1 ) { + sieve_argument_validate_error(valdtr, arg, + "member '%s' does not exist for testsuite object '%s'", member, objname); + return FALSE; + } + } + + /* Assign argument context */ + + ctx = p_new(sieve_command_pool(cmd), struct testsuite_object_argctx, 1); + ctx->object = tobj; + ctx->member = member_id; + + arg->argument = sieve_argument_create + (arg->ast, &testsuite_object_argument, testsuite_ext, 0); + arg->argument->data = (void *) ctx; + + return TRUE; +} + +static bool arg_testsuite_object_generate + (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, + struct sieve_command *cmd ATTR_UNUSED) +{ + struct testsuite_object_argctx *ctx = + (struct testsuite_object_argctx *) arg->argument->data; + + testsuite_object_emit(cgenv->sblock, ctx->object, ctx->member); + + return TRUE; +} + +/* + * Testsuite core object implementation + */ + +static bool tsto_message_set_member + (const struct sieve_runtime_env *renv, int id, string_t *value); + +static int tsto_envelope_get_member_id(const char *identifier); +static const char *tsto_envelope_get_member_name(int id); +static bool tsto_envelope_set_member + (const struct sieve_runtime_env *renv, int id, string_t *value); + +const struct testsuite_object_def message_testsuite_object = { + SIEVE_OBJECT("message", + &testsuite_object_operand, TESTSUITE_OBJECT_MESSAGE), + .set_member = tsto_message_set_member +}; + +const struct testsuite_object_def envelope_testsuite_object = { + SIEVE_OBJECT("envelope", + &testsuite_object_operand, TESTSUITE_OBJECT_ENVELOPE), + .get_member_id = tsto_envelope_get_member_id, + .get_member_name = tsto_envelope_get_member_name, + .set_member = tsto_envelope_set_member +}; + +enum testsuite_object_envelope_field { + TESTSUITE_OBJECT_ENVELOPE_FROM, + TESTSUITE_OBJECT_ENVELOPE_TO, + TESTSUITE_OBJECT_ENVELOPE_ORIG_TO, + TESTSUITE_OBJECT_ENVELOPE_AUTH_USER +}; + +static bool tsto_message_set_member +(const struct sieve_runtime_env *renv, int id, string_t *value) +{ + if ( id != -1 ) return FALSE; + + testsuite_message_set_string(renv, value); + + return TRUE; +} + +static int tsto_envelope_get_member_id(const char *identifier) +{ + if ( strcasecmp(identifier, "from") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_FROM; + if ( strcasecmp(identifier, "to") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_TO; + if ( strcasecmp(identifier, "orig_to") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_ORIG_TO; + if ( strcasecmp(identifier, "auth") == 0 ) + return TESTSUITE_OBJECT_ENVELOPE_AUTH_USER; + + return -1; +} + +static const char *tsto_envelope_get_member_name(int id) +{ + switch ( id ) { + case TESTSUITE_OBJECT_ENVELOPE_FROM: + return "from"; + case TESTSUITE_OBJECT_ENVELOPE_TO: + return "to"; + case TESTSUITE_OBJECT_ENVELOPE_ORIG_TO: + return "orig_to"; + case TESTSUITE_OBJECT_ENVELOPE_AUTH_USER: + return "auth"; + } + + return NULL; +} + +static bool tsto_envelope_set_member +(const struct sieve_runtime_env *renv, int id, string_t *value) +{ + switch ( id ) { + case TESTSUITE_OBJECT_ENVELOPE_FROM: + testsuite_envelope_set_sender(renv, str_c(value)); + return TRUE; + case TESTSUITE_OBJECT_ENVELOPE_TO: + testsuite_envelope_set_recipient(renv, str_c(value)); + return TRUE; + case TESTSUITE_OBJECT_ENVELOPE_ORIG_TO: + testsuite_envelope_set_orig_recipient(renv, str_c(value)); + return TRUE; + case TESTSUITE_OBJECT_ENVELOPE_AUTH_USER: + testsuite_envelope_set_auth_user(renv, str_c(value)); + return TRUE; + } + + return FALSE; +} |