]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/url.cc
3 * $Id: url.cc,v 1.66 1997/11/05 05:29:40 wessels Exp $
5 * DEBUG: section 23 URL Parsing
6 * AUTHOR: Duane Wessels
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * --------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 const char *RequestMethodStr
[] =
46 const char *ProtocolStr
[] =
57 static int url_acceptable
[256];
58 static const char *const hex
= "0123456789abcdef";
60 /* convert %xx in url string to a character
61 * Allocate a new string and return a pointer to converted string */
64 url_convert_hex(char *org_url
, int allocate
)
66 static char code
[] = "00";
71 url
= allocate
? (char *) xstrdup(org_url
) : org_url
;
73 if ((int) strlen(url
) < 3 || !strchr(url
, '%'))
76 for (s
= t
= url
; *(s
+ 2); s
++) {
80 *t
++ = (char) strtol(code
, NULL
, 16);
92 /* INIT Acceptable table.
93 * Borrow from libwww2 with Mosaic2.4 Distribution */
99 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
100 debug(23, 5) ("urlInitialize: Initializing...\n");
101 for (i
= 0; i
< 256; i
++)
102 url_acceptable
[i
] = 0;
103 for (; *good
; good
++)
104 url_acceptable
[(unsigned int) *good
] = 1;
108 /* Encode prohibited char in string */
109 /* return the pointer to new (allocated) string */
111 url_escape(const char *url
)
115 char *tmpline
= xcalloc(1, MAX_URL
);
118 for (p
= url
; *p
; p
++) {
119 if (url_acceptable
[(int) (*p
)])
122 *q
++ = '%'; /* Means hex coming */
123 *q
++ = hex
[(int) ((*p
) >> 4)];
124 *q
++ = hex
[(int) ((*p
) & 15)];
132 urlParseMethod(const char *s
)
134 if (strcasecmp(s
, "GET") == 0) {
136 } else if (strcasecmp(s
, "POST") == 0) {
138 } else if (strcasecmp(s
, "PUT") == 0) {
140 } else if (strcasecmp(s
, "HEAD") == 0) {
142 } else if (strcasecmp(s
, "CONNECT") == 0) {
143 return METHOD_CONNECT
;
144 } else if (strcasecmp(s
, "TRACE") == 0) {
146 } else if (strcasecmp(s
, "PURGE") == 0) {
154 urlParseProtocol(const char *s
)
156 if (strncasecmp(s
, "http", 4) == 0)
158 if (strncasecmp(s
, "ftp", 3) == 0)
160 #ifndef NO_FTP_FOR_FILE
161 if (strncasecmp(s
, "file", 4) == 0)
164 if (strncasecmp(s
, "gopher", 6) == 0)
166 if (strncasecmp(s
, "wais", 4) == 0)
168 if (strncasecmp(s
, "cache_object", 12) == 0)
169 return PROTO_CACHEOBJ
;
175 urlDefaultPort(protocol_t p
)
187 return CACHE_HTTP_PORT
;
194 urlParse(method_t method
, char *url
)
196 LOCAL_ARRAY(char, proto
, MAX_URL
);
197 LOCAL_ARRAY(char, login
, MAX_URL
);
198 LOCAL_ARRAY(char, host
, MAX_URL
);
199 LOCAL_ARRAY(char, urlpath
, MAX_URL
);
200 request_t
*request
= NULL
;
203 protocol_t protocol
= PROTO_NONE
;
205 proto
[0] = host
[0] = urlpath
[0] = login
[0] = '\0';
207 if ((l
= strlen(url
)) + Config
.appendDomainLen
> (MAX_URL
- 1)) {
208 /* terminate so it doesn't overflow other buffers */
209 *(url
+ (MAX_URL
>> 1)) = '\0';
210 debug(23, 0) ("urlParse: URL too large (%d bytes)\n", l
);
213 if (method
== METHOD_CONNECT
) {
215 if (sscanf(url
, "%[^:]:%d", host
, &port
) < 1)
218 if (sscanf(url
, "%[^:]://%[^/]%s", proto
, host
, urlpath
) < 2)
220 protocol
= urlParseProtocol(proto
);
221 port
= urlDefaultPort(protocol
);
222 /* Is there any login informaiton? */
223 if ((t
= strrchr(host
, '@'))) {
225 t
= strrchr(login
, '@');
229 if ((t
= strrchr(host
, ':'))) {
235 for (t
= host
; *t
; t
++)
237 /* remove trailing dots from hostnames */
238 while ((l
= strlen(host
)) > 0 && host
[--l
] == '.')
240 if (Config
.appendDomain
&& !strchr(host
, '.'))
241 strncat(host
, Config
.appendDomain
, SQUIDHOSTNAMELEN
);
243 debug(23, 0) ("urlParse: Invalid port == 0\n");
246 #ifdef HARDCODE_DENY_PORTS
247 /* These ports are filtered in the default squid.conf, but
248 * maybe someone wants them hardcoded... */
249 if (port
== 7 || port
== 9 || port
= 19) {
250 debug(23, 0) ("urlParse: Deny access to port %d\n", port
);
254 #ifdef REMOVE_FTP_TRAILING_SLASHES
255 /* remove trailing slashes from FTP URLs */
256 if (protocol
== PROTO_FTP
) {
257 t
= urlpath
+ strlen(urlpath
);
258 while (t
> urlpath
&& *(--t
) == '/')
262 request
= get_free_request_t();
263 request
->method
= method
;
264 request
->protocol
= protocol
;
265 xstrncpy(request
->host
, host
, SQUIDHOSTNAMELEN
);
266 xstrncpy(request
->login
, login
, MAX_LOGIN_SZ
);
267 request
->port
= (u_short
) port
;
268 xstrncpy(request
->urlpath
, urlpath
, MAX_URL
);
269 request
->max_age
= -1;
270 request
->max_forwards
= -1;
275 urlCanonical(const request_t
* request
, char *buf
)
277 LOCAL_ARRAY(char, urlbuf
, MAX_URL
);
278 LOCAL_ARRAY(char, portbuf
, 32);
281 switch (request
->method
) {
283 snprintf(buf
, MAX_URL
, "%s:%d", request
->host
, request
->port
);
287 if (request
->port
!= urlDefaultPort(request
->protocol
))
288 snprintf(portbuf
, 32, ":%d", request
->port
);
289 snprintf(buf
, MAX_URL
, "%s://%s%s%s%s%s",
290 ProtocolStr
[request
->protocol
],
292 *request
->login
? "@" : null_string
,
302 urlCanonicalClean(const request_t
* request
)
304 LOCAL_ARRAY(char, buf
, MAX_URL
);
305 LOCAL_ARRAY(char, portbuf
, 32);
307 switch (request
->method
) {
309 snprintf(buf
, MAX_URL
, "%s:%d", request
->host
, request
->port
);
313 if (request
->port
!= urlDefaultPort(request
->protocol
))
314 snprintf(portbuf
, 32, ":%d", request
->port
);
315 snprintf(buf
, MAX_URL
, "%s://%s%s%s",
316 ProtocolStr
[request
->protocol
],
320 if ((t
= strchr(buf
, '?')))
328 urlClean(char *dirty
)
331 request_t
*r
= urlParse(METHOD_GET
, dirty
);
334 clean
= urlCanonicalClean(r
);
335 put_free_request_t(r
);
341 requestLink(request_t
* request
)
343 request
->link_count
++;
348 requestUnlink(request_t
* request
)
352 request
->link_count
--;
353 if (request
->link_count
)
355 safe_free(request
->headers
);
356 put_free_request_t(request
);
360 matchDomainName(const char *domain
, const char *host
)
363 if ((offset
= strlen(host
) - strlen(domain
)) < 0)
364 return 0; /* host too short */
365 if (strcasecmp(domain
, host
+ offset
) != 0)
366 return 0; /* no match at all */
369 if (*(host
+ offset
- 1) == '.')
377 urlCheckRequest(const request_t
* r
)
380 if (r
->method
== METHOD_CONNECT
)
382 if (r
->method
== METHOD_TRACE
)
384 if (r
->method
== METHOD_PURGE
)
386 switch (r
->protocol
) {
394 if (r
->method
== METHOD_GET
)