]> git.ipfire.org Git - thirdparty/squid.git/blob - src/Notes.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / Notes.cc
1 /*
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "AccessLogEntry.h"
11 #include "acl/FilledChecklist.h"
12 #include "acl/Gadgets.h"
13 #include "client_side.h"
14 #include "ConfigParser.h"
15 #include "globals.h"
16 #include "HttpReply.h"
17 #include "HttpRequest.h"
18 #include "SquidConfig.h"
19 #include "Store.h"
20 #include "StrList.h"
21
22 #include <algorithm>
23 #include <string>
24
25 Note::Value::~Value()
26 {
27 aclDestroyAclList(&aclList);
28 }
29
30 Note::Value::Pointer
31 Note::addValue(const String &value)
32 {
33 Value::Pointer v = new Value(value);
34 values.push_back(v);
35 return v;
36 }
37
38 const char *
39 Note::match(HttpRequest *request, HttpReply *reply, const AccessLogEntry::Pointer &al)
40 {
41
42 typedef Values::iterator VLI;
43 ACLFilledChecklist ch(NULL, request, NULL);
44 ch.reply = reply;
45 if (reply)
46 HTTPMSGLOCK(ch.reply);
47
48 for (VLI i = values.begin(); i != values.end(); ++i ) {
49 const int ret= ch.fastCheck((*i)->aclList);
50 debugs(93, 5, HERE << "Check for header name: " << key << ": " << (*i)->value
51 <<", HttpRequest: " << request << " HttpReply: " << reply << " matched: " << ret);
52 if (ret == ACCESS_ALLOWED) {
53 if (al != NULL && (*i)->valueFormat != NULL) {
54 static MemBuf mb;
55 mb.reset();
56 (*i)->valueFormat->assemble(mb, al, 0);
57 return mb.content();
58 } else
59 return (*i)->value.termedBuf();
60 }
61 }
62 return NULL;
63 }
64
65 Note::Pointer
66 Notes::add(const String &noteKey)
67 {
68 typedef Notes::NotesList::iterator AMLI;
69 for (AMLI i = notes.begin(); i != notes.end(); ++i) {
70 if ((*i)->key == noteKey)
71 return (*i);
72 }
73
74 Note::Pointer note = new Note(noteKey);
75 notes.push_back(note);
76 return note;
77 }
78
79 Note::Pointer
80 Notes::parse(ConfigParser &parser)
81 {
82 String key = ConfigParser::NextToken();
83 ConfigParser::EnableMacros();
84 String value = ConfigParser::NextQuotedToken();
85 ConfigParser::DisableMacros();
86 bool valueWasQuoted = ConfigParser::LastTokenWasQuoted();
87 Note::Pointer note = add(key);
88 Note::Value::Pointer noteValue = note->addValue(value);
89
90 String label(key);
91 label.append('=');
92 label.append(value);
93 aclParseAclList(parser, &noteValue->aclList, label.termedBuf());
94 if (formattedValues && valueWasQuoted) {
95 noteValue->valueFormat = new Format::Format(descr ? descr : "Notes");
96 noteValue->valueFormat->parse(value.termedBuf());
97 }
98 if (blacklisted) {
99 for (int i = 0; blacklisted[i] != NULL; ++i) {
100 if (note->key.caseCmp(blacklisted[i]) == 0) {
101 fatalf("%s:%d: meta key \"%s\" is a reserved %s name",
102 cfg_filename, config_lineno, note->key.termedBuf(),
103 descr ? descr : "");
104 }
105 }
106 }
107
108 return note;
109 }
110
111 void
112 Notes::dump(StoreEntry *entry, const char *key)
113 {
114 typedef Notes::NotesList::iterator AMLI;
115 for (AMLI m = notes.begin(); m != notes.end(); ++m) {
116 typedef Note::Values::iterator VLI;
117 for (VLI v =(*m)->values.begin(); v != (*m)->values.end(); ++v ) {
118 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH " %s",
119 key, SQUIDSTRINGPRINT((*m)->key), ConfigParser::QuoteString((*v)->value));
120 dump_acl_list(entry, (*v)->aclList);
121 storeAppendPrintf(entry, "\n");
122 }
123 }
124 }
125
126 void
127 Notes::clean()
128 {
129 notes.clear();
130 }
131
132 NotePairs::~NotePairs()
133 {
134 while (!entries.empty()) {
135 delete entries.back();
136 entries.pop_back();
137 }
138 }
139
140 const char *
141 NotePairs::find(const char *noteKey, const char *sep) const
142 {
143 static String value;
144 value.clean();
145 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
146 if ((*i)->name.cmp(noteKey) == 0) {
147 if (value.size())
148 value.append(sep);
149 value.append((*i)->value);
150 }
151 }
152 return value.size() ? value.termedBuf() : NULL;
153 }
154
155 const char *
156 NotePairs::toString(const char *sep) const
157 {
158 static String value;
159 value.clean();
160 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
161 value.append((*i)->name);
162 value.append(": ");
163 value.append((*i)->value);
164 value.append(sep);
165 }
166 return value.size() ? value.termedBuf() : NULL;
167 }
168
169 const char *
170 NotePairs::findFirst(const char *noteKey) const
171 {
172 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
173 if ((*i)->name.cmp(noteKey) == 0)
174 return (*i)->value.termedBuf();
175 }
176 return NULL;
177 }
178
179 void
180 NotePairs::add(const char *key, const char *note)
181 {
182 entries.push_back(new NotePairs::Entry(key, note));
183 }
184
185 void
186 NotePairs::remove(const char *key)
187 {
188 std::vector<NotePairs::Entry *>::iterator i = entries.begin();
189 while (i != entries.end()) {
190 if ((*i)->name.cmp(key) == 0) {
191 delete *i;
192 i = entries.erase(i);
193 } else {
194 ++i;
195 }
196 }
197 }
198
199 void
200 NotePairs::addStrList(const char *key, const char *values)
201 {
202 String strValues(values);
203 const char *item;
204 const char *pos = NULL;
205 int ilen = 0;
206 while (strListGetItem(&strValues, ',', &item, &ilen, &pos)) {
207 String v;
208 v.append(item, ilen);
209 entries.push_back(new NotePairs::Entry(key, v.termedBuf()));
210 }
211 }
212
213 bool
214 NotePairs::hasPair(const char *key, const char *value) const
215 {
216 for (std::vector<NotePairs::Entry *>::const_iterator i = entries.begin(); i != entries.end(); ++i) {
217 if ((*i)->name.cmp(key) == 0 && (*i)->value.cmp(value) == 0)
218 return true;
219 }
220 return false;
221 }
222
223 void
224 NotePairs::append(const NotePairs *src)
225 {
226 for (std::vector<NotePairs::Entry *>::const_iterator i = src->entries.begin(); i != src->entries.end(); ++i) {
227 entries.push_back(new NotePairs::Entry((*i)->name.termedBuf(), (*i)->value.termedBuf()));
228 }
229 }
230
231 void
232 NotePairs::appendNewOnly(const NotePairs *src)
233 {
234 for (std::vector<NotePairs::Entry *>::const_iterator i = src->entries.begin(); i != src->entries.end(); ++i) {
235 if (!hasPair((*i)->name.termedBuf(), (*i)->value.termedBuf()))
236 entries.push_back(new NotePairs::Entry((*i)->name.termedBuf(), (*i)->value.termedBuf()));
237 }
238 }
239
240 void
241 NotePairs::replaceOrAdd(const NotePairs *src)
242 {
243 for (std::vector<NotePairs::Entry *>::const_iterator i = src->entries.begin(); i != src->entries.end(); ++i) {
244 remove((*i)->name.termedBuf());
245 }
246 append(src);
247 }
248
249 NotePairs &
250 SyncNotes(AccessLogEntry &ale, HttpRequest &request)
251 {
252 // XXX: auth code only has access to HttpRequest being authenticated
253 // so we must handle the case where HttpRequest is set without ALE being set.
254
255 if (!ale.notes) {
256 if (!request.notes)
257 request.notes = new NotePairs;
258 ale.notes = request.notes;
259 } else {
260 assert(ale.notes == request.notes);
261 }
262 return *ale.notes;
263 }
264
265 void
266 UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const &helperNotes)
267 {
268 // Tag client connection if the helper responded with clt_conn_tag=tag.
269 if (const char *connTag = helperNotes.findFirst("clt_conn_tag")) {
270 if (csd)
271 csd->connectionTag(connTag);
272 }
273 if (!request.notes)
274 request.notes = new NotePairs;
275 request.notes->replaceOrAdd(&helperNotes);
276 }
277