defer_ok was not working if used on a callout with verify=header_sender.
[exim.git] / src / src / filter.c
1 /* $Cambridge: exim/src/src/filter.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
2
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2005 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
10
11 /* Code for mail filtering functions. */
12
13 #include "exim.h"
14
15
16 /* Command arguments and left/right points in conditions can contain different
17 types of data, depending on the particular command or condition. Originally,
18 (void *) was used as "any old type", with casts, but this gives trouble and
19 warnings in some environments. So now it is done "properly", with a union. We
20 need to declare the structures first because some of them are recursive. */
21
22 struct filter_cmd;
23 struct condition_block;
24
25 union argtypes {
26 struct string_item *a;
27 BOOL b;
28 struct condition_block *c;
29 struct filter_cmd *f;
30 int i;
31 uschar *u;
32 };
33
34 /* Local structures used in this module */
35
36 typedef struct filter_cmd {
37 struct filter_cmd *next;
38 int command;
39 BOOL seen;
40 BOOL noerror;
41 union argtypes args[1];
42 } filter_cmd;
43
44 typedef struct condition_block {
45 struct condition_block *parent;
46 int type;
47 BOOL testfor;
48 union argtypes left;
49 union argtypes right;
50 } condition_block;
51
52 /* Miscellaneous other declarations */
53
54 static uschar **error_pointer;
55 static uschar *log_filename;
56 static int filter_options;
57 static int line_number;
58 static int expect_endif;
59 static int had_else_endif;
60 static int log_fd;
61 static int log_mode;
62 static int output_indent;
63 static BOOL filter_delivered;
64 static BOOL finish_obeyed;
65 static BOOL seen_force;
66 static BOOL seen_value;
67 static BOOL noerror_force;
68
69 enum { had_neither, had_else, had_elif, had_endif };
70
71 static BOOL read_command_list(uschar **, filter_cmd ***, BOOL);
72
73
74 /* The string arguments for the mail command. The header line ones (that are
75 permitted to include \n followed by white space) first, and then the body text
76 one (it can have \n anywhere). Then the file names and once_repeat, which may
77 not contain \n. */
78
79 static char *mailargs[] = { /* "to" must be first, and */
80 "to", /* "cc" and "bcc" must follow */
81 "cc",
82 "bcc",
83 "from",
84 "reply_to",
85 "subject",
86 "extra_headers", /* miscellaneous added header lines */
87 "text",
88 "file",
89 "log",
90 "once",
91 "once_repeat"
92 };
93
94 /* The count of string arguments */
95
96 #define MAILARGS_STRING_COUNT (sizeof(mailargs)/sizeof(uschar *))
97
98 /* The count of string arguments that are actually passed over as strings
99 (once_repeat is converted to an int). */
100
101 #define mailargs_string_passed (MAILARGS_STRING_COUNT - 1)
102
103 /* This defines the offsets for the arguments; first the string ones, and
104 then the non-string ones. The order must be as above. */
105
106 enum { mailarg_index_to,
107 mailarg_index_cc,
108 mailarg_index_bcc,
109 mailarg_index_from,
110 mailarg_index_reply_to,
111 mailarg_index_subject,
112 mailarg_index_headers, /* misc headers must be last */
113 mailarg_index_text, /* text is first after headers */
114 mailarg_index_file, /* between text and expand are filenames */
115 mailarg_index_log,
116 mailarg_index_once,
117 mailarg_index_once_repeat, /* a time string */
118 mailarg_index_expand, /* first non-string argument */
119 mailarg_index_return,
120 mailargs_total /* total number of arguments */
121 };
122
123 /* Offsets in the data structure for the string arguments (note that
124 once_repeat isn't a string argument at this point.) */
125
126 static int reply_offsets[] = { /* must be in same order as above */
127 offsetof(reply_item, to),
128 offsetof(reply_item, cc),
129 offsetof(reply_item, bcc),
130 offsetof(reply_item, from),
131 offsetof(reply_item, reply_to),
132 offsetof(reply_item, subject),
133 offsetof(reply_item, headers),
134 offsetof(reply_item, text),
135 offsetof(reply_item, file),
136 offsetof(reply_item, logfile),
137 offsetof(reply_item, oncelog),
138 };
139
140 /* Condition identities and names, with negated versions for some
141 of them. */
142
143 enum { cond_and, cond_or, cond_personal, cond_begins, cond_BEGINS,
144 cond_ends, cond_ENDS, cond_is, cond_IS, cond_matches,
145 cond_MATCHES, cond_contains, cond_CONTAINS, cond_delivered,
146 cond_above, cond_below, cond_errormsg, cond_firsttime,
147 cond_manualthaw, cond_foranyaddress };
148
149 static char *cond_names[] = {
150 "and", "or", "personal",
151 "begins", "BEGINS", "ends", "ENDS",
152 "is", "IS", "matches", "MATCHES", "contains",
153 "CONTAINS", "delivered", "above", "below", "error_message",
154 "first_delivery", "manually_thawed", "foranyaddress" };
155
156 static char *cond_not_names[] = {
157 "", "", "not personal",
158 "does not begin", "does not BEGIN",
159 "does not end", "does not END",
160 "is not", "IS not", "does not match",
161 "does not MATCH", "does not contain", "does not CONTAIN",
162 "not delivered", "not above", "not below", "not error_message",
163 "not first_delivery", "not manually_thawed", "not foranyaddress" };
164
165 /* Tables of binary condition words and their corresponding types. Not easy
166 to amalgamate with the above because of the different variants. */
167
168 static char *cond_words[] = {
169 "BEGIN",
170 "BEGINS",
171 "CONTAIN",
172 "CONTAINS",
173 "END",
174 "ENDS",
175 "IS",
176 "MATCH",
177 "MATCHES",
178 "above",
179 "begin",
180 "begins",
181 "below",
182 "contain",
183 "contains",
184 "end",
185 "ends",
186 "is",
187 "match",
188 "matches"};
189
190 static int cond_word_count = (sizeof(cond_words)/sizeof(uschar *));
191
192 static int cond_types[] = { cond_BEGINS, cond_BEGINS, cond_CONTAINS,
193 cond_CONTAINS, cond_ENDS, cond_ENDS, cond_IS, cond_MATCHES, cond_MATCHES,
194 cond_above, cond_begins, cond_begins, cond_below, cond_contains,
195 cond_contains, cond_ends, cond_ends, cond_is, cond_matches, cond_matches };
196
197 /* Command identities: must be kept in step with the list of command words
198 and the list of expanded argument counts which follow. */
199
200 enum { add_command, defer_command, deliver_command, elif_command, else_command,
201 endif_command, finish_command, fail_command, freeze_command,
202 headers_command, if_command, logfile_command, logwrite_command,
203 mail_command, noerror_command, pipe_command, save_command, seen_command,
204 testprint_command, unseen_command, vacation_command };
205
206 static char *command_list[] = {
207 "add", "defer", "deliver", "elif", "else", "endif", "finish",
208 "fail", "freeze", "headers", "if", "logfile", "logwrite", "mail",
209 "noerror", "pipe", "save", "seen", "testprint", "unseen", "vacation"
210 };
211
212 static int command_list_count = sizeof(command_list)/sizeof(uschar *);
213
214 /* This table contains the number of expanded arguments in the bottom 4 bits.
215 If the top bit is set, it means that the default for the command is "seen". */
216
217 static uschar command_exparg_count[] = {
218 2, /* add */
219 1, /* defer */
220 128+2, /* deliver */
221 0, /* elif */
222 0, /* else */
223 0, /* endif */
224 0, /* finish */
225 1, /* fail */
226 1, /* freeze */
227 1, /* headers */
228 0, /* if */
229 1, /* logfile */
230 1, /* logwrite */
231 MAILARGS_STRING_COUNT, /* mail */
232 0, /* noerror */
233 128+0, /* pipe */
234 128+1, /* save */
235 0, /* seen */
236 1, /* testprint */
237 0, /* unseen */
238 MAILARGS_STRING_COUNT /* vacation */
239 };
240
241
242
243 /*************************************************
244 * Find next significant uschar *
245 *************************************************/
246
247 /* Function to skip over white space and, optionally, comments.
248
249 Arguments:
250 ptr pointer to next character
251 comment_allowed if TRUE, comments (# to \n) are skipped
252
253 Returns: pointer to next non-whitespace character
254 */
255
256 static uschar *
257 nextsigchar(uschar *ptr, BOOL comment_allowed)
258 {
259 for (;;)
260 {
261 while (isspace(*ptr))
262 {
263 if (*ptr == '\n') line_number++;
264 ptr++;
265 }
266 if (comment_allowed && *ptr == '#')
267 {
268 while (*(++ptr) != '\n' && *ptr != 0);
269 continue;
270 }
271 else break;
272 }
273 return ptr;
274 }
275
276
277
278 /*************************************************
279 * Read one word *
280 *************************************************/
281
282 /* The terminator is white space unless bracket is TRUE, in which
283 case ( and ) terminate.
284
285 Arguments
286 ptr pointer to next character
287 buffer where to put the word
288 size size of buffer
289 bracket if TRUE, terminate on ( and ) as well as space
290
291 Returns: pointer to the next significant character after the word
292 */
293
294 static uschar *
295 nextword(uschar *ptr, uschar *buffer, int size, BOOL bracket)
296 {
297 uschar *bp = buffer;
298 while (*ptr != 0 && !isspace(*ptr) &&
299 (!bracket || (*ptr != '(' && *ptr != ')')))
300 {
301 if (bp - buffer < size - 1) *bp++ = *ptr++; else
302 {
303 *error_pointer = string_sprintf("word is too long in line %d of "
304 "filter file (max = %d chars)", line_number, size);
305 break;
306 }
307 }
308 *bp = 0;
309 return nextsigchar(ptr, TRUE);
310 }
311
312
313
314 /*************************************************
315 * Read one item *
316 *************************************************/
317
318 /* Might be a word, or might be a quoted string; in the latter case
319 do the escape stuff.
320
321 Arguments:
322 ptr pointer to next character
323 buffer where to put the item
324 size size of buffer
325 bracket if TRUE, terminate non-quoted on ( and ) as well as space
326
327 Returns: the next significant character after the item
328 */
329
330 static uschar *
331 nextitem(uschar *ptr, uschar *buffer, int size, BOOL bracket)
332 {
333 uschar *bp = buffer;
334 if (*ptr != '\"') return nextword(ptr, buffer, size, bracket);
335
336 while (*(++ptr) != 0 && *ptr != '\"' && *ptr != '\n')
337 {
338 if (bp - buffer >= size - 1)
339 {
340 *error_pointer = string_sprintf("string is too long in line %d of "
341 "filter file (max = %d chars)", line_number, size);
342 break;
343 }
344
345 if (*ptr != '\\') *bp++ = *ptr; else
346 {
347 if (isspace(ptr[1])) /* \<whitespace>NL<whitespace> ignored */
348 {
349 uschar *p = ptr + 1;
350 while (*p != '\n' && isspace(*p)) p++;
351 if (*p == '\n')
352 {
353 line_number++;
354 ptr = p;
355 while (ptr[1] != '\n' && isspace(ptr[1])) ptr++;
356 continue;
357 }
358 }
359
360 *bp++ = string_interpret_escape(&ptr);
361 }
362 }
363
364 if (*ptr == '\"') ptr++;
365 else if (*error_pointer == NULL)
366 *error_pointer = string_sprintf("quote missing at end of string "
367 "in line %d", line_number);
368
369 *bp = 0;
370 return nextsigchar(ptr, TRUE);
371 }
372
373
374
375
376 /*************************************************
377 * Convert a string + K|M to a number *
378 *************************************************/
379
380 /*
381 Arguments:
382 s points to text string
383 OK set TRUE if a valid number was read
384
385 Returns: the number, or 0 on error (with *OK FALSE)
386 */
387
388 static int
389 get_number(uschar *s, BOOL *ok)
390 {
391 int value, count;
392 *ok = FALSE;
393 if (sscanf(CS s, "%i%n", &value, &count) != 1) return 0;
394 if (tolower(s[count]) == 'k') { value *= 1024; count++; }
395 if (tolower(s[count]) == 'm') { value *= 1024*1024; count++; }
396 while (isspace((s[count]))) count++;
397 if (s[count] != 0) return 0;
398 *ok = TRUE;
399 return value;
400 }
401
402
403
404 /*************************************************
405 * Read one condition *
406 *************************************************/
407
408 /* A complete condition must be terminated by "then"; bracketed internal
409 conditions must be terminated by a closing bracket. They are read by calling
410 this function recursively.
411
412 Arguments:
413 ptr points to start of condition
414 condition_block where to hang the created condition block
415 toplevel TRUE when called at the top level
416
417 Returns: points to next character after "then"
418 */
419
420 static uschar *
421 read_condition(uschar *ptr, condition_block **cond, BOOL toplevel)
422 {
423 uschar buffer[1024];
424 BOOL testfor = TRUE;
425 condition_block *current_parent = NULL;
426 condition_block **current = cond;
427
428 *current = NULL;
429
430 /* Loop to read next condition */
431
432 for (;;)
433 {
434 condition_block *c;
435
436 /* reaching the end of the input is an error. */
437
438 if (*ptr == 0)
439 {
440 *error_pointer = string_sprintf("\"then\" missing at end of filter file");
441 break;
442 }
443
444 /* Opening bracket at the start of a condition introduces a nested
445 condition, which must be terminated by a closing bracket. */
446
447 if (*ptr == '(')
448 {
449 ptr = read_condition(nextsigchar(ptr+1, TRUE), &c, FALSE);
450 if (*error_pointer != NULL) break;
451 if (*ptr != ')')
452 {
453 *error_pointer = string_sprintf("expected \")\" in line %d of "
454 "filter file", line_number);
455 break;
456 }
457 if (!testfor)
458 {
459 c->testfor = !c->testfor;
460 testfor = TRUE;
461 }
462 ptr = nextsigchar(ptr+1, TRUE);
463 }
464
465
466 /* Closing bracket at the start of a condition is an error. Give an
467 explicit message, as otherwise "unknown condition" would be confusing. */
468
469 else if (*ptr == ')')
470 {
471 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
472 "filter file", line_number);
473 break;
474 }
475
476 /* Otherwise we expect a word or a string. */
477
478 else
479 {
480 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
481 if (*error_pointer != NULL) break;
482
483 /* "Then" at the start of a condition is an error */
484
485 if (Ustrcmp(buffer, "then") == 0)
486 {
487 *error_pointer = string_sprintf("unexpected \"then\" near line %d of "
488 "filter file", line_number);
489 break;
490 }
491
492 /* "Not" at the start of a condition negates the testing condition. */
493
494 if (Ustrcmp(buffer, "not") == 0)
495 {
496 testfor = !testfor;
497 continue;
498 }
499
500 /* Build a condition block from the specific word. */
501
502 c = store_get(sizeof(condition_block));
503 c->left.u = c->right.u = NULL;
504 c->testfor = testfor;
505 testfor = TRUE;
506
507 /* Check for conditions that start with a keyword */
508
509 if (Ustrcmp(buffer, "delivered") == 0) c->type = cond_delivered;
510 else if (Ustrcmp(buffer, "error_message") == 0) c->type = cond_errormsg;
511 else if (Ustrcmp(buffer, "first_delivery") == 0) c->type = cond_firsttime;
512 else if (Ustrcmp(buffer, "manually_thawed") == 0) c->type = cond_manualthaw;
513
514 /* Personal can be followed by any number of aliases */
515
516 else if (Ustrcmp(buffer, "personal") == 0)
517 {
518 c->type = cond_personal;
519 for (;;)
520 {
521 string_item *aa;
522 uschar *saveptr = ptr;
523 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
524 if (*error_pointer != NULL) break;
525 if (Ustrcmp(buffer, "alias") != 0)
526 {
527 ptr = saveptr;
528 break;
529 }
530 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
531 if (*error_pointer != NULL) break;
532 aa = store_get(sizeof(string_item));
533 aa->text = string_copy(buffer);
534 aa->next = c->left.a;
535 c->left.a = aa;
536 }
537 }
538
539 /* Foranyaddress must be followed by a string and a condition enclosed
540 in parentheses, which is handled as a subcondition. */
541
542 else if (Ustrcmp(buffer, "foranyaddress") == 0)
543 {
544 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
545 if (*error_pointer != NULL) break;
546 if (*ptr != '(')
547 {
548 *error_pointer = string_sprintf("\"(\" expected after \"foranyaddress\" "
549 "near line %d of filter file", line_number);
550 break;
551 }
552
553 c->type = cond_foranyaddress;
554 c->left.u = string_copy(buffer);
555
556 ptr = read_condition(nextsigchar(ptr+1, TRUE), &(c->right.c), FALSE);
557 if (*error_pointer != NULL) break;
558 if (*ptr != ')')
559 {
560 *error_pointer = string_sprintf("expected \")\" in line %d of "
561 "filter file", line_number);
562 break;
563 }
564 if (!testfor)
565 {
566 c->testfor = !c->testfor;
567 testfor = TRUE;
568 }
569 ptr = nextsigchar(ptr+1, TRUE);
570 }
571
572 /* If it's not a word we recognize, then it must be the lefthand
573 operand of one of the comparison words. */
574
575 else
576 {
577 int i;
578 uschar *isptr = NULL;
579
580 c->left.u = string_copy(buffer);
581 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
582 if (*error_pointer != NULL) break;
583
584 /* Handle "does|is [not]", preserving the pointer after "is" in
585 case it isn't that, but the form "is <string>". */
586
587 if (strcmpic(buffer, US"does") == 0 || strcmpic(buffer, US"is") == 0)
588 {
589 if (buffer[0] == 'i') { c->type = cond_is; isptr = ptr; }
590 if (buffer[0] == 'I') { c->type = cond_IS; isptr = ptr; }
591
592 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
593 if (*error_pointer != NULL) break;
594 if (strcmpic(buffer, US"not") == 0)
595 {
596 c->testfor = !c->testfor;
597 if (isptr != NULL) isptr = ptr;
598 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
599 if (*error_pointer != NULL) break;
600 }
601 }
602
603 for (i = 0; i < cond_word_count; i++)
604 {
605 if (Ustrcmp(buffer, cond_words[i]) == 0)
606 {
607 c->type = cond_types[i];
608 break;
609 }
610 }
611
612 /* If an unknown word follows "is" or "is not"
613 it's actually the argument. Reset to read it. */
614
615 if (i >= cond_word_count)
616 {
617 if (isptr != NULL)
618 {
619 ptr = isptr;
620 }
621 else
622 {
623 *error_pointer = string_sprintf("unrecognized condition word \"%s\" "
624 "near line %d of filter file", buffer, line_number);
625 break;
626 }
627 }
628
629 /* Get the RH argument. */
630
631 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
632 if (*error_pointer != NULL) break;
633 c->right.u = string_copy(buffer);
634 }
635 }
636
637 /* We have read some new condition and set it up in the condition block
638 c; point the current pointer at it, and then deal with what follows. */
639
640 *current = c;
641
642 /* Closing bracket terminates if this is a lower-level condition. Otherwise
643 it is unexpected. */
644
645 if (*ptr == ')')
646 {
647 if (toplevel)
648 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
649 "filter file", line_number);
650 break;
651 }
652
653 /* Opening bracket following a condition is an error; give an explicit
654 message to make it clearer what is wrong. */
655
656 else if (*ptr == '(')
657 {
658 *error_pointer = string_sprintf("unexpected \"(\" in line %d of "
659 "filter file", line_number);
660 break;
661 }
662
663 /* Otherwise the next thing must be one of the words "and", "or" or "then" */
664
665 else
666 {
667 uschar *saveptr = ptr;
668 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
669 if (*error_pointer != NULL) break;
670
671 /* "Then" terminates a toplevel condition; otherwise a closing bracket
672 has been omitted. Put a string terminator at the start of "then" so
673 that reflecting the condition can be done when testing. */
674
675 if (Ustrcmp(buffer, "then") == 0)
676 {
677 if (toplevel) *saveptr = 0;
678 else *error_pointer = string_sprintf("missing \")\" at end of "
679 "condition near line %d of filter file", line_number);
680 break;
681 }
682
683 /* "And" causes a new condition block to replace the one we have
684 just read, which becomes the left sub-condition. The current pointer
685 is reset to the pointer for the right sub-condition. We have to keep
686 track of the tree of sequential "ands", so as to traverse back up it
687 if an "or" is met. */
688
689 else if (Ustrcmp(buffer, "and") == 0)
690 {
691 condition_block *andc = store_get(sizeof(condition_block));
692 andc->parent = current_parent;
693 andc->type = cond_and;
694 andc->testfor = TRUE;
695 andc->left.c = c;
696 andc->right.u = NULL; /* insurance */
697 *current = andc;
698 current = &(andc->right.c);
699 current_parent = andc;
700 }
701
702 /* "Or" is similar, but has to be done a bit more carefully to
703 ensure that "and" is more binding. If there's a parent set, we
704 are following a sequence of "and"s and must track back to their
705 start. */
706
707 else if (Ustrcmp(buffer, "or") == 0)
708 {
709 condition_block *orc = store_get(sizeof(condition_block));
710 condition_block *or_parent = NULL;
711
712 if (current_parent != NULL)
713 {
714 while (current_parent->parent != NULL &&
715 current_parent->parent->type == cond_and)
716 current_parent = current_parent->parent;
717
718 /* If the parent has a parent, it must be an "or" parent. */
719
720 if (current_parent->parent != NULL)
721 or_parent = current_parent->parent;
722 }
723
724 orc->parent = or_parent;
725 if (or_parent == NULL) *cond = orc; else
726 or_parent->right.c = orc;
727 orc->type = cond_or;
728 orc->testfor = TRUE;
729 orc->left.c = (current_parent == NULL)? c : current_parent;
730 orc->right.c = NULL; /* insurance */
731 current = &(orc->right.c);
732 current_parent = orc;
733 }
734
735 /* Otherwise there is a disaster */
736
737 else
738 {
739 *error_pointer = string_sprintf("\"and\" or \"or\" or \"%s\" "
740 "expected near line %d of filter file, but found \"%s\"",
741 toplevel? "then" : ")", line_number, buffer);
742 break;
743 }
744 }
745 }
746
747 return nextsigchar(ptr, TRUE);
748 }
749
750
751
752 /*************************************************
753 * Ouput the current indent *
754 *************************************************/
755
756 static void
757 indent(void)
758 {
759 int i;
760 for (i = 0; i < output_indent; i++) debug_printf(" ");
761 }
762
763
764
765 /*************************************************
766 * Condition printer: for debugging *
767 *************************************************/
768
769 /*
770 Arguments:
771 c the block at the top of the tree
772 toplevel TRUE at toplevel - stops overall brackets
773
774 Returns: nothing
775 */
776
777 static void
778 print_condition(condition_block *c, BOOL toplevel)
779 {
780 char *name = (c->testfor)? cond_names[c->type] : cond_not_names[c->type];
781 switch(c->type)
782 {
783 case cond_personal:
784 case cond_delivered:
785 case cond_errormsg:
786 case cond_firsttime:
787 case cond_manualthaw:
788 debug_printf("%s", name);
789 break;
790
791 case cond_is:
792 case cond_IS:
793 case cond_matches:
794 case cond_MATCHES:
795 case cond_contains:
796 case cond_CONTAINS:
797 case cond_begins:
798 case cond_BEGINS:
799 case cond_ends:
800 case cond_ENDS:
801 case cond_above:
802 case cond_below:
803 debug_printf("%s %s %s", c->left.u, (char *)name, c->right.u);
804 break;
805
806 case cond_and:
807 if (!c->testfor) debug_printf("not (");
808 print_condition(c->left.c, FALSE);
809 debug_printf(" %s ", cond_names[c->type]);
810 print_condition(c->right.c, FALSE);
811 if (!c->testfor) debug_printf(")");
812 break;
813
814 case cond_or:
815 if (!c->testfor) debug_printf("not (");
816 else if (!toplevel) debug_printf("(");
817 print_condition(c->left.c, FALSE);
818 debug_printf(" %s ", cond_names[c->type]);
819 print_condition(c->right.c, FALSE);
820 if (!toplevel || !c->testfor) debug_printf(")");
821 break;
822
823 case cond_foranyaddress:
824 debug_printf("%s %s (", name, c->left.u);
825 print_condition(c->right.c, FALSE);
826 debug_printf(")");
827 break;
828 }
829 }
830
831
832
833
834 /*************************************************
835 * Read one filtering command *
836 *************************************************/
837
838 /*
839 Arguments:
840 pptr points to pointer to first character of command; the pointer
841 is updated to point after the last character read
842 lastcmdptr points to pointer to pointer to last command; used for hanging
843 on the newly read command
844
845 Returns: TRUE if command successfully read, else FALSE
846 */
847
848 static BOOL
849 read_command(uschar **pptr, filter_cmd ***lastcmdptr)
850 {
851 int command, i, cmd_bit;
852 filter_cmd *new, **newlastcmdptr;
853 BOOL yield = TRUE;
854 BOOL was_seen_or_unseen = FALSE;
855 BOOL was_noerror = FALSE;
856 uschar buffer[1024];
857 uschar *ptr = *pptr;
858 uschar *saveptr;
859 uschar *fmsg = NULL;
860
861 /* Read the next word and find which command it is. Command words are normally
862 terminated by white space, but there are two exceptions, which are the "if" and
863 "elif" commands. We must allow for them to be terminated by an opening bracket,
864 as brackets are allowed in conditions and users will expect not to require
865 white space here. */
866
867 if (Ustrncmp(ptr, "if(", 3) == 0)
868 {
869 Ustrcpy(buffer, "if");
870 ptr += 2;
871 }
872 else if (Ustrncmp(ptr, "elif(", 5) == 0)
873 {
874 Ustrcpy(buffer, "elif");
875 ptr += 4;
876 }
877 else
878 {
879 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
880 if (*error_pointer != NULL) return FALSE;
881 }
882
883 for (command = 0; command < command_list_count; command++)
884 if (Ustrcmp(buffer, command_list[command]) == 0) break;
885
886 /* Handle the individual commands */
887
888 switch (command)
889 {
890 /* Add takes two arguments, separated by the word "to". Headers has two
891 arguments, but the first must be "add", "remove", or "charset", and it gets
892 stored in the second argument slot. Neither may be preceded by seen, unseen
893 or noerror. */
894
895 case add_command:
896 case headers_command:
897 if (seen_force || noerror_force)
898 {
899 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
900 "found before an \"%s\" command near line %d",
901 command_list[command], line_number);
902 yield = FALSE;
903 }
904 /* Fall through */
905
906 /* Logwrite, logfile, pipe, and testprint all take a single argument, save
907 and logfile can have an option second argument for the mode, and deliver can
908 have "errors_to <address>" in a system filter, or in a user filter if the
909 address is the current one. */
910
911 case deliver_command:
912 case logfile_command:
913 case logwrite_command:
914 case pipe_command:
915 case save_command:
916 case testprint_command:
917
918 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
919 if (*buffer == 0)
920 *error_pointer = string_sprintf("\"%s\" requires an argument "
921 "near line %d of filter file", command_list[command], line_number);
922
923 if (*error_pointer != NULL) yield = FALSE; else
924 {
925 union argtypes argument, second_argument;
926
927 argument.u = second_argument.u = NULL;
928
929 if (command == add_command)
930 {
931 argument.u = string_copy(buffer);
932 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
933 if (*buffer == 0 || Ustrcmp(buffer, "to") != 0)
934 *error_pointer = string_sprintf("\"to\" expected in \"add\" command "
935 "near line %d of filter file", line_number);
936 else
937 {
938 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
939 if (*buffer == 0)
940 *error_pointer = string_sprintf("value missing after \"to\" "
941 "near line %d of filter file", line_number);
942 else second_argument.u = string_copy(buffer);
943 }
944 }
945
946 else if (command == headers_command)
947 {
948 if (Ustrcmp(buffer, "add") == 0)
949 second_argument.b = TRUE;
950 else
951 if (Ustrcmp(buffer, "remove") == 0) second_argument.b = FALSE;
952 else
953 if (Ustrcmp(buffer, "charset") == 0)
954 second_argument.b = TRUE_UNSET;
955 else
956 {
957 *error_pointer = string_sprintf("\"add\", \"remove\", or \"charset\" "
958 "expected after \"headers\" near line %d of filter file",
959 line_number);
960 yield = FALSE;
961 }
962
963 if (!system_filtering && second_argument.b != TRUE_UNSET)
964 {
965 *error_pointer = string_sprintf("header addition and removal is "
966 "available only in system filters: near line %d of filter file",
967 line_number);
968 yield = FALSE;
969 break;
970 }
971
972 if (yield)
973 {
974 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
975 if (*buffer == 0)
976 *error_pointer = string_sprintf("value missing after \"add\", "
977 "\"remove\", or \"charset\" near line %d of filter file",
978 line_number);
979 else argument.u = string_copy(buffer);
980 }
981 }
982
983 /* The argument for the logwrite command must end in a newline, and the save
984 and logfile commands can have an optional mode argument. The deliver
985 command can have an optional "errors_to <address>" for a system filter,
986 or for a user filter if the address is the user's address. Accept the
987 syntax here - the check is later. */
988
989 else
990 {
991 if (command == logwrite_command)
992 {
993 int len = Ustrlen(buffer);
994 if (len == 0 || buffer[len-1] != '\n') Ustrcat(buffer, "\n");
995 }
996
997 argument.u = string_copy(buffer);
998
999 if (command == save_command || command == logfile_command)
1000 {
1001 if (isdigit(*ptr))
1002 {
1003 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1004 second_argument.i = (int)Ustrtol(buffer, NULL, 8);
1005 }
1006 else second_argument.i = -1;
1007 }
1008
1009 else if (command == deliver_command)
1010 {
1011 uschar *save_ptr = ptr;
1012 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1013 if (Ustrcmp(buffer, "errors_to") == 0)
1014 {
1015 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1016 second_argument.u = string_copy(buffer);
1017 }
1018 else ptr = save_ptr;
1019 }
1020 }
1021
1022 /* Set up the command block. Seen defaults TRUE for delivery commands,
1023 FALSE for logging commands, and it doesn't matter for testprint, as
1024 that doesn't change the "delivered" status. */
1025
1026 if (*error_pointer != NULL) yield = FALSE; else
1027 {
1028 new = store_get(sizeof(filter_cmd) + sizeof(union argtypes));
1029 new->next = NULL;
1030 **lastcmdptr = new;
1031 *lastcmdptr = &(new->next);
1032 new->command = command;
1033 new->seen = seen_force? seen_value : command_exparg_count[command] >= 128;
1034 new->noerror = noerror_force;
1035 new->args[0] = argument;
1036 new->args[1] = second_argument;
1037 }
1038 }
1039 break;
1040
1041
1042 /* Elif, else and endif just set a flag if expected. */
1043
1044 case elif_command:
1045 case else_command:
1046 case endif_command:
1047 if (expect_endif > 0)
1048 had_else_endif = (command == elif_command)? had_elif :
1049 (command == else_command)? had_else : had_endif;
1050 else
1051 {
1052 *error_pointer = string_sprintf("unexpected \"%s\" command near "
1053 "line %d of filter file", buffer, line_number);
1054 yield = FALSE;
1055 }
1056 break;
1057
1058
1059 /* Defer, freeze, and fail are available only if permitted. */
1060
1061 case defer_command:
1062 cmd_bit = RDO_DEFER;
1063 goto DEFER_FREEZE_FAIL;
1064
1065 case fail_command:
1066 cmd_bit = RDO_FAIL;
1067 goto DEFER_FREEZE_FAIL;
1068
1069 case freeze_command:
1070 cmd_bit = RDO_FREEZE;
1071
1072 DEFER_FREEZE_FAIL:
1073 if ((filter_options & cmd_bit) == 0)
1074 {
1075 *error_pointer = string_sprintf("filtering command \"%s\" is disabled: "
1076 "near line %d of filter file", buffer, line_number);
1077 yield = FALSE;
1078 break;
1079 }
1080
1081 /* A text message can be provided after the "text" keyword, or
1082 as a string in quotes. */
1083
1084 saveptr = ptr;
1085 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1086 if (*saveptr != '\"' && (*buffer == 0 || Ustrcmp(buffer, "text") != 0))
1087 {
1088 ptr = saveptr;
1089 fmsg = US"";
1090 }
1091 else
1092 {
1093 if (*saveptr != '\"')
1094 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1095 fmsg = string_copy(buffer);
1096 }
1097
1098 /* Drop through and treat as "finish", but never set "seen". */
1099
1100 seen_value = FALSE;
1101
1102 /* Finish has no arguments; fmsg defaults to NULL */
1103
1104 case finish_command:
1105 new = store_get(sizeof(filter_cmd));
1106 new->next = NULL;
1107 **lastcmdptr = new;
1108 *lastcmdptr = &(new->next);
1109 new->command = command;
1110 new->seen = seen_force? seen_value : FALSE;
1111 new->args[0].u = fmsg;
1112 break;
1113
1114
1115 /* Seen, unseen, and noerror are not allowed before if, which takes a
1116 condition argument and then and else sub-commands. */
1117
1118 case if_command:
1119 if (seen_force || noerror_force)
1120 {
1121 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1122 "found before an \"if\" command near line %d",
1123 line_number);
1124 yield = FALSE;
1125 }
1126
1127 /* Set up the command block for if */
1128
1129 new = store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1130 new->next = NULL;
1131 **lastcmdptr = new;
1132 *lastcmdptr = &(new->next);
1133 new->command = command;
1134 new->seen = FALSE;
1135 new->args[0].u = NULL;
1136 new->args[1].u = new->args[2].u = NULL;
1137 new->args[3].u = ptr;
1138
1139 /* Read the condition */
1140
1141 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1142 if (*error_pointer != NULL) { yield = FALSE; break; }
1143
1144 /* Read the commands to be obeyed if the condition is true */
1145
1146 newlastcmdptr = &(new->args[1].f);
1147 if (!read_command_list(&ptr, &newlastcmdptr, TRUE)) yield = FALSE;
1148
1149 /* If commands were successfully read, handle the various possible
1150 terminators. There may be a number of successive "elif" sections. */
1151
1152 else
1153 {
1154 while (had_else_endif == had_elif)
1155 {
1156 filter_cmd *newnew =
1157 store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1158 new->args[2].f = newnew;
1159 new = newnew;
1160 new->next = NULL;
1161 new->command = command;
1162 new->seen = FALSE;
1163 new->args[0].u = NULL;
1164 new->args[1].u = new->args[2].u = NULL;
1165 new->args[3].u = ptr;
1166
1167 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1168 if (*error_pointer != NULL) { yield = FALSE; break; }
1169 newlastcmdptr = &(new->args[1].f);
1170 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1171 yield = FALSE;
1172 }
1173
1174 if (yield == FALSE) break;
1175
1176 /* Handle termination by "else", possibly following one or more
1177 "elsif" sections. */
1178
1179 if (had_else_endif == had_else)
1180 {
1181 newlastcmdptr = &(new->args[2].f);
1182 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1183 yield = FALSE;
1184 else if (had_else_endif != had_endif)
1185 {
1186 *error_pointer = string_sprintf("\"endif\" missing near line %d of "
1187 "filter file", line_number);
1188 yield = FALSE;
1189 }
1190 }
1191
1192 /* Otherwise the terminator was "endif" - this is checked by
1193 read_command_list(). The pointer is already set to NULL. */
1194 }
1195
1196 /* Reset the terminator flag. */
1197
1198 had_else_endif = had_neither;
1199 break;
1200
1201
1202 /* The mail & vacation commands have a whole slew of keyworded arguments.
1203 The final argument values are the file expand and return message booleans,
1204 whose offsets are defined in mailarg_index_{expand,return}. Although they
1205 are logically booleans, because they are stored in a uschar * value, we use
1206 NULL and not FALSE, to keep 64-bit compilers happy. */
1207
1208 case mail_command:
1209 case vacation_command:
1210 new = store_get(sizeof(filter_cmd) + mailargs_total * sizeof(union argtypes));
1211 new->next = NULL;
1212 new->command = command;
1213 new->seen = seen_force? seen_value : FALSE;
1214 new->noerror = noerror_force;
1215 for (i = 0; i < mailargs_total; i++) new->args[i].u = NULL;
1216
1217 /* Read keyword/value pairs until we hit one that isn't. The data
1218 must contain only printing chars plus tab, though the "text" value
1219 can also contain newlines. The "file" keyword can be preceded by the
1220 word "expand", and "return message" has no data. */
1221
1222 for (;;)
1223 {
1224 uschar *saveptr = ptr;
1225 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1226 if (*error_pointer != NULL)
1227 {
1228 yield = FALSE;
1229 break;
1230 }
1231
1232 /* Ensure "return" is followed by "message"; that's a complete option */
1233
1234 if (Ustrcmp(buffer, "return") == 0)
1235 {
1236 new->args[mailarg_index_return].u = US""; /* not NULL => TRUE */
1237 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1238 if (Ustrcmp(buffer, "message") != 0)
1239 {
1240 *error_pointer = string_sprintf("\"return\" not followed by \"message\" "
1241 " near line %d of filter file", line_number);
1242 yield = FALSE;
1243 break;
1244 }
1245 continue;
1246 }
1247
1248 /* Ensure "expand" is followed by "file", then fall through to process the
1249 file keyword. */
1250
1251 if (Ustrcmp(buffer, "expand") == 0)
1252 {
1253 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1254 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1255 if (Ustrcmp(buffer, "file") != 0)
1256 {
1257 *error_pointer = string_sprintf("\"expand\" not followed by \"file\" "
1258 " near line %d of filter file", line_number);
1259 yield = FALSE;
1260 break;
1261 }
1262 }
1263
1264 /* Scan for the keyword */
1265
1266 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
1267 if (Ustrcmp(buffer, mailargs[i]) == 0) break;
1268
1269 /* Not found keyword; assume end of this command */
1270
1271 if (i >= MAILARGS_STRING_COUNT)
1272 {
1273 ptr = saveptr;
1274 break;
1275 }
1276
1277 /* Found keyword, read the data item */
1278
1279 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1280 if (*error_pointer != NULL)
1281 {
1282 yield = FALSE;
1283 break;
1284 }
1285 else new->args[i].u = string_copy(buffer);
1286 }
1287
1288 /* If this is the vacation command, apply some default settings to
1289 some of the arguments. */
1290
1291 if (command == vacation_command)
1292 {
1293 if (new->args[mailarg_index_file].u == NULL)
1294 {
1295 new->args[mailarg_index_file].u = string_copy(US".vacation.msg");
1296 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1297 }
1298 if (new->args[mailarg_index_log].u == NULL)
1299 new->args[mailarg_index_log].u = string_copy(US".vacation.log");
1300 if (new->args[mailarg_index_once].u == NULL)
1301 new->args[mailarg_index_once].u = string_copy(US".vacation");
1302 if (new->args[mailarg_index_once_repeat].u == NULL)
1303 new->args[mailarg_index_once_repeat].u = string_copy(US"7d");
1304 if (new->args[mailarg_index_subject].u == NULL)
1305 new->args[mailarg_index_subject].u = string_copy(US"On vacation");
1306 }
1307
1308 /* Join the address on to the chain of generated addresses */
1309
1310 **lastcmdptr = new;
1311 *lastcmdptr = &(new->next);
1312 break;
1313
1314
1315 /* Seen and unseen just set flags */
1316
1317 case seen_command:
1318 case unseen_command:
1319 if (seen_force)
1320 {
1321 *error_pointer = string_sprintf("\"seen\" or \"unseen\" repeated "
1322 "near line %d", line_number);
1323 yield = FALSE;
1324 }
1325 seen_value = (command == seen_command);
1326 seen_force = TRUE;
1327 was_seen_or_unseen = TRUE;
1328 break;
1329
1330
1331 /* So does noerror */
1332
1333 case noerror_command:
1334 noerror_force = TRUE;
1335 was_noerror = TRUE;
1336 break;
1337
1338
1339 /* Oops */
1340
1341 default:
1342 *error_pointer = string_sprintf("unknown filtering command \"%s\" "
1343 "near line %d of filter file", buffer, line_number);
1344 yield = FALSE;
1345 break;
1346 }
1347
1348 if (!was_seen_or_unseen && !was_noerror)
1349 {
1350 seen_force = FALSE;
1351 noerror_force = FALSE;
1352 }
1353
1354 *pptr = ptr;
1355 return yield;
1356 }
1357
1358
1359
1360 /*************************************************
1361 * Read a list of commands *
1362 *************************************************/
1363
1364 /* If condional is TRUE, the list must be terminated
1365 by the words "else" or "endif".
1366
1367 Arguments:
1368 pptr points to pointer to next character; the pointer is updated
1369 lastcmdptr points to pointer to pointer to previously-read command; used
1370 for hanging on the new command
1371 conditional TRUE if this command is the subject of a condition
1372
1373 Returns: TRUE on success
1374 */
1375
1376 static BOOL
1377 read_command_list(uschar **pptr, filter_cmd ***lastcmdptr, BOOL conditional)
1378 {
1379 if (conditional) expect_endif++;
1380 had_else_endif = had_neither;
1381 while (**pptr != 0 && had_else_endif == had_neither)
1382 {
1383 if (!read_command(pptr, lastcmdptr)) return FALSE;
1384 *pptr = nextsigchar(*pptr, TRUE);
1385 }
1386 if (conditional)
1387 {
1388 expect_endif--;
1389 if (had_else_endif == had_neither)
1390 {
1391 *error_pointer = US"\"endif\" missing at end of filter file";
1392 return FALSE;
1393 }
1394 }
1395 return TRUE;
1396 }
1397
1398
1399
1400
1401 /*************************************************
1402 * Test a condition *
1403 *************************************************/
1404
1405 /*
1406 Arguments:
1407 c points to the condition block; c->testfor indicated whether
1408 it's a positive or negative condition
1409 toplevel TRUE if called from "if" directly; FALSE otherwise
1410
1411 Returns: TRUE if the condition is met
1412 */
1413
1414 static BOOL
1415 test_condition(condition_block *c, BOOL toplevel)
1416 {
1417 BOOL yield;
1418 const pcre *re;
1419 uschar *exp[2], *p, *pp;
1420 const uschar *regcomp_error = NULL;
1421 int regcomp_error_offset;
1422 int val[2];
1423 int i;
1424
1425 if (c == NULL) return TRUE; /* does this ever occur? */
1426
1427 switch (c->type)
1428 {
1429 case cond_and:
1430 yield = test_condition(c->left.c, FALSE) &&
1431 *error_pointer == NULL &&
1432 test_condition(c->right.c, FALSE);
1433 break;
1434
1435 case cond_or:
1436 yield = test_condition(c->left.c, FALSE) ||
1437 (*error_pointer == NULL &&
1438 test_condition(c->right.c, FALSE));
1439 break;
1440
1441 /* The personal test is meaningless in a system filter. The tests are now in
1442 a separate function (so Sieve can use them). However, an Exim filter does not
1443 scan Cc: (hence the FALSE argument). */
1444
1445 case cond_personal:
1446 yield = system_filtering? FALSE : filter_personal(c->left.a, FALSE);
1447 break;
1448
1449 case cond_delivered:
1450 yield = filter_delivered;
1451 break;
1452
1453 /* Only TRUE if a message is actually being processed; FALSE for address
1454 testing and verification. */
1455
1456 case cond_errormsg:
1457 yield = message_id[0] != 0 &&
1458 (sender_address == NULL || sender_address[0] == 0);
1459 break;
1460
1461 /* Only FALSE if a message is actually being processed; TRUE for address
1462 and filter testing and verification. */
1463
1464 case cond_firsttime:
1465 yield = filter_test != FTEST_NONE || message_id[0] == 0 || deliver_firsttime;
1466 break;
1467
1468 /* Only TRUE if a message is actually being processed; FALSE for address
1469 testing and verification. */
1470
1471 case cond_manualthaw:
1472 yield = message_id[0] != 0 && deliver_manual_thaw;
1473 break;
1474
1475 /* The foranyaddress condition loops through a list of addresses */
1476
1477 case cond_foranyaddress:
1478 p = c->left.u;
1479 pp = expand_string(p);
1480 if (pp == NULL)
1481 {
1482 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1483 "filter file: %s", p, expand_string_message);
1484 return FALSE;
1485 }
1486
1487 yield = FALSE;
1488 parse_allow_group = TRUE; /* Allow group syntax */
1489
1490 while (*pp != 0)
1491 {
1492 uschar *error;
1493 int start, end, domain;
1494 int saveend;
1495
1496 p = parse_find_address_end(pp, FALSE);
1497 saveend = *p;
1498
1499 *p = 0;
1500 filter_thisaddress =
1501 parse_extract_address(pp, &error, &start, &end, &domain, FALSE);
1502 *p = saveend;
1503
1504 if (filter_thisaddress != NULL)
1505 {
1506 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1507 (debug_selector & D_filter) != 0)
1508 {
1509 indent();
1510 debug_printf("Extracted address %s\n", filter_thisaddress);
1511 }
1512 yield = test_condition(c->right.c, FALSE);
1513 }
1514
1515 if (yield) break;
1516 if (saveend == 0) break;
1517 pp = p + 1;
1518 }
1519
1520 parse_allow_group = FALSE; /* Reset group syntax flags */
1521 parse_found_group = FALSE;
1522 break;
1523
1524 /* All other conditions have left and right values that need expanding;
1525 on error, it doesn't matter what value is returned. */
1526
1527 default:
1528 p = c->left.u;
1529 for (i = 0; i < 2; i++)
1530 {
1531 exp[i] = expand_string(p);
1532 if (exp[i] == NULL)
1533 {
1534 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1535 "filter file: %s", p, expand_string_message);
1536 return FALSE;
1537 }
1538 p = c->right.u;
1539 }
1540
1541 /* Inner switch for the different cases */
1542
1543 switch(c->type)
1544 {
1545 case cond_is:
1546 yield = strcmpic(exp[0], exp[1]) == 0;
1547 break;
1548
1549 case cond_IS:
1550 yield = Ustrcmp(exp[0], exp[1]) == 0;
1551 break;
1552
1553 case cond_contains:
1554 yield = strstric(exp[0], exp[1], FALSE) != NULL;
1555 break;
1556
1557 case cond_CONTAINS:
1558 yield = Ustrstr(exp[0], exp[1]) != NULL;
1559 break;
1560
1561 case cond_begins:
1562 yield = strncmpic(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1563 break;
1564
1565 case cond_BEGINS:
1566 yield = Ustrncmp(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1567 break;
1568
1569 case cond_ends:
1570 case cond_ENDS:
1571 {
1572 int len = Ustrlen(exp[1]);
1573 uschar *s = exp[0] + Ustrlen(exp[0]) - len;
1574 yield = (s < exp[0])? FALSE :
1575 ((c->type == cond_ends)? strcmpic(s, exp[1]) : Ustrcmp(s, exp[1])) == 0;
1576 }
1577 break;
1578
1579 case cond_matches:
1580 case cond_MATCHES:
1581 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1582 (debug_selector & D_filter) != 0)
1583 {
1584 debug_printf("Match expanded arguments:\n");
1585 debug_printf(" Subject = %s\n", exp[0]);
1586 debug_printf(" Pattern = %s\n", exp[1]);
1587 }
1588
1589 re = pcre_compile(CS exp[1],
1590 PCRE_COPT | ((c->type == cond_matches)? PCRE_CASELESS : 0),
1591 (const char **)&regcomp_error, &regcomp_error_offset, NULL);
1592
1593 if (re == NULL)
1594 {
1595 *error_pointer = string_sprintf("error while compiling "
1596 "regular expression \"%s\": %s at offset %d",
1597 exp[1], regcomp_error, regcomp_error_offset);
1598 return FALSE;
1599 }
1600
1601 yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1);
1602 break;
1603
1604 /* For above and below, convert the strings to numbers */
1605
1606 case cond_above:
1607 case cond_below:
1608 for (i = 0; i < 2; i++)
1609 {
1610 val[i] = get_number(exp[i], &yield);
1611 if (!yield)
1612 {
1613 *error_pointer = string_sprintf("malformed numerical string \"%s\"",
1614 exp[i]);
1615 return FALSE;
1616 }
1617 }
1618 yield = (c->type == cond_above)? (val[0] > val[1]) : (val[0] < val[1]);
1619 break;
1620 }
1621 break;
1622 }
1623
1624 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1625 (debug_selector & D_filter) != 0)
1626 {
1627 indent();
1628 debug_printf("%sondition is %s: ",
1629 toplevel? "C" : "Sub-c",
1630 (yield == c->testfor)? "true" : "false");
1631 print_condition(c, TRUE);
1632 debug_printf("\n");
1633 }
1634
1635 return yield == c->testfor;
1636 }
1637
1638
1639
1640 /*************************************************
1641 * Interpret chain of commands *
1642 *************************************************/
1643
1644 /* In testing state, just say what would be done rather than doing it. The
1645 testprint command just expands and outputs its argument in testing state, and
1646 does nothing otherwise.
1647
1648 Arguments:
1649 commands points to chain of commands to interpret
1650 generated where to hang newly-generated addresses
1651
1652 Returns: FF_DELIVERED success, a significant action was taken
1653 FF_NOTDELIVERED success, no significant action
1654 FF_DEFER defer requested
1655 FF_FAIL fail requested
1656 FF_FREEZE freeze requested
1657 FF_ERROR there was a problem
1658 */
1659
1660 static int
1661 interpret_commands(filter_cmd *commands, address_item **generated)
1662 {
1663 uschar *s;
1664 int mode;
1665 address_item *addr;
1666 BOOL condition_value;
1667
1668 while (commands != NULL)
1669 {
1670 int ff_ret;
1671 uschar *fmsg, *ff_name;
1672 uschar *expargs[MAILARGS_STRING_COUNT];
1673
1674 int i, n[2];
1675
1676 /* Expand the relevant number of arguments for the command that are
1677 not NULL. */
1678
1679 for (i = 0; i < (command_exparg_count[commands->command] & 15); i++)
1680 {
1681 uschar *ss = commands->args[i].u;
1682 if (ss == NULL)
1683 {
1684 expargs[i] = NULL;
1685 }
1686 else
1687 {
1688 expargs[i] = expand_string(ss);
1689 if (expargs[i] == NULL)
1690 {
1691 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1692 "%s command: %s", ss, command_list[commands->command],
1693 expand_string_message);
1694 return FF_ERROR;
1695 }
1696 }
1697 }
1698
1699 /* Now switch for each command, setting the "delivered" flag if any of them
1700 have "seen" set. */
1701
1702 if (commands->seen) filter_delivered = TRUE;
1703
1704 switch(commands->command)
1705 {
1706 case add_command:
1707 for (i = 0; i < 2; i++)
1708 {
1709 uschar *ss = expargs[i];
1710 uschar *end;
1711
1712 if (i == 1 && (*ss++ != 'n' || ss[1] != 0))
1713 {
1714 *error_pointer = string_sprintf("unknown variable \"%s\" in \"add\" "
1715 "command", expargs[i]);
1716 return FF_ERROR;
1717 }
1718
1719 /* Allow for "--" at the start of the value (from -$n0) for example */
1720 if (i == 0) while (ss[0] == '-' && ss[1] == '-') ss += 2;
1721
1722 n[i] = (int)Ustrtol(ss, &end, 0);
1723 if (*end != 0)
1724 {
1725 *error_pointer = string_sprintf("malformed number \"%s\" in \"add\" "
1726 "command", ss);
1727 return FF_ERROR;
1728 }
1729 }
1730
1731 filter_n[n[1]] += n[0];
1732 if (filter_test != FTEST_NONE) printf("Add %d to n%d\n", n[0], n[1]);
1733 break;
1734
1735 /* A deliver command's argument must be a valid address. Its optional
1736 second argument (system filter only) must also be a valid address. */
1737
1738 case deliver_command:
1739 for (i = 0; i < 2; i++)
1740 {
1741 s = expargs[i];
1742 if (s != NULL)
1743 {
1744 int start, end, domain;
1745 uschar *error;
1746 uschar *ss = parse_extract_address(s, &error, &start, &end, &domain,
1747 FALSE);
1748 if (ss != NULL)
1749 expargs[i] = ((filter_options & RDO_REWRITE) != 0)?
1750 rewrite_address(ss, TRUE, FALSE, global_rewrite_rules,
1751 rewrite_existflags) :
1752 rewrite_address_qualify(ss, TRUE);
1753 else
1754 {
1755 *error_pointer = string_sprintf("malformed address \"%s\" in "
1756 "filter file: %s", s, error);
1757 return FF_ERROR;
1758 }
1759 }
1760 }
1761
1762 /* Stick the errors address into a simple variable, as it will
1763 be referenced a few times. Check that the caller is permitted to
1764 specify it. */
1765
1766 s = expargs[1];
1767
1768 if (s != NULL && !system_filtering)
1769 {
1770 uschar *ownaddress = expand_string(US"$local_part@$domain");
1771 if (strcmpic(ownaddress, s) != 0)
1772 {
1773 *error_pointer = US"errors_to must point to the caller's address";
1774 return FF_ERROR;
1775 }
1776 }
1777
1778 /* Test case: report what would happen */
1779
1780 if (filter_test != FTEST_NONE)
1781 {
1782 indent();
1783 printf("%seliver message to: %s%s%s%s\n",
1784 (commands->seen)? "D" : "Unseen d",
1785 expargs[0],
1786 commands->noerror? " (noerror)" : "",
1787 (s != NULL)? " errors_to " : "",
1788 (s != NULL)? s : US"");
1789 }
1790
1791 /* Real case. */
1792
1793 else
1794 {
1795 DEBUG(D_filter) debug_printf("Filter: %sdeliver message to: %s%s%s%s\n",
1796 (commands->seen)? "" : "unseen ",
1797 expargs[0],
1798 commands->noerror? " (noerror)" : "",
1799 (s != NULL)? " errors_to " : "",
1800 (s != NULL)? s : US"");
1801
1802 /* Create the new address and add it to the chain, setting the
1803 af_ignore_error flag if necessary, and the errors address, which can be
1804 set in a system filter and to the local address in user filters. */
1805
1806 addr = deliver_make_addr(expargs[0], TRUE); /* TRUE => copy s */
1807 addr->p.errors_address = (s == NULL)?
1808 s : string_copy(s); /* Default is NULL */
1809 if (commands->noerror) setflag(addr, af_ignore_error);
1810 addr->next = *generated;
1811 *generated = addr;
1812 }
1813 break;
1814
1815 case save_command:
1816 s = expargs[0];
1817 mode = commands->args[1].i;
1818
1819 /* Test case: report what would happen */
1820
1821 if (filter_test != FTEST_NONE)
1822 {
1823 indent();
1824 if (mode < 0)
1825 printf("%save message to: %s%s\n", (commands->seen)?
1826 "S" : "Unseen s", s, commands->noerror? " (noerror)" : "");
1827 else
1828 printf("%save message to: %s %04o%s\n", (commands->seen)?
1829 "S" : "Unseen s", s, mode, commands->noerror? " (noerror)" : "");
1830 }
1831
1832 /* Real case: Ensure save argument starts with / if there is a home
1833 directory to prepend. */
1834
1835 else
1836 {
1837 DEBUG(D_filter) debug_printf("Filter: %ssave message to: %s%s\n",
1838 (commands->seen)? "" : "unseen ", s,
1839 commands->noerror? " (noerror)" : "");
1840 if (s[0] != '/' && deliver_home != NULL && deliver_home[0] != 0)
1841 s = string_sprintf("%s/%s", deliver_home, s);
1842
1843 /* Create the new address and add it to the chain, setting the
1844 af_pfr and af_file flags, the af_ignore_error flag if necessary, and the
1845 mode value. */
1846
1847 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1848 setflag(addr, af_pfr|af_file);
1849 if (commands->noerror) setflag(addr, af_ignore_error);
1850 addr->mode = mode;
1851 addr->next = *generated;
1852 *generated = addr;
1853 }
1854 break;
1855
1856 case pipe_command:
1857 s = string_copy(commands->args[0].u);
1858 if (filter_test != FTEST_NONE)
1859 {
1860 indent();
1861 printf("%sipe message to: %s%s\n", (commands->seen)?
1862 "P" : "Unseen p", s, commands->noerror? " (noerror)" : "");
1863 }
1864 else /* Ensure pipe command starts with | */
1865 {
1866 DEBUG(D_filter) debug_printf("Filter: %spipe message to: %s%s\n",
1867 (commands->seen)? "" : "unseen ", s,
1868 commands->noerror? " (noerror)" : "");
1869 if (s[0] != '|') s = string_sprintf("|%s", s);
1870
1871 /* Create the new address and add it to the chain, setting the
1872 af_ignore_error flag if necessary. Set the af_expand_pipe flag so that
1873 each command argument is expanded in the transport after the command
1874 has been split up into separate arguments. */
1875
1876 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1877 setflag(addr, af_pfr|af_expand_pipe);
1878 if (commands->noerror) setflag(addr, af_ignore_error);
1879 addr->next = *generated;
1880 *generated = addr;
1881
1882 /* If there are any numeric variables in existence (e.g. after a regex
1883 condition), or if $thisaddress is set, take a copy for use in the
1884 expansion. Note that we can't pass NULL for filter_thisaddress, because
1885 NULL terminates the list. */
1886
1887 if (expand_nmax >= 0 || filter_thisaddress != NULL)
1888 {
1889 int i;
1890 int ecount = (expand_nmax >= 0)? expand_nmax : -1;
1891 uschar **ss = store_get(sizeof(uschar *) * (ecount + 3));
1892 addr->pipe_expandn = ss;
1893 if (filter_thisaddress == NULL) filter_thisaddress = US"";
1894 *ss++ = string_copy(filter_thisaddress);
1895 for (i = 0; i <= expand_nmax; i++)
1896 *ss++ = string_copyn(expand_nstring[i], expand_nlength[i]);
1897 *ss = NULL;
1898 }
1899 }
1900 break;
1901
1902 /* Set up the file name and mode, and close any previously open
1903 file. */
1904
1905 case logfile_command:
1906 log_mode = commands->args[1].i;
1907 if (log_mode == -1) log_mode = 0600;
1908 if (log_fd >= 0)
1909 {
1910 close(log_fd);
1911 log_fd = -1;
1912 }
1913 log_filename = expargs[0];
1914 if (filter_test != FTEST_NONE)
1915 {
1916 indent();
1917 printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
1918 }
1919 break;
1920
1921 case logwrite_command:
1922 s = expargs[0];
1923
1924 if (filter_test != FTEST_NONE)
1925 {
1926 indent();
1927 printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
1928 string_printing(s));
1929 }
1930
1931 /* Attempt to write to a log file only if configured as permissible.
1932 Logging may be forcibly skipped for verifying or testing. */
1933
1934 else if ((filter_options & RDO_LOG) != 0) /* Locked out */
1935 {
1936 DEBUG(D_filter)
1937 debug_printf("filter log command aborted: euid=%ld\n",
1938 (long int)geteuid());
1939 *error_pointer = US"logwrite command forbidden";
1940 return FF_ERROR;
1941 }
1942 else if ((filter_options & RDO_REALLOG) != 0)
1943 {
1944 int len;
1945 DEBUG(D_filter) debug_printf("writing filter log as euid %ld\n",
1946 (long int)geteuid());
1947 if (log_fd < 0)
1948 {
1949 if (log_filename == NULL)
1950 {
1951 *error_pointer = US"attempt to obey \"logwrite\" command "
1952 "without a previous \"logfile\"";
1953 return FF_ERROR;
1954 }
1955 log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode);
1956 if (log_fd < 0)
1957 {
1958 *error_pointer = string_open_failed(errno, "filter log file \"%s\"",
1959 log_filename);
1960 return FF_ERROR;
1961 }
1962 }
1963 len = Ustrlen(s);
1964 if (write(log_fd, s, len) != len)
1965 {
1966 *error_pointer = string_sprintf("write error on file \"%s\": %s",
1967 log_filename, strerror(errno));
1968 return FF_ERROR;
1969 }
1970 }
1971 else
1972 {
1973 DEBUG(D_filter) debug_printf("skipping logwrite (verifying or testing)\n");
1974 }
1975 break;
1976
1977 /* Header addition and removal is available only in the system filter. The
1978 command is rejected at parse time otherwise. However "headers charset" is
1979 always permitted. */
1980
1981 case headers_command:
1982 {
1983 int subtype = commands->args[1].i;
1984 s = expargs[0];
1985
1986 if (filter_test != FTEST_NONE)
1987 printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" :
1988 (subtype == FALSE)? "remove" : "charset", string_printing(s));
1989
1990 if (subtype == TRUE)
1991 {
1992 while (isspace(*s)) s++;
1993 if (s[0] != 0)
1994 {
1995 header_add(htype_other, "%s%s", s, (s[Ustrlen(s)-1] == '\n')?
1996 "" : "\n");
1997 header_last->type = header_checkname(header_last, FALSE);
1998 if (header_last->type >= 'a') header_last->type = htype_other;
1999 }
2000 }
2001
2002 else if (subtype == FALSE)
2003 {
2004 int sep = 0;
2005 uschar *ss;
2006 uschar *list = s;
2007 uschar buffer[128];
2008 while ((ss = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
2009 != NULL)
2010 header_remove(0, ss);
2011 }
2012
2013 /* This setting lasts only while the filter is running; on exit, the
2014 variable is reset to the previous value. */
2015
2016 else headers_charset = s;
2017 }
2018 break;
2019
2020 /* Defer, freeze, and fail are available only when explicitly permitted.
2021 These commands are rejected at parse time otherwise. The message can get
2022 very long by the inclusion of message headers; truncate if it is, and also
2023 ensure printing characters so as not to mess up log files. */
2024
2025 case defer_command:
2026 ff_name = US"defer";
2027 ff_ret = FF_DEFER;
2028 goto DEFERFREEZEFAIL;
2029
2030 case fail_command:
2031 ff_name = US"fail";
2032 ff_ret = FF_FAIL;
2033 goto DEFERFREEZEFAIL;
2034
2035 case freeze_command:
2036 ff_name = US"freeze";
2037 ff_ret = FF_FREEZE;
2038
2039 DEFERFREEZEFAIL:
2040 fmsg = expargs[0];
2041 if (Ustrlen(fmsg) > 1024) Ustrcpy(fmsg + 1000, " ... (truncated)");
2042 fmsg = string_printing(fmsg);
2043 *error_pointer = fmsg;
2044
2045 if (filter_test != FTEST_NONE)
2046 {
2047 indent();
2048 printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
2049 }
2050 else DEBUG(D_filter) debug_printf("Filter: %s \"%s\"\n", ff_name, fmsg);
2051 return ff_ret;
2052
2053 case finish_command:
2054 if (filter_test != FTEST_NONE)
2055 {
2056 indent();
2057 printf("%sinish\n", (commands->seen)? "Seen f" : "F");
2058 }
2059 else
2060 {
2061 DEBUG(D_filter) debug_printf("Filter: %sfinish\n",
2062 (commands->seen)? " Seen " : "");
2063 }
2064 finish_obeyed = TRUE;
2065 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2066
2067 case if_command:
2068 {
2069 uschar *save_address = filter_thisaddress;
2070 int ok = FF_DELIVERED;
2071 condition_value = test_condition(commands->args[0].c, TRUE);
2072 if (*error_pointer != NULL) ok = FF_ERROR; else
2073 {
2074 output_indent += 2;
2075 ok = interpret_commands(commands->args[condition_value? 1:2].f,
2076 generated);
2077 output_indent -= 2;
2078 }
2079 filter_thisaddress = save_address;
2080 if (finish_obeyed || (ok != FF_DELIVERED && ok != FF_NOTDELIVERED))
2081 return ok;
2082 }
2083 break;
2084
2085
2086 /* To try to catch runaway loops, do not generate mail if the
2087 return path is unset or if a non-trusted user supplied -f <>
2088 as the return path. */
2089
2090 case mail_command:
2091 case vacation_command:
2092 if (return_path == NULL || return_path[0] == 0)
2093 {
2094 if (filter_test != FTEST_NONE)
2095 printf("%s command ignored because return_path is empty\n",
2096 command_list[commands->command]);
2097 else DEBUG(D_filter) debug_printf("%s command ignored because return_path "
2098 "is empty\n", command_list[commands->command]);
2099 break;
2100 }
2101
2102 /* Check the contents of the strings. The type of string can be deduced
2103 from the value of i.
2104
2105 . If i is equal to mailarg_index_text it's a text string for the body,
2106 where anything goes.
2107
2108 . If i is > mailarg_index_text, we are dealing with a file name, which
2109 cannot contain non-printing characters.
2110
2111 . If i is less than mailarg_index_headers we are dealing with something
2112 that will go in a single message header line, where newlines must be
2113 followed by white space.
2114
2115 . If i is equal to mailarg_index_headers, we have a string that contains
2116 one or more headers. Newlines that are not followed by white space must
2117 be followed by a header name.
2118 */
2119
2120 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
2121 {
2122 uschar *p;
2123 uschar *s = expargs[i];
2124
2125 if (s == NULL) continue;
2126
2127 if (i != mailarg_index_text) for (p = s; *p != 0; p++)
2128 {
2129 int c = *p;
2130 if (i > mailarg_index_text)
2131 {
2132 if (!mac_isprint(c))
2133 {
2134 *error_pointer = string_sprintf("non-printing character in \"%s\" "
2135 "in %s command", string_printing(s),
2136 command_list[commands->command]);
2137 return FF_ERROR;
2138 }
2139 }
2140
2141 /* i < mailarg_index_text */
2142
2143 else if (c == '\n' && !isspace(p[1]))
2144 {
2145 if (i < mailarg_index_headers)
2146 {
2147 *error_pointer = string_sprintf("\\n not followed by space in "
2148 "\"%.1024s\" in %s command", string_printing(s),
2149 command_list[commands->command]);
2150 return FF_ERROR;
2151 }
2152
2153 /* Check for the start of a new header line within the string */
2154
2155 else
2156 {
2157 uschar *pp;
2158 for (pp = p + 1;; pp++)
2159 {
2160 c = *pp;
2161 if (c == ':' && pp != p + 1) break;
2162 if (c == 0 || c == ':' || isspace(*pp))
2163 {
2164 *error_pointer = string_sprintf("\\n not followed by space or "
2165 "valid header name in \"%.1024s\" in %s command",
2166 string_printing(s), command_list[commands->command]);
2167 return FF_ERROR;
2168 }
2169 pp++;
2170 }
2171 p = pp;
2172 }
2173 }
2174 } /* Loop to scan the string */
2175
2176 /* The string is OK */
2177
2178 commands->args[i].u = s;
2179 }
2180
2181 /* Proceed with mail or vacation command */
2182
2183 if (filter_test != FTEST_NONE)
2184 {
2185 uschar *to = commands->args[mailarg_index_to].u;
2186 indent();
2187 printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2188 (to == NULL)? US"<default>" : to,
2189 (commands->command == vacation_command)? " (vacation)" : "",
2190 (commands->noerror)? " (noerror)" : "");
2191 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2192 {
2193 uschar *arg = commands->args[i].u;
2194 if (arg != NULL)
2195 {
2196 int len = Ustrlen(mailargs[i]);
2197 int indent = (debug_selector != 0)? output_indent : 0;
2198 while (len++ < 7 + indent) printf(" ");
2199 printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2200 (commands->args[mailarg_index_expand].u != NULL &&
2201 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2202 }
2203 }
2204 if (commands->args[mailarg_index_return].u != NULL)
2205 printf("Return original message\n");
2206 }
2207 else
2208 {
2209 uschar *tt;
2210 uschar *to = commands->args[mailarg_index_to].u;
2211 if (to == NULL) to = expand_string(US"$reply_address");
2212 while (isspace(*to)) to++;
2213
2214 for (tt = to; *tt != 0; tt++) /* Get rid of newlines so that */
2215 if (*tt == '\n') *tt = ' '; /* the eventual log line is OK */
2216
2217 DEBUG(D_filter)
2218 {
2219 debug_printf("Filter: %smail to: %s%s%s\n",
2220 (commands->seen)? "seen " : "",
2221 to,
2222 (commands->command == vacation_command)? " (vacation)" : "",
2223 (commands->noerror)? " (noerror)" : "");
2224 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2225 {
2226 uschar *arg = commands->args[i].u;
2227 if (arg != NULL)
2228 {
2229 int len = Ustrlen(mailargs[i]);
2230 while (len++ < 15) debug_printf(" ");
2231 debug_printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2232 (commands->args[mailarg_index_expand].u != NULL &&
2233 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2234 }
2235 }
2236 }
2237
2238 /* Create the "address" for the autoreply */
2239
2240 addr = deliver_make_addr(string_sprintf(">%.256s", to), FALSE);
2241 setflag(addr, af_pfr);
2242 if (commands->noerror) setflag(addr, af_ignore_error);
2243 addr->next = *generated;
2244 *generated = addr;
2245 addr->reply = store_get(sizeof(reply_item));
2246 addr->reply->from = NULL;
2247 addr->reply->to = string_copy(to);
2248 addr->reply->file_expand =
2249 commands->args[mailarg_index_expand].u != NULL;
2250 addr->reply->expand_forbid = expand_forbid;
2251 addr->reply->return_message =
2252 commands->args[mailarg_index_return].u != NULL;
2253 addr->reply->once_repeat = 0;
2254
2255 if (commands->args[mailarg_index_once_repeat].u != NULL)
2256 {
2257 addr->reply->once_repeat =
2258 readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2259 FALSE);
2260 if (addr->reply->once_repeat < 0)
2261 {
2262 *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2263 "in mail or vacation command: %s",
2264 commands->args[mailarg_index_once_repeat]);
2265 return FF_ERROR;
2266 }
2267 }
2268
2269 /* Set up all the remaining string arguments (those other than "to") */
2270
2271 for (i = 1; i < mailargs_string_passed; i++)
2272 {
2273 uschar *ss = commands->args[i].u;
2274 *((uschar **)(((uschar *)(addr->reply)) + reply_offsets[i])) =
2275 (ss == NULL)? NULL : string_copy(ss);
2276 }
2277 }
2278 break;
2279
2280 case testprint_command:
2281 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2282 {
2283 uschar *s = string_printing(expargs[0]);
2284 if (filter_test == FTEST_NONE)
2285 debug_printf("Filter: testprint: %s\n", s);
2286 else
2287 printf("Testprint: %s\n", s);
2288 }
2289 }
2290
2291 commands = commands->next;
2292 }
2293
2294 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2295 }
2296
2297
2298
2299 /*************************************************
2300 * Test for a personal message *
2301 *************************************************/
2302
2303 /* This function is global so that it can also be called from the code that
2304 implements Sieve filters.
2305
2306 Arguments:
2307 aliases a chain of aliases
2308 scan_cc TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2309
2310 Returns: TRUE if the message is deemed to be personal
2311 */
2312
2313 BOOL
2314 filter_personal(string_item *aliases, BOOL scan_cc)
2315 {
2316 uschar *self, *self_from, *self_to;
2317 uschar *psself = NULL, *psself_from = NULL, *psself_to = NULL;
2318 void *reset_point = store_get(0);
2319 BOOL yield;
2320 header_line *h;
2321 int to_count = 2;
2322 int from_count = 9;
2323
2324 /* If any header line in the message starts with "List-", it is not
2325 a personal message. */
2326
2327 for (h = header_list; h != NULL; h = h->next)
2328 {
2329 if (h->type != htype_old && h->slen > 5 &&
2330 strncmpic(h->text, US"List-", 5) == 0)
2331 return FALSE;
2332 }
2333
2334 /* Set up "my" address */
2335
2336 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2337 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2338 global_rewrite_rules);
2339 self_to = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2340 global_rewrite_rules);
2341
2342
2343 if (self_from == NULL) self_from = self;
2344 if (self_to == NULL) self_to = self;
2345
2346 /* If there's a prefix or suffix set, we must include the prefixed/
2347 suffixed version of the local part in the tests. */
2348
2349 if (deliver_localpart_prefix != NULL || deliver_localpart_suffix != NULL)
2350 {
2351 psself = string_sprintf("%s%s%s@%s",
2352 (deliver_localpart_prefix == NULL)? US"" : deliver_localpart_prefix,
2353 deliver_localpart,
2354 (deliver_localpart_suffix == NULL)? US"" : deliver_localpart_suffix,
2355 deliver_domain);
2356 psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2357 global_rewrite_rules);
2358 psself_to = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2359 global_rewrite_rules);
2360 if (psself_from == NULL) psself_from = psself;
2361 if (psself_to == NULL) psself_to = psself;
2362 to_count += 2;
2363 from_count += 2;
2364 }
2365
2366 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2367
2368 yield =
2369 (
2370 header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2371 psself_to) ||
2372 (scan_cc &&
2373 (
2374 header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2375 psself, psself_to)
2376 ||
2377 header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2378 psself, psself_to)
2379 )
2380 )
2381 ) &&
2382
2383 header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2384 "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2385 "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2386
2387 header_match(US"auto-submitted:", FALSE, FALSE, NULL, 1, "auto-") &&
2388 header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2389
2390 (sender_address == NULL || sender_address[0] != 0);
2391
2392 store_reset(reset_point);
2393 return yield;
2394 }
2395
2396
2397
2398 /*************************************************
2399 * Interpret a mail filter file *
2400 *************************************************/
2401
2402 /*
2403 Arguments:
2404 filter points to the entire file, read into store as a single string
2405 options controls whether various special things are allowed, and requests
2406 special actions
2407 generated where to hang newly-generated addresses
2408 error where to pass back an error text
2409
2410 Returns: FF_DELIVERED success, a significant action was taken
2411 FF_NOTDELIVERED success, no significant action
2412 FF_DEFER defer requested
2413 FF_FAIL fail requested
2414 FF_FREEZE freeze requested
2415 FF_ERROR there was a problem
2416 */
2417
2418 int
2419 filter_interpret(uschar *filter, int options, address_item **generated,
2420 uschar **error)
2421 {
2422 int i;
2423 int yield = FF_ERROR;
2424 uschar *ptr = filter;
2425 uschar *save_headers_charset = headers_charset;
2426 filter_cmd *commands = NULL;
2427 filter_cmd **lastcmdptr = &commands;
2428
2429 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2430
2431 /* Initialize "not in an if command", set the global flag that is always TRUE
2432 while filtering, and zero the variables. */
2433
2434 expect_endif = 0;
2435 output_indent = 0;
2436 filter_running = TRUE;
2437 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2438
2439 /* To save having to pass certain values about all the time, make them static.
2440 Also initialize the line number, for error messages, and the log file
2441 variables. */
2442
2443 filter_options = options;
2444 filter_delivered = FALSE;
2445 finish_obeyed = FALSE;
2446 error_pointer = error;
2447 *error_pointer = NULL;
2448 line_number = 1;
2449 log_fd = -1;
2450 log_mode = 0600;
2451 log_filename = NULL;
2452
2453 /* Scan filter file for syntax and build up an interpretation thereof, and
2454 interpret the compiled commands, and if testing, say whether we ended up
2455 delivered or not, unless something went wrong. */
2456
2457 seen_force = FALSE;
2458 ptr = nextsigchar(ptr, TRUE);
2459
2460 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2461 yield = interpret_commands(commands, generated);
2462
2463 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2464 {
2465 uschar *s = US"";
2466 switch(yield)
2467 {
2468 case FF_DEFER:
2469 s = US"Filtering ended by \"defer\".";
2470 break;
2471
2472 case FF_FREEZE:
2473 s = US"Filtering ended by \"freeze\".";
2474 break;
2475
2476 case FF_FAIL:
2477 s = US"Filtering ended by \"fail\".";
2478 break;
2479
2480 case FF_DELIVERED:
2481 s = US"Filtering set up at least one significant delivery "
2482 "or other action.\n"
2483 "No other deliveries will occur.";
2484 break;
2485
2486 case FF_NOTDELIVERED:
2487 s = US"Filtering did not set up a significant delivery.\n"
2488 "Normal delivery will occur.";
2489 break;
2490
2491 case FF_ERROR:
2492 s = string_sprintf("Filter error: %s", *error);
2493 break;
2494 }
2495
2496 if (filter_test != FTEST_NONE) printf("%s\n", CS s);
2497 else debug_printf("%s\n", s);
2498 }
2499
2500 /* Close the log file if it was opened, and kill off any numerical variables
2501 before returning. Reset the header decoding charset. */
2502
2503 if (log_fd >= 0) close(log_fd);
2504 expand_nmax = -1;
2505 filter_running = FALSE;
2506 headers_charset = save_headers_charset;
2507
2508 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2509 return yield;
2510 }
2511
2512
2513 /* End of filter.c */