/* * Copyright (C) 1996-2023 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. */ #ifndef SQUID_ACL_OPTIONS_H #define SQUID_ACL_OPTIONS_H #include "acl/forward.h" #include "sbuf/forward.h" #include #include #include // After all same-name acl configuration lines are merged into one ACL: // configuration = acl name type [option...] [[flag...] parameter...] // option = -x[=value] | --name[=value] // flag = option // // Options and flags use the same syntax, but differ in scope and handling code: // * ACL options appear before all parameters and apply to all parameters. // They are handled by ACL kids (or equivalent). // * Parameter flags may appear after some other parameters and apply only to // the subsequent parameters (until they are overwritten by later flags). // They are handled by ACLData kids. // ACL options parsing code skips and leaves leading parameter flags (if any) // for ACLData code to process. namespace Acl { typedef const char *OptionName; /// A single option supported by an ACL: -x[=value] or --name[=value] /// Unlike a parameter flag, this option applies to all ACL parameters. class Option { public: typedef enum { valueNone, valueOptional, valueRequired } ValueExpectation; explicit Option(ValueExpectation vex = valueNone): valueExpectation(vex) {} virtual ~Option() {} /// whether the admin explicitly specified this option /// (i.e., whether configureWith() or configureDefault() has been called) virtual bool configured() const = 0; /// called after parsing -x or --name virtual void configureDefault() const = 0; /// called after parsing -x=value or --name=value virtual void configureWith(const SBuf &rawValue) const = 0; virtual bool valued() const = 0; /// prints a configuration snippet (as an admin could have typed) virtual void print(std::ostream &os) const = 0; ValueExpectation valueExpectation = valueNone; ///< expect "=value" part? }; /// Stores configuration of a typical boolean flag or a single-value Option. template class OptionValue { public: typedef Value value_type; OptionValue(): value {} {} explicit OptionValue(const Value &aValue): value(aValue) {} explicit operator bool() const { return configured; } Value value; ///< final value storage, possibly after conversions bool configured = false; ///< whether the option was present in squid.conf bool valued = false; ///< whether a configured option had a value }; /// a type-specific Option (e.g., a boolean --toggle or -m=SBuf) template class TypedOption: public Option { public: //typedef typename Recipient::value_type value_type; explicit TypedOption(ValueExpectation vex = valueNone): Option(vex) {} /// who to tell when this option is enabled void linkWith(Recipient *recipient) const { assert(recipient); recipient_ = recipient; } /* Option API */ virtual bool configured() const override { return recipient_ && recipient_->configured; } virtual bool valued() const override { return recipient_ && recipient_->valued; } /// sets the default value when option is used without a value virtual void configureDefault() const override { assert(recipient_); recipient_->configured = true; recipient_->valued = false; // sets recipient_->value to default setDefault(); } /// sets the option value from rawValue virtual void configureWith(const SBuf &rawValue) const override { assert(recipient_); recipient_->configured = true; recipient_->valued = true; import(rawValue); } virtual void print(std::ostream &os) const override { if (valued()) os << recipient_->value; } private: void import(const SBuf &rawValue) const { recipient_->value = rawValue; } void setDefault() const { /*leave recipient_->value as is*/} // The "mutable" specifier demarcates set-once Option kind/behavior from the // ever-changing recipient of the actual admin-configured option value. mutable Recipient *recipient_ = nullptr; ///< parsing results storage }; /* two typical option kinds: --foo and --bar=text */ typedef OptionValue BooleanOptionValue; typedef OptionValue TextOptionValue; typedef TypedOption BooleanOption; typedef TypedOption TextOption; // this specialization should never be called until we start supporting // boolean option values like --name=enable or --name=false template <> inline void BooleanOption::import(const SBuf &) const { assert(!"boolean options do not have ...=values (for now)"); } template <> inline void BooleanOption::setDefault() const { recipient_->value = true; } /// option name comparison functor class OptionNameCmp { public: bool operator()(const OptionName a, const OptionName b) const; }; /// name:option map typedef std::map Options; /// a set of parameter flag names typedef std::set ParameterFlags; /// parses the flags part of the being-parsed ACL, filling Option values /// \param options options supported by the ACL as a whole (e.g., -n) /// \param flags options supported by ACL parameter(s) (e.g., -i) void ParseFlags(const Options &options, const ParameterFlags &flags); /* handy for Class::options() and Class::supportedFlags() defaults */ const Options &NoOptions(); ///< \returns an empty Options container const ParameterFlags &NoFlags(); ///< \returns an empty ParameterFlags container } // namespace Acl std::ostream &operator <<(std::ostream &os, const Acl::Option &option); std::ostream &operator <<(std::ostream &os, const Acl::Options &options); #endif /* SQUID_ACL_OPTIONS_H */