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