MEDIUM: http: unify acl and sample fetch functions

The following sample fetch functions were only usable by ACLs but are now
usable by sample fetches too :

    cook, cook_cnt, cook_val, hdr_cnt, hdr_ip, hdr_val, http_auth,
    http_auth_group, http_first_req, method, req_proto_http, req_ver,
    resp_ver, scook, scook_cnt, scook_val, shdr, shdr_cnt, shdr_ip,
    shdr_val, status, urlp, urlp_val,

Most of them won't bring much benefit at the moment, or are even aliases of
existing ones, however they'll be needed for ACL->SMP convergence.

A new val_usr() function was added to resolve userlist names into pointers.

The http_auth_group ACL forgot to make its first argument mandatory, so
there was a check in cfgparse to report a vague error. Now that args are
correctly parsed, let's report something more precise.

All urlp* ACLs now support an optional 3rd argument like their sample
counter-part which is the optional delimiter.

The fetch functions have been renamed "smp_fetch_*".

Some args controls on the sample keywords have been relaxed so that we
can soon use them for ACLs :

  - cookie now accepts to have an optional name ; it will return the
    first matching cookie if the name is not set ;
  - same for set-cookie and hdr
diff --git a/doc/configuration.txt b/doc/configuration.txt
index aef2a2c..8183daa 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -9612,17 +9612,35 @@
                queue size. This is only used with ACLs. See the ACL "connslots"
                keyword description for more information on possible caveats.
 
-  cookie(<name>)
+  cook([<name>])
+               This extracts the last occurrence of the cookie name <name> on a
+               "Cookie" header line from the request, and returns its value as
+               string. If no name is specified, the first cookie value is
+               returned.
+
+  cookie([<name>])
                This extracts the last occurrence of the cookie name <name> on a
                "Cookie" header line from the request, or a "Set-Cookie" header
-               from the response, and uses the corresponding value to match. A
-               typical use is to get multiple clients sharing a same profile
-               use the same server. This can be similar to what "appsession"
-               does with the "request-learn" statement, but with support for
-               multi-peer synchronization and state keeping across restarts.
+               from the response, and returns its value as a string. A typical
+               use is to get multiple clients sharing a same profile use the
+               same server. This can be similar to what "appsession" does with
+               the "request-learn" statement, but with support for multi-peer
+               synchronization and state keeping across restarts. If no name is
+               specified, the first cookie value is returned.
 
                See also : "appsession"
 
+  cook_cnt([<name>])
+               Returns an integer value representing the number of occurrences of
+               the cookie <name> in the request, or all cookies if <name> is not
+               specified.
+
+  cook_val([<name>])
+               This extracts the last occurrence of the cookie name <name> on a
+               "Cookie" header line from the request, and converts its value to
+               an integer which is returned. If no name is specified, the first
+               cookie value is returned.
+
   dst          This is the destination IPv4 address of the session on the
                client side, which is the address the client connected to.
                It can be useful when running in transparent mode. It is of
@@ -9673,6 +9691,49 @@
                last one. A typical use is with the X-Forwarded-For header once
                converted to IP, associated with an IP stick-table.
 
+  hdr_cnt([<name>])
+               Returns an integer value representing the number of occurrences
+               of request header field name <name>, or the total number of
+               header fields if <name> is not specified.
+
+  hdr_ip([<name>[,<occ>]])
+               This extracts the last occurrence of header <name> in an HTTP
+               request, converts it to an IPv4 or IPv6 address and returns this
+               address. Optionally, a specific occurrence might be specified as
+               a position number. Positive values indicate a position from the
+               first occurrence, with 1 being the first one. Negative values
+               indicate positions relative to the last one, with -1 being the
+               last one. A typical use is with the X-Forwarded-For header.
+
+  hdr_val([<name>[,<occ>]])
+               This extracts the last occurrence of header <name> in an HTTP
+               request, and converts it to an integer value. Optionally, a
+               specific occurrence might be specified as a position number.
+               Positive values indicate a position from the first occurrence,
+               with 1 being the first one. Negative values indicate positions
+               relative to the last one, with -1 being the last one. A typical
+               use is with the X-Forwarded-For header.
+
+  http_auth(<userlist>)
+  http_auth_group(<userlist>)
+               Returns a boolean indicating whether the authentication data
+               received from the client match a username & password stored in
+               the specified userlist. These fetch functions are not really
+               useful outside of ACLs.
+
+  http_first_req
+               Returns true when the request being processed is the first one
+               of the connection. This can be used to add or remove headers
+               that may be missing from some requests when a request is not the
+               first one, or to help grouping requests in the logs.
+
+  method
+               Returns an integer value corresponding to the to the method in
+               the HTTP request. For example, "GET" equals 1 (check sources to
+               establish the matching). Value 9 means "other method" and may be
+               converted to a string extracted from the stream. This should not
+               be used directly, this is only meant to be used from ACLs.
+
   nbsrv([<backend>])
                Returns an integer value corresponding to the number of usable
                servers of either the current backend or the named backend. This
@@ -9758,6 +9819,13 @@
   req_len      Returns an integer value corresponding to the number of bytes
                present in the request buffer. This is mostly used in ACL.
 
+  req_proto_http
+               Returns true when data in the request buffer look like HTTP and
+               correctly parses as such. It is the same parser as the common
+               HTTP request parser which is used so there should be no
+               surprises. This test may be used to report the protocol in TCP
+               logs.
+
   req_ssl_hello_type
                Returns an integer value containing the type of the SSL hello
                message found in the request buffer. Note that this only applies
@@ -9781,6 +9849,29 @@
                data layer, so this will not work with "bind" lines having the
                "ssl" option. This is mostly used in ACL.
 
+  req_ver      Returns the version string from the HTTP request, for example
+               "1.1". This can be useful for logs, but is mostly there for ACL.
+
+  resp_ver     Returns the version string from the HTTP response, for example
+               "1.1". This can be useful for logs, but is mostly there for ACL.
+
+  scook([<name>])
+               This extracts the last occurrence of the cookie name <name> on a
+               "Set-Cookie" header line from the response, and returns its
+               value as string. If no name is specified, the first cookie value
+               is returned.
+
+  scook_cnt([<name>])
+               Returns an integer value representing the number of occurrences of
+               the cookie <name> in the response, or all cookies if <name> is not
+               specified.
+
+  scook_val([<name>])
+               This extracts the last occurrence of the cookie name <name> on a
+               "Set-Cookie" header line from the response, and converts its
+               value to an integer which is returned. If no name is specified,
+               the first cookie value is returned.
+
   set-cookie(<name>)
                This fetch function is deprecated and has been superseded by the
                "cookie" fetch which is capable of handling both requests and
@@ -9794,6 +9885,39 @@
 
                See also : "appsession"
 
+  shdr(<name>[,<occ>])
+               This extracts the last occurrence of header <name> in an HTTP
+               response. Optionally, a specific occurrence might be specified
+               as a position number. Positive values indicate a position from
+               the first occurrence, with 1 being the first one. Negative
+               values indicate positions relative to the last one, with -1
+               being the last one. This can be useful to learn some data into
+               a stick-table.
+
+  shdr_cnt([<name>])
+               Returns an integer value representing the number of occurrences
+               of response header field name <name>, or the total number of
+               header fields if <name> is not specified.
+
+  shdr_ip([<name>[,<occ>]])
+               This extracts the last occurrence of header <name> in an HTTP
+               response, convert it to an IPv4 or IPv6 address and returns this
+               address. Optionally, a specific occurrence might be specified as
+               a position number. Positive values indicate a position from the
+               first occurrence, with 1 being the first one. Negative values
+               indicate positions relative to the last one, with -1 being the
+               last one. This can be useful to learn some data into a stick
+               table.
+
+  shdr_val([<name>[,<occ>]])
+               This extracts the last occurrence of header <name> in an HTTP
+               response, and converts it to an integer value. Optionally, a
+               specific occurrence might be specified as a position number.
+               Positive values indicate a position from the first occurrence,
+               with 1 being the first one. Negative values indicate positions
+               relative to the last one, with -1 being the last one. This can
+               be useful to learn some data into a stick table.
+
   so_id        Returns an integer containing the listening socket's id.
 
   src          This is the source IPv4 address of the client of the session.
@@ -10006,11 +10130,27 @@
                Returns the symmetric cipher key size used in bits when the
                incoming connection was made over an SSL/TLS transport layer.
 
+  status       Returns an integer containing the HTTP status code in the HTTP
+               response, for example, 302. It is mostly used within ACLs.
+
   url          This extracts the request's URL as presented in the request. A
                typical use is with prefetch-capable caches, and with portals
                which need to aggregate multiple information from databases and
                keep them in caches. See also "path".
 
+  urlp(<name>[,<delim>])
+               Note: all "urlp*" sample fetch methods apply only to the first
+               occurrence of the parameter <name> in the query string, which
+               is delimited by character <delim> if specified, otherwise '&'.
+               The parameter name is case-sensitive. This one extracts a string
+               corresponding to the value of the parameter <name>. This can be
+               used for session stickiness.
+
+  urlp_val(<name>[,<delim>])
+               See "urlp" above. This one extracts the URL parameter <name> in
+               the request and converts it ao an integer value. This can be
+               used for session stickiness.
+
   url_ip       This extracts the IP address from the request's URL when the
                host part is presented as an IP address. Its use is very
                limited. For instance, a monitoring system might use this field
diff --git a/src/proto_http.c b/src/proto_http.c
index 56d8dd6..e11d2a7 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -8471,7 +8471,7 @@
  * This is intended to be used with acl_match_meth() only.
  */
 static int
-acl_fetch_meth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_meth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                const struct arg *args, struct sample *smp)
 {
 	int meth;
@@ -8537,7 +8537,7 @@
 }
 
 static int
-acl_fetch_rqver(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_rqver(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                 const struct arg *args, struct sample *smp)
 {
 	struct http_txn *txn = l7;
@@ -8562,7 +8562,7 @@
 }
 
 static int
-acl_fetch_stver(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_stver(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                 const struct arg *args, struct sample *smp)
 {
 	struct http_txn *txn = l7;
@@ -8591,7 +8591,7 @@
 
 /* 3. Check on Status Code. We manipulate integers here. */
 static int
-acl_fetch_stcode(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_stcode(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                  const struct arg *args, struct sample *smp)
 {
 	struct http_txn *txn = l7;
@@ -8974,7 +8974,7 @@
 }
 
 static int
-acl_fetch_proto_http(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_proto_http(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                      const struct arg *args, struct sample *smp)
 {
 	/* Note: hdr_idx.v cannot be NULL in this ACL because the ACL is tagged
@@ -8990,7 +8990,7 @@
 
 /* return a valid test if the current request is the first one on the connection */
 static int
-acl_fetch_http_first_req(struct proxy *px, struct session *s, void *l7, unsigned int opt,
+smp_fetch_http_first_req(struct proxy *px, struct session *s, void *l7, unsigned int opt,
                          const struct arg *args, struct sample *smp)
 {
 	if (!s)
@@ -9003,7 +9003,7 @@
 
 /* Accepts exactly 1 argument of type userlist */
 static int
-acl_fetch_http_auth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_http_auth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                     const struct arg *args, struct sample *smp)
 {
 
@@ -9022,7 +9022,7 @@
 
 /* Accepts exactly 1 argument of type userlist */
 static int
-acl_fetch_http_auth_grp(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_http_auth_grp(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                         const struct arg *args, struct sample *smp)
 {
 
@@ -9254,7 +9254,7 @@
  * Accepts exactly 1 argument of type string.
  */
 static int
-acl_fetch_cookie_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+smp_fetch_cookie_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                      const struct arg *args, struct sample *smp)
 {
 	struct http_txn *txn = l7;
@@ -9485,6 +9485,35 @@
 	return 1;
 }
 
+/* This function is used to validate the arguments passed to any "http_auth" fetch
+ * keyword. These keywords support a mandatory userlist name which must be replaced
+ * by a pointer to the userlist. It is assumed that the types are already the correct
+ * ones. Returns 0 on error, non-zero if OK. If <err> is not NULL, it will be filled
+ * with a pointer to an error message in case of error, that the caller is responsible
+ * for freeing. The initial location must either be freeable or NULL.
+ */
+static int val_usr(struct arg *arg, char **err_msg)
+{
+	struct userlist *ul;
+
+	if (!arg || arg[0].type != ARGT_USR || !arg[0].data.str.len) {
+		memprintf(err_msg, "the name of a userlist is expected");
+		return 0;
+	}
+
+	ul = auth_find_userlist(arg[0].data.str.str);
+	if (!ul) {
+		memprintf(err_msg, "unable to find userlist <%s>", arg[0].data.str.str);
+		return 0;
+	}
+
+	free(arg[0].data.str.str);
+	arg[0].data.str.str = NULL;
+	arg[0].unresolved = 0;
+	arg[0].data.usr = ul;
+	return 1;
+}
+
 /************************************************************************/
 /*          All supported ACL keywords must be declared here.           */
 /************************************************************************/
@@ -9504,7 +9533,7 @@
 
 	{ "cook",            acl_parse_str,     smp_fetch_cookie,         acl_match_str,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
 	{ "cook_beg",        acl_parse_str,     smp_fetch_cookie,         acl_match_beg,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
-	{ "cook_cnt",        acl_parse_int,     acl_fetch_cookie_cnt,     acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
+	{ "cook_cnt",        acl_parse_int,     smp_fetch_cookie_cnt,     acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
 	{ "cook_dir",        acl_parse_str,     smp_fetch_cookie,         acl_match_dir,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
 	{ "cook_dom",        acl_parse_str,     smp_fetch_cookie,         acl_match_dom,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
 	{ "cook_end",        acl_parse_str,     smp_fetch_cookie,         acl_match_end,     ACL_USE_L7REQ_VOLATILE, ARG1(0,STR) },
@@ -9525,11 +9554,12 @@
 	{ "hdr_sub",         acl_parse_str,     smp_fetch_hdr,            acl_match_sub,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
 	{ "hdr_val",         acl_parse_int,     smp_fetch_hdr_val,        acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG2(0,STR,SINT), val_hdr },
 
-	{ "http_auth",       acl_parse_nothing, acl_fetch_http_auth,      acl_match_nothing, ACL_USE_L7REQ_VOLATILE, ARG1(0,USR) },
-	{ "http_auth_group", acl_parse_strcat,  acl_fetch_http_auth_grp,  acl_match_auth,    ACL_USE_L7REQ_VOLATILE, ARG1(0,USR) },
-	{ "http_first_req",  acl_parse_nothing, acl_fetch_http_first_req, acl_match_nothing, ACL_USE_L7REQ_PERMANENT, 0 },
+	{ "http_auth",       acl_parse_nothing, smp_fetch_http_auth,      acl_match_nothing, ACL_USE_L7REQ_VOLATILE, ARG1(0,USR) },
+	{ "http_auth_group", acl_parse_strcat,  smp_fetch_http_auth_grp,  acl_match_auth,    ACL_USE_L7REQ_VOLATILE, ARG1(1,USR) },
 
-	{ "method",          acl_parse_meth,    acl_fetch_meth,           acl_match_meth,    ACL_USE_L7REQ_PERMANENT, 0 },
+	{ "http_first_req",  acl_parse_nothing, smp_fetch_http_first_req, acl_match_nothing, ACL_USE_L7REQ_PERMANENT, 0 },
+
+	{ "method",          acl_parse_meth,    smp_fetch_meth,           acl_match_meth,    ACL_USE_L7REQ_PERMANENT, 0 },
 
 	{ "path",            acl_parse_str,     smp_fetch_path,           acl_match_str,     ACL_USE_L7REQ_VOLATILE, 0 },
 	{ "path_beg",        acl_parse_str,     smp_fetch_path,           acl_match_beg,     ACL_USE_L7REQ_VOLATILE, 0 },
@@ -9540,13 +9570,13 @@
 	{ "path_reg",        acl_parse_reg,     smp_fetch_path,           acl_match_reg,     ACL_USE_L7REQ_VOLATILE, 0 },
 	{ "path_sub",        acl_parse_str,     smp_fetch_path,           acl_match_sub,     ACL_USE_L7REQ_VOLATILE, 0 },
 
-	{ "req_proto_http",  acl_parse_nothing, acl_fetch_proto_http,     acl_match_nothing, ACL_USE_L7REQ_PERMANENT, 0 },
-	{ "req_ver",         acl_parse_ver,     acl_fetch_rqver,          acl_match_str,     ACL_USE_L7REQ_VOLATILE, 0 },
-	{ "resp_ver",        acl_parse_ver,     acl_fetch_stver,          acl_match_str,     ACL_USE_L7RTR_VOLATILE, 0 },
+	{ "req_proto_http",  acl_parse_nothing, smp_fetch_proto_http,     acl_match_nothing, ACL_USE_L7REQ_PERMANENT, 0 },
+	{ "req_ver",         acl_parse_ver,     smp_fetch_rqver,          acl_match_str,     ACL_USE_L7REQ_VOLATILE,  0 },
+	{ "resp_ver",        acl_parse_ver,     smp_fetch_stver,          acl_match_str,     ACL_USE_L7RTR_VOLATILE,  0 },
 
 	{ "scook",           acl_parse_str,     smp_fetch_cookie,         acl_match_str,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
 	{ "scook_beg",       acl_parse_str,     smp_fetch_cookie,         acl_match_beg,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
-	{ "scook_cnt",       acl_parse_int,     acl_fetch_cookie_cnt,     acl_match_int,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
+	{ "scook_cnt",       acl_parse_int,     smp_fetch_cookie_cnt,     acl_match_int,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
 	{ "scook_dir",       acl_parse_str,     smp_fetch_cookie,         acl_match_dir,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
 	{ "scook_dom",       acl_parse_str,     smp_fetch_cookie,         acl_match_dom,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
 	{ "scook_end",       acl_parse_str,     smp_fetch_cookie,         acl_match_end,     ACL_USE_L7RTR_VOLATILE, ARG1(0,STR) },
@@ -9567,7 +9597,7 @@
 	{ "shdr_sub",        acl_parse_str,     smp_fetch_hdr,            acl_match_sub,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
 	{ "shdr_val",        acl_parse_int,     smp_fetch_hdr_val,        acl_match_int,     ACL_USE_L7RTR_VOLATILE, ARG2(0,STR,SINT), val_hdr },
 
-	{ "status",          acl_parse_int,     acl_fetch_stcode,         acl_match_int,     ACL_USE_L7RTR_PERMANENT, 0 },
+	{ "status",          acl_parse_int,     smp_fetch_stcode,         acl_match_int,     ACL_USE_L7RTR_PERMANENT, 0 },
 
 	{ "url",             acl_parse_str,     smp_fetch_url,            acl_match_str,     ACL_USE_L7REQ_VOLATILE, 0 },
 	{ "url_beg",         acl_parse_str,     smp_fetch_url,            acl_match_beg,     ACL_USE_L7REQ_VOLATILE, 0 },
@@ -9580,16 +9610,16 @@
 	{ "url_reg",         acl_parse_reg,     smp_fetch_url,            acl_match_reg,     ACL_USE_L7REQ_VOLATILE, 0 },
 	{ "url_sub",         acl_parse_str,     smp_fetch_url,            acl_match_sub,     ACL_USE_L7REQ_VOLATILE, 0 },
 
-	{ "urlp",            acl_parse_str,     smp_fetch_url_param,      acl_match_str,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_beg",        acl_parse_str,     smp_fetch_url_param,      acl_match_beg,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_dir",        acl_parse_str,     smp_fetch_url_param,      acl_match_dir,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_dom",        acl_parse_str,     smp_fetch_url_param,      acl_match_dom,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_end",        acl_parse_str,     smp_fetch_url_param,      acl_match_end,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_ip",         acl_parse_ip,      smp_fetch_url_param,      acl_match_ip,      ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_len",        acl_parse_int,     smp_fetch_url_param,      acl_match_len,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_reg",        acl_parse_reg,     smp_fetch_url_param,      acl_match_reg,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_sub",        acl_parse_str,     smp_fetch_url_param,      acl_match_sub,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
-	{ "urlp_val",        acl_parse_int,     smp_fetch_url_param_val,  acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG1(1,STR) },
+	{ "urlp",            acl_parse_str,     smp_fetch_url_param,      acl_match_str,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_beg",        acl_parse_str,     smp_fetch_url_param,      acl_match_beg,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_dir",        acl_parse_str,     smp_fetch_url_param,      acl_match_dir,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_dom",        acl_parse_str,     smp_fetch_url_param,      acl_match_dom,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_end",        acl_parse_str,     smp_fetch_url_param,      acl_match_end,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_ip",         acl_parse_ip,      smp_fetch_url_param,      acl_match_ip,      ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_len",        acl_parse_int,     smp_fetch_url_param,      acl_match_len,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_reg",        acl_parse_reg,     smp_fetch_url_param,      acl_match_reg,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_sub",        acl_parse_str,     smp_fetch_url_param,      acl_match_sub,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
+	{ "urlp_val",        acl_parse_int,     smp_fetch_url_param_val,  acl_match_int,     ACL_USE_L7REQ_VOLATILE, ARG2(1,STR,STR) },
 
 	{ NULL, NULL, NULL, NULL },
 }};
@@ -9599,18 +9629,57 @@
 /************************************************************************/
 /* Note: must not be declared <const> as its list will be overwritten */
 static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
-	{ "hdr",        smp_fetch_hdr,            ARG2(1,STR,SINT), val_hdr, SMP_T_CSTR, SMP_USE_HRQHV|SMP_USE_HRSHV },
-	{ "base",       smp_fetch_base,           0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
-	{ "base32",     smp_fetch_base32,         0,                NULL,    SMP_T_UINT, SMP_USE_HRQHV },
-	{ "base32+src", smp_fetch_base32_src,     0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
-	{ "path",       smp_fetch_path,           0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
-	{ "url",        smp_fetch_url,            0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
-	{ "url_ip",     smp_fetch_url_ip,         0,                NULL,    SMP_T_IPV4, SMP_USE_HRQHV },
-	{ "url_port",   smp_fetch_url_port,       0,                NULL,    SMP_T_UINT, SMP_USE_HRQHV },
-	{ "url_param",  smp_fetch_url_param,      ARG2(1,STR,STR),  NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
-	{ "cookie",     smp_fetch_cookie,         ARG1(1,STR),      NULL,    SMP_T_CSTR, SMP_USE_HRQHV|SMP_USE_HRSHV },
-	{ "set-cookie", smp_fetch_cookie,         ARG1(1,STR),      NULL,    SMP_T_CSTR, SMP_USE_HRSHV }, /* deprecated */
-	{ NULL, NULL, 0, 0, 0 },
+	{ "base",            smp_fetch_base,           0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
+	{ "base32",          smp_fetch_base32,         0,                NULL,    SMP_T_UINT, SMP_USE_HRQHV },
+	{ "base32+src",      smp_fetch_base32_src,     0,                NULL,    SMP_T_BIN,  SMP_USE_HRQHV },
+
+	/* cookie is valid in both directions (eg: for "stick ...") but cook*
+	 * are only here to match the ACL's name, are request-only and are used
+	 * for ACL compatibility only.
+	 */
+	{ "cook",            smp_fetch_cookie,         ARG1(0,STR),      NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
+	{ "cookie",          smp_fetch_cookie,         ARG1(0,STR),      NULL,    SMP_T_CSTR, SMP_USE_HRQHV|SMP_USE_HRSHV },
+	{ "cook_cnt",        smp_fetch_cookie_cnt,     ARG1(0,STR),      NULL,    SMP_T_UINT, SMP_USE_HRQHV },
+	{ "cook_val",        smp_fetch_cookie_val,     ARG1(0,STR),      NULL,    SMP_T_UINT, SMP_USE_HRQHV },
+
+	/* hdr is valid in both directions (eg: for "stick ...") but hdr_* are
+	 * only here to match the ACL's name, are request-only and are used for
+	 * ACL compatibility only.
+	 */
+	{ "hdr",             smp_fetch_hdr,            ARG2(0,STR,SINT), val_hdr, SMP_T_CSTR, SMP_USE_HRQHV|SMP_USE_HRSHV },
+	{ "hdr_cnt",         smp_fetch_hdr_cnt,        ARG1(0,STR),      NULL,    SMP_T_UINT, SMP_USE_HRQHV },
+	{ "hdr_ip",          smp_fetch_hdr_ip,         ARG2(0,STR,SINT), val_hdr, SMP_T_IPV4, SMP_USE_HRQHV },
+	{ "hdr_val",         smp_fetch_hdr_val,        ARG2(0,STR,SINT), val_hdr, SMP_T_UINT, SMP_USE_HRQHV },
+
+	{ "http_auth",       smp_fetch_http_auth,      ARG1(1,USR),      val_usr, SMP_T_BOOL, SMP_USE_HRQHV },
+	{ "http_auth_group", smp_fetch_http_auth_grp,  ARG1(1,USR),      val_usr, SMP_T_BOOL, SMP_USE_HRQHV },
+	{ "http_first_req",  smp_fetch_http_first_req, 0,                NULL,    SMP_T_BOOL, SMP_USE_HRQHP },
+	{ "method",          smp_fetch_meth,           0,                NULL,    SMP_T_UINT, SMP_USE_HRQHP },
+	{ "path",            smp_fetch_path,           0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
+	{ "req_proto_http",  smp_fetch_proto_http,     0,                NULL,    SMP_T_BOOL, SMP_USE_HRQHP },
+	{ "req_ver",         smp_fetch_rqver,          0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
+	{ "resp_ver",        smp_fetch_stver,          0,                NULL,    SMP_T_CSTR, SMP_USE_HRSHV },
+
+	/* scook is valid only on the response and is used for ACL compatibility */
+	{ "scook",           smp_fetch_cookie,         ARG1(0,STR),      NULL,    SMP_T_CSTR, SMP_USE_HRSHV },
+	{ "scook_cnt",       smp_fetch_cookie_cnt,     ARG1(0,STR),      NULL,    SMP_T_UINT, SMP_USE_HRSHV },
+	{ "scook_val",       smp_fetch_cookie_val,     ARG1(0,STR),      NULL,    SMP_T_UINT, SMP_USE_HRSHV },
+	{ "set-cookie",      smp_fetch_cookie,         ARG1(0,STR),      NULL,    SMP_T_CSTR, SMP_USE_HRSHV }, /* deprecated */
+
+	/* shdr is valid only on the response and is used for ACL compatibility */
+	{ "shdr",            smp_fetch_hdr,            ARG2(0,STR,SINT), val_hdr, SMP_T_CSTR, SMP_USE_HRSHV },
+	{ "shdr_cnt",        smp_fetch_hdr_cnt,        ARG1(0,STR),      NULL,    SMP_T_UINT, SMP_USE_HRSHV },
+	{ "shdr_ip",         smp_fetch_hdr_ip,         ARG2(0,STR,SINT), val_hdr, SMP_T_IPV4, SMP_USE_HRSHV },
+	{ "shdr_val",        smp_fetch_hdr_val,        ARG2(0,STR,SINT), val_hdr, SMP_T_UINT, SMP_USE_HRSHV },
+
+	{ "status",          smp_fetch_stcode,         0,                NULL,    SMP_T_UINT, SMP_USE_HRSHP },
+	{ "url",             smp_fetch_url,            0,                NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
+	{ "url_ip",          smp_fetch_url_ip,         0,                NULL,    SMP_T_IPV4, SMP_USE_HRQHV },
+	{ "url_port",        smp_fetch_url_port,       0,                NULL,    SMP_T_UINT, SMP_USE_HRQHV },
+	{ "url_param",       smp_fetch_url_param,      ARG2(1,STR,STR),  NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
+	{ "urlp"     ,       smp_fetch_url_param,      ARG2(1,STR,STR),  NULL,    SMP_T_CSTR, SMP_USE_HRQHV },
+	{ "urlp_val",        smp_fetch_url_param_val,  ARG2(1,STR,STR),  NULL,    SMP_T_UINT, SMP_USE_HRQHV },
+	{ /* END */ },
 }};