mirror of
https://github.com/mirror/wget.git
synced 2025-01-22 18:21:03 +08:00
[svn] Add proper detection of numeric IPv6 addresses.
By Mauro Tortonesi.
This commit is contained in:
parent
564f6aa349
commit
05715ed4d6
@ -1,3 +1,15 @@
|
|||||||
|
2003-09-05 Hrvoje Niksic <hniksic@xemacs.org>
|
||||||
|
|
||||||
|
* url.c (is_valid_ipv6_address): Modified to not require
|
||||||
|
zero-terminated strings.
|
||||||
|
(is_valid_ipv4_address): Ditto.
|
||||||
|
|
||||||
|
2003-09-05 Mauro Tortonesi <mauro@deepspace6.net>
|
||||||
|
|
||||||
|
src/url.c: added RFC 2732 compliance for URL parsing. The
|
||||||
|
functions is_*_address valid are a modified version of
|
||||||
|
glibc 2.3.2 inet_pton's code.
|
||||||
|
|
||||||
2003-09-03 Ahmon Dancy <dancy@dancysoft.com>
|
2003-09-03 Ahmon Dancy <dancy@dancysoft.com>
|
||||||
|
|
||||||
* main.c init.c options.h: Added --retry-connrefused option so
|
* main.c init.c options.h: Added --retry-connrefused option so
|
||||||
|
176
src/url.c
176
src/url.c
@ -58,6 +58,11 @@ extern int errno;
|
|||||||
/* Is X ".."? */
|
/* Is X ".."? */
|
||||||
#define DDOTP(x) ((*(x) == '.') && (*(x + 1) == '.') && (!*(x + 2)))
|
#define DDOTP(x) ((*(x) == '.') && (*(x + 1) == '.') && (!*(x + 2)))
|
||||||
|
|
||||||
|
static const int NS_INADDRSZ = 4;
|
||||||
|
static const int NS_IN6ADDRSZ = 16;
|
||||||
|
static const int NS_INT16SZ = 2;
|
||||||
|
|
||||||
|
|
||||||
struct scheme_data
|
struct scheme_data
|
||||||
{
|
{
|
||||||
char *leading_string;
|
char *leading_string;
|
||||||
@ -645,7 +650,7 @@ static char *parse_errors[] = {
|
|||||||
#define PE_UNTERMINATED_IPV6_ADDRESS 5
|
#define PE_UNTERMINATED_IPV6_ADDRESS 5
|
||||||
"Unterminated IPv6 numeric address",
|
"Unterminated IPv6 numeric address",
|
||||||
#define PE_INVALID_IPV6_ADDRESS 6
|
#define PE_INVALID_IPV6_ADDRESS 6
|
||||||
"Invalid char in IPv6 numeric address"
|
"Invalid IPv6 numeric address"
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SETERR(p, v) do { \
|
#define SETERR(p, v) do { \
|
||||||
@ -653,6 +658,137 @@ static char *parse_errors[] = {
|
|||||||
*(p) = (v); \
|
*(p) = (v); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/* The following two functions were adapted from glibc. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_valid_ipv4_address (const char *str, const char *end)
|
||||||
|
{
|
||||||
|
int saw_digit, octets;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
saw_digit = 0;
|
||||||
|
octets = 0;
|
||||||
|
val = 0;
|
||||||
|
|
||||||
|
while (str < end) {
|
||||||
|
int ch = *str++;
|
||||||
|
|
||||||
|
if (ch >= '0' && ch <= '9') {
|
||||||
|
val = val * 10 + (ch - '0');
|
||||||
|
|
||||||
|
if (val > 255)
|
||||||
|
return 0;
|
||||||
|
if (saw_digit == 0) {
|
||||||
|
if (++octets > 4)
|
||||||
|
return 0;
|
||||||
|
saw_digit = 1;
|
||||||
|
}
|
||||||
|
} else if (ch == '.' && saw_digit == 1) {
|
||||||
|
if (octets == 4)
|
||||||
|
return 0;
|
||||||
|
val = 0;
|
||||||
|
saw_digit = 0;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (octets < 4)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_valid_ipv6_address (const char *str, const char *end)
|
||||||
|
{
|
||||||
|
static const char xdigits[] = "0123456789abcdef";
|
||||||
|
const char *curtok;
|
||||||
|
int tp;
|
||||||
|
const char *colonp;
|
||||||
|
int saw_xdigit;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
tp = 0;
|
||||||
|
colonp = NULL;
|
||||||
|
|
||||||
|
if (str == end)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Leading :: requires some special handling. */
|
||||||
|
if (*str == ':')
|
||||||
|
{
|
||||||
|
++str;
|
||||||
|
if (str == end || *str != ':')
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
curtok = str;
|
||||||
|
saw_xdigit = 0;
|
||||||
|
val = 0;
|
||||||
|
|
||||||
|
while (str < end) {
|
||||||
|
int ch = *str++;
|
||||||
|
const char *pch;
|
||||||
|
|
||||||
|
/* if ch is a number, add it to val. */
|
||||||
|
pch = strchr(xdigits, ch);
|
||||||
|
if (pch != NULL) {
|
||||||
|
val <<= 4;
|
||||||
|
val |= (pch - xdigits);
|
||||||
|
if (val > 0xffff)
|
||||||
|
return 0;
|
||||||
|
saw_xdigit = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if ch is a colon ... */
|
||||||
|
if (ch == ':') {
|
||||||
|
curtok = str;
|
||||||
|
if (saw_xdigit == 0) {
|
||||||
|
if (colonp != NULL)
|
||||||
|
return 0;
|
||||||
|
colonp = str + tp;
|
||||||
|
continue;
|
||||||
|
} else if (str == end) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
|
||||||
|
return 0;
|
||||||
|
tp += NS_INT16SZ;
|
||||||
|
saw_xdigit = 0;
|
||||||
|
val = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if ch is a dot ... */
|
||||||
|
if (ch == '.' && (tp <= NS_IN6ADDRSZ - NS_INADDRSZ) &&
|
||||||
|
is_valid_ipv4_address(curtok, end) == 1) {
|
||||||
|
tp += NS_INADDRSZ;
|
||||||
|
saw_xdigit = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saw_xdigit == 1) {
|
||||||
|
if (tp > NS_IN6ADDRSZ - NS_INT16SZ)
|
||||||
|
return 0;
|
||||||
|
tp += NS_INT16SZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colonp != NULL) {
|
||||||
|
if (tp == NS_IN6ADDRSZ)
|
||||||
|
return 0;
|
||||||
|
tp = NS_IN6ADDRSZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tp != NS_IN6ADDRSZ)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parse a URL.
|
/* Parse a URL.
|
||||||
|
|
||||||
Return a new struct url if successful, NULL on error. In case of
|
Return a new struct url if successful, NULL on error. In case of
|
||||||
@ -710,36 +846,29 @@ url_parse (const char *url, int *error)
|
|||||||
|
|
||||||
if (*p == '[')
|
if (*p == '[')
|
||||||
{
|
{
|
||||||
/* Support http://[::1]/ used by IPv6. */
|
/* Handle IPv6 address inside square brackets. Ideally we'd
|
||||||
int invalid = 0;
|
just look for the terminating ']', but rfc2732 mandates
|
||||||
++p;
|
rejecting invalid IPv6 addresses. */
|
||||||
while (1)
|
|
||||||
|
/* The address begins after '['. */
|
||||||
|
host_b = p + 1;
|
||||||
|
host_e = strchr (host_b, ']');
|
||||||
|
|
||||||
|
if (!host_e)
|
||||||
{
|
{
|
||||||
char c = *p++;
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case ']':
|
|
||||||
goto out;
|
|
||||||
case '\0':
|
|
||||||
SETERR (error, PE_UNTERMINATED_IPV6_ADDRESS);
|
SETERR (error, PE_UNTERMINATED_IPV6_ADDRESS);
|
||||||
return NULL;
|
return NULL;
|
||||||
case ':': case '.':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (ISXDIGIT (c))
|
|
||||||
break;
|
|
||||||
invalid = 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
out:
|
/* Check if the IPv6 address is valid. */
|
||||||
if (invalid)
|
if (!is_valid_ipv6_address(host_b, host_e))
|
||||||
{
|
{
|
||||||
SETERR (error, PE_INVALID_IPV6_ADDRESS);
|
SETERR (error, PE_INVALID_IPV6_ADDRESS);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Don't include brackets in [host_b, host_p). */
|
|
||||||
++host_b;
|
/* Continue parsing after the closing ']'. */
|
||||||
host_e = p - 1;
|
p = host_e + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -782,6 +911,7 @@ url_parse (const char *url, int *error)
|
|||||||
SETERR (error, PE_BAD_PORT_NUMBER);
|
SETERR (error, PE_BAD_PORT_NUMBER);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
port = 10 * port + (*pp - '0');
|
port = 10 * port + (*pp - '0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user