]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: args: implement a new arg type for regex : ARGT_REG
authorWilly Tarreau <w@1wt.eu>
Mon, 19 Jan 2015 18:00:58 +0000 (19:00 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 22 Jan 2015 13:24:53 +0000 (14:24 +0100)
This one will be used when a regex is expected. It is automatically
resolved after the parsing and compiled into a regex. Some optional
flags are supported in the type-specific flags that should be set by
the optional arg checker. One is used during the regex compilation :
ARGF_REG_ICASE to ignore case.

include/types/arg.h
src/arg.c
src/haproxy.c
src/sample.c

index f429b8296d9e59cb31777ca8f3656a53aad31a76..c62102578329d67e74951d4a4c6ed3ba8473d583 100644 (file)
@@ -57,6 +57,7 @@ enum {
        ARGT_SRV,      /* a pointer to a server */
        ARGT_USR,      /* a pointer to a user list */
        ARGT_MAP,      /* a pointer to a map descriptor */
+       ARGT_REG,      /* a pointer to a regex */
 };
 
 /* context where arguments are used, in order to help error reporting */
@@ -72,10 +73,15 @@ enum {
        ARGC_CAP,      /* capture rule */
 };
 
+/* flags used when compiling and executing regex */
+#define ARGF_REG_ICASE 1
+#define ARGF_REG_GLOB  2
+
 /* some types that are externally defined */
 struct proxy;
 struct server;
 struct userlist;
+struct my_regex;
 
 union arg_data {
        unsigned int uint; /* used for uint, time, size */
@@ -87,6 +93,7 @@ union arg_data {
        struct server *srv;
        struct userlist *usr;
        struct map_descriptor *map;
+       struct my_regex *reg;
 };
 
 struct arg {
index a0717380a097dc3f27c68e0df3bbccc9559c8c4a..e609ac5f57a9fafd81f968d3ba83a2dcbf386a5e 100644 (file)
--- a/src/arg.c
+++ b/src/arg.c
@@ -34,6 +34,7 @@ static const char *arg_type_names[ARGT_NBTYPES] = {
        [ARGT_SRV]  = "server",
        [ARGT_USR]  = "user list",
        [ARGT_MAP]  = "map",
+       [ARGT_REG]  = "regex",
        /* Unassigned types must never happen. Better crash during parsing if they do. */
 };
 
@@ -173,6 +174,7 @@ int make_arg_list(const char *in, int len, unsigned int mask, struct arg **argp,
                case ARGT_TAB:
                case ARGT_SRV:
                case ARGT_USR:
+               case ARGT_REG:
                        /* These argument types need to be stored as strings during
                         * parsing then resolved later.
                         */
index 31447bf0827b62a94dab8b285a7d4aba15a9b141..60a0ca26acfdd5ad6112cc3285ba90b236e0b11b 100644 (file)
@@ -1086,6 +1086,13 @@ static void deinit_sample_arg(struct arg *p)
                        p->data.str.str = NULL;
                        p->unresolved = 0;
                }
+               else if (p->type == ARGT_REG) {
+                       if (p->data.reg) {
+                               regex_free(p->data.reg);
+                               free(p->data.reg);
+                               p->data.reg = NULL;
+                       }
+               }
                p++;
        }
 
index 377c4c8f3f07bacf3b2ef90130845d1d2d9edfad..8fe341f3990df75b818b00e56661db290f6b227b 100644 (file)
@@ -983,13 +983,16 @@ int smp_resolve_args(struct proxy *p)
        const char *ctx, *where;
        const char *conv_ctx, *conv_pre, *conv_pos;
        struct userlist *ul;
+       struct my_regex *reg;
        struct arg *arg;
        int cfgerr = 0;
+       int rflags;
 
        list_for_each_entry_safe(cur, bak, &p->conf.args.list, list) {
                struct proxy *px;
                struct server *srv;
                char *pname, *sname;
+               char *err;
 
                arg = cur->arg;
 
@@ -1004,7 +1007,7 @@ int smp_resolve_args(struct proxy *p)
                where = "in";
                ctx = "sample fetch keyword";
                switch (cur->ctx) {
-               case ARGC_STK:where = "in stick rule in"; break;
+               case ARGC_STK: where = "in stick rule in"; break;
                case ARGC_TRK: where = "in tracking rule in"; break;
                case ARGC_LOG: where = "in log-format string in"; break;
                case ARGC_HRQ: where = "in http-request header format string in"; break;
@@ -1175,6 +1178,45 @@ int smp_resolve_args(struct proxy *p)
                        arg->unresolved = 0;
                        arg->data.usr = ul;
                        break;
+
+               case ARGT_REG:
+                       if (!arg->data.str.len) {
+                               Alert("parsing [%s:%d] : missing regex in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
+                                     cur->file, cur->line,
+                                     cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
+                               cfgerr++;
+                               continue;
+                       }
+
+                       reg = calloc(1, sizeof(*reg));
+                       if (!reg) {
+                               Alert("parsing [%s:%d] : not enough memory to build regex in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
+                                     cur->file, cur->line,
+                                     cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
+                               cfgerr++;
+                               continue;
+                       }
+
+                       rflags = 0;
+                       rflags |= (arg->type_flags & ARGF_REG_ICASE) ? REG_ICASE : 0;
+                       err = NULL;
+
+                       if (!regex_comp(arg->data.str.str, reg, rflags, 1 /* capture substr */, &err)) {
+                               Alert("parsing [%s:%d] : error in regex '%s' in arg %d of %s%s%s%s '%s' %s proxy '%s' : %s.\n",
+                                     cur->file, cur->line,
+                                     arg->data.str.str,
+                                     cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id, err);
+                               cfgerr++;
+                               continue;
+                       }
+
+                       free(arg->data.str.str);
+                       arg->data.str.str = NULL;
+                       arg->unresolved = 0;
+                       arg->data.reg = reg;
+                       break;
+
+
                }
 
                LIST_DEL(&cur->list);