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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors