#include "config.h"
#endif
-#define _GNU_SOURCE
#include <assert.h>
-#include <stdbool.h>
#include <string.h>
#include "log/log.h"
struct pb_url *url;
const char *p;
- pb_log("%s: '%s'\n", __func__, url_str);
-
if (!url_str || !*url_str) {
assert(0 && "bad url");
return NULL;
path = strchr(p, '/');
if (!path) {
- pb_log("%s: parse path failed '%s'\n", __func__ , p);
+ pb_log_fn("parse path failed '%s'\n" , p);
goto fail;
}
- col = strchr(p, ':');
+ col = strrchr(p, ':');
+ if (col <= p)
+ col = NULL;
+ if (col && strchr(col , ']')) {
+ /*
+ * This is likely an IPv6 address with no port.
+ * See https://www.ietf.org/rfc/rfc2732.txt
+ */
+ col = NULL;
+ }
if (col) {
len = path - col - 1;
url->port = len ? talloc_strndup(url, col + 1, len)
: NULL;
len = col - p;
- url->host = len ? talloc_strndup(url, p, len) : NULL;
} else {
url->port = NULL;
- url->host = talloc_strndup(url, p, path - p);
+ len = path - p;
}
+ if (p[0] == '[' && p[len - 1] == ']')
+ /* IPv6 */
+ url->host = talloc_strndup(url, p + 1, len - 2);
+ else
+ /* IPv4 */
+ url->host = talloc_strndup(url, p, len);
+
+
/* remove multiple leading slashes */
for (; *path && *(path+1) == '/'; path++)
;
pb_url_parse_path(url);
- pb_log(" scheme %d\n", url->scheme);
- pb_log(" host '%s'\n", url->host);
- pb_log(" port '%s'\n", url->port);
- pb_log(" path '%s'\n", url->path);
- pb_log(" dir '%s'\n", url->dir);
- pb_log(" file '%s'\n", url->file);
-
return url;
fail:
return NULL;
}
-static bool is_url(const char *str)
+bool is_url(const char *str)
{
return strstr(str, "://") != NULL;
}
-static void pb_url_update_full(struct pb_url *url)
+int addr_scheme(const char *address)
{
- const struct pb_scheme_info *scheme = pb_url_scheme_info(url->scheme);
+ uint8_t buf[sizeof(struct in6_addr)];
+ int rc;
+
+ rc = inet_pton(AF_INET, address , buf);
+ if (rc == 1)
+ return AF_INET;
+ rc = inet_pton(AF_INET6, address , buf);
+ if (rc == 1)
+ return AF_INET6;
+
+ return 0;
+}
+char *pb_url_to_string(struct pb_url *url)
+{
+ const struct pb_scheme_info *scheme = pb_url_scheme_info(url->scheme);
+ char *str, *port;
assert(scheme);
- talloc_free(url->full);
+ port = url->port ? talloc_asprintf(url, ":%s", url->port) : NULL;
- url->full = talloc_asprintf(url, "%s://%s%s", scheme->str,
- scheme->has_host ? url->host : "", url->path);
+ if (scheme->has_host && addr_scheme(url->host) == AF_INET6)
+ str = talloc_asprintf(url, "%s://[%s]%s%s", scheme->str,
+ url->host, port ?: "", url->path);
+ else
+ str = talloc_asprintf(url, "%s://%s%s%s", scheme->str,
+ scheme->has_host ? url->host : "",
+ port ?: "", url->path);
+
+ talloc_free(port);
+ return str;
+}
+
+static void pb_url_update_full(struct pb_url *url)
+{
+ talloc_free(url->full);
+ url->full = pb_url_to_string(url);
}
-static struct pb_url *pb_url_copy(void *ctx, const struct pb_url *url)
+struct pb_url *pb_url_copy(void *ctx, const struct pb_url *url)
{
struct pb_url *new_url;
new_url = talloc(ctx, struct pb_url);
new_url->scheme = url->scheme;
- new_url->full = talloc_strdup(url, url->full);
+ new_url->full = talloc_strdup(new_url, url->full);
- new_url->host = url->host ? talloc_strdup(url, url->host) : NULL;
- new_url->port = url->port ? talloc_strdup(url, url->port) : NULL;
- new_url->path = url->path ? talloc_strdup(url, url->path) : NULL;
- new_url->dir = url->dir ? talloc_strdup(url, url->dir) : NULL;
- new_url->file = url->file ? talloc_strdup(url, url->file) : NULL;
+ new_url->host = url->host ? talloc_strdup(new_url, url->host) : NULL;
+ new_url->port = url->port ? talloc_strdup(new_url, url->port) : NULL;
+ new_url->path = url->path ? talloc_strdup(new_url, url->path) : NULL;
+ new_url->dir = url->dir ? talloc_strdup(new_url, url->dir) : NULL;
+ new_url->file = url->file ? talloc_strdup(new_url, url->file) : NULL;
return new_url;
}