[master] b2a04a0 Add support for caseless string comparison and regular expression evaluation.
Martin Blix Grydeland
martin at varnish-cache.org
Thu Oct 10 16:48:39 CEST 2013
commit b2a04a0aa6b738bf6e879e92f444b02016f6b14e
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date: Thu Oct 10 14:17:06 2013 +0200
Add support for caseless string comparison and regular expression
evaluation.
diff --git a/bin/varnishlog/varnishlog_options.h b/bin/varnishlog/varnishlog_options.h
index 4ca0dd5..f03b2ce 100644
--- a/bin/varnishlog/varnishlog_options.h
+++ b/bin/varnishlog/varnishlog_options.h
@@ -33,6 +33,7 @@
VUT_OPT_a
VSL_OPT_b
VSL_OPT_c
+VSL_OPT_C
VUT_OPT_d
VUT_OPT_D
VUT_OPT_g
diff --git a/doc/sphinx/reference/varnishlog.rst b/doc/sphinx/reference/varnishlog.rst
index 0127d3d..50329e1 100644
--- a/doc/sphinx/reference/varnishlog.rst
+++ b/doc/sphinx/reference/varnishlog.rst
@@ -29,12 +29,6 @@ The following options are available:
.. include:: ../../../bin/varnishlog/varnishlog_options.rst
--C
-
- Ignore case when matching regular expressions.
-
- XXX: Not yet implemented
-
-k num
Only show the first num log transactions (or log records
diff --git a/include/vapi/vapi_options.h b/include/vapi/vapi_options.h
index e2ddcfa..c3cbaa6 100644
--- a/include/vapi/vapi_options.h
+++ b/include/vapi/vapi_options.h
@@ -45,6 +45,11 @@
" client communication." \
)
+#define VSL_OPT_C \
+ VOPT("C", "[-C]", "Caseless regular expressions", \
+ "Do all regular expression and string matching caseless." \
+ )
+
#define VSL_OPT_i \
VOPT("i:", "[-i taglist]", "Include tags", \
"Include log records of these tags in output. Taglist is" \
diff --git a/lib/libvarnishapi/vsl_api.h b/lib/libvarnishapi/vsl_api.h
index 782fed8..c7996a9 100644
--- a/lib/libvarnishapi/vsl_api.h
+++ b/lib/libvarnishapi/vsl_api.h
@@ -87,6 +87,7 @@ struct VSL_data {
int b_opt;
int c_opt;
+ int C_opt;
int L_opt;
double T_opt;
int v_opt;
diff --git a/lib/libvarnishapi/vsl_arg.c b/lib/libvarnishapi/vsl_arg.c
index 9370ed9..eb0eda1 100644
--- a/lib/libvarnishapi/vsl_arg.c
+++ b/lib/libvarnishapi/vsl_arg.c
@@ -286,7 +286,7 @@ vsl_IX_arg(struct VSL_data *vsl, int opt, const char *arg)
b = e + 1;
}
- vre = VRE_compile(b, 0, &err, &off);
+ vre = VRE_compile(b, vsl->C_opt ? VRE_CASELESS : 0, &err, &off);
if (vre == NULL) {
if (tags)
vbit_destroy(tags);
@@ -326,6 +326,10 @@ VSL_Arg(struct VSL_data *vsl, int opt, const char *arg)
switch (opt) {
case 'b': vsl->b_opt = 1; return (1);
case 'c': vsl->c_opt = 1; return (1);
+ case 'C':
+ /* Caseless regular expressions */
+ vsl->C_opt = 1;
+ return (1);
case 'i': case 'x': return (vsl_ix_arg(vsl, opt, arg));
case 'I': case 'X': return (vsl_IX_arg(vsl, opt, arg));
case 'L':
diff --git a/lib/libvarnishapi/vsl_query.c b/lib/libvarnishapi/vsl_query.c
index 6ec44b4..ba8b173 100644
--- a/lib/libvarnishapi/vsl_query.c
+++ b/lib/libvarnishapi/vsl_query.c
@@ -168,15 +168,27 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
VSLQ_TEST_NUMOP(rhs->type, lhs, >=, rhs->val);
case T_SEQ: /* eq */
assert(rhs->type == VEX_STRING);
- if (e - b == rhs->val_stringlen &&
- !strncmp(b, rhs->val_string, e - b))
- return (1);
- return (0);
+ if (e - b != rhs->val_stringlen)
+ return (0);
+ if (vex->options & VEX_OPT_CASELESS) {
+ if (strncasecmp(b, rhs->val_string, e - b))
+ return (0);
+ } else {
+ if (strncmp(b, rhs->val_string, e - b))
+ return (0);
+ }
+ return (1);
case T_SNEQ: /* ne */
assert(rhs->type == VEX_STRING);
- if (e - b != rhs->val_stringlen ||
- strncmp(b, rhs->val_string, e - b))
+ if (e - b != rhs->val_stringlen)
return (1);
+ if (vex->options & VEX_OPT_CASELESS) {
+ if (strncasecmp(b, rhs->val_string, e - b))
+ return (1);
+ } else {
+ if (strncmp(b, rhs->val_string, e - b))
+ return (1);
+ }
return (0);
case '~': /* ~ */
assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
@@ -294,7 +306,7 @@ vslq_newquery(struct VSL_data *vsl, enum VSL_grouping_e grouping,
vsb = VSB_new_auto();
AN(vsb);
- vex = vex_New(querystring, vsb);
+ vex = vex_New(querystring, vsb, vsl->C_opt ? VEX_OPT_CASELESS : 0);
AZ(VSB_finish(vsb));
if (vex == NULL)
vsl_diag(vsl, "%s", VSB_data(vsb));
diff --git a/lib/libvarnishapi/vxp.c b/lib/libvarnishapi/vxp.c
index fffa550..75a7614 100644
--- a/lib/libvarnishapi/vxp.c
+++ b/lib/libvarnishapi/vxp.c
@@ -195,7 +195,7 @@ vxp_Delete(struct vxp **pvxp)
}
struct vex *
-vex_New(const char *query, struct vsb *sb)
+vex_New(const char *query, struct vsb *sb, unsigned options)
{
struct vxp *vxp;
struct vex *vex;
@@ -205,6 +205,9 @@ vex_New(const char *query, struct vsb *sb)
vxp = vxp_New(sb);
vxp->b = query;
vxp->e = query + strlen(query);
+ vxp->vex_options = options;
+ if (options & VEX_OPT_CASELESS)
+ vxp->vre_options |= VRE_CASELESS;
vxp_Lexer(vxp);
diff --git a/lib/libvarnishapi/vxp.h b/lib/libvarnishapi/vxp.h
index 20df7ed..1e773a5 100644
--- a/lib/libvarnishapi/vxp.h
+++ b/lib/libvarnishapi/vxp.h
@@ -70,6 +70,9 @@ struct vxp {
VTAILQ_HEAD(, membit) membits;
struct token *t;
+ unsigned vex_options;
+ int vre_options;
+
struct vsb *sb;
int err;
};
@@ -115,6 +118,7 @@ struct vex {
unsigned magic;
#define VEX_MAGIC 0xC7DB792D
unsigned tok;
+ unsigned options;
struct vex *a, *b;
struct vex_lhs *lhs;
struct vex_rhs *rhs;
@@ -137,8 +141,8 @@ void vxp_Lexer(struct vxp *vxp);
struct vex * vxp_Parse(struct vxp *vxp);
/* API internal interface */
-
-struct vex * vex_New(const char *query, struct vsb *sb);
+#define VEX_OPT_CASELESS (1 << 0)
+struct vex * vex_New(const char *query, struct vsb *sb, unsigned options);
void vex_Free(struct vex **pvex);
/* Debug routines */
diff --git a/lib/libvarnishapi/vxp_parse.c b/lib/libvarnishapi/vxp_parse.c
index 99a7999..01f5272 100644
--- a/lib/libvarnishapi/vxp_parse.c
+++ b/lib/libvarnishapi/vxp_parse.c
@@ -49,6 +49,17 @@
static void vxp_expr_or(struct vxp *vxp, struct vex **pvex);
+static struct vex *
+vex_alloc(struct vxp *vxp)
+{
+ struct vex *vex;
+
+ ALLOC_OBJ(vex, VEX_MAGIC);
+ AN(vex);
+ vex->options = vxp->vex_options;
+ return (vex);
+}
+
static void
vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
{
@@ -244,7 +255,8 @@ vxp_expr_regex(struct vxp *vxp, struct vex_rhs **prhs)
AN(*prhs);
(*prhs)->type = VEX_REGEX;
(*prhs)->val_string = strdup(vxp->t->dec);
- (*prhs)->val_regex = VRE_compile(vxp->t->dec, 0, &errptr, &erroff);
+ (*prhs)->val_regex = VRE_compile(vxp->t->dec, vxp->vre_options,
+ &errptr, &erroff);
if ((*prhs)->val_regex == NULL) {
AN(errptr);
VSB_printf(vxp->sb, "Regular expression error: %s ", errptr);
@@ -267,7 +279,7 @@ vxp_expr_cmp(struct vxp *vxp, struct vex **pvex)
AN(pvex);
AZ(*pvex);
- ALLOC_OBJ(*pvex, VEX_MAGIC);
+ *pvex = vex_alloc(vxp);
AN(*pvex);
vxp_expr_lhs(vxp, &(*pvex)->lhs);
ERRCHK(vxp);
@@ -373,7 +385,7 @@ vxp_expr_not(struct vxp *vxp, struct vex **pvex)
AZ(*pvex);
if (vxp->t->tok == T_NOT) {
- ALLOC_OBJ(*pvex, VEX_MAGIC);
+ *pvex = vex_alloc(vxp);
AN(*pvex);
(*pvex)->tok = vxp->t->tok;
vxp_NextToken(vxp);
@@ -402,7 +414,7 @@ vxp_expr_and(struct vxp *vxp, struct vex **pvex)
ERRCHK(vxp);
while (vxp->t->tok == T_AND) {
a = *pvex;
- ALLOC_OBJ(*pvex, VEX_MAGIC);
+ *pvex = vex_alloc(vxp);
AN(*pvex);
(*pvex)->tok = vxp->t->tok;
(*pvex)->a = a;
@@ -430,7 +442,7 @@ vxp_expr_or(struct vxp *vxp, struct vex **pvex)
ERRCHK(vxp);
while (vxp->t->tok == T_OR) {
a = *pvex;
- ALLOC_OBJ(*pvex, VEX_MAGIC);
+ *pvex = vex_alloc(vxp);
AN(*pvex);
(*pvex)->tok = vxp->t->tok;
(*pvex)->a = a;
More information about the varnish-commit
mailing list