--------------------- PatchSet 4716 Date: 2002/08/19 11:42:57 Author: rbcollins Branch: esi Tag: (none) Log: esi:vars support (minus USER_AGENT) Members: src/ESI.c:1.1.2.16->1.1.2.17 src/client_side_reply.c:1.1.2.15->1.1.2.16 Index: squid/src/ESI.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/ESI.c,v retrieving revision 1.1.2.16 retrieving revision 1.1.2.17 diff -u -r1.1.2.16 -r1.1.2.17 --- squid/src/ESI.c 19 Aug 2002 00:23:48 -0000 1.1.2.16 +++ squid/src/ESI.c 19 Aug 2002 11:42:57 -0000 1.1.2.17 @@ -1,6 +1,6 @@ /* - * $Id: ESI.c,v 1.1.2.16 2002/08/19 00:23:48 rbcollins Exp $ + * $Id: ESI.c,v 1.1.2.17 2002/08/19 11:42:57 rbcollins Exp $ * * DEBUG: section 86 ESI processing * AUTHOR: Robert Collins @@ -48,6 +48,7 @@ /* TODO: Factor the store memory segment management into a reusable code block * or perhaps use membuffers here? */ + typedef struct _esiSegment { char buf[HTTP_REQBUF_SZ]; size_t len; /* how much data has been pushed into this */ @@ -91,6 +92,25 @@ * NOT TODO: esi:inline - out of scope. */ +/* esi variable replacement logic */ +/* Recursive uses are not supported by design */ +struct _query_elem{char *var, *val;}; +typedef struct { + esiSegment *output; + HttpHeader hdr; + struct _query_elem *query; + size_t query_sz; + size_t query_elements; + char *query_string; +} esiVarState; +CBDATA_TYPE (esiVarState); +FREE esiVarStateFree; +static esiVarState *esiVarStateNew(HttpHeader const *, const char *uri); +static void esiVarStateDoIt (esiVarState *); +static void esiVarStateFeedData (esiVarState *, const char *buf, size_t len); +static esiSegment *esiVarStateExtractList(esiVarState *); +static char * esiVarStateExtractChar (esiVarState *); + typedef enum { ESI_PROCESS_COMPLETE, ESI_PROCESS_PENDING_WONTFAIL, @@ -111,8 +131,8 @@ #define RENDER(foo, bar) foo->vptr->render(foo, bar) typedef int esiAddElement (void *, esiElement *); /* add a child to an element */ #define ADDELEMENT(foo, bar) foo->vptr->add(foo,bar) -typedef esiProcessResult_t esiProcessSelf (void *); /* process this element */ -#define PROCESS(foo) foo->vptr->process(foo) +typedef esiProcessResult_t esiProcessSelf (void *, int); /* process this element */ +#define PROCESS(foo, bar) foo->vptr->process(foo, bar) struct _esiElementType { esiRender *render; esiAddElement *add; @@ -131,6 +151,7 @@ static esiRender esiCommentRender; static esiRender esiLiteralRender; +static esiProcessSelf esiLiteralProcess; static esiAddElement esiSequenceAdd; static esiRender esiSequenceRender; @@ -155,18 +176,20 @@ ESI_ELEMENT_REMOVE, ESI_ELEMENT_TRY, ESI_ELEMENT_ATTEMPT, - ESI_ELEMENT_EXCEPT + ESI_ELEMENT_EXCEPT, + ESI_ELEMENT_VARS } esiElementType_t; static esiElementType _esiComment = {esiCommentRender,esiAddFail,esiProcessComplete}; -static esiElementType _esiLiteral = {esiLiteralRender,esiAddFail,esiProcessComplete}; +static esiElementType _esiLiteral = {esiLiteralRender,esiAddFail,esiLiteralProcess}; static esiElementType _esiSequence = {esiSequenceRender,esiSequenceAdd,esiSequenceProcess}; static esiElementType _esiInclude = {esiIncludeRender, esiAddFail, esiIncludeProcess}; static esiElementType _esiRemove = {esiRemoveRender, esiRemoveAdd, esiProcessComplete}; static esiElementType _esiTry = {esiTryRender, esiTryAdd, esiTryProcess}; -/* esiAttempt and esiExcept are 'Sequences' */ +/* esiAttempt, esiExcept and esiVar are 'Sequences' */ static esiElementType _esiAttempt = {esiSequenceRender,esiSequenceAdd,esiSequenceProcess}; static esiElementType _esiExcept = {esiSequenceRender,esiSequenceAdd,esiSequenceProcess}; +static esiElementType _esiVar = {esiSequenceRender,esiSequenceAdd,esiSequenceProcess}; /* esiComment */ typedef struct { @@ -181,10 +204,14 @@ esiElementType *vptr; /* optimise copies away later */ esiSegment *buffer; + struct { + int donevars:1; + } flags; + esiVarState *varState; } esiLiteral; CBDATA_TYPE (esiLiteral); static FREE esiLiteralFree; -static esiElement * esiLiteralNew(const XML_Char *s, int len); +static esiElement * esiLiteralNew(esiContext *, const XML_Char *s, int len); /* esiSequence */ typedef struct { @@ -194,6 +221,9 @@ size_t allocedsize; int elementcount; int processedcount; + struct { + int dovars:1; + } flags; } esiSequence; CBDATA_TYPE (esiSequence); static FREE esiSequenceFree; @@ -250,6 +280,10 @@ static FREE esiTryFree; static esiElement *esiTryNew(void); +/* esiVar */ +typedef esiSequence esiVar; +static esiElement *esiVarNew(void); + /* esiContext */ struct _esiContext { clientStreamNode *this; /* our stream node */ @@ -288,6 +322,7 @@ int stackdepth; /* self explanatory */ XML_Parser p; /* our parser */ } parserState; /* todo factor this off somewhere else; */ + esiVarState *varState; esiElement *tree; }; @@ -314,6 +349,9 @@ static esiStreamContext *esiStreamContextNew (esiInclude *); /* esiSegment */ static void esiSegmentFreeList (esiSegment **head); +static void esiSegmentTransferList (esiSegment **from, esiSegment **to); +static char *esiSegmentListToChar (esiSegment *head); +static void esiSegmentListAppend (esiSegment **head, char const *, size_t); /* other */ static CSCB esiBufferRecipient; @@ -733,26 +771,12 @@ rv->this = this; rv->http = http; rv->flags.clientwantsdata = 1; + rv->varState = esiVarStateNew (&http->request->header, http->uri); debug (86,5)("esiContextNew: Client wants data (always created during reply cycle\n"); } return rv; } -typedef struct { - char *buf; /* not owned by us. */ - size_t len; -} inplacetoken; - -inplacetoken -esiFindToken (esiSegment *buffer, off_t startat); - -typedef enum { - TOKEN_START, /* looking for < */ - TOKEN_QUOTED, /* looking for a match to the start quote */ - TOKEN_UNQUOTED, /* looking for " or ' or > */ - TOKEN_COMPLETE /* finished */ -} tokenstate; - int esiAddLiteral (esiContext *context, const XML_Char *s, int len); void start(void *data, const XML_Char *el, const char **attr); @@ -779,6 +803,8 @@ return ESI_ELEMENT_REMOVE; if (!strncmp (el + 4, "except", 6)) return ESI_ELEMENT_EXCEPT; + if (!strncmp (el + 4, "vars", 4)) + return ESI_ELEMENT_VARS; if (!strncmp (el + 4, "try", 3)) return ESI_ELEMENT_TRY; @@ -874,6 +900,11 @@ element = esiExceptNew (); esiAddStackElement (context, element); break; + case ESI_ELEMENT_VARS: + /* Put on the stack to allow skipping of 'invalid' markup */ + element = esiVarNew (); + esiAddStackElement (context, element); + break; } debug (86,5)("esi stack depth %d\n",context->parserState.stackdepth); @@ -912,6 +943,7 @@ case ESI_ELEMENT_TRY: case ESI_ELEMENT_ATTEMPT: case ESI_ELEMENT_EXCEPT: + case ESI_ELEMENT_VARS: /* pop of the stack */ --context->parserState.stackdepth; break; @@ -946,7 +978,8 @@ /* wrap the comment in some tags */ assert (XML_Parse (p, "
", 5,0)); - if (! XML_Parse(p, s + 3, strlen(s) - 3, 0)) { + if (! XML_Parse(p, s + 3, strlen(s) - 3, 0) || + ! XML_Parse (p, "
",6,1)) { debug (86,0)("esiExpatComment: Parsing fragment '%s' failed.\n", s + 3); context->errorpage = ERR_UNSUP_REQ; context->errorstatus = HTTP_INTERNAL_SERVER_ERROR; @@ -956,7 +989,6 @@ XML_GetCurrentLineNumber(p), XML_ErrorString(XML_GetErrorCode(p))); } - assert (XML_Parse (p, "",6,1)); XML_ParserFree (p); debug (86,5)("esiExpatComment: ESI