]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/Config.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / adaptation / Config.cc
CommitLineData
64bdef96
AR
1
2/*
262a0e14 3 * $Id$
64bdef96
AR
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
26ac0430 21 *
64bdef96
AR
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26ac0430 26 *
64bdef96
AR
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 */
32
582c2af2 33#include "squid.h"
71be37e0 34#include "acl/FilledChecklist.h"
582c2af2
FC
35#include "acl/Gadgets.h"
36#include "adaptation/AccessRule.h"
64bdef96 37#include "adaptation/Config.h"
582c2af2 38#include "adaptation/History.h"
64bdef96 39#include "adaptation/Service.h"
62c7f90e 40#include "adaptation/ServiceGroups.h"
582c2af2
FC
41#include "Array.h"
42#include "ConfigParser.h"
43#include "globals.h"
44#include "HttpReply.h"
71be37e0 45#include "HttpRequest.h"
582c2af2
FC
46#include "Store.h"
47#include "structs.h"
64bdef96 48
8f361c50 49bool Adaptation::Config::Enabled = false;
3ff65596 50char *Adaptation::Config::masterx_shared_name = NULL;
a22e6cd3 51int Adaptation::Config::service_iteration_limit = 16;
22fff3bf
AR
52int Adaptation::Config::send_client_ip = false;
53int Adaptation::Config::send_username = false;
54int Adaptation::Config::use_indirect_client = true;
71be37e0
CT
55Adaptation::Config::MetaHeaders Adaptation::Config::metaHeaders;
56
71be37e0
CT
57Adaptation::Config::MetaHeader::Value::~Value()
58{
59 aclDestroyAclList(&aclList);
60}
61
71ee0835 62Adaptation::Config::MetaHeader::Value::Pointer
71be37e0
CT
63Adaptation::Config::MetaHeader::addValue(const String &value)
64{
65 Value::Pointer v = new Value(value);
66 values.push_back(v);
67 return v;
68}
69
70const char *
71Adaptation::Config::MetaHeader::match(HttpRequest *request, HttpReply *reply)
72{
73
74 typedef Values::iterator VLI;
75 ACLFilledChecklist ch(NULL, request, NULL);
76 if (reply)
77 ch.reply = HTTPMSGLOCK(reply);
78
79 for (VLI i = values.begin(); i != values.end(); ++i ) {
71ee0835 80 const int ret= ch.fastCheck((*i)->aclList);
71be37e0
CT
81 debugs(93, 5, HERE << "Check for header name: " << name << ": " << (*i)->value
82 <<", HttpRequest: " << request << " HttpReply: " << reply << " matched: " << ret);
83 if (ret == ACCESS_ALLOWED)
84 return (*i)->value.termedBuf();
85 }
86 return NULL;
87}
88
71ee0835 89Adaptation::Config::MetaHeader::Pointer
71be37e0
CT
90Adaptation::Config::addMetaHeader(const String &headerName)
91{
92 typedef MetaHeaders::iterator AMLI;
71ee0835 93 for (AMLI i = metaHeaders.begin(); i != metaHeaders.end(); ++i) {
71be37e0
CT
94 if ((*i)->name == headerName)
95 return (*i);
96 }
97
98 MetaHeader::Pointer meta = new MetaHeader(headerName);
99 metaHeaders.push_back(meta);
100 return meta;
101}
8f361c50 102
e1e90d26
AR
103Adaptation::ServiceConfig*
104Adaptation::Config::newServiceConfig() const
105{
106 return new ServiceConfig();
107}
108
7e8c4ee9
CT
109void
110Adaptation::Config::removeService(const String& service)
111{
112 removeRule(service);
113 const Groups& groups = AllGroups();
114 for (unsigned int i = 0; i < groups.size(); ) {
115 const ServiceGroupPointer group = groups[i];
116 const ServiceGroup::Store& services = group->services;
117 typedef ServiceGroup::Store::const_iterator SGSI;
118 for (SGSI it = services.begin(); it != services.end(); ++it) {
119 if (*it == service) {
120 group->removedServices.push_back(service);
121 group->services.prune(service);
208c88d5 122 debugs(93, 5, HERE << "adaptation service " << service <<
7e8c4ee9
CT
123 " removed from group " << group->id);
124 break;
125 }
126 }
127 if (services.empty()) {
128 removeRule(group->id);
129 AllGroups().prune(group);
130 } else {
131 ++i;
132 }
133 }
134}
135
136void
137Adaptation::Config::removeRule(const String& id)
138{
139 typedef AccessRules::const_iterator ARI;
140 const AccessRules& rules = AllRules();
141 for (ARI it = rules.begin(); it != rules.end(); ++it) {
142 AccessRule* rule = *it;
143 if (rule->groupId == id) {
144 debugs(93, 5, HERE << "removing access rules for:" << id);
145 AllRules().prune(rule);
146 delete (rule);
147 break;
148 }
149 }
150}
151
152void
153Adaptation::Config::clear()
154{
155 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
156 AllGroups().size() << ", services: " << serviceConfigs.size());
157 typedef ServiceConfigs::const_iterator SCI;
158 const ServiceConfigs& configs = serviceConfigs;
159 for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg)
160 removeService((*cfg)->key);
161 serviceConfigs.clean();
162 debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " <<
163 AllGroups().size() << ", services: " << serviceConfigs.size());
164}
165
64bdef96
AR
166void
167Adaptation::Config::parseService()
168{
e1e90d26 169 ServiceConfigPointer cfg = newServiceConfig();
a22e6cd3
AR
170 if (!cfg->parse()) {
171 fatalf("%s:%d: malformed adaptation service configuration",
e1381638 172 cfg_filename, config_lineno);
a22e6cd3 173 }
64bdef96
AR
174 serviceConfigs.push_back(cfg);
175}
176
177void
178Adaptation::Config::freeService()
179{
76fc7e57
AJ
180 FreeAccess();
181 FreeServiceGroups();
182
183 DetachServices();
184
e1e90d26 185 serviceConfigs.clean();
71be37e0
CT
186
187 FreeMetaHeader();
64bdef96
AR
188}
189
190void
191Adaptation::Config::dumpService(StoreEntry *entry, const char *name) const
192{
193 typedef Services::iterator SCI;
194 for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) {
195 const ServiceConfig &cfg = (*i)->cfg();
b4197865 196 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "_%s %s %d " SQUIDSTRINGPH "\n",
af6a12ee
AJ
197 name,
198 SQUIDSTRINGPRINT(cfg.key),
199 cfg.methodStr(), cfg.vectPointStr(), cfg.bypass,
200 SQUIDSTRINGPRINT(cfg.uri));
64bdef96
AR
201 }
202}
203
7e8c4ee9 204bool
64bdef96
AR
205Adaptation::Config::finalize()
206{
7e8c4ee9
CT
207 if (!onoff) {
208 clear();
209 return false;
210 }
211
64bdef96 212 // create service reps from service configs
e1e90d26
AR
213 int created = 0;
214
215 typedef ServiceConfigs::const_iterator VISCI;
216 const ServiceConfigs &configs = serviceConfigs;
62c7f90e 217 for (VISCI i = configs.begin(); i != configs.end(); ++i) {
e1e90d26
AR
218 const ServiceConfigPointer cfg = *i;
219 if (FindService(cfg->key) != NULL) {
fa84c01d 220 debugs(93, DBG_CRITICAL, "ERROR: Duplicate adaptation service name: " <<
e1e90d26 221 cfg->key);
26ac0430
AJ
222 continue; // TODO: make fatal
223 }
e1e90d26
AR
224 ServicePointer s = createService(cfg);
225 if (s != NULL) {
62c7f90e 226 AllServices().push_back(s);
742a021b 227 ++created;
e1e90d26 228 }
64bdef96
AR
229 }
230
e1e90d26
AR
231 debugs(93,3, HERE << "Created " << created << " adaptation services");
232
233 // services remember their configs; we do not have to
234 serviceConfigs.clean();
7e8c4ee9 235 return true;
64bdef96
AR
236}
237
62c7f90e
AR
238// poor man for_each
239template <class Collection>
240static void
241FinalizeEach(Collection &collection, const char *label)
64bdef96 242{
62c7f90e
AR
243 typedef typename Collection::iterator CI;
244 for (CI i = collection.begin(); i != collection.end(); ++i)
245 (*i)->finalize();
64bdef96 246
192378eb 247 debugs(93,2, HERE << "Initialized " << collection.size() << ' ' << label);
64bdef96
AR
248}
249
250void
8f361c50 251Adaptation::Config::Finalize(bool enabled)
64bdef96 252{
8f361c50 253 Enabled = enabled;
e0236918 254 debugs(93, DBG_IMPORTANT, "Adaptation support is " << (Enabled ? "on" : "off."));
8f361c50 255
62c7f90e
AR
256 FinalizeEach(AllServices(), "message adaptation services");
257 FinalizeEach(AllGroups(), "message adaptation service groups");
258 FinalizeEach(AllRules(), "message adaptation access rules");
259}
64bdef96 260
71be37e0
CT
261void
262Adaptation::Config::ParseMetaHeader(ConfigParser &parser)
263{
264 String name, value;
265 const char *warnFor[] = {
266 "Methods",
267 "Service",
268 "ISTag",
269 "Encapsulated",
270 "Opt-body-type",
271 "Max-Connections",
272 "Options-TTL",
273 "Date",
274 "Service-ID",
275 "Allow",
276 "Preview",
277 "Transfer-Preview",
278 "Transfer-Ignore",
279 "Transfer-Complete",
280 NULL
281 };
282 ConfigParser::ParseString(&name);
283 ConfigParser::ParseQuotedString(&value);
284
285 // TODO: Find a way to move this check to ICAP
742a021b 286 for (int i = 0; warnFor[i] != NULL; ++i) {
71be37e0
CT
287 if (name.caseCmp(warnFor[i]) == 0) {
288 fatalf("%s:%d: meta name \"%s\" is a reserved ICAP header name",
289 cfg_filename, config_lineno, name.termedBuf());
290 }
291 }
292
293 MetaHeader::Pointer meta = addMetaHeader(name);
294 MetaHeader::Value::Pointer headValue = meta->addValue(value);
295 aclParseAclList(parser, &headValue->aclList);
296}
297
298void
299Adaptation::Config::DumpMetaHeader(StoreEntry *entry, const char *name)
300{
301 typedef MetaHeaders::iterator AMLI;
71ee0835 302 for (AMLI m = metaHeaders.begin(); m != metaHeaders.end(); ++m) {
71be37e0
CT
303 typedef MetaHeader::Values::iterator VLI;
304 for (VLI v =(*m)->values.begin(); v != (*m)->values.end(); ++v ) {
71ee0835 305 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH " %s",
71be37e0
CT
306 name, SQUIDSTRINGPRINT((*m)->name), ConfigParser::QuoteString((*v)->value));
307 dump_acl_list(entry, (*v)->aclList);
308 storeAppendPrintf(entry, "\n");
71ee0835
A
309 }
310 }
71be37e0
CT
311}
312
71ee0835 313void
71be37e0
CT
314Adaptation::Config::FreeMetaHeader()
315{
316 metaHeaders.clean();
317}
318
64bdef96 319void
62c7f90e 320Adaptation::Config::ParseServiceSet()
64bdef96 321{
a22e6cd3
AR
322 Adaptation::Config::ParseServiceGroup(new ServiceSet);
323}
324
325void
326Adaptation::Config::ParseServiceChain()
327{
328 Adaptation::Config::ParseServiceGroup(new ServiceChain);
329}
330
331void
332Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g)
333{
334 assert(g != NULL);
62c7f90e
AR
335 g->parse();
336 AllGroups().push_back(g);
64bdef96
AR
337}
338
339void
a22e6cd3 340Adaptation::Config::FreeServiceGroups()
64bdef96 341{
62c7f90e 342 while (!AllGroups().empty()) {
a22e6cd3 343 // groups are refcounted so we do not explicitly delete them
b6b637eb
AR
344 AllGroups().pop_back();
345 }
64bdef96
AR
346}
347
348void
a22e6cd3 349Adaptation::Config::DumpServiceGroups(StoreEntry *entry, const char *name)
64bdef96 350{
62c7f90e
AR
351 typedef Groups::iterator GI;
352 for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i)
2c1fd837 353 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id));
62c7f90e 354}
64bdef96 355
62c7f90e
AR
356void
357Adaptation::Config::ParseAccess(ConfigParser &parser)
358{
287bbe9a
CT
359 String groupId;
360 ConfigParser::ParseString(&groupId);
361 AccessRule *r;
899fad67 362 if (!(r=FindRuleByGroupId(groupId))) {
af6a12ee
AJ
363 r = new AccessRule(groupId);
364 AllRules().push_back(r);
899fad67 365 }
62c7f90e 366 r->parse(parser);
62c7f90e 367}
64bdef96
AR
368
369void
62c7f90e 370Adaptation::Config::FreeAccess()
64bdef96 371{
62c7f90e
AR
372 while (!AllRules().empty()) {
373 delete AllRules().back();
374 AllRules().pop_back();
b6b637eb 375 }
64bdef96
AR
376}
377
378void
62c7f90e 379Adaptation::Config::DumpAccess(StoreEntry *entry, const char *name)
64bdef96
AR
380{
381 LOCAL_ARRAY(char, nom, 64);
382
62c7f90e
AR
383 typedef AccessRules::iterator CI;
384 for (CI i = AllRules().begin(); i != AllRules().end(); ++i) {
2c1fd837 385 snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId));
62c7f90e 386 dump_acl_access(entry, nom, (*i)->acl);
b6b637eb 387 }
64bdef96
AR
388}
389
390Adaptation::Config::Config()
391{
392 // XXX: should we init members?
393}
394
26ac0430 395// XXX: this is called for ICAP and eCAP configs, but deals mostly
62c7f90e 396// with global arrays shared by those individual configs
64bdef96
AR
397Adaptation::Config::~Config()
398{
62c7f90e 399 freeService();
64bdef96 400}