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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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,
};
|