]> git.ipfire.org Git - thirdparty/squid.git/blob - src/Notes.cc
Sync with trunk rev.13542
[thirdparty/squid.git] / src / Notes.cc
1 /*
2 * SQUID Web Proxy Cache http://www.squid-cache.org/
3 * ----------------------------------------------------------
4 *
5 * Squid is the result of efforts by numerous individuals from
6 * the Internet community; see the CONTRIBUTORS file for full
7 * details. Many organizations have provided support for Squid's
8 * development; see the SPONSORS file for full details. Squid is
9 * Copyrighted (C) 2001 by the Regents of the University of
10 * California; see the COPYRIGHT file for full details. Squid
11 * incorporates software developed and/or copyrighted by other
12 * sources; see the CREDITS file for full details.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
27 *
28 */
29
30 #include "squid.h"
31 #include "AccessLogEntry.h"
32 #include "acl/FilledChecklist.h"
33 #include "acl/Gadgets.h"
34 #include "client_side.h"
35 #include "ConfigParser.h"
36 #include "globals.h"
37 #include "HttpReply.h"
38 #include "HttpRequest.h"
39 #include "SquidConfig.h"
40 #include "Store.h"
41 #include "StrList.h"
42
43 #include <algorithm>
44 #include <string>
45
46 Note::Value::~Value()
47 {
48 aclDestroyAclList(&aclList);
49 }
50
51 Note::Value::Pointer
52 Note::addValue(const String &value)
53 {
54 Value::Pointer v = new Value(value);
55 values.push_back(v);
56 return v;
57 }
58
59 const char *
60 Note::match(HttpRequest *request, HttpReply *reply, const AccessLogEntry::Pointer &al)
61 {
62
63 typedef Values::iterator VLI;
64 ACLFilledChecklist ch(NULL, request, NULL);
65 ch.reply = reply;
66 if (reply)
67 HTTPMSGLOCK(ch.reply);
68
69 for (VLI i = values.begin(); i != values.end(); ++i ) {
70 const int ret= ch.fastCheck((*i)->aclList);
71 debugs(93, 5, HERE << "Check for header name: " << key << ": " << (*i)->value
72 <<", HttpRequest: " << request << " HttpReply: " << reply << " matched: " << ret);
73 if (ret == ACCESS_ALLOWED) {
74 if (al != NULL && (*i)->valueFormat != NULL) {
75 static MemBuf mb;
76 mb.reset();
77 (*i)->valueFormat->assemble(mb, al, 0);
78 return mb.content();
79 } else
80 return (*i)->value.termedBuf();
81 }
82 }
83 return NULL;
84 }
85
86 Note::Pointer
87 Notes::add(const String &noteKey)
88 {
89 typedef Notes::NotesList::iterator AMLI;
90 for (AMLI i = notes.begin(); i != notes.end(); ++i) {
91 if ((*i)->key == noteKey)
92 return (*i);
93 }
94
95 Note::Pointer note = new Note(noteKey);
96 notes.push_back(note);
97 return note;
98 }
99
100 Note::Pointer
101 Notes::parse(ConfigParser &parser)
102 {
103 String key = ConfigParser::NextToken();
104 ConfigParser::EnableMacros();
105 String value = ConfigParser::NextQuotedToken();
106 ConfigParser::DisableMacros();
107 bool valueWasQuoted = ConfigParser::LastTokenWasQuoted();
108 Note::Pointer note = add(key);
109 Note::Value::Pointer noteValue = note->addValue(value);
110
111 String label(key);
112 label.append('=');
113 label.append(value);
114 aclParseAclList(parser, &noteValue->aclList, label.termedBuf());
115 if (formattedValues && valueWasQuoted) {
116 noteValue->valueFormat = new Format::Format(descr ? descr : "Notes");
117 noteValue->valueFormat->parse(value.termedBuf());
118 }
119 if (blacklisted) {
120 for (int i = 0; blacklisted[i] != NULL; ++i) {
121 if (note->key.caseCmp(blacklisted[i]) == 0) {
122 fatalf("%s:%d: meta key \"%s\" is a reserved %s name",
123 cfg_filename, config_lineno, note->key.termedBuf(),
124 descr ? descr : "");
125 }
126 }
127 }
128
129 return note;
130 }
131
132 void
133 Notes::dump(StoreEntry *entry, const char *key)
134 {
135 typedef Notes::NotesList::iterator AMLI;
136 for (AMLI m = notes.begin(); m != notes.end(); ++m) {
137 typedef Note::Values::iterator VLI;
138 for (VLI v =(*m)->values.begin(); v != (*m)->values.end(); ++v ) {
139 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH " %s",
140 key, SQUIDSTRINGPRINT((*m)->key), ConfigParser::QuoteString((*v)->value));
141 dump_acl_list(entry, (*v)->aclList);
142 storeAppendPrintf(entry, "\n");
143 }
144 }
145 }
146
147 void
148 Notes::clean()
149 {
150 notes.clear();
151 }
152
153 NotePairs::~NotePairs()
154 {
155 while (!entries.empty()) {
156 delete entries.back();
157 entries.pop_back();
158 }
159 }
160
161 const char *
162 NotePairs::find(const char *noteKey, const char *sep) const
163 {
164 static String value;
165 value.clean();
166 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
167 if ((*i)->name.cmp(noteKey) == 0) {
168 if (value.size())
169 value.append(sep);
170 value.append((*i)->value);
171 }
172 }
173 return value.size() ? value.termedBuf() : NULL;
174 }
175
176 const char *
177 NotePairs::toString(const char *sep) const
178 {
179 static String value;
180 value.clean();
181 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
182 value.append((*i)->name);
183 value.append(": ");
184 value.append((*i)->value);
185 value.append(sep);
186 }
187 return value.size() ? value.termedBuf() : NULL;
188 }
189
190 const char *
191 NotePairs::findFirst(const char *noteKey) const
192 {
193 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
194 if ((*i)->name.cmp(noteKey) == 0)
195 return (*i)->value.termedBuf();
196 }
197 return NULL;
198 }
199
200 void
201 NotePairs::add(const char *key, const char *note)
202 {
203 entries.push_back(new NotePairs::Entry(key, note));
204 }
205
206 void
207 NotePairs::remove(const char *key)
208 {
209 std::vector<NotePairs::Entry *>::iterator i = entries.begin();
210 while (i != entries.end()) {
211 if ((*i)->name.cmp(key) == 0) {
212 delete *i;
213 i = entries.erase(i);
214 } else {
215 ++i;
216 }
217 }
218 }
219
220 void
221 NotePairs::addStrList(const char *key, const char *values)
222 {
223 String strValues(values);
224 const char *item;
225 const char *pos = NULL;
226 int ilen = 0;
227 while (strListGetItem(&strValues, ',', &item, &ilen, &pos)) {
228 String v;
229 v.append(item, ilen);
230 entries.push_back(new NotePairs::Entry(key, v.termedBuf()));
231 }
232 }
233
234 bool
235 NotePairs::hasPair(const char *key, const char *value) const
236 {
237 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
238 if ((*i)->name.cmp(key) == 0 && (*i)->value.cmp(value) == 0)
239 return true;
240 }
241 return false;
242 }
243
244 void
245 NotePairs::append(const NotePairs *src)
246 {
247 for (std::vector<NotePairs::Entry *>::const_iterator i = src->entries.begin(); i != src->entries.end(); ++i) {
248 entries.push_back(new NotePairs::Entry((*i)->name.termedBuf(), (*i)->value.termedBuf()));
249 }
250 }
251
252 void
253 NotePairs::appendNewOnly(const NotePairs *src)
254 {
255 for (std::vector<NotePairs::Entry *>::const_iterator i = src->entries.begin(); i != src->entries.end(); ++i) {
256 if (!hasPair((*i)->name.termedBuf(), (*i)->value.termedBuf()))
257 entries.push_back(new NotePairs::Entry((*i)->name.termedBuf(), (*i)->value.termedBuf()));
258 }
259 }
260
261 void
262 NotePairs::replaceOrAdd(const NotePairs *src)
263 {
264 for (std::vector<NotePairs::Entry *>::const_iterator i = src->entries.begin(); i != src->entries.end(); ++i) {
265 remove((*i)->name.termedBuf());
266 }
267 append(src);
268 }
269
270 NotePairs &
271 SyncNotes(AccessLogEntry &ale, HttpRequest &request)
272 {
273 // XXX: auth code only has access to HttpRequest being authenticated
274 // so we must handle the case where HttpRequest is set without ALE being set.
275
276 if (!ale.notes) {
277 if (!request.notes)
278 request.notes = new NotePairs;
279 ale.notes = request.notes;
280 } else {
281 assert(ale.notes == request.notes);
282 }
283 return *ale.notes;
284 }
285
286 void
287 UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const &helperNotes)
288 {
289 // Tag client connection if the helper responded with clt_conn_tag=tag.
290 if (const char *connTag = helperNotes.findFirst("clt_conn_tag")) {
291 if (csd)
292 csd->connectionTag(connTag);
293 }
294 if (!request.notes)
295 request.notes = new NotePairs;
296 request.notes->replaceOrAdd(&helperNotes);
297 }