1
/* Copyright (c) 2002-2009 Dovecot Sieve authors, see the included COPYING file
5
#include "str-sanitize.h"
7
#include "sieve-common.h"
8
#include "sieve-commands.h"
9
#include "sieve-code.h"
10
#include "sieve-comparators.h"
11
#include "sieve-match-types.h"
12
#include "sieve-address-parts.h"
13
#include "sieve-validator.h"
14
#include "sieve-generator.h"
15
#include "sieve-interpreter.h"
16
#include "sieve-dump.h"
17
#include "sieve-match.h"
25
* address [ADDRESS-PART] [COMPARATOR] [MATCH-TYPE]
26
* <header-list: string-list> <key-list: string-list>
29
static bool tst_address_registered
30
(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg);
31
static bool tst_address_validate
32
(struct sieve_validator *valdtr, struct sieve_command_context *tst);
33
static bool tst_address_generate
34
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
36
const struct sieve_command tst_address = {
40
tst_address_registered,
51
static bool tst_address_operation_dump
52
(const struct sieve_operation *op,
53
const struct sieve_dumptime_env *denv, sieve_size_t *address);
54
static int tst_address_operation_execute
55
(const struct sieve_operation *op,
56
const struct sieve_runtime_env *renv, sieve_size_t *address);
58
const struct sieve_operation tst_address_operation = {
61
SIEVE_OPERATION_ADDRESS,
62
tst_address_operation_dump,
63
tst_address_operation_execute
70
static bool tst_address_registered
71
(struct sieve_validator *valdtr, struct sieve_command_registration *cmd_reg)
73
/* The order of these is not significant */
74
sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_AM_OPT_COMPARATOR );
75
sieve_address_parts_link_tags(valdtr, cmd_reg, SIEVE_AM_OPT_ADDRESS_PART);
76
sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_AM_OPT_MATCH_TYPE);
85
/* List of valid headers:
86
* Implementations MUST restrict the address test to headers that
87
* contain addresses, but MUST include at least From, To, Cc, Bcc,
88
* Sender, Resent-From, and Resent-To, and it SHOULD include any other
89
* header that utilizes an "address-list" structured header body.
91
* This list explicitly does not contain the envelope-to and return-path
92
* headers. The envelope test must be used to test against these addresses.
94
* FIXME: this restriction is somewhat odd. Sieve list advises to allow
95
* any other header as long as its content matches the address-list
98
static const char * const _allowed_headers[] = {
100
"from", "to", "cc", "bcc", "sender", "resent-from", "resent-to",
102
/* Additional (RFC 822 / RFC 2822) */
103
"reply-to", "resent-reply-to", "resent-sender", "resent-cc", "resent-bcc",
105
/* Non-standard (RFC 2076, draft-palme-mailext-headers-08.txt) */
106
"for-approval", "for-handling", "for-comment", "apparently-to", "errors-to",
107
"delivered-to", "return-receipt-to", "x-admin", "read-receipt-to",
108
"x-confirm-reading-to", "return-receipt-requested",
109
"registered-mail-reply-requested-by", "mail-followup-to", "mail-reply-to",
110
"abuse-reports-to", "x-complaints-to", "x-report-abuse-to",
118
static int _header_is_allowed
119
(void *context ATTR_UNUSED, struct sieve_ast_argument *arg)
121
if ( sieve_argument_is_string_literal(arg) ) {
122
const char *header = sieve_ast_strlist_strc(arg);
124
const char * const *hdsp = _allowed_headers;
125
while ( *hdsp != NULL ) {
126
if ( strcasecmp( *hdsp, header ) == 0 )
138
static bool tst_address_validate
139
(struct sieve_validator *valdtr, struct sieve_command_context *tst)
141
struct sieve_ast_argument *arg = tst->first_positional;
142
struct sieve_ast_argument *header;
144
if ( !sieve_validate_positional_argument
145
(valdtr, tst, arg, "header list", 1, SAAT_STRING_LIST) ) {
149
if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
152
if ( !sieve_command_verify_headers_argument(valdtr, arg) )
155
/* Check if supplied header names are allowed
156
* FIXME: verify dynamic header names at runtime
159
if ( !sieve_ast_stringlist_map(&header, NULL, _header_is_allowed) ) {
160
sieve_argument_validate_error(valdtr, header,
161
"specified header '%s' is not allowed for the address test",
162
str_sanitize(sieve_ast_strlist_strc(header), 64));
168
arg = sieve_ast_argument_next(arg);
170
if ( !sieve_validate_positional_argument
171
(valdtr, tst, arg, "key list", 2, SAAT_STRING_LIST) ) {
175
if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
178
/* Validate the key argument to a specified match type */
179
return sieve_match_type_validate
180
(valdtr, tst, arg, &is_match_type, &i_ascii_casemap_comparator);
187
static bool tst_address_generate
188
(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx)
190
sieve_operation_emit_code(cgenv->sbin, &tst_address_operation);
192
/* Generate arguments */
193
return sieve_generate_arguments(cgenv, ctx, NULL);
200
static bool tst_address_operation_dump
201
(const struct sieve_operation *op ATTR_UNUSED,
202
const struct sieve_dumptime_env *denv, sieve_size_t *address)
204
sieve_code_dumpf(denv, "ADDRESS");
205
sieve_code_descend(denv);
207
/* Handle any optional arguments */
208
if ( !sieve_addrmatch_default_dump_optionals(denv, address) )
212
sieve_opr_stringlist_dump(denv, address, "header list") &&
213
sieve_opr_stringlist_dump(denv, address, "key list");
220
static int tst_address_operation_execute
221
(const struct sieve_operation *op ATTR_UNUSED,
222
const struct sieve_runtime_env *renv, sieve_size_t *address)
225
const struct sieve_comparator *cmp = &i_ascii_casemap_comparator;
226
const struct sieve_match_type *mtch = &is_match_type;
227
const struct sieve_address_part *addrp = &all_address_part;
228
struct sieve_match_context *mctx;
229
struct sieve_coded_stringlist *hdr_list;
230
struct sieve_coded_stringlist *key_list;
235
/* Read optional operands */
236
if ( (ret=sieve_addrmatch_default_get_optionals
237
(renv, address, &addrp, &mtch, &cmp)) <= 0 )
240
/* Read header-list */
241
if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
242
sieve_runtime_trace_error(renv, "invalid header-list operand");
243
return SIEVE_EXEC_BIN_CORRUPT;
247
if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
248
sieve_runtime_trace_error(renv, "invalid key-list operand");
249
return SIEVE_EXEC_BIN_CORRUPT;
252
sieve_runtime_trace(renv, "ADDRESS test");
254
/* Initialize match context */
255
mctx = sieve_match_begin(renv->interp, mtch, cmp, NULL, key_list);
257
/* Iterate through all requested headers to match */
260
while ( result && !matched &&
261
(result=sieve_coded_stringlist_next_item(hdr_list, &hdr_item))
262
&& hdr_item != NULL ) {
263
const char *const *headers;
265
if ( mail_get_headers_utf8(renv->msgdata->mail, str_c(hdr_item), &headers) >= 0 ) {
268
for ( i = 0; !matched && headers[i] != NULL; i++ ) {
269
if ( (ret=sieve_address_match(addrp, mctx, headers[i])) < 0 ) {
281
if ( (ret=sieve_match_end(&mctx)) < 0 )
284
matched = ( ret > 0 || matched );
286
/* Set test result for subsequent conditional jump */
288
sieve_interpreter_set_test_result(renv->interp, matched);
289
return SIEVE_EXEC_OK;
292
sieve_runtime_trace_error(renv, "invalid string-list item");
293
return SIEVE_EXEC_BIN_CORRUPT;