]> err.no Git - varnish/commitdiff
Add attribute parsing
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 24 Oct 2007 19:38:43 +0000 (19:38 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 24 Oct 2007 19:38:43 +0000 (19:38 +0000)
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

index 93f953b3c08bf1eeac1ccff50e10fd61d07b77de..91e86b0aa9cf2a6a63e5c77e09d0ddddcb416e39 100644 (file)
@@ -41,6 +41,7 @@
  */
 
 #include <stdio.h>
+#include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -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 {