]> git.ipfire.org Git - thirdparty/squid.git/blame - src/HttpHdrCc.cc
Summary: Fix bug #560.
[thirdparty/squid.git] / src / HttpHdrCc.cc
CommitLineData
7faf2bdb 1
2/*
62e76326 3 * $Id: HttpHdrCc.cc,v 1.25 2003/02/21 22:50:05 robertc Exp $
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.
e25c139f 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.
e25c139f 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 */
41static const HttpHeaderFieldAttrs CcAttrs[CC_ENUM_END] =
62e76326 42 {
43 {"public", (http_hdr_type)CC_PUBLIC},
44
45 {"private", (http_hdr_type)CC_PRIVATE},
46 {"no-cache", (http_hdr_type)CC_NO_CACHE},
47 {"no-store", (http_hdr_type)CC_NO_STORE},
48 {"no-transform", (http_hdr_type)CC_NO_TRANSFORM},
49 {"must-revalidate", (http_hdr_type)CC_MUST_REVALIDATE},
50 {"proxy-revalidate", (http_hdr_type)CC_PROXY_REVALIDATE},
51 {"only-if-cached", (http_hdr_type)CC_ONLY_IF_CACHED},
52 {"max-age", (http_hdr_type)CC_MAX_AGE},
53 {"s-maxage", (http_hdr_type)CC_S_MAXAGE},
54 {"max-stale", (http_hdr_type)CC_MAX_STALE},
55 {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */
56 };
57
de336bbe 58HttpHeaderFieldInfo *CcFieldsInfo = NULL;
7faf2bdb 59
e6ccf245 60http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader)
61{
62 aHeader = (http_hdr_cc_type)(++(int)aHeader);
63 return aHeader;
64}
65
66
b5107edb 67/* local prototypes */
5999b776 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 *
5999b776 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
5999b776 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;
119 assert(cc && str);
120
7faf2bdb 121 /* iterate through comma separated list */
62e76326 122
7faf2bdb 123 while (strListGetItem(str, ',', &item, &ilen, &pos)) {
62e76326 124 /* strip '=' statements @?@ */
125
126 if ((p = strchr(item, '=')) && (p - item < ilen))
127 ilen = p++ - item;
128
129 /* find type */
130 type = (http_hdr_cc_type ) httpHeaderIdByName(item, ilen,
131 CcFieldsInfo, CC_ENUM_END);
132
133 if (type < 0) {
134 debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, str->buf());
135 type = CC_OTHER;
136 }
137
138 if (EBIT_TEST(cc->mask, type)) {
139 if (type != CC_OTHER)
140 debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, str->buf());
141
142 CcFieldsInfo[type].stat.repCount++;
143
144 continue;
145 }
146
147 /* update mask */
148 EBIT_SET(cc->mask, type);
149
150 /* post-processing special cases */
151 switch (type) {
152
153 case CC_MAX_AGE:
154
155 if (!p || !httpHeaderParseInt(p, &cc->max_age)) {
156 debug(65, 2) ("cc: invalid max-age specs near '%s'\n", item);
157 cc->max_age = -1;
158 EBIT_CLR(cc->mask, type);
159 }
160
161 break;
162
163 case CC_S_MAXAGE:
164
165 if (!p || !httpHeaderParseInt(p, &cc->s_maxage)) {
166 debug(65, 2) ("cc: invalid s-maxage specs near '%s'\n", item);
167 cc->s_maxage = -1;
168 EBIT_CLR(cc->mask, type);
169 }
170
171 break;
172
173 case CC_MAX_STALE:
174
175 if (!p || !httpHeaderParseInt(p, &cc->max_stale)) {
176 debug(65, 2) ("cc: max-stale directive is valid without value\n");
177 cc->max_stale = -1;
178 }
179
180 break;
181
182 default:
183 /* note that we ignore most of '=' specs */
184 break;
185 }
7faf2bdb 186 }
62e76326 187
b5107edb 188 return cc->mask != 0;
7faf2bdb 189}
190
191void
192httpHdrCcDestroy(HttpHdrCc * cc)
193{
194 assert(cc);
db1cd23c 195 memFree(cc, MEM_HTTP_HDR_CC);
7faf2bdb 196}
197
198HttpHdrCc *
02922e76 199httpHdrCcDup(const HttpHdrCc * cc)
7faf2bdb 200{
201 HttpHdrCc *dup;
202 assert(cc);
203 dup = httpHdrCcCreate();
204 dup->mask = cc->mask;
205 dup->max_age = cc->max_age;
7e3ce7b9 206 dup->s_maxage = cc->s_maxage;
49ff0930 207 dup->max_stale = cc->max_stale;
7faf2bdb 208 return dup;
209}
210
211void
d76fcfa7 212httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p)
7faf2bdb 213{
214 http_hdr_cc_type flag;
215 int pcount = 0;
216 assert(cc && p);
62e76326 217
e6ccf245 218 for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) {
62e76326 219 if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) {
220
221 /* print option name */
222 packerPrintf(p, (pcount ? ", %s" : "%s"), CcFieldsInfo[flag].name.buf());
91274dd0 223
62e76326 224 /* handle options with values */
91274dd0 225
62e76326 226 if (flag == CC_MAX_AGE)
227 packerPrintf(p, "=%d", (int) cc->max_age);
91274dd0 228
62e76326 229 if (flag == CC_S_MAXAGE)
230 packerPrintf(p, "=%d", (int) cc->s_maxage);
7e3ce7b9 231
62e76326 232 if (flag == CC_MAX_STALE)
233 packerPrintf(p, "=%d", (int) cc->max_stale);
49ff0930 234
62e76326 235 pcount++;
236 }
7faf2bdb 237 }
238}
239
240void
02922e76 241httpHdrCcJoinWith(HttpHdrCc * cc, const HttpHdrCc * new_cc)
7faf2bdb 242{
243 assert(cc && new_cc);
62e76326 244
7faf2bdb 245 if (cc->max_age < 0)
62e76326 246 cc->max_age = new_cc->max_age;
247
7e3ce7b9 248 if (cc->s_maxage < 0)
62e76326 249 cc->s_maxage = new_cc->s_maxage;
250
49ff0930 251 if (cc->max_stale < 0)
62e76326 252 cc->max_stale = new_cc->max_stale;
253
7faf2bdb 254 cc->mask |= new_cc->mask;
255}
256
99edd1c3 257/* negative max_age will clean old max_Age setting */
258void
259httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age)
260{
261 assert(cc);
262 cc->max_age = max_age;
62e76326 263
99edd1c3 264 if (max_age >= 0)
62e76326 265 EBIT_SET(cc->mask, CC_MAX_AGE);
99edd1c3 266 else
62e76326 267 EBIT_CLR(cc->mask, CC_MAX_AGE);
99edd1c3 268}
269
7e3ce7b9 270/* negative s_maxage will clean old s-maxage setting */
271void
272httpHdrCcSetSMaxAge(HttpHdrCc * cc, int s_maxage)
273{
274 assert(cc);
275 cc->s_maxage = s_maxage;
62e76326 276
7e3ce7b9 277 if (s_maxage >= 0)
62e76326 278 EBIT_SET(cc->mask, CC_S_MAXAGE);
7e3ce7b9 279 else
62e76326 280 EBIT_CLR(cc->mask, CC_S_MAXAGE);
7e3ce7b9 281}
282
7faf2bdb 283void
284httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist)
285{
286 http_hdr_cc_type c;
287 assert(cc);
62e76326 288
e6ccf245 289 for (c = CC_PUBLIC; c < CC_ENUM_END; ++c)
62e76326 290 if (EBIT_TEST(cc->mask, c))
291 statHistCount(hist, c);
7faf2bdb 292}
293
294void
295httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count)
296{
0cdcddb9 297 extern const HttpHeaderStat *dump_stat; /* argh! */
7faf2bdb 298 const int id = (int) val;
299 const int valid_id = id >= 0 && id < CC_ENUM_END;
528b2c61 300 const char *name = valid_id ? CcFieldsInfo[id].name.buf() : "INVALID";
62e76326 301
7faf2bdb 302 if (count || valid_id)
62e76326 303 storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
304 id, name, count, xdiv(count, dump_stat->ccParsedCount));
7faf2bdb 305}