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