Parsing.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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/Stream.h"
16 #include "globals.h"
17 #include "Parsing.h"
18 #include "sbuf/Stream.h"
19 
20 /*
21  * These functions is the same as atoi/l/f, except that they check for errors
22  */
23 
24 double
25 xatof(const char *token)
26 {
27  char *end = nullptr;
28  double ret = strtod(token, &end);
29 
30  if (ret == 0 && end == token) {
31  debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'.");
32  self_destruct();
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  }
39 
40  return ret;
41 }
42 
43 int
44 xatoi(const char *token)
45 {
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 
57 unsigned int
58 xatoui(const char *token, char eov)
59 {
60  int64_t input = xatoll(token, 10, eov);
61  if (input < 0)
62  throw TextException(ToSBuf("the input value '", token, "' cannot be less than 0"), Here());
63 
64  unsigned int ret = (unsigned int) input;
65  if (input != static_cast<int64_t>(ret))
66  throw TextException(ToSBuf("the value '", token, "' is larger than the type 'unsigned int'"), Here());
67 
68  return ret;
69 }
70 
71 long
72 xatol(const char *token)
73 {
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 
85 int64_t
86 xatoll(const char *token, int base, char eov)
87 {
88  char *end = nullptr;
89  int64_t ret = strtoll(token, &end, base);
90 
91  if (end == token) {
92  debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'.");
93  self_destruct();
94  }
95 
96  if (*end != eov) {
97  debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid value: '" << token << "' is supposed to be a number.");
98  self_destruct();
99  }
100 
101  return ret;
102 }
103 
104 uint64_t
105 xatoull(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 
113 unsigned short
114 xatos(const char *token)
115 {
116  long port = xatol(token);
117 
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'.");
125  self_destruct();
126  }
127 
128  return port;
129 }
130 
131 int64_t
133 {
134  char *token = ConfigParser::NextToken();
135  if (!token) {
136  self_destruct();
137  return -1; // not reachable
138  }
139 
140  return xatoll(token, 10);
141 }
142 
143 /*
144  * This function is different from others (e.g., GetInteger64, GetShort)
145  * because it supports octal and hexadecimal numbers
146  */
147 int
149 {
150  char *token = ConfigParser::NextToken();
151  int i;
152 
153  if (!token) {
154  self_destruct();
155  return -1; // not reachable
156  }
157 
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'.");
164  self_destruct();
165  }
166 
167  return i;
168 }
169 
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
175  * unless the limit parameter is set to false.
176  */
177 double
178 GetPercentage(bool limit)
179 {
180  char *token = ConfigParser::NextToken();
181 
182  if (!token) {
183  debugs(3, DBG_CRITICAL, "FATAL: A percentage value is missing.");
184  self_destruct();
185  return 0.0; // not reachable
186  }
187 
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 
194  int p = xatoi(token);
195 
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].");
198  self_destruct();
199  }
200 
201  return static_cast<double>(p) / 100.0;
202 }
203 
204 unsigned short
205 GetShort(void)
206 {
207  char *token = ConfigParser::NextToken();
208  if (!token) {
209  self_destruct();
210  return 0; // not reachable
211  }
212 
213  return xatos(token);
214 }
215 
216 bool
217 StringToInt(const char *s, int &result, const char **p, int base)
218 {
219  if (s) {
220  char *ptr = nullptr;
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 }
235 
236 bool
237 StringToInt64(const char *s, int64_t &result, const char **p, int base)
238 {
239  if (s) {
240  char *ptr = nullptr;
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 }
255 
256 bool
257 GetHostWithPort(char *token, Ip::Address *ipa)
258 {
259  char *t;
260  char *host;
261  char *tmp;
262  unsigned short port;
263 
264  host = nullptr;
265  port = 0;
266 
267  if (*token == '[') {
268  /* [host]:port */
269  host = token + 1;
270  t = strchr(host, ']');
271  if (!t)
272  return false;
273  *t = '\0';
274  ++t;
275  if (*t != ':')
276  return false;
277  port = xatos(t + 1);
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;
286  } else if (strtol(token, &tmp, 10) && !*tmp) {
287  port = xatos(token);
288  } else {
289  host = token;
290  port = 0;
291  }
292 
293  if (nullptr == host)
294  ipa->setAnyAddr();
295  else if (ipa->GetHostByName(host)) /* do not use ipcache. Accept either FQDN or IPA. */
296  (void) 0;
297  else
298  return false;
299 
300  /* port MUST be set after the IPA lookup/conversion is performed. */
301  ipa->port(port);
302 
303  return true;
304 }
305 
#define Here()
source code location of the caller
Definition: Here.h:15
#define DBG_CRITICAL
Definition: Stream.h:37
double GetPercentage(bool limit)
Definition: Parsing.cc:178
long xatol(const char *token)
Definition: Parsing.cc:72
bool GetHostByName(const char *s)
Definition: Address.cc:392
unsigned short xatos(const char *token)
Definition: Parsing.cc:114
static int port
Definition: ldap_backend.cc:70
void self_destruct(void)
Definition: cache_cf.cc:276
number
Definition: testStatHist.cc:32
double xatof(const char *token)
Definition: Parsing.cc:25
int64_t GetInteger64(void)
Definition: Parsing.cc:132
#define DBG_PARSE_NOTE(x)
Definition: Stream.h:42
unsigned short port() const
Definition: Address.cc:798
bool StringToInt(const char *s, int &result, const char **p, int base)
Definition: Parsing.cc:217
int xatoi(const char *token)
Definition: Parsing.cc:44
bool StringToInt64(const char *s, int64_t &result, const char **p, int base)
Definition: Parsing.cc:237
int64_t strtoll(const char *nptr, char **endptr, int base)
Definition: strtoll.c:61
unsigned int xatoui(const char *token, char eov)
Definition: Parsing.cc:58
static char * NextToken()
unsigned short GetShort(void)
Definition: Parsing.cc:205
bool GetHostWithPort(char *token, Ip::Address *ipa)
Definition: Parsing.cc:257
int64_t xatoll(const char *token, int base, char eov)
Definition: Parsing.cc:86
an std::runtime_error with thrower location info
Definition: TextException.h:20
uint64_t xatoull(const char *token, int base, char eov)
Definition: Parsing.cc:105
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
Definition: Address.cc:197
#define DBG_IMPORTANT
Definition: Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
int unsigned int
Definition: stub_fd.cc:19
int GetInteger(void)
Definition: Parsing.cc:148

 

Introduction

Documentation

Support

Miscellaneous