Commit Diff


commit - 723bee54d360957eec85ac2eef9ebd5516db3ade
commit + 15dc7d0816a074f495897ddb8790f482fbfa27f1
blob - c1931a699d4fd7f28ab71456257f3c97eceb250d
blob + b7d99055862723b1ee6e5a9e62cc963169110af0
--- url.c
+++ url.c
@@ -431,6 +431,54 @@ url_parse(const char *data, struct url *url, const cha
 		strlcpy(url->query, u.query, sizeof(url->query));
 	if (u.fragment != NULL)
 		strlcpy(url->fragment, u.fragment, sizeof(url->fragment));
+
+	return 1;
+}
+
+int
+url_resolve_from(struct url *url, const char *str, const char **err)
+{
+	char *marker, *query, *hash, *i;
+
+	marker = strstr(str, "://");
+	query = strchr(str, '?');
+	hash = strchr(str, '#');
+
+	/* full URL */
+	if (marker != NULL
+	    && (query == NULL || marker < query)
+	    && (hash == NULL || marker < hash))
+		return url_parse(str, url, err);
+
+	/* TODO: reuse more of the above */
+
+	/* absolute url */
+	if (*str == '/') {
+		strlcpy(url->path, str, sizeof(url->path));
+
+                if ((hash = strchr(url->path, '#')) != NULL) {
+			*hash = '\0';
+			hash++;
+			strlcpy(url->fragment, hash,
+			    sizeof(url->fragment));
+		}
 
+		if ((query = strchr(url->path, '?')) != NULL) {
+			*query = '\0';
+			query++;
+			strlcpy(url->query, query,
+			    sizeof(url->query));
+		}
+		return 1;
+	}
+
+	/* local url */
+	for (i = strchr(url->path, '\0'); i >= url->path; --i) {
+		if (*i == '/')
+			break;
+	}
+
+	*i = '\0';
+	strlcat(url->path, str, sizeof(url->path));
 	return 1;
 }
blob - b43ea710c8ecda1d6981658ecdab720281d9da80
blob + 1da297cb09c85ac346bf9128b7838afb3ccb901a
--- url.h
+++ url.h
@@ -29,3 +29,4 @@ struct url {
 };
 
 int		 url_parse(const char*, struct url*, const char**);
+int		 url_resolve_from(struct url*, const char*, const char**);