]> git.ipfire.org Git - thirdparty/squid.git/blob - src/Parsing.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / Parsing.cc
1 /*
2 * Copyright (C) 1996-2016 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 /* DEBUG: section 03 Configuration File Parsing */
10
11 #include "squid.h"
12 #include "cache_cf.h"
13 #include "compat/strtoll.h"
14 #include "ConfigParser.h"
15 #include "Debug.h"
16 #include "globals.h"
17 #include "Parsing.h"
18
19 /*
20 * These functions is the same as atoi/l/f, except that they check for errors
21 */
22
23 double
24 xatof(const char *token)
25 {
26 char *end = NULL;
27 double ret = strtod(token, &end);
28
29 if (ret == 0 && end == token) {
30 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'.");
31 self_destruct();
32 }
33
34 if (*end) {
35 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid value: '" << token << "' is supposed to be a number.");
36 self_destruct();
37 }
38
39 return ret;
40 }
41
42 int
43 xatoi(const char *token)
44 {
45 int64_t input = xatoll(token, 10);
46 int ret = (int) input;
47
48 if (input != static_cast<int64_t>(ret)) {
49 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'int'.");
50 self_destruct();
51 }
52
53 return ret;
54 }
55
56 unsigned int
57 xatoui(const char *token, char eov)
58 {
59 int64_t input = xatoll(token, 10, eov);
60 if (input < 0) {
61 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The input value '" << token << "' cannot be less than 0.");
62 self_destruct();
63 }
64
65 unsigned int ret = (unsigned int) input;
66 if (input != static_cast<int64_t>(ret)) {
67 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'unsigned int'.");
68 self_destruct();
69 }
70
71 return ret;
72 }
73
74 long
75 xatol(const char *token)
76 {
77 int64_t input = xatoll(token, 10);
78 long ret = (long) input;
79
80 if (input != static_cast<int64_t>(ret)) {
81 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'long'.");
82 self_destruct();
83 }
84
85 return ret;
86 }
87
88 int64_t
89 xatoll(const char *token, int base, char eov)
90 {
91 char *end = NULL;
92 int64_t ret = strtoll(token, &end, base);
93
94 if (end == token) {
95 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'.");
96 self_destruct();
97 }
98
99 if (*end != eov) {
100 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid value: '" << token << "' is supposed to be a number.");
101 self_destruct();
102 }
103
104 return ret;
105 }
106
107 unsigned short
108 xatos(const char *token)
109 {
110 long port = xatol(token);
111
112 if (port < 0) {
113 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' cannot be less than 0.");
114 self_destruct();
115 }
116
117 if (port & ~0xFFFF) {
118 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'short'.");
119 self_destruct();
120 }
121
122 return port;
123 }
124
125 int64_t
126 GetInteger64(void)
127 {
128 char *token = ConfigParser::NextToken();
129
130 if (token == NULL)
131 self_destruct();
132
133 return xatoll(token, 10);
134 }
135
136 /*
137 * This function is different from others (e.g., GetInteger64, GetShort)
138 * because it supports octal and hexadecimal numbers
139 */
140 int
141 GetInteger(void)
142 {
143 char *token = ConfigParser::NextToken();
144 int i;
145
146 if (token == NULL)
147 self_destruct();
148
149 // The conversion must honor 0 and 0x prefixes, which are important for things like umask
150 int64_t ret = xatoll(token, 0);
151
152 i = (int) ret;
153 if (ret != static_cast<int64_t>(i)) {
154 debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'int'.");
155 self_destruct();
156 }
157
158 return i;
159 }
160
161 /*
162 * This function is similar as GetInteger() but the token might contain
163 * the percentage symbol (%) and we check whether the value is in the range
164 * of [0, 100]
165 * So, we accept two types of input: 1. XX% or 2. XX , 0<=XX<=100
166 * unless the limit parameter is set to false.
167 */
168 double
169 GetPercentage(bool limit)
170 {
171 char *token = ConfigParser::NextToken();
172
173 if (!token) {
174 debugs(3, DBG_CRITICAL, "FATAL: A percentage value is missing.");
175 self_destruct();
176 }
177
178 //if there is a % in the end of the digits, we remove it and go on.
179 char* end = &token[strlen(token)-1];
180 if (*end == '%') {
181 *end = '\0';
182 }
183
184 int p = xatoi(token);
185
186 if (p < 0 || (limit && p > 100)) {
187 debugs(3, DBG_CRITICAL, "FATAL: The value '" << token << "' is out of range. A percentage should be within [0, 100].");
188 self_destruct();
189 }
190
191 return static_cast<double>(p) / 100.0;
192 }
193
194 unsigned short
195 GetShort(void)
196 {
197 char *token = ConfigParser::NextToken();
198
199 if (token == NULL)
200 self_destruct();
201
202 return xatos(token);
203 }
204
205 bool
206 StringToInt(const char *s, int &result, const char **p, int base)
207 {
208 if (s) {
209 char *ptr = 0;
210 const int h = (int) strtol(s, &ptr, base);
211
212 if (ptr != s && ptr) {
213 result = h;
214
215 if (p)
216 *p = ptr;
217
218 return true;
219 }
220 }
221
222 return false;
223 }
224
225 bool
226 StringToInt64(const char *s, int64_t &result, const char **p, int base)
227 {
228 if (s) {
229 char *ptr = 0;
230 const int64_t h = (int64_t) strtoll(s, &ptr, base);
231
232 if (ptr != s && ptr) {
233 result = h;
234
235 if (p)
236 *p = ptr;
237
238 return true;
239 }
240 }
241
242 return false;
243 }
244
245 bool
246 GetHostWithPort(char *token, Ip::Address *ipa)
247 {
248 char *t;
249 char *host;
250 char *tmp;
251 unsigned short port;
252
253 host = NULL;
254 port = 0;
255
256 if (*token == '[') {
257 /* [host]:port */
258 host = token + 1;
259 t = strchr(host, ']');
260 if (!t)
261 return false;
262 *t = '\0';
263 ++t;
264 if (*t != ':')
265 return false;
266 port = xatos(t + 1);
267 } else if ((t = strchr(token, ':'))) {
268 /* host:port */
269 host = token;
270 *t = '\0';
271 port = xatos(t + 1);
272
273 if (0 == port)
274 return false;
275 } else if (strtol(token, &tmp, 10) && !*tmp) {
276 port = xatos(token);
277 } else {
278 host = token;
279 port = 0;
280 }
281
282 if (NULL == host)
283 ipa->setAnyAddr();
284 else if ( ipa->GetHostByName(host) ) /* dont use ipcache. Accept either FQDN or IPA. */
285 (void) 0;
286 else
287 return false;
288
289 /* port MUST be set after the IPA lookup/conversion is performed. */
290 ipa->port(port);
291
292 return true;
293 }
294