]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] ACL regex matching on the URI ; uri_reg
authorWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 20:45:09 +0000 (22:45 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2007 21:24:51 +0000 (23:24 +0200)
The URI can be matched on regexen now. The upcase/lowcase flag
can not be set yet and will soon have to.

include/proto/acl.h
src/acl.c
src/proto_http.c

index 86cbe74ff5a3bad0bbc9829865ceeb61a36f9127..ace72dd9095380096ec298c4158101ad0cc584f5 100644 (file)
@@ -118,6 +118,9 @@ int acl_parse_range(const char *text, struct acl_pattern *pattern);
 /* Parse a string. It is allocated and duplicated. */
 int acl_parse_str(const char *text, struct acl_pattern *pattern);
 
+/* Parse a regex. It is allocated. */
+int acl_parse_reg(const char *text, struct acl_pattern *pattern);
+
 /* Parse an IP address and an optional mask in the form addr[/mask].
  * The addr may either be an IPv4 address or a hostname. The mask
  * may either be a dotted mask or a number of bits. Returns 1 if OK,
@@ -149,6 +152,13 @@ int acl_match_dom(struct acl_test *test, struct acl_pattern *pattern);
 /* Check that the IPv4 address in <test> matches the IP/mask in pattern */
 int acl_match_ip(struct acl_test *test, struct acl_pattern *pattern);
 
+/* Executes a regex. It needs to change the data. If it is marked READ_ONLY
+ * then it will be allocated and duplicated in place so that others may use
+ * it later on. Note that this is embarrassing because we always try to avoid
+ * allocating memory at run time.
+ */
+int acl_match_reg(struct acl_test *test, struct acl_pattern *pattern);
+
 #endif /* _PROTO_ACL_H */
 
 /*
index e5d7594ea769f036f18e4420353b45fb4331c7e2..1dce3ea3f7e64df30a7dd671fef59382193aa1fe 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -47,6 +47,44 @@ int acl_match_str(struct acl_test *test, struct acl_pattern *pattern)
        return 0;
 }
 
+/* Executes a regex. It needs to change the data. If it is marked READ_ONLY
+ * then it will be allocated and duplicated in place so that others may use
+ * it later on. Note that this is embarrassing because we always try to avoid
+ * allocating memory at run time.
+ */
+int acl_match_reg(struct acl_test *test, struct acl_pattern *pattern)
+{
+       char old_char;
+       int ret;
+
+       if (unlikely(test->flags & ACL_TEST_F_READ_ONLY)) {
+               char *new_str;
+
+               new_str = calloc(1, test->len + 1);
+               if (!new_str)
+                       return 0;
+
+               memcpy(new_str, test->ptr, test->len);
+               new_str[test->len] = 0;
+               if (test->flags & ACL_TEST_F_MUST_FREE)
+                       free(test->ptr);
+               test->ptr = new_str;
+               test->flags |= ACL_TEST_F_MUST_FREE;
+               test->flags &= ~ACL_TEST_F_READ_ONLY;
+       }
+
+       old_char = test->ptr[test->len];
+       test->ptr[test->len] = 0;
+
+       if (regexec(pattern->ptr.reg, test->ptr, 0, NULL, 0) == 0)
+               ret = 1;
+       else
+               ret = 0;
+
+       test->ptr[test->len] = old_char;
+       return ret;
+}
+
 /* Checks that the pattern matches the beginning of the tested string. */
 int acl_match_beg(struct acl_test *test, struct acl_pattern *pattern)
 {
@@ -199,6 +237,25 @@ int acl_parse_str(const char *text, struct acl_pattern *pattern)
        return 1;
 }
 
+/* Parse a regex. It is allocated. */
+int acl_parse_reg(const char *text, struct acl_pattern *pattern)
+{
+       regex_t *preg;
+
+       preg = calloc(1, sizeof(regex_t));
+
+       if (!preg)
+               return 0;
+
+       if (regcomp(preg, text, REG_EXTENDED | REG_NOSUB) != 0) {
+               free(preg);
+               return 0;
+       }
+
+       pattern->ptr.reg = preg;
+       return 1;
+}
+
 /* Parse an integer. It is put both in min and max. */
 int acl_parse_int(const char *text, struct acl_pattern *pattern)
 {
index 6d4c152801c063c5af2d109f11a88f621a548093..9506b167eb98fea897acc281635cd1eb3cbd254f 100644 (file)
@@ -5276,7 +5276,8 @@ static int acl_fetch_url(struct proxy *px, struct session *l4, void *l7, void *a
        test->len = txn->req.sl.rq.u_l;
        test->ptr = txn->req.sol + txn->req.sl.rq.u;
 
-       test->flags = ACL_TEST_F_READ_ONLY | ACL_TEST_F_VOL_1ST;
+       /* we do not need to set READ_ONLY because the data is in a buffer */
+       test->flags = ACL_TEST_F_VOL_1ST;
        return 1;
 }
 
@@ -5299,10 +5300,11 @@ static struct acl_kw_list acl_kws = {{ },{
        { "url_sub",    acl_parse_str,   acl_fetch_url,    acl_match_sub   },
        { "url_dir",    acl_parse_str,   acl_fetch_url,    acl_match_dir   },
        { "url_dom",    acl_parse_str,   acl_fetch_url,    acl_match_dom   },
-       { NULL, NULL, NULL, NULL },
-#if 0
        { "url_reg",    acl_parse_reg,   acl_fetch_url,    acl_match_reg   },
 
+       { NULL, NULL, NULL, NULL },
+
+#if 0
        { "line",       acl_parse_str,   acl_fetch_line,   acl_match_str   },
        { "line_reg",   acl_parse_reg,   acl_fetch_line,   acl_match_reg   },
        { "line_beg",   acl_parse_str,   acl_fetch_line,   acl_match_beg   },