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