diff options
Diffstat (limited to 'pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c')
-rw-r--r-- | pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c new file mode 100644 index 0000000..a6dd1ed --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/ext-relational-common.c @@ -0,0 +1,171 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Syntax: + + MATCH-TYPE =/ COUNT / VALUE + COUNT = ":count" relational-match + VALUE = ":value" relational-match + relational-match = DQUOTE ( "gt" / "ge" / "lt" + / "le" / "eq" / "ne" ) DQUOTE + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-code.h" +#include "sieve-extensions.h" +#include "sieve-commands.h" +#include "sieve-comparators.h" +#include "sieve-match-types.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" + +#include "ext-relational-common.h" + +/* + * Forward declarations + */ + +const struct sieve_match_type_def *rel_match_types[]; + +/* + * Validation + */ + +bool mcht_relational_validate(struct sieve_validator *valdtr, + struct sieve_ast_argument **arg, + struct sieve_match_type_context *ctx) +{ + struct sieve_match_type *mcht; + enum relational_match rel_match = REL_MATCH_INVALID; + pool_t pool = sieve_ast_argument_pool(ctx->argument); + string_t *rel_match_ident; + + /* Check syntax: + relational-match = DQUOTE ( "gt" / "ge" / "lt" + / "le" / "eq" / "ne" ) DQUOTE + + So, actually this must be a constant string and it is implemented as + such. + */ + + /* Did we get a string in the first place? */ + if (*arg == NULL || (*arg)->type != SAAT_STRING) { + sieve_argument_validate_error( + valdtr, (*arg == NULL ? ctx->argument : *arg), + "the :%s match-type requires a constant string argument being " + "one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", " + "but %s was found", + sieve_match_type_name(ctx->match_type), + (*arg == NULL ? + "none" : sieve_ast_argument_name(*arg))); + return FALSE; + } + + /* Check the relational match id */ + + rel_match_ident = sieve_ast_argument_str(*arg); + if (str_len(rel_match_ident) == 2) { + const char *rel_match_id = str_c(rel_match_ident); + + switch (rel_match_id[0]) { + /* "gt" or "ge" */ + case 'g': + switch (rel_match_id[1]) { + case 't': + rel_match = REL_MATCH_GREATER; + break; + case 'e': + rel_match = REL_MATCH_GREATER_EQUAL; + break; + default: + rel_match = REL_MATCH_INVALID; + } + break; + /* "lt" or "le" */ + case 'l': + switch (rel_match_id[1]) { + case 't': + rel_match = REL_MATCH_LESS; + break; + case 'e': + rel_match = REL_MATCH_LESS_EQUAL; + break; + default: + rel_match = REL_MATCH_INVALID; + } + break; + /* "eq" */ + case 'e': + if (rel_match_id[1] == 'q') + rel_match = REL_MATCH_EQUAL; + else + rel_match = REL_MATCH_INVALID; + break; + /* "ne" */ + case 'n': + if (rel_match_id[1] == 'e') + rel_match = REL_MATCH_NOT_EQUAL; + else + rel_match = REL_MATCH_INVALID; + break; + /* invalid */ + default: + rel_match = REL_MATCH_INVALID; + } + } + + if (rel_match >= REL_MATCH_INVALID) { + sieve_argument_validate_error( + valdtr, *arg, + "the :%s match-type requires a constant string argument being " + "one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", " + "but \"%s\" was found", + sieve_match_type_name(ctx->match_type), + str_sanitize(str_c(rel_match_ident), 32)); + return FALSE; + } + + /* Delete argument */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + /* Not used just yet */ + ctx->ctx_data = (void *) rel_match; + + /* Override the actual match type with a parameter-specific one + * FIXME: ugly! + */ + mcht = p_new(pool, struct sieve_match_type, 1); + mcht->object.ext = ctx->match_type->object.ext; + SIEVE_OBJECT_SET_DEF(mcht, rel_match_types[ + REL_MATCH_INDEX(ctx->match_type->object.def->code, rel_match)]); + ctx->match_type = mcht; + + return TRUE; +} + +/* + * Relational match-type operand + */ + +const struct sieve_match_type_def *rel_match_types[] = { + &rel_match_value_gt, &rel_match_value_ge, &rel_match_value_lt, + &rel_match_value_le, &rel_match_value_eq, &rel_match_value_ne, + &rel_match_count_gt, &rel_match_count_ge, &rel_match_count_lt, + &rel_match_count_le, &rel_match_count_eq, &rel_match_count_ne, +}; + +static const struct sieve_extension_objects ext_match_types = + SIEVE_EXT_DEFINE_MATCH_TYPES(rel_match_types); + +const struct sieve_operand_def rel_match_type_operand = { + .name = "relational match", + .ext_def = &relational_extension, + .class = &sieve_match_type_operand_class, + .interface = &ext_match_types, +}; |