aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac18
-rw-r--r--src/variable.c139
-rw-r--r--tests/batchset.at6
3 files changed, 101 insertions, 62 deletions
diff --git a/configure.ac b/configure.ac
index 2fa32f6..f21fcfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -99,42 +99,24 @@ AC_ARG_WITH([vmoddir],
no) unset VMODDIR;;
*) AC_MSG_ERROR([argument to --with-vmoddir must be absolute pathname])
esac],[VMODDIR=`pkg-config --variable=vmoddir varnishapi`
if test -z "$VMODDIR"; then
AC_MSG_FAILURE([cannot determine vmod installation directory])
fi])
if test -z "$VMODDIR"; then
VMODDIR='$(libdir)/varnish/mods'
fi
-###########
-# Check for db.h and libdb
-#
-AC_CHECK_HEADER([db.h],,[AC_MSG_ERROR([Required header file db.h not found])])
-
-AC_CHECK_LIB(db, db_create,
- [LIBS="$LIBS -ldb"
- AC_RUN_IFELSE(
- [AC_LANG_PROGRAM([#include "db.h"],
- [int v_major, v_minor, v_patch;
- db_version(&v_major, &v_minor, &v_patch);
- return !(v_major == DB_VERSION_MAJOR
- && v_minor == DB_VERSION_MINOR
- && v_patch == DB_VERSION_PATCH);
- ])],
- [],
- [AC_MSG_ERROR([header file db.h is not the same version as libdb])])])
-
AC_CONFIG_COMMANDS([status],[
delim="-------------------------------------------------------------------"
echo ""
echo $delim
echo "Building for Varnish version $VARNISHVERSION"
echo $delim
],
[VARNISHVERSION=$VARNISHVERSION])
AC_CONFIG_TESTDIR(tests)
AC_CONFIG_FILES([tests/Makefile tests/atlocal])
AM_MISSING_PROG([AUTOM4TE], [autom4te])
diff --git a/src/variable.c b/src/variable.c
index 6403c1a..9442b6b 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -491,25 +491,26 @@ log_error(const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
vsyslog(LOG_DAEMON|LOG_NOTICE, fmt, ap);
va_end(ap);
}
#define S(s) ((s) ? (s) : "NULL")
struct vardef {
struct vardef *next;
enum variable_type type;
- char name[1];
+ char *name;
+ char *repl;
};
static void
vardef_free(struct vardef *v)
{
while (v) {
struct vardef *n = v->next;
free(v);
v = n;
}
}
@@ -561,24 +562,69 @@ str2duration(const char *str)
break;
case 'y':
r *= 60.*60.*24.*365.;
break;
default:
return 0.0;
}
while (*p && isspace(*p))
p++;
return *p ? 0 : r;
}
+char *
+bref_expand(const char *str, const char *input, pcre *re,
+ int ovsize, int *ovector)
+{
+ size_t rlen = 0;
+ char *rbase = NULL;
+ char *rptr;
+ int nm = 2*ovsize/3;
+ const char *p;
+
+ for (p = str; *p; ) {
+ if (*p == '\\' && strchr("123456789", p[1])) {
+ int n = 2*(p[1] - '0');
+ if (n < nm) {
+ rlen += ovector[n+1] - ovector[n];
+ p += 2;
+ continue;
+ }
+ }
+ ++p;
+ ++rlen;
+ }
+ rbase = malloc(rlen + 1);
+ AN(rbase);
+ p = str;
+ rptr = rbase;
+ while (*p) {
+ if (*p == '\\' && strchr("123456789", p[1])) {
+ int n = 2*(p[1] - '0');
+ if (n < nm) {
+ memcpy(rptr, input + ovector[n],
+ ovector[n+1] - ovector[n]);
+ rptr += ovector[n+1] - ovector[n];
+ p += 2;
+ continue;
+ }
+ }
+
+ *rptr++ = *p++;
+ }
+ *rptr = 0;
+
+ return rbase;
+}
+
VCL_VOID
vmod_batchset(VARIABLE_CTX ctx,
VCL_STRING vars, VCL_STRING rxs, VCL_STRING input)
{
struct symtab *vt = get_symtab(ctx);
struct vardef *head = NULL, *tail = NULL, *def;
size_t count = 0;
size_t n;
const char *v = vars;
const char *error_ptr;
int error_offset;
int cflags = 0;
@@ -589,68 +635,81 @@ vmod_batchset(VARIABLE_CTX ctx,
int *ovector;
int i;
int rc;
pcre *re;
if (!vars || !rxs || !input) {
log_error("variable.batchset: bad arguments: vars=%s, rxs=%s, input=%s",
S(vars), S(rxs), S(input));
return;
}
while (*v) {
- size_t n = strcspn(v, "=");
+ char const *nameptr = v;
+ size_t n = strcspn(v, ":=,");
+ size_t namelen;
+ char const *replptr;
+ size_t repllen;
+ char rbuf[3];
+ enum variable_type type;
+ int delim;
+
+ namelen = n;
- if (!v[n]) {
- log_error("variable.batchset: vars argument invalid near %s",
- v);
- vardef_free(head);
- return;
+ v += n;
+ delim = *v ? *v++ : 0;
+
+ if (delim == ':') {
+ n = strcspn(v, "=,");
+ type = str2type(v, n);
+ v += n;
+ delim = *v ? *v++ : 0;
+ } else
+ type = variable_string;
+
+ if (delim == '=') {
+ n = strcspn(v, ",");
+ replptr = v;
+ repllen = n;
+ v += n;
+ delim = *v ? *v++ : 0;
+ } else {
+ rbuf[0] = '\\';
+ rbuf[1] = count + '1';
+ rbuf[2] = 0;
+ replptr = rbuf;
+ repllen = 2;
}
- def = malloc(sizeof(def[0]) + n);
+
+ def = malloc(sizeof(def[0]) + namelen + repllen + 2);
def->next = NULL;
- memcpy(def->name, v, n);
- def->name[n] = 0;
if (tail)
tail->next = def;
else
head = def;
tail = def;
++count;
-
- v += n + 1;
- if (!*v) {
- log_error("variable.batchset: no type for %s", def->name);
- vardef_free(head);
- return;
- }
-
- n = strcspn(v, ",");
- def->type = str2type(v, n);
- if (def->type == variable_unset) {
- log_error("variable.batchset: invalid type for %s",
- def->name);
- vardef_free(head);
- return;
- }
-
- v += n;
- if (*v)
- ++v;
+ def->type = type;
+ def->name = (char*)(def + 1);
+ memcpy(def->name, nameptr, namelen);
+ def->name[namelen] = 0;
+ def->repl = def->name + namelen + 1;
+ memcpy(def->repl, replptr, repllen);
+ def->repl[repllen] = 0;
}
re = pcre_compile(rxs, cflags, &error_ptr, &error_offset, NULL);
if (!re) {
log_error("variable.batchset: %s: compilation failed near %s: %s",
- rxs, rxs + error_offset, error_ptr);
+ rxs, rxs + error_offset, error_ptr);
vardef_free(head);
return;
}
rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &n);
if (rc) {
log_error("pcre_fullinfo() failed: %d", rc);
vardef_free(head);
return;
}
if (n < count) {
@@ -664,70 +723,66 @@ vmod_batchset(VARIABLE_CTX ctx,
ovector = calloc(ovsize, sizeof(*ovector));
rc = pcre_exec(re, 0, input, strlen(input), 0, 0, ovector, ovsize);
if (rc <= 0) {
if (rc == 0)
log_error("matched, but too many substrings");
else
/*FIXME*/;
vardef_free(head);
return;
}
- for (def = head, i = 1; def; def = def->next, i++) {
- const char *s;
-
- rc = pcre_get_substring(input, ovector, ovsize, i, &s);
- if (rc < 0) {
- log_error("variable.batchset: %s(%s) can't get subexpr #%d: %d",
- rxs, input, i, rc);
- vardef_free(head);
- return;
- }
+ for (def = head; def; def = def->next, i++) {
+ char *s = bref_expand(def->repl, input, re, ovsize, ovector);
switch (def->type) {
case variable_string:
value.s = (char*)s;
break;
case variable_int:
errno = 0;
lval = strtol(s, &p, 10);
if (*p) {
log_error("variable.batchset: %s(%s)#%d: not an integer", rxs, input, i);
value.i = 0;
} else if (errno) {
log_error("variable.batchset: %s(%s)#%d: %s",
rxs, input, i, strerror(errno));
value.i = 0;
} else if (lval < INT_MIN || lval > INT_MAX) {
log_error("variable.batchset: %s(%s)#%d: value out of range",
rxs, input, i);
value.i = 0;
} else
value.i = lval;
+ free(s);
break;
case variable_real:
errno = 0;
value.r = strtod(s, &p);
if (*p) {
log_error("variable.batchset: %s(%s)#%d: not a valid number", rxs, input, i);
value.r = 0;
} else if (errno) {
log_error("variable.batchset: %s(%s)#%d: %s",
rxs, input, i, strerror(errno));
value.r = 0;
}
+ free(s);
break;
case variable_duration:
value.d = str2duration(s);
- break;
+ free(s);
+ break;
default:
abort();
}
defvar(vt, def->name, def->type, &value);
}
pcre_free(re);
free(ovector);
vardef_free(head);
}
+
diff --git a/tests/batchset.at b/tests/batchset.at
index be07cae..506fe78 100644
--- a/tests/batchset.at
+++ b/tests/batchset.at
@@ -10,28 +10,30 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with vmod-variable. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP(batchset)
AT_KEYWORDS(batchset)
AT_VARNISHTEST([
sub vcl_recv {
- variable.batchset("y=i,x=s", "^/(\d+)/(.+)", req.url);
+ variable.batchset("y:i,x,time:d=\3s", "^/(\d+)/(.+)/(\d+)", req.url);
}
sub vcl_deliver {
set resp.http.X-X = variable.get("x");
set resp.http.X-Y = variable.get_int("y");
+ set resp.http.X-Time = variable.get_duration("time");
}
],[
-txreq -url /10/test
+txreq -url /10/test/60
rxresp
expect resp.http.X-X == "test"
expect resp.http.X-Y == "10"
+expect resp.http.X-Time == "60.000"
])
AT_CLEANUP
\ No newline at end of file

Return to:

Send suggestions and report system problems to the System administrator.