]> git.ipfire.org Git - thirdparty/squid.git/blob - src/Notes.h
mkrelease: allow two digits for minor release numbers (#1837)
[thirdparty/squid.git] / src / Notes.h
1 /*
2 * Copyright (C) 1996-2023 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 #ifndef SQUID_SRC_NOTES_H
10 #define SQUID_SRC_NOTES_H
11
12 #include "acl/forward.h"
13 #include "base/RefCount.h"
14 #include "format/Format.h"
15 #include "mem/forward.h"
16 #include "sbuf/forward.h"
17 #include "SquidString.h"
18
19 #include <iosfwd>
20 #include <string>
21 #include <vector>
22
23 class HttpRequest;
24 class HttpReply;
25 class AccessLogEntry;
26 class NotePairs;
27
28 typedef RefCount<AccessLogEntry> AccessLogEntryPointer;
29 typedef RefCount<NotePairs> NotePairsPointer;
30
31 /**
32 * Used to store a note configuration. The notes are custom key:value
33 * pairs ICAP request headers or ECAP options used to pass
34 * custom transaction-state related meta information to squid
35 * internal subsystems or to adaptation services.
36 */
37 class Note: public RefCountable
38 {
39 public:
40 typedef RefCount<Note> Pointer;
41
42 /// Stores a value for the note.
43 class Value: public RefCountable
44 {
45 public:
46 typedef RefCount<Value> Pointer;
47 friend class Note;
48
49 enum Method { mhReplace, mhAppend };
50
51 Value(const char *aVal, const bool quoted, const char *descr, const Method method = mhReplace);
52 ~Value() override;
53 Value(const Value&) = delete;
54 Value &operator=(const Value&) = delete;
55
56 Method method() const { return theMethod; }
57 const SBuf &value() const { return theValue; }
58
59 ACLList *aclList; ///< The access list used to determine if this value is valid for a request
60
61 private:
62 /// \return the formatted value with expanded logformat %macros (quoted values).
63 /// \return the original value (non-quoted values).
64 const SBuf &format(const AccessLogEntryPointer &al);
65
66 Format::Format *valueFormat; ///< Compiled annotation value format.
67 SBuf theValue; ///< Configured annotation value, possibly with %macros.
68 /// The expanded value produced by format(), empty for non-quoted values.
69 SBuf theFormattedValue;
70 /// Specifies how theValue will be applied to the existing annotation
71 /// with the same key: it either replaces the existing value or is appended
72 /// to the list of existing values.
73 Method theMethod;
74 };
75 typedef std::vector<Value::Pointer> Values;
76
77 Note(const char *aKey, const size_t keyLen): theKey(aKey, keyLen) {}
78 explicit Note(const SBuf aKey): theKey(aKey) {}
79 Note(const Note&) = delete;
80 Note &operator=(const Note&) = delete;
81
82 /// Adds a value to the note and returns a pointer to the
83 /// related Value object.
84 Value::Pointer addValue(const char *value, const bool quoted, const char *descr,
85 const Value::Method m = Value::mhAppend);
86
87 /// Walks through the possible values list of the note, selects
88 /// the first value, matching the given HttpRequest and HttpReply
89 /// and assigns the given 'matched' to it.
90 /// \return true if matched, false otherwise
91 bool match(HttpRequest *request, HttpReply *reply, const AccessLogEntryPointer &al, SBuf &matched);
92 const SBuf &key() const { return theKey; }
93 void updateNotePairs(NotePairsPointer pairs, const CharacterSet *delimiters, const AccessLogEntryPointer &al);
94
95 /// Prints key and value(s) using a "note" directive format (including directive name).
96 void printAsNoteDirective(StoreEntry *, const char *directiveName) const;
97
98 /// Prints using "annotate_transaction acl parameter" format, one key=value
99 /// or key+=value parameter per stored value.
100 void printAsAnnotationAclParameters(std::ostream &) const;
101
102 private:
103 SBuf theKey; ///< The note key
104 Values values; ///< The possible values list for the note
105 };
106
107 class ConfigParser;
108
109 /**
110 * Used to store a notes configuration list.
111 */
112 class Notes : public RefCountable
113 {
114 public:
115 typedef RefCount<Notes> Pointer;
116 typedef std::vector<SBuf> Keys; ///< unordered annotation names
117 typedef std::vector<Note::Pointer> NotesList;
118 typedef NotesList::iterator iterator; ///< iterates over the notes list
119 typedef NotesList::const_iterator const_iterator; ///< iterates over the notes list
120
121 explicit Notes(const char *aDescr, const Keys *extraReservedKeys = nullptr, bool allowFormatted = true);
122 Notes() = default;
123 ~Notes() override { notes.clear(); }
124 Notes(const Notes&) = delete;
125 Notes &operator=(const Notes&) = delete;
126
127 /// Parses a notes line and returns a pointer to the parsed Note object.
128 Note::Pointer parse(ConfigParser &parser);
129
130 /// Parses an annotate line with "key=value" or "key+=value" formats.
131 void parseKvPair();
132
133 /// Prints notes using "note" squid.conf directive format, one directive per stored note.
134 void printAsNoteDirectives(StoreEntry *, const char *directiveName) const;
135
136 /// clean the notes list
137 void clean() { notes.clear(); }
138
139 /// points to the first argument
140 iterator begin() { return notes.begin(); }
141 /// points to the end of list
142 iterator end() { return notes.end(); }
143 /// \returns true if the notes list is empty
144 bool empty() const { return notes.empty(); }
145
146 /// print notes using "annotate_transaction acl parameters" format, one
147 /// key=value parameter per note
148 void printAsAnnotationAclParameters(std::ostream &) const;
149
150 void updateNotePairs(NotePairsPointer pairs, const CharacterSet *delimiters,
151 const AccessLogEntryPointer &al);
152 private:
153 /// Makes sure the given key is not on the given list of banned names.
154 void banReservedKey(const SBuf &key, const Keys &banned) const;
155
156 /// Verifies that the key is not reserved (fatal error) and
157 /// does not contain special characters (non-fatal error).
158 void validateKey(const SBuf &key) const;
159
160 /// Adds a note to the notes list and returns a pointer to the
161 /// related Note object. If the note key already exists in list,
162 /// returns a pointer to the existing object.
163 /// If keyLen is not provided, the noteKey is assumed null-terminated.
164 Note::Pointer add(const SBuf &noteKey);
165 Note::Pointer find(const SBuf &noteKey);
166
167 NotesList notes; ///< The Note::Pointer objects array list
168 const char *descr = nullptr; ///< identifies note source in error messages
169
170 Keys reservedKeys; ///< a list of additional prohibited key names
171 bool formattedValues = false; ///< whether to expand quoted logformat %codes
172
173 static const Notes::Keys &ReservedKeys(); ///< always prohibited key names
174 };
175
176 /**
177 * Used to store list of notes
178 */
179 class NotePairs: public RefCountable
180 {
181 public:
182 typedef RefCount<NotePairs> Pointer;
183
184 /// Used to store a note key/value pair.
185 class Entry : public RefCountable
186 {
187 MEMPROXY_CLASS(Entry);
188 public:
189 typedef RefCount<Entry> Pointer;
190
191 Entry(const SBuf &aKey, const SBuf &aValue)
192 : theName(aKey), theValue(aValue) {}
193 Entry(const char *aKey, const char *aValue)
194 : theName(aKey), theValue(aValue) {}
195 Entry(const Entry &) = delete;
196 Entry &operator=(const Entry &) = delete;
197
198 const SBuf &name() const { return theName; }
199 const SBuf &value() const { return theValue; }
200
201 private:
202 SBuf theName;
203 SBuf theValue;
204 };
205 typedef std::vector<Entry::Pointer> Entries; ///< The key/value pair entries
206 typedef std::vector<SBuf> Names;
207
208 NotePairs() {}
209 NotePairs &operator=(NotePairs const &) = delete;
210 NotePairs(NotePairs const &) = delete;
211
212 /// Append the entries of the src NotePairs list to our list.
213 void append(const NotePairs *src);
214
215 /// Replace existing list entries with the src NotePairs entries.
216 /// Do not replace but append entries named in the appendables
217 /// Entries which do not exist in the destination set are added.
218 void replaceOrAddOrAppend(const NotePairs *src, const Names &appendables);
219
220 /// Replace existing list entries with the src NotePairs entries.
221 /// Entries which do not exist in the destination set are added.
222 void replaceOrAdd(const NotePairs *src);
223
224 /// Append any new entries of the src NotePairs list to our list.
225 /// Entries which already exist in the destination set are ignored.
226 void appendNewOnly(const NotePairs *src);
227
228 /// \param resultNote a comma separated list of notes with key 'noteKey'.
229 /// \returns true if there are entries with the given 'noteKey'.
230 /// Use findFirst() instead when a unique kv-pair is needed.
231 bool find(SBuf &resultNote, const char *noteKey, const char *sep = ",") const;
232
233 /// \returns the first note value for this key or an empty string.
234 const char *findFirst(const char *noteKey) const;
235
236 /// Adds a note key and value to the notes list.
237 /// If the key name already exists in the list, add the given value to its set
238 /// of values.
239 void add(const SBuf &key, const SBuf &value);
240 void add(const char *key, const char *value);
241
242 /// Remove all notes with a given key. If keyLen is not
243 /// provided, the key is assumed null-terminated.
244 void remove(const char *key);
245 void remove(const SBuf &key);
246
247 /// Adds a note key and values strList to the notes list.
248 /// If the key name already exists in the list, add the new values to its set
249 /// of values.
250 void addStrList(const SBuf &key, const SBuf &values, const CharacterSet &delimiters);
251
252 /// \returns true if the key/value pair is already stored
253 bool hasPair(const SBuf &key, const SBuf &value) const;
254
255 /// Reports all entries (if any), printing exactly four items for each:
256 /// entry name, nameValueSeparator, entry value, and entry terminator.
257 void print(std::ostream &os, const char *nameValueSeparator, const char *entryTerminator) const;
258
259 /// \returns true if there are not entries in the list
260 bool empty() const {return entries.empty();}
261
262 void clear() { entries.clear(); }
263
264 /// If delimiters are provided, returns another Entries, converting each single multi-token
265 /// pair to multiple single-token pairs; returns existing entries otherwise.
266 const Entries &expandListEntries(const CharacterSet *delimiters) const;
267
268 private:
269 Entries entries; ///< The key/value pair entries
270 };
271
272 #endif /* SQUID_SRC_NOTES_H */
273