Notes.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 "http/Stream.h"
17 #include "HttpReply.h"
18 #include "HttpRequest.h"
19 #include "parser/Tokenizer.h"
20 #include "sbuf/StringConvert.h"
21 #include "SquidConfig.h"
22 #include "Store.h"
23 #include "StrList.h"
24 
25 #include <algorithm>
26 #include <string>
27 
29 {
31  delete valueFormat;
32 }
33 
34 Note::Value::Value(const char *aVal, const bool quoted, const char *descr, const Method m)
35  : aclList(nullptr), valueFormat(nullptr), theValue(aVal), theMethod(m)
36 {
37  if (quoted) {
38  valueFormat = new Format::Format(descr ? descr : "Notes");
39  if (!valueFormat->parse(theValue.c_str())) {
40  delete valueFormat;
41  SBuf exceptionMsg;
42  exceptionMsg.Printf("failed to parse annotation value %s", theValue.c_str());
43  throw TexcHere(exceptionMsg.c_str());
44  }
45  }
46 }
47 
48 const SBuf &
50 {
51  if (al && valueFormat) {
52  static MemBuf mb;
53  mb.reset();
54  valueFormat->assemble(mb, al, 0);
55  theFormattedValue.assign(mb.content());
56  return theFormattedValue;
57  }
58  return theValue;
59 }
60 
62 Note::addValue(const char *value, const bool quoted, const char *descr, const Value::Method m)
63 {
64  values.push_back(new Value(value, quoted, descr, m));
65  return values.back();
66 }
67 
68 bool
70 {
71  ACLFilledChecklist ch(nullptr, request, nullptr);
72  ch.reply = reply;
73  if (reply)
74  HTTPMSGLOCK(ch.reply);
75 
76  for (auto v: values) {
77  assert(v->aclList);
78  const auto ret = ch.fastCheck(v->aclList);
79  debugs(93, 5, "Check for header name: " << theKey << ": " << v->value() <<
80  ", HttpRequest: " << request << " HttpReply: " << reply << " matched: " << ret);
81  if (ret.allowed()) {
82  matched = v->format(al);
83  return true;
84  }
85  }
86  matched.clear();
87  return false;
88 }
89 
90 void
92 {
93  for (auto v: values) {
94  const SBuf &formatted = v->format(al);
95  if (!pairs->empty() && v->method() == Value::mhReplace)
96  pairs->remove(theKey);
97  if (delimiters)
98  pairs->addStrList(key(), formatted, *delimiters);
99  else
100  pairs->add(key(), formatted);
101  }
102 }
103 
104 void
105 Note::dump(StoreEntry *entry, const char *k)
106 {
107  for (auto v: values) {
108  storeAppendPrintf(entry, "%s %.*s %s",
109  k, key().length(), key().rawContent(), ConfigParser::QuoteString(SBufToString(v->value())));
110  dump_acl_list(entry, v->aclList);
111  storeAppendPrintf(entry, "\n");
112  }
113 }
114 
115 SBuf
116 Note::toString(const char *sep) const
117 {
118  SBuf result;
119  for (auto val: values)
120  result.appendf("%.*s: %.*s%s", key().length(), key().rawContent(),
121  val->value().length(), val->value().rawContent(), sep);
122  return result;
123 }
124 
126 Notes::add(const SBuf &noteKey)
127 {
128  if (Note::Pointer p = find(noteKey))
129  return p;
130  notes.push_back(new Note(noteKey));
131  return notes.back();
132 }
133 
135 Notes::find(const SBuf &noteKey)
136 {
137  for (auto n: notes)
138  if (n->key() == noteKey)
139  return n;
140  return nullptr;
141 }
142 
143 void
145 {
146  if (blacklisted) {
147  for (int i = 0; blacklisted[i] != nullptr; ++i) {
148  if (!key.cmp(blacklisted[i])) {
149  fatalf("%s:%d: meta key \"%.*s\" is a reserved %s name",
151  descr ? descr : "");
152  }
153  }
154  }
155  // TODO: fix code duplication: the same set of specials is produced
156  // by isKeyNameChar().
157  static const CharacterSet allowedSpecials = CharacterSet::ALPHA +
158  CharacterSet::DIGIT + CharacterSet("specials", "-_");
159  const auto specialIndex = key.findFirstNotOf(allowedSpecials);
160  if (specialIndex != SBuf::npos) {
161  debugs(28, DBG_CRITICAL, "Warning: used special character '" <<
162  key[specialIndex] << "' within annotation name. " <<
163  "Future Squid versions will not support this.");
164  }
165 }
166 
169 {
170  const char *tok = ConfigParser::NextToken();
171  if (!tok)
172  fatalf("FATAL: Missing note key");
173  SBuf key(tok);
174  validateKey(key);
176  const char *val = ConfigParser::NextQuotedToken();
177  if (!val)
178  fatalf("FATAL: Missing note value");
180  Note::Pointer note = add(key);
181  Note::Value::Pointer noteValue = note->addValue(val, formattedValues && ConfigParser::LastTokenWasQuoted(), descr);
182  key.append('=');
183  key.append(val);
184  aclParseAclList(parser, &noteValue->aclList, key.c_str());
185  return note;
186 }
187 
188 void
190  char *k, *v;
191  int parsedPairs = 0;
192  while (ConfigParser::NextKvPair(k, v)) {
193  int keyLen = strlen(k);
194  const Note::Value::Method method = (k[keyLen - 1] == '+') ? Note::Value::mhAppend : Note::Value::mhReplace;
195  if (method == Note::Value::mhAppend)
196  keyLen--;
197  else {
198  assert(method == Note::Value::mhReplace);
199  if (Note::Pointer oldNote = find(SBuf(k, keyLen)))
200  debugs(28, DBG_CRITICAL, "Warning: annotation configuration with key " << k <<
201  " already exists and will be overwritten");
202  }
203  SBuf key(k, keyLen);
204  validateKey(key);
205  Note::Pointer note = add(key);
206  (void)note->addValue(v, formattedValues && ConfigParser::LastTokenWasQuoted(), descr, method);
207  parsedPairs++;
208  }
209  if (!parsedPairs)
210  fatalf("FATAL: Missing annotation kv pair");
211 }
212 
213 void
215 {
216  for (auto n: notes)
217  n->updateNotePairs(pairs, delimiters, al);
218 }
219 
220 void
221 Notes::dump(StoreEntry *entry, const char *key)
222 {
223  for (auto n: notes)
224  n->dump(entry, key);
225 }
226 
227 const char *
228 Notes::toString(const char *sep) const
229 {
230  static SBuf result;
231  result.clear();
232  for (auto note: notes)
233  result.append(note->toString(sep));
234  return result.isEmpty() ? nullptr : result.c_str();
235 }
236 
237 bool
238 NotePairs::find(SBuf &resultNote, const char *noteKey, const char *sep) const
239 {
240  resultNote.clear();
241  for (auto e: entries) {
242  if (!e->name().cmp(noteKey)) {
243  if (!resultNote.isEmpty())
244  resultNote.append(sep);
245  resultNote.append(e->value());
246  }
247  }
248  return resultNote.length();
249 }
250 
251 const char *
252 NotePairs::toString(const char *sep) const
253 {
254  static SBuf result;
255  result.clear();
256  for (auto e: entries)
257  result.appendf("%.*s: %.*s%s", e->name().length(), e->name().rawContent(),
258  e->value().length(), e->value().rawContent(), sep);
259  return result.isEmpty() ? nullptr : result.c_str();
260 }
261 
262 const char *
263 NotePairs::findFirst(const char *noteKey) const
264 {
265  for (auto e: entries)
266  if (!e->name().cmp(noteKey))
267  return const_cast<SBuf &>(e->value()).c_str();
268  return nullptr;
269 }
270 
271 void
272 NotePairs::add(const char *key, const char *note)
273 {
274  entries.push_back(new NotePairs::Entry(key, note));
275 }
276 
277 void
278 NotePairs::add(const SBuf &key, const SBuf &note)
279 {
280  entries.push_back(new NotePairs::Entry(key, note));
281 }
282 
283 void
284 NotePairs::remove(const char *key)
285 {
286  Entries::iterator i = entries.begin();
287  while (i != entries.end())
288  i = (*i)->name().cmp(key) ? i+1 : entries.erase(i);
289 }
290 
291 void
293 {
294  Entries::iterator i = entries.begin();
295  while (i != entries.end())
296  i = (*i)->name() == key ? entries.erase(i) : i+1;
297 }
298 
299 static void
300 AppendTokens(NotePairs::Entries &entries, const SBuf &key, const SBuf &val, const CharacterSet &delimiters)
301 {
302  Parser::Tokenizer tok(val);
303  SBuf v;
304  while (tok.token(v, delimiters))
305  entries.push_back(new NotePairs::Entry(key, v));
306  v = tok.remaining();
307  if (!v.isEmpty())
308  entries.push_back(new NotePairs::Entry(key, v));
309 }
310 
311 const NotePairs::Entries &
313 {
314  if (delimiters) {
315  static NotePairs::Entries expandedEntries;
316  expandedEntries.clear();
317  for(auto entry: entries)
318  AppendTokens(expandedEntries, entry->name(), entry->value(), *delimiters);
319  return expandedEntries;
320  }
321  return entries;
322 }
323 
324 void
325 NotePairs::addStrList(const SBuf &key, const SBuf &values, const CharacterSet &delimiters)
326 {
327  AppendTokens(entries, key, values, delimiters);
328 }
329 
330 bool
331 NotePairs::hasPair(const SBuf &key, const SBuf &value) const
332 {
333  for (auto e: entries)
334  if (e->name() == key && e->value() == value)
335  return true;
336  return false;
337 }
338 
339 void
341 {
342  for (auto e: src->entries)
343  entries.push_back(new NotePairs::Entry(e->name(), e->value()));
344 }
345 
346 void
348 {
349  for (auto e: src->entries) {
350  if (!hasPair(e->name(), e->value()))
351  entries.push_back(new NotePairs::Entry(e->name(), e->value()));
352  }
353 }
354 
355 void
357 {
358  for (auto e: src->entries)
359  remove(e->name());
360  append(src);
361 }
362 
const SBuf & format(const AccessLogEntryPointer &al)
Definition: Notes.cc:49
#define assert(EX)
Definition: assert.h:17
SBuf & appendf(const char *fmt,...)
Definition: SBuf.cc:251
SBuf theValue
Definition: Notes.h:65
static void EnableMacros()
Allow macros inside quoted strings.
Definition: ConfigParser.h:123
Note::Pointer add(const SBuf &noteKey)
Definition: Notes.cc:126
static bool LastTokenWasQuoted()
Definition: ConfigParser.h:90
Definition: SBuf.h:87
Note(const char *aKey, const size_t keyLen)
Definition: Notes.h:75
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
void add(const SBuf &key, const SBuf &value)
Definition: Notes.cc:278
int i
Definition: membanger.c:49
SBuf & append(const SBuf &S)
Definition: SBuf.cc:207
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:154
const Entries & expandListEntries(const CharacterSet *delimiters) const
Definition: Notes.cc:312
void clear()
Definition: SBuf.cc:190
void appendNewOnly(const NotePairs *src)
Definition: Notes.cc:347
bool match(HttpRequest *request, HttpReply *reply, const AccessLogEntryPointer &al, SBuf &matched)
Definition: Notes.cc:69
void replaceOrAdd(const NotePairs *src)
Definition: Notes.cc:356
bool isEmpty() const
Definition: SBuf.h:422
#define DBG_CRITICAL
Definition: Debug.h:44
char * p
Definition: membanger.c:43
static const CharacterSet ALPHA
Definition: CharacterSet.h:73
Stores a value for the note.
Definition: Notes.h:41
void updateNotePairs(NotePairsPointer pairs, const CharacterSet *delimiters, const AccessLogEntryPointer &al)
Definition: Notes.cc:91
void fatalf(const char *fmt,...)
Definition: fatal.cc:79
static void DisableMacros()
Do not allow macros inside quoted strings.
Definition: ConfigParser.h:126
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:405
const char * toString(const char *sep="\r\n") const
Definition: Notes.cc:228
void addStrList(const SBuf &key, const SBuf &values, const CharacterSet &delimiters)
Definition: Notes.cc:325
std::vector< Entry::Pointer > Entries
The key/value pair entries.
Definition: Notes.h:193
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
int config_lineno
String SBufToString(const SBuf &s)
Definition: StringConvert.h:26
static char * NextQuotedToken()
bool empty() const
Definition: Notes.h:242
Used to store a note key/value pair.
Definition: Notes.h:173
static const CharacterSet DIGIT
Definition: CharacterSet.h:81
SBuf & Printf(const char *fmt,...)
Definition: SBuf.cc:236
void reset()
Definition: MemBuf.cc:141
ACLList * aclList
The access list used to determine if this value is valid for a request.
Definition: Notes.h:57
const char * cfg_filename
static char * NextToken()
Value::Pointer addValue(const char *value, const bool quoted, const char *descr, const Value::Method m=Value::mhAppend)
Definition: Notes.cc:62
Values values
The possible values list for the note.
Definition: Notes.h:100
const char * c_str()
Definition: SBuf.cc:546
optimized set of C chars, with quick membership test and merge support
Definition: CharacterSet.h:17
static void AppendTokens(NotePairs::Entries &entries, const SBuf &key, const SBuf &val, const CharacterSet &delimiters)
Definition: Notes.cc:300
Definition: parse.c:160
void validateKey(const SBuf &key) const
Definition: Notes.cc:144
bool find(SBuf &resultNote, const char *noteKey, const char *sep=",") const
Definition: Notes.cc:238
static const char * QuoteString(const String &var)
char * content()
start of the added data
Definition: MemBuf.h:41
bool parse(const char *def)
Definition: Format.cc:65
Note::Pointer parse(ConfigParser &parser)
Parses a notes line and returns a pointer to the parsed Note object.
Definition: Notes.cc:168
Format::Format * valueFormat
Compiled annotation value format.
Definition: Notes.h:64
SBuf toString(const char *sep) const
Definition: Notes.cc:116
allow_t const & fastCheck()
Definition: Checklist.cc:336
const SBuf & remaining() const
the remaining unprocessed section of buffer
Definition: Tokenizer.h:44
void updateNotePairs(NotePairsPointer pairs, const CharacterSet *delimiters, const AccessLogEntryPointer &al)
Definition: Notes.cc:214
Value(const char *aVal, const bool quoted, const char *descr, const Method method=mhReplace)
Definition: Notes.cc:34
static bool NextKvPair(char *&key, char *&value)
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:126
void dump_acl_list(StoreEntry *entry, ACLList *head)
Definition: cache_cf.cc:1381
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Definition: SBuf.h:265
void parseKvPair()
Parses an annotate line with "key=value" or "key+=value" formats.
Definition: Notes.cc:189
static const size_type npos
Definition: SBuf.h:93
bool hasPair(const SBuf &key, const SBuf &value) const
Definition: Notes.cc:331
Definition: MemBuf.h:23
#define TexcHere(msg)
Definition: TextException.h:81
const SBuf & key() const
Definition: Notes.h:90
void aclParseAclList(ConfigParser &, Acl::Tree **treep, const char *label)
Definition: Gadgets.cc:198
~Value()
Definition: Notes.cc:28
size_type findFirstNotOf(const CharacterSet &set, size_type startPos=0) const
Definition: SBuf.cc:776
void dump(StoreEntry *entry, const char *name)
Dump the notes list to the given StoreEntry object.
Definition: Notes.cc:221
const char * rawContent() const
Definition: SBuf.cc:539
const char * findFirst(const char *noteKey) const
Definition: Notes.cc:263
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:904
void aclDestroyAclList(ACLList **list)
Definition: Gadgets.cc:275
Note::Pointer find(const SBuf &noteKey)
Definition: Notes.cc:135
const char * toString(const char *sep="\r\n") const
Definition: Notes.cc:252
void remove(const char *key)
Definition: Notes.cc:284
SBuf theKey
The note key.
Definition: Notes.h:99
void append(const NotePairs *src)
Append the entries of the src NotePairs list to our list.
Definition: Notes.cc:340
void dump(StoreEntry *entry, const char *key)
Dump the single Note to the given StoreEntry object.
Definition: Notes.cc:105
bool token(SBuf &returnedToken, const CharacterSet &delimiters)
Definition: Tokenizer.cc:61
Entries entries
The key/value pair entries.
Definition: Notes.h:251

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors