[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