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