2 * Copyright (C) 1996-2020 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.
12 #include "acl/forward.h"
13 #include "base/RefCount.h"
14 #include "format/Format.h"
15 #include "mem/forward.h"
16 #include "SquidString.h"
26 typedef RefCount
<AccessLogEntry
> AccessLogEntryPointer
;
27 typedef RefCount
<NotePairs
> NotePairsPointer
;
30 * Used to store a note configuration. The notes are custom key:value
31 * pairs ICAP request headers or ECAP options used to pass
32 * custom transaction-state related meta information to squid
33 * internal subsystems or to adaptation services.
35 class Note
: public RefCountable
38 typedef RefCount
<Note
> Pointer
;
40 /// Stores a value for the note.
41 class Value
: public RefCountable
44 typedef RefCount
<Value
> Pointer
;
47 enum Method
{ mhReplace
, mhAppend
};
49 Value(const char *aVal
, const bool quoted
, const char *descr
, const Method method
= mhReplace
);
51 Value(const Value
&) = delete;
52 Value
&operator=(const Value
&) = delete;
54 Method
method() const { return theMethod
; }
55 const SBuf
&value() const { return theValue
; }
57 ACLList
*aclList
; ///< The access list used to determine if this value is valid for a request
60 /// \return the formatted value with expanded logformat %macros (quoted values).
61 /// \return the original value (non-quoted values).
62 const SBuf
&format(const AccessLogEntryPointer
&al
);
64 Format::Format
*valueFormat
; ///< Compiled annotation value format.
65 SBuf theValue
; ///< Configured annotation value, possibly with %macros.
66 /// The expanded value produced by format(), empty for non-quoted values.
67 SBuf theFormattedValue
;
68 /// Specifies how theValue will be applied to the existing annotation
69 /// with the same key: it either replaces the existing value or is appended
70 /// to the list of existing values.
73 typedef std::vector
<Value::Pointer
> Values
;
75 Note(const char *aKey
, const size_t keyLen
): theKey(aKey
, keyLen
) {}
76 explicit Note(const SBuf aKey
): theKey(aKey
) {}
77 Note(const Note
&) = delete;
78 Note
&operator=(const Note
&) = delete;
80 /// Adds a value to the note and returns a pointer to the
81 /// related Value object.
82 Value::Pointer
addValue(const char *value
, const bool quoted
, const char *descr
,
83 const Value::Method m
= Value::mhAppend
);
85 /// Walks through the possible values list of the note, selects
86 /// the first value, matching the given HttpRequest and HttpReply
87 /// and assigns the given 'matched' to it.
88 /// \return true if matched, false otherwise
89 bool match(HttpRequest
*request
, HttpReply
*reply
, const AccessLogEntryPointer
&al
, SBuf
&matched
);
90 const SBuf
&key() const { return theKey
; }
91 void updateNotePairs(NotePairsPointer pairs
, const CharacterSet
*delimiters
, const AccessLogEntryPointer
&al
);
92 /// Dump the single Note to the given StoreEntry object.
93 void dump(StoreEntry
*entry
, const char *key
);
94 /// For the key and all its Values compile a string of
95 /// "Key: Value" pairs separated by sep string.
96 SBuf
toString(const char *sep
) const;
99 SBuf theKey
; ///< The note key
100 Values values
; ///< The possible values list for the note
106 * Used to store a notes configuration list.
108 class Notes
: public RefCountable
111 typedef RefCount
<Notes
> Pointer
;
112 typedef std::vector
<SBuf
> Keys
; ///< unordered annotation names
113 typedef std::vector
<Note::Pointer
> NotesList
;
114 typedef NotesList::iterator iterator
; ///< iterates over the notes list
115 typedef NotesList::const_iterator const_iterator
; ///< iterates over the notes list
117 explicit Notes(const char *aDescr
, const Keys
*extraReservedKeys
= nullptr, bool allowFormatted
= true);
119 ~Notes() { notes
.clear(); }
120 Notes(const Notes
&) = delete;
121 Notes
&operator=(const Notes
&) = delete;
123 /// Parses a notes line and returns a pointer to the parsed Note object.
124 Note::Pointer
parse(ConfigParser
&parser
);
126 /// Parses an annotate line with "key=value" or "key+=value" formats.
129 /// Dump the notes list to the given StoreEntry object.
130 void dump(StoreEntry
*entry
, const char *name
);
131 /// clean the notes list
132 void clean() { notes
.clear(); }
134 /// points to the first argument
135 iterator
begin() { return notes
.begin(); }
136 /// points to the end of list
137 iterator
end() { return notes
.end(); }
138 /// \returns true if the notes list is empty
139 bool empty() const { return notes
.empty(); }
140 /// Convert Notes list to a string consist of "Key: Value"
141 /// entries separated by sep string.
142 const char *toString(const char *sep
= "\r\n") const;
143 void updateNotePairs(NotePairsPointer pairs
, const CharacterSet
*delimiters
,
144 const AccessLogEntryPointer
&al
);
146 /// Makes sure the given key is not on the given list of banned names.
147 void banReservedKey(const SBuf
&key
, const Keys
&banned
) const;
149 /// Verifies that the key is not reserved (fatal error) and
150 /// does not contain special characters (non-fatal error).
151 void validateKey(const SBuf
&key
) const;
153 /// Adds a note to the notes list and returns a pointer to the
154 /// related Note object. If the note key already exists in list,
155 /// returns a pointer to the existing object.
156 /// If keyLen is not provided, the noteKey is assumed null-terminated.
157 Note::Pointer
add(const SBuf
¬eKey
);
158 Note::Pointer
find(const SBuf
¬eKey
);
160 NotesList notes
; ///< The Note::Pointer objects array list
161 const char *descr
= nullptr; ///< identifies note source in error messages
163 Keys reservedKeys
; ///< a list of additional prohibited key names
164 bool formattedValues
= false; ///< whether to expand quoted logformat %codes
166 static const Notes::Keys
&ReservedKeys(); ///< always prohibited key names
170 * Used to store list of notes
172 class NotePairs
: public RefCountable
175 typedef RefCount
<NotePairs
> Pointer
;
177 /// Used to store a note key/value pair.
178 class Entry
: public RefCountable
180 MEMPROXY_CLASS(Entry
);
182 typedef RefCount
<Entry
> Pointer
;
184 Entry(const SBuf
&aKey
, const SBuf
&aValue
)
185 : theName(aKey
), theValue(aValue
) {}
186 Entry(const char *aKey
, const char *aValue
)
187 : theName(aKey
), theValue(aValue
) {}
188 Entry(const Entry
&) = delete;
189 Entry
&operator=(const Entry
&) = delete;
191 const SBuf
&name() const { return theName
; }
192 const SBuf
&value() const { return theValue
; }
198 typedef std::vector
<Entry::Pointer
> Entries
; ///< The key/value pair entries
199 typedef std::vector
<SBuf
> Names
;
202 NotePairs
&operator=(NotePairs
const &) = delete;
203 NotePairs(NotePairs
const &) = delete;
205 /// Append the entries of the src NotePairs list to our list.
206 void append(const NotePairs
*src
);
208 /// Replace existing list entries with the src NotePairs entries.
209 /// Do not replace but append entries named in the appendables
210 /// Entries which do not exist in the destination set are added.
211 void replaceOrAddOrAppend(const NotePairs
*src
, const Names
&appendables
);
213 /// Replace existing list entries with the src NotePairs entries.
214 /// Entries which do not exist in the destination set are added.
215 void replaceOrAdd(const NotePairs
*src
);
217 /// Append any new entries of the src NotePairs list to our list.
218 /// Entries which already exist in the destination set are ignored.
219 void appendNewOnly(const NotePairs
*src
);
221 /// \param resultNote a comma separated list of notes with key 'noteKey'.
222 /// \returns true if there are entries with the given 'noteKey'.
223 /// Use findFirst() instead when a unique kv-pair is needed.
224 bool find(SBuf
&resultNote
, const char *noteKey
, const char *sep
= ",") const;
226 /// \returns the first note value for this key or an empty string.
227 const char *findFirst(const char *noteKey
) const;
229 /// Adds a note key and value to the notes list.
230 /// If the key name already exists in the list, add the given value to its set
232 void add(const SBuf
&key
, const SBuf
&value
);
233 void add(const char *key
, const char *value
);
235 /// Remove all notes with a given key. If keyLen is not
236 /// provided, the key is assumed null-terminated.
237 void remove(const char *key
);
238 void remove(const SBuf
&key
);
240 /// Adds a note key and values strList to the notes list.
241 /// If the key name already exists in the list, add the new values to its set
243 void addStrList(const SBuf
&key
, const SBuf
&values
, const CharacterSet
&delimiters
);
245 /// \returns true if the key/value pair is already stored
246 bool hasPair(const SBuf
&key
, const SBuf
&value
) const;
248 /// Convert NotePairs list to a string consist of "Key: Value"
249 /// entries separated by sep string.
250 const char *toString(const char *sep
= "\r\n") const;
252 /// \returns true if there are not entries in the list
253 bool empty() const {return entries
.empty();}
255 void clear() { entries
.clear(); }
257 /// If delimiters are provided, returns another Entries, converting each single multi-token
258 /// pair to multiple single-token pairs; returns existing entries otherwise.
259 const Entries
&expandListEntries(const CharacterSet
*delimiters
) const;
262 Entries entries
; ///< The key/value pair entries