]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2025 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 | #ifndef SQUID_SRC_CONFIGPARSER_H | |
10 | #define SQUID_SRC_CONFIGPARSER_H | |
11 | ||
12 | #include "acl/forward.h" | |
13 | #include "base/forward.h" | |
14 | #include "sbuf/forward.h" | |
15 | #include "SquidString.h" | |
16 | ||
17 | #include <memory> | |
18 | #include <queue> | |
19 | #include <stack> | |
20 | #include <string> | |
21 | ||
22 | class CachePeer; | |
23 | class wordlist; | |
24 | ||
25 | /** | |
26 | * Limit to how long any given config line may be. | |
27 | * This affects squid.conf and all included files. | |
28 | * | |
29 | * Behaviour when setting larger than 2KB is unknown. | |
30 | * The config parser read mechanism can cope, but the other systems | |
31 | * receiving the data from its buffers on such lines may not. | |
32 | */ | |
33 | #define CONFIG_LINE_LIMIT 2048 | |
34 | ||
35 | /** | |
36 | * A configuration file Parser. Instances of this class track | |
37 | * parsing state and perform tokenisation. Syntax is currently | |
38 | * taken care of outside this class. | |
39 | * | |
40 | * One reason for this class is to allow testing of configuration | |
41 | * using modules without linking cache_cf.o in - because that drags | |
42 | * in all of squid by reference. Instead the tokeniser only is | |
43 | * brought in. | |
44 | */ | |
45 | class ConfigParser | |
46 | { | |
47 | ||
48 | public: | |
49 | /** | |
50 | * Parsed tokens type: simple tokens, quoted tokens or function | |
51 | * like parameters. | |
52 | */ | |
53 | enum TokenType {SimpleToken, QuotedToken, FunctionParameters}; | |
54 | ||
55 | void destruct(); | |
56 | ||
57 | /// stops parsing the current configuration directive | |
58 | void closeDirective(); | |
59 | ||
60 | /// rejects configuration due to a repeated directive | |
61 | void rejectDuplicateDirective(); | |
62 | ||
63 | /// extracts and returns a required token | |
64 | SBuf token(const char *expectedTokenDescription); | |
65 | ||
66 | /// extracts an optional key=value token or returns false | |
67 | /// rejects configurations with empty keys or empty values | |
68 | /// key and value have lifetime of the current line/directive | |
69 | bool optionalKvPair(char * &key, char * &value); | |
70 | ||
71 | /// either extracts the given (optional) token or returns false | |
72 | bool skipOptional(const char *keyword); | |
73 | ||
74 | /// parses an [if [!]<acl>...] construct | |
75 | ACLList *optionalAclList(); | |
76 | ||
77 | /// extracts and returns a regex (including any optional flags) | |
78 | std::unique_ptr<RegexPattern> regex(const char *expectedRegexDescription); | |
79 | ||
80 | /// extracts a cache_peer name token and returns the corresponding CachePeer | |
81 | CachePeer &cachePeer(const char *peerNameTokenDescription); | |
82 | ||
83 | static void ParseUShort(unsigned short *var); | |
84 | static void ParseBool(bool *var); | |
85 | static const char *QuoteString(const String &var); | |
86 | static void ParseWordList(wordlist **list); | |
87 | ||
88 | /** | |
89 | * Backward compatibility wrapper for the ConfigParser::NextToken method. | |
90 | * If the configuration_includes_quoted_values configuration parameter is | |
91 | * set to 'off' this interprets the quoted tokens as filenames. | |
92 | */ | |
93 | static char * strtokFile(); | |
94 | ||
95 | /** | |
96 | * Returns the body of the next element. The element is either a token or | |
97 | * a quoted string with optional escape sequences and/or macros. The body | |
98 | * of a quoted string element does not include quotes or escape sequences. | |
99 | * Future code will want to see Elements and not just their bodies. | |
100 | */ | |
101 | static char *NextToken(); | |
102 | ||
103 | /** | |
104 | * Backward compatibility wrapper for ConfigParser::RegexPattern method. | |
105 | * If the configuration_includes_quoted_values configuration parameter is | |
106 | * set to 'off' this interprets the quoted tokens as filenames. | |
107 | */ | |
108 | static char *RegexStrtokFile(); | |
109 | ||
110 | /** | |
111 | * Parse the next token with support for quoted values enabled even if | |
112 | * the configuration_includes_quoted_values is set to off | |
113 | */ | |
114 | static char *NextQuotedToken(); | |
115 | ||
116 | /// \return true if the last parsed token was quoted | |
117 | static bool LastTokenWasQuoted() {return (LastTokenType == ConfigParser::QuotedToken);} | |
118 | ||
119 | /** | |
120 | * \return the next quoted string or the raw string data until the end of line. | |
121 | * This method allows %macros in unquoted strings to keep compatibility | |
122 | * for the logformat option. | |
123 | */ | |
124 | static char *NextQuotedOrToEol(); | |
125 | ||
126 | /** | |
127 | * the next key value pair which must be separated by "=" | |
128 | * \return true on success, false otherwise | |
129 | */ | |
130 | static bool NextKvPair(char * &key, char * &value); | |
131 | ||
132 | /** | |
133 | * Preview the next token. The next NextToken() and strtokFile() call | |
134 | * will return the same token. | |
135 | * On parse error (eg invalid characters in token) will return an | |
136 | * error message as token. | |
137 | */ | |
138 | static char *PeekAtToken(); | |
139 | ||
140 | /// Set the configuration file line to parse. | |
141 | static void SetCfgLine(char *line); | |
142 | ||
143 | /// Allow %macros inside quoted strings | |
144 | static void EnableMacros() {AllowMacros_ = true;} | |
145 | ||
146 | /// Do not allow %macros inside quoted strings | |
147 | static void DisableMacros() {AllowMacros_ = false;} | |
148 | ||
149 | static SBuf CurrentLocation(); | |
150 | ||
151 | /// configuration_includes_quoted_values in squid.conf | |
152 | static bool RecognizeQuotedValues; | |
153 | ||
154 | /** | |
155 | * Strict syntax mode. Does not allow not alphanumeric characters in unquoted tokens. | |
156 | * Controlled by the configuration_includes_quoted_values in squid.conf but remains | |
157 | * false when the the legacy ConfigParser::NextQuotedToken() call forces | |
158 | * RecognizeQuotedValues to be temporary true. | |
159 | */ | |
160 | static bool StrictMode; | |
161 | ||
162 | protected: | |
163 | /** | |
164 | * Class used to store required information for the current | |
165 | * configuration file. | |
166 | */ | |
167 | class CfgFile | |
168 | { | |
169 | public: | |
170 | CfgFile(): wordFile(nullptr), parsePos(nullptr), lineNo(0) { parseBuffer[0] = '\0';} | |
171 | ~CfgFile(); | |
172 | /// True if the configuration file is open | |
173 | bool isOpen() {return wordFile != nullptr;} | |
174 | ||
175 | /** | |
176 | * Open the file given by 'path' and initializes the CfgFile object | |
177 | * to start parsing | |
178 | */ | |
179 | bool startParse(char *path); | |
180 | ||
181 | /** | |
182 | * Do the next parsing step: | |
183 | * reads the next line from file if required. | |
184 | * \return the body of next element or a NULL pointer if there are no more token elements in the file. | |
185 | * \param type will be filled with the ConfigParse::TokenType for any element found, or left unchanged if NULL is returned. | |
186 | */ | |
187 | char *parse(TokenType &type); | |
188 | ||
189 | private: | |
190 | bool getFileLine(); ///< Read the next line from the file | |
191 | /** | |
192 | * Return the body of the next element. If the wasQuoted is given | |
193 | * set to true if the element was quoted. | |
194 | */ | |
195 | char *nextElement(TokenType &type); | |
196 | FILE *wordFile; ///< Pointer to the file. | |
197 | char parseBuffer[CONFIG_LINE_LIMIT]; ///< Temporary buffer to store data to parse | |
198 | const char *parsePos; ///< The next element position in parseBuffer string | |
199 | public: | |
200 | std::string filePath; ///< The file path | |
201 | std::string currentLine; ///< The current line to parse | |
202 | int lineNo; ///< Current line number | |
203 | }; | |
204 | ||
205 | /** | |
206 | * Unquotes the token, which must be quoted. | |
207 | * \param next if it is not NULL, it is set after the end of token. | |
208 | */ | |
209 | static char *UnQuote(const char *token, const char **next = nullptr); | |
210 | ||
211 | /** | |
212 | * Does the real tokens parsing job: Ignore comments, unquote an | |
213 | * element if required. | |
214 | * \return the next token, or NULL if there are no available tokens in the nextToken string. | |
215 | * \param nextToken updated to point to the pos after parsed token. | |
216 | * \param type The token type | |
217 | */ | |
218 | static char *TokenParse(const char * &nextToken, TokenType &type); | |
219 | ||
220 | /// Wrapper method for TokenParse. | |
221 | static char *NextElement(TokenType &type); | |
222 | static std::stack<CfgFile *> CfgFiles; ///< The stack of open cfg files | |
223 | static TokenType LastTokenType; ///< The type of last parsed element | |
224 | static const char *CfgLine; ///< The current line to parse | |
225 | static const char *CfgPos; ///< Pointer to the next element in cfgLine string | |
226 | static std::queue<char *> CfgLineTokens_; ///< Store the list of tokens for current configuration line | |
227 | static bool AllowMacros_; | |
228 | static bool ParseQuotedOrToEol_; ///< The next tokens will be handled as quoted or to_eol token | |
229 | static bool RecognizeQuotedPair_; ///< The next tokens may contain quoted-pair (\-escaped) characters | |
230 | static bool PreviewMode_; ///< The next token will not popped from cfg files, will just previewd. | |
231 | static bool ParseKvPair_; ///<The next token will be handled as kv-pair token | |
232 | static enum ParsingStates {atParseKey, atParseValue} KvPairState_; ///< Parsing state while parsing kv-pair tokens | |
233 | }; | |
234 | ||
235 | namespace Configuration { | |
236 | /// interprets (and partially applies) squid.conf or equivalent configuration | |
237 | void Parse(); | |
238 | } | |
239 | ||
240 | #endif /* SQUID_SRC_CONFIGPARSER_H */ | |
241 |