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