Use %ld not %l
[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 */
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   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(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 uschar *
256 nextsigchar(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 uschar *
294 nextword(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 uschar *
330 nextitem(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) != 0 && *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       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(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 uschar *
420 read_condition(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 == 0)
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 != NULL) 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         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       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     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
666     if (Ustrcmp(buffer, "then") == 0)
667       {
668       if (toplevel) *saveptr = 0;
669       else *error_pointer = string_sprintf("missing \")\" at end of "
670           "condition near line %d of filter file", line_number);
671       break;
672       }
673
674     /* "And" causes a new condition block to replace the one we have
675     just read, which becomes the left sub-condition. The current pointer
676     is reset to the pointer for the right sub-condition. We have to keep
677     track of the tree of sequential "ands", so as to traverse back up it
678     if an "or" is met. */
679
680     else if (Ustrcmp(buffer, "and") == 0)
681       {
682       condition_block *andc = store_get(sizeof(condition_block), FALSE);
683       andc->parent = current_parent;
684       andc->type = cond_and;
685       andc->testfor = TRUE;
686       andc->left.c = c;
687       andc->right.u = NULL;    /* insurance */
688       *current = andc;
689       current = &(andc->right.c);
690       current_parent = andc;
691       }
692
693     /* "Or" is similar, but has to be done a bit more carefully to
694     ensure that "and" is more binding. If there's a parent set, we
695     are following a sequence of "and"s and must track back to their
696     start. */
697
698     else if (Ustrcmp(buffer, "or") == 0)
699       {
700       condition_block *orc = store_get(sizeof(condition_block), FALSE);
701       condition_block *or_parent = NULL;
702
703       if (current_parent)
704         {
705         while (current_parent->parent &&
706                current_parent->parent->type == cond_and)
707           current_parent = current_parent->parent;
708
709         /* If the parent has a parent, it must be an "or" parent. */
710
711         if (current_parent->parent)
712           or_parent = current_parent->parent;
713         }
714
715       orc->parent = or_parent;
716       if (!or_parent) *cond = orc;
717       else or_parent->right.c = orc;
718       orc->type = cond_or;
719       orc->testfor = TRUE;
720       orc->left.c = (current_parent == NULL)? c : current_parent;
721       orc->right.c = NULL;   /* insurance */
722       current = &(orc->right.c);
723       current_parent = orc;
724       }
725
726     /* Otherwise there is a disaster */
727
728     else
729       {
730       *error_pointer = string_sprintf("\"and\" or \"or\" or \"%s\" "
731         "expected near line %d of filter file, but found \"%s\"",
732           toplevel? "then" : ")", line_number, buffer);
733       break;
734       }
735     }
736   }
737
738 return nextsigchar(ptr, TRUE);
739 }
740
741
742
743 /*************************************************
744 *             Output the current indent          *
745 *************************************************/
746
747 static void
748 indent(void)
749 {
750 int i;
751 for (i = 0; i < output_indent; i++) debug_printf(" ");
752 }
753
754
755
756 /*************************************************
757 *          Condition printer: for debugging      *
758 *************************************************/
759
760 /*
761 Arguments:
762   c           the block at the top of the tree
763   toplevel    TRUE at toplevel - stops overall brackets
764
765 Returns:      nothing
766 */
767
768 static void
769 print_condition(condition_block *c, BOOL toplevel)
770 {
771 const char *name = (c->testfor)? cond_names[c->type] : cond_not_names[c->type];
772 switch(c->type)
773   {
774   case cond_personal:
775   case cond_delivered:
776   case cond_errormsg:
777   case cond_firsttime:
778   case cond_manualthaw:
779   debug_printf("%s", name);
780   break;
781
782   case cond_is:
783   case cond_IS:
784   case cond_matches:
785   case cond_MATCHES:
786   case cond_contains:
787   case cond_CONTAINS:
788   case cond_begins:
789   case cond_BEGINS:
790   case cond_ends:
791   case cond_ENDS:
792   case cond_above:
793   case cond_below:
794   debug_printf("%s %s %s", c->left.u, name, c->right.u);
795   break;
796
797   case cond_and:
798   if (!c->testfor) debug_printf("not (");
799   print_condition(c->left.c, FALSE);
800   debug_printf(" %s ", cond_names[c->type]);
801   print_condition(c->right.c, FALSE);
802   if (!c->testfor) debug_printf(")");
803   break;
804
805   case cond_or:
806   if (!c->testfor) debug_printf("not (");
807   else if (!toplevel) debug_printf("(");
808   print_condition(c->left.c, FALSE);
809   debug_printf(" %s ", cond_names[c->type]);
810   print_condition(c->right.c, FALSE);
811   if (!toplevel || !c->testfor) debug_printf(")");
812   break;
813
814   case cond_foranyaddress:
815   debug_printf("%s %s (", name, c->left.u);
816   print_condition(c->right.c, FALSE);
817   debug_printf(")");
818   break;
819   }
820 }
821
822
823
824
825 /*************************************************
826 *            Read one filtering command          *
827 *************************************************/
828
829 /*
830 Arguments:
831    pptr        points to pointer to first character of command; the pointer
832                  is updated to point after the last character read
833    lastcmdptr  points to pointer to pointer to last command; used for hanging
834                  on the newly read command
835
836 Returns:       TRUE if command successfully read, else FALSE
837 */
838
839 static BOOL
840 read_command(uschar **pptr, filter_cmd ***lastcmdptr)
841 {
842 int command, i, cmd_bit;
843 filter_cmd *new, **newlastcmdptr;
844 BOOL yield = TRUE;
845 BOOL was_seen_or_unseen = FALSE;
846 BOOL was_noerror = FALSE;
847 uschar buffer[1024];
848 uschar *ptr = *pptr;
849 uschar *saveptr;
850 uschar *fmsg = NULL;
851
852 /* Read the next word and find which command it is. Command words are normally
853 terminated by white space, but there are two exceptions, which are the "if" and
854 "elif" commands. We must allow for them to be terminated by an opening bracket,
855 as brackets are allowed in conditions and users will expect not to require
856 white space here. */
857
858 if (Ustrncmp(ptr, "if(", 3) == 0)
859   {
860   Ustrcpy(buffer, US"if");
861   ptr += 2;
862   }
863 else if (Ustrncmp(ptr, "elif(", 5) == 0)
864   {
865   Ustrcpy(buffer, US"elif");
866   ptr += 4;
867   }
868 else
869   {
870   ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
871   if (*error_pointer != NULL) return FALSE;
872   }
873
874 for (command = 0; command < command_list_count; command++)
875   if (Ustrcmp(buffer, command_list[command]) == 0) break;
876
877 /* Handle the individual commands */
878
879 switch (command)
880   {
881   /* Add takes two arguments, separated by the word "to". Headers has two
882   arguments, but the first must be "add", "remove", or "charset", and it gets
883   stored in the second argument slot. Neither may be preceded by seen, unseen
884   or noerror. */
885
886   case add_command:
887   case headers_command:
888   if (seen_force || noerror_force)
889     {
890     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
891       "found before an \"%s\" command near line %d",
892         command_list[command], line_number);
893     yield = FALSE;
894     }
895   /* Fall through */
896
897   /* Logwrite, logfile, pipe, and testprint all take a single argument, save
898   and logfile can have an option second argument for the mode, and deliver can
899   have "errors_to <address>" in a system filter, or in a user filter if the
900   address is the current one. */
901
902   case deliver_command:
903   case logfile_command:
904   case logwrite_command:
905   case pipe_command:
906   case save_command:
907   case testprint_command:
908
909   ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
910   if (*buffer == 0)
911     *error_pointer = string_sprintf("\"%s\" requires an argument "
912       "near line %d of filter file", command_list[command], line_number);
913
914   if (*error_pointer != NULL) yield = FALSE; else
915     {
916     union argtypes argument, second_argument;
917
918     argument.u = second_argument.u = NULL;
919
920     if (command == add_command)
921       {
922       argument.u = string_copy(buffer);
923       ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
924       if (*buffer == 0 || Ustrcmp(buffer, "to") != 0)
925         *error_pointer = string_sprintf("\"to\" expected in \"add\" command "
926           "near line %d of filter file", line_number);
927       else
928         {
929         ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
930         if (*buffer == 0)
931           *error_pointer = string_sprintf("value missing after \"to\" "
932             "near line %d of filter file", line_number);
933         else second_argument.u = string_copy(buffer);
934         }
935       }
936
937     else if (command == headers_command)
938       {
939       if (Ustrcmp(buffer, "add") == 0)
940         second_argument.b = TRUE;
941       else
942         if (Ustrcmp(buffer, "remove") == 0) second_argument.b = FALSE;
943       else
944         if (Ustrcmp(buffer, "charset") == 0)
945           second_argument.b = TRUE_UNSET;
946       else
947         {
948         *error_pointer = string_sprintf("\"add\", \"remove\", or \"charset\" "
949           "expected after \"headers\" near line %d of filter file",
950             line_number);
951         yield = FALSE;
952         }
953
954       if (!f.system_filtering && second_argument.b != TRUE_UNSET)
955         {
956         *error_pointer = string_sprintf("header addition and removal is "
957           "available only in system filters: near line %d of filter file",
958           line_number);
959         yield = FALSE;
960         break;
961         }
962
963       if (yield)
964         {
965         ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
966         if (*buffer == 0)
967           *error_pointer = string_sprintf("value missing after \"add\", "
968             "\"remove\", or \"charset\" near line %d of filter file",
969               line_number);
970         else argument.u = string_copy(buffer);
971         }
972       }
973
974     /* The argument for the logwrite command must end in a newline, and the save
975     and logfile commands can have an optional mode argument. The deliver
976     command can have an optional "errors_to <address>" for a system filter,
977     or for a user filter if the address is the user's address. Accept the
978     syntax here - the check is later. */
979
980     else
981       {
982       if (command == logwrite_command)
983         {
984         int len = Ustrlen(buffer);
985         if (len == 0 || buffer[len-1] != '\n') Ustrcat(buffer, US"\n");
986         }
987
988       argument.u = string_copy(buffer);
989
990       if (command == save_command || command == logfile_command)
991         {
992         if (isdigit(*ptr))
993           {
994           ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
995           second_argument.i = (int)Ustrtol(buffer, NULL, 8);
996           }
997         else second_argument.i = -1;
998         }
999
1000       else if (command == deliver_command)
1001         {
1002         uschar *save_ptr = ptr;
1003         ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1004         if (Ustrcmp(buffer, "errors_to") == 0)
1005           {
1006           ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1007           second_argument.u = string_copy(buffer);
1008           }
1009         else ptr = save_ptr;
1010         }
1011       }
1012
1013     /* Set up the command block. Seen defaults TRUE for delivery commands,
1014     FALSE for logging commands, and it doesn't matter for testprint, as
1015     that doesn't change the "delivered" status. */
1016
1017     if (*error_pointer != NULL) yield = FALSE; else
1018       {
1019       new = store_get(sizeof(filter_cmd) + sizeof(union argtypes), FALSE);
1020       new->next = NULL;
1021       **lastcmdptr = new;
1022       *lastcmdptr = &(new->next);
1023       new->command = command;
1024       new->seen = seen_force? seen_value : command_exparg_count[command] >= 128;
1025       new->noerror = noerror_force;
1026       new->args[0] = argument;
1027       new->args[1] = second_argument;
1028       }
1029     }
1030   break;
1031
1032
1033   /* Elif, else and endif just set a flag if expected. */
1034
1035   case elif_command:
1036   case else_command:
1037   case endif_command:
1038   if (seen_force || noerror_force)
1039     {
1040     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1041       "near line %d is not followed by a command", line_number);
1042     yield = FALSE;
1043     }
1044
1045   if (expect_endif > 0)
1046     had_else_endif = (command == elif_command)? had_elif :
1047                      (command == else_command)? had_else : had_endif;
1048   else
1049     {
1050     *error_pointer = string_sprintf("unexpected \"%s\" command near "
1051       "line %d of filter file", buffer, line_number);
1052     yield = FALSE;
1053     }
1054   break;
1055
1056
1057   /* Defer, freeze, and fail are available only if permitted. */
1058
1059   case defer_command:
1060   cmd_bit = RDO_DEFER;
1061   goto DEFER_FREEZE_FAIL;
1062
1063   case fail_command:
1064   cmd_bit = RDO_FAIL;
1065   goto DEFER_FREEZE_FAIL;
1066
1067   case freeze_command:
1068   cmd_bit = RDO_FREEZE;
1069
1070   DEFER_FREEZE_FAIL:
1071   if ((filter_options & cmd_bit) == 0)
1072     {
1073     *error_pointer = string_sprintf("filtering command \"%s\" is disabled: "
1074       "near line %d of filter file", buffer, line_number);
1075     yield = FALSE;
1076     break;
1077     }
1078
1079   /* A text message can be provided after the "text" keyword, or
1080   as a string in quotes. */
1081
1082   saveptr = ptr;
1083   ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1084   if (*saveptr != '\"' && (*buffer == 0 || Ustrcmp(buffer, "text") != 0))
1085     {
1086     ptr = saveptr;
1087     fmsg = US"";
1088     }
1089   else
1090     {
1091     if (*saveptr != '\"')
1092       ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1093     fmsg = string_copy(buffer);
1094     }
1095
1096   /* Drop through and treat as "finish", but never set "seen". */
1097
1098   seen_value = FALSE;
1099
1100   /* Finish has no arguments; fmsg defaults to NULL */
1101
1102   case finish_command:
1103   new = store_get(sizeof(filter_cmd), FALSE);
1104   new->next = NULL;
1105   **lastcmdptr = new;
1106   *lastcmdptr = &(new->next);
1107   new->command = command;
1108   new->seen = seen_force? seen_value : FALSE;
1109   new->args[0].u = fmsg;
1110   break;
1111
1112
1113   /* Seen, unseen, and noerror are not allowed before if, which takes a
1114   condition argument and then and else sub-commands. */
1115
1116   case if_command:
1117   if (seen_force || noerror_force)
1118     {
1119     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1120       "found before an \"if\" command near line %d",
1121         line_number);
1122     yield = FALSE;
1123     }
1124
1125   /* Set up the command block for if */
1126
1127   new = store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes), FALSE);
1128   new->next = NULL;
1129   **lastcmdptr = new;
1130   *lastcmdptr = &(new->next);
1131   new->command = command;
1132   new->seen = FALSE;
1133   new->args[0].u = NULL;
1134   new->args[1].u = new->args[2].u = NULL;
1135   new->args[3].u = ptr;
1136
1137   /* Read the condition */
1138
1139   ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1140   if (*error_pointer != NULL) { yield = FALSE; break; }
1141
1142   /* Read the commands to be obeyed if the condition is true */
1143
1144   newlastcmdptr = &(new->args[1].f);
1145   if (!read_command_list(&ptr, &newlastcmdptr, TRUE)) yield = FALSE;
1146
1147   /* If commands were successfully read, handle the various possible
1148   terminators. There may be a number of successive "elif" sections. */
1149
1150   else
1151     {
1152     while (had_else_endif == had_elif)
1153       {
1154       filter_cmd *newnew =
1155         store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes), FALSE);
1156       new->args[2].f = newnew;
1157       new = newnew;
1158       new->next = NULL;
1159       new->command = command;
1160       new->seen = FALSE;
1161       new->args[0].u = NULL;
1162       new->args[1].u = new->args[2].u = NULL;
1163       new->args[3].u = ptr;
1164
1165       ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1166       if (*error_pointer != NULL) { yield = FALSE; break; }
1167       newlastcmdptr = &(new->args[1].f);
1168       if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1169         yield = FALSE;
1170       }
1171
1172     if (yield == FALSE) break;
1173
1174     /* Handle termination by "else", possibly following one or more
1175     "elsif" sections. */
1176
1177     if (had_else_endif == had_else)
1178       {
1179       newlastcmdptr = &(new->args[2].f);
1180       if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1181         yield = FALSE;
1182       else if (had_else_endif != had_endif)
1183         {
1184         *error_pointer = string_sprintf("\"endif\" missing near line %d of "
1185           "filter file", line_number);
1186         yield = FALSE;
1187         }
1188       }
1189
1190     /* Otherwise the terminator was "endif" - this is checked by
1191     read_command_list(). The pointer is already set to NULL. */
1192     }
1193
1194   /* Reset the terminator flag. */
1195
1196   had_else_endif = had_neither;
1197   break;
1198
1199
1200   /* The mail & vacation commands have a whole slew of keyworded arguments.
1201   The final argument values are the file expand and return message booleans,
1202   whose offsets are defined in mailarg_index_{expand,return}. Although they
1203   are logically booleans, because they are stored in a uschar * value, we use
1204   NULL and not FALSE, to keep 64-bit compilers happy. */
1205
1206   case mail_command:
1207   case vacation_command:
1208   new = store_get(sizeof(filter_cmd) + mailargs_total * sizeof(union argtypes), FALSE);
1209   new->next = NULL;
1210   new->command = command;
1211   new->seen = seen_force? seen_value : FALSE;
1212   new->noerror = noerror_force;
1213   for (i = 0; i < mailargs_total; i++) new->args[i].u = NULL;
1214
1215   /* Read keyword/value pairs until we hit one that isn't. The data
1216   must contain only printing chars plus tab, though the "text" value
1217   can also contain newlines. The "file" keyword can be preceded by the
1218   word "expand", and "return message" has no data. */
1219
1220   for (;;)
1221     {
1222     uschar *saveptr = ptr;
1223     ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1224     if (*error_pointer != NULL)
1225       {
1226       yield = FALSE;
1227       break;
1228       }
1229
1230     /* Ensure "return" is followed by "message"; that's a complete option */
1231
1232     if (Ustrcmp(buffer, "return") == 0)
1233       {
1234       new->args[mailarg_index_return].u = US"";  /* not NULL => TRUE */
1235       ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1236       if (Ustrcmp(buffer, "message") != 0)
1237         {
1238         *error_pointer = string_sprintf("\"return\" not followed by \"message\" "
1239           " near line %d of filter file", line_number);
1240         yield = FALSE;
1241         break;
1242         }
1243       continue;
1244       }
1245
1246     /* Ensure "expand" is followed by "file", then fall through to process the
1247     file keyword. */
1248
1249     if (Ustrcmp(buffer, "expand") == 0)
1250       {
1251       new->args[mailarg_index_expand].u = US"";  /* not NULL => TRUE */
1252       ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1253       if (Ustrcmp(buffer, "file") != 0)
1254         {
1255         *error_pointer = string_sprintf("\"expand\" not followed by \"file\" "
1256           " near line %d of filter file", line_number);
1257         yield = FALSE;
1258         break;
1259         }
1260       }
1261
1262     /* Scan for the keyword */
1263
1264     for (i = 0; i < MAILARGS_STRING_COUNT; i++)
1265       if (Ustrcmp(buffer, mailargs[i]) == 0) break;
1266
1267     /* Not found keyword; assume end of this command */
1268
1269     if (i >= MAILARGS_STRING_COUNT)
1270       {
1271       ptr = saveptr;
1272       break;
1273       }
1274
1275     /* Found keyword, read the data item */
1276
1277     ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1278     if (*error_pointer != NULL)
1279       {
1280       yield = FALSE;
1281       break;
1282       }
1283     else new->args[i].u = string_copy(buffer);
1284     }
1285
1286   /* If this is the vacation command, apply some default settings to
1287   some of the arguments. */
1288
1289   if (command == vacation_command)
1290     {
1291     if (new->args[mailarg_index_file].u == NULL)
1292       {
1293       new->args[mailarg_index_file].u = string_copy(US".vacation.msg");
1294       new->args[mailarg_index_expand].u = US"";   /* not NULL => TRUE */
1295       }
1296     if (new->args[mailarg_index_log].u == NULL)
1297       new->args[mailarg_index_log].u = string_copy(US".vacation.log");
1298     if (new->args[mailarg_index_once].u == NULL)
1299       new->args[mailarg_index_once].u = string_copy(US".vacation");
1300     if (new->args[mailarg_index_once_repeat].u == NULL)
1301       new->args[mailarg_index_once_repeat].u = string_copy(US"7d");
1302     if (new->args[mailarg_index_subject].u == NULL)
1303       new->args[mailarg_index_subject].u = string_copy(US"On vacation");
1304     }
1305
1306   /* Join the address on to the chain of generated addresses */
1307
1308   **lastcmdptr = new;
1309   *lastcmdptr = &(new->next);
1310   break;
1311
1312
1313   /* Seen and unseen just set flags */
1314
1315   case seen_command:
1316   case unseen_command:
1317   if (*ptr == 0)
1318     {
1319     *error_pointer = string_sprintf("\"seen\" or \"unseen\" "
1320       "near line %d is not followed by a command", line_number);
1321     yield = FALSE;
1322     }
1323   if (seen_force)
1324     {
1325     *error_pointer = string_sprintf("\"seen\" or \"unseen\" repeated "
1326       "near line %d", line_number);
1327     yield = FALSE;
1328     }
1329   seen_value = (command == seen_command);
1330   seen_force = TRUE;
1331   was_seen_or_unseen = TRUE;
1332   break;
1333
1334
1335   /* So does noerror */
1336
1337   case noerror_command:
1338   if (*ptr == 0)
1339     {
1340     *error_pointer = string_sprintf("\"noerror\" "
1341       "near line %d is not followed by a command", line_number);
1342     yield = FALSE;
1343     }
1344   noerror_force = TRUE;
1345   was_noerror = TRUE;
1346   break;
1347
1348
1349   /* Oops */
1350
1351   default:
1352   *error_pointer = string_sprintf("unknown filtering command \"%s\" "
1353     "near line %d of filter file", buffer, line_number);
1354   yield = FALSE;
1355   break;
1356   }
1357
1358 if (!was_seen_or_unseen && !was_noerror)
1359   {
1360   seen_force = FALSE;
1361   noerror_force = FALSE;
1362   }
1363
1364 *pptr = ptr;
1365 return yield;
1366 }
1367
1368
1369
1370 /*************************************************
1371 *              Read a list of commands           *
1372 *************************************************/
1373
1374 /* If conditional is TRUE, the list must be terminated
1375 by the words "else" or "endif".
1376
1377 Arguments:
1378   pptr        points to pointer to next character; the pointer is updated
1379   lastcmdptr  points to pointer to pointer to previously-read command; used
1380                 for hanging on the new command
1381   conditional TRUE if this command is the subject of a condition
1382
1383 Returns:      TRUE on success
1384 */
1385
1386 static BOOL
1387 read_command_list(uschar **pptr, filter_cmd ***lastcmdptr, BOOL conditional)
1388 {
1389 if (conditional) expect_endif++;
1390 had_else_endif = had_neither;
1391 while (**pptr != 0 && had_else_endif == had_neither)
1392   {
1393   if (!read_command(pptr, lastcmdptr)) return FALSE;
1394   *pptr = nextsigchar(*pptr, TRUE);
1395   }
1396 if (conditional)
1397   {
1398   expect_endif--;
1399   if (had_else_endif == had_neither)
1400     {
1401     *error_pointer = US"\"endif\" missing at end of filter file";
1402     return FALSE;
1403     }
1404   }
1405 return TRUE;
1406 }
1407
1408
1409
1410
1411 /*************************************************
1412 *             Test a condition                   *
1413 *************************************************/
1414
1415 /*
1416 Arguments:
1417   c              points to the condition block; c->testfor indicated whether
1418                    it's a positive or negative condition
1419   toplevel       TRUE if called from "if" directly; FALSE otherwise
1420
1421 Returns:         TRUE if the condition is met
1422 */
1423
1424 static BOOL
1425 test_condition(condition_block *c, BOOL toplevel)
1426 {
1427 BOOL yield = FALSE;
1428 uschar *exp[2], *p, *pp;
1429 int val[2];
1430 int i;
1431
1432 if (c == NULL) return TRUE;  /* does this ever occur? */
1433
1434 switch (c->type)
1435   {
1436   case cond_and:
1437   yield = test_condition(c->left.c, FALSE) &&
1438           *error_pointer == NULL &&
1439           test_condition(c->right.c, FALSE);
1440   break;
1441
1442   case cond_or:
1443   yield = test_condition(c->left.c, FALSE) ||
1444           (*error_pointer == NULL &&
1445           test_condition(c->right.c, FALSE));
1446   break;
1447
1448   /* The personal test is meaningless in a system filter. The tests are now in
1449   a separate function (so Sieve can use them). However, an Exim filter does not
1450   scan Cc: (hence the FALSE argument). */
1451
1452   case cond_personal:
1453   yield = f.system_filtering? FALSE : filter_personal(c->left.a, FALSE);
1454   break;
1455
1456   case cond_delivered:
1457   yield = filter_delivered;
1458   break;
1459
1460   /* Only TRUE if a message is actually being processed; FALSE for address
1461   testing and verification. */
1462
1463   case cond_errormsg:
1464   yield = message_id[0] != 0 &&
1465     (sender_address == NULL || sender_address[0] == 0);
1466   break;
1467
1468   /* Only FALSE if a message is actually being processed; TRUE for address
1469   and filter testing and verification. */
1470
1471   case cond_firsttime:
1472   yield = filter_test != FTEST_NONE || message_id[0] == 0 || f.deliver_firsttime;
1473   break;
1474
1475   /* Only TRUE if a message is actually being processed; FALSE for address
1476   testing and verification. */
1477
1478   case cond_manualthaw:
1479   yield = message_id[0] != 0 && f.deliver_manual_thaw;
1480   break;
1481
1482   /* The foranyaddress condition loops through a list of addresses */
1483
1484   case cond_foranyaddress:
1485   p = c->left.u;
1486   pp = expand_string(p);
1487   if (pp == NULL)
1488     {
1489     *error_pointer = string_sprintf("failed to expand \"%s\" in "
1490       "filter file: %s", p, expand_string_message);
1491     return FALSE;
1492     }
1493
1494   yield = FALSE;
1495   f.parse_allow_group = TRUE;     /* Allow group syntax */
1496
1497   while (*pp != 0)
1498     {
1499     uschar *error;
1500     int start, end, domain;
1501     int saveend;
1502
1503     p = parse_find_address_end(pp, FALSE);
1504     saveend = *p;
1505
1506     *p = 0;
1507     filter_thisaddress =
1508       parse_extract_address(pp, &error, &start, &end, &domain, FALSE);
1509     *p = saveend;
1510
1511     if (filter_thisaddress)
1512       {
1513       if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1514           (debug_selector & D_filter) != 0)
1515         {
1516         indent();
1517         debug_printf_indent("Extracted address %s\n", filter_thisaddress);
1518         }
1519       yield = test_condition(c->right.c, FALSE);
1520       }
1521
1522     if (yield) break;
1523     if (saveend == 0) break;
1524     pp = p + 1;
1525     }
1526
1527   f.parse_allow_group = FALSE;      /* Reset group syntax flags */
1528   f.parse_found_group = FALSE;
1529   break;
1530
1531   /* All other conditions have left and right values that need expanding;
1532   on error, it doesn't matter what value is returned. */
1533
1534   default:
1535   p = c->left.u;
1536   for (i = 0; i < 2; i++)
1537     {
1538     exp[i] = expand_string(p);
1539     if (exp[i] == NULL)
1540       {
1541       *error_pointer = string_sprintf("failed to expand \"%s\" in "
1542         "filter file: %s", p, expand_string_message);
1543       return FALSE;
1544       }
1545     p = c->right.u;
1546     }
1547
1548   /* Inner switch for the different cases */
1549
1550   switch(c->type)
1551     {
1552     case cond_is:
1553     yield = strcmpic(exp[0], exp[1]) == 0;
1554     break;
1555
1556     case cond_IS:
1557     yield = Ustrcmp(exp[0], exp[1]) == 0;
1558     break;
1559
1560     case cond_contains:
1561     yield = strstric(exp[0], exp[1], FALSE) != NULL;
1562     break;
1563
1564     case cond_CONTAINS:
1565     yield = Ustrstr(exp[0], exp[1]) != NULL;
1566     break;
1567
1568     case cond_begins:
1569     yield = strncmpic(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1570     break;
1571
1572     case cond_BEGINS:
1573     yield = Ustrncmp(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1574     break;
1575
1576     case cond_ends:
1577     case cond_ENDS:
1578       {
1579       int len = Ustrlen(exp[1]);
1580       uschar *s = exp[0] + Ustrlen(exp[0]) - len;
1581       yield = (s < exp[0])? FALSE :
1582         ((c->type == cond_ends)? strcmpic(s, exp[1]) : Ustrcmp(s, exp[1])) == 0;
1583       }
1584     break;
1585
1586     case cond_matches:
1587     case cond_MATCHES:
1588       {
1589       const pcre2_code *re;
1590       int err;
1591       PCRE2_SIZE offset;
1592
1593       if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1594           (debug_selector & D_filter) != 0)
1595         {
1596         debug_printf_indent("Match expanded arguments:\n");
1597         debug_printf_indent("  Subject = %s\n", exp[0]);
1598         debug_printf_indent("  Pattern = %s\n", exp[1]);
1599         }
1600
1601       if (!(re = pcre2_compile((PCRE2_SPTR)exp[1], PCRE2_ZERO_TERMINATED,
1602                   PCRE_COPT | (c->type == cond_matches ? PCRE2_CASELESS : 0),
1603                   &err, &offset, pcre_cmp_ctx)))
1604         {
1605         uschar errbuf[128];
1606         pcre2_get_error_message(err, errbuf, sizeof(errbuf));
1607         *error_pointer = string_sprintf("error while compiling "
1608           "regular expression \"%s\": %s at offset %ld",
1609           exp[1], errbuf, (long)offset);
1610         return FALSE;
1611         }
1612
1613       yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1);
1614       break;
1615       }
1616
1617     /* For above and below, convert the strings to numbers */
1618
1619     case cond_above:
1620     case cond_below:
1621     for (i = 0; i < 2; i++)
1622       {
1623       val[i] = get_number(exp[i], &yield);
1624       if (!yield)
1625         {
1626         *error_pointer = string_sprintf("malformed numerical string \"%s\"",
1627           exp[i]);
1628         return FALSE;
1629         }
1630       }
1631     yield = (c->type == cond_above)? (val[0] > val[1]) : (val[0] < val[1]);
1632     break;
1633     }
1634   break;
1635   }
1636
1637 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1638     (debug_selector & D_filter) != 0)
1639   {
1640   indent();
1641   debug_printf_indent("%sondition is %s: ",
1642     toplevel? "C" : "Sub-c",
1643     (yield == c->testfor)? "true" : "false");
1644   print_condition(c, TRUE);
1645   debug_printf_indent("\n");
1646   }
1647
1648 return yield == c->testfor;
1649 }
1650
1651
1652
1653 /*************************************************
1654 *          Interpret chain of commands           *
1655 *************************************************/
1656
1657 /* In testing state, just say what would be done rather than doing it. The
1658 testprint command just expands and outputs its argument in testing state, and
1659 does nothing otherwise.
1660
1661 Arguments:
1662   commands    points to chain of commands to interpret
1663   generated   where to hang newly-generated addresses
1664
1665 Returns:      FF_DELIVERED     success, a significant action was taken
1666               FF_NOTDELIVERED  success, no significant action
1667               FF_DEFER         defer requested
1668               FF_FAIL          fail requested
1669               FF_FREEZE        freeze requested
1670               FF_ERROR         there was a problem
1671 */
1672
1673 static int
1674 interpret_commands(filter_cmd *commands, address_item **generated)
1675 {
1676 const uschar *s;
1677 int mode;
1678 address_item *addr;
1679 BOOL condition_value;
1680
1681 while (commands)
1682   {
1683   int ff_ret;
1684   uschar *fmsg, *ff_name;
1685   const uschar *expargs[MAILARGS_STRING_COUNT];
1686
1687   int i, n[2];
1688
1689   /* Expand the relevant number of arguments for the command that are
1690   not NULL. */
1691
1692   for (i = 0; i < (command_exparg_count[commands->command] & 15); i++)
1693     {
1694     uschar *ss = commands->args[i].u;
1695     if (!ss)
1696       expargs[i] = NULL;
1697     else
1698       if (!(expargs[i] = expand_string(ss)))
1699         {
1700         *error_pointer = string_sprintf("failed to expand \"%s\" in "
1701           "%s command: %s", ss, command_list[commands->command],
1702           expand_string_message);
1703         return FF_ERROR;
1704         }
1705     }
1706
1707   /* Now switch for each command, setting the "delivered" flag if any of them
1708   have "seen" set. */
1709
1710   if (commands->seen) filter_delivered = TRUE;
1711
1712   switch(commands->command)
1713     {
1714     case add_command:
1715       for (i = 0; i < 2; i++)
1716         {
1717         const uschar *ss = expargs[i];
1718         uschar *end;
1719
1720         if (i == 1 && (*ss++ != 'n' || ss[1] != 0))
1721           {
1722           *error_pointer = string_sprintf("unknown variable \"%s\" in \"add\" "
1723             "command", expargs[i]);
1724           return FF_ERROR;
1725           }
1726
1727         /* Allow for "--" at the start of the value (from -$n0) for example */
1728         if (i == 0) while (ss[0] == '-' && ss[1] == '-') ss += 2;
1729
1730         n[i] = (int)Ustrtol(ss, &end, 0);
1731         if (*end != 0)
1732           {
1733           *error_pointer = string_sprintf("malformed number \"%s\" in \"add\" "
1734             "command", ss);
1735           return FF_ERROR;
1736           }
1737         }
1738
1739       filter_n[n[1]] += n[0];
1740       if (filter_test != FTEST_NONE) printf("Add %d to n%d\n", n[0], n[1]);
1741       break;
1742
1743       /* A deliver command's argument must be a valid address. Its optional
1744       second argument (system filter only) must also be a valid address. */
1745
1746     case deliver_command:
1747       for (i = 0; i < 2; i++)
1748         {
1749         s = expargs[i];
1750         if (s != NULL)
1751           {
1752           int start, end, domain;
1753           uschar *error;
1754           uschar *ss = parse_extract_address(s, &error, &start, &end, &domain,
1755             FALSE);
1756           if (ss)
1757             expargs[i] = filter_options & RDO_REWRITE
1758               ? rewrite_address(ss, TRUE, FALSE, global_rewrite_rules,
1759                                 rewrite_existflags)
1760               : rewrite_address_qualify(ss, TRUE);
1761           else
1762             {
1763             *error_pointer = string_sprintf("malformed address \"%s\" in "
1764               "filter file: %s", s, error);
1765             return FF_ERROR;
1766             }
1767           }
1768         }
1769
1770       /* Stick the errors address into a simple variable, as it will
1771       be referenced a few times. Check that the caller is permitted to
1772       specify it. */
1773
1774       s = expargs[1];
1775
1776       if (s != NULL && !f.system_filtering)
1777         {
1778         uschar *ownaddress = expand_string(US"$local_part@$domain");
1779         if (strcmpic(ownaddress, s) != 0)
1780           {
1781           *error_pointer = US"errors_to must point to the caller's address";
1782           return FF_ERROR;
1783           }
1784         }
1785
1786       /* Test case: report what would happen */
1787
1788       if (filter_test != FTEST_NONE)
1789         {
1790         indent();
1791         printf("%seliver message to: %s%s%s%s\n",
1792           (commands->seen)? "D" : "Unseen d",
1793           expargs[0],
1794           commands->noerror? " (noerror)" : "",
1795           (s != NULL)? " errors_to " : "",
1796           (s != NULL)? s : US"");
1797         }
1798
1799       /* Real case. */
1800
1801       else
1802         {
1803         DEBUG(D_filter) debug_printf_indent("Filter: %sdeliver message to: %s%s%s%s\n",
1804           (commands->seen)? "" : "unseen ",
1805           expargs[0],
1806           commands->noerror? " (noerror)" : "",
1807           (s != NULL)? " errors_to " : "",
1808           (s != NULL)? s : US"");
1809
1810         /* Create the new address and add it to the chain, setting the
1811         af_ignore_error flag if necessary, and the errors address, which can be
1812         set in a system filter and to the local address in user filters. */
1813
1814         addr = deliver_make_addr(US expargs[0], TRUE);  /* TRUE => copy s, so deconst ok */
1815         addr->prop.errors_address = !s ? NULL : string_copy(s); /* Default is NULL */
1816         if (commands->noerror) addr->prop.ignore_error = TRUE;
1817         addr->next = *generated;
1818         *generated = addr;
1819         }
1820       break;
1821
1822     case save_command:
1823       s = expargs[0];
1824       mode = commands->args[1].i;
1825
1826       /* Test case: report what would happen */
1827
1828       if (filter_test != FTEST_NONE)
1829         {
1830         indent();
1831         if (mode < 0)
1832           printf("%save message to: %s%s\n", (commands->seen)?
1833             "S" : "Unseen s", s, commands->noerror? " (noerror)" : "");
1834         else
1835           printf("%save message to: %s %04o%s\n", (commands->seen)?
1836             "S" : "Unseen s", s, mode, commands->noerror? " (noerror)" : "");
1837         }
1838
1839       /* Real case: Ensure save argument starts with / if there is a home
1840       directory to prepend. */
1841
1842       else
1843         {
1844         if (s[0] != '/' && (filter_options & RDO_PREPEND_HOME) != 0 &&
1845             deliver_home != NULL && deliver_home[0] != 0)
1846           s = string_sprintf("%s/%s", deliver_home, s);
1847         DEBUG(D_filter) debug_printf_indent("Filter: %ssave message to: %s%s\n",
1848           (commands->seen)? "" : "unseen ", s,
1849           commands->noerror? " (noerror)" : "");
1850
1851         /* Create the new address and add it to the chain, setting the
1852         af_pfr and af_file flags, the af_ignore_error flag if necessary, and the
1853         mode value. */
1854
1855         addr = deliver_make_addr(US s, TRUE);  /* TRUE => copy s, so deconst ok */
1856         setflag(addr, af_pfr);
1857         setflag(addr, af_file);
1858         if (commands->noerror) addr->prop.ignore_error = TRUE;
1859         addr->mode = mode;
1860         addr->next = *generated;
1861         *generated = addr;
1862         }
1863       break;
1864
1865     case pipe_command:
1866       s = string_copy(commands->args[0].u);
1867       if (filter_test != FTEST_NONE)
1868         {
1869         indent();
1870         printf("%sipe message to: %s%s\n", (commands->seen)?
1871           "P" : "Unseen p", s, commands->noerror? " (noerror)" : "");
1872         }
1873       else /* Ensure pipe command starts with | */
1874         {
1875         DEBUG(D_filter) debug_printf_indent("Filter: %spipe message to: %s%s\n",
1876           commands->seen ? "" : "unseen ", s,
1877           commands->noerror ? " (noerror)" : "");
1878         if (s[0] != '|') s = string_sprintf("|%s", s);
1879
1880         /* Create the new address and add it to the chain, setting the
1881         af_ignore_error flag if necessary. Set the af_expand_pipe flag so that
1882         each command argument is expanded in the transport after the command
1883         has been split up into separate arguments. */
1884
1885         addr = deliver_make_addr(US s, TRUE);  /* TRUE => copy s, so deconst ok */
1886         setflag(addr, af_pfr);
1887         setflag(addr, af_expand_pipe);
1888         if (commands->noerror) addr->prop.ignore_error = TRUE;
1889         addr->next = *generated;
1890         *generated = addr;
1891
1892         /* If there are any numeric variables in existence (e.g. after a regex
1893         condition), or if $thisaddress is set, take a copy for use in the
1894         expansion. Note that we can't pass NULL for filter_thisaddress, because
1895         NULL terminates the list. */
1896
1897         if (expand_nmax >= 0 || filter_thisaddress != NULL)
1898           {
1899           int ecount = expand_nmax >= 0 ? expand_nmax : -1;
1900           uschar **ss = store_get(sizeof(uschar *) * (ecount + 3), FALSE);
1901
1902           addr->pipe_expandn = ss;
1903           if (!filter_thisaddress) filter_thisaddress = US"";
1904           *ss++ = string_copy(filter_thisaddress);
1905           for (int i = 0; i <= expand_nmax; i++)
1906             *ss++ = string_copyn(expand_nstring[i], expand_nlength[i]);
1907           *ss = NULL;
1908           }
1909         }
1910       break;
1911
1912       /* Set up the file name and mode, and close any previously open
1913       file. */
1914
1915     case logfile_command:
1916       log_mode = commands->args[1].i;
1917       if (log_mode == -1) log_mode = 0600;
1918       if (log_fd >= 0)
1919         {
1920         (void)close(log_fd);
1921         log_fd = -1;
1922         }
1923       log_filename = expargs[0];
1924       if (filter_test != FTEST_NONE)
1925         {
1926         indent();
1927         printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
1928         }
1929       break;
1930
1931     case logwrite_command:
1932       s = expargs[0];
1933
1934       if (filter_test != FTEST_NONE)
1935         {
1936         indent();
1937         printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
1938           string_printing(s));
1939         }
1940
1941       /* Attempt to write to a log file only if configured as permissible.
1942       Logging may be forcibly skipped for verifying or testing. */
1943
1944       else if ((filter_options & RDO_LOG) != 0)   /* Locked out */
1945         {
1946         DEBUG(D_filter)
1947           debug_printf_indent("filter log command aborted: euid=%ld\n",
1948           (long int)geteuid());
1949         *error_pointer = US"logwrite command forbidden";
1950         return FF_ERROR;
1951         }
1952       else if ((filter_options & RDO_REALLOG) != 0)
1953         {
1954         int len;
1955         DEBUG(D_filter) debug_printf_indent("writing filter log as euid %ld\n",
1956           (long int)geteuid());
1957         if (log_fd < 0)
1958           {
1959           if (!log_filename)
1960             {
1961             *error_pointer = US"attempt to obey \"logwrite\" command "
1962               "without a previous \"logfile\"";
1963             return FF_ERROR;
1964             }
1965           log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode);
1966           if (log_fd < 0)
1967             {
1968             *error_pointer = string_open_failed("filter log file \"%s\"",
1969               log_filename);
1970             return FF_ERROR;
1971             }
1972           }
1973         len = Ustrlen(s);
1974         if (write(log_fd, s, len) != len)
1975           {
1976           *error_pointer = string_sprintf("write error on file \"%s\": %s",
1977             log_filename, strerror(errno));
1978           return FF_ERROR;
1979           }
1980         }
1981       else
1982         DEBUG(D_filter)
1983           debug_printf_indent("skipping logwrite (verifying or testing)\n");
1984       break;
1985
1986       /* Header addition and removal is available only in the system filter. The
1987       command is rejected at parse time otherwise. However "headers charset" is
1988       always permitted. */
1989
1990     case headers_command:
1991         {
1992         int subtype = commands->args[1].i;
1993         s = expargs[0];
1994
1995         if (filter_test != FTEST_NONE)
1996           printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" :
1997             (subtype == FALSE)? "remove" : "charset", string_printing(s));
1998
1999         if (subtype == TRUE)
2000           {
2001           while (isspace(*s)) s++;
2002           if (s[0] != 0)
2003             {
2004             header_add(htype_other, "%s%s", s, (s[Ustrlen(s)-1] == '\n')?
2005               "" : "\n");
2006             header_last->type = header_checkname(header_last, FALSE);
2007             if (header_last->type >= 'a') header_last->type = htype_other;
2008             }
2009           }
2010
2011         else if (subtype == FALSE)
2012           {
2013           int sep = 0;
2014           const uschar * list = s;
2015
2016           for (uschar * ss; ss = string_nextinlist(&list, &sep, NULL, 0); )
2017             header_remove(0, ss);
2018           }
2019
2020         /* This setting lasts only while the filter is running; on exit, the
2021         variable is reset to the previous value. */
2022
2023         else headers_charset = s;       /*XXX loses track of const */
2024         }
2025       break;
2026
2027       /* Defer, freeze, and fail are available only when explicitly permitted.
2028       These commands are rejected at parse time otherwise. The message can get
2029       very long by the inclusion of message headers; truncate if it is, and also
2030       ensure printing characters so as not to mess up log files. */
2031
2032     case defer_command:
2033       ff_name = US"defer";
2034       ff_ret = FF_DEFER;
2035       goto DEFERFREEZEFAIL;
2036
2037     case fail_command:
2038       ff_name = US"fail";
2039       ff_ret = FF_FAIL;
2040       goto DEFERFREEZEFAIL;
2041
2042     case freeze_command:
2043       ff_name = US"freeze";
2044       ff_ret = FF_FREEZE;
2045
2046       DEFERFREEZEFAIL:
2047       fmsg = expargs[0];                /*XXX loses track of const */
2048       if (Ustrlen(fmsg) > 1024) Ustrcpy(fmsg + 1000, US" ... (truncated)");
2049       fmsg = US string_printing(fmsg);
2050       *error_pointer = fmsg;
2051
2052       if (filter_test != FTEST_NONE)
2053         {
2054         indent();
2055         printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
2056         }
2057       else 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         {
2068         DEBUG(D_filter) debug_printf_indent("Filter: %sfinish\n",
2069           (commands->seen)? " Seen " : "");
2070         }
2071       finish_obeyed = TRUE;
2072       return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2073
2074     case if_command:
2075         {
2076         uschar *save_address = filter_thisaddress;
2077         int ok = FF_DELIVERED;
2078         condition_value = test_condition(commands->args[0].c, TRUE);
2079         if (*error_pointer != NULL) ok = FF_ERROR; 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 == NULL || return_path[0] == 0)
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           uschar *p;
2130           const uschar *s = expargs[i];
2131
2132           if (s == NULL) continue;
2133
2134           if (i != mailarg_index_text) for (p = s; *p != 0; p++)
2135             {
2136             int c = *p;
2137             if (i > mailarg_index_text)
2138               {
2139               if (!mac_isprint(c))
2140                 {
2141                 *error_pointer = string_sprintf("non-printing character in \"%s\" "
2142                   "in %s command", string_printing(s),
2143                   command_list[commands->command]);
2144                 return FF_ERROR;
2145                 }
2146               }
2147
2148             /* i < mailarg_index_text */
2149
2150             else if (c == '\n' && !isspace(p[1]))
2151               {
2152               if (i < mailarg_index_headers)
2153                 {
2154                 *error_pointer = string_sprintf("\\n not followed by space in "
2155                   "\"%.1024s\" in %s command", string_printing(s),
2156                   command_list[commands->command]);
2157                 return FF_ERROR;
2158                 }
2159
2160               /* Check for the start of a new header line within the string */
2161
2162               else
2163                 {
2164                 uschar *pp;
2165                 for (pp = p + 1;; pp++)
2166                   {
2167                   c = *pp;
2168                   if (c == ':' && pp != p + 1) break;
2169                   if (c == 0 || c == ':' || isspace(*pp))
2170                     {
2171                     *error_pointer = string_sprintf("\\n not followed by space or "
2172                       "valid header name in \"%.1024s\" in %s command",
2173                       string_printing(s), command_list[commands->command]);
2174                     return FF_ERROR;
2175                     }
2176                   }
2177                 p = pp;
2178                 }
2179               }
2180             }       /* Loop to scan the string */
2181
2182           /* The string is OK */
2183
2184           commands->args[i].u = s;      /*XXX loses track of const */
2185           }
2186
2187         /* Proceed with mail or vacation command */
2188
2189         if (filter_test != FTEST_NONE)
2190           {
2191           uschar *to = commands->args[mailarg_index_to].u;
2192           indent();
2193           printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2194             to ? to : US"<default>",
2195             commands->command == vacation_command ? " (vacation)" : "",
2196             commands->noerror ? " (noerror)" : "");
2197           for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2198             {
2199             uschar *arg = commands->args[i].u;
2200             if (arg)
2201               {
2202               int len = Ustrlen(mailargs[i]);
2203               int indent = (debug_selector != 0)? output_indent : 0;
2204               while (len++ < 7 + indent) printf(" ");
2205               printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2206                 (commands->args[mailarg_index_expand].u != NULL &&
2207                   Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2208               }
2209             }
2210           if (commands->args[mailarg_index_return].u)
2211             printf("Return original message\n");
2212           }
2213         else
2214           {
2215           uschar *tt;
2216           uschar *to = commands->args[mailarg_index_to].u;
2217           gstring * log_addr = NULL;
2218
2219           if (!to) to = expand_string(US"$reply_address");
2220           while (isspace(*to)) to++;
2221
2222           for (tt = to; *tt != 0; tt++)     /* Get rid of newlines */
2223             if (*tt == '\n') *tt = ' ';
2224
2225           DEBUG(D_filter)
2226             {
2227             debug_printf_indent("Filter: %smail to: %s%s%s\n",
2228               commands->seen ? "seen " : "",
2229               to,
2230               commands->command == vacation_command ? " (vacation)" : "",
2231               commands->noerror ? " (noerror)" : "");
2232             for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2233               {
2234               uschar *arg = commands->args[i].u;
2235               if (arg != NULL)
2236                 {
2237                 int len = Ustrlen(mailargs[i]);
2238                 while (len++ < 15) debug_printf_indent(" ");
2239                 debug_printf_indent("%s: %s%s\n", mailargs[i], string_printing(arg),
2240                   (commands->args[mailarg_index_expand].u != NULL &&
2241                     Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2242                 }
2243               }
2244             }
2245
2246           /* Create the "address" for the autoreply. This is used only for logging,
2247           as the actual recipients are extracted from the To: line by -t. We use the
2248           same logic here to extract the working addresses (there may be more than
2249           one). Just in case there are a vast number of addresses, stop when the
2250           string gets too long. */
2251
2252           tt = to;
2253           while (*tt != 0)
2254             {
2255             uschar *ss = parse_find_address_end(tt, FALSE);
2256             uschar *recipient, *errmess;
2257             int start, end, domain;
2258             int temp = *ss;
2259
2260             *ss = 0;
2261             recipient = parse_extract_address(tt, &errmess, &start, &end, &domain,
2262               FALSE);
2263             *ss = temp;
2264
2265             /* Ignore empty addresses and errors; an error will occur later if
2266             there's something really bad. */
2267
2268             if (recipient)
2269               {
2270               log_addr = string_catn(log_addr, log_addr ? US"," : US">", 1);
2271               log_addr = string_cat (log_addr, recipient);
2272               }
2273
2274             /* Check size */
2275
2276             if (log_addr && log_addr->ptr > 256)
2277               {
2278               log_addr = string_catn(log_addr, US", ...", 5);
2279               break;
2280               }
2281
2282             /* Move on past this address */
2283
2284             tt = ss + (*ss ? 1 : 0);
2285             while (isspace(*tt)) tt++;
2286             }
2287
2288           if (log_addr)
2289             addr = deliver_make_addr(string_from_gstring(log_addr), FALSE);
2290           else
2291             {
2292             addr = deliver_make_addr(US ">**bad-reply**", FALSE);
2293             setflag(addr, af_bad_reply);
2294             }
2295
2296           setflag(addr, af_pfr);
2297           if (commands->noerror) addr->prop.ignore_error = TRUE;
2298           addr->next = *generated;
2299           *generated = addr;
2300
2301           addr->reply = store_get(sizeof(reply_item), FALSE);
2302           addr->reply->from = NULL;
2303           addr->reply->to = string_copy(to);
2304           addr->reply->file_expand =
2305             commands->args[mailarg_index_expand].u != NULL;
2306           addr->reply->expand_forbid = expand_forbid;
2307           addr->reply->return_message =
2308             commands->args[mailarg_index_return].u != NULL;
2309           addr->reply->once_repeat = 0;
2310
2311           if (commands->args[mailarg_index_once_repeat].u != NULL)
2312             {
2313             addr->reply->once_repeat =
2314               readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2315                 FALSE);
2316             if (addr->reply->once_repeat < 0)
2317               {
2318               *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2319                 "in mail or vacation command: %s",
2320                 commands->args[mailarg_index_once_repeat].u);
2321               return FF_ERROR;
2322               }
2323             }
2324
2325           /* Set up all the remaining string arguments (those other than "to") */
2326
2327           for (i = 1; i < mailargs_string_passed; i++)
2328             {
2329             uschar *ss = commands->args[i].u;
2330             *(USS((US addr->reply) + reply_offsets[i])) =
2331               ss ? string_copy(ss) : NULL;
2332             }
2333           }
2334         break;
2335
2336     case testprint_command:
2337         if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2338           {
2339           const uschar *s = string_printing(expargs[0]);
2340           if (filter_test == FTEST_NONE)
2341             debug_printf_indent("Filter: testprint: %s\n", s);
2342           else
2343             printf("Testprint: %s\n", s);
2344           }
2345     }
2346
2347   commands = commands->next;
2348   }
2349
2350 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2351 }
2352
2353
2354
2355 /*************************************************
2356 *        Test for a personal message             *
2357 *************************************************/
2358
2359 /* This function is global so that it can also be called from the code that
2360 implements Sieve filters.
2361
2362 Arguments:
2363   aliases    a chain of aliases
2364   scan_cc    TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2365
2366 Returns:     TRUE if the message is deemed to be personal
2367 */
2368
2369 BOOL
2370 filter_personal(string_item *aliases, BOOL scan_cc)
2371 {
2372 const uschar *self, *self_from, *self_to;
2373 uschar *psself = NULL;
2374 const uschar *psself_from = NULL, *psself_to = NULL;
2375 rmark reset_point = store_mark();
2376 BOOL yield;
2377 header_line *h;
2378 int to_count = 2;
2379 int from_count = 9;
2380
2381 /* If any header line in the message is a defined "List-" header field, it is
2382 not a personal message. We used to check for any header line that started with
2383 "List-", but this was tightened up for release 4.54. The check is now for
2384 "List-Id", defined in RFC 2929, or "List-Help", "List-Subscribe", "List-
2385 Unsubscribe", "List-Post", "List-Owner" or "List-Archive", all of which are
2386 defined in RFC 2369. We also scan for "Auto-Submitted"; if it is found to
2387 contain any value other than "no", the message is not personal (RFC 3834).
2388 Previously the test was for "auto-". */
2389
2390 for (h = header_list; h; h = h->next)
2391   {
2392   if (h->type == htype_old) continue;
2393
2394   if (strncmpic(h->text, US"List-", 5) == 0)
2395     {
2396     uschar * s = h->text + 5;
2397     if (strncmpic(s, US"Id:", 3) == 0 ||
2398         strncmpic(s, US"Help:", 5) == 0 ||
2399         strncmpic(s, US"Subscribe:", 10) == 0 ||
2400         strncmpic(s, US"Unsubscribe:", 12) == 0 ||
2401         strncmpic(s, US"Post:", 5) == 0 ||
2402         strncmpic(s, US"Owner:", 6) == 0 ||
2403         strncmpic(s, US"Archive:", 8) == 0)
2404       return FALSE;
2405     }
2406
2407   else if (strncmpic(h->text, US"Auto-submitted:", 15) == 0)
2408     {
2409     uschar * s = h->text + 15;
2410     Uskip_whitespace(&s);
2411     if (strncmpic(s, US"no", 2) != 0) return FALSE;
2412     s += 2;
2413     Uskip_whitespace(&s);
2414     if (*s) return FALSE;
2415     }
2416   }
2417
2418 /* Set up "my" address */
2419
2420 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2421 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2422   global_rewrite_rules);
2423 self_to   = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2424   global_rewrite_rules);
2425
2426
2427 if (!self_from) self_from = self;
2428 if (self_to) self_to = self;
2429
2430 /* If there's a prefix or suffix set, we must include the prefixed/
2431 suffixed version of the local part in the tests. */
2432
2433 if (deliver_localpart_prefix || deliver_localpart_suffix)
2434   {
2435   psself = string_sprintf("%s%s%s@%s",
2436     deliver_localpart_prefix ? deliver_localpart_prefix : US"",
2437     deliver_localpart,
2438     deliver_localpart_suffix ? deliver_localpart_suffix : US"",
2439     deliver_domain);
2440   psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2441     global_rewrite_rules);
2442   psself_to   = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2443     global_rewrite_rules);
2444   if (psself_from == NULL) psself_from = psself;
2445   if (psself_to == NULL) psself_to = psself;
2446   to_count += 2;
2447   from_count += 2;
2448   }
2449
2450 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2451
2452 yield =
2453   (
2454   header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2455                psself_to) ||
2456     (scan_cc &&
2457        (
2458        header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2459                              psself, psself_to)
2460        ||
2461        header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2462                               psself, psself_to)
2463        )
2464     )
2465   ) &&
2466
2467   header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2468     "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2469     "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2470
2471   header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2472
2473   (sender_address == NULL || sender_address[0] != 0);
2474
2475 store_reset(reset_point);
2476 return yield;
2477 }
2478
2479
2480
2481 /*************************************************
2482 *            Interpret a mail filter file        *
2483 *************************************************/
2484
2485 /*
2486 Arguments:
2487   filter      points to the entire file, read into store as a single string
2488   options     controls whether various special things are allowed, and requests
2489               special actions
2490   generated   where to hang newly-generated addresses
2491   error       where to pass back an error text
2492
2493 Returns:      FF_DELIVERED     success, a significant action was taken
2494               FF_NOTDELIVERED  success, no significant action
2495               FF_DEFER         defer requested
2496               FF_FAIL          fail requested
2497               FF_FREEZE        freeze requested
2498               FF_ERROR         there was a problem
2499 */
2500
2501 int
2502 filter_interpret(uschar *filter, int options, address_item **generated,
2503   uschar **error)
2504 {
2505 int i;
2506 int yield = FF_ERROR;
2507 uschar *ptr = filter;
2508 uschar *save_headers_charset = headers_charset;
2509 filter_cmd *commands = NULL;
2510 filter_cmd **lastcmdptr = &commands;
2511
2512 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2513 acl_level++;
2514
2515 /* Initialize "not in an if command", set the global flag that is always TRUE
2516 while filtering, and zero the variables. */
2517
2518 expect_endif = 0;
2519 output_indent = 0;
2520 f.filter_running = TRUE;
2521 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2522
2523 /* To save having to pass certain values about all the time, make them static.
2524 Also initialize the line number, for error messages, and the log file
2525 variables. */
2526
2527 filter_options = options;
2528 filter_delivered = FALSE;
2529 finish_obeyed = FALSE;
2530 error_pointer = error;
2531 *error_pointer = NULL;
2532 line_number = 1;
2533 log_fd = -1;
2534 log_mode = 0600;
2535 log_filename = NULL;
2536
2537 /* Scan filter file for syntax and build up an interpretation thereof, and
2538 interpret the compiled commands, and if testing, say whether we ended up
2539 delivered or not, unless something went wrong. */
2540
2541 seen_force = FALSE;
2542 ptr = nextsigchar(ptr, TRUE);
2543
2544 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2545   yield = interpret_commands(commands, generated);
2546
2547 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2548   {
2549   uschar *s = US"";
2550   switch(yield)
2551     {
2552     case FF_DEFER:
2553       s = US"Filtering ended by \"defer\".";
2554       break;
2555
2556     case FF_FREEZE:
2557       s = US"Filtering ended by \"freeze\".";
2558       break;
2559
2560     case FF_FAIL:
2561       s = US"Filtering ended by \"fail\".";
2562       break;
2563
2564     case FF_DELIVERED:
2565       s = US"Filtering set up at least one significant delivery "
2566              "or other action.\n"
2567              "No other deliveries will occur.";
2568       break;
2569
2570     case FF_NOTDELIVERED:
2571       s = US"Filtering did not set up a significant delivery.\n"
2572              "Normal delivery will occur.";
2573       break;
2574
2575     case FF_ERROR:
2576       s = string_sprintf("Filter error: %s", *error);
2577       break;
2578     }
2579
2580   if (filter_test != FTEST_NONE) printf("%s\n", CS s);
2581     else debug_printf_indent("%s\n", s);
2582   }
2583
2584 /* Close the log file if it was opened, and kill off any numerical variables
2585 before returning. Reset the header decoding charset. */
2586
2587 if (log_fd >= 0) (void)close(log_fd);
2588 expand_nmax = -1;
2589 f.filter_running = FALSE;
2590 headers_charset = save_headers_charset;
2591
2592 acl_level--;
2593 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2594 return yield;
2595 }
2596
2597
2598 /* End of filter.c */