Commit 0b06c851 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Replay of SVN r5764:

Retire the old ESI code.
parent a48f5ed3
......@@ -27,7 +27,6 @@ varnishd_SOURCES = \
cache_dir_round_robin.c \
cache_esi_parse.c \
cache_esi_deliver.c \
cache_esi.c \
cache_expire.c \
cache_fetch.c \
cache_gzip.c \
......
......@@ -35,8 +35,6 @@
*/
#define VARNISH_CACHE_CHILD 1
#undef OLD_ESI
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/socket.h>
......@@ -94,9 +92,6 @@ struct objhead;
struct objcore;
struct storage;
struct workreq;
#ifdef OLD_ESI
struct esidata;
#endif
struct vrt_backend;
struct cli_proto;
struct ban;
......@@ -444,11 +439,7 @@ struct object {
VTAILQ_HEAD(, storage) store;
#ifdef OLD_ESI
struct esidata *esidata;
#else
struct storage *esidata;
#endif
double last_use;
......@@ -807,16 +798,7 @@ void VCL_Poll(void);
char *VRT_String(struct ws *ws, const char *h, const char *p, va_list ap);
char *VRT_StringList(char *d, unsigned dl, const char *p, va_list ap);
#ifdef OLD_ESI
/* cache_vrt_esi.c */
void ESI_Deliver(struct sess *);
void ESI_Destroy(struct object *);
void ESI_Parse(struct sess *);
#else
void ESI_Deliver(struct sess *);
#endif /* OLD_ESI */
void ESI_Include(struct sess *sp, const char *src, const char *host);
/* cache_vrt_vmod.c */
void VMOD_Init(void);
......
......@@ -587,11 +587,9 @@ cnt_fetch(struct sess *sp)
AZ(sp->wrk->vfp);
/* XXX: precedence, also: do_esi */
#ifndef OLD_ESI
if (sp->wrk->do_esi) {
sp->wrk->vfp = &vfp_esi;
} else
#endif
if (sp->wrk->do_gunzip &&
http_HdrIs(sp->wrk->beresp, H_Content_Encoding, "gzip")) {
http_Unset(sp->wrk->beresp, H_Content_Encoding);
......@@ -677,11 +675,6 @@ cnt_fetch(struct sess *sp)
return (0);
}
#ifdef OLD_ESI
if (sp->wrk->do_esi)
ESI_Parse(sp);
#endif
switch (sp->handling) {
case VCL_RET_RESTART:
HSH_Drop(sp);
......
/*-
* Copyright (c) 2006 Verdens Gang AS
* Copyright (c) 2006-2010 Linpro AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Runtime support for compiled VCL programs ESI processing.
*
* The basic ESI 1.0 is a very simple specification:
* http://www.w3.org/TR/esi-lang
* But it seems that Oracle and Akamai has embrodiered it to be almost a new
* layer of scripting language in HTTP transmission chains.
*
* It is not obvious how much help the "advanced" features of ESI really
* are to users, so our aim is to pick the fruit starting with the lowest
* hanging, esi:include
*/
#include "config.h"
#include "svnid.h"
SVNID("$Id$")
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "vrt.h"
#include "vcl.h"
#include "vct.h"
#include "cache.h"
#include "stevedore.h"
#ifdef OLD_ESI
/*--------------------------------------------------------------------*/
struct esi_bit {
VTAILQ_ENTRY(esi_bit) list;
char chunk_length[20];
txt verbatim;
txt host;
txt include;
};
struct esi_ptr {
const char *p;
const char *e;
struct storage *st;
};
struct esi_work {
struct sess *sp;
size_t off;
struct esi_ptr s;
struct esi_ptr p;
txt tag;
txt t;
struct esi_bit *eb;
int remflg; /* inside <esi:remove> </esi:remove> */
int incmt; /* inside <!--esi ... --> comment */
unsigned space; /* ... needed */
VTAILQ_HEAD(, esi_bit) esibits;
};
struct esidata {
unsigned magic;
#define ESIDATA_MAGIC 0x7255277f
VTAILQ_HEAD(, esi_bit) esibits;
struct storage *storage;
};
/*--------------------------------------------------------------------
* Move an esi_ptr one char forward
*/
static void
Nep(struct esi_ptr *ep)
{
static const char * const finis = "";
if (ep->p == finis)
return;
ep->p++;
if (ep->p < (char*)ep->st->ptr + ep->st->len)
return;
ep->st = VTAILQ_NEXT(ep->st, list);
if (ep->st != NULL) {
ep->p = (char *)ep->st->ptr;
ep->e = ep->p + ep->st->len;
return;
}
ep->p = finis;
ep->e = finis;
return;
}
/*--------------------------------------------------------------------
* Consume one input character.
*/
static void
N(struct esi_work *ew)
{
if (ew->p.p < ew->p.e)
ew->off++;
Nep(&ew->p);
}
/*--------------------------------------------------------------------
* Strcmp for objects pointers
*/
static int
CMP(const struct esi_ptr *ep, const char *str)
{
struct esi_ptr p2;
for (p2 = *ep; *str == *p2.p; str++)
Nep(&p2);
return (*str);
}
/*--------------------------------------------------------------------
* Replace the mandatory XML 1.0 entity references, in place.
*/
static void
XMLentity(txt *t)
{
char *s, *d;
for (s = d = t->b; s < t->e; ) {
if (*s == '&') {
#define R(l,f,r) \
if (s + l <= t->e && !memcmp(s, f, l)) { \
*d++ = r; \
s += l; \
continue; \
}
R(6, "&apos;", '\'');
R(6, "&quot;", '"');
R(4, "&lt;", '<');
R(4, "&gt;", '>');
R(5, "&amp;", '&');
}
#undef R
*d++ = *s++;
}
t->e = d;
t->e[0] = '\0';
}
/*--------------------------------------------------------------------
* Report a parsing error
*
* XXX: The "at xxx" count is usually the tail of the sequence. Since we
* XXX: wander over the storage in an oderly manner now, we could keep
* XXX: track of line+pos and record the beginning of the stuff that
* XXX: offends os in the central dispatch loop.
* XXX: This is left a an excercise for the reader.
*/
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;
VSC_main->esi_errors++;
if (i == 0)
i = p - ew->t.b;
if (i > 20) {
i = 20;
ellipsis = 1;
}
q = buf;
q += sprintf(buf, "at %zu: %s \"", ew->off, 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 & 0xff);
}
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 void
esi_addbit(struct esi_work *ew, const char *verbatim, unsigned len)
{
ew->space += sizeof(*ew->eb);
ew->eb = (void*)WS_Alloc(ew->sp->wrk->ws, sizeof *ew->eb);
AN(ew->eb);
memset(ew->eb, 0, sizeof *ew->eb);
VTAILQ_INSERT_TAIL(&ew->esibits, ew->eb, list);
if (verbatim != NULL) {
ew->eb->verbatim.b = TRUST_ME(verbatim);
if (len > 0)
ew->eb->verbatim.e = TRUST_ME(verbatim + len);
sprintf(ew->eb->chunk_length, "%x\r\n", Tlen(ew->eb->verbatim));
if (params->esi_syntax & 0x4)
WSP(ew->sp, SLT_Debug, "AddBit: %d <%.*s>",
Tlen(ew->eb->verbatim),
Tlen(ew->eb->verbatim),
ew->eb->verbatim.b);
} else {
AN(ew->s.p);
ew->eb->verbatim.b = ew->eb->verbatim.e = TRUST_ME(ew->s.p);
}
}
/*--------------------------------------------------------------------*/
static void
esi_addpfx(struct esi_work *ew)
{
const char *ep;
if (ew->remflg) {
/* In <esi:remove...> don't add anything */
ew->s = ew->p;
return;
}
while (ew->s.st != ew->p.st) {
ep = (const char *)(ew->s.st->ptr + ew->s.st->len);
esi_addbit(ew, ew->s.p, ep - ew->s.p);
ew->s.p = ep;
Nep(&ew->s);
}
if (ew->s.st != NULL && ew->p.p != ew->s.p)
esi_addbit(ew, ew->s.p, ew->p.p - ew->s.p);
ew->s.p = ew->p.p;
}
/*--------------------------------------------------------------------
* Tease the next attribute and value out of an XML element.
*
* XXX: is the syntax correct ?
*/
static int
esi_attrib(const struct esi_work *ew, txt *in, txt *attrib, txt *val)
{
AN(*in->b);
/* Skip leading blanks */
while(in->b < in->e && isspace(*in->b))
in->b++;
/* Nothing found */
if (in->b >= in->e)
return (0);
if (!vct_isxmlnamestart(*in->b)) {
/* XXX error */
esi_error(ew, in->b, 1,
"XML 1.0 Illegal attribute start character");
return (-1);
}
/* Attribute name until '=' or space */
*attrib = *in;
while(in->b < in->e && *in->b != '=' && !isspace(*in->b)) {
if (!vct_isxmlname(*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++;
if (isspace(*in->b)) {
val->e = val->b = in->b;
in->b++;
return (1);
}
/* 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;
in->b++;
}
return (1);
}
/*--------------------------------------------------------------------
* Add one piece to the output, either verbatim or include
*/
static void
esi_handle_include(struct esi_work *ew)
{
struct esi_bit *eb;
char *p, *q, *c;
txt t = ew->tag;
txt tag;
txt val;
unsigned u, v, s;
if (ew->eb == NULL || ew->eb->include.b != NULL)
esi_addbit(ew, NULL, 0);
eb = ew->eb;
WSP(ew->sp, SLT_Debug, "Incl \"%.*s\"", t.e - t.b, t.b);
while (esi_attrib(ew, &t, &tag, &val) == 1) {
if (params->esi_syntax & 0x4)
WSP(ew->sp, SLT_Debug, "<%.*s> -> <%.*s>",
tag.e - tag.b, tag.b, val.e - val.b, val.b);
if (Tlen(tag) != 3 || memcmp(tag.b, "src", 3))
continue;
if (Tlen(val) == 0) {
esi_error(ew, tag.b, Tlen(tag),
"ESI esi:include src attribute without value");
continue;
}
/* We are saving the original string */
s = 0;
if (val.b != val.e) {
s = Tlen(val) + 1;
c = WS_Alloc(ew->sp->wrk->ws, s);
XXXAN(c);
memcpy(c, val.b, Tlen(val));
val.b = c;
val.e = val.b + s;
val.e[-1] = '\0';
}
if (strchr(val.b, '&'))
XMLentity(&val);
if (Tlen(val) > 7 && !memcmp(val.b, "http://", 7)) {
/* Rewrite to Host: header inplace */
eb->host.b = val.b;
memcpy(eb->host.b, "Host: ", 6);
q = eb->host.b + 6;
for (p = eb->host.b + 7; p < val.e && *p != '/'; p++)
*q++ = *p;
*q++ = '\0';
eb->host.e = q;
assert(*p == '/'); /* XXX */
/* The rest is the URL */
eb->include.b = p;
eb->include.e = val.e;
} else if (Tlen(val) > 0 && *val.b == '/') {
/* Absolute on this host */
eb->include = val;
} else {
/*
* Decision: We interpret the relative URL against
* the actual URL we asked the backend for.
* The client's request URL may be entirely
* different and have been rewritten underway.
*/
CHECK_OBJ_NOTNULL(ew->sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(ew->sp->wrk->bereq, HTTP_MAGIC);
tag = ew->sp->wrk->bereq->hd[HTTP_HDR_URL];
/* Use the objects WS to store the result */
CHECK_OBJ_NOTNULL(ew->sp->obj, OBJECT_MAGIC);
/* Look for the last '/' before a '?' */
q = NULL;
for (p = tag.b; p < tag.e && *p != '?'; p++)
if (*p == '/')
q = p;
if (q != NULL)
tag.e = q + 1;
u = WS_Reserve(ew->sp->wrk->ws, 0);
v = snprintf(ew->sp->wrk->ws->f, u - 1, "%.*s%.*s",
pdiff(tag.b, tag.e), tag.b,
pdiff(val.b, val.e), val.b);
v++;
xxxassert(v < u);
eb->include.b = ew->sp->wrk->ws->f;
eb->include.e = ew->sp->wrk->ws->f + v;
WS_Release(ew->sp->wrk->ws, v);
}
if (eb->include.b != NULL)
ew->space += Tlen(eb->include);
if (eb->host.b != NULL)
ew->space += Tlen(eb->host);
}
}
/*--------------------------------------------------------------------
* See if this looks like XML: first non-white char must be '<'
*/
static int
looks_like_xml(const struct object *obj) {
struct storage *st;
unsigned u;
VTAILQ_FOREACH(st, &obj->store, list) {
AN(st);
for (u = 0; u < st->len; u++) {
if (isspace(st->ptr[u]))
continue;
if (st->ptr[u] == '<')
return (1);
else
return (0);
}
}
return (0);
}
/*--------------------------------------------------------------------
* A quick stroll through the object, to find out if it contains any
* esi sequences at all.
*/
static int
contain_esi(const struct object *obj) {
struct storage *st;
unsigned u;
const char *r, *r2;
static const char * const wanted = "<esi:";
static const char * const wanted2 = "<!--esi";
/*
* Do a fast check to see if there is any '<esi:' sequences at all
*/
r = wanted;
r2 = wanted2;
VTAILQ_FOREACH(st, &obj->store, list) {
AN(st);
for (u = 0; u < st->len; u++) {
if (st->ptr[u] != *r) {
r = wanted;
} else if (*++r == '\0')
return (1);
if (st->ptr[u] != *r2) {
r2 = wanted2;
} else if (*++r2 == '\0')
return (1);
}
}
return (0);
}
/*--------------------------------------------------------------------*/
static void
parse_esi_comment(struct esi_work *ew)
{
esi_addpfx(ew);
N(ew); N(ew); N(ew); N(ew); N(ew); N(ew); N(ew);
assert(!ew->incmt);
ew->incmt = 1;
ew->s.p = ew->p.p;
}
/*--------------------------------------------------------------------*/
static void
parse_comment(struct esi_work *ew)
{
do {
N(ew);
if (*ew->p.p == '-' && !CMP(&ew->p, "-->")) {
N(ew);
N(ew);
N(ew);
break;
}
} while (ew->p.p < ew->p.e);
}
/*--------------------------------------------------------------------*/
static void
parse_cdata(struct esi_work *ew)
{
esi_addpfx(ew);
do {
N(ew);
if (*ew->p.p == ']' && !CMP(&ew->p, "]]>")) {
N(ew);
N(ew);
N(ew);
break;
}
} while (ew->p.p < ew->p.e);
}
/*--------------------------------------------------------------------*/
static void
parse_esi_tag(struct esi_work *ew, int closing)
{
int l, ll, empty;
struct esi_ptr px;
char *q;
esi_addpfx(ew);
do
N(ew);
while (*ew->p.p != '>' && ew->p.p < ew->p.e);
if (ew->p.p == ew->p.e) {
esi_addpfx(ew);
esi_error(ew, ew->s.p, 0,
"XML 1.0 incomplete language element");
return;
}
N(ew);
if (ew->p.st == ew->s.st) {
ew->tag.b = TRUST_ME(ew->s.p);
ew->tag.e = TRUST_ME(ew->p.p);
} else {
/*
* The element is spread over more than one storage
* segment, pull it together in the object workspace
* XXX: Ideally, we should only pull together the bits
* XXX: we need, like the filename.
*/
ew->tag.b = ew->sp->wrk->ws->f;
ew->tag.e = ew->tag.b + WS_Reserve(ew->sp->wrk->ws, 0);
px = ew->s;
q = ew->tag.b;
while (px.p != ew->p.p) {
xxxassert(q < ew->tag.e);
*q++ = *px.p;
Nep(&px);
}
ew->tag.e = q;
WS_Release(ew->sp->wrk->ws, Tlen(ew->tag));
}
ll = Tlen(ew->tag);
ew->tag.b++;
ew->tag.e--;
empty = (ew->tag.e[-1] == '/') ? 1 : 0;
if (empty)
ew->tag.e--;
if (empty && closing)
esi_error(ew, ew->s.p, ll,
"XML 1.0 empty and closing element");
ew->tag.b += 4 + (closing ? 1 : 0);
l = Tlen(ew->tag);
WSP(ew->sp, SLT_Debug,
"tag {%.*s} %d %d %d", l, ew->tag.b, ew->remflg, empty, closing);
if (l >= 6 && !memcmp(ew->tag.b, "remove", 6)) {
if (empty) {
/* XXX ?? */
} else if (closing) {
if (!ew->remflg)
esi_error(ew, ew->s.p, ll,
"ESI 1.0 esi:remove not opened");
ew->remflg = 0;
} else {
if (ew->remflg)
esi_error(ew, ew->s.p, ll,
"ESI 1.0 forbids nested esi:remove");
ew->remflg = 1;
}
} else if (ew->remflg) {
esi_error(ew, ew->s.p, ll,
"ESI 1.0 forbids esi: elements inside esi:remove");
} else if (l >= 7 && !memcmp(ew->tag.b, "comment", 7)) {
if (closing)
esi_error(ew, ew->s.p, ll,
"ESI 1.0 closing esi:comment illegal");
else if (!empty)
esi_error(ew, ew->s.p, ll,
"ESI 1.0 wants empty esi:comment");
} else if (l >= 7 && !memcmp(ew->tag.b, "include", 7)) {
if (closing) {
esi_error(ew, ew->s.p, ll,
"ESI 1.0 closing esi:include illegal");
} else if (!empty) {
esi_error(ew, ew->s.p, ll,
"ESI 1.0 wants empty esi:include");
}
ew->tag.b += 7;
esi_handle_include(ew);
} else {
esi_error(ew, ew->s.p, ll,
"ESI 1.0 unimplemented element");
}
ew->s = ew->p;
}
/*--------------------------------------------------------------------*/
void
ESI_Parse(struct sess *sp)
{
struct esi_work *ew, eww[1];
struct esi_bit *eb;
struct esidata *ed;
struct storage *st;
unsigned u;
char *hack;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(sp->obj, OBJECT_MAGIC);
AssertObjPassOrBusy(sp->obj);
if (VTAILQ_EMPTY(&sp->obj->store))
return;
if (!(params->esi_syntax & 0x00000001)) {
/*
* By default, we will not ESI process an object where
* the first non-space character is different from '<'
*/
if (!looks_like_xml(sp->obj)) {
WSP(sp, SLT_ESI_xmlerror,
"No ESI processing, first char not '<'");
return;
}
}
/*
* Do a fast check to see if there is any '<esi:' sequences at all
*/
if (!contain_esi(sp->obj))
return;
/* XXX: debugging hack */
hack = sp->wrk->ws->f;
VSC_main->esi_parse++;
/* XXX: only if GET ? */
ew = eww;
memset(eww, 0, sizeof eww);
VTAILQ_INIT(&ew->esibits);
ew->sp = sp;
ew->off = 1;
ew->space += sizeof(struct esidata);
ew->p.st = VTAILQ_FIRST(&sp->obj->store);
AN(ew->p.st);
ew->p.p = (char *)ew->p.st->ptr;
ew->p.e = ew->p.p + ew->p.st->len;
/* ->s points to the first un-dealt-with byte */
ew->s = ew->p;
while (ew->p.p < ew->p.e) {
if (ew->incmt && *ew->p.p == '-' && !CMP(&ew->p, "-->")) {
/* End of ESI comment */
esi_addpfx(ew);
N(ew);
N(ew);
N(ew);
ew->s = ew->p;
ew->incmt = 0;
continue;
}
/* Skip forward to the first '<' */
if (*ew->p.p != '<') {
N(ew);
continue;
}
if (!CMP(&ew->p, "<!--esi")) {
parse_esi_comment(ew);
} else if (!CMP(&ew->p, "<!--")) {
parse_comment(ew);
} else if (!CMP(&ew->p, "</esi")) {
parse_esi_tag(ew, 1);
} else if (!CMP(&ew->p, "<esi:")) {
parse_esi_tag(ew, 0);
} else if (!CMP(&ew->p, "<![CDATA[")) {
parse_cdata(ew);
} else {
/*
* Something we don't care about, just skip it.
*/
N(ew);
if (!(params->esi_syntax & 0x2)) {
/* XXX: drop this ? */
do {
N(ew);
} while (*ew->p.p != '>' && ew->p.p < ew->p.e);
}
}
}
esi_addpfx(ew);
/*
* XXX: we could record the starting point of these elements
* XXX: so that the char-index were more useful, but we are
* XXX: not trivially able to print their contents, so leave
* XXX: it like this for now, pending more thought about the
* XXX: proper way to report these errors.
*/
if (ew->remflg)
esi_error(ew, ew->t.e, -1,
"ESI 1.0 unterminated <esi:remove> element");
if (ew->incmt)
esi_error(ew, ew->t.e, -1,
"ESI 1.0 unterminated <!--esi comment");
st = STV_alloc(sp, ew->space);
AN(st);
assert(st->space >= ew->space);
ed = (void*)st->ptr;
st->len += sizeof(*ed);
memset(ed, 0, sizeof *ed);
ed->magic = ESIDATA_MAGIC;
ed->storage = st;
VTAILQ_INIT(&ed->esibits);
while (!VTAILQ_EMPTY(&ew->esibits)) {
eb = VTAILQ_FIRST(&ew->esibits);
VTAILQ_REMOVE(&ew->esibits, eb, list);
memcpy(st->ptr + st->len, eb, sizeof *eb);
eb = (void*)(st->ptr + st->len);
st->len += sizeof(*eb);
if (eb->include.b != NULL) {
u = Tlen(eb->include);
memcpy(st->ptr + st->len, eb->include.b, u);
eb->include.b = (void*)(st->ptr + st->len);
eb->include.e = eb->include.b + u;
st->len += u;
}
if (eb->host.b != NULL) {
u = Tlen(eb->host);
memcpy(st->ptr + st->len, eb->host.b, u);
eb->host.b = (void*)(st->ptr + st->len);
eb->host.e = eb->host.b + u;
st->len += u;
}
VTAILQ_INSERT_TAIL(&ed->esibits, eb, list);
}
assert(st->len <= st->space);
assert(st->len == ew->space);
sp->obj->esidata = ed;
memset(hack, 0xaa, sp->wrk->ws->f - hack);
}
/*--------------------------------------------------------------------*/
void
ESI_Deliver(struct sess *sp)
{
struct esi_bit *eb;
struct worker *w;
struct esidata *ed;
w = sp->wrk;
ed = sp->obj->esidata;
CHECK_OBJ_NOTNULL(ed, ESIDATA_MAGIC);
VTAILQ_FOREACH(eb, &ed->esibits, list) {
if (Tlen(eb->verbatim)) {
if (sp->wrk->res_mode & RES_CHUNKED)
(void)WRW_Write(w, eb->chunk_length, -1);
sp->acct_tmp.bodybytes += WRW_Write(w,
eb->verbatim.b, Tlen(eb->verbatim));
if (sp->http->protover >= 1.1)
(void)WRW_Write(w, "\r\n", -1);
}
if (eb->include.b == NULL ||
sp->esi_level >= params->max_esi_includes)
continue;
ESI_Include(sp, eb->include.b, eb->host.b);
if (sp->fd < 0)
break;
}
}
/*--------------------------------------------------------------------*/
void
ESI_Destroy(struct object *o)
{
struct esidata *ed;
ed = o->esidata;
o->esidata = NULL;
CHECK_OBJ_NOTNULL(ed, ESIDATA_MAGIC);
STV_free(ed->storage);
}
#endif /* OLD_ESI */
......@@ -44,7 +44,7 @@ SVNID("$Id")
/*--------------------------------------------------------------------*/
void
static void
ESI_Include(struct sess *sp, const char *src, const char *host)
{
struct object *obj;
......@@ -120,7 +120,6 @@ ESI_Include(struct sess *sp, const char *src, const char *host)
/*--------------------------------------------------------------------*/
#ifndef OLD_ESI
//#define Debug(fmt, ...) printf(fmt, __VA_ARGS__)
#define Debug(fmt, ...) /**/
......@@ -233,4 +232,3 @@ ESI_Deliver(struct sess *sp)
(void)WRW_Flush(sp->wrk);
}
#endif /* OLD_ESI */
......@@ -42,8 +42,6 @@ SVNID("$Id")
#include "zlib.h"
#include "stevedore.h"
#ifndef OLD_ESI
//#define Debug(fmt, ...) printf(fmt, __VA_ARGS__)
#define Debug(fmt, ...) /**/
......@@ -1098,8 +1096,6 @@ struct vfp vfp_esi = {
.end = vfp_esi_end,
};
#endif /* OLD_ESI */
#if 0
digraph xml {
......
......@@ -693,15 +693,10 @@ HSH_Deref(struct worker *w, struct objcore *oc, struct object **oo)
DSL(0x40, SLT_Debug, 0, "Object %u workspace min free %u",
o->xid, WS_Free(o->ws_o));
#ifdef OLD_ESI
if (o->esidata != NULL)
ESI_Destroy(o);
#else
if (o->esidata != NULL) {
STV_free(o->esidata);
o->esidata = NULL;
}
#endif
if (oc != NULL)
oc_freeobj(oc);
w->stats.n_object--;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment