5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
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.
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.
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.
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.
33 #include "squid-old.h"
36 #include "ConfigParser.h"
37 #include "acl/Gadgets.h"
39 #include "Array.h" // really Vector
40 #include "acl/FilledChecklist.h"
41 #include "adaptation/Config.h"
42 #include "adaptation/Service.h"
43 #include "adaptation/AccessRule.h"
44 #include "adaptation/ServiceGroups.h"
45 #include "adaptation/History.h"
46 #include "HttpRequest.h"
49 bool Adaptation::Config::Enabled
= false;
50 char *Adaptation::Config::masterx_shared_name
= NULL
;
51 int Adaptation::Config::service_iteration_limit
= 16;
52 int Adaptation::Config::send_client_ip
= false;
53 int Adaptation::Config::send_username
= false;
54 int Adaptation::Config::use_indirect_client
= true;
55 Adaptation::Config::MetaHeaders
Adaptation::Config::metaHeaders
;
58 Adaptation::Config::MetaHeader::Value::~Value()
60 aclDestroyAclList(&aclList
);
63 Adaptation::Config::MetaHeader::Value::Pointer
64 Adaptation::Config::MetaHeader::addValue(const String
&value
)
66 Value::Pointer v
= new Value(value
);
72 Adaptation::Config::MetaHeader::match(HttpRequest
*request
, HttpReply
*reply
)
75 typedef Values::iterator VLI
;
76 ACLFilledChecklist
ch(NULL
, request
, NULL
);
78 ch
.reply
= HTTPMSGLOCK(reply
);
80 for (VLI i
= values
.begin(); i
!= values
.end(); ++i
) {
81 const int ret
= ch
.fastCheck((*i
)->aclList
);
82 debugs(93, 5, HERE
<< "Check for header name: " << name
<< ": " << (*i
)->value
83 <<", HttpRequest: " << request
<< " HttpReply: " << reply
<< " matched: " << ret
);
84 if (ret
== ACCESS_ALLOWED
)
85 return (*i
)->value
.termedBuf();
90 Adaptation::Config::MetaHeader::Pointer
91 Adaptation::Config::addMetaHeader(const String
&headerName
)
93 typedef MetaHeaders::iterator AMLI
;
94 for (AMLI i
= metaHeaders
.begin(); i
!= metaHeaders
.end(); ++i
) {
95 if ((*i
)->name
== headerName
)
99 MetaHeader::Pointer meta
= new MetaHeader(headerName
);
100 metaHeaders
.push_back(meta
);
105 Adaptation::ServiceConfig
*
106 Adaptation::Config::newServiceConfig() const
108 return new ServiceConfig();
112 Adaptation::Config::removeService(const String
& service
)
115 const Groups
& groups
= AllGroups();
116 for (unsigned int i
= 0; i
< groups
.size(); ) {
117 const ServiceGroupPointer group
= groups
[i
];
118 const ServiceGroup::Store
& services
= group
->services
;
119 typedef ServiceGroup::Store::const_iterator SGSI
;
120 for (SGSI it
= services
.begin(); it
!= services
.end(); ++it
) {
121 if (*it
== service
) {
122 group
->removedServices
.push_back(service
);
123 group
->services
.prune(service
);
124 debugs(93, 5, HERE
<< "adaptation service " << service
<<
125 " removed from group " << group
->id
);
129 if (services
.empty()) {
130 removeRule(group
->id
);
131 AllGroups().prune(group
);
139 Adaptation::Config::removeRule(const String
& id
)
141 typedef AccessRules::const_iterator ARI
;
142 const AccessRules
& rules
= AllRules();
143 for (ARI it
= rules
.begin(); it
!= rules
.end(); ++it
) {
144 AccessRule
* rule
= *it
;
145 if (rule
->groupId
== id
) {
146 debugs(93, 5, HERE
<< "removing access rules for:" << id
);
147 AllRules().prune(rule
);
155 Adaptation::Config::clear()
157 debugs(93, 3, HERE
<< "rules: " << AllRules().size() << ", groups: " <<
158 AllGroups().size() << ", services: " << serviceConfigs
.size());
159 typedef ServiceConfigs::const_iterator SCI
;
160 const ServiceConfigs
& configs
= serviceConfigs
;
161 for (SCI cfg
= configs
.begin(); cfg
!= configs
.end(); ++cfg
)
162 removeService((*cfg
)->key
);
163 serviceConfigs
.clean();
164 debugs(93, 3, HERE
<< "rules: " << AllRules().size() << ", groups: " <<
165 AllGroups().size() << ", services: " << serviceConfigs
.size());
169 Adaptation::Config::parseService()
171 ServiceConfigPointer cfg
= newServiceConfig();
173 fatalf("%s:%d: malformed adaptation service configuration",
174 cfg_filename
, config_lineno
);
176 serviceConfigs
.push_back(cfg
);
180 Adaptation::Config::freeService()
187 serviceConfigs
.clean();
193 Adaptation::Config::dumpService(StoreEntry
*entry
, const char *name
) const
195 typedef Services::iterator SCI
;
196 for (SCI i
= AllServices().begin(); i
!= AllServices().end(); ++i
) {
197 const ServiceConfig
&cfg
= (*i
)->cfg();
198 storeAppendPrintf(entry
, "%s " SQUIDSTRINGPH
"_%s %s %d " SQUIDSTRINGPH
"\n",
200 SQUIDSTRINGPRINT(cfg
.key
),
201 cfg
.methodStr(), cfg
.vectPointStr(), cfg
.bypass
,
202 SQUIDSTRINGPRINT(cfg
.uri
));
207 Adaptation::Config::finalize()
214 // create service reps from service configs
217 typedef ServiceConfigs::const_iterator VISCI
;
218 const ServiceConfigs
&configs
= serviceConfigs
;
219 for (VISCI i
= configs
.begin(); i
!= configs
.end(); ++i
) {
220 const ServiceConfigPointer cfg
= *i
;
221 if (FindService(cfg
->key
) != NULL
) {
222 debugs(93,0, "ERROR: Duplicate adaptation service name: " <<
224 continue; // TODO: make fatal
226 ServicePointer s
= createService(cfg
);
228 AllServices().push_back(s
);
233 debugs(93,3, HERE
<< "Created " << created
<< " adaptation services");
235 // services remember their configs; we do not have to
236 serviceConfigs
.clean();
241 template <class Collection
>
243 FinalizeEach(Collection
&collection
, const char *label
)
245 typedef typename
Collection::iterator CI
;
246 for (CI i
= collection
.begin(); i
!= collection
.end(); ++i
)
249 debugs(93,2, HERE
<< "Initialized " << collection
.size() << ' ' << label
);
253 Adaptation::Config::Finalize(bool enabled
)
256 debugs(93,1, "Adaptation support is " << (Enabled
? "on" : "off."));
258 FinalizeEach(AllServices(), "message adaptation services");
259 FinalizeEach(AllGroups(), "message adaptation service groups");
260 FinalizeEach(AllRules(), "message adaptation access rules");
264 Adaptation::Config::ParseMetaHeader(ConfigParser
&parser
)
267 const char *warnFor
[] = {
284 ConfigParser::ParseString(&name
);
285 ConfigParser::ParseQuotedString(&value
);
287 // TODO: Find a way to move this check to ICAP
288 for (int i
= 0; warnFor
[i
] != NULL
; ++i
) {
289 if (name
.caseCmp(warnFor
[i
]) == 0) {
290 fatalf("%s:%d: meta name \"%s\" is a reserved ICAP header name",
291 cfg_filename
, config_lineno
, name
.termedBuf());
295 MetaHeader::Pointer meta
= addMetaHeader(name
);
296 MetaHeader::Value::Pointer headValue
= meta
->addValue(value
);
297 aclParseAclList(parser
, &headValue
->aclList
);
301 Adaptation::Config::DumpMetaHeader(StoreEntry
*entry
, const char *name
)
303 typedef MetaHeaders::iterator AMLI
;
304 for (AMLI m
= metaHeaders
.begin(); m
!= metaHeaders
.end(); ++m
) {
305 typedef MetaHeader::Values::iterator VLI
;
306 for (VLI v
=(*m
)->values
.begin(); v
!= (*m
)->values
.end(); ++v
) {
307 storeAppendPrintf(entry
, "%s " SQUIDSTRINGPH
" %s",
308 name
, SQUIDSTRINGPRINT((*m
)->name
), ConfigParser::QuoteString((*v
)->value
));
309 dump_acl_list(entry
, (*v
)->aclList
);
310 storeAppendPrintf(entry
, "\n");
316 Adaptation::Config::FreeMetaHeader()
322 Adaptation::Config::ParseServiceSet()
324 Adaptation::Config::ParseServiceGroup(new ServiceSet
);
328 Adaptation::Config::ParseServiceChain()
330 Adaptation::Config::ParseServiceGroup(new ServiceChain
);
334 Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g
)
338 AllGroups().push_back(g
);
342 Adaptation::Config::FreeServiceGroups()
344 while (!AllGroups().empty()) {
345 // groups are refcounted so we do not explicitly delete them
346 AllGroups().pop_back();
351 Adaptation::Config::DumpServiceGroups(StoreEntry
*entry
, const char *name
)
353 typedef Groups::iterator GI
;
354 for (GI i
= AllGroups().begin(); i
!= AllGroups().end(); ++i
)
355 storeAppendPrintf(entry
, "%s " SQUIDSTRINGPH
"\n", name
, SQUIDSTRINGPRINT((*i
)->id
));
359 Adaptation::Config::ParseAccess(ConfigParser
&parser
)
362 ConfigParser::ParseString(&groupId
);
364 if (!(r
=FindRuleByGroupId(groupId
))) {
365 r
= new AccessRule(groupId
);
366 AllRules().push_back(r
);
372 Adaptation::Config::FreeAccess()
374 while (!AllRules().empty()) {
375 delete AllRules().back();
376 AllRules().pop_back();
381 Adaptation::Config::DumpAccess(StoreEntry
*entry
, const char *name
)
383 LOCAL_ARRAY(char, nom
, 64);
385 typedef AccessRules::iterator CI
;
386 for (CI i
= AllRules().begin(); i
!= AllRules().end(); ++i
) {
387 snprintf(nom
, 64, "%s " SQUIDSTRINGPH
, name
, SQUIDSTRINGPRINT((*i
)->groupId
));
388 dump_acl_access(entry
, nom
, (*i
)->acl
);
392 Adaptation::Config::Config()
394 // XXX: should we init members?
397 // XXX: this is called for ICAP and eCAP configs, but deals mostly
398 // with global arrays shared by those individual configs
399 Adaptation::Config::~Config()