]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
bbc27441 AJ |
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 | ||
ff9d9458 FC |
9 | #ifndef SQUID_SRC_NOTES_H |
10 | #define SQUID_SRC_NOTES_H | |
b3404bc5 | 11 | |
6f58d7d7 | 12 | #include "acl/forward.h" |
cf9f0261 | 13 | #include "base/RefCount.h" |
af0ded40 | 14 | #include "format/Format.h" |
ed6e9fb9 | 15 | #include "mem/forward.h" |
ab2acef6 | 16 | #include "sbuf/forward.h" |
cf9f0261 | 17 | #include "SquidString.h" |
b3404bc5 | 18 | |
e67eab3a | 19 | #include <iosfwd> |
b3404bc5 | 20 | #include <string> |
81481ec0 | 21 | #include <vector> |
b3404bc5 | 22 | |
b3404bc5 CT |
23 | class HttpRequest; |
24 | class HttpReply; | |
75d47340 CT |
25 | class AccessLogEntry; |
26 | class NotePairs; | |
27 | ||
af0ded40 | 28 | typedef RefCount<AccessLogEntry> AccessLogEntryPointer; |
75d47340 | 29 | typedef RefCount<NotePairs> NotePairsPointer; |
b3404bc5 CT |
30 | |
31 | /** | |
cf9f0261 CT |
32 | * Used to store a note configuration. The notes are custom key:value |
33 | * pairs ICAP request headers or ECAP options used to pass | |
b3404bc5 | 34 | * custom transaction-state related meta information to squid |
cf9f0261 | 35 | * internal subsystems or to adaptation services. |
b3404bc5 CT |
36 | */ |
37 | class Note: public RefCountable | |
38 | { | |
39 | public: | |
40 | typedef RefCount<Note> Pointer; | |
75d47340 | 41 | |
b3404bc5 CT |
42 | /// Stores a value for the note. |
43 | class Value: public RefCountable | |
44 | { | |
45 | public: | |
46 | typedef RefCount<Value> Pointer; | |
75d47340 CT |
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); | |
337b9aa4 | 52 | ~Value() override; |
75d47340 CT |
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; } | |
b3404bc5 | 58 | |
75d47340 | 59 | ACLList *aclList; ///< The access list used to determine if this value is valid for a request |
b3404bc5 | 60 | |
75d47340 CT |
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; | |
b3404bc5 | 76 | |
75d47340 CT |
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, | |
b8f75894 | 85 | const Value::Method m = Value::mhAppend); |
75d47340 CT |
86 | |
87 | /// Walks through the possible values list of the note, selects | |
88 | /// the first value, matching the given HttpRequest and HttpReply | |
2f8abb64 | 89 | /// and assigns the given 'matched' to it. |
75d47340 CT |
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); | |
e67eab3a FC |
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; | |
fd7f26ea | 101 | |
75d47340 CT |
102 | private: |
103 | SBuf theKey; ///< The note key | |
b3404bc5 CT |
104 | Values values; ///< The possible values list for the note |
105 | }; | |
106 | ||
107 | class ConfigParser; | |
75d47340 | 108 | |
b3404bc5 | 109 | /** |
cf9f0261 | 110 | * Used to store a notes configuration list. |
b3404bc5 | 111 | */ |
75d47340 | 112 | class Notes : public RefCountable |
ffb82151 | 113 | { |
b3404bc5 | 114 | public: |
75d47340 | 115 | typedef RefCount<Notes> Pointer; |
4668df3d | 116 | typedef std::vector<SBuf> Keys; ///< unordered annotation names |
81481ec0 | 117 | typedef std::vector<Note::Pointer> NotesList; |
b3404bc5 | 118 | typedef NotesList::iterator iterator; ///< iterates over the notes list |
bc600349 | 119 | typedef NotesList::const_iterator const_iterator; ///< iterates over the notes list |
b3404bc5 | 120 | |
70d0ef18 | 121 | explicit Notes(const char *aDescr, const Keys *extraReservedKeys = nullptr, bool allowFormatted = true); |
4668df3d | 122 | Notes() = default; |
337b9aa4 | 123 | ~Notes() override { notes.clear(); } |
75d47340 CT |
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. | |
b3404bc5 | 128 | Note::Pointer parse(ConfigParser &parser); |
75d47340 CT |
129 | |
130 | /// Parses an annotate line with "key=value" or "key+=value" formats. | |
131 | void parseKvPair(); | |
132 | ||
e67eab3a FC |
133 | /// Prints notes using "note" squid.conf directive format, one directive per stored note. |
134 | void printAsNoteDirectives(StoreEntry *, const char *directiveName) const; | |
135 | ||
75d47340 CT |
136 | /// clean the notes list |
137 | void clean() { notes.clear(); } | |
b3404bc5 CT |
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(); } | |
75d47340 CT |
143 | /// \returns true if the notes list is empty |
144 | bool empty() const { return notes.empty(); } | |
e67eab3a FC |
145 | |
146 | /// print notes using "annotate_transaction acl parameters" format, one | |
147 | /// key=value parameter per note | |
148 | void printAsAnnotationAclParameters(std::ostream &) const; | |
149 | ||
75d47340 | 150 | void updateNotePairs(NotePairsPointer pairs, const CharacterSet *delimiters, |
b8f75894 | 151 | const AccessLogEntryPointer &al); |
75d47340 | 152 | private: |
4668df3d CT |
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; | |
75d47340 | 155 | |
70d0ef18 | 156 | /// Verifies that the key is not reserved (fatal error) and |
75d47340 | 157 | /// does not contain special characters (non-fatal error). |
75d47340 CT |
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 ¬eKey); | |
165 | Note::Pointer find(const SBuf ¬eKey); | |
b3404bc5 CT |
166 | |
167 | NotesList notes; ///< The Note::Pointer objects array list | |
4668df3d CT |
168 | const char *descr = nullptr; ///< identifies note source in error messages |
169 | ||
70d0ef18 | 170 | Keys reservedKeys; ///< a list of additional prohibited key names |
4668df3d CT |
171 | bool formattedValues = false; ///< whether to expand quoted logformat %codes |
172 | ||
70d0ef18 | 173 | static const Notes::Keys &ReservedKeys(); ///< always prohibited key names |
b3404bc5 CT |
174 | }; |
175 | ||
cf9f0261 CT |
176 | /** |
177 | * Used to store list of notes | |
178 | */ | |
179 | class NotePairs: public RefCountable | |
ffb82151 | 180 | { |
b3404bc5 | 181 | public: |
cf9f0261 CT |
182 | typedef RefCount<NotePairs> Pointer; |
183 | ||
75d47340 CT |
184 | /// Used to store a note key/value pair. |
185 | class Entry : public RefCountable | |
7e6ef752 | 186 | { |
741c2986 | 187 | MEMPROXY_CLASS(Entry); |
cf9f0261 | 188 | public: |
75d47340 CT |
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; | |
cf9f0261 | 204 | }; |
75d47340 | 205 | typedef std::vector<Entry::Pointer> Entries; ///< The key/value pair entries |
d665de37 | 206 | typedef std::vector<SBuf> Names; |
cf9f0261 | 207 | |
d74740bd | 208 | NotePairs() {} |
75d47340 CT |
209 | NotePairs &operator=(NotePairs const &) = delete; |
210 | NotePairs(NotePairs const &) = delete; | |
cf9f0261 | 211 | |
75d47340 | 212 | /// Append the entries of the src NotePairs list to our list. |
cf9f0261 CT |
213 | void append(const NotePairs *src); |
214 | ||
d665de37 A |
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 | ||
75d47340 CT |
220 | /// Replace existing list entries with the src NotePairs entries. |
221 | /// Entries which do not exist in the destination set are added. | |
457857fe CT |
222 | void replaceOrAdd(const NotePairs *src); |
223 | ||
75d47340 CT |
224 | /// Append any new entries of the src NotePairs list to our list. |
225 | /// Entries which already exist in the destination set are ignored. | |
71e7400c AJ |
226 | void appendNewOnly(const NotePairs *src); |
227 | ||
75d47340 CT |
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; | |
cf9f0261 | 232 | |
75d47340 | 233 | /// \returns the first note value for this key or an empty string. |
cf9f0261 CT |
234 | const char *findFirst(const char *noteKey) const; |
235 | ||
75d47340 CT |
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); | |
cf9f0261 CT |
240 | void add(const char *key, const char *value); |
241 | ||
75d47340 CT |
242 | /// Remove all notes with a given key. If keyLen is not |
243 | /// provided, the key is assumed null-terminated. | |
457857fe | 244 | void remove(const char *key); |
75d47340 CT |
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); | |
457857fe | 251 | |
75d47340 CT |
252 | /// \returns true if the key/value pair is already stored |
253 | bool hasPair(const SBuf &key, const SBuf &value) const; | |
254 | ||
e67eab3a FC |
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; | |
cf9f0261 | 258 | |
75d47340 | 259 | /// \returns true if there are not entries in the list |
cf9f0261 CT |
260 | bool empty() const {return entries.empty();} |
261 | ||
75d47340 CT |
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; | |
95c0dbfc CT |
267 | |
268 | private: | |
75d47340 | 269 | Entries entries; ///< The key/value pair entries |
b3404bc5 CT |
270 | }; |
271 | ||
ff9d9458 | 272 | #endif /* SQUID_SRC_NOTES_H */ |
f53969cc | 273 |