1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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;
}
|