Forward bugfix from pdkim repo
[exim.git] / src / src / match.c
index 218944530acff9e7112e55996a0b1375a8ec4b00..8b25d2e13dae09c0c1c3d126bc2479816ef49dcf 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/match.c,v 1.14 2006/04/04 10:01:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/match.c,v 1.19 2007/06/26 13:50:41 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2007 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for matching strings */
@@ -74,7 +74,8 @@ Arguments:
                    returns ERROR)
 
 Contents of the argument block:
-  subject        the subject string to be checked
+  origsubject    the subject in its original casing
+  subject        the subject string to be checked, lowercased if caseless
   expand_setup   if < 0, don't set up any numeric expansion variables;
                  if = 0, set $0 to whole subject, and either
                    $1 to what matches * or
@@ -99,7 +100,7 @@ check_string_block *cb = (check_string_block *)arg;
 int search_type, partial, affixlen, starflags;
 int expand_setup = cb->expand_setup;
 uschar *affix;
-uschar *s = cb->subject;
+uschar *s;
 uschar *filename = NULL;
 uschar *keyquery, *result, *semicolon;
 void *handle;
@@ -108,6 +109,12 @@ error = error;  /* Keep clever compilers from complaining */
 
 if (valueptr != NULL) *valueptr = NULL;  /* For non-lookup matches */
 
+/* For regular expressions, use cb->origsubject rather than cb->subject so that
+it works if the pattern uses (?-i) to turn off case-independence, overriding
+"caseless". */
+
+s = (pattern[0] == '^')? cb->origsubject : cb->subject;
+
 /* If required to set up $0, initialize the data but don't turn on by setting
 expand_nmax until the match is assured. */
 
@@ -437,6 +444,8 @@ int yield = OK;
 unsigned int *original_cache_bits = *cache_ptr;
 BOOL include_unknown = FALSE;
 BOOL ignore_unknown = FALSE;
+BOOL include_defer = FALSE;
+BOOL ignore_defer = FALSE;
 uschar *list;
 uschar *sss;
 uschar *ot = NULL;
@@ -474,7 +483,19 @@ if (type >= MCL_NOEXPAND)
   }
 else
   {
-  list = expand_string(*listptr);
+  /* If we are searching a domain list, and $domain is not set, set it to the
+  subject that is being sought for the duration of the expansion. */
+
+  if (type == MCL_DOMAIN && deliver_domain == NULL)
+    {
+    check_string_block *cb = (check_string_block *)arg;
+    deliver_domain = cb->subject;
+    list = expand_string(*listptr);
+    deliver_domain = NULL;
+    }
+
+  else list = expand_string(*listptr);
+
   if (list == NULL)
     {
     if (expand_string_forcedfail)
@@ -534,10 +555,11 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
       }
     }
 
-  /* If the host item is "+include_unknown", remember it in case there's a
-  subsequent failed reverse lookup. */
+  /* If the host item is "+include_unknown" or "+ignore_unknown", remember it
+  in case there's a subsequent failed reverse lookup. There is similar
+  processing for "defer". */
 
-  else if (type == MCL_HOST)
+  else if (type == MCL_HOST && *ss == '+')
     {
     if (Ustrcmp(ss, "+include_unknown") == 0)
       {
@@ -551,6 +573,18 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
       include_unknown = FALSE;
       continue;
       }
+    if (Ustrcmp(ss, "+include_defer") == 0)
+      {
+      include_defer = TRUE;
+      ignore_defer = FALSE;
+      continue;
+      }
+    if (Ustrcmp(ss, "+ignore_defer") == 0)
+      {
+      ignore_defer = TRUE;
+      include_defer = FALSE;
+      continue;
+      }
     }
 
   /* Starting with ! specifies a negative item. It is theoretically possible
@@ -696,7 +730,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
 
     else
       {
-      uschar *error;
+      uschar *error = NULL;
       switch ((func)(arg, ss, valueptr, &error))
         {
         case OK:
@@ -705,6 +739,19 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
         return yield;
 
         case DEFER:
+        if (error == NULL)
+          error = string_sprintf("DNS lookup of %s deferred", ss);
+        if (ignore_defer)
+          {
+          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n",
+            error);
+          break;
+          }
+        if (include_defer)
+          {
+          log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
+          return OK;
+          }
         goto DEFER_RETURN;
 
         /* The ERROR return occurs when checking hosts, when either a forward
@@ -804,7 +851,20 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
         return file_yield;
 
         case DEFER:
+        if (error == NULL)
+          error = string_sprintf("DNS lookup of %s deferred", ss);
+        if (ignore_defer)
+          {
+          HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n",
+            error);
+          break;
+          }
         (void)fclose(f);
+        if (include_defer)
+          {
+          log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error);
+          return OK;
+          }
         goto DEFER_RETURN;
 
         case ERROR:          /* host name lookup failed - this can only */