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