[MEDIUM] add support for anonymous ACLs

Anonymous ACLs allow the declaration of rules which rely directly on
ACL expressions without passing via the declaration of an ACL. Example :

   With named ACLs :

        acl site_dead nbsrv(dynamic) lt 2
        acl site_dead nbsrv(static)  lt 2
        monitor fail  if site_dead

   With anonymous ACLs :

        monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 }
diff --git a/doc/configuration.txt b/doc/configuration.txt
index ccb7e1c..4e6f631 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -6216,6 +6216,36 @@
    use_backend static if host_static or host_www url_static
    use_backend www    if host_www
 
+It is also possible to form rules using "anonymous ACLs". Those are unnamed ACL
+expressions that are built on the fly without needing to be declared. They must
+be enclosed between braces, with a space before and after each brace (because
+the braces must be seen as independant words). Example :
+
+   The following rule :
+
+       acl missing_cl hdr_cnt(Content-length) eq 0
+       block if METH_POST missing_cl
+
+   Can also be written that way :
+
+       block if METH_POST { hdr_cnt(Content-length) eq 0 }
+
+It is generally not recommended to use this construct because it's a lot easier
+to leave errors in the configuration when written that way. However, for very
+simple rules matching only one source IP address for instance, it can make more
+sense to use them than to declare ACLs with random names. Another example of
+good use is the following :
+
+   With named ACLs :
+
+        acl site_dead nbsrv(dynamic) lt 2
+        acl site_dead nbsrv(static)  lt 2
+        monitor fail  if site_dead
+
+   With anonymous ACLs :
+
+        monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 }
+
 See section 4.2 for detailed help on the "block" and "use_backend" keywords.
 
 
diff --git a/src/acl.c b/src/acl.c
index 007751d..c6c7484 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -963,16 +963,45 @@
 			continue;
 		}
 
-		/* search for <word> in the known ACL names. If we do not find
-		 * it, let's look for it in the default ACLs, and if found, add
-		 * it to the list of ACLs of this proxy. This makes it possible
-		 * to override them.
-		 */
-		cur_acl = find_acl_by_name(word, known_acl);
-		if (cur_acl == NULL) {
-			cur_acl = find_acl_default(word, known_acl);
-			if (cur_acl == NULL)
+		if (strcmp(word, "{") == 0) {
+			/* we may have a complete ACL expression between two braces,
+			 * find the last one.
+			 */
+			int arg_end = arg + 1;
+			const char **args_new;
+
+			while (*args[arg_end] && strcmp(args[arg_end], "}") != 0)
+				arg_end++;
+
+			if (!*args[arg_end])
+				goto out_free_suite;
+
+			args_new = calloc(1, (arg_end - arg + 1) * sizeof(*args_new));
+			if (!args_new)
+				goto out_free_suite;
+
+			args_new[0] = ".noname";
+			memcpy(args_new + 1, args + arg + 1, (arg_end - arg) * sizeof(*args_new));
+			args_new[arg_end - arg] = "";
+			cur_acl = parse_acl(args_new, known_acl);
+			free(args_new);
+
+			if (!cur_acl)
 				goto out_free_suite;
+			arg = arg_end;
+		}
+		else {
+			/* search for <word> in the known ACL names. If we do not find
+			 * it, let's look for it in the default ACLs, and if found, add
+			 * it to the list of ACLs of this proxy. This makes it possible
+			 * to override them.
+			 */
+			cur_acl = find_acl_by_name(word, known_acl);
+			if (cur_acl == NULL) {
+				cur_acl = find_acl_default(word, known_acl);
+				if (cur_acl == NULL)
+					goto out_free_suite;
+			}
 		}
 
 		cur_term = (struct acl_term *)calloc(1, sizeof(*cur_term));
diff --git a/src/cfgparse.c b/src/cfgparse.c
index a57f1bf..4263f94 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -4733,42 +4733,36 @@
 		}
 
 		if (curproxy->uri_auth && curproxy->uri_auth->userlist) {
-			const char *uri_auth_compat_acl[3] = { ".internal-stats-auth-ok", "http_auth(.internal-stats-userlist)", ""};
-			const char *uri_auth_compat_req[][4] = {
-				{ "allow", "if", ".internal-stats-auth-ok", ""},
-				{ "auth", "", "", ""},
-				{ 0 },
-			};
+			const char *uri_auth_compat_req[10];
 			struct req_acl_rule *req_acl;
-			int i;
+			int i = 0;
 
-			if (parse_acl(uri_auth_compat_acl, &curproxy->acl) == NULL) {
-				Alert("Error compiling internal auth-compat acl.\n");
-				cfgerr++;
-				goto out_uri_auth_compat;
-			}
+			/* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
+			uri_auth_compat_req[i++] = "auth";
 
 			if (curproxy->uri_auth->auth_realm) {
-				uri_auth_compat_req[1][1] = "realm";
-				uri_auth_compat_req[1][2] = curproxy->uri_auth->auth_realm;
-			} else
-				uri_auth_compat_req[1][1] = "";
+				uri_auth_compat_req[i++] = "realm";
+				uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
+			}
 
-			for (i = 0; *uri_auth_compat_req[i]; i++) {
-				req_acl = parse_auth_cond(uri_auth_compat_req[i], "internal-stats-auth-compat", i, curproxy);
-				if (!req_acl) {
-					cfgerr++;
-					break;
-				}
+			uri_auth_compat_req[i++] = "unless";
+			uri_auth_compat_req[i++] = "{";
+			uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
+			uri_auth_compat_req[i++] = "}";
+			uri_auth_compat_req[i++] = "";
 
-				LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
+			req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
+			if (!req_acl) {
+				cfgerr++;
+				break;
 			}
 
+			LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
+
 			if (curproxy->uri_auth->auth_realm) {
 				free(curproxy->uri_auth->auth_realm);
 				curproxy->uri_auth->auth_realm = NULL;
 			}
-
 		}
 out_uri_auth_compat: