Options.cc
Go to the documentation of this file.
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#include "squid.h"
10#include "acl/Options.h"
11#include "ConfigParser.h"
12#include "debug/Stream.h"
13#include "sbuf/Stream.h"
14
15#include <iostream>
16#include <utility>
17#include <vector>
18
19namespace Acl {
20
23{
24public:
27 bool extractOne();
28
29 /* extracted option details (after successful extraction */
31 bool hasValue = false;
32 const SBuf &value() const;
33
34protected:
35 bool advance();
36 void extractWhole();
37 void extractShort();
38
39private:
43 bool sawValue_ = false;
44};
45
48{
49public:
50 explicit OptionsParser(const Options &options);
51
52 // fill previously supplied options container, throwing on errors
53 void parse();
54
55private:
56 using SupportedOption = std::pair<const Option *, bool /* enable */ >;
57 SupportedOption supportedOption(const SBuf &name) const;
58
60};
61
62} // namespace Acl
63
64/* Acl::Option */
65
66Acl::Option::Option(const char * const nameThatEnables, const char * const nameThatDisables, const ValueExpectation vex):
67 onName(nameThatEnables),
68 offName(nameThatDisables),
69 valueExpectation(vex)
70{
72}
73
74/* Acl::OptionExtractor */
75
76const SBuf &
78{
79 Must(hasValue);
80 return value_;
81}
82
83bool
85{
86 if (!prefix_.isEmpty()) {
87 extractShort(); // continue with the previously extracted flags
88 return true;
89 }
90
91 if (!advance())
92 return false; // end of options (and, possibly, the whole "acl" directive)
93
94 if (prefix_.length() < 2)
95 throw TexcHere(ToSBuf("truncated(?) ACL flag: ", prefix_)); // single - or +
96
97 if (prefix_[0] == '-' && prefix_[1] == '-') {
98 if (prefix_.length() == 2)
99 return false; // skipped "--", an explicit end-of-options marker
100 extractWhole();
101 return true;
102 }
103
104 if (prefix_.length() == 2) { // common trivial case: -x or +y
105 extractWhole();
106 return true;
107 }
108
109 // -xyz or +xyz
110 letterPos_ = 1;
111 extractShort();
112 return true;
113}
114
116bool
118{
119 const char *next = ConfigParser::PeekAtToken();
120 if (!next)
121 return false; // end of the "acl" line
122
123 const char nextChar = *next;
124 if (!(nextChar == '-' || nextChar == '+'))
125 return false; // start of ACL parameters
126
127 sawValue_ = strchr(next, '='); // TODO: Make ConfigParser reject '^=.*' tokens
128 if (sawValue_) {
129 char *rawPrefix = nullptr;
130 char *rawValue = nullptr;
131 if (!ConfigParser::NextKvPair(rawPrefix, rawValue))
132 throw TexcHere(ToSBuf("Malformed acl option=value: ", next));
133 prefix_.assign(rawPrefix);
134 value_.assign(rawValue);
135 } else {
136 prefix_.assign(next);
137 ConfigParser::NextToken(); // consume what we have peeked at
138 }
139 return true;
140}
141
143void
145{
146 debugs(28, 8, "from " << prefix_ << " value: " << sawValue_);
147 hasValue = sawValue_;
148 name = prefix_;
149 prefix_.clear();
150}
151
153void
155{
156 debugs(28, 8, "from " << prefix_ << " at " << letterPos_ << " value: " << sawValue_);
157 name.assign(prefix_.rawContent(), 1); // leading - or +
158 name.append(prefix_.at(letterPos_++));
159 if (letterPos_ >= prefix_.length()) { // got last flag in the sequence
160 hasValue = sawValue_;
161 prefix_.clear();
162 } else {
163 hasValue = false;
164 }
165}
166
167/* Acl::OptionsParser */
168
170 options_(options)
171{
172}
173
177{
178 for (const auto option: options_) {
179 if (name.cmp(option->onName) == 0)
180 return SupportedOption(option, true);
181 if (option->offName && name.cmp(option->offName) == 0)
182 return SupportedOption(option, false);
183 }
184
185 throw TexcHere(ToSBuf("unsupported ACL option: ", name));
186}
187
188void
190{
191 OptionExtractor oex;
192 while (oex.extractOne()) {
193 const auto explicitOption = supportedOption(oex.name);
194 const auto &option = *explicitOption.first;
195 if (explicitOption.second) {
196 /* configuration enables this option */
197 if (option.configured())
198 debugs(28, 7, "acl uses multiple " << oex.name << " options");
199 switch (option.valueExpectation)
200 {
202 if (oex.hasValue)
203 throw TexcHere(ToSBuf("unexpected value for an ACL option: ", oex.name, '=', oex.value()));
204 option.enable();
205 break;
207 if (!oex.hasValue)
208 throw TexcHere(ToSBuf("missing required value for ACL option ", oex.name));
209 option.configureWith(oex.value());
210 break;
212 if (oex.hasValue)
213 option.configureWith(oex.value());
214 else
215 option.enable();
216 break;
217 }
218 } else {
219 if (oex.hasValue)
220 throw TexcHere(ToSBuf("unexpected value when disabling an ACL option: ", oex.name, '=', oex.value()));
221 option.disable();
222 }
223 }
224}
225
226void
228{
229 OptionsParser parser(options);
230 parser.parse();
231}
232
233const Acl::Options &
235{
236 static const Options none;
237 return none;
238}
239
240const Acl::BooleanOption &
242{
243 static const BooleanOption MyOption("-i", "+i");
244 return MyOption;
245}
246
247std::ostream &
248Acl::operator <<(std::ostream &os, const Option &option)
249{
250 option.print(os);
251 return os;
252}
253
254std::ostream &
255Acl::operator <<(std::ostream &os, const Options &options)
256{
257 for (const auto option: options)
258 os << *option;
259
260 // TODO: Remember "--" presence and print that delimiter when present.
261 // Detecting its need is difficult because parameter flags start with "-".
262 return os;
263}
264
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
Definition: TextException.h:63
#define Must(condition)
Definition: TextException.h:75
#define assert(EX)
Definition: assert.h:17
low-level parser that extracts but does not interpret ACL options
Definition: Options.cc:23
bool advance()
extracts a token with the next option/flag(s) or returns false
Definition: Options.cc:117
bool sawValue_
the current option sequence had a value
Definition: Options.cc:43
const SBuf & value() const
extracted option value (requires hasValue)
Definition: Options.cc:77
SBuf name
extracted option name, including dash(es)
Definition: Options.cc:30
SBuf prefix_
option name(s), including leading dash(es)
Definition: Options.cc:40
bool hasValue
whether the option has a value (-x=value)
Definition: Options.cc:31
void extractWhole()
handles -x[=option] or –foo[=option]
Definition: Options.cc:144
SBuf::size_type letterPos_
letter position inside an -xyz sequence
Definition: Options.cc:42
SBuf value_
the last seen value of some option
Definition: Options.cc:41
void extractShort()
handles one flag letter inside an -xyx[=option] or +xyz[=option] sequence
Definition: Options.cc:154
A single option supported by an ACL: -x[=value] or –name[=value].
Definition: Options.h:57
const char *const onName
A name that must be used to explicitly enable this Option (required).
Definition: Options.h:88
virtual void print(std::ostream &os) const =0
prints a configuration snippet (as an admin could have typed)
Option(const char *nameThatEnables, const char *nameThatDisables=nullptr, ValueExpectation vex=valueNone)
Definition: Options.cc:66
ValueExpectation
Definition: Options.h:59
@ valueNone
Definition: Options.h:59
@ valueRequired
Definition: Options.h:59
@ valueOptional
Definition: Options.h:59
parses/validates/stores ACL options; skips/preserves parameter flags
Definition: Options.cc:48
OptionsParser(const Options &options)
Definition: Options.cc:169
const Options & options_
caller-supported, linked options
Definition: Options.cc:59
SupportedOption supportedOption(const SBuf &name) const
Definition: Options.cc:176
std::pair< const Option *, bool > SupportedOption
Definition: Options.cc:56
a type-specific Option (e.g., a boolean –toggle or -m=SBuf)
Definition: Options.h:130
static char * PeekAtToken()
static bool NextKvPair(char *&key, char *&value)
static char * NextToken()
Definition: SBuf.h:94
int cmp(const SBuf &S, const size_type n) const
shorthand version for compare()
Definition: SBuf.h:275
MemBlob::size_type size_type
Definition: SBuf.h:96
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
Definition: Acl.cc:31
std::ostream & operator<<(std::ostream &o, const Answer a)
Definition: Acl.h:177
const BooleanOption & CaseSensitivityOption()
Definition: Options.cc:241
const Options & NoOptions()
Definition: Options.cc:234
void ParseFlags(const Options &options)
Definition: Options.cc:227
std::vector< const Option * > Options
Definition: Options.h:214
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors