VarState.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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
17 "WIN",
18 "MAC",
19 "UNIX",
20 "OTHER"
21};
22
23char const * esiBrowsers[]= {"MSIE",
24 "MOZILLA",
25 "OTHER"
26 };
27
29
30void
31ESIVarState::Variable::eval(ESIVarState &state, char const *, 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
39void
41{
42 flags.host = 1;
43}
44
45void
47{
48 flags.cookie = 1;
49}
50
51void
53{
54 flags.language = 1;
55}
56
57void
59{
60 flags.referer = 1;
61}
62
63void
65{
66 flags.useragent = 1;
67}
68
71{
72 return hdr;
73}
74
77{
78 return output;
79}
80
81char const *
83{
84 return query_string;
85}
86
87struct _query_elem const *
89 return query;
90}
91
92size_t const &
94{
95 return query_elements;
96}
97
98void
99ESIVarState::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 = nullptr;
112 debugs(86, 6, "ESIVarStateExtractList: Extracted list");
113 return rv;
114}
115
116char *
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 = nullptr;
138 hdr.clean();
139
140 while (!variablesForCleanup.empty()) {
141 delete variablesForCleanup.back();
142 variablesForCleanup.pop_back();
143 }
144
145 delete defaultVariable;
146}
147
148char *
150{
151 char const *t;
152 int len;
153 t = strchr(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
163ESIVariableQuery::ESIVariableQuery(char const *uri) : query (nullptr), query_sz (0), query_elements (0), query_string (nullptr)
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, '&'))) {
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
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
242ESIVarState::ESIVarState(HttpHeader const *aHeader, char const *uri) :
243 output(nullptr),
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
266void
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
281void
282ESIVarState::addVariable(char const *name, size_t len, Variable *aVariable)
283{
284 String temp;
285 temp.assign(name, len);
286 removeVariable (temp);
287 variables.add(name, len, aVariable);
288 variablesForCleanup.push_back(aVariable);
289}
290
292{
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 * Using 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"))) {
331 t = strchr(t, ' ');
332
333 if (!t)
335 else {
336 t1 = strchr(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")) {
346 } else {
349 }
350 } else {
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
373void
374ESIVariableCookie::eval (ESIVarState &state, char const *subref, char const *found_default) const
375{
376 const char *s = nullptr;
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
397void
398ESIVariableHost::eval (ESIVarState &state, char const *subref, char const *found_default) const
399{
400 const char *s = nullptr;
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
411void
412ESIVariableLanguage::eval (ESIVarState &state, char const *subref, char const *found_default) const
413{
414 char const *s = nullptr;
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
436void
437ESIVariableQuery::eval (ESIVarState &state, char const *subref, char const *found_default) const
438{
439 char const *s = nullptr;
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
460void
461ESIVariableReferer::eval (ESIVarState &state, char const *subref, char const *found_default) const
462{
463 const char *s = nullptr;
464 state.refererUsed();
465
466 if (!subref && state.header().has(Http::HdrType::REFERER))
468 else
469 s = found_default;
470
471 ESISegment::ListAppend (state.getOutput(), s, strlen (s));
472}
473
474void
475ESIVariableUserAgent::eval (ESIVarState &state, char const *subref, char const *found_default) const
476{
477 char const *s = nullptr;
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
512public:
513 static ESIFunction *GetFunction (char const *symbol, ESIVariableProcessor &);
515 void doIt();
516
517private:
519
520};
521
522ESIFunction::ESIFunction(ESIVariableProcessor &aProcessor) : processor(aProcessor)
523{}
524
526ESIFunction::GetFunction(char const *symbol, ESIVariableProcessor &aProcessor)
527{
528 if (*symbol == '(')
529 return new ESIFunction(aProcessor);
530
531 return nullptr;
532}
533
535{
536
537public:
540 void doIt();
541
542private:
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;
551 int state;
552 size_t len;
553 size_t pos;
554 size_t var_pos;
555 size_t done_pos;
560};
561
562void
563ESIVariableProcessor::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
573bool
575{
576 if (('A' <= c && c <= 'Z') ||
577 ('a' <= c && c <= 'z') ||
578 '_' == c || '-' == c)
579 return true;
580
581 return false;
582}
583
585ESIVarState::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
597void
599{
600 char *string = input->listToChar();
602 ESIVariableProcessor theProcessor(string, output, variables, this);
603 theProcessor.doIt();
604 safe_free(string);
605}
606
607#define LOOKFORSTART 0
608ESIVariableProcessor::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 (nullptr),
611 found_default (nullptr), currentFunction(nullptr)
612{
613 len = strlen (string);
614 vartype = varState->GetVar("",0);
615}
616
617void
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 */
630void
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
754void
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
769void
771{
772 assert (output == nullptr);
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: this should be comma delimited, no? */
809void
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
@ hoReply
Definition: HttpHeader.h:37
char const * esiBrowsers[]
Definition: VarState.cc:23
#define LOOKFORSTART
Definition: VarState.cc:607
CBDATA_CLASS_INIT(ESIVarState)
@ ESI_BROWSER_MOZILLA
Definition: VarState.h:24
@ ESI_BROWSER_OTHER
Definition: VarState.h:25
@ ESI_BROWSER_MSIE
Definition: VarState.h:23
#define assert(EX)
Definition: assert.h:17
ESIFunction(ESIVariableProcessor &)
Definition: VarState.cc:522
static ESIFunction * GetFunction(char const *symbol, ESIVariableProcessor &)
Definition: VarState.cc:526
void doIt()
Definition: VarState.cc:618
ESIVariableProcessor & processor
Definition: VarState.cc:518
static void ListAppend(Pointer &, char const *, size_t)
Definition: Segment.cc:120
char * listToChar() const
Definition: Segment.cc:81
virtual void eval(ESIVarState &state, char const *, char const *) const
Definition: VarState.cc:31
void removeVariable(String const &)
Definition: VarState.cc:267
ESISegment::Pointer input
Definition: VarState.h:61
void useragentUsed()
Definition: VarState.cc:64
Variable * GetVar(char const *s, int len)
Definition: VarState.cc:585
void cookieUsed()
Definition: VarState.cc:46
HttpHeader hdr
Definition: VarState.h:63
HttpHeader & header()
Definition: VarState.cc:70
void doIt()
Definition: VarState.cc:598
void refererUsed()
Definition: VarState.cc:58
char * extractChar()
Definition: VarState.cc:117
ESISegment::Pointer output
Definition: VarState.h:62
void languageUsed()
Definition: VarState.cc:52
void buildVary(HttpReply *rep)
Definition: VarState.cc:810
void hostUsed()
Definition: VarState.cc:40
ESIVarState(HttpHeader const *hdr, char const *uri)
Definition: VarState.cc:242
std::vector< Variable * > variablesForCleanup
Definition: VarState.h:96
ESISegment::Pointer extractList()
Definition: VarState.cc:107
ESISegment::Pointer & getOutput()
Definition: VarState.cc:76
void addVariable(char const *, size_t, Variable *)
Definition: VarState.cc:282
struct ESIVarState::@62 flags
Variable * defaultVariable
Definition: VarState.h:97
Trie variables
Definition: VarState.h:95
void feedData(const char *buf, size_t len)
Definition: VarState.cc:99
void eval(ESIVarState &state, char const *, char const *) const override
Definition: VarState.cc:374
void eval(ESIVarState &state, char const *, char const *) const override
Definition: VarState.cc:398
void eval(ESIVarState &state, char const *, char const *) const override
Definition: VarState.cc:412
bool validChar(char c)
Definition: VarState.cc:574
void eval(ESIVarState::Variable *var, char const *subref, char const *foundDefault)
Definition: VarState.cc:563
ESIVariableProcessor(char *, ESISegment::Pointer &, Trie &, ESIVarState *)
Definition: VarState.cc:608
ESISegment::Pointer & output
Definition: VarState.cc:548
ESIVarState::Variable * vartype
Definition: VarState.cc:558
ESIFunction * currentFunction
Definition: VarState.cc:559
ESIVarState * varState
Definition: VarState.cc:550
char const * queryString() const
Definition: VarState.cc:82
ESIVariableQuery(char const *uri)
Definition: VarState.cc:163
~ESIVariableQuery() override
Definition: VarState.cc:226
size_t query_sz
Definition: VarState.h:134
size_t query_elements
Definition: VarState.h:135
size_t const & queryElements() const
Definition: VarState.cc:93
struct _query_elem * query
Definition: VarState.h:133
void eval(ESIVarState &state, char const *, char const *) const override
Definition: VarState.cc:437
char * query_string
Definition: VarState.h:136
struct _query_elem const * queryVector() const
Definition: VarState.cc:88
void eval(ESIVarState &state, char const *, char const *) const override
Definition: VarState.cc:461
static char const * esiUserOs[]
Definition: VarState.h:155
ESIVariableUserAgent(ESIVarState &state)
Definition: VarState.cc:296
char const * browserVersion() const
Definition: VarState.h:163
esiUserOs_t identifyOs(char const *) const
Definition: VarState.cc:358
char * getProductVersion(char const *s)
Definition: VarState.cc:149
~ESIVariableUserAgent() override
Definition: VarState.cc:291
esiBrowser_t browser
Definition: VarState.h:167
void eval(ESIVarState &state, char const *, char const *) const override
Definition: VarState.cc:475
esiUserOs_t UserOs
Definition: VarState.h:166
void putStr(Http::HdrType id, const char *str)
Definition: HttpHeader.cc:996
SBuf getListMember(Http::HdrType id, const char *member, const char separator) const
Definition: HttpHeader.cc:929
String getList(Http::HdrType id) const
Definition: HttpHeader.cc:789
const char * getStr(Http::HdrType id) const
Definition: HttpHeader.cc:1164
int has(Http::HdrType id) const
Definition: HttpHeader.cc:938
void clean()
Definition: HttpHeader.cc:186
void append(const HttpHeader *src)
Definition: HttpHeader.cc:232
int hasListMember(Http::HdrType id, const char *member, const char separator) const
Definition: HttpHeader.cc:1663
HttpHeader header
Definition: Message.h:74
C * getRaw() const
Definition: RefCount.h:89
void assign(const char *str, int len)
Definition: String.cc:78
char const * rawBuf() const
Definition: SquidString.h:86
size_type size() const
Definition: SquidString.h:73
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
void ESISegmentFreeList(ESISegment::Pointer &head)
Definition: Segment.cc:19
void fatal(const char *message)
Definition: fatal.cc:28
void memFreeBuf(size_t size, void *)
Definition: minimal.cc:90
void * memReallocBuf(void *buf, size_t net_size, size_t *gross_size)
Definition: minimal.cc:53
@ ACCEPT_LANGUAGE
#define xstrdup
char * val
Definition: VarState.h:32
char * var
Definition: VarState.h:32
#define safe_free(x)
Definition: xalloc.h:73
char * xstrndup(const char *s, size_t n)
Definition: xstring.cc:56

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors