source: bin/varnishd/cache_esi_parse.c @ c5c8bb

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

Make esi:remove discard any attributes

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