alphabetical order. */
static uschar *item_table[] = {
+ US"acl",
US"dlfunc",
US"extract",
US"filter",
US"tr" };
enum {
+ EITEM_ACL,
EITEM_DLFUNC,
EITEM_EXTRACT,
EITEM_FILTER,
US"l",
US"lc",
US"length",
- US"list",
+ US"listcount",
+ US"listnamed",
US"mask",
US"md5",
US"nh",
US"nhash",
- US"nlist",
US"quote",
US"randint",
US"rfc2047",
EOP_L,
EOP_LC,
EOP_LENGTH,
- EOP_LIST,
+ EOP_LISTCOUNT,
+ EOP_LISTNAMED,
EOP_MASK,
EOP_MD5,
EOP_NH,
EOP_NHASH,
- EOP_NLIST,
EOP_QUOTE,
EOP_RANDINT,
EOP_RFC2047,
static var_entry var_table[] = {
/* WARNING: Do not invent variables whose names start acl_c or acl_m because
they will be confused with user-creatable ACL variables. */
+ { "acl_arg1", vtype_stringptr, &acl_arg[0] },
+ { "acl_arg2", vtype_stringptr, &acl_arg[1] },
+ { "acl_arg3", vtype_stringptr, &acl_arg[2] },
+ { "acl_arg4", vtype_stringptr, &acl_arg[3] },
+ { "acl_arg5", vtype_stringptr, &acl_arg[4] },
+ { "acl_arg6", vtype_stringptr, &acl_arg[5] },
+ { "acl_arg7", vtype_stringptr, &acl_arg[6] },
+ { "acl_arg8", vtype_stringptr, &acl_arg[7] },
+ { "acl_arg9", vtype_stringptr, &acl_arg[8] },
+ { "acl_narg", vtype_int, &acl_narg },
{ "acl_verify_message", vtype_stringptr, &acl_verify_message },
{ "address_data", vtype_stringptr, &deliver_address_data },
{ "address_file", vtype_stringptr, &address_file },
switch(item_type)
{
+ /* Call an ACL from an expansion. We feed data in via $acl_arg1 - $acl_arg9.
+ If the ACL returns acceptance we return content set by "message ="
+ There is currently no limit on recursion; this would have us call
+ acl_check_internal() directly and get a current level from somewhere.
+ */
+
+ case EITEM_ACL:
+ {
+ int rc;
+ uschar *sub[10]; /* name + arg1-arg9, must match number of acl_arg[] */
+ uschar *new_yield;
+ uschar *user_msg;
+ uschar *log_msg;
+ switch(read_subs(sub, 10, 1, &s, skipping, TRUE, US"acl"))
+ {
+ case 1: goto EXPAND_FAILED_CURLY;
+ case 2:
+ case 3: goto EXPAND_FAILED;
+ }
+ if (skipping) continue;
+
+ for (rc = 1; rc < sizeof(sub)/sizeof(*sub) && sub[rc]; rc++)
+ acl_arg[rc-1] = sub[rc];
+ acl_narg = rc-1;
+ while (rc < sizeof(sub)/sizeof(*sub))
+ acl_arg[rc++ - 1] = NULL;
+
+ DEBUG(D_expand)
+ debug_printf("expanding: acl: %s arg: %s%s\n",
+ sub[0],
+ acl_narg>0 ? sub[1] : US"<none>",
+ acl_narg>1 ? " +more" : "");
+
+ switch(rc = acl_check(ACL_WHERE_EXPANSION, NULL, sub[0], &user_msg, &log_msg))
+ {
+ case OK:
+ if (user_msg)
+ yield = string_cat(yield, &size, &ptr, user_msg, Ustrlen(user_msg));
+ continue;
+ case DEFER:
+ continue;
+ default:
+ expand_string_message = string_sprintf("acl \"%s\" did not accept", sub[0]);
+ goto EXPAND_FAILED;
+ }
+ }
+
/* Handle conditionals - preserve the values of the numerical expansion
variables in case they get changed by a regular expression match in the
condition. If not, they retain their external settings. At the end
continue;
}
+ /* count the number of list elements */
+
+ case EOP_LISTCOUNT:
+ {
+ int cnt = 0;
+ int sep = 0;
+ uschar * cp;
+ uschar buffer[256];
+
+ while (string_nextinlist(&sub, &sep, buffer, sizeof(buffer)) != NULL) cnt++;
+ cp = string_sprintf("%d", cnt);
+ yield = string_cat(yield, &size, &ptr, cp, Ustrlen(cp));
+ continue;
+ }
+
/* expand a named list given the name */
- /* handles nested named lists but will confuse the separators in the result */
+ /* handles nested named lists; requotes as colon-sep list */
- case EOP_LIST:
+ case EOP_LISTNAMED:
{
tree_node *t = NULL;
uschar * list;
goto EXPAND_FAILED;
}
- if (skipping) continue;
list = ((namedlist_block *)(t->data.ptr))->string;
while ((item = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
if (*item == '+') /* list item is itself a named list */
{
- uschar * sub = string_sprintf("${list%s:%s}", suffix, item);
+ uschar * sub = string_sprintf("${listnamed%s:%s}", suffix, item);
item = expand_string_internal(sub, FALSE, NULL, FALSE, TRUE);
}
else if (sep != ':') /* item from non-colon-sep list, re-quote for colon list-separator */
continue;
}
- /* count the number of list elements */
-
- case EOP_NLIST:
- {
- int cnt = 0;
- int sep = 0;
- uschar * cp;
- uschar buffer[256];
-
- while (string_nextinlist(&sub, &sep, buffer, sizeof(buffer)) != NULL) cnt++;
- cp = string_sprintf("%d", cnt);
- yield = string_cat(yield, &size, &ptr, cp, Ustrlen(cp));
- continue;
- }
-
/* mask applies a mask to an IP address; for example the result of
${mask:131.111.10.206/28} is 131.111.10.192/28. */