]>
Commit | Line | Data |
---|---|---|
c8f4eac4 | 1 | /* |
bde978a6 | 2 | * Copyright (C) 1996-2015 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 | |
166 | */ | |
167 | int | |
168 | GetPercentage(void) | |
169 | { | |
223d18cd | 170 | char *token = ConfigParser::NextToken(); |
54a063a2 | 171 | |
f5bc7b15 AJ |
172 | if (!token) { |
173 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: A percentage value is missing."); | |
174 | self_destruct(); | |
175 | } | |
176 | ||
54a063a2 TX |
177 | //if there is a % in the end of the digits, we remove it and go on. |
178 | char* end = &token[strlen(token)-1]; | |
179 | if (*end == '%') { | |
180 | *end = '\0'; | |
181 | } | |
182 | ||
223d18cd | 183 | int p = xatoi(token); |
54a063a2 TX |
184 | |
185 | if (p < 0 || p > 100) { | |
186 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is out of range. A percentage should be within [0, 100]."); | |
187 | self_destruct(); | |
188 | } | |
189 | ||
190 | return p; | |
191 | } | |
192 | ||
f45dd259 | 193 | unsigned short |
0e656b69 | 194 | GetShort(void) |
195 | { | |
2eceb328 | 196 | char *token = ConfigParser::NextToken(); |
0e656b69 | 197 | |
198 | if (token == NULL) | |
199 | self_destruct(); | |
200 | ||
201 | return xatos(token); | |
202 | } | |
203 | ||
053b1f59 | 204 | bool |
205 | StringToInt(const char *s, int &result, const char **p, int base) | |
206 | { | |
207 | if (s) { | |
208 | char *ptr = 0; | |
209 | const int h = (int) strtol(s, &ptr, base); | |
210 | ||
211 | if (ptr != s && ptr) { | |
212 | result = h; | |
213 | ||
214 | if (p) | |
215 | *p = ptr; | |
216 | ||
217 | return true; | |
218 | } | |
219 | } | |
220 | ||
221 | return false; | |
222 | } | |
47f6e231 | 223 | |
224 | bool | |
225 | StringToInt64(const char *s, int64_t &result, const char **p, int base) | |
226 | { | |
227 | if (s) { | |
228 | char *ptr = 0; | |
229 | const int64_t h = (int64_t) strtoll(s, &ptr, base); | |
230 | ||
231 | if (ptr != s && ptr) { | |
232 | result = h; | |
233 | ||
234 | if (p) | |
235 | *p = ptr; | |
236 | ||
237 | return true; | |
238 | } | |
239 | } | |
240 | ||
241 | return false; | |
242 | } | |
82b7abe3 AJ |
243 | |
244 | bool | |
b7ac5457 | 245 | GetHostWithPort(char *token, Ip::Address *ipa) |
82b7abe3 AJ |
246 | { |
247 | char *t; | |
248 | char *host; | |
249 | char *tmp; | |
250 | unsigned short port; | |
251 | ||
252 | host = NULL; | |
253 | port = 0; | |
254 | ||
82b7abe3 AJ |
255 | if (*token == '[') { |
256 | /* [host]:port */ | |
257 | host = token + 1; | |
258 | t = strchr(host, ']'); | |
259 | if (!t) | |
260 | return false; | |
f412b2d6 FC |
261 | *t = '\0'; |
262 | ++t; | |
82b7abe3 AJ |
263 | if (*t != ':') |
264 | return false; | |
265 | port = xatos(t + 1); | |
055421ee AJ |
266 | } else if ((t = strchr(token, ':'))) { |
267 | /* host:port */ | |
268 | host = token; | |
269 | *t = '\0'; | |
270 | port = xatos(t + 1); | |
271 | ||
272 | if (0 == port) | |
273 | return false; | |
54a063a2 TX |
274 | } else if (strtol(token, &tmp, 10) && !*tmp) { |
275 | port = xatos(token); | |
055421ee AJ |
276 | } else { |
277 | host = token; | |
278 | port = 0; | |
279 | } | |
82b7abe3 AJ |
280 | |
281 | if (NULL == host) | |
4dd643d5 | 282 | ipa->setAnyAddr(); |
82b7abe3 AJ |
283 | else if ( ipa->GetHostByName(host) ) /* dont use ipcache. Accept either FQDN or IPA. */ |
284 | (void) 0; | |
285 | else | |
286 | return false; | |
287 | ||
288 | /* port MUST be set after the IPA lookup/conversion is performed. */ | |
4dd643d5 | 289 | ipa->port(port); |
82b7abe3 AJ |
290 | |
291 | return true; | |
292 | } | |
f53969cc | 293 |