version 1.94, 2009/08/03 21:34:54 |
version 1.95, 2009/08/06 23:33:35 |
|
|
static int redirect_loop; |
static int redirect_loop; |
|
|
/* |
/* |
|
* Determine whether the character needs encoding, per RFC1738: |
|
* - No corresponding graphic US-ASCII. |
|
* - Unsafe characters. |
|
*/ |
|
static int |
|
unsafe_char(const char *c) |
|
{ |
|
const char *unsafe_chars = " <>\"#{}|\\^~[]`"; |
|
|
|
/* |
|
* No corresponding graphic US-ASCII. |
|
* Control characters and octets not used in US-ASCII. |
|
*/ |
|
return (iscntrl(*c) || !isascii(*c) || |
|
|
|
/* |
|
* Unsafe characters. |
|
* '%' is also unsafe, if is not followed by two |
|
* hexadecimal digits. |
|
*/ |
|
strchr(unsafe_chars, *c) != NULL || |
|
(*c == '%' && (!isxdigit(*++c) || !isxdigit(*++c)))); |
|
} |
|
|
|
/* |
|
* Encode given URL, per RFC1738. |
|
* Allocate and return string to the caller. |
|
*/ |
|
static char * |
|
url_encode(const char *path) |
|
{ |
|
size_t i, length, new_length; |
|
char *epath, *epathp; |
|
|
|
length = new_length = strlen(path); |
|
|
|
/* |
|
* First pass: |
|
* Count unsafe characters, and determine length of the |
|
* final URL. |
|
*/ |
|
for (i = 0; i < length; i++) |
|
if (unsafe_char(path + i)) |
|
new_length += 2; |
|
|
|
epath = epathp = malloc(new_length + 1); /* One more for '\0'. */ |
|
if (epath == NULL) |
|
return NULL; |
|
|
|
/* |
|
* Second pass: |
|
* Encode, and copy final URL. |
|
*/ |
|
for (i = 0; i < length; i++) |
|
if (unsafe_char(path + i)) { |
|
snprintf(epathp, 4, "%%" "%02x", path[i]); |
|
epathp += 3; |
|
} else |
|
*(epathp++) = path[i]; |
|
|
|
*epathp = '\0'; |
|
return (epath); |
|
} |
|
|
|
/* |
* Retrieve URL, via the proxy in $proxyvar if necessary. |
* Retrieve URL, via the proxy in $proxyvar if necessary. |
* Modifies the string argument given. |
* Modifies the string argument given. |
* Returns -1 on failure, 0 on success |
* Returns -1 on failure, 0 on success |
|
|
{ |
{ |
char pbuf[NI_MAXSERV], hbuf[NI_MAXHOST], *cp, *portnum, *path, ststr[4]; |
char pbuf[NI_MAXSERV], hbuf[NI_MAXHOST], *cp, *portnum, *path, ststr[4]; |
char *hosttail, *cause = "unknown", *newline, *host, *port, *buf = NULL; |
char *hosttail, *cause = "unknown", *newline, *host, *port, *buf = NULL; |
|
char *epath; |
int error, i, isftpurl = 0, isfileurl = 0, isredirect = 0, rval = -1; |
int error, i, isftpurl = 0, isfileurl = 0, isredirect = 0, rval = -1; |
struct addrinfo hints, *res0, *res; |
struct addrinfo hints, *res0, *res; |
const char * volatile savefile; |
const char * volatile savefile; |
|
|
|
|
if (verbose) |
if (verbose) |
fprintf(ttyout, "Requesting %s", origline); |
fprintf(ttyout, "Requesting %s", origline); |
|
|
/* |
/* |
* Construct and send the request. Proxy requests don't want leading /. |
* Construct and send the request. Proxy requests don't want leading /. |
*/ |
*/ |
#ifndef SMALL |
#ifndef SMALL |
cookie_get(host, path, ishttpsurl, &buf); |
cookie_get(host, path, ishttpsurl, &buf); |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
|
|
|
epath = url_encode(path); |
|
if (epath == NULL) |
|
return (-1); |
if (proxyurl) { |
if (proxyurl) { |
if (verbose) |
if (verbose) |
fprintf(ttyout, " (via %s)\n", proxyurl); |
fprintf(ttyout, " (via %s)\n", proxyurl); |
|
|
if (cookie) |
if (cookie) |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n" |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n" |
"Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n", |
"Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n", |
path, cookie, buf ? buf : "", HTTP_USER_AGENT); |
epath, cookie, buf ? buf : "", HTTP_USER_AGENT); |
else |
else |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n", |
ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n", |
path, buf ? buf : "", HTTP_USER_AGENT); |
epath, buf ? buf : "", HTTP_USER_AGENT); |
|
|
} else { |
} else { |
#ifndef SMALL |
#ifndef SMALL |
|
|
restart_point = 0; |
restart_point = 0; |
} |
} |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", path, |
ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath, |
#ifndef SMALL |
#ifndef SMALL |
restart_point ? "HTTP/1.1" : |
restart_point ? "HTTP/1.1" : |
#endif /* !SMALL */ |
#endif /* !SMALL */ |
|
|
if (verbose) |
if (verbose) |
fprintf(ttyout, "\n"); |
fprintf(ttyout, "\n"); |
} |
} |
|
free(epath); |
|
|
#ifndef SMALL |
#ifndef SMALL |
free(buf); |
free(buf); |