source: bin/varnishd/cache_esi_parse.c @ ea6090

Revision ea6090, 19.9 KB checked in by Poul-Henning Kamp <phk@…>, 3 years ago (diff)

Munge the esi:include src attribute as required, to produce URL and
Host: header.

Correctly unpack Host: header in esi delivery.

Now e00008.vtc is the first case to fail.

git-svn-id:  http://www.varnish-cache.org/svn/trunk/varnish-cache@5730 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2011 Varnish Software AS
3 * All rights reserved.
4 *
5 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 */
29
30#include "config.h"
31
32#include "svnid.h"
33SVNID("$Id")
34
35#include <stdio.h>
36#include <stdlib.h>
37
38#include "cache.h"
39#include "cache_esi.h"
40#include "vend.h"
41#include "vct.h"
42#include "stevedore.h"
43
44#ifndef OLD_ESI
45
46struct vep_state;
47
48enum dowhat {DO_ATTR, DO_TAG};
49typedef void dostuff_f(struct vep_state *, enum dowhat);
50
51struct vep_match {
52        const char      *match;
53        const char      **state;
54};
55
56struct vep_state {
57        unsigned                magic;
58#define VEP_MAGIC               0x55cb9b82
59        vfp_bytes_f             *bytes;
60        struct vsb              *vsb;
61
62        struct sess             *sp;
63
64        /* parser state */
65        const char              *state;
66
67        unsigned                endtag;
68        unsigned                emptytag;
69        unsigned                canattr;
70
71        unsigned                remove;
72        unsigned                skip;
73
74        unsigned                o_verbatim;
75        unsigned                o_skip;
76
77        const char              *ver_p;
78
79        const char              *until;
80        const char              *until_p;
81        const char              *until_s;
82
83        const char              *esicmt;
84        const char              *esicmt_p;
85
86        struct vep_match        *attr;
87        int                     attr_l;
88        struct vsb              *attr_vsb;
89        int                     attr_delim;
90
91        struct vep_match        *match;
92        int                     match_l;
93        struct vep_match        *match_hit;
94
95        char                    tag[10];
96        int                     tag_i;
97
98        dostuff_f               *dostuff;
99
100        struct vsb              *include_src;
101};
102
103/*---------------------------------------------------------------------*/
104
105static const char *VEP_START =          "[Start]";
106static const char *VEP_NOTXML =         "[NotXml]";
107
108static const char *VEP_NEXTTAG =        "[NxtTag]";
109static const char *VEP_NOTMYTAG =       "[NotMyTag]";
110
111static const char *VEP_STARTTAG =       "[StartTag]";
112static const char *VEP_COMMENT =        "[Comment]";
113static const char *VEP_CDATA =          "[CDATA]";
114static const char *VEP_ESITAG =         "[ESITag]";
115static const char *VEP_ESIETAG =        "[ESIEndTag]";
116
117static const char *VEP_ESIREMOVE =      "[ESI:Remove]";
118static const char *VEP_ESIINCLUDE =     "[ESI:Include]";
119static const char *VEP_ESICOMMENT =     "[ESI:Comment]";
120
121static const char *VEP_INTAG =          "[InTag]";
122
123static const char *VEP_ATTR =           "[Attribute]";
124static const char *VEP_SKIPATTR =       "[SkipAttribute]";
125static const char *VEP_SKIPATTR2 =      "[SkipAttribute2]";
126static const char *VEP_ATTRGETVAL =     "[AttrGetValue]";
127static const char *VEP_ATTRVAL =        "[AttrValue]";
128
129static const char *VEP_UNTIL =          "[Until]";
130static const char *VEP_MATCHBUF =       "[MatchBuf]";
131static const char *VEP_MATCH =          "[Match]";
132static const char *VEP_XXX =            "[XXX]";
133
134/*---------------------------------------------------------------------*/
135
136static struct vep_match vep_match_starttag[] = {
137        { "<!--",       &VEP_COMMENT },
138        { "</esi:",     &VEP_ESIETAG },
139        { "<esi:",      &VEP_ESITAG },
140        { "<![CDATA[",  &VEP_CDATA },
141        { NULL,         &VEP_NOTMYTAG }
142};
143
144static const int vep_match_starttag_len =
145    sizeof vep_match_starttag / sizeof vep_match_starttag[0];
146
147/*---------------------------------------------------------------------*/
148
149static struct vep_match vep_match_esi[] = {
150        { "include",    &VEP_ESIINCLUDE },
151        { "remove",     &VEP_ESIREMOVE },
152        { "comment",    &VEP_ESICOMMENT },
153        { NULL,         &VEP_XXX }
154};
155
156static const int vep_match_esi_len =
157    sizeof vep_match_esi / sizeof vep_match_esi[0];
158
159/*---------------------------------------------------------------------*/
160
161static struct vep_match vep_match_esie[] = {
162        { "remove",     &VEP_ESIREMOVE },
163        { NULL,         &VEP_XXX }
164};
165
166static const int vep_match_esie_len =
167    sizeof vep_match_esie / sizeof vep_match_esie[0];
168
169/*---------------------------------------------------------------------*/
170
171static struct vep_match vep_match_attr_include[] = {
172        { "src=",       &VEP_ATTRGETVAL },
173        { NULL,         &VEP_SKIPATTR }
174};
175
176static const int vep_match_attr_include_len =
177    sizeof vep_match_attr_include / sizeof vep_match_attr_include[0];
178
179/*---------------------------------------------------------------------
180 * return match or NULL if more input needed.
181 */
182static struct vep_match *
183vep_match(struct vep_state *vep, const char *b, const char *e)
184{
185        struct vep_match *vm;
186        const char *q, *r;
187
188        for (vm = vep->match; vm->match; vm++) {
189                r = b;
190                for (q = vm->match; *q && r < e; q++, r++)
191                        if (*q != *r)
192                                break;
193                if (*q != '\0' && r == e) {
194                        if (b != vep->tag) {
195                                assert(e - b < sizeof vep->tag);
196                                memcpy(vep->tag, b, e - b);
197                                vep->tag_i = e - b;
198                        }
199                        return (NULL);
200                }
201                if (*q == '\0')
202                        return (vm);
203        }
204        return (vm);
205}
206
207/*---------------------------------------------------------------------
208 *
209 */
210
211static void
212vep_emit_len(struct vep_state *vep, ssize_t l, int m8, int m16, int m32)
213{
214        uint8_t buf[5];
215
216        assert(l > 0);
217        if (l < 256) {
218                buf[0] = m8;
219                buf[1] = (uint8_t)l;
220                vsb_bcat(vep->vsb, buf, 2);
221        } else if (l < 65536) {
222                buf[0] = m16;
223                vbe16enc(buf + 1, (uint16_t)l);
224                vsb_bcat(vep->vsb, buf, 3);
225        } else {
226                /* XXX assert < 2^32 */
227                buf[0] = m32;
228                vbe32enc(buf + 1, (uint32_t)l);
229                vsb_bcat(vep->vsb, buf, 5);
230        }
231} 
232
233static void
234vep_emit_skip(struct vep_state *vep)
235{
236        ssize_t l;
237
238        l = vep->o_skip;
239        vep->o_skip = 0;
240        assert(l > 0);
241        vep_emit_len(vep, l, VEC_S1, VEC_S2, VEC_S4);
242} 
243
244static void
245vep_emit_verbatim(struct vep_state *vep)
246{
247        ssize_t l;
248
249        l = vep->o_verbatim;
250        vep->o_verbatim = 0;
251        assert(l > 0);
252        vep_emit_len(vep, l, VEC_V1, VEC_V2, VEC_V4);
253        vsb_printf(vep->vsb, "%lx\r\n%c", l, 0);
254} 
255
256static void
257vep_emit_literal(struct vep_state *vep, const char *p, const char *e)
258{
259        ssize_t l;
260
261        if (e == NULL)
262                e = strchr(p, '\0');
263        if (vep->o_verbatim > 0) 
264                vep_emit_verbatim(vep);
265        if (vep->o_skip > 0) 
266                vep_emit_skip(vep);
267        l = e - p;
268        printf("---->L(%d) [%.*s]\n", (int)l, (int)l, p);
269        vep_emit_len(vep, l, VEC_L1, VEC_L2, VEC_L4);
270        vsb_printf(vep->vsb, "%lx\r\n%c", l, 0);
271        vsb_bcat(vep->vsb, p, l);
272}
273
274
275static void
276vep_mark_verbatim(struct vep_state *vep, const char *p)
277{
278        ssize_t l;
279
280        AN(vep->ver_p);
281        l = p - vep->ver_p;
282        if (l == 0)
283                return;
284        if (vep->o_skip > 0) 
285                vep_emit_skip(vep);
286        AZ(vep->o_skip);
287        printf("-->V(%d) [%.*s]\n", (int)l, (int)l, vep->ver_p);
288        vep->o_verbatim += l;
289        vep->ver_p = p;
290} 
291
292static void
293vep_mark_skip(struct vep_state *vep, const char *p)
294{
295        ssize_t l;
296
297        AN(vep->ver_p);
298        l = p - vep->ver_p;
299        if (l == 0)
300                return;
301        if (vep->o_verbatim > 0) 
302                vep_emit_verbatim(vep);
303        AZ(vep->o_verbatim);
304        printf("-->S(%d) [%.*s]\n", (int)l, (int)l, vep->ver_p);
305        vep->o_skip += l;
306        vep->ver_p = p;
307} 
308
309/*---------------------------------------------------------------------
310 */
311
312static void
313vep_do_nothing(struct vep_state *vep, enum dowhat what)
314{
315        printf("DO_NOTHING(%d)\n", what);
316        if (what == DO_ATTR) {
317                printf("ATTR (%s) (%s)\n", vep->match_hit->match,
318                        vsb_data(vep->attr_vsb));
319                vsb_delete(vep->attr_vsb);
320        }
321}
322
323/*---------------------------------------------------------------------
324 */
325
326static void
327vep_do_include(struct vep_state *vep, enum dowhat what)
328{
329        char *p, *q, *h;
330        ssize_t l;
331        txt url;
332
333        printf("DO_INCLUDE(%d)\n", what);
334        if (what == DO_ATTR) {
335                printf("ATTR (%s) (%s)\n", vep->match_hit->match,
336                        vsb_data(vep->attr_vsb));
337                XXXAZ(vep->include_src);        /* multiple src= */
338                vep->include_src = vep->attr_vsb;
339        } else {
340                XXXAN(vep->include_src);
341                if (vep->o_skip > 0) 
342                        vep_emit_skip(vep);
343                if (vep->o_verbatim > 0) 
344                        vep_emit_verbatim(vep);
345                /* XXX: what if it contains NUL bytes ?? */
346                p = vsb_data(vep->include_src);
347                l = vsb_len(vep->include_src);
348                h = 0;
349
350                if (l > 7 && !memcmp(p, "http://", 7)) {
351                        h = p + 7;
352                        p = strchr(h, '/');
353                        AN(p);
354                        printf("HOST <%.*s> PATH <%s>\n", (int)(p-h),h, p);
355                        vsb_printf(vep->vsb, "%c%s%cHost: %.*s%c",
356                            VEC_INCL, p, 0,
357                            (int)(p-h), h, 0);
358                } else if (*p == '/') {
359                        vsb_printf(vep->vsb, "%c%s%c%c",
360                            VEC_INCL, p, 0, 0);
361                } else {
362                        url = vep->sp->wrk->bereq->hd[HTTP_HDR_URL];
363                        /* Look for the last / before a '?' */
364                        h = NULL;
365                        for (q = url.b; q < url.e && *q != '?'; q++)
366                                if (*q == '/')
367                                        h = q;
368                        if (h == NULL)
369                                h = q + 1;
370                               
371                        printf("INCL:: %.*s/%s\n",
372                            (int)(h - url.b), url.b, p);
373                        vsb_printf(vep->vsb, "%c%.*s/%s%c%c",
374                            VEC_INCL, 
375                            (int)(h - url.b), url.b,
376                            p, 0, 0);
377                }
378
379                vsb_delete(vep->include_src);
380                vep->include_src = NULL;
381        }
382}
383
384/*---------------------------------------------------------------------
385 * Lex/Parse object for ESI instructions
386 *
387 * This function is called with the input object piecemal so do not
388 * assume that we have more than one char available at at time, but
389 * optimize for getting huge chunks.
390 */
391
392static void
393vep_parse(struct vep_state *vep, const char *b, size_t l)
394{
395        const char *e, *p;
396        struct vep_match *vm;
397        int i;
398
399        CHECK_OBJ_NOTNULL(vep, VEP_MAGIC);
400        assert(l > 0);
401
402        e = b + l;
403
404        if (0)
405                vep_emit_literal(vep, "A", "B");
406
407        p = b;
408        while (p < e) {
409                AN(vep->state);
410                i = e - p;
411                if (i > 10)
412                        i = 10;
413                printf("EP %s %d %d (%.*s) [%.*s]\n",
414                    vep->state,
415                    vep->skip,
416                    vep->remove,
417                    vep->tag_i, vep->tag,
418                    i, p);
419                fflush(stdout);
420                usleep(10);
421
422                /******************************************************
423                 * SECTION A
424                 */
425
426                if (vep->state == VEP_START) {
427                        /*
428                         * If the first non-whitespace char is different
429                         * from '<' we assume this is not XML.
430                         */
431                        while (p < e && vct_islws(*p)) {
432                                p++;
433                                vep_mark_verbatim(vep, p);
434                        }
435                        if (p < e) {
436                                if (*p == '<') {
437                                        vep->state = VEP_STARTTAG;
438                                } else
439                                        vep->state = VEP_NOTXML;
440                        }
441                } else if (vep->state == VEP_NOTXML) {
442                        /*
443                         * This is not recognized as XML, just skip thru
444                         * vfp_esi_end() will handle the rest
445                         */
446                        p = e;
447
448                /******************************************************
449                 * SECTION D
450                 */
451
452                } else if (vep->state == VEP_NOTMYTAG) {
453                        vep->tag_i = 0;
454                        while (p < e) {
455                                if (*p++ == '>') {
456                                        vep->state = VEP_NEXTTAG;
457                                        break;
458                                }
459                        }
460                        if (!vep->remove)
461                                vep_mark_verbatim(vep, p + 1);
462                } else if (vep->state == VEP_NEXTTAG) {
463                        /*
464                         * Hunt for start of next tag and keep an eye
465                         * out for end of EsiCmt if armed.
466                         */
467                        while (p < e && *p != '<') {
468                                if (vep->esicmt_p != NULL &&
469                                    *p == *vep->esicmt_p++) {
470                                        p++;
471                                        if (*vep->esicmt_p == '\0') {
472                                                vep->esicmt = NULL;
473                                                vep->esicmt_p = NULL;
474                                                /*
475                                                 * The end of the esicmt
476                                                 * should not be emitted.
477                                                 * But the stuff before should
478                                                 */
479                                                if (!vep->remove)
480                                                        vep_mark_verbatim(vep,
481                                                            p - 3);
482                                                vep_mark_skip(vep, p);
483                                        }
484                                } else {
485                                        p++;
486                                        vep->esicmt_p = vep->esicmt;
487                                }
488                        }
489                        if (vep->esicmt_p == NULL && !vep->remove)
490                                vep_mark_verbatim(vep, p);
491                        if (p < e)
492                                vep->state = VEP_STARTTAG;
493
494                /******************************************************
495                 * SECTION B
496                 */
497
498                } else if (vep->state == VEP_STARTTAG) {
499                        /*
500                         * Start of tag, set up match table
501                         */
502                        assert(*p == '<');
503                        if (!vep->remove)
504                                vep_mark_verbatim(vep, p);
505                        vep->match = vep_match_starttag;
506                        vep->match_l = vep_match_starttag_len;
507                        vep->state = VEP_MATCH;
508                } else if (vep->state == VEP_COMMENT) {
509                        /*
510                         * We are in a comment, find out if it is an
511                         * ESI comment or a regular comment
512                         */
513                        if (vep->esicmt == NULL)
514                                vep->esicmt_p = vep->esicmt = "esi";
515                        while (p < e) {
516                                if (*p == *vep->esicmt_p) {
517                                        p++;
518                                        if (*++vep->esicmt_p == '\0') {
519                                                vep->esicmt_p =
520                                                    vep->esicmt = "-->";
521                                                vep->state = VEP_NEXTTAG;
522                                                vep_mark_skip(vep, p);
523                                                break;
524                                        }
525                                } else {
526                                        vep->esicmt_p = vep->esicmt = NULL; 
527                                        vep->until_p = vep->until = "-->";
528                                        vep->until_s = VEP_NEXTTAG;
529                                        vep->state = VEP_UNTIL;
530                                        break;
531                                }
532                        }
533                } else if (vep->state == VEP_CDATA) {
534                        /*
535                         * Easy: just look for the end of CDATA
536                         */
537                        vep->until_p = vep->until = "]]>";
538                        vep->until_s = VEP_NEXTTAG;
539                        vep->state = VEP_UNTIL;
540                } else if (vep->state == VEP_ESITAG) {
541                        vep->tag_i = 0;
542                        vep->endtag = 0;
543                        if (vep->remove) {
544                                VSC_main->esi_errors++;
545                                vep->state = VEP_NOTMYTAG;
546                        } else {
547                                vep->skip = 1;
548                                vep_mark_skip(vep, p);
549                                vep->match = vep_match_esi;
550                                vep->match_l = vep_match_esi_len;
551                                vep->state = VEP_MATCH;
552                        }
553                } else if (vep->state == VEP_ESIETAG) {
554                        vep->tag_i = 0;
555                        vep->endtag = 1;
556                        vep->match = vep_match_esie;
557                        vep->match_l = vep_match_esie_len;
558                        vep->state = VEP_MATCH;
559                } else if (vep->state == VEP_ESIINCLUDE) {
560                        vep->dostuff = vep_do_include;
561                        vep->state = VEP_INTAG;
562                        vep->attr = vep_match_attr_include;
563                        vep->attr_l = vep_match_attr_include_len;
564                } else if (vep->state == VEP_ESIREMOVE) {
565                        vep->dostuff = vep_do_nothing;
566                        vep->remove = !vep->endtag;
567printf(">>> REMOVE %d\n", vep->remove);
568                        vep->state = VEP_INTAG;
569
570                /******************************************************
571                 * SECTION F
572                 */
573
574                } else if (vep->state == VEP_INTAG) {
575                        vep->tag_i = 0;
576                        while (p < e && vct_islws(*p)) {
577                                p++;   
578                                vep->canattr = 1;
579                        }
580                        if (p < e && *p == '/' && !vep->emptytag) {
581                                p++;
582                                vep->emptytag = 1;
583                                vep->canattr = 0;
584                        }
585                        if (p < e && *p == '>') {
586                                p++;
587                                vep_mark_skip(vep, p);
588                                AN(vep->dostuff);
589                                vep->dostuff(vep, DO_TAG);
590                                vep->state = VEP_NEXTTAG;
591                        } else if (p < e && vep->emptytag) {
592                                INCOMPL();      /* ESI-SYNTAX ERROR */
593                        } else if (p < e && vct_isxmlnamestart(*p)) {
594                                vep->state = VEP_ATTR;
595                        } else if (p < e) {
596                                INCOMPL();      /* ESI-SYNTAX ERROR */
597                        }
598
599                /******************************************************
600                 * SECTION G
601                 */
602
603                } else if (vep->state == VEP_ATTR) {
604                        AZ(vep->attr_delim);
605                        if (vep->attr == NULL) {
606                                p++;
607                                AZ(vep->attr_vsb);
608                                vep->state = VEP_SKIPATTR;
609                                break;
610                        }
611                        vep->match = vep->attr;
612                        vep->match_l = vep->attr_l;
613                        vep->state = VEP_MATCH;
614                } else if (vep->state == VEP_SKIPATTR) {
615                        vep->state = VEP_SKIPATTR2;
616                        for (i = 0; i < vep->tag_i; i++) {
617                                if (vct_isxmlname(vep->tag[i]))
618                                        continue;
619                                if (vep->tag[i] == '=') {
620                                        assert(i + 1 == vep->tag_i);
621                                        vep->state = VEP_ATTRVAL;
622                                }
623                        }
624                        xxxassert(i == vep->tag_i);
625                        vep->tag_i = 0;
626                } else if (vep->state == VEP_SKIPATTR2) {
627                        while (p < e && vct_isxmlname(*p))
628                                p++;
629                        if (p < e && *p == '=') {
630                                p++;
631                                vep->state = VEP_ATTRVAL;
632                        } else if (p < e) {
633                                INCOMPL();      /* ESI-SYNTAX ERROR */
634                        }
635                } else if (vep->state == VEP_ATTRGETVAL) {
636                        vep->attr_vsb = vsb_newauto();
637                        vep->state = VEP_ATTRVAL;
638                } else if (vep->state == VEP_ATTRVAL) {
639                        if (vep->attr_delim == 0)  {
640                                if (*p != '"' && *p != '\'')
641                                        INCOMPL();      /* ESI-SYNTAX */
642                                vep->attr_delim = *p++;
643                        }
644                        while (p < e && *p != vep->attr_delim) {
645                                if (vep->attr_vsb != NULL)
646                                        vsb_bcat(vep->attr_vsb, p, 1);
647                                p++;
648                        }
649                        if (p < e) {
650                                if (vep->attr_vsb != NULL) {
651                                        vsb_finish(vep->attr_vsb);
652                                        AN(vep->dostuff);
653                                        vep->dostuff(vep, DO_ATTR);
654                                        vep->attr_vsb = NULL;
655                                }
656                                p++;
657                                vep->attr_delim = 0;
658                                vep->state = VEP_INTAG;
659                        }
660       
661
662                /******************************************************
663                 * Utility Section
664                 */
665
666                } else if (vep->state == VEP_MATCH) {
667                        /*
668                         * Match against a table
669                         */
670                        vm = vep_match(vep, p, e);
671                        vep->match_hit = vm;
672                        if (vm != NULL) {
673                                if (vm->match != NULL)
674                                        p += strlen(vm->match);
675                                b = p;
676                                vep->state = *vm->state;
677                                vep->match = NULL;
678                                vep->tag_i = 0;
679                        } else {
680                                memcpy(vep->tag, p, e - p);
681                                vep->tag_i = e - p;
682                                vep->state = VEP_MATCHBUF;
683                                p = e;
684                        }
685                } else if (vep->state == VEP_MATCHBUF) {
686                        /*
687                         * Match against a table while split over input
688                         * sections.
689                         */
690                        do {
691                                if (*p == '>') {
692                                        vm = NULL;
693                                } else {
694                                        vep->tag[vep->tag_i++] = *p++;
695                                        vm = vep_match(vep,
696                                            vep->tag, vep->tag + vep->tag_i);
697                                }
698                        } while (vm == NULL && p < e);
699                        vep->match_hit = vm;
700                        if (vm == NULL) {
701                                assert(p == e);
702                        } else {
703                                vep->state = *vm->state;
704                                vep->match = NULL;
705                        }
706                } else if (vep->state == VEP_UNTIL) {
707                        /*
708                         * Skip until we see magic string
709                         */
710                        while (p < e) {
711                                if (*p++ != *vep->until_p++) {
712                                        vep->until_p = vep->until;
713                                } else if (*vep->until_p == '\0') {
714                                        vep->state = vep->until_s;
715                                        break;
716                                }
717                        }
718                } else {
719                        printf("*** Unknown state %s\n", vep->state);
720                        INCOMPL();
721                }
722        }
723}
724
725/*---------------------------------------------------------------------
726 * We receive a ungzip'ed object, and want to store it ungzip'ed.
727 */
728
729static int __match_proto__()
730vfp_esi_bytes_uu(struct sess *sp, struct http_conn *htc, size_t bytes)
731{
732        struct vep_state *vep;
733        ssize_t l, w;
734        struct storage *st;
735
736        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
737        vep = sp->wrk->vep;
738        CHECK_OBJ_NOTNULL(vep, VEP_MAGIC);
739
740        while (bytes > 0) {
741                if (sp->wrk->storage == NULL) {
742                        l = params->fetch_chunksize * 1024LL;
743                        sp->wrk->storage = STV_alloc(sp, l);
744                }
745                if (sp->wrk->storage == NULL) {
746                        errno = ENOMEM;
747                        return (-1);
748                }
749                st = sp->wrk->storage;
750                l = st->space - st->len;
751                if (l > bytes)
752                        l = bytes;
753                w = HTC_Read(htc, st->ptr + st->len, l);
754                if (w <= 0)
755                        return (w);
756                vep->ver_p = (const char *)st->ptr + st->len;
757#if 1
758                {
759                for (l = 0; l < w; l++) 
760                        vep_parse(vep, (const char *)st->ptr + st->len + l, 1);
761                }
762#else
763                vep_parse(vep, (const char *)st->ptr + st->len, w);
764#endif
765                st->len += w;
766                sp->obj->len += w;
767                if (st->len == st->space) {
768                        VTAILQ_INSERT_TAIL(&sp->obj->store,
769                            sp->wrk->storage, list);
770                        sp->wrk->storage = NULL;
771                        st = NULL;
772                }
773                bytes -= w;
774        }
775        return (1);
776}
777
778/*---------------------------------------------------------------------*/
779
780static void __match_proto__()
781vfp_esi_begin(struct sess *sp, size_t estimate)
782{
783        struct vep_state *vep;
784
785        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
786        AZ(sp->wrk->vep);
787        /* XXX: snapshot WS ? We'll need the space */
788        vep = (void*)WS_Alloc(sp->wrk->ws, sizeof *vep);
789        AN(vep);
790
791
792        memset(vep, 0, sizeof *vep);
793        vep->magic = VEP_MAGIC;
794        vep->sp = sp;
795        vep->bytes = vfp_esi_bytes_uu;
796        vep->vsb = vsb_newauto();
797        vep->state = VEP_START;
798        AN(vep->vsb);
799
800        sp->wrk->vep = vep;
801        (void)estimate;
802}
803
804static int __match_proto__()
805vfp_esi_bytes(struct sess *sp, struct http_conn *htc, size_t bytes)
806{
807        struct vep_state *vep;
808
809        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
810        vep = sp->wrk->vep;
811        CHECK_OBJ_NOTNULL(vep, VEP_MAGIC);
812        AN(vep->bytes);
813        return (vep->bytes(sp, htc, bytes));
814}
815
816static int __match_proto__()
817vfp_esi_end(struct sess *sp)
818{
819        struct storage *st;
820        struct vep_state *vep;
821        size_t l;
822
823        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
824        vep = sp->wrk->vep;
825        CHECK_OBJ_NOTNULL(vep, VEP_MAGIC);
826
827        if (vep->o_verbatim)
828                vep_emit_verbatim(vep);
829        if (vep->o_skip)
830                vep_emit_skip(vep);
831        vsb_finish(vep->vsb);
832        l = vsb_len(vep->vsb);
833        if (vep->state != VEP_NOTXML && l != 0) {
834                printf("ESI %d <%s>\n", (int)l, vsb_data(vep->vsb));
835
836                /* XXX: This is a huge waste of storage... */
837                sp->obj->esidata = STV_alloc(sp, vsb_len(vep->vsb));
838                AN(sp->obj->esidata);
839                memcpy(sp->obj->esidata->ptr,
840                    vsb_data(vep->vsb), vsb_len(vep->vsb));
841                sp->obj->esidata->len = vsb_len(vep->vsb);
842        }
843        vsb_delete(vep->vsb);
844
845        st = sp->wrk->storage;
846        sp->wrk->storage = NULL;
847        if (st == NULL)
848                return (0);
849
850        if (st->len == 0) {
851                STV_free(st);
852                return (0);
853        }
854        if (st->len < st->space)
855                STV_trim(st, st->len);
856        VTAILQ_INSERT_TAIL(&sp->obj->store, st, list);
857        sp->wrk->vep = NULL;
858        return (0);
859}
860
861struct vfp vfp_esi = {
862        .begin  =       vfp_esi_begin,
863        .bytes  =       vfp_esi_bytes,
864        .end    =       vfp_esi_end,
865};
866
867#endif /* OLD_ESI */
Note: See TracBrowser for help on using the repository browser.