diff options
Diffstat (limited to 'pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c')
-rw-r--r-- | pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c b/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c new file mode 100644 index 0000000..e31a63a --- /dev/null +++ b/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +/* Match-type ':count' + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-stringlist.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 "sieve-runtime-trace.h" +#include "sieve-match.h" + +#include "ext-relational-common.h" + +/* + * Forward declarations + */ + +static int mcht_count_match + (struct sieve_match_context *mctx, struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list); + +/* + * Match-type objects + */ + +const struct sieve_match_type_def count_match_type = { + SIEVE_OBJECT("count", + &rel_match_type_operand, RELATIONAL_COUNT), + .validate = mcht_relational_validate +}; + +#define COUNT_MATCH_TYPE(name, rel_match) \ +const struct sieve_match_type_def rel_match_count_ ## name = { \ + SIEVE_OBJECT("count-" #name, \ + &rel_match_type_operand, \ + REL_MATCH_INDEX(RELATIONAL_COUNT, rel_match)), \ + .match = mcht_count_match, \ +} + +COUNT_MATCH_TYPE(gt, REL_MATCH_GREATER); +COUNT_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL); +COUNT_MATCH_TYPE(lt, REL_MATCH_LESS); +COUNT_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL); +COUNT_MATCH_TYPE(eq, REL_MATCH_EQUAL); +COUNT_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL); + +/* + * Match-type implementation + */ + +static int mcht_count_match +(struct sieve_match_context *mctx, struct sieve_stringlist *value_list, + struct sieve_stringlist *key_list) +{ + const struct sieve_runtime_env *renv = mctx->runenv; + bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); + int count; + string_t *key_item; + int match, ret; + + if ( (count=sieve_stringlist_get_length(value_list)) < 0 ) { + mctx->exec_status = value_list->exec_status; + return -1; + } + + sieve_stringlist_reset(key_list); + + string_t *value = t_str_new(20); + str_printfa(value, "%d", count); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "matching count value `%s'", str_sanitize(str_c(value), 80)); + } + + sieve_runtime_trace_descend(renv); + + /* Match to all key values */ + key_item = NULL; + match = 0; + while ( match == 0 && + (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) + { + match = mcht_value_match_key + (mctx, str_c(value), str_len(value), str_c(key_item), str_len(key_item)); + + if ( trace ) { + sieve_runtime_trace(renv, 0, + "with key `%s' => %d", str_sanitize(str_c(key_item), 80), ret); + } + } + + sieve_runtime_trace_ascend(renv); + + if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } + + return match; +} + + + + + |