-/* $Cambridge: exim/src/src/match.c,v 1.16 2006/10/31 16:08:11 ph10 Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for matching strings */
strings, domains, and local parts. */
typedef struct check_string_block {
- uschar *origsubject; /* caseful; keep these two first, in */
- uschar *subject; /* step with the block below */
+ const uschar *origsubject; /* caseful; keep these two first, in */
+ const uschar *subject; /* step with the block below */
int expand_setup;
BOOL use_partial;
BOOL caseless;
static int
check_string(void *arg, uschar *pattern, uschar **valueptr, uschar **error)
{
-check_string_block *cb = (check_string_block *)arg;
+const check_string_block *cb = arg;
int search_type, partial, affixlen, starflags;
int expand_setup = cb->expand_setup;
uschar *affix;
it works if the pattern uses (?-i) to turn off case-independence, overriding
"caseless". */
-s = (pattern[0] == '^')? cb->origsubject : cb->subject;
+s = string_copy(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. */
{
const pcre *re = regex_must_compile(pattern, cb->caseless, FALSE);
return ((expand_setup < 0)?
- pcre_exec(re, NULL, CS s, Ustrlen(s), 0, PCRE_EOPT, NULL, 0) >= 0
+ pcre_exec(re, NULL, CCS s, Ustrlen(s), 0, PCRE_EOPT, NULL, 0) >= 0
:
regex_match_and_setup(re, s, 0, expand_setup)
)?
NULL, /* service name not relevant */
NULL, /* srv_fail_domains not relevant */
NULL, /* mx_fail_domains not relevant */
+ NULL, /* no dnssec request XXX ? */
+ NULL, /* no dnssec require XXX ? */
NULL, /* no feedback FQDN */
&removed); /* feedback if local removed */
type MCL_STRING, MCL_DOMAIN, MCL_HOST, MCL_ADDRESS, or MCL_LOCALPART
*/
-static uschar *
+static const uschar *
get_check_key(void *arg, int type)
{
switch(type)
int
match_check_list(uschar **listptr, int sep, tree_node **anchorptr,
unsigned int **cache_ptr, int (*func)(void *,uschar *,uschar **,uschar **),
- void *arg, int type, uschar *name, uschar **valueptr)
+ void *arg, int type, const uschar *name, uschar **valueptr)
{
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;
if (type == MCL_DOMAIN && deliver_domain == NULL)
{
check_string_block *cb = (check_string_block *)arg;
- deliver_domain = cb->subject;
+ deliver_domain = string_copy(cb->subject);
list = expand_string(*listptr);
deliver_domain = 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)
{
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
cached = US" - cached";
if (valueptr != NULL)
{
- uschar *key = get_check_key(arg, type);
+ const uschar *key = get_check_key(arg, type);
namedlist_cacheblock *p;
for (p = nb->cache_data; p != NULL; p = p->next)
{
else
{
- uschar *error;
+ uschar *error = NULL;
switch ((func)(arg, ss, valueptr, &error))
{
case OK:
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
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 */
*/
int
-match_isinlist(uschar *s, uschar **listptr, int sep, tree_node **anchorptr,
+match_isinlist(const uschar *s, uschar **listptr, int sep,
+ tree_node **anchorptr,
unsigned int *cache_bits, int type, BOOL caseless, uschar **valueptr)
{
unsigned int *local_cache_bits = cache_bits;
error = error; /* Keep clever compilers from complaining */
-DEBUG(D_lists) debug_printf("address match: subject=%s pattern=%s\n",
+DEBUG(D_lists) debug_printf("address match test: subject=%s pattern=%s\n",
subject, pattern);
/* Find the subject's domain */