static int
is_valid_ipv4_address (const char *str, const char *end)
{
- int saw_digit, octets;
- int val;
+ int saw_digit = 0;
+ int octets = 0;
+ int val = 0;
- saw_digit = 0;
- octets = 0;
- val = 0;
-
- while (str < end) {
- int ch = *str++;
+ while (str < end)
+ {
+ int ch = *str++;
- if (ch >= '0' && ch <= '9') {
- val = val * 10 + (ch - '0');
+ 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 (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 const int NS_INADDRSZ = 4;
-static const int NS_IN6ADDRSZ = 16;
-static const int NS_INT16SZ = 2;
-
static int
is_valid_ipv6_address (const char *str, const char *end)
{
- static const char xdigits[] = "0123456789abcdef";
+ enum {
+ NS_INADDRSZ = 4,
+ NS_IN6ADDRSZ = 16,
+ NS_INT16SZ = 2
+ };
+
const char *curtok;
int tp;
const char *colonp;
saw_xdigit = 0;
val = 0;
- while (str < end) {
- int ch = *str++;
- const char *pch;
+ while (str < end)
+ {
+ int ch = *str++;
- /* 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 number, add it to val. */
+ if (ISXDIGIT (ch))
+ {
+ val <<= 4;
+ val |= XDIGIT_TO_NUM (ch);
+ 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 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)
+ if (saw_xdigit == 1)
+ {
+ 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;
+ if (colonp != NULL)
+ {
+ if (tp == NS_IN6ADDRSZ)
+ return 0;
+ tp = NS_IN6ADDRSZ;
}
-
- 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;
}
}
- u = (struct url *)xmalloc (sizeof (struct url));
- memset (u, 0, sizeof (*u));
-
+ u = xnew0 (struct url);
u->scheme = scheme;
u->host = strdupdelim (host_b, host_e);
u->port = port;
/* Quote path element, characters in [b, e), as file name, and append
the quoted string to DEST. Each character is quoted as per
- file_unsafe_char and the corresponding table. */
+ file_unsafe_char and the corresponding table.
+
+ If ESCAPED_P is non-zero, the path element is considered to be
+ URL-escaped and will be unescaped prior to inspection. */
static void
-append_uri_pathel (const char *b, const char *e, struct growable *dest)
+append_uri_pathel (const char *b, const char *e, int escaped_p,
+ struct growable *dest)
{
- char *pathel;
- int pathlen;
-
const char *p;
int quoted, outlen;
mask |= filechr_control;
/* Copy [b, e) to PATHEL and URL-unescape it. */
- BOUNDED_TO_ALLOCA (b, e, pathel);
- url_unescape (pathel);
- pathlen = strlen (pathel);
+ if (escaped_p)
+ {
+ char *unescaped;
+ BOUNDED_TO_ALLOCA (b, e, unescaped);
+ url_unescape (unescaped);
+ b = unescaped;
+ e = unescaped + strlen (unescaped);
+ }
- /* Go through PATHEL and check how many characters we'll need to
- add for file quoting. */
+ /* Walk the PATHEL string and check how many characters we'll need
+ to add for file quoting. */
quoted = 0;
- for (p = pathel; *p; p++)
+ for (p = b; p < e; p++)
if (FILE_CHAR_TEST (*p, mask))
++quoted;
- /* p - pathel is the string length. Each quoted char means two
- additional characters in the string, hence 2*quoted. */
- outlen = (p - pathel) + (2 * quoted);
+ /* e-b is the string length. Each quoted char means two additional
+ characters in the string, hence 2*quoted. */
+ outlen = (e - b) + (2 * quoted);
GROW (dest, outlen);
if (!quoted)
{
/* If there's nothing to quote, we don't need to go through the
string the second time. */
- memcpy (TAIL (dest), pathel, outlen);
+ memcpy (TAIL (dest), b, outlen);
}
else
{
char *q = TAIL (dest);
- for (p = pathel; *p; p++)
+ for (p = b; p < e; p++)
{
if (!FILE_CHAR_TEST (*p, mask))
*q++ = *p;
if (dest->tail)
append_char ('/', dest);
- append_uri_pathel (pathel, next, dest);
+ append_uri_pathel (pathel, next, 1, dest);
}
}
if (fnres.tail)
append_char ('/', &fnres);
u_file = *u->file ? u->file : "index.html";
- append_uri_pathel (u_file, u_file + strlen (u_file), &fnres);
+ append_uri_pathel (u_file, u_file + strlen (u_file), 0, &fnres);
/* Append "?query" to the file name. */
u_query = u->query && *u->query ? u->query : NULL;
if (u_query)
{
append_char (FN_QUERY_SEP, &fnres);
- append_uri_pathel (u_query, u_query + strlen (u_query), &fnres);
+ append_uri_pathel (u_query, u_query + strlen (u_query), 1, &fnres);
}
/* Zero-terminate the file name. */