Process Auto-submitted: in the triggering message and add it to
[users/heiko/exim.git] / src / src / filter.c
1 /* $Cambridge: exim/src/src/filter.c,v 1.14 2007/01/08 10:50:18 ph10 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2007 */
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 = FALSE;
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               }
2190             p = pp;
2191             }
2192           }
2193         }       /* Loop to scan the string */
2194
2195       /* The string is OK */
2196
2197       commands->args[i].u = s;
2198       }
2199
2200     /* Proceed with mail or vacation command */
2201
2202     if (filter_test != FTEST_NONE)
2203       {
2204       uschar *to = commands->args[mailarg_index_to].u;
2205       indent();
2206       printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2207         (to == NULL)? US"<default>" : to,
2208         (commands->command == vacation_command)? " (vacation)" : "",
2209         (commands->noerror)? " (noerror)" : "");
2210       for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2211         {
2212         uschar *arg = commands->args[i].u;
2213         if (arg != NULL)
2214           {
2215           int len = Ustrlen(mailargs[i]);
2216           int indent = (debug_selector != 0)? output_indent : 0;
2217           while (len++ < 7 + indent) printf(" ");
2218           printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2219             (commands->args[mailarg_index_expand].u != NULL &&
2220               Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2221           }
2222         }
2223       if (commands->args[mailarg_index_return].u != NULL)
2224         printf("Return original message\n");
2225       }
2226     else
2227       {
2228       uschar *tt;
2229       uschar *log_addr = NULL;
2230       uschar *to = commands->args[mailarg_index_to].u;
2231       int size = 0;
2232       int ptr = 0;
2233       int badflag = 0;
2234
2235       if (to == NULL) to = expand_string(US"$reply_address");
2236       while (isspace(*to)) to++;
2237
2238       for (tt = to; *tt != 0; tt++)     /* Get rid of newlines */
2239         if (*tt == '\n') *tt = ' ';
2240
2241       DEBUG(D_filter)
2242         {
2243         debug_printf("Filter: %smail to: %s%s%s\n",
2244           (commands->seen)? "seen " : "",
2245           to,
2246           (commands->command == vacation_command)? " (vacation)" : "",
2247           (commands->noerror)? " (noerror)" : "");
2248         for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2249           {
2250           uschar *arg = commands->args[i].u;
2251           if (arg != NULL)
2252             {
2253             int len = Ustrlen(mailargs[i]);
2254             while (len++ < 15) debug_printf(" ");
2255             debug_printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2256               (commands->args[mailarg_index_expand].u != NULL &&
2257                 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2258             }
2259           }
2260         }
2261
2262       /* Create the "address" for the autoreply. This is used only for logging,
2263       as the actual recipients are extracted from the To: line by -t. We use the
2264       same logic here to extract the working addresses (there may be more than
2265       one). Just in case there are a vast number of addresses, stop when the
2266       string gets too long. */
2267
2268       tt = to;
2269       while (*tt != 0)
2270         {
2271         uschar *ss = parse_find_address_end(tt, FALSE);
2272         uschar *recipient, *errmess;
2273         int start, end, domain;
2274         int temp = *ss;
2275
2276         *ss = 0;
2277         recipient = parse_extract_address(tt, &errmess, &start, &end, &domain,
2278           FALSE);
2279         *ss = temp;
2280
2281         /* Ignore empty addresses and errors; an error will occur later if
2282         there's something really bad. */
2283
2284         if (recipient != NULL)
2285           {
2286           log_addr = string_cat(log_addr, &size, &ptr,
2287             (log_addr == NULL)? US">" : US",", 1);
2288           log_addr = string_cat(log_addr, &size, &ptr, recipient,
2289             Ustrlen(recipient));
2290           }
2291
2292         /* Check size */
2293
2294         if (ptr > 256)
2295           {
2296           log_addr = string_cat(log_addr, &size, &ptr, US", ...", 5);
2297           break;
2298           }
2299
2300         /* Move on past this address */
2301
2302         tt = ss + (*ss? 1:0);
2303         while (isspace(*tt)) tt++;
2304         }
2305
2306       if (log_addr == NULL)
2307         {
2308         log_addr = string_sprintf(">**bad-reply**");
2309         badflag = af_bad_reply;
2310         }
2311       else log_addr[ptr] = 0;
2312
2313       addr = deliver_make_addr(log_addr, FALSE);
2314       setflag(addr, (af_pfr|badflag));
2315       if (commands->noerror) setflag(addr, af_ignore_error);
2316       addr->next = *generated;
2317       *generated = addr;
2318       addr->reply = store_get(sizeof(reply_item));
2319       addr->reply->from = NULL;
2320       addr->reply->to = string_copy(to);
2321       addr->reply->file_expand =
2322         commands->args[mailarg_index_expand].u != NULL;
2323       addr->reply->expand_forbid = expand_forbid;
2324       addr->reply->return_message =
2325         commands->args[mailarg_index_return].u != NULL;
2326       addr->reply->once_repeat = 0;
2327
2328       if (commands->args[mailarg_index_once_repeat].u != NULL)
2329         {
2330         addr->reply->once_repeat =
2331           readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2332             FALSE);
2333         if (addr->reply->once_repeat < 0)
2334           {
2335           *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2336             "in mail or vacation command: %s",
2337             commands->args[mailarg_index_once_repeat]);
2338           return FF_ERROR;
2339           }
2340         }
2341
2342       /* Set up all the remaining string arguments (those other than "to") */
2343
2344       for (i = 1; i < mailargs_string_passed; i++)
2345         {
2346         uschar *ss = commands->args[i].u;
2347         *((uschar **)(((uschar *)(addr->reply)) + reply_offsets[i])) =
2348           (ss == NULL)? NULL : string_copy(ss);
2349         }
2350       }
2351     break;
2352
2353     case testprint_command:
2354     if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2355       {
2356       uschar *s = string_printing(expargs[0]);
2357       if (filter_test == FTEST_NONE)
2358         debug_printf("Filter: testprint: %s\n", s);
2359       else
2360         printf("Testprint: %s\n", s);
2361       }
2362     }
2363
2364   commands = commands->next;
2365   }
2366
2367 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2368 }
2369
2370
2371
2372 /*************************************************
2373 *        Test for a personal message             *
2374 *************************************************/
2375
2376 /* This function is global so that it can also be called from the code that
2377 implements Sieve filters.
2378
2379 Arguments:
2380   aliases    a chain of aliases
2381   scan_cc    TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2382
2383 Returns:     TRUE if the message is deemed to be personal
2384 */
2385
2386 BOOL
2387 filter_personal(string_item *aliases, BOOL scan_cc)
2388 {
2389 uschar *self, *self_from, *self_to;
2390 uschar *psself = NULL, *psself_from = NULL, *psself_to = NULL;
2391 void *reset_point = store_get(0);
2392 BOOL yield;
2393 header_line *h;
2394 int to_count = 2;
2395 int from_count = 9;
2396
2397 /* If any header line in the message is a defined "List-" header field, it is
2398 not a personal message. We used to check for any header line that started with
2399 "List-", but this was tightened up for release 4.54. The check is now for
2400 "List-Id", defined in RFC 2929, or "List-Help", "List-Subscribe", "List-
2401 Unsubscribe", "List-Post", "List-Owner" or "List-Archive", all of which are
2402 defined in RFC 2369. We also scan for "Auto-Submitted"; if it is found to
2403 contain any value other than "no", the message is not personal (RFC 3834).
2404 Previously the test was for "auto-". */
2405
2406 for (h = header_list; h != NULL; h = h->next)
2407   {
2408   uschar *s;
2409   if (h->type == htype_old) continue;
2410
2411   if (strncmpic(h->text, US"List-", 5) == 0)
2412     {
2413     s = h->text + 5;
2414     if (strncmpic(s, US"Id:", 3) == 0 ||
2415         strncmpic(s, US"Help:", 5) == 0 ||
2416         strncmpic(s, US"Subscribe:", 10) == 0 ||
2417         strncmpic(s, US"Unsubscribe:", 12) == 0 ||
2418         strncmpic(s, US"Post:", 5) == 0 ||
2419         strncmpic(s, US"Owner:", 6) == 0 ||
2420         strncmpic(s, US"Archive:", 8) == 0)
2421       return FALSE;
2422     }
2423
2424   else if (strncmpic(h->text, US"Auto-submitted:", 15) == 0)
2425     {
2426     s = h->text + 15;
2427     while (isspace(*s)) s++;
2428     if (strncmpic(s, US"no", 2) != 0) return FALSE;
2429     s += 2;
2430     while (isspace(*s)) s++;
2431     if (*s != 0) return FALSE;
2432     }
2433   }
2434
2435 /* Set up "my" address */
2436
2437 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2438 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2439   global_rewrite_rules);
2440 self_to   = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2441   global_rewrite_rules);
2442
2443
2444 if (self_from == NULL) self_from = self;
2445 if (self_to == NULL) self_to = self;
2446
2447 /* If there's a prefix or suffix set, we must include the prefixed/
2448 suffixed version of the local part in the tests. */
2449
2450 if (deliver_localpart_prefix != NULL || deliver_localpart_suffix != NULL)
2451   {
2452   psself = string_sprintf("%s%s%s@%s",
2453     (deliver_localpart_prefix == NULL)? US"" : deliver_localpart_prefix,
2454     deliver_localpart,
2455     (deliver_localpart_suffix == NULL)? US"" : deliver_localpart_suffix,
2456     deliver_domain);
2457   psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2458     global_rewrite_rules);
2459   psself_to   = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2460     global_rewrite_rules);
2461   if (psself_from == NULL) psself_from = psself;
2462   if (psself_to == NULL) psself_to = psself;
2463   to_count += 2;
2464   from_count += 2;
2465   }
2466
2467 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2468
2469 yield =
2470   (
2471   header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2472                psself_to) ||
2473     (scan_cc &&
2474        (
2475        header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2476                              psself, psself_to)
2477        ||
2478        header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2479                               psself, psself_to)
2480        )
2481     )
2482   ) &&
2483
2484   header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2485     "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2486     "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2487
2488   header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2489
2490   (sender_address == NULL || sender_address[0] != 0);
2491
2492 store_reset(reset_point);
2493 return yield;
2494 }
2495
2496
2497
2498 /*************************************************
2499 *            Interpret a mail filter file        *
2500 *************************************************/
2501
2502 /*
2503 Arguments:
2504   filter      points to the entire file, read into store as a single string
2505   options     controls whether various special things are allowed, and requests
2506               special actions
2507   generated   where to hang newly-generated addresses
2508   error       where to pass back an error text
2509
2510 Returns:      FF_DELIVERED     success, a significant action was taken
2511               FF_NOTDELIVERED  success, no significant action
2512               FF_DEFER         defer requested
2513               FF_FAIL          fail requested
2514               FF_FREEZE        freeze requested
2515               FF_ERROR         there was a problem
2516 */
2517
2518 int
2519 filter_interpret(uschar *filter, int options, address_item **generated,
2520   uschar **error)
2521 {
2522 int i;
2523 int yield = FF_ERROR;
2524 uschar *ptr = filter;
2525 uschar *save_headers_charset = headers_charset;
2526 filter_cmd *commands = NULL;
2527 filter_cmd **lastcmdptr = &commands;
2528
2529 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2530
2531 /* Initialize "not in an if command", set the global flag that is always TRUE
2532 while filtering, and zero the variables. */
2533
2534 expect_endif = 0;
2535 output_indent = 0;
2536 filter_running = TRUE;
2537 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2538
2539 /* To save having to pass certain values about all the time, make them static.
2540 Also initialize the line number, for error messages, and the log file
2541 variables. */
2542
2543 filter_options = options;
2544 filter_delivered = FALSE;
2545 finish_obeyed = FALSE;
2546 error_pointer = error;
2547 *error_pointer = NULL;
2548 line_number = 1;
2549 log_fd = -1;
2550 log_mode = 0600;
2551 log_filename = NULL;
2552
2553 /* Scan filter file for syntax and build up an interpretation thereof, and
2554 interpret the compiled commands, and if testing, say whether we ended up
2555 delivered or not, unless something went wrong. */
2556
2557 seen_force = FALSE;
2558 ptr = nextsigchar(ptr, TRUE);
2559
2560 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2561   yield = interpret_commands(commands, generated);
2562
2563 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2564   {
2565   uschar *s = US"";
2566   switch(yield)
2567     {
2568     case FF_DEFER:
2569     s = US"Filtering ended by \"defer\".";
2570     break;
2571
2572     case FF_FREEZE:
2573     s = US"Filtering ended by \"freeze\".";
2574     break;
2575
2576     case FF_FAIL:
2577     s = US"Filtering ended by \"fail\".";
2578     break;
2579
2580     case FF_DELIVERED:
2581     s = US"Filtering set up at least one significant delivery "
2582            "or other action.\n"
2583            "No other deliveries will occur.";
2584     break;
2585
2586     case FF_NOTDELIVERED:
2587     s = US"Filtering did not set up a significant delivery.\n"
2588            "Normal delivery will occur.";
2589     break;
2590
2591     case FF_ERROR:
2592     s = string_sprintf("Filter error: %s", *error);
2593     break;
2594     }
2595
2596   if (filter_test != FTEST_NONE) printf("%s\n", CS s);
2597     else debug_printf("%s\n", s);
2598   }
2599
2600 /* Close the log file if it was opened, and kill off any numerical variables
2601 before returning. Reset the header decoding charset. */
2602
2603 if (log_fd >= 0) (void)close(log_fd);
2604 expand_nmax = -1;
2605 filter_running = FALSE;
2606 headers_charset = save_headers_charset;
2607
2608 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2609 return yield;
2610 }
2611
2612
2613 /* End of filter.c */