From ecd17c64c9eea86af6126aae9d08583718c0795c Mon Sep 17 00:00:00 2001 From: phk Date: Wed, 24 Oct 2007 19:38:43 +0000 Subject: [PATCH] Add attribute parsing git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2169 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache_vrt_esi.c | 197 +++++++++++++++------ 1 file changed, 143 insertions(+), 54 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache_vrt_esi.c b/varnish-cache/bin/varnishd/cache_vrt_esi.c index 93f953b3..91e86b0a 100644 --- a/varnish-cache/bin/varnishd/cache_vrt_esi.c +++ b/varnish-cache/bin/varnishd/cache_vrt_esi.c @@ -41,6 +41,7 @@ */ #include +#include #include #include #include @@ -75,10 +76,63 @@ struct esi_work { }; /*-------------------------------------------------------------------- - * Add ESI bit to object + * Report a parsing error */ static void +esi_error(const struct esi_work *ew, const char *p, int i, const char *err) +{ + int ellipsis = 0; + char buf[256], *q; + txt t; + + if (i == 0) + i = p - ((char *)ew->st->ptr + ew->st->len); + if (i > 20) { + i = 20; + ellipsis = 1; + } + q = buf; + q += sprintf(buf, "at %zd: %s \"", + ew->off + (p - (char*)ew->st->ptr), err); + while (i > 0) { + if (*p >= ' ' && *p <= '~') { + *q++ = *p; + } else if (*p == '\n') { + *q++ = '\\'; + *q++ = 'n'; + } else if (*p == '\r') { + *q++ = '\\'; + *q++ = 'r'; + } else if (*p == '\t') { + *q++ = '\\'; + *q++ = 't'; + } else { + /* XXX: use %%%02x instead ? */ + q += sprintf(q, "\\x%02x", *p); + } + p++; + i--; + } + if (ellipsis) { + *q++ = '['; + *q++ = '.'; + *q++ = '.'; + *q++ = '.'; + *q++ = ']'; + } + *q++ = '"'; + *q++ = '\0'; + t.b = buf; + t.e = q; + WSPR(ew->sp, SLT_ESI_xmlerror, t); +} + +/*-------------------------------------------------------------------- + * Add ESI bit to object + */ + +static struct esi_bit * esi_addbit(struct esi_work *ew) { @@ -99,6 +153,7 @@ printf("ADD %p->%p\n", ew->sp->obj, ew->eb); ew->eb->verbatim = ew->dst; sprintf(ew->eb->chunk_length, "%x\r\n", Tlen(ew->dst)); VSL(SLT_Debug, ew->sp->fd, "AddBit: %.*s", Tlen(ew->dst), ew->dst.b); + return(ew->eb); } @@ -116,69 +171,101 @@ esi_addverbatim(struct esi_work *ew, txt t) } /*-------------------------------------------------------------------- - * Add one piece to the output, either verbatim or include + * Tease the next attribute and value out of an XML element. + * + * XXX: is the syntax correct ? */ -static void -esi_addinclude(struct esi_work *ew, txt t) +static int +esi_attrib(const struct esi_work *ew, txt *in, txt *attrib, txt *val) { - VSL(SLT_Debug, 0, "Incl \"%.*s\"", t.e - t.b, t.b); - esi_addbit(ew); - ew->eb->include = t; + /* Skip leading blanks */ + while(in->b < in->e && isspace(*in->b)) + in->b++; + + /* Nothing found */ + if (in->b >= in->e) + return (0); + + if (!isalpha(*in->b)) { + /* XXX error */ + esi_error(ew, in->b, 1, "XML 1.0 Illegal attribute character"); + return (-1); + } + + /* Attribute name until '=' or space */ + *attrib = *in; + while(in->b < in->e && *in->b != '=' && !isspace(*in->b)) { + if (!isalnum(*in->b)) { + esi_error(ew, attrib->b, 1 + (in->b - attrib->b), + "XML 1.0 Illegal attribute character"); + return (-1); + } + in->b++; + } + attrib->e = in->b; + + if (in->b >= in->e || isspace(*in->b)) { + /* Attribute without value */ + val->b = val->e = in->b; + return (1); + } + + /* skip '=' */ + in->b++; + + /* Value, if any ? */ + *val = *in; + if (in->b >= in->e) + return (1); + + if (*in->b == '"') { + /* Skip quote */ + in->b++; + val->b++; + + /* Anything goes, until next quote */ + while(in->b < in->e && *in->b != '"') + in->b++; + val->e = in->b; + + if (in->b >= in->e) { + esi_error(ew, val->b, in->e - val->b, + "XML 1.0 missing ending quote"); + return (-1); + } + + /* Skip quote */ + in->b++; + } else { + /* Anything until whitespace */ + while(in->b < in->e && !isspace(*in->b)) + in->b++; + val->e = in->b; + } + return (1); } /*-------------------------------------------------------------------- - * Report a parsing error + * Add one piece to the output, either verbatim or include */ static void -esi_error(const struct esi_work *ew, const char *p, int i, const char *err) +esi_addinclude(struct esi_work *ew, txt t) { - int ellipsis = 0; - char buf[256], *q; - txt t; - - if (i == 0) - i = p - ((char *)ew->st->ptr + ew->st->len); - if (i > 20) { - i = 20; - ellipsis = 1; - } - q = buf; - q += sprintf(buf, "at %zd: %s \"", - ew->off + (p - (char*)ew->st->ptr), err); - while (i > 0) { - if (*p >= ' ' && *p <= '~') { - *q++ = *p; - } else if (*p == '\n') { - *q++ = '\\'; - *q++ = 'n'; - } else if (*p == '\r') { - *q++ = '\\'; - *q++ = 'r'; - } else if (*p == '\t') { - *q++ = '\\'; - *q++ = 't'; - } else { - /* XXX: use %%%02x instead ? */ - q += sprintf(q, "\\x%02x", *p); - } - p++; - i--; - } - if (ellipsis) { - *q++ = '['; - *q++ = '.'; - *q++ = '.'; - *q++ = '.'; - *q++ = ']'; + struct esi_bit *eb; + txt tag; + txt cont; + + eb = esi_addbit(ew); + while (esi_attrib(ew, &t, &tag, &cont) == 1) { + VSL(SLT_Debug, 0, "<%.*s> -> <%.*s>", + tag.e - tag.b, tag.b, + cont.e - cont.b, cont.b); } - *q++ = '"'; - *q++ = '\0'; - t.b = buf; - t.e = q; - WSPR(ew->sp, SLT_ESI_xmlerror, t); + eb->include = t; + VSL(SLT_Debug, 0, "Incl \"%.*s\"", t.e - t.b, t.b); } /*-------------------------------------------------------------------- @@ -366,12 +453,14 @@ esi_parse(struct esi_work *ew) if (celem == 0) { o.b = r + 11; - o.e = q; - esi_addinclude(ew, o); if (q[-1] != '/') { esi_error(ew, p, 1 + q - p, "ESI 1.0 wants emtpy esi:include"); + o.e = q; + } else { + o.e = q - 1; } + esi_addinclude(ew, o); ew->dst.b = q + 1; ew->dst.e = q + 1; } else { -- 2.39.5