[MEDIUM] acl: support maching on 'path' component

'path', 'path_reg', 'path_beg', 'path_end', 'path_sub', 'path_dir'
and 'path_dom' have been implemented to process the path component
of the URI. It starts after the host part, and stops before the
question mark.
diff --git a/src/proto_http.c b/src/proto_http.c
index 13ee746..84aa91a 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5457,7 +5457,65 @@
 	return 0;
 }
 
+/* 8. Check on URI PATH. A pointer to the PATH is stored. The path starts at
+ * the first '/' after the possible hostname, and ends before the possible '?'.
+ */
+static int
+acl_fetch_path(struct proxy *px, struct session *l4, void *l7, int dir,
+               struct acl_expr *expr, struct acl_test *test)
+{
+	struct http_txn *txn = l7;
+	char *ptr, *end;
 
+	ptr = txn->req.sol + txn->req.sl.rq.u;
+	end = ptr + txn->req.sl.rq.u_l;
+
+	if (ptr >= end)
+		return 0;
+
+	/* RFC2616, par. 5.1.2 :
+	 * Request-URI = "*" | absuri | abspath | authority
+	 */
+
+	if (*ptr == '*')
+		return 0;
+
+	if (isalpha(*ptr)) {
+		/* this is a scheme as described by RFC3986, par. 3.1 */
+		ptr++;
+		while (ptr < end &&
+		       (isalnum(*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.'))
+			ptr++;
+		/* skip '://' */
+		if (ptr == end || *ptr++ != ':')
+			return 0;
+		if (ptr == end || *ptr++ != '/')
+			return 0;
+		if (ptr == end || *ptr++ != '/')
+			return 0;
+	}
+	/* skip [user[:passwd]@]host[:[port]] */
+
+	while (ptr < end && *ptr != '/')
+		ptr++;
+
+	if (ptr == end)
+		return 0;
+
+	/* OK, we got the '/' ! */
+	test->ptr = ptr;
+
+	while (ptr < end && *ptr != '?')
+		ptr++;
+
+	test->len = ptr - test->ptr;
+
+	/* we do not need to set READ_ONLY because the data is in a buffer */
+	test->flags = ACL_TEST_F_VOL_1ST;
+	return 1;
+}
+
+
 
 /************************************************************************/
 /*             All supported keywords must be declared here.            */
@@ -5487,6 +5545,15 @@
 	{ "hdr_dom",    acl_parse_str,   acl_fetch_hdr,     acl_match_dom },
 	{ "hdr_cnt",    acl_parse_int,   acl_fetch_hdr_cnt, acl_match_int },
 	{ "hdr_val",    acl_parse_int,   acl_fetch_hdr_val, acl_match_int },
+
+	{ "path",       acl_parse_str,   acl_fetch_path,   acl_match_str  },
+	{ "path_reg",   acl_parse_reg,   acl_fetch_path,   acl_match_reg  },
+	{ "path_beg",   acl_parse_str,   acl_fetch_path,   acl_match_beg  },
+	{ "path_end",   acl_parse_str,   acl_fetch_path,   acl_match_end  },
+	{ "path_sub",   acl_parse_str,   acl_fetch_path,   acl_match_sub  },
+	{ "path_dir",   acl_parse_str,   acl_fetch_path,   acl_match_dir  },
+	{ "path_dom",   acl_parse_str,   acl_fetch_path,   acl_match_dom  },
+
 	{ NULL, NULL, NULL, NULL },
 
 #if 0
@@ -5498,14 +5565,6 @@
 	{ "line_dir",   acl_parse_str,   acl_fetch_line,   acl_match_dir   },
 	{ "line_dom",   acl_parse_str,   acl_fetch_line,   acl_match_dom   },
 
-	{ "path",       acl_parse_str,   acl_fetch_path,   acl_match_str   },
-	{ "path_reg",   acl_parse_reg,   acl_fetch_path,   acl_match_reg   },
-	{ "path_beg",   acl_parse_str,   acl_fetch_path,   acl_match_beg   },
-	{ "path_end",   acl_parse_str,   acl_fetch_path,   acl_match_end   },
-	{ "path_sub",   acl_parse_str,   acl_fetch_path,   acl_match_sub   },
-	{ "path_dir",   acl_parse_str,   acl_fetch_path,   acl_match_dir   },
-	{ "path_dom",   acl_parse_str,   acl_fetch_path,   acl_match_dom   },
-
 	{ "cook",       acl_parse_str,   acl_fetch_cook,   acl_match_str   },
 	{ "cook_reg",   acl_parse_reg,   acl_fetch_cook,   acl_match_reg   },
 	{ "cook_beg",   acl_parse_str,   acl_fetch_cook,   acl_match_beg   },