]> git.ipfire.org Git - thirdparty/squid.git/blame - src/esi/VarState.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / esi / VarState.cc
CommitLineData
924f73bc 1/*
bde978a6 2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
26ac0430 3 *
bbc27441
AJ
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
924f73bc 7 */
8
bbc27441
AJ
9/* DEBUG: section 86 ESI processing */
10
582c2af2 11#include "squid.h"
f99c2cfe 12#include "esi/VarState.h"
ed6e9fb9 13#include "fatal.h"
924f73bc 14#include "HttpReply.h"
15
16CBDATA_TYPE (ESIVarState);
17FREE ESIVarStateFree;
18
26ac0430
AJ
19char const *ESIVariableUserAgent::esiUserOs[]= {
20 "WIN",
21 "MAC",
22 "UNIX",
23 "OTHER"
24};
924f73bc 25
26ac0430
AJ
26char const * esiBrowsers[]= {"MSIE",
27 "MOZILLA",
28 "OTHER"
29 };
924f73bc 30
924f73bc 31void
32ESIVarState::Variable::eval (ESIVarState &state, char const *subref, char const *found_default) const
33{
34 /* No-op. We swallow it */
35
36 if (found_default)
37 ESISegment::ListAppend (state.getOutput(), found_default, strlen (found_default));
38}
39
40void
41ESIVarState::hostUsed()
42{
43 flags.host = 1;
44}
45
46void
47ESIVarState::cookieUsed()
48{
49 flags.cookie = 1;
50}
51
52void
53ESIVarState::languageUsed()
54{
55 flags.language = 1;
56}
57
58void
59ESIVarState::refererUsed()
60{
61 flags.referer = 1;
62}
63
64void
65ESIVarState::useragentUsed()
66{
67 flags.useragent = 1;
68}
69
70HttpHeader &
71ESIVarState::header()
72{
73 return hdr;
74}
75
76ESISegment::Pointer &
77ESIVarState::getOutput()
78{
79 return output;
80}
81
82char const *
83ESIVariableQuery::queryString() const
84{
85 return query_string;
86}
87
88struct _query_elem const *
e1381638
AJ
89ESIVariableQuery::queryVector() const {
90 return query;
91}
924f73bc 92
93size_t const &
94ESIVariableQuery::queryElements() const
95{
96 return query_elements;
97}
98
99void
100ESIVarState::feedData (const char *buf, size_t len)
101{
102 /* TODO: if needed - tune to skip segment iteration */
137a13ea 103 debugs (86,6, "esiVarState::feedData: accepting " << len << " bytes");
924f73bc 104 ESISegment::ListAppend (input, buf, len);
105}
106
107ESISegment::Pointer
108ESIVarState::extractList()
109{
110 doIt();
111 ESISegment::Pointer rv = output;
112 output = NULL;
bf8fe701 113 debugs(86, 6, "ESIVarStateExtractList: Extracted list");
924f73bc 114 return rv;
115}
116
117char *
118ESIVarState::extractChar ()
119{
120 if (!input.getRaw())
121 fatal ("Attempt to extract variable state with no data fed in \n");
122
123 doIt();
124
125 char *rv = output->listToChar();
126
127 ESISegmentFreeList (output);
128
bf8fe701 129 debugs(86, 6, "ESIVarStateExtractList: Extracted char");
924f73bc 130
131 return rv;
132}
133
134/* ESIVarState */
135void
136esiVarStateFree (void *data)
137{
138 ESIVarState *thisNode = (ESIVarState*)data;
139 thisNode->freeResources();
140}
141
142ESIVarState::~ESIVarState()
143{
144 freeResources();
145
385acf91 146 while (!variablesForCleanup.empty()) {
38c22baf
FC
147 delete variablesForCleanup.back();
148 variablesForCleanup.pop_back();
149 }
924f73bc 150
151 delete defaultVariable;
152}
153
154void
155ESIVarState::freeResources()
156{
157 input = NULL;
158 ESISegmentFreeList (output);
519e0948 159 hdr.clean();
924f73bc 160}
161
162void *
163ESIVarState::operator new(size_t byteCount)
164{
165 assert (byteCount == sizeof (ESIVarState));
166 void *rv;
167 CBDATA_INIT_TYPE_FREECB(ESIVarState, esiVarStateFree);
168 rv = (void *)cbdataAlloc (ESIVarState);
169 return rv;
170}
171
172void
173ESIVarState::operator delete (void *address)
174{
175 cbdataFree (address);
176}
177
924f73bc 178char *
179ESIVariableUserAgent::getProductVersion (char const *s)
180{
181 char const *t;
182 int len;
86c63190 183 t = index(s,'/');
924f73bc 184
185 if (!t || !*(++t))
86c63190 186 return xstrdup("");
924f73bc 187
86c63190 188 len = strcspn(t, " \r\n()<>@,;:\\\"/[]?={}");
924f73bc 189
86c63190 190 return xstrndup(t, len + 1);
924f73bc 191}
192
193ESIVariableQuery::ESIVariableQuery(char const *uri) : query (NULL), query_sz (0), query_elements (0), query_string (NULL)
194{
195 /* Count off the query elements */
196 char const *query_start = strchr (uri, '?');
197
198 if (query_start && query_start[1] != '\0' ) {
199 unsigned int n;
86c63190 200 query_string = xstrdup(query_start + 1);
924f73bc 201 query_elements = 1;
202 char const *query_pos = query_start + 1;
203
86c63190 204 while ((query_pos = strchr(query_pos, '&'))) {
924f73bc 205 ++query_elements;
206 ++query_pos;
207 }
208
209 query = (_query_elem *)memReallocBuf(query, query_elements * sizeof (struct _query_elem),
210 &query_sz);
211 query_pos = query_start + 1;
212 n = 0;
213
214 while (query_pos) {
86c63190
AJ
215 char const *next = strchr(query_pos, '&');
216 char const *div = strchr(query_pos, '=');
924f73bc 217
218 if (next)
219 ++next;
220
221 assert (n < query_elements);
222
223 if (!div)
224 div = next;
225
226 if (!(div - query_pos + 1))
227 /* zero length between & and = or & and & */
228 continue;
229
86c63190 230 query[n].var = xstrndup(query_pos, div - query_pos + 1) ;
924f73bc 231
232 if (div == next) {
86c63190 233 query[n].val = xstrdup("");
924f73bc 234 } else {
86c63190 235 query[n].val = xstrndup(div + 1, next - div - 1);
924f73bc 236 }
237
238 query_pos = next;
239 ++n;
240 }
241 } else {
86c63190 242 query_string = xstrdup("");
924f73bc 243 }
244
245 if (query) {
246 unsigned int n = 0;
bf8fe701 247 debugs(86, 6, "esiVarStateNew: Parsed Query string: '" << uri << "'");
924f73bc 248
249 while (n < query_elements) {
bf8fe701 250 debugs(86, 6, "esiVarStateNew: Parsed Query element " << n + 1 << " '" << query[n].var << "'='" << query[n].val << "'");
924f73bc 251 ++n;
252 }
253 }
254}
255
256ESIVariableQuery::~ESIVariableQuery()
257{
258 if (query) {
259 unsigned int i;
260
261 for (i = 0; i < query_elements; ++i) {
262 safe_free(query[i].var);
263 safe_free(query[i].val);
264 }
265
266 memFreeBuf (query_sz, query);
267 }
268
269 safe_free (query_string);
270}
271
a5488e5d 272ESIVarState::ESIVarState(HttpHeader const *aHeader, char const *uri) :
f53969cc
SM
273 output(NULL),
274 hdr(hoReply)
924f73bc 275{
a5488e5d
AJ
276 memset(&flags, 0, sizeof(flags));
277
924f73bc 278 /* TODO: only grab the needed headers */
279 /* Note that as we pass these through to included requests, we
280 * cannot trim them */
4dd8a5fd 281 hdr.append(aHeader);
924f73bc 282
283 /* populate our variables trie with the available variables.
284 * Additional ones can be added during the parsing.
285 * If there is a lazy evaluation approach to this, consider it!
286 */
287 defaultVariable = new Variable;
288 addVariable ("HTTP_ACCEPT_LANGUAGE", 20, new ESIVariableLanguage);
289 addVariable ("HTTP_COOKIE", 11, new ESIVariableCookie);
290 addVariable ("HTTP_HOST", 9, new ESIVariableHost);
291 addVariable ("HTTP_REFERER", 12, new ESIVariableReferer);
292 addVariable ("HTTP_USER_AGENT", 15, new ESIVariableUserAgent(*this));
293 addVariable ("QUERY_STRING", 12, new ESIVariableQuery(uri));
294}
295
296void
30abd221 297ESIVarState::removeVariable (String const &name)
924f73bc 298{
9c175897 299 Variable *candidate = static_cast <Variable *>(variables.find (name.rawBuf(), name.size()));
924f73bc 300
301 if (candidate) {
302 /* XXX: remove me */
303 /* Note - this involves:
304 * extend libTrie to have a remove() call.
305 * delete from the vector.
306 * delete the object.
307 */
308 }
309}
310
311void
312ESIVarState::addVariable(char const *name, size_t len, Variable *aVariable)
313{
30abd221 314 String temp;
924f73bc 315 temp.limitInit (name, len);
316 removeVariable (temp);
317 variables.add(name, len, aVariable);
318 variablesForCleanup.push_back(aVariable);
319}
320
321ESIVariableUserAgent::~ESIVariableUserAgent()
322{
323 safe_free (browserversion);
324}
325
326ESIVariableUserAgent::ESIVariableUserAgent(ESIVarState &state)
327{
328 /* An example:
329 * User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705) */
330 /* Grr this Node is painful - RFC 2616 specifies that 'by convention' the tokens are in order of importance
331 * in identifying the product. According to the RFC the above should be interpreted as:
332 * Product - Mozilla version 4.0
26ac0430 333 * in comments - compatible; .... 3705
924f73bc 334 *
335 * Useing the RFC a more appropriate header would be
336 * User-Agent: MSIE/6.0 Mozilla/4.0 Windows-NT/5.1 .NET-CLR/1.0.3705
337 * or something similar.
338 *
26ac0430 339 * Because we can't parse under those rules and get real-world useful answers, we follow the following
924f73bc 340 * algorithm:
341 * if the string Windows appears in the header, the OS is WIN.
342 * If the string Mac appears in the header, the OS is MAC.
343 * If the string nix, or BSD appears in the header, the OS is UNIX.
26ac0430 344 * If the string MSIE appears in the header, the BROWSER is MSIE, and the version is the string from
924f73bc 345 * MSIE<sp> to the first ;, or end of string.
26ac0430 346 * If the String MSIE does not appear in the header, and MOZILLA does, we use the version from the
924f73bc 347 * /version field.
348 * if MOZILLA doesn't appear, the browser is set to OTHER.
349 * In future, this may be better implemented as a regexp.
350 */
351
4dd8a5fd 352 if (state.header().has(HDR_USER_AGENT)) {
353 char const *s = state.header().getStr(HDR_USER_AGENT);
924f73bc 354 UserOs = identifyOs(s);
355 char const *t, *t1;
356
357 /* Now the browser and version */
358
359 if ((t = strstr (s, "MSIE"))) {
360 browser = ESI_BROWSER_MSIE;
361 t = index (t, ' ');
362
363 if (!t)
86c63190 364 browserversion = xstrdup("");
924f73bc 365 else {
86c63190 366 t1 = index(t, ';');
924f73bc 367
368 if (!t1)
86c63190 369 browserversion = xstrdup(t + 1);
924f73bc 370 else
86c63190 371 browserversion = xstrndup(t + 1, t1-t);
924f73bc 372 }
373 } else if (strstr (s, "Mozilla")) {
374 browser = ESI_BROWSER_MOZILLA;
375 browserversion = getProductVersion(s);
376 } else {
377 browser = ESI_BROWSER_OTHER;
378 browserversion = getProductVersion(s);
379 }
380 } else {
381 UserOs = ESI_OS_OTHER;
382 browser = ESI_BROWSER_OTHER;
86c63190 383 browserversion = xstrdup("");
924f73bc 384 }
385}
386
387ESIVariableUserAgent::esiUserOs_t
388ESIVariableUserAgent::identifyOs(char const *s) const
389{
390 if (!s)
391 return ESI_OS_OTHER;
392
393 if (strstr (s, "Windows"))
394 return ESI_OS_WIN;
395 else if (strstr (s, "Mac"))
396 return ESI_OS_MAC;
397 else if (strstr (s, "nix") || strstr (s, "BSD"))
398 return ESI_OS_UNIX;
399 else
400 return ESI_OS_OTHER;
401}
402
403void
404ESIVariableCookie::eval (ESIVarState &state, char const *subref, char const *found_default) const
405{
406 const char *s = NULL;
407 state.cookieUsed();
408
4dd8a5fd 409 if (state.header().has(HDR_COOKIE)) {
924f73bc 410 if (!subref)
4dd8a5fd 411 s = state.header().getStr (HDR_COOKIE);
924f73bc 412 else {
30abd221 413 String S = state.header().getListMember (HDR_COOKIE, subref, ';');
924f73bc 414
415 if (S.size())
9c175897 416 ESISegment::ListAppend (state.getOutput(), S.rawBuf(), S.size());
924f73bc 417 else if (found_default)
418 ESISegment::ListAppend (state.getOutput(), found_default, strlen (found_default));
419 }
420 } else
421 s = found_default;
422
423 if (s)
424 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
425}
426
427void
428ESIVariableHost::eval (ESIVarState &state, char const *subref, char const *found_default) const
429{
430 const char *s = NULL;
431 state.hostUsed();
432
4dd8a5fd 433 if (!subref && state.header().has(HDR_HOST)) {
434 s = state.header().getStr (HDR_HOST);
924f73bc 435 } else
436 s = found_default;
437
438 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
439}
440
441void
442ESIVariableLanguage::eval (ESIVarState &state, char const *subref, char const *found_default) const
443{
444 char const *s = NULL;
445 state.languageUsed();
446
4dd8a5fd 447 if (state.header().has(HDR_ACCEPT_LANGUAGE)) {
924f73bc 448 if (!subref) {
30abd221 449 String S (state.header().getList (HDR_ACCEPT_LANGUAGE));
9c175897 450 ESISegment::ListAppend (state.getOutput(), S.rawBuf(), S.size());
924f73bc 451 } else {
4dd8a5fd 452 if (state.header().hasListMember (HDR_ACCEPT_LANGUAGE, subref, ',')) {
924f73bc 453 s = "true";
454 } else {
455 s = "false";
456 }
457
458 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
459 }
460 } else {
461 s = found_default;
462 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
463 }
464}
465
466void
467ESIVariableQuery::eval (ESIVarState &state, char const *subref, char const *found_default) const
468{
469 char const *s = NULL;
470
471 if (!subref)
472 s = queryString();
473 else {
474 unsigned int i = 0;
475
476 while (i < queryElements() && !s) {
477 if (!strcmp (subref, queryVector()[i].var))
478 s = queryVector()[i].val;
479
480 ++i;
481 }
482
483 if (!s)
484 s = found_default;
485 }
486
487 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
488}
489
490void
491ESIVariableReferer::eval (ESIVarState &state, char const *subref, char const *found_default) const
492{
493 const char *s = NULL;
494 state.refererUsed();
495
4dd8a5fd 496 if (!subref && state.header().has(HDR_REFERER))
497 s = state.header().getStr (HDR_REFERER);
924f73bc 498 else
499 s = found_default;
500
501 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
502}
503
504void
505ESIVariableUserAgent::eval (ESIVarState &state, char const *subref, char const *found_default) const
506{
507 char const *s = NULL;
508 state.useragentUsed();
509
4dd8a5fd 510 if (state.header().has(HDR_USER_AGENT)) {
924f73bc 511 if (!subref)
4dd8a5fd 512 s = state.header().getStr (HDR_USER_AGENT);
924f73bc 513 else {
514 if (!strcmp (subref, "os")) {
515 s = esiUserOs[UserOs];
516 } else if (!strcmp (subref, "browser")) {
517 s = esiBrowsers[browser];
518 } else if (!strcmp (subref, "version")) {
519 s = browserVersion();
520 } else
521 s = "";
522 }
523 } else
524 s = found_default;
525
526 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
527}
528
529/* thoughts on long term:
530 * get $
531 * get () handler
532 * hand off to handler.
533 * one handler for variables.
534 * one handler for each function.
535 */
536
537class ESIVariableProcessor;
538
539class ESIFunction
540{
541
542public:
543 static ESIFunction *GetFunction (char const *symbol, ESIVariableProcessor &);
544 ESIFunction(ESIVariableProcessor &);
545 void doIt();
546
547private:
548 ESIVariableProcessor &processor;
549
550};
551
552ESIFunction::ESIFunction(ESIVariableProcessor &aProcessor) : processor(aProcessor)
553{}
554
555ESIFunction *
556ESIFunction::GetFunction(char const *symbol, ESIVariableProcessor &aProcessor)
557{
558 if (*symbol == '(')
559 return new ESIFunction(aProcessor);
560
561 return NULL;
562}
563
564class ESIVariableProcessor
565{
566
567public:
568 ESIVariableProcessor(char *, ESISegment::Pointer &, Trie &, ESIVarState *);
569 ~ESIVariableProcessor();
570 void doIt();
571
572private:
573 bool validChar (char c);
b0365bd9 574 void eval (ESIVarState::Variable *var, char const *subref, char const *foundDefault );
924f73bc 575 void doFunction();
576 void identifyFunction();
577 char *string;
578 ESISegment::Pointer &output;
579 Trie &variables;
580 ESIVarState *varState;
581 int state;
582 size_t len;
583 size_t pos;
584 size_t var_pos;
585 size_t done_pos;
586 char * found_subref;
587 char *found_default;
588 ESIVarState::Variable *vartype;
589 ESIFunction *currentFunction;
590};
591
592void
b0365bd9 593ESIVariableProcessor::eval (ESIVarState::Variable *var, char const *subref, char const *foundDefault )
924f73bc 594{
595 assert (var);
596
b0365bd9
FC
597 if (!foundDefault)
598 foundDefault = "";
924f73bc 599
b0365bd9 600 var->eval (*varState, subref, foundDefault);
924f73bc 601}
602
603bool
604ESIVariableProcessor::validChar (char c)
605{
606 if (('A' <= c && c <= 'Z') ||
607 ('a' <= c && c <= 'z') ||
608 '_' == c || '-' == c)
609 return true;
610
611 return false;
612}
613
614ESIVarState::Variable *
615ESIVarState::GetVar(char const *symbol, int len)
616{
617 assert (symbol);
618
619 void *result = variables.find (symbol, len);
620
621 if (result)
622 return static_cast<Variable *>(result);
623
624 return defaultVariable;
625}
626
627void
628ESIVarState::doIt ()
629{
630 char *string = input->listToChar();
631 ESISegmentFreeList (input);
632 ESIVariableProcessor theProcessor(string, output, variables, this);
633 theProcessor.doIt();
634 safe_free(string);
635}
636
637#define LOOKFORSTART 0
638ESIVariableProcessor::ESIVariableProcessor(char *aString, ESISegment::Pointer &aSegment, Trie &aTrie, ESIVarState *aState) :
f53969cc
SM
639 string(aString), output (aSegment), variables(aTrie), varState (aState),
640 state(LOOKFORSTART), pos(0), var_pos(0), done_pos(0), found_subref (NULL),
641 found_default (NULL), currentFunction(NULL)
924f73bc 642{
643 len = strlen (string);
644 vartype = varState->GetVar("",0);
645}
646
647void
648ESIFunction::doIt()
649{}
650
651/* because we are only used to process:
652 * - include URL's
653 * - non-esi elements
654 * - choose clauses
655 * buffering is ok - we won't delay the start of async activity, or
656 * of output data preparation
657 */
658/* Should make these an enum or something...
659 */
660void
661ESIVariableProcessor::doFunction()
662{
663 if (!currentFunction)
664 return;
665
666 /* stay in here whilst operating */
667 while (pos < len && state)
668 switch (state) {
669
670 case 2: /* looking for variable name */
671
672 if (!validChar(string[pos])) {
673 /* not a variable name char */
674
675 if (pos - var_pos) {
676 vartype = varState->GetVar (string + var_pos, pos - var_pos);
677 }
678
679 state = 3;
680 } else {
681 ++pos;
682 }
683
684 break;
685
686 case 3: /* looking for variable subref, end bracket or default indicator */
687
688 if (string[pos] == ')') {
689 /* end of string */
690 eval(vartype, found_subref, found_default);
691 done_pos = ++pos;
692 safe_free(found_subref);
693 safe_free(found_default);
694 state = LOOKFORSTART;
695 } else if (!found_subref && !found_default && string[pos] == '{') {
bf8fe701 696 debugs(86, 6, "ESIVarStateDoIt: Subref of some sort");
924f73bc 697 /* subreference of some sort */
698 /* look for the entry name */
699 var_pos = ++pos;
700 state = 4;
701 } else if (!found_default && string[pos] == '|') {
bf8fe701 702 debugs(86, 6, "esiVarStateDoIt: Default present");
924f73bc 703 /* extract default value */
704 state = 5;
705 var_pos = ++pos;
706 } else {
707 /* unexpected char, not a variable after all */
bf8fe701 708 debugs(86, 6, "esiVarStateDoIt: unexpected char after varname");
924f73bc 709 state = LOOKFORSTART;
710 pos = done_pos + 2;
711 }
712
713 break;
714
715 case 4: /* looking for variable subref */
716
717 if (string[pos] == '}') {
718 /* end of subref */
719 found_subref = xstrndup (&string[var_pos], pos - var_pos + 1);
bf8fe701 720 debugs(86, 6, "esiVarStateDoIt: found end of variable subref '" << found_subref << "'");
924f73bc 721 state = 3;
722 ++pos;
723 } else if (!validChar (string[pos])) {
bf8fe701 724 debugs(86, 6, "esiVarStateDoIt: found invalid char in variable subref");
924f73bc 725 /* not a valid subref */
726 safe_free(found_subref);
727 state = LOOKFORSTART;
728 pos = done_pos + 2;
729 } else {
730 ++pos;
731 }
732
733 break;
734
735 case 5: /* looking for a default value */
736
737 if (string[pos] == '\'') {
738 /* begins with a quote */
bf8fe701 739 debugs(86, 6, "esiVarStateDoIt: found quoted default");
924f73bc 740 state = 6;
741 var_pos = ++pos;
742 } else {
743 /* doesn't */
bf8fe701 744 debugs(86, 6, "esiVarStateDoIt: found unquoted default");
924f73bc 745 state = 7;
746 ++pos;
747 }
748
749 break;
750
751 case 6: /* looking for a quote terminate default value */
752
753 if (string[pos] == '\'') {
754 /* end of default */
755 found_default = xstrndup (&string[var_pos], pos - var_pos + 1);
bf8fe701 756 debugs(86, 6, "esiVarStateDoIt: found end of quoted default '" << found_default << "'");
924f73bc 757 state = 3;
758 }
759
760 ++pos;
761 break;
762
763 case 7: /* looking for } terminate default value */
764
765 if (string[pos] == ')') {
766 /* end of default - end of variable*/
767 found_default = xstrndup (&string[var_pos], pos - var_pos + 1);
bf8fe701 768 debugs(86, 6, "esiVarStateDoIt: found end of variable (w/ unquoted default) '" << found_default << "'");
924f73bc 769 eval(vartype,found_subref, found_default);
770 done_pos = ++pos;
771 safe_free(found_default);
772 safe_free(found_subref);
773 state = LOOKFORSTART;
774 }
775
776 ++pos;
777 break;
778
779 default:
780 fatal("esiVarStateDoIt: unexpected state\n");
781 }
782}
783
784void
785ESIVariableProcessor::identifyFunction()
786{
787 delete currentFunction;
788 currentFunction = ESIFunction::GetFunction (&string[pos], *this);
789
790 if (!currentFunction) {
791 state = LOOKFORSTART;
792 } else {
793 state = 2; /* process a function */
794 /* advance past function name */
795 var_pos = ++pos;
796 }
797}
798
799void
800ESIVariableProcessor::doIt()
801{
802 assert (output == NULL);
803
804 while (pos < len) {
805 /* skipping pre-variables */
806
807 if (string[pos] != '$') {
808 ++pos;
809 } else {
810 if (pos - done_pos)
811 /* extract known plain text */
812 ESISegment::ListAppend (output, string + done_pos, pos - done_pos);
813
814 done_pos = pos;
815
816 ++pos;
817
818 identifyFunction();
819
820 doFunction();
821 }
822 }
823
824 /* pos-done_pos chars are ready to copy */
825 if (pos-done_pos)
826 ESISegment::ListAppend (output, string+done_pos, pos - done_pos);
827
828 safe_free (found_default);
829
830 safe_free (found_subref);
831}
832
833ESIVariableProcessor::~ESIVariableProcessor()
834{
835 delete currentFunction;
836}
837
924f73bc 838/* XXX FIXME: this should be comma delimited, no? */
839void
840ESIVarState::buildVary (HttpReply *rep)
841{
842 char tempstr[1024];
843 tempstr[0]='\0';
844
845 if (flags.language)
846 strcat (tempstr, "Accept-Language ");
847
848 if (flags.cookie)
849 strcat (tempstr, "Cookie ");
850
851 if (flags.host)
852 strcat (tempstr, "Host ");
853
854 if (flags.referer)
855 strcat (tempstr, "Referer ");
856
857 if (flags.useragent)
858 strcat (tempstr, "User-Agent ");
859
860 if (!tempstr[0])
861 return;
862
30abd221 863 String strVary (rep->header.getList (HDR_VARY));
924f73bc 864
9c175897 865 if (!strVary.size() || strVary[0] != '*') {
4dd8a5fd 866 rep->header.putStr (HDR_VARY, tempstr);
924f73bc 867 }
868}
30abd221 869