]>
Commit | Line | Data |
---|---|---|
c8f4eac4 | 1 | /* |
b510f3a1 | 2 | * DEBUG: section 03 Configuration File Parsing |
c8f4eac4 | 3 | * AUTHOR: Harvest Derived |
4 | * | |
5 | * SQUID Web Proxy Cache http://www.squid-cache.org/ | |
6 | * ---------------------------------------------------------- | |
7 | * | |
8 | * Squid is the result of efforts by numerous individuals from | |
9 | * the Internet community; see the CONTRIBUTORS file for full | |
10 | * details. Many organizations have provided support for Squid's | |
11 | * development; see the SPONSORS file for full details. Squid is | |
12 | * Copyrighted (C) 2001 by the Regents of the University of | |
13 | * California; see the COPYRIGHT file for full details. Squid | |
14 | * incorporates software developed and/or copyrighted by other | |
15 | * sources; see the CREDITS file for full details. | |
16 | * | |
17 | * This program is free software; you can redistribute it and/or modify | |
18 | * it under the terms of the GNU General Public License as published by | |
19 | * the Free Software Foundation; either version 2 of the License, or | |
20 | * (at your option) any later version. | |
26ac0430 | 21 | * |
c8f4eac4 | 22 | * This program is distributed in the hope that it will be useful, |
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | * GNU General Public License for more details. | |
26ac0430 | 26 | * |
c8f4eac4 | 27 | * You should have received a copy of the GNU General Public License |
28 | * along with this program; if not, write to the Free Software | |
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
30 | * | |
31 | */ | |
32 | ||
f7f3304a | 33 | #include "squid.h" |
8a01b99e | 34 | #include "cache_cf.h" |
27bc2077 | 35 | #include "compat/strtoll.h" |
079a8480 | 36 | #include "ConfigParser.h" |
54a063a2 | 37 | #include "Debug.h" |
602d9612 A |
38 | #include "globals.h" |
39 | #include "Parsing.h" | |
c8f4eac4 | 40 | |
41 | /* | |
42 | * These functions is the same as atoi/l/f, except that they check for errors | |
43 | */ | |
44 | ||
0e656b69 | 45 | double |
46 | xatof(const char *token) | |
c8f4eac4 | 47 | { |
54a063a2 | 48 | char *end = NULL; |
0e656b69 | 49 | double ret = strtod(token, &end); |
c8f4eac4 | 50 | |
54a063a2 TX |
51 | if (ret == 0 && end == token) { |
52 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'."); | |
c8f4eac4 | 53 | self_destruct(); |
54a063a2 TX |
54 | } |
55 | ||
56 | if (*end) { | |
57 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid value: '" << token << "' is supposed to be a number."); | |
58 | self_destruct(); | |
59 | } | |
c8f4eac4 | 60 | |
61 | return ret; | |
62 | } | |
63 | ||
64 | int | |
65 | xatoi(const char *token) | |
66 | { | |
54a063a2 TX |
67 | int64_t input = xatoll(token, 10); |
68 | int ret = (int) input; | |
69 | ||
70 | if (input != static_cast<int64_t>(ret)) { | |
71 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'int'."); | |
72 | self_destruct(); | |
73 | } | |
74 | ||
75 | return ret; | |
76 | } | |
77 | ||
78 | unsigned int | |
e398d16e | 79 | xatoui(const char *token, char eov) |
54a063a2 | 80 | { |
e398d16e | 81 | int64_t input = xatoll(token, 10, eov); |
54a063a2 TX |
82 | if (input < 0) { |
83 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The input value '" << token << "' cannot be less than 0."); | |
84 | self_destruct(); | |
85 | } | |
86 | ||
87 | unsigned int ret = (unsigned int) input; | |
88 | if (input != static_cast<int64_t>(ret)) { | |
89 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'unsigned int'."); | |
90 | self_destruct(); | |
91 | } | |
92 | ||
93 | return ret; | |
c8f4eac4 | 94 | } |
95 | ||
0e656b69 | 96 | long |
97 | xatol(const char *token) | |
98 | { | |
54a063a2 TX |
99 | int64_t input = xatoll(token, 10); |
100 | long ret = (long) input; | |
101 | ||
102 | if (input != static_cast<int64_t>(ret)) { | |
103 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'long'."); | |
104 | self_destruct(); | |
105 | } | |
106 | ||
107 | return ret; | |
108 | } | |
109 | ||
110 | int64_t | |
e398d16e | 111 | xatoll(const char *token, int base, char eov) |
54a063a2 TX |
112 | { |
113 | char *end = NULL; | |
114 | int64_t ret = strtoll(token, &end, base); | |
0e656b69 | 115 | |
54a063a2 TX |
116 | if (end == token) { |
117 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'."); | |
0e656b69 | 118 | self_destruct(); |
54a063a2 TX |
119 | } |
120 | ||
e398d16e | 121 | if (*end != eov) { |
54a063a2 TX |
122 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid value: '" << token << "' is supposed to be a number."); |
123 | self_destruct(); | |
124 | } | |
0e656b69 | 125 | |
126 | return ret; | |
127 | } | |
128 | ||
129 | unsigned short | |
130 | xatos(const char *token) | |
131 | { | |
132 | long port = xatol(token); | |
133 | ||
54a063a2 TX |
134 | if (port < 0) { |
135 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' cannot be less than 0."); | |
136 | self_destruct(); | |
137 | } | |
138 | ||
139 | if (port & ~0xFFFF) { | |
140 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'short'."); | |
0e656b69 | 141 | self_destruct(); |
54a063a2 | 142 | } |
0e656b69 | 143 | |
144 | return port; | |
145 | } | |
146 | ||
b1fb3348 AJ |
147 | int64_t |
148 | GetInteger64(void) | |
149 | { | |
2eceb328 | 150 | char *token = ConfigParser::NextToken(); |
b1fb3348 AJ |
151 | |
152 | if (token == NULL) | |
153 | self_destruct(); | |
154 | ||
54a063a2 | 155 | return xatoll(token, 10); |
b1fb3348 AJ |
156 | } |
157 | ||
54a063a2 TX |
158 | /* |
159 | * This function is different from others (e.g., GetInteger64, GetShort) | |
160 | * because it supports octal and hexadecimal numbers | |
161 | */ | |
c8f4eac4 | 162 | int |
163 | GetInteger(void) | |
164 | { | |
2eceb328 | 165 | char *token = ConfigParser::NextToken(); |
c8f4eac4 | 166 | int i; |
167 | ||
168 | if (token == NULL) | |
169 | self_destruct(); | |
170 | ||
54a063a2 TX |
171 | // The conversion must honor 0 and 0x prefixes, which are important for things like umask |
172 | int64_t ret = xatoll(token, 0); | |
173 | ||
174 | i = (int) ret; | |
175 | if (ret != static_cast<int64_t>(i)) { | |
176 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'int'."); | |
c8f4eac4 | 177 | self_destruct(); |
54a063a2 | 178 | } |
c8f4eac4 | 179 | |
180 | return i; | |
181 | } | |
182 | ||
54a063a2 TX |
183 | /* |
184 | * This function is similar as GetInteger() but the token might contain | |
185 | * the percentage symbol (%) and we check whether the value is in the range | |
186 | * of [0, 100] | |
187 | * So, we accept two types of input: 1. XX% or 2. XX , 0<=XX<=100 | |
188 | */ | |
189 | int | |
190 | GetPercentage(void) | |
191 | { | |
223d18cd | 192 | char *token = ConfigParser::NextToken(); |
54a063a2 | 193 | |
f5bc7b15 AJ |
194 | if (!token) { |
195 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: A percentage value is missing."); | |
196 | self_destruct(); | |
197 | } | |
198 | ||
54a063a2 TX |
199 | //if there is a % in the end of the digits, we remove it and go on. |
200 | char* end = &token[strlen(token)-1]; | |
201 | if (*end == '%') { | |
202 | *end = '\0'; | |
203 | } | |
204 | ||
223d18cd | 205 | int p = xatoi(token); |
54a063a2 TX |
206 | |
207 | if (p < 0 || p > 100) { | |
208 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is out of range. A percentage should be within [0, 100]."); | |
209 | self_destruct(); | |
210 | } | |
211 | ||
212 | return p; | |
213 | } | |
214 | ||
f45dd259 | 215 | unsigned short |
0e656b69 | 216 | GetShort(void) |
217 | { | |
2eceb328 | 218 | char *token = ConfigParser::NextToken(); |
0e656b69 | 219 | |
220 | if (token == NULL) | |
221 | self_destruct(); | |
222 | ||
223 | return xatos(token); | |
224 | } | |
225 | ||
053b1f59 | 226 | bool |
227 | StringToInt(const char *s, int &result, const char **p, int base) | |
228 | { | |
229 | if (s) { | |
230 | char *ptr = 0; | |
231 | const int h = (int) strtol(s, &ptr, base); | |
232 | ||
233 | if (ptr != s && ptr) { | |
234 | result = h; | |
235 | ||
236 | if (p) | |
237 | *p = ptr; | |
238 | ||
239 | return true; | |
240 | } | |
241 | } | |
242 | ||
243 | return false; | |
244 | } | |
47f6e231 | 245 | |
246 | bool | |
247 | StringToInt64(const char *s, int64_t &result, const char **p, int base) | |
248 | { | |
249 | if (s) { | |
250 | char *ptr = 0; | |
251 | const int64_t h = (int64_t) strtoll(s, &ptr, base); | |
252 | ||
253 | if (ptr != s && ptr) { | |
254 | result = h; | |
255 | ||
256 | if (p) | |
257 | *p = ptr; | |
258 | ||
259 | return true; | |
260 | } | |
261 | } | |
262 | ||
263 | return false; | |
264 | } | |
82b7abe3 AJ |
265 | |
266 | bool | |
b7ac5457 | 267 | GetHostWithPort(char *token, Ip::Address *ipa) |
82b7abe3 AJ |
268 | { |
269 | char *t; | |
270 | char *host; | |
271 | char *tmp; | |
272 | unsigned short port; | |
273 | ||
274 | host = NULL; | |
275 | port = 0; | |
276 | ||
82b7abe3 AJ |
277 | if (*token == '[') { |
278 | /* [host]:port */ | |
279 | host = token + 1; | |
280 | t = strchr(host, ']'); | |
281 | if (!t) | |
282 | return false; | |
f412b2d6 FC |
283 | *t = '\0'; |
284 | ++t; | |
82b7abe3 AJ |
285 | if (*t != ':') |
286 | return false; | |
287 | port = xatos(t + 1); | |
055421ee AJ |
288 | } else if ((t = strchr(token, ':'))) { |
289 | /* host:port */ | |
290 | host = token; | |
291 | *t = '\0'; | |
292 | port = xatos(t + 1); | |
293 | ||
294 | if (0 == port) | |
295 | return false; | |
54a063a2 TX |
296 | } else if (strtol(token, &tmp, 10) && !*tmp) { |
297 | port = xatos(token); | |
055421ee AJ |
298 | } else { |
299 | host = token; | |
300 | port = 0; | |
301 | } | |
82b7abe3 AJ |
302 | |
303 | if (NULL == host) | |
4dd643d5 | 304 | ipa->setAnyAddr(); |
82b7abe3 AJ |
305 | else if ( ipa->GetHostByName(host) ) /* dont use ipcache. Accept either FQDN or IPA. */ |
306 | (void) 0; | |
307 | else | |
308 | return false; | |
309 | ||
310 | /* port MUST be set after the IPA lookup/conversion is performed. */ | |
4dd643d5 | 311 | ipa->port(port); |
82b7abe3 AJ |
312 | |
313 | return true; | |
314 | } |