2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_SRC_NOTES_H
10 #define SQUID_SRC_NOTES_H
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"
28 typedef RefCount
<AccessLogEntry
> AccessLogEntryPointer
;
29 typedef RefCount
<NotePairs
> NotePairsPointer
;
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.
37 class Note
: public RefCountable
40 typedef RefCount
<Note
> Pointer
;
42 /// Stores a value for the note.
43 class Value
: public RefCountable
46 typedef RefCount
<Value
> Pointer
;
49 enum Method
{ mhReplace
, mhAppend
};
51 Value(const char *aVal
, const bool quoted
, const char *descr
, const Method method
= mhReplace
);
53 Value(const Value
&) = delete;
54 Value
&operator=(const Value
&) = delete;
56 Method
method() const { return theMethod
; }
57 const SBuf
&value() const { return theValue
; }
59 ACLList
*aclList
; ///< The access list used to determine if this value is valid for a request
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
);
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.
75 typedef std::vector
<Value::Pointer
> Values
;
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;
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
);
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
);
95 /// Prints key and value(s) using a "note" directive format (including directive name).
96 void printAsNoteDirective(StoreEntry
*, const char *directiveName
) const;
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;
103 SBuf theKey
; ///< The note key
104 Values values
; ///< The possible values list for the note
110 * Used to store a notes configuration list.
112 class Notes
: public RefCountable
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
121 explicit Notes(const char *aDescr
, const Keys
*extraReservedKeys
= nullptr, bool allowFormatted
= true);
123 ~Notes() override
{ notes
.clear(); }
124 Notes(const Notes
&) = delete;
125 Notes
&operator=(const Notes
&) = delete;
127 /// Parses a notes line and returns a pointer to the parsed Note object.
128 Note::Pointer
parse(ConfigParser
&parser
);
130 /// Parses an annotate line with "key=value" or "key+=value" formats.
133 /// Prints notes using "note" squid.conf directive format, one directive per stored note.
134 void printAsNoteDirectives(StoreEntry
*, const char *directiveName
) const;
136 /// clean the notes list
137 void clean() { notes
.clear(); }
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(); }
146 /// print notes using "annotate_transaction acl parameters" format, one
147 /// key=value parameter per note
148 void printAsAnnotationAclParameters(std::ostream
&) const;
150 void updateNotePairs(NotePairsPointer pairs
, const CharacterSet
*delimiters
,
151 const AccessLogEntryPointer
&al
);
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;
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;
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
);
167 NotesList notes
; ///< The Note::Pointer objects array list
168 const char *descr
= nullptr; ///< identifies note source in error messages
170 Keys reservedKeys
; ///< a list of additional prohibited key names
171 bool formattedValues
= false; ///< whether to expand quoted logformat %codes
173 static const Notes::Keys
&ReservedKeys(); ///< always prohibited key names
177 * Used to store list of notes
179 class NotePairs
: public RefCountable
182 typedef RefCount
<NotePairs
> Pointer
;
184 /// Used to store a note key/value pair.
185 class Entry
: public RefCountable
187 MEMPROXY_CLASS(Entry
);
189 typedef RefCount
<Entry
> Pointer
;
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;
198 const SBuf
&name() const { return theName
; }
199 const SBuf
&value() const { return theValue
; }
205 typedef std::vector
<Entry::Pointer
> Entries
; ///< The key/value pair entries
206 typedef std::vector
<SBuf
> Names
;
209 NotePairs
&operator=(NotePairs
const &) = delete;
210 NotePairs(NotePairs
const &) = delete;
212 /// Append the entries of the src NotePairs list to our list.
213 void append(const NotePairs
*src
);
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
);
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
);
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
);
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;
233 /// \returns the first note value for this key or an empty string.
234 const char *findFirst(const char *noteKey
) const;
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
239 void add(const SBuf
&key
, const SBuf
&value
);
240 void add(const char *key
, const char *value
);
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
);
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
250 void addStrList(const SBuf
&key
, const SBuf
&values
, const CharacterSet
&delimiters
);
252 /// \returns true if the key/value pair is already stored
253 bool hasPair(const SBuf
&key
, const SBuf
&value
) const;
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;
259 /// \returns true if there are not entries in the list
260 bool empty() const {return entries
.empty();}
262 void clear() { entries
.clear(); }
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;
269 Entries entries
; ///< The key/value pair entries
272 #endif /* SQUID_SRC_NOTES_H */