/src/pigeonhole/src/lib-sieve/plugins/relational/mcht-count.c
Line | Count | Source |
1 | | /* Copyright (c) Pigeonhole authors, see top-level COPYING file */ |
2 | | |
3 | | /* Match-type ':count' |
4 | | */ |
5 | | |
6 | | #include "lib.h" |
7 | | #include "str.h" |
8 | | #include "str-sanitize.h" |
9 | | |
10 | | #include "sieve-common.h" |
11 | | #include "sieve-ast.h" |
12 | | #include "sieve-stringlist.h" |
13 | | #include "sieve-code.h" |
14 | | #include "sieve-extensions.h" |
15 | | #include "sieve-commands.h" |
16 | | #include "sieve-comparators.h" |
17 | | #include "sieve-match-types.h" |
18 | | #include "sieve-validator.h" |
19 | | #include "sieve-generator.h" |
20 | | #include "sieve-interpreter.h" |
21 | | #include "sieve-runtime-trace.h" |
22 | | #include "sieve-match.h" |
23 | | |
24 | | #include "ext-relational-common.h" |
25 | | |
26 | | /* |
27 | | * Forward declarations |
28 | | */ |
29 | | |
30 | | static int |
31 | | mcht_count_match(struct sieve_match_context *mctx, |
32 | | struct sieve_stringlist *value_list, |
33 | | struct sieve_stringlist *key_list); |
34 | | |
35 | | /* |
36 | | * Match-type objects |
37 | | */ |
38 | | |
39 | | const struct sieve_match_type_def count_match_type = { |
40 | | SIEVE_OBJECT("count", |
41 | | &rel_match_type_operand, RELATIONAL_COUNT), |
42 | | .validate = mcht_relational_validate, |
43 | | }; |
44 | | |
45 | | #define COUNT_MATCH_TYPE(name, rel_match) \ |
46 | | const struct sieve_match_type_def rel_match_count_ ## name = { \ |
47 | | SIEVE_OBJECT("count-" #name, \ |
48 | | &rel_match_type_operand, \ |
49 | | REL_MATCH_INDEX(RELATIONAL_COUNT, rel_match)), \ |
50 | | .match = mcht_count_match, \ |
51 | | } |
52 | | |
53 | | COUNT_MATCH_TYPE(gt, REL_MATCH_GREATER); |
54 | | COUNT_MATCH_TYPE(ge, REL_MATCH_GREATER_EQUAL); |
55 | | COUNT_MATCH_TYPE(lt, REL_MATCH_LESS); |
56 | | COUNT_MATCH_TYPE(le, REL_MATCH_LESS_EQUAL); |
57 | | COUNT_MATCH_TYPE(eq, REL_MATCH_EQUAL); |
58 | | COUNT_MATCH_TYPE(ne, REL_MATCH_NOT_EQUAL); |
59 | | |
60 | | /* |
61 | | * Match-type implementation |
62 | | */ |
63 | | |
64 | | static int |
65 | | mcht_count_match(struct sieve_match_context *mctx, |
66 | | struct sieve_stringlist *value_list, |
67 | | struct sieve_stringlist *key_list) |
68 | 0 | { |
69 | 0 | const struct sieve_runtime_env *renv = mctx->runenv; |
70 | 0 | bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); |
71 | 0 | int count; |
72 | 0 | string_t *key_item; |
73 | 0 | int match, ret; |
74 | |
|
75 | 0 | count = sieve_stringlist_get_length(value_list); |
76 | 0 | if (count < 0) { |
77 | 0 | mctx->exec_status = value_list->exec_status; |
78 | 0 | return -1; |
79 | 0 | } |
80 | | |
81 | 0 | sieve_stringlist_reset(key_list); |
82 | |
|
83 | 0 | string_t *value = t_str_new(20); |
84 | 0 | str_printfa(value, "%d", count); |
85 | |
|
86 | 0 | if (trace) { |
87 | 0 | sieve_runtime_trace(renv, 0, "matching count value '%s'", |
88 | 0 | str_sanitize(str_c(value), 80)); |
89 | 0 | } |
90 | |
|
91 | 0 | sieve_runtime_trace_descend(renv); |
92 | | |
93 | | /* Match to all key values */ |
94 | 0 | key_item = NULL; |
95 | 0 | match = 0; |
96 | 0 | while (match == 0 && |
97 | 0 | (ret = sieve_stringlist_next_item(key_list, &key_item)) > 0) |
98 | 0 | { |
99 | 0 | match = mcht_value_match_key( |
100 | 0 | mctx, str_c(value), str_len(value), |
101 | 0 | str_c(key_item), str_len(key_item)); |
102 | |
|
103 | 0 | if (trace) { |
104 | 0 | sieve_runtime_trace(renv, 0, "with key '%s' => %d", |
105 | 0 | str_sanitize(str_c(key_item), 80), |
106 | 0 | ret); |
107 | 0 | } |
108 | 0 | } |
109 | |
|
110 | 0 | sieve_runtime_trace_ascend(renv); |
111 | |
|
112 | 0 | if (ret < 0) { |
113 | 0 | mctx->exec_status = key_list->exec_status; |
114 | 0 | match = -1; |
115 | 0 | } |
116 | 0 | return match; |
117 | 0 | } |