-/* $Cambridge: exim/src/src/expand.c,v 1.31 2005/06/20 10:28:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.38 2005/08/01 14:00:35 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
US"match",
US"match_address",
US"match_domain",
+ US"match_ip",
US"match_local_part",
US"or",
US"pam",
ECOND_MATCH,
ECOND_MATCH_ADDRESS,
ECOND_MATCH_DOMAIN,
+ ECOND_MATCH_IP,
ECOND_MATCH_LOCAL_PART,
ECOND_OR,
ECOND_PAM,
{ "message_body", vtype_msgbody, &message_body },
{ "message_body_end", vtype_msgbody_end, &message_body_end },
{ "message_body_size", vtype_int, &message_body_size },
+ { "message_exim_id", vtype_stringptr, &message_id },
{ "message_headers", vtype_msgheaders, NULL },
{ "message_id", vtype_stringptr, &message_id },
{ "message_linecount", vtype_int, &message_linecount },
switch (var_table[middle].type)
{
- case vtype_filter_int:
- if (!filter_running) return NULL;
- /* Fall through */
-
#ifdef EXPERIMENTAL_DOMAINKEYS
case vtype_dk_verify:
if (Ustrcmp(var_table[middle].name, "dk_sender_source") == 0)
switch(dk_verify_block->address_source) {
- case DK_EXIM_ADDRESS_NONE: s = "0"; break;
- case DK_EXIM_ADDRESS_FROM_FROM: s = "from"; break;
- case DK_EXIM_ADDRESS_FROM_SENDER: s = "sender"; break;
+ case DK_EXIM_ADDRESS_NONE: s = US"0"; break;
+ case DK_EXIM_ADDRESS_FROM_FROM: s = US"from"; break;
+ case DK_EXIM_ADDRESS_FROM_SENDER: s = US"sender"; break;
}
if (Ustrcmp(var_table[middle].name, "dk_status") == 0)
switch(dk_verify_block->result) {
- case DK_EXIM_RESULT_ERR: s = "error"; break;
- case DK_EXIM_RESULT_BAD_FORMAT: s = "bad format"; break;
- case DK_EXIM_RESULT_NO_KEY: s = "no key"; break;
- case DK_EXIM_RESULT_NO_SIGNATURE: s = "no signature"; break;
- case DK_EXIM_RESULT_REVOKED: s = "revoked"; break;
- case DK_EXIM_RESULT_NON_PARTICIPANT: s = "non-participant"; break;
- case DK_EXIM_RESULT_GOOD: s = "good"; break;
- case DK_EXIM_RESULT_BAD: s = "bad"; break;
+ case DK_EXIM_RESULT_ERR: s = US"error"; break;
+ case DK_EXIM_RESULT_BAD_FORMAT: s = US"bad format"; break;
+ case DK_EXIM_RESULT_NO_KEY: s = US"no key"; break;
+ case DK_EXIM_RESULT_NO_SIGNATURE: s = US"no signature"; break;
+ case DK_EXIM_RESULT_REVOKED: s = US"revoked"; break;
+ case DK_EXIM_RESULT_NON_PARTICIPANT: s = US"non-participant"; break;
+ case DK_EXIM_RESULT_GOOD: s = US"good"; break;
+ case DK_EXIM_RESULT_BAD: s = US"bad"; break;
}
if (Ustrcmp(var_table[middle].name, "dk_signsall") == 0)
- s = (dk_verify_block->signsall)? "1" : "0";
+ s = (dk_verify_block->signsall)? US"1" : US"0";
if (Ustrcmp(var_table[middle].name, "dk_testing") == 0)
- s = (dk_verify_block->testing)? "1" : "0";
+ s = (dk_verify_block->testing)? US"1" : US"0";
if (Ustrcmp(var_table[middle].name, "dk_is_signed") == 0)
- s = (dk_verify_block->is_signed)? "1" : "0";
+ s = (dk_verify_block->is_signed)? US"1" : US"0";
return (s == NULL)? US"" : s;
#endif
+ case vtype_filter_int:
+ if (!filter_running) return NULL;
+ /* Fall through */
+ /* VVVVVVVVVVVV */
case vtype_int:
sprintf(CS var_buffer, "%d", *(int *)(var_table[middle].value)); /* Integer */
return var_buffer;
variables if it succeeds
match_address: matches in an address list
match_domain: matches in a domain list
+ match_ip: matches a host list that is restricted to IP addresses
match_local_part: matches in a local part list
crypteq: encrypts plaintext and compares against an encrypted text,
using crypt(), crypt16(), MD5 or SHA-1
case ECOND_MATCH:
case ECOND_MATCH_ADDRESS:
case ECOND_MATCH_DOMAIN:
+ case ECOND_MATCH_IP:
case ECOND_MATCH_LOCAL_PART:
case ECOND_CRYPTEQ:
MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
goto MATCHED_SOMETHING;
+ case ECOND_MATCH_IP: /* Match IP address in a host list */
+ if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) <= 0)
+ {
+ expand_string_message = string_sprintf("\"%s\" is not an IP address",
+ sub[0]);
+ return NULL;
+ }
+ else
+ {
+ unsigned int *nullcache = NULL;
+ check_host_block cb;
+
+ cb.host_name = US"";
+ cb.host_address = sub[0];
+
+ /* If the host address starts off ::ffff: it is an IPv6 address in
+ IPv4-compatible mode. Find the IPv4 part for checking against IPv4
+ addresses. */
+
+ cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
+ cb.host_address + 7 : cb.host_address;
+
+ rc = match_check_list(
+ &sub[1], /* the list */
+ 0, /* separator character */
+ &hostlist_anchor, /* anchor pointer */
+ &nullcache, /* cache pointer */
+ check_host, /* function for testing */
+ &cb, /* argument for function */
+ MCL_HOST, /* type of check */
+ sub[0], /* text for debugging */
+ NULL); /* where to pass back data */
+ }
+ goto MATCHED_SOMETHING;
+
case ECOND_MATCH_LOCAL_PART:
rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL);
/* Fall through */
-
+ /* VVVVVVVVVVVV */
MATCHED_SOMETHING:
switch(rc)
{
/* Check that a key was provided for those lookup types that need it,
and was not supplied for those that use the query style. */
- if (!mac_islookup(stype, lookup_querystyle))
+ if (!mac_islookup(stype, lookup_querystyle|lookup_absfilequery))
{
if (key == NULL)
{
}
/* Get the next string in brackets and expand it. It is the file name for
- single-key+file lookups, and the whole query otherwise. */
+ single-key+file lookups, and the whole query otherwise. In the case of
+ queries that also require a file name (e.g. sqlite), the file name comes
+ first. */
if (*s != '{') goto EXPAND_FAILED_CURLY;
filename = expand_string_internal(s+1, TRUE, &s, skipping);
while (isspace(*s)) s++;
/* If this isn't a single-key+file lookup, re-arrange the variables
- to be appropriate for the search_ functions. */
+ to be appropriate for the search_ functions. For query-style lookups,
+ there is just a "key", and no file name. For the special query-style +
+ file types, the query (i.e. "key") starts with a file name. */
if (key == NULL)
{
+ while (isspace(*filename)) filename++;
key = filename;
- filename = NULL;
+
+ if (mac_islookup(stype, lookup_querystyle))
+ {
+ filename = NULL;
+ }
+ else
+ {
+ if (*filename != '/')
+ {
+ expand_string_message = string_sprintf(
+ "absolute file name expected for \"%s\" lookup", name);
+ goto EXPAND_FAILED;
+ }
+ while (*key != 0 && !isspace(*key)) key++;
+ if (*key != 0) *key++ = 0;
+ }
}
/* If skipping, don't do the next bit - just lookup_value == NULL, as if
uschar *now = prvs_daystamp(0);
unsigned int inow = 0,iexpire = 1;
- sscanf(CS now,"%u",&inow);
- sscanf(CS daystamp,"%u",&iexpire);
+ (void)sscanf(CS now,"%u",&inow);
+ (void)sscanf(CS daystamp,"%u",&iexpire);
/* When "iexpire" is < 7, a "flip" has occured.
Adjust "inow" accordingly. */
}
yield = cat_file(f, yield, &size, &ptr, sub_arg[1]);
- fclose(f);
+ (void)fclose(f);
continue;
}
alarm(timeout);
yield = cat_file(f, yield, &size, &ptr, sub_arg[3]);
alarm(0);
- fclose(f);
+ (void)fclose(f);
/* After a timeout, we restore the pointer in the result, that is,
make sure we add nothing from the socket. */
/* Nothing is written to the standard input. */
- close(fd_in);
+ (void)close(fd_in);
/* Wait for the process to finish, applying the timeout, and inspect its
return code for serious disasters. Simple non-zero returns are passed on.
f = fdopen(fd_out, "rb");
lookup_value = NULL;
lookup_value = cat_file(f, lookup_value, &lsize, &lptr, NULL);
- fclose(f);
+ (void)fclose(f);
}
/* Process the yes/no strings; $value may be useful in both cases */