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