]> git.ipfire.org Git - thirdparty/squid.git/blame - src/HttpHdrCc.cc
Verified and converted more String users.
[thirdparty/squid.git] / src / HttpHdrCc.cc
CommitLineData
7faf2bdb 1
2/*
262a0e14 3 * $Id$
7faf2bdb 4 *
5 * DEBUG: section 65 HTTP Cache Control Header
6 * AUTHOR: Alex Rousskov
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
7faf2bdb 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
7faf2bdb 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
26ac0430 24 *
7faf2bdb 25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
26ac0430 29 *
7faf2bdb 30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
7faf2bdb 33 *
34 */
35
36#include "squid.h"
e6ccf245 37#include "Store.h"
38#include "HttpHeader.h"
7faf2bdb 39
de336bbe 40/* this table is used for parsing cache control header */
26ac0430
AJ
41static const HttpHeaderFieldAttrs CcAttrs[CC_ENUM_END] = {
42 {"public", (http_hdr_type)CC_PUBLIC},
62e76326 43
26ac0430
AJ
44 {"private", (http_hdr_type)CC_PRIVATE},
45 {"no-cache", (http_hdr_type)CC_NO_CACHE},
46 {"no-store", (http_hdr_type)CC_NO_STORE},
47 {"no-transform", (http_hdr_type)CC_NO_TRANSFORM},
48 {"must-revalidate", (http_hdr_type)CC_MUST_REVALIDATE},
49 {"proxy-revalidate", (http_hdr_type)CC_PROXY_REVALIDATE},
50 {"only-if-cached", (http_hdr_type)CC_ONLY_IF_CACHED},
51 {"max-age", (http_hdr_type)CC_MAX_AGE},
52 {"s-maxage", (http_hdr_type)CC_S_MAXAGE},
53 {"max-stale", (http_hdr_type)CC_MAX_STALE},
54 {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */
55};
62e76326 56
de336bbe 57HttpHeaderFieldInfo *CcFieldsInfo = NULL;
7faf2bdb 58
e6ccf245 59http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader)
60{
1f1ae50a 61 int tmp = (int)aHeader;
62 aHeader = (http_hdr_cc_type)(++tmp);
e6ccf245 63 return aHeader;
64}
65
66
b5107edb 67/* local prototypes */
30abd221 68static int httpHdrCcParseInit(HttpHdrCc * cc, const String * str);
7faf2bdb 69
70
71/* module initialization */
72
73void
9bc73deb 74httpHdrCcInitModule(void)
7faf2bdb 75{
de336bbe 76 CcFieldsInfo = httpHeaderBuildFieldsInfo(CcAttrs, CC_ENUM_END);
77}
78
79void
9bc73deb 80httpHdrCcCleanModule(void)
de336bbe 81{
82 httpHeaderDestroyFieldsInfo(CcFieldsInfo, CC_ENUM_END);
83 CcFieldsInfo = NULL;
7faf2bdb 84}
85
86/* implementation */
87
88HttpHdrCc *
9bc73deb 89httpHdrCcCreate(void)
7faf2bdb 90{
e6ccf245 91 HttpHdrCc *cc = (HttpHdrCc *)memAllocate(MEM_HTTP_HDR_CC);
49ff0930 92 cc->max_age = cc->s_maxage = cc->max_stale = -1;
7faf2bdb 93 return cc;
94}
95
96/* creates an cc object from a 0-terminating string */
97HttpHdrCc *
30abd221 98httpHdrCcParseCreate(const String * str)
7faf2bdb 99{
100 HttpHdrCc *cc = httpHdrCcCreate();
62e76326 101
b5107edb 102 if (!httpHdrCcParseInit(cc, str)) {
62e76326 103 httpHdrCcDestroy(cc);
104 cc = NULL;
b5107edb 105 }
62e76326 106
7faf2bdb 107 return cc;
108}
109
110/* parses a 0-terminating string and inits cc */
b5107edb 111static int
30abd221 112httpHdrCcParseInit(HttpHdrCc * cc, const String * str)
7faf2bdb 113{
114 const char *item;
115 const char *p; /* '=' parameter */
116 const char *pos = NULL;
e6ccf245 117 http_hdr_cc_type type;
7faf2bdb 118 int ilen;
1b2e9616 119 int nlen;
7faf2bdb 120 assert(cc && str);
121
7faf2bdb 122 /* iterate through comma separated list */
62e76326 123
7faf2bdb 124 while (strListGetItem(str, ',', &item, &ilen, &pos)) {
1b2e9616 125 /* isolate directive name */
62e76326 126
1b2e9616 127 if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen))
128 nlen = p++ - item;
129 else
130 nlen = ilen;
62e76326 131
132 /* find type */
30abd221 133 type = (http_hdr_cc_type ) httpHeaderIdByName(item, nlen,
134 CcFieldsInfo, CC_ENUM_END);
62e76326 135
136 if (type < 0) {
99524de7 137 debugs(65, 2, "hdr cc: unknown cache-directive: near '" << item << "' in '" << str->unsafeBuf() << "'");
62e76326 138 type = CC_OTHER;
139 }
140
141 if (EBIT_TEST(cc->mask, type)) {
142 if (type != CC_OTHER)
99524de7 143 debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str->unsafeBuf() << "'");
62e76326 144
145 CcFieldsInfo[type].stat.repCount++;
146
147 continue;
148 }
149
150 /* update mask */
151 EBIT_SET(cc->mask, type);
152
153 /* post-processing special cases */
154 switch (type) {
155
156 case CC_MAX_AGE:
157
158 if (!p || !httpHeaderParseInt(p, &cc->max_age)) {
bf8fe701 159 debugs(65, 2, "cc: invalid max-age specs near '" << item << "'");
62e76326 160 cc->max_age = -1;
161 EBIT_CLR(cc->mask, type);
162 }
163
164 break;
165
166 case CC_S_MAXAGE:
167
168 if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) {
bf8fe701 169 debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'");
62e76326 170 cc->s_maxage = -1;
171 EBIT_CLR(cc->mask, type);
172 }
173
174 break;
175
176 case CC_MAX_STALE:
177
178 if (!p || !httpHeaderParseInt(p, &cc->max_stale)) {
bf8fe701 179 debugs(65, 2, "cc: max-stale directive is valid without value");
62e76326 180 cc->max_stale = -1;
181 }
182
183 break;
184
1b2e9616 185 case CC_OTHER:
186
187 if (cc->other.size())
188 cc->other.append(", ");
189
190 cc->other.append(item, ilen);
191
192 break;
193
62e76326 194 default:
1b2e9616 195 /* note that we ignore most of '=' specs (RFCVIOLATION) */
62e76326 196 break;
197 }
7faf2bdb 198 }
62e76326 199
b5107edb 200 return cc->mask != 0;
7faf2bdb 201}
202
203void
204httpHdrCcDestroy(HttpHdrCc * cc)
205{
206 assert(cc);
1b2e9616 207
99524de7 208 if (cc->other.unsafeBuf())
30abd221 209 cc->other.clean();
1b2e9616 210
db1cd23c 211 memFree(cc, MEM_HTTP_HDR_CC);
7faf2bdb 212}
213
214HttpHdrCc *
02922e76 215httpHdrCcDup(const HttpHdrCc * cc)
7faf2bdb 216{
217 HttpHdrCc *dup;
218 assert(cc);
219 dup = httpHdrCcCreate();
220 dup->mask = cc->mask;
221 dup->max_age = cc->max_age;
7e3ce7b9 222 dup->s_maxage = cc->s_maxage;
49ff0930 223 dup->max_stale = cc->max_stale;
7faf2bdb 224 return dup;
225}
226
227void
d76fcfa7 228httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p)
7faf2bdb 229{
230 http_hdr_cc_type flag;
231 int pcount = 0;
232 assert(cc && p);
62e76326 233
e6ccf245 234 for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) {
62e76326 235 if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) {
236
237 /* print option name */
99524de7 238 packerPrintf(p, (pcount ? ", %s" : "%s"), CcFieldsInfo[flag].name.unsafeBuf());
91274dd0 239
62e76326 240 /* handle options with values */
91274dd0 241
62e76326 242 if (flag == CC_MAX_AGE)
243 packerPrintf(p, "=%d", (int) cc->max_age);
91274dd0 244
62e76326 245 if (flag == CC_S_MAXAGE)
246 packerPrintf(p, "=%d", (int) cc->s_maxage);
7e3ce7b9 247
410c4eb1 248 if (flag == CC_MAX_STALE && cc->max_stale >= 0)
62e76326 249 packerPrintf(p, "=%d", (int) cc->max_stale);
49ff0930 250
62e76326 251 pcount++;
252 }
7faf2bdb 253 }
1b2e9616 254
255 if (cc->other.size())
99524de7 256 packerPrintf(p, (pcount ? ", %s" : "%s"), cc->other.unsafeBuf());
7faf2bdb 257}
258
99edd1c3 259/* negative max_age will clean old max_Age setting */
260void
261httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age)
262{
263 assert(cc);
264 cc->max_age = max_age;
62e76326 265
99edd1c3 266 if (max_age >= 0)
62e76326 267 EBIT_SET(cc->mask, CC_MAX_AGE);
99edd1c3 268 else
62e76326 269 EBIT_CLR(cc->mask, CC_MAX_AGE);
99edd1c3 270}
271
7e3ce7b9 272/* negative s_maxage will clean old s-maxage setting */
273void
274httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage)
275{
276 assert(cc);
277 cc->s_maxage = s_maxage;
62e76326 278
7e3ce7b9 279 if (s_maxage >= 0)
62e76326 280 EBIT_SET(cc->mask, CC_S_MAXAGE);
7e3ce7b9 281 else
62e76326 282 EBIT_CLR(cc->mask, CC_S_MAXAGE);
7e3ce7b9 283}
284
7faf2bdb 285void
286httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist)
287{
288 http_hdr_cc_type c;
289 assert(cc);
62e76326 290
e6ccf245 291 for (c = CC_PUBLIC; c < CC_ENUM_END; ++c)
62e76326 292 if (EBIT_TEST(cc->mask, c))
293 statHistCount(hist, c);
7faf2bdb 294}
295
296void
297httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
298{
0cdcddb9 299 extern const HttpHeaderStat *dump_stat; /* argh! */
7faf2bdb 300 const int id = (int) val;
301 const int valid_id = id >= 0 && id < CC_ENUM_END;
99524de7 302 const char *name = valid_id ? CcFieldsInfo[id].name.unsafeBuf() : "INVALID";
62e76326 303
7faf2bdb 304 if (count || valid_id)
62e76326 305 storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
306 id, name, count, xdiv(count, dump_stat->ccParsedCount));
7faf2bdb 307}