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