MEDIUM: acl: support using sample fetches directly in ACLs

Now it becomes possible to directly use sample fetches as the ACL fetch
methods. In this case, the matching method is mandatory. This allows to
form more ACL combinations from existing fetches and will limit the need
for new ACLs when everything is available to form them from sample fetches
and matches.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index da287f3..0b14d0e 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -8288,6 +8288,14 @@
 7.5. Available matching criteria
 --------------------------------
 
+A number of predefined criteria may be used to form ACL expressions. The ones
+that are ACL-specific are detailed here. In addition to these ones, all sample
+fetch methods described in section 7.8 may be used. However, with these last
+ones, no default pattern matching method is defined, so it is mandatory to pass
+"-m" followed by a method. When a same keyword exists in both forms, the ACL
+compatible form prevails.
+
+
 7.5.1. Matching at Layer 4 and below
 ------------------------------------
 
diff --git a/src/acl.c b/src/acl.c
index 5077273..4a53072 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -1037,11 +1037,24 @@
 	struct acl_pattern *pattern;
 	int opaque, patflags;
 	const char *arg;
+	struct sample_fetch *smp = NULL;
 
+	/* First, we lookd for an ACL keyword. And if we don't find one, then
+	 * we look for a sample fetch keyword.
+	 */
 	aclkw = find_acl_kw(args[0]);
 	if (!aclkw || !aclkw->parse) {
-		memprintf(err, "unknown ACL keyword '%s'", *args);
-		goto out_return;
+		const char *kwend;
+
+		kwend = strchr(args[0], '(');
+		if (!kwend)
+			kwend = args[0] + strlen(args[0]);
+		smp = find_sample_fetch(args[0], kwend - args[0]);
+
+		if (!smp) {
+			memprintf(err, "unknown ACL or sample keyword '%s'", *args);
+			goto out_return;
+		}
 	}
 
 	expr = (struct acl_expr *)calloc(1, sizeof(*expr));
@@ -1050,13 +1063,13 @@
 		goto out_return;
 	}
 
-	expr->kw = aclkw->kw;
+	expr->kw = aclkw ? aclkw->kw : smp->kw;
 	LIST_INIT(&expr->patterns);
 	expr->pattern_tree = EB_ROOT_UNIQUE;
-	expr->parse = aclkw->parse;
-	expr->match = aclkw->match;
+	expr->parse = aclkw ? aclkw->parse : NULL;
+	expr->match = aclkw ? aclkw->match : NULL;
 	expr->args = empty_arg_list;
-	expr->smp = aclkw->smp;
+	expr->smp = aclkw ? aclkw->smp : smp;
 
 	arg = strchr(args[0], '(');
 	if (expr->smp->arg_mask) {
@@ -1146,6 +1159,11 @@
 		if ((*args)[1] == 'i')
 			patflags |= ACL_PAT_F_IGNORE_CASE;
 		else if ((*args)[1] == 'f') {
+			if (!expr->parse) {
+				memprintf(err, "matching method must be specified first (using '-m') when using a sample fetch ('%s')", expr->kw);
+				goto out_free_expr;
+			}
+
 			if (!acl_read_patterns_from_file(expr, args[1], patflags | ACL_PAT_F_FROM_FILE, err))
 				goto out_free_expr;
 			args++;
@@ -1198,6 +1216,11 @@
 		args++;
 	}
 
+	if (!expr->parse) {
+		memprintf(err, "matching method must be specified first (using '-m') when using a sample fetch ('%s')", expr->kw);
+		goto out_free_expr;
+	}
+
 	/* now parse all patterns */
 	opaque = 0;
 	while (**args) {