Notes.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 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.al = al;
73  ch.reply = reply;
74  ch.syncAle(request, nullptr);
75  if (reply)
76  HTTPMSGLOCK(ch.reply);
77 
78  for (auto v: values) {
79  assert(v->aclList);
80  const auto ret = ch.fastCheck(v->aclList);
81  debugs(93, 5, "Check for header name: " << theKey << ": " << v->value() <<
82  ", HttpRequest: " << request << " HttpReply: " << reply << " matched: " << ret);
83  if (ret.allowed()) {
84  matched = v->format(al);
85  return true;
86  }
87  }
88  matched.clear();
89  return false;
90 }
91 
92 void
94 {
95  for (auto v: values) {
96  const SBuf &formatted = v->format(al);
97  if (!pairs->empty() && v->method() == Value::mhReplace)
98  pairs->remove(theKey);
99  if (delimiters)
100  pairs->addStrList(key(), formatted, *delimiters);
101  else
102  pairs->add(key(), formatted);
103  }
104 }
105 
106 void
107 Note::dump(StoreEntry *entry, const char *k)
108 {
109  for (auto v: values) {
110  storeAppendPrintf(entry, "%s %.*s %s",
111  k, key().length(), key().rawContent(), ConfigParser::QuoteString(SBufToString(v->value())));
112  dump_acl_list(entry, v->aclList);
113  storeAppendPrintf(entry, "\n");
114  }
115 }
116 
117 SBuf
118 Note::toString(const char *sep) const
119 {
120  SBuf result;
121  for (auto val: values)
122  result.appendf("%.*s: %.*s%s", key().length(), key().rawContent(),
123  val->value().length(), val->value().rawContent(), sep);
124  return result;
125 }
126 
128 Notes::add(const SBuf &noteKey)
129 {
130  if (Note::Pointer p = find(noteKey))
131  return p;
132  notes.push_back(new Note(noteKey));
133  return notes.back();
134 }
135 
137 Notes::find(const SBuf &noteKey)
138 {
139  for (auto n: notes)
140  if (n->key() == noteKey)
141  return n;
142  return nullptr;
143 }
144 
145 void
147 {
148  if (blacklisted) {
149  for (int i = 0; blacklisted[i] != nullptr; ++i) {
150  if (!key.cmp(blacklisted[i])) {
151  fatalf("%s:%d: meta key \"%.*s\" is a reserved %s name",
153  descr ? descr : "");
154  }
155  }
156  }
157  // TODO: fix code duplication: the same set of specials is produced
158  // by isKeyNameChar().
159  static const CharacterSet allowedSpecials = CharacterSet::ALPHA +
160  CharacterSet::DIGIT + CharacterSet("specials", "-_");
161  const auto specialIndex = key.findFirstNotOf(allowedSpecials);
162  if (specialIndex != SBuf::npos) {
163  debugs(28, DBG_CRITICAL, "Warning: used special character '" <<
164  key[specialIndex] << "' within annotation name. " <<
165  "Future Squid versions will not support this.");
166  }
167 }
168 
171 {
172  const char *tok = ConfigParser::NextToken();
173  if (!tok)
174  fatalf("FATAL: Missing note key");
175  SBuf key(tok);
176  validateKey(key);
178  const char *val = ConfigParser::NextQuotedToken();
179  if (!val)
180  fatalf("FATAL: Missing note value");
182  Note::Pointer note = add(key);
183  Note::Value::Pointer noteValue = note->addValue(val, formattedValues && ConfigParser::LastTokenWasQuoted(), descr);
184  key.append('=');
185  key.append(val);
186  aclParseAclList(parser, &noteValue->aclList, key.c_str());
187  return note;
188 }
189 
190 void
192  char *k, *v;
193  int parsedPairs = 0;
194  while (ConfigParser::NextKvPair(k, v)) {
195  int keyLen = strlen(k);
196  const Note::Value::Method method = (k[keyLen - 1] == '+') ? Note::Value::mhAppend : Note::Value::mhReplace;
197  if (method == Note::Value::mhAppend)
198  keyLen--;
199  else {
200  assert(method == Note::Value::mhReplace);
201  if (Note::Pointer oldNote = find(SBuf(k, keyLen)))
202  debugs(28, DBG_CRITICAL, "Warning: annotation configuration with key " << k <<
203  " already exists and will be overwritten");
204  }
205  SBuf key(k, keyLen);
206  validateKey(key);
207  Note::Pointer note = add(key);
208  (void)note->addValue(v, formattedValues && ConfigParser::LastTokenWasQuoted(), descr, method);
209  parsedPairs++;
210  }
211  if (!parsedPairs)
212  fatalf("FATAL: Missing annotation kv pair");
213 }
214 
215 void
217 {
218  for (auto n: notes)
219  n->updateNotePairs(pairs, delimiters, al);
220 }
221 
222 void
223 Notes::dump(StoreEntry *entry, const char *key)
224 {
225  for (auto n: notes)
226  n->dump(entry, key);
227 }
228 
229 const char *
230 Notes::toString(const char *sep) const
231 {
232  static SBuf result;
233  result.clear();
234  for (auto note: notes)
235  result.append(note->toString(sep));
236  return result.isEmpty() ? nullptr : result.c_str();
237 }
238 
239 bool
240 NotePairs::find(SBuf &resultNote, const char *noteKey, const char *sep) const
241 {
242  resultNote.clear();
243  for (auto e: entries) {
244  if (!e->name().cmp(noteKey)) {
245  if (!resultNote.isEmpty())
246  resultNote.append(sep);
247  resultNote.append(e->value());
248  }
249  }
250  return resultNote.length();
251 }
252 
253 const char *
254 NotePairs::toString(const char *sep) const
255 {
256  static SBuf result;
257  result.clear();
258  for (auto e: entries)
259  result.appendf("%.*s: %.*s%s", e->name().length(), e->name().rawContent(),
260  e->value().length(), e->value().rawContent(), sep);
261  return result.isEmpty() ? nullptr : result.c_str();
262 }
263 
264 const char *
265 NotePairs::findFirst(const char *noteKey) const
266 {
267  for (auto e: entries)
268  if (!e->name().cmp(noteKey))
269  return const_cast<SBuf &>(e->value()).c_str();
270  return nullptr;
271 }
272 
273 void
274 NotePairs::add(const char *key, const char *note)
275 {
276  entries.push_back(new NotePairs::Entry(key, note));
277 }
278 
279 void
280 NotePairs::add(const SBuf &key, const SBuf &note)
281 {
282  entries.push_back(new NotePairs::Entry(key, note));
283 }
284 
285 void
286 NotePairs::remove(const char *key)
287 {
288  Entries::iterator i = entries.begin();
289  while (i != entries.end())
290  i = (*i)->name().cmp(key) ? i+1 : entries.erase(i);
291 }
292 
293 void
295 {
296  Entries::iterator i = entries.begin();
297  while (i != entries.end())
298  i = (*i)->name() == key ? entries.erase(i) : i+1;
299 }
300 
301 static void
302 AppendTokens(NotePairs::Entries &entries, const SBuf &key, const SBuf &val, const CharacterSet &delimiters)
303 {
304  Parser::Tokenizer tok(val);
305  SBuf v;
306  while (tok.token(v, delimiters))
307  entries.push_back(new NotePairs::Entry(key, v));
308  v = tok.remaining();
309  if (!v.isEmpty())
310  entries.push_back(new NotePairs::Entry(key, v));
311 }
312 
313 const NotePairs::Entries &
315 {
316  if (delimiters) {
317  static NotePairs::Entries expandedEntries;
318  expandedEntries.clear();
319  for(auto entry: entries)
320  AppendTokens(expandedEntries, entry->name(), entry->value(), *delimiters);
321  return expandedEntries;
322  }
323  return entries;
324 }
325 
326 void
327 NotePairs::addStrList(const SBuf &key, const SBuf &values, const CharacterSet &delimiters)
328 {
329  AppendTokens(entries, key, values, delimiters);
330 }
331 
332 bool
333 NotePairs::hasPair(const SBuf &key, const SBuf &value) const
334 {
335  for (auto e: entries)
336  if (e->name() == key && e->value() == value)
337  return true;
338  return false;
339 }
340 
341 void
343 {
344  for (auto e: src->entries)
345  entries.push_back(new NotePairs::Entry(e->name(), e->value()));
346 }
347 
348 void
350 {
351  for (auto e: src->entries) {
352  if (!hasPair(e->name(), e->value()))
353  entries.push_back(new NotePairs::Entry(e->name(), e->value()));
354  }
355 }
356 
357 void
359 {
360  for (auto e: src->entries)
361  remove(e->name());
362  append(src);
363 }
364 
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:239
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:128
static bool LastTokenWasQuoted()
Definition: ConfigParser.h:90
Definition: SBuf.h:86
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:280
int i
Definition: membanger.c:49
SBuf & append(const SBuf &S)
Definition: SBuf.cc:195
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:154
const Entries & expandListEntries(const CharacterSet *delimiters) const
Definition: Notes.cc:314
void clear()
Definition: SBuf.cc:178
void appendNewOnly(const NotePairs *src)
Definition: Notes.cc:349
bool match(HttpRequest *request, HttpReply *reply, const AccessLogEntryPointer &al, SBuf &matched)
Definition: Notes.cc:69
void replaceOrAdd(const NotePairs *src)
Definition: Notes.cc:358
bool isEmpty() const
Definition: SBuf.h:420
#define DBG_CRITICAL
Definition: Debug.h:45
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:93
void fatalf(const char *fmt,...)
Definition: fatal.cc:68
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:404
const char * toString(const char *sep="\r\n") const
Definition: Notes.cc:230
void addStrList(const SBuf &key, const SBuf &values, const CharacterSet &delimiters)
Definition: Notes.cc:327
std::vector< Entry::Pointer > Entries
The key/value pair entries.
Definition: Notes.h:193
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
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:224
void reset()
Definition: MemBuf.cc:132
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:526
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:302
Definition: parse.c:160
void validateKey(const SBuf &key) const
Definition: Notes.cc:146
bool find(SBuf &resultNote, const char *noteKey, const char *sep=",") const
Definition: Notes.cc:240
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:64
Note::Pointer parse(ConfigParser &parser)
Parses a notes line and returns a pointer to the parsed Note object.
Definition: Notes.cc:170
Format::Format * valueFormat
Compiled annotation value format.
Definition: Notes.h:64
SBuf toString(const char *sep) const
Definition: Notes.cc:118
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:216
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:1392
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Definition: SBuf.h:264
void parseKvPair()
Parses an annotate line with "key=value" or "key+=value" formats.
Definition: Notes.cc:191
static const size_type npos
Definition: SBuf.h:92
bool hasPair(const SBuf &key, const SBuf &value) const
Definition: Notes.cc:333
Definition: MemBuf.h:23
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
Definition: TextException.h:55
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:756
void dump(StoreEntry *entry, const char *name)
Dump the notes list to the given StoreEntry object.
Definition: Notes.cc:223
const char * rawContent() const
Definition: SBuf.cc:519
const char * findFirst(const char *noteKey) const
Definition: Notes.cc:265
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:893
void aclDestroyAclList(ACLList **list)
Definition: Gadgets.cc:275
Note::Pointer find(const SBuf &noteKey)
Definition: Notes.cc:137
const char * toString(const char *sep="\r\n") const
Definition: Notes.cc:254
void remove(const char *key)
Definition: Notes.cc:286
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:342
void dump(StoreEntry *entry, const char *key)
Dump the single Note to the given StoreEntry object.
Definition: Notes.cc:107
virtual void syncAle(HttpRequest *adaptedRequest, const char *logUri) const
assigns uninitialized adapted_request and url ALE components
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