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