summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorHiltjo Posthuma <hiltjo@codemadness.org>2015-08-22 14:58:28 +0200
committerHiltjo Posthuma <hiltjo@codemadness.org>2015-08-22 14:58:28 +0200
commit7dc9d08969c61ea0e187f54bba58f3d98af63135 (patch)
tree1f676d72cfb0bbc36cbc7c755583ca6bff9f3454 /util.c
parentb3940ddf986bad891c7d76249860957691affda7 (diff)
util: support ipv6 address, parse port separately
Diffstat (limited to 'util.c')
-rw-r--r--util.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/util.c b/util.c
index 05d0453..ab01132 100644
--- a/util.c
+++ b/util.c
@@ -25,10 +25,12 @@ encodehex(unsigned char c, char *s)
int
parseuri(const char *s, struct uri *u, int rel)
{
- const char *p = s;
+ const char *p = s, *b;
+ char *endptr = NULL;
size_t i;
+ unsigned long l;
- u->proto[0] = u->host[0] = u->path[0] = '\0';
+ u->proto[0] = u->host[0] = u->path[0] = u->port[0] = '\0';
if (!*s)
return 0;
@@ -41,7 +43,7 @@ parseuri(const char *s, struct uri *u, int rel)
*p == '+' || *p == '-' || *p == '.'); p++)
;
if (!strncmp(p, "://", 3)) {
- if (p - s + 1 >= (ssize_t)sizeof(u->proto))
+ if (p - s >= (ssize_t)sizeof(u->proto))
return -1; /* protocol too long */
memcpy(u->proto, s, p - s);
u->proto[p - s] = '\0';
@@ -53,20 +55,41 @@ parseuri(const char *s, struct uri *u, int rel)
goto readpath;
}
}
- /* domain / host part, skip until "/" or end. */
- i = strcspn(p, "/");
- if (i + 1 >= sizeof(u->host))
- return -1; /* host too long */
- memcpy(u->host, p, i);
- u->host[i] = '\0';
- p = &p[i];
-
+ /* IPv6 address */
+ if (*p == '[') {
+ /* bracket not found or host too long */
+ if (!(b = strchr(p, ']')) || b - p >= (ssize_t)sizeof(u->host))
+ return -1;
+ memcpy(u->host, p + 1, b - p - 1);
+ u->host[b - p] = '\0';
+ p = b + 1;
+ } else {
+ /* domain / host part, skip until port, path or end. */
+ if ((i = strcspn(p, ":/")) >= sizeof(u->host))
+ return -1; /* host too long */
+ memcpy(u->host, p, i);
+ u->host[i] = '\0';
+ p = &p[i];
+ }
+ /* port */
+ if (*p == ':') {
+ if ((i = strcspn(++p, "/")) >= sizeof(u->port))
+ return -1; /* port too long */
+ memcpy(u->port, p, i);
+ u->port[i] = '\0';
+ /* check for valid port */
+ errno = 0;
+ l = strtoul(u->port, &endptr, 10);
+ if (errno || *endptr != '\0' || !l || l > 65535)
+ return -1;
+ p = &p[i];
+ }
readpath:
if (u->host[0]) {
p = &p[strspn(p, "/")];
strlcpy(u->path, "/", sizeof(u->path));
} else {
- /* having no host is an error in this case */
+ /* absolute uri must have a host specified */
if (!rel)
return -1;
}