From: Jerome Magnin Date: Sun, 16 Feb 2020 18:20:19 +0000 (+0100) Subject: MINOR: sample: regsub now supports backreferences X-Git-Tag: v2.2-dev3~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=07e1e3c93e;p=thirdparty%2Fhaproxy.git MINOR: sample: regsub now supports backreferences Now that the configuration parser is more flexible with samples, converters and their arguments, we can leverage this to enable support for backreferences in regsub. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 392742eea3..306d6396a6 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -14161,6 +14161,11 @@ regsub(,[,]) # copy query string to x-query and drop all leading '?', ';' and '&' http-request set-header x-query "%[query,regsub([?;&]*,'')]" + # capture groups and backreferences + # both lines do the same. + http-request redirect location %[url,'regsub("(foo|bar)([0-9]+)?","\2\1",i)]' + http-request redirect location %[url,regsub(\"(foo|bar)([0-9]+)?\",\"\2\1\",i)] + capture-req() Capture the string entry in the request slot and returns the entry as is. If the slot doesn't exist, the capture fails silently. diff --git a/src/sample.c b/src/sample.c index ef0f7b00cb..24d21100e0 100644 --- a/src/sample.c +++ b/src/sample.c @@ -2354,6 +2354,7 @@ static int sample_conv_regsub(const struct arg *arg_p, struct sample *smp, void struct my_regex *reg = arg_p[0].data.reg; regmatch_t pmatch[MAX_MATCH]; struct buffer *trash = get_trash_chunk(); + struct buffer *output; int flag, max; int found; @@ -2386,16 +2387,21 @@ static int sample_conv_regsub(const struct arg *arg_p, struct sample *smp, void if (!found) break; + output = alloc_trash_chunk(); + output->data = exp_replace(output->area, output->size, start, arg_p[1].data.str.area, pmatch); + /* replace the matching part */ - max = trash->size - trash->data; + max = output->size - output->data; if (max) { - if (max > arg_p[1].data.str.data) - max = arg_p[1].data.str.data; + if (max > output->data) + max = output->data; memcpy(trash->area + trash->data, - arg_p[1].data.str.area, max); + output->area, max); trash->data += max; } + free_trash_chunk(output); + /* stop here if we're done with this string */ if (start >= end) break;