/src/pigeonhole/src/lib-sieve/ext-envelope.c
Line | Count | Source |
1 | | /* Copyright (c) Pigeonhole authors, see top-level COPYING file */ |
2 | | |
3 | | /* Extension envelope |
4 | | * ------------------ |
5 | | * |
6 | | * Authors: Stephan Bosch |
7 | | * Specification: RFC 5228 |
8 | | * Implementation: full |
9 | | * Status: testing |
10 | | * |
11 | | */ |
12 | | |
13 | | #include "lib.h" |
14 | | #include "str-sanitize.h" |
15 | | #include "array.h" |
16 | | |
17 | | #include "sieve-common.h" |
18 | | #include "sieve-extensions.h" |
19 | | #include "sieve-commands.h" |
20 | | #include "sieve-stringlist.h" |
21 | | #include "sieve-code.h" |
22 | | #include "sieve-address.h" |
23 | | #include "sieve-comparators.h" |
24 | | #include "sieve-match-types.h" |
25 | | #include "sieve-address-parts.h" |
26 | | #include "sieve-message.h" |
27 | | |
28 | | #include "sieve-validator.h" |
29 | | #include "sieve-generator.h" |
30 | | #include "sieve-interpreter.h" |
31 | | #include "sieve-dump.h" |
32 | | #include "sieve-match.h" |
33 | | |
34 | | /* |
35 | | * Forward declarations |
36 | | */ |
37 | | |
38 | | static const struct sieve_command_def envelope_test; |
39 | | const struct sieve_operation_def envelope_operation; |
40 | | const struct sieve_extension_def envelope_extension; |
41 | | |
42 | | /* |
43 | | * Extension |
44 | | */ |
45 | | |
46 | | static bool |
47 | | ext_envelope_validator_load(const struct sieve_extension *ext, |
48 | | struct sieve_validator *valdtr); |
49 | | static bool |
50 | | ext_envelope_interpreter_load(const struct sieve_extension *ext, |
51 | | const struct sieve_runtime_env *renv, |
52 | | sieve_size_t *address); |
53 | | |
54 | | static bool |
55 | | ext_envelope_validator_validate(const struct sieve_extension *ext, |
56 | | struct sieve_validator *valdtr, void *context, |
57 | | struct sieve_ast_argument *require_arg, |
58 | | bool required); |
59 | | static int |
60 | | ext_envelope_interpreter_run(const struct sieve_extension *this_ext, |
61 | | const struct sieve_runtime_env *renv, |
62 | | void *context, bool deferred); |
63 | | |
64 | | const struct sieve_extension_def envelope_extension = { |
65 | | .name = "envelope", |
66 | | .interpreter_load = ext_envelope_interpreter_load, |
67 | | .validator_load = ext_envelope_validator_load, |
68 | | SIEVE_EXT_DEFINE_OPERATION(envelope_operation) |
69 | | }; |
70 | | const struct sieve_validator_extension |
71 | | envelope_validator_extension = { |
72 | | .ext = &envelope_extension, |
73 | | .validate = ext_envelope_validator_validate |
74 | | }; |
75 | | const struct sieve_interpreter_extension |
76 | | envelope_interpreter_extension = { |
77 | | .ext_def = &envelope_extension, |
78 | | .run = ext_envelope_interpreter_run |
79 | | }; |
80 | | |
81 | | static bool |
82 | | ext_envelope_validator_load(const struct sieve_extension *ext, |
83 | | struct sieve_validator *valdtr) |
84 | 0 | { |
85 | | /* Register new test */ |
86 | 0 | sieve_validator_register_command(valdtr, ext, &envelope_test); |
87 | |
|
88 | 0 | sieve_validator_extension_register(valdtr, ext, |
89 | 0 | &envelope_validator_extension, NULL); |
90 | 0 | return TRUE; |
91 | 0 | } |
92 | | |
93 | | static bool |
94 | | ext_envelope_interpreter_load(const struct sieve_extension *ext, |
95 | | const struct sieve_runtime_env *renv, |
96 | | sieve_size_t *address ATTR_UNUSED) |
97 | 0 | { |
98 | 0 | sieve_interpreter_extension_register(renv->interp, ext, |
99 | 0 | &envelope_interpreter_extension, |
100 | 0 | NULL); |
101 | 0 | return TRUE; |
102 | 0 | } |
103 | | |
104 | | static bool |
105 | | ext_envelope_validator_validate(const struct sieve_extension *ext, |
106 | | struct sieve_validator *valdtr, |
107 | | void *context ATTR_UNUSED, |
108 | | struct sieve_ast_argument *require_arg, |
109 | | bool required) |
110 | 0 | { |
111 | 0 | if (required) { |
112 | 0 | enum sieve_compile_flags flags = |
113 | 0 | sieve_validator_compile_flags(valdtr); |
114 | |
|
115 | 0 | if ((flags & SIEVE_COMPILE_FLAG_NO_ENVELOPE) != 0) { |
116 | 0 | sieve_argument_validate_error( |
117 | 0 | valdtr, require_arg, |
118 | 0 | "the %s extension cannot be used in this context " |
119 | 0 | "(needs access to message envelope)", |
120 | 0 | sieve_extension_name(ext)); |
121 | 0 | return FALSE; |
122 | 0 | } |
123 | 0 | } |
124 | 0 | return TRUE; |
125 | 0 | } |
126 | | |
127 | | static int |
128 | | ext_envelope_interpreter_run(const struct sieve_extension *ext, |
129 | | const struct sieve_runtime_env *renv, |
130 | | void *context ATTR_UNUSED, bool deferred) |
131 | 0 | { |
132 | 0 | const struct sieve_execute_env *eenv = renv->exec_env; |
133 | |
|
134 | 0 | if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) != 0) { |
135 | 0 | if (!deferred) { |
136 | 0 | sieve_runtime_error( |
137 | 0 | renv, NULL, |
138 | 0 | "the %s extension cannot be used in this context " |
139 | 0 | "(needs access to message envelope)", |
140 | 0 | sieve_extension_name(ext)); |
141 | 0 | } |
142 | 0 | return SIEVE_EXEC_FAILURE; |
143 | 0 | } |
144 | 0 | return SIEVE_EXEC_OK; |
145 | 0 | } |
146 | | |
147 | | /* |
148 | | * Envelope test |
149 | | * |
150 | | * Syntax |
151 | | * envelope [COMPARATOR] [ADDRESS-PART] [MATCH-TYPE] |
152 | | * <envelope-part: string-list> <key-list: string-list> |
153 | | */ |
154 | | |
155 | | static bool |
156 | | tst_envelope_registered(struct sieve_validator *valdtr, |
157 | | const struct sieve_extension *ext, |
158 | | struct sieve_command_registration *cmd_reg); |
159 | | static bool |
160 | | tst_envelope_validate(struct sieve_validator *valdtr, |
161 | | struct sieve_command *tst); |
162 | | static bool |
163 | | tst_envelope_generate(const struct sieve_codegen_env *cgenv, |
164 | | struct sieve_command *ctx); |
165 | | |
166 | | static const struct sieve_command_def envelope_test = { |
167 | | .identifier = "envelope", |
168 | | .type = SCT_TEST, |
169 | | .positional_args= 2, |
170 | | .subtests = 0, |
171 | | .block_allowed = FALSE, |
172 | | .block_required = FALSE, |
173 | | .registered = tst_envelope_registered, |
174 | | .validate = tst_envelope_validate, |
175 | | .generate = tst_envelope_generate |
176 | | }; |
177 | | |
178 | | /* |
179 | | * Envelope operation |
180 | | */ |
181 | | |
182 | | static bool |
183 | | ext_envelope_operation_dump(const struct sieve_dumptime_env *denv, |
184 | | sieve_size_t *address); |
185 | | static int |
186 | | ext_envelope_operation_execute(const struct sieve_runtime_env *renv, |
187 | | sieve_size_t *address); |
188 | | |
189 | | const struct sieve_operation_def envelope_operation = { |
190 | | .mnemonic = "ENVELOPE", |
191 | | .ext_def = &envelope_extension, |
192 | | .dump = ext_envelope_operation_dump, |
193 | | .execute = ext_envelope_operation_execute |
194 | | }; |
195 | | |
196 | | /* |
197 | | * Envelope parts |
198 | | * |
199 | | * FIXME: not available to extensions |
200 | | */ |
201 | | |
202 | | struct sieve_envelope_part { |
203 | | const char *identifier; |
204 | | |
205 | | const struct smtp_address *const *(*get_addresses) |
206 | | (const struct sieve_runtime_env *renv); |
207 | | const char *const *(*get_values) |
208 | | (const struct sieve_runtime_env *renv); |
209 | | }; |
210 | | |
211 | | static const struct smtp_address *const * |
212 | | _from_part_get_addresses(const struct sieve_runtime_env *renv); |
213 | | static const char *const * |
214 | | _from_part_get_values(const struct sieve_runtime_env *renv); |
215 | | static const struct smtp_address *const * |
216 | | _to_part_get_addresses(const struct sieve_runtime_env *renv); |
217 | | static const char *const * |
218 | | _to_part_get_values(const struct sieve_runtime_env *renv); |
219 | | static const char *const * |
220 | | _auth_part_get_values(const struct sieve_runtime_env *renv); |
221 | | |
222 | | static const struct sieve_envelope_part _from_part = { |
223 | | "from", |
224 | | _from_part_get_addresses, |
225 | | _from_part_get_values, |
226 | | }; |
227 | | |
228 | | static const struct sieve_envelope_part _to_part = { |
229 | | "to", |
230 | | _to_part_get_addresses, |
231 | | _to_part_get_values, |
232 | | }; |
233 | | |
234 | | static const struct sieve_envelope_part _auth_part = { |
235 | | "auth", |
236 | | NULL, |
237 | | _auth_part_get_values, |
238 | | }; |
239 | | |
240 | | static const struct sieve_envelope_part *_envelope_parts[] = { |
241 | | /* Required */ |
242 | | &_from_part, &_to_part, |
243 | | |
244 | | /* Non-standard */ |
245 | | &_auth_part |
246 | | }; |
247 | | |
248 | | static unsigned int _envelope_part_count = N_ELEMENTS(_envelope_parts); |
249 | | |
250 | | static const struct sieve_envelope_part * |
251 | | _envelope_part_find(const char *identifier) |
252 | 0 | { |
253 | 0 | unsigned int i; |
254 | |
|
255 | 0 | for (i = 0; i < _envelope_part_count; i++) { |
256 | 0 | if (strcasecmp(_envelope_parts[i]->identifier, |
257 | 0 | identifier) == 0) |
258 | 0 | return _envelope_parts[i]; |
259 | 0 | } |
260 | | |
261 | 0 | return NULL; |
262 | 0 | } |
263 | | |
264 | | /* Envelope parts implementation */ |
265 | | |
266 | | static const struct smtp_address *const * |
267 | | _from_part_get_addresses(const struct sieve_runtime_env *renv) |
268 | 0 | { |
269 | 0 | ARRAY(const struct smtp_address *) envelope_values; |
270 | 0 | const struct smtp_address *address = |
271 | 0 | sieve_message_get_sender(renv->msgctx); |
272 | |
|
273 | 0 | t_array_init(&envelope_values, 2); |
274 | |
|
275 | 0 | if (address == NULL) |
276 | 0 | address = smtp_address_create_temp(NULL, NULL); |
277 | 0 | array_append(&envelope_values, &address, 1); |
278 | |
|
279 | 0 | (void)array_append_space(&envelope_values); |
280 | 0 | return array_idx(&envelope_values, 0); |
281 | 0 | } |
282 | | |
283 | | static const char *const * |
284 | | _from_part_get_values(const struct sieve_runtime_env *renv) |
285 | 0 | { |
286 | 0 | ARRAY(const char *)envelope_values; |
287 | 0 | const struct smtp_address *address = |
288 | 0 | sieve_message_get_sender(renv->msgctx); |
289 | 0 | const char *value; |
290 | |
|
291 | 0 | t_array_init(&envelope_values, 2); |
292 | |
|
293 | 0 | value = ""; |
294 | 0 | if (!smtp_address_isnull(address)) |
295 | 0 | value = smtp_address_encode(address); |
296 | 0 | array_append(&envelope_values, &value, 1); |
297 | |
|
298 | 0 | (void)array_append_space(&envelope_values); |
299 | |
|
300 | 0 | return array_idx(&envelope_values, 0); |
301 | 0 | } |
302 | | |
303 | | static const struct smtp_address *const * |
304 | | _to_part_get_addresses(const struct sieve_runtime_env *renv) |
305 | 0 | { |
306 | 0 | ARRAY(const struct smtp_address *) envelope_values; |
307 | 0 | const struct smtp_address *address = |
308 | 0 | sieve_message_get_orig_recipient(renv->msgctx); |
309 | |
|
310 | 0 | if (address != NULL && address->localpart != NULL) { |
311 | 0 | t_array_init(&envelope_values, 2); |
312 | |
|
313 | 0 | array_append(&envelope_values, &address, 1); |
314 | |
|
315 | 0 | (void)array_append_space(&envelope_values); |
316 | 0 | return array_idx(&envelope_values, 0); |
317 | 0 | } |
318 | 0 | return NULL; |
319 | 0 | } |
320 | | |
321 | | static const char *const * |
322 | | _to_part_get_values(const struct sieve_runtime_env *renv) |
323 | 0 | { |
324 | 0 | ARRAY(const char *) envelope_values; |
325 | 0 | const struct smtp_address *address = |
326 | 0 | sieve_message_get_orig_recipient(renv->msgctx); |
327 | |
|
328 | 0 | t_array_init(&envelope_values, 2); |
329 | |
|
330 | 0 | if (address != NULL && address->localpart != NULL) { |
331 | 0 | const char *value = smtp_address_encode(address); |
332 | 0 | array_append(&envelope_values, &value, 1); |
333 | 0 | } |
334 | |
|
335 | 0 | (void)array_append_space(&envelope_values); |
336 | |
|
337 | 0 | return array_idx(&envelope_values, 0); |
338 | 0 | } |
339 | | |
340 | | static const char *const * |
341 | | _auth_part_get_values(const struct sieve_runtime_env *renv) |
342 | 0 | { |
343 | 0 | const struct sieve_execute_env *eenv = renv->exec_env; |
344 | 0 | ARRAY(const char *) envelope_values; |
345 | |
|
346 | 0 | t_array_init(&envelope_values, 2); |
347 | |
|
348 | 0 | if (eenv->msgdata->auth_user != NULL) |
349 | 0 | array_append(&envelope_values, &eenv->msgdata->auth_user, 1); |
350 | |
|
351 | 0 | (void)array_append_space(&envelope_values); |
352 | |
|
353 | 0 | return array_idx(&envelope_values, 0); |
354 | 0 | } |
355 | | |
356 | | /* |
357 | | * Envelope address list |
358 | | */ |
359 | | |
360 | | /* Forward declarations */ |
361 | | |
362 | | static int |
363 | | sieve_envelope_address_list_next_string_item(struct sieve_stringlist *_strlist, |
364 | | string_t **str_r); |
365 | | static int |
366 | | sieve_envelope_address_list_next_item(struct sieve_address_list *_addrlist, |
367 | | struct smtp_address *addr_r, |
368 | | string_t **unparsed_r); |
369 | | static void |
370 | | sieve_envelope_address_list_reset(struct sieve_stringlist *_strlist); |
371 | | |
372 | | /* Stringlist object */ |
373 | | |
374 | | struct sieve_envelope_address_list { |
375 | | struct sieve_address_list addrlist; |
376 | | |
377 | | struct sieve_stringlist *env_parts; |
378 | | |
379 | | const struct smtp_address *const *cur_addresses; |
380 | | const char *const *cur_values; |
381 | | |
382 | | int value_index; |
383 | | }; |
384 | | |
385 | | static struct sieve_address_list * |
386 | | sieve_envelope_address_list_create(const struct sieve_runtime_env *renv, |
387 | | struct sieve_stringlist *env_parts) |
388 | 0 | { |
389 | 0 | struct sieve_envelope_address_list *addrlist; |
390 | |
|
391 | 0 | addrlist = t_new(struct sieve_envelope_address_list, 1); |
392 | 0 | addrlist->addrlist.strlist.runenv = renv; |
393 | 0 | addrlist->addrlist.strlist.exec_status = SIEVE_EXEC_OK; |
394 | 0 | addrlist->addrlist.strlist.next_item = |
395 | 0 | sieve_envelope_address_list_next_string_item; |
396 | 0 | addrlist->addrlist.strlist.reset = sieve_envelope_address_list_reset; |
397 | 0 | addrlist->addrlist.next_item = sieve_envelope_address_list_next_item; |
398 | 0 | addrlist->env_parts = env_parts; |
399 | |
|
400 | 0 | return &addrlist->addrlist; |
401 | 0 | } |
402 | | |
403 | | static int |
404 | | sieve_envelope_address_list_next_item(struct sieve_address_list *_addrlist, |
405 | | struct smtp_address *addr_r, |
406 | | string_t **unparsed_r) |
407 | 0 | { |
408 | 0 | struct sieve_envelope_address_list *addrlist = |
409 | 0 | (struct sieve_envelope_address_list *)_addrlist; |
410 | 0 | const struct sieve_runtime_env *renv = _addrlist->strlist.runenv; |
411 | |
|
412 | 0 | if (addr_r != NULL) |
413 | 0 | smtp_address_init(addr_r, NULL, NULL); |
414 | 0 | if (unparsed_r != NULL) *unparsed_r = NULL; |
415 | |
|
416 | 0 | while (addrlist->cur_addresses == NULL && |
417 | 0 | addrlist->cur_values == NULL) { |
418 | 0 | const struct sieve_envelope_part *epart; |
419 | 0 | string_t *envp_item = NULL; |
420 | 0 | int ret; |
421 | | |
422 | | /* Read next header value from source list */ |
423 | 0 | if ((ret = sieve_stringlist_next_item(addrlist->env_parts, |
424 | 0 | &envp_item)) <= 0) |
425 | 0 | return ret; |
426 | | |
427 | 0 | if (_addrlist->strlist.trace) { |
428 | 0 | sieve_runtime_trace( |
429 | 0 | _addrlist->strlist.runenv, 0, |
430 | 0 | "getting '%s' part from message envelope", |
431 | 0 | str_sanitize(str_c(envp_item), 80)); |
432 | 0 | } |
433 | |
|
434 | 0 | if ((epart=_envelope_part_find(str_c(envp_item))) != NULL) { |
435 | 0 | addrlist->value_index = 0; |
436 | |
|
437 | 0 | if (epart->get_addresses != NULL) { |
438 | | /* Field contains addresses */ |
439 | 0 | addrlist->cur_addresses = |
440 | 0 | epart->get_addresses(renv); |
441 | | |
442 | | /* Drop empty list */ |
443 | 0 | if (addrlist->cur_addresses != NULL && |
444 | 0 | addrlist->cur_addresses[0] == NULL) |
445 | 0 | addrlist->cur_addresses = NULL; |
446 | 0 | } |
447 | |
|
448 | 0 | if (addrlist->cur_addresses == NULL && |
449 | 0 | epart->get_values != NULL) { |
450 | | /* Field contains something else */ |
451 | 0 | addrlist->cur_values = epart->get_values(renv); |
452 | | |
453 | | /* Drop empty list */ |
454 | 0 | if (addrlist->cur_values != NULL && |
455 | 0 | addrlist->cur_values[0] == NULL) |
456 | 0 | addrlist->cur_values = NULL; |
457 | 0 | } |
458 | 0 | } |
459 | 0 | } |
460 | | |
461 | | /* Return next item */ |
462 | 0 | if (addrlist->cur_addresses != NULL) { |
463 | 0 | const struct smtp_address *addr = |
464 | 0 | addrlist->cur_addresses[addrlist->value_index]; |
465 | |
|
466 | 0 | if (addr->localpart == NULL) { |
467 | | /* Null path <> */ |
468 | 0 | if (unparsed_r != NULL) |
469 | 0 | *unparsed_r = t_str_new_const("", 0); |
470 | 0 | } else { |
471 | 0 | if (addr_r != NULL) |
472 | 0 | *addr_r = *addr; |
473 | 0 | } |
474 | | |
475 | | /* Advance to next value */ |
476 | 0 | addrlist->value_index++; |
477 | 0 | if (addrlist->cur_addresses[addrlist->value_index] == NULL) { |
478 | 0 | addrlist->cur_addresses = NULL; |
479 | 0 | addrlist->value_index = 0; |
480 | 0 | } |
481 | 0 | } else { |
482 | 0 | if (unparsed_r != NULL) { |
483 | 0 | const char *value = |
484 | 0 | addrlist->cur_values[addrlist->value_index]; |
485 | |
|
486 | 0 | *unparsed_r = t_str_new_const(value, strlen(value)); |
487 | 0 | } |
488 | | |
489 | | /* Advance to next value */ |
490 | 0 | addrlist->value_index++; |
491 | 0 | if (addrlist->cur_values[addrlist->value_index] == NULL) { |
492 | 0 | addrlist->cur_values = NULL; |
493 | 0 | addrlist->value_index = 0; |
494 | 0 | } |
495 | 0 | } |
496 | |
|
497 | 0 | return 1; |
498 | 0 | } |
499 | | |
500 | | static int |
501 | | sieve_envelope_address_list_next_string_item(struct sieve_stringlist *_strlist, |
502 | | string_t **str_r) |
503 | 0 | { |
504 | 0 | struct sieve_address_list *addrlist = |
505 | 0 | (struct sieve_address_list *)_strlist; |
506 | 0 | struct smtp_address addr; |
507 | 0 | int ret; |
508 | |
|
509 | 0 | if ((ret=sieve_envelope_address_list_next_item(addrlist, &addr, |
510 | 0 | str_r)) <= 0) |
511 | 0 | return ret; |
512 | | |
513 | 0 | if (addr.localpart != NULL) { |
514 | 0 | const char *addr_str = smtp_address_encode(&addr); |
515 | 0 | if (str_r != NULL) |
516 | 0 | *str_r = t_str_new_const(addr_str, strlen(addr_str)); |
517 | 0 | } |
518 | 0 | return 1; |
519 | 0 | } |
520 | | |
521 | | static void |
522 | | sieve_envelope_address_list_reset(struct sieve_stringlist *_strlist) |
523 | 0 | { |
524 | 0 | struct sieve_envelope_address_list *addrlist = |
525 | 0 | (struct sieve_envelope_address_list *)_strlist; |
526 | |
|
527 | 0 | sieve_stringlist_reset(addrlist->env_parts); |
528 | 0 | addrlist->cur_addresses = NULL; |
529 | 0 | addrlist->cur_values = NULL; |
530 | 0 | addrlist->value_index = 0; |
531 | 0 | } |
532 | | |
533 | | /* |
534 | | * Command Registration |
535 | | */ |
536 | | |
537 | | static bool |
538 | | tst_envelope_registered(struct sieve_validator *valdtr, |
539 | | const struct sieve_extension *ext ATTR_UNUSED, |
540 | | struct sieve_command_registration *cmd_reg) |
541 | 0 | { |
542 | | /* The order of these is not significant */ |
543 | 0 | sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR); |
544 | 0 | sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE); |
545 | 0 | sieve_address_parts_link_tags(valdtr, cmd_reg, SIEVE_AM_OPT_ADDRESS_PART); |
546 | 0 | return TRUE; |
547 | 0 | } |
548 | | |
549 | | /* |
550 | | * Validation |
551 | | */ |
552 | | |
553 | | static int |
554 | | _envelope_part_is_supported(void *context, struct sieve_ast_argument *arg) |
555 | 0 | { |
556 | 0 | const struct sieve_envelope_part **not_address = |
557 | 0 | (const struct sieve_envelope_part **) context; |
558 | |
|
559 | 0 | if (sieve_argument_is_string_literal(arg)) { |
560 | 0 | const struct sieve_envelope_part *epart; |
561 | |
|
562 | 0 | if ((epart=_envelope_part_find( |
563 | 0 | sieve_ast_strlist_strc(arg))) != NULL) { |
564 | 0 | if (epart->get_addresses == NULL) { |
565 | 0 | if (*not_address == NULL) |
566 | 0 | *not_address = epart; |
567 | 0 | } |
568 | 0 | return 1; |
569 | 0 | } |
570 | 0 | return 0; |
571 | 0 | } |
572 | 0 | return 1; /* Can't check at compile time */ |
573 | 0 | } |
574 | | |
575 | | static bool |
576 | | tst_envelope_validate(struct sieve_validator *valdtr, struct sieve_command *tst) |
577 | 0 | { |
578 | 0 | struct sieve_ast_argument *arg = tst->first_positional; |
579 | 0 | struct sieve_ast_argument *epart; |
580 | 0 | struct sieve_comparator cmp_default = |
581 | 0 | SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); |
582 | 0 | struct sieve_match_type mcht_default = |
583 | 0 | SIEVE_MATCH_TYPE_DEFAULT(is_match_type); |
584 | 0 | const struct sieve_envelope_part *not_address = NULL; |
585 | |
|
586 | 0 | if (!sieve_validate_positional_argument(valdtr, tst, arg, |
587 | 0 | "envelope part", 1, |
588 | 0 | SAAT_STRING_LIST)) { |
589 | 0 | return FALSE; |
590 | 0 | } |
591 | | |
592 | 0 | if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) |
593 | 0 | return FALSE; |
594 | | |
595 | | /* Check whether supplied envelope parts are supported |
596 | | * FIXME: verify dynamic envelope parts at runtime |
597 | | */ |
598 | 0 | epart = arg; |
599 | 0 | if (sieve_ast_stringlist_map(&epart, ¬_address, |
600 | 0 | _envelope_part_is_supported) <= 0) { |
601 | 0 | i_assert(epart != NULL); |
602 | 0 | sieve_argument_validate_error( |
603 | 0 | valdtr, epart, |
604 | 0 | "specified envelope part '%s' is not supported by the envelope test", |
605 | 0 | str_sanitize(sieve_ast_strlist_strc(epart), 64)); |
606 | 0 | return FALSE; |
607 | 0 | } |
608 | | |
609 | 0 | if (not_address != NULL) { |
610 | 0 | struct sieve_ast_argument *addrp_arg = |
611 | 0 | sieve_command_find_argument(tst, &address_part_tag); |
612 | |
|
613 | 0 | if (addrp_arg != NULL) { |
614 | 0 | sieve_argument_validate_error( |
615 | 0 | valdtr, addrp_arg, |
616 | 0 | "address part ':%s' specified while non-address envelope part '%s' " |
617 | 0 | "is tested with the envelope test", |
618 | 0 | sieve_ast_argument_tag(addrp_arg), |
619 | 0 | not_address->identifier); |
620 | 0 | return FALSE; |
621 | 0 | } |
622 | 0 | } |
623 | | |
624 | 0 | arg = sieve_ast_argument_next(arg); |
625 | |
|
626 | 0 | if (!sieve_validate_positional_argument(valdtr, tst, arg, "key list", 2, |
627 | 0 | SAAT_STRING_LIST)) |
628 | 0 | return FALSE; |
629 | | |
630 | 0 | if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE)) |
631 | 0 | return FALSE; |
632 | | |
633 | | /* Validate the key argument to a specified match type */ |
634 | 0 | return sieve_match_type_validate(valdtr, tst, arg, |
635 | 0 | &mcht_default, &cmp_default); |
636 | 0 | } |
637 | | |
638 | | /* |
639 | | * Code generation |
640 | | */ |
641 | | |
642 | | static bool |
643 | | tst_envelope_generate(const struct sieve_codegen_env *cgenv, |
644 | | struct sieve_command *cmd) |
645 | 0 | { |
646 | 0 | (void)sieve_operation_emit(cgenv->sblock, cmd->ext, |
647 | 0 | &envelope_operation); |
648 | | |
649 | | /* Generate arguments */ |
650 | 0 | if (!sieve_generate_arguments(cgenv, cmd, NULL)) |
651 | 0 | return FALSE; |
652 | 0 | return TRUE; |
653 | 0 | } |
654 | | |
655 | | /* |
656 | | * Code dump |
657 | | */ |
658 | | |
659 | | static bool |
660 | | ext_envelope_operation_dump(const struct sieve_dumptime_env *denv, |
661 | | sieve_size_t *address) |
662 | 0 | { |
663 | 0 | sieve_code_dumpf(denv, "ENVELOPE"); |
664 | 0 | sieve_code_descend(denv); |
665 | | |
666 | | /* Handle any optional arguments */ |
667 | 0 | if (sieve_addrmatch_opr_optional_dump(denv, address, NULL) != 0) |
668 | 0 | return FALSE; |
669 | | |
670 | 0 | return (sieve_opr_stringlist_dump(denv, address, "envelope part") && |
671 | 0 | sieve_opr_stringlist_dump(denv, address, "key list")); |
672 | 0 | } |
673 | | |
674 | | /* |
675 | | * Interpretation |
676 | | */ |
677 | | |
678 | | static int |
679 | | ext_envelope_operation_execute(const struct sieve_runtime_env *renv, |
680 | | sieve_size_t *address) |
681 | 0 | { |
682 | 0 | struct sieve_comparator cmp = |
683 | 0 | SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); |
684 | 0 | struct sieve_match_type mcht = |
685 | 0 | SIEVE_MATCH_TYPE_DEFAULT(is_match_type); |
686 | 0 | struct sieve_address_part addrp = |
687 | 0 | SIEVE_ADDRESS_PART_DEFAULT(all_address_part); |
688 | 0 | struct sieve_stringlist *env_part_list, *value_list, *key_list; |
689 | 0 | struct sieve_address_list *addr_list; |
690 | 0 | int match, ret; |
691 | | |
692 | | /* |
693 | | * Read operands |
694 | | */ |
695 | | |
696 | | /* Read optional operands */ |
697 | 0 | if (sieve_addrmatch_opr_optional_read(renv, address, NULL, &ret, |
698 | 0 | &addrp, &mcht, &cmp) < 0) |
699 | 0 | return ret; |
700 | | |
701 | | /* Read envelope-part */ |
702 | 0 | if ((ret = sieve_opr_stringlist_read(renv, address, "envelope-part", |
703 | 0 | &env_part_list)) <= 0) |
704 | 0 | return ret; |
705 | | |
706 | | /* Read key-list */ |
707 | 0 | if ((ret = sieve_opr_stringlist_read(renv, address, "key-list", |
708 | 0 | &key_list)) <= 0) |
709 | 0 | return ret; |
710 | | |
711 | | /* |
712 | | * Perform test |
713 | | */ |
714 | | |
715 | 0 | sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "envelope test"); |
716 | | |
717 | | /* Create value stringlist */ |
718 | 0 | addr_list = sieve_envelope_address_list_create(renv, env_part_list); |
719 | 0 | value_list = sieve_address_part_stringlist_create(renv, &addrp, |
720 | 0 | addr_list); |
721 | | |
722 | | /* Perform match */ |
723 | 0 | if ((match = sieve_match(renv, &mcht, &cmp, |
724 | 0 | value_list, key_list, &ret)) < 0) |
725 | 0 | return ret; |
726 | | |
727 | | /* Set test result for subsequent conditional jump */ |
728 | 0 | sieve_interpreter_set_test_result(renv->interp, match > 0); |
729 | 0 | return SIEVE_EXEC_OK; |
730 | 0 | } |
731 | | |