aboutsummaryrefslogtreecommitdiff
path: root/src/url.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/url.c')
-rw-r--r--src/url.c112
1 files changed, 79 insertions, 33 deletions
diff --git a/src/url.c b/src/url.c
index 500aa0a..be74974 100644
--- a/src/url.c
+++ b/src/url.c
@@ -18,11 +18,12 @@
# include <config.h>
#endif
#include "pies.h"
+#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
-/* proto://[user[:password]@][host[:port]/]path[;arg=str[;arg=str...]
+/* scheme://[user[:password]@][host[:port]/]path[;arg=str[;arg=str...]
*/
static int
@@ -59,17 +60,17 @@ url_parse_args (struct pies_url *url, char **str)
static int
url_parse_path (struct pies_url *url, char **str)
{
- char *p;
-
- p = strchr (*str, ';');
- if (!p)
- p = *str + strlen (*str);
- if (alloc_string(&url->path, *str, p))
- return 1;
- *str = p;
- if (*p)
- ++ * str;
- return url_parse_args (url, str);
+ char *p;
+
+ p = strchr (*str, ';');
+ if (!p)
+ p = *str + strlen (*str);
+ if (alloc_string (&url->path, *str, p))
+ return 1;
+ *str = p;
+ if (*p)
+ ++*str;
+ return url_parse_args (url, str);
}
/* On input str points at the beginning of host part */
@@ -81,12 +82,29 @@ url_parse_host (struct pies_url *url, char **str)
if (s[len] == ':')
{
+ char *start = s + len + 1;
char *q;
- unsigned long n = strtoul (s + len + 1, &q, 10);
- if ((*q && !strchr("/;:", *q)) || n > USHRT_MAX)
+ unsigned long n = strtoul (start, &q, 10);
+ if (n > USHRT_MAX)
return 1;
- url->port = n;
- *str = q + strcspn(q, "/");
+ if ((*q && !strchr ("/;:", *q)))
+ {
+ char *proto = url->proto_s ? url->proto_s : "tcp";
+ size_t size = strcspn (start, "/;:");
+ struct servent *serv;
+
+ alloc_string_len (&url->port_s, start, size);
+ serv = getservbyname (url->port_s, proto);
+ if (!serv)
+ return 1;
+ url->port = ntohs (serv->s_port);
+ *str = start + size;
+ }
+ else
+ {
+ url->port = n;
+ *str = q;
+ }
}
else
*str = s + len;
@@ -106,22 +124,22 @@ url_parse_user (struct pies_url *url, char **str)
{
size_t len = strcspn (*str, ":;@/");
char *p = *str + len;
-
+
switch (*p)
{
case ';':
case ':':
len = strcspn (p + 1, "@/:");
- if (p[len+1] == '@')
+ if (p[len + 1] == '@')
{
- if (alloc_string_len(&url->passwd, p + 1, len))
+ if (alloc_string_len (&url->passwd, p + 1, len))
return 1;
if (alloc_string (&url->user, *str, p))
return 1;
*str = p + len + 2;
}
break;
-
+
case '@':
if (alloc_string (&url->user, *str, p))
return 1;
@@ -132,27 +150,53 @@ url_parse_user (struct pies_url *url, char **str)
}
static int
-url_parse_proto (struct pies_url *url, const char *str)
+url_parse_scheme (struct pies_url *url, const char *str)
{
+ size_t len;
char *p;
-
+
if (!str)
{
errno = EINVAL;
return 1;
}
-
- p = strchr (str, ':');
- if (!p)
+
+ len = strcspn (str, ":+");
+ if (!str[len])
{
errno = EINVAL;
return 1;
}
-
- alloc_string (&url->proto, str, p);
+ alloc_string_len (&url->scheme, str, len);
+
+ str += len;
+
+ if (*str == '+')
+ {
+ struct protoent *proto;
+
+ len = strcspn (++str, ":");
+ if (str[len] == 0)
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ alloc_string_len (&url->proto_s, str, len);
+ str += len;
+ proto = getprotobyname (url->proto_s);
+ if (!proto)
+ {
+ errno = EINVAL;
+ return 1;
+ }
+ url->proto = proto->p_proto;
+ }
+ else
+ url->proto = 0;
+
/* Skip slashes */
- for (p++; *p == '/'; p++)
+ for (p = (char*) str + 1; *p == '/'; p++)
;
return url_parse_user (url, &p);
}
@@ -164,15 +208,17 @@ pies_url_destroy (struct pies_url **purl)
struct pies_url *url = *purl;
free (url->string);
- free (url->proto);
+ free (url->scheme);
free (url->host);
+ free (url->port_s);
+ free (url->proto_s);
free (url->path);
free (url->user);
free (url->passwd);
for (i = 0; i < url->argc; i++)
free (url->argv[i]);
free (url->argv);
- free(url);
+ free (url);
*purl = NULL;
}
@@ -181,12 +227,12 @@ pies_url_create (struct pies_url **purl, const char *str)
{
int rc;
struct pies_url *url;
-
+
url = malloc (sizeof (*url));
if (!url)
return 1;
- memset (url, 0, sizeof(*url));
- rc = url_parse_proto (url, str);
+ memset (url, 0, sizeof (*url));
+ rc = url_parse_scheme (url, str);
if (rc)
pies_url_destroy (&url);
else

Return to:

Send suggestions and report system problems to the System administrator.