]>
Commit | Line | Data |
---|---|---|
c8f4eac4 | 1 | /* |
ef57eb7b | 2 | * Copyright (C) 1996-2016 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 | 23 | double |
24 | xatof(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 | ||
42 | int | |
43 | xatoi(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 | ||
56 | unsigned int | |
e398d16e | 57 | xatoui(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 | 74 | long |
75 | xatol(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 | ||
88 | int64_t | |
e398d16e | 89 | xatoll(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 | ||
107 | unsigned short | |
108 | xatos(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 |
125 | int64_t |
126 | GetInteger64(void) | |
127 | { | |
2eceb328 | 128 | char *token = ConfigParser::NextToken(); |
b1fb3348 AJ |
129 | |
130 | if (token == NULL) | |
131 | self_destruct(); | |
132 | ||
54a063a2 | 133 | return xatoll(token, 10); |
b1fb3348 AJ |
134 | } |
135 | ||
54a063a2 TX |
136 | /* |
137 | * This function is different from others (e.g., GetInteger64, GetShort) | |
138 | * because it supports octal and hexadecimal numbers | |
139 | */ | |
c8f4eac4 | 140 | int |
141 | GetInteger(void) | |
142 | { | |
2eceb328 | 143 | char *token = ConfigParser::NextToken(); |
c8f4eac4 | 144 | int i; |
145 | ||
146 | if (token == NULL) | |
147 | self_destruct(); | |
148 | ||
54a063a2 TX |
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'."); | |
c8f4eac4 | 155 | self_destruct(); |
54a063a2 | 156 | } |
c8f4eac4 | 157 | |
158 | return i; | |
159 | } | |
160 | ||
54a063a2 TX |
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 | |
1454480a | 166 | * unless the limit parameter is set to false. |
54a063a2 | 167 | */ |
1454480a AJ |
168 | double |
169 | GetPercentage(bool limit) | |
54a063a2 | 170 | { |
223d18cd | 171 | char *token = ConfigParser::NextToken(); |
54a063a2 | 172 | |
f5bc7b15 | 173 | if (!token) { |
1454480a | 174 | debugs(3, DBG_CRITICAL, "FATAL: A percentage value is missing."); |
f5bc7b15 AJ |
175 | self_destruct(); |
176 | } | |
177 | ||
54a063a2 TX |
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 | ||
223d18cd | 184 | int p = xatoi(token); |
54a063a2 | 185 | |
1454480a AJ |
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]."); | |
54a063a2 TX |
188 | self_destruct(); |
189 | } | |
190 | ||
1454480a | 191 | return static_cast<double>(p) / 100.0; |
54a063a2 TX |
192 | } |
193 | ||
f45dd259 | 194 | unsigned short |
0e656b69 | 195 | GetShort(void) |
196 | { | |
2eceb328 | 197 | char *token = ConfigParser::NextToken(); |
0e656b69 | 198 | |
199 | if (token == NULL) | |
200 | self_destruct(); | |
201 | ||
202 | return xatos(token); | |
203 | } | |
204 | ||
053b1f59 | 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 | } | |
47f6e231 | 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 | } | |
82b7abe3 AJ |
244 | |
245 | bool | |
b7ac5457 | 246 | GetHostWithPort(char *token, Ip::Address *ipa) |
82b7abe3 AJ |
247 | { |
248 | char *t; | |
249 | char *host; | |
250 | char *tmp; | |
251 | unsigned short port; | |
252 | ||
253 | host = NULL; | |
254 | port = 0; | |
255 | ||
82b7abe3 AJ |
256 | if (*token == '[') { |
257 | /* [host]:port */ | |
258 | host = token + 1; | |
259 | t = strchr(host, ']'); | |
260 | if (!t) | |
261 | return false; | |
f412b2d6 FC |
262 | *t = '\0'; |
263 | ++t; | |
82b7abe3 AJ |
264 | if (*t != ':') |
265 | return false; | |
266 | port = xatos(t + 1); | |
055421ee AJ |
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; | |
54a063a2 TX |
275 | } else if (strtol(token, &tmp, 10) && !*tmp) { |
276 | port = xatos(token); | |
055421ee AJ |
277 | } else { |
278 | host = token; | |
279 | port = 0; | |
280 | } | |
82b7abe3 AJ |
281 | |
282 | if (NULL == host) | |
4dd643d5 | 283 | ipa->setAnyAddr(); |
82b7abe3 AJ |
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. */ | |
4dd643d5 | 290 | ipa->port(port); |
82b7abe3 AJ |
291 | |
292 | return true; | |
293 | } | |
f53969cc | 294 |