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