summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/urlapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/urlapi.c')
-rw-r--r--libs/libcurl/src/urlapi.c164
1 files changed, 47 insertions, 117 deletions
diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c
index 9b137193dd..6198d1aa04 100644
--- a/libs/libcurl/src/urlapi.c
+++ b/libs/libcurl/src/urlapi.c
@@ -86,6 +86,9 @@ struct Curl_URL {
#define DEFAULT_SCHEME "https"
+static CURLUcode parseurl_and_replace(const char *url, CURLU *u,
+ unsigned int flags);
+
static void free_urlhandle(struct Curl_URL *u)
{
free(u->scheme);
@@ -244,92 +247,47 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
/*
* Concatenate a relative URL to a base URL making it absolute.
- * URL-encodes any spaces.
- * The returned pointer must be freed by the caller unless NULL
- * (returns NULL on out of memory).
*
* Note that this function destroys the 'base' string.
*/
-static CURLcode concat_url(char *base, const char *relurl, char **newurl)
+static CURLUcode redirect_url(char *base, const char *relurl,
+ CURLU *u, unsigned int flags)
{
- /***
- TRY to append this new path to the old URL
- to the right of the host part. Oh crap, this is doomed to cause
- problems in the future...
- */
- struct dynbuf newest;
- char *protsep;
- char *pathsep;
+ struct dynbuf urlbuf;
bool host_changed = FALSE;
const char *useurl = relurl;
CURLcode result = CURLE_OK;
CURLUcode uc;
- bool skip_slash = FALSE;
- *newurl = NULL;
-
/* protsep points to the start of the hostname */
- protsep = strstr(base, "//");
+ char *protsep = strstr(base, "//");
+ DEBUGASSERT(protsep);
if(!protsep)
protsep = base;
else
protsep += 2; /* pass the slashes */
- if('/' != relurl[0]) {
- int level = 0;
-
- /* First we need to find out if there is a ?-letter in the URL,
+ if(('/' != relurl[0]) && ('#' != relurl[0])) {
+ /* First we need to find out if there is a ?-letter in the original URL,
and cut it and the right-side of that off */
- pathsep = strchr(protsep, '?');
+ char *pathsep = strchr(protsep, '?');
if(pathsep)
*pathsep = 0;
-
- /* we have a relative path to append to the last slash if there is one
- available, or the new URL is just a query string (starts with a '?') or
- a fragment (starts with '#') we append the new one at the end of the
- current URL */
- if((useurl[0] != '?') && (useurl[0] != '#')) {
- pathsep = strrchr(protsep, '/');
+ else {
+ /* if not, cut off the potential fragment */
+ pathsep = strchr(protsep, '#');
if(pathsep)
*pathsep = 0;
+ }
- /* Check if there is any slash after the hostname, and if so, remember
- that position instead */
- pathsep = strchr(protsep, '/');
+ /* if the redirect-to piece is not just a query, cut the path after the
+ last slash */
+ if(useurl[0] != '?') {
+ pathsep = strrchr(protsep, '/');
if(pathsep)
- protsep = pathsep + 1;
- else
- protsep = NULL;
-
- /* now deal with one "./" or any amount of "../" in the newurl
- and act accordingly */
-
- if((useurl[0] == '.') && (useurl[1] == '/'))
- useurl += 2; /* just skip the "./" */
-
- while((useurl[0] == '.') &&
- (useurl[1] == '.') &&
- (useurl[2] == '/')) {
- level++;
- useurl += 3; /* pass the "../" */
- }
-
- if(protsep) {
- while(level--) {
- /* cut off one more level from the right of the original URL */
- pathsep = strrchr(protsep, '/');
- if(pathsep)
- *pathsep = 0;
- else {
- *protsep = 0;
- break;
- }
- }
- }
+ pathsep[1] = 0; /* leave the slash */
}
- else
- skip_slash = TRUE;
}
- else {
+ else if('/' == relurl[0]) {
/* We got a new absolute path for this server */
if(relurl[1] == '/') {
@@ -341,54 +299,36 @@ static CURLcode concat_url(char *base, const char *relurl, char **newurl)
host_changed = TRUE;
}
else {
- /* cut off the original URL from the first slash, or deal with URLs
- without slash */
- pathsep = strchr(protsep, '/');
- if(pathsep) {
- /* When people use badly formatted URLs, such as
- "http://www.example.com?dir=/home/daniel" we must not use the first
- slash, if there is a ?-letter before it! */
- char *sep = strchr(protsep, '?');
- if(sep && (sep < pathsep))
- pathsep = sep;
+ /* cut the original URL at first slash */
+ char *pathsep = strchr(protsep, '/');
+ if(pathsep)
*pathsep = 0;
- }
- else {
- /* There was no slash. Now, since we might be operating on a badly
- formatted URL, such as "http://www.example.com?id=2380" which does
- not use a slash separator as it is supposed to, we need to check
- for a ?-letter as well! */
- pathsep = strchr(protsep, '?');
- if(pathsep)
- *pathsep = 0;
- }
}
}
+ else {
+ /* the relative piece starts with '#' */
+
+ /* If there is a fragment in the original URL, cut it off */
+ char *pathsep = strchr(protsep, '#');
+ if(pathsep)
+ *pathsep = 0;
+ }
- Curl_dyn_init(&newest, CURL_MAX_INPUT_LENGTH);
+ Curl_dyn_init(&urlbuf, CURL_MAX_INPUT_LENGTH);
/* copy over the root URL part */
- result = Curl_dyn_add(&newest, base);
+ result = Curl_dyn_add(&urlbuf, base);
if(result)
- return result;
-
- /* check if we need to append a slash */
- if(('/' == useurl[0]) || (protsep && !*protsep) || skip_slash)
- ;
- else {
- result = Curl_dyn_addn(&newest, "/", 1);
- if(result)
- return result;
- }
+ return cc2cu(result);
/* then append the new piece on the right side */
- uc = urlencode_str(&newest, useurl, strlen(useurl), !host_changed,
+ uc = urlencode_str(&urlbuf, useurl, strlen(useurl), !host_changed,
FALSE);
- if(uc)
- return (uc == CURLUE_TOO_LARGE) ? CURLE_TOO_LARGE : CURLE_OUT_OF_MEMORY;
-
- *newurl = Curl_dyn_ptr(&newest);
- return CURLE_OK;
+ if(!uc)
+ uc = parseurl_and_replace(Curl_dyn_ptr(&urlbuf), u,
+ flags&~CURLU_PATH_AS_IS);
+ Curl_dyn_free(&urlbuf);
+ return uc;
}
/* scan for byte values <= 31, 127 and sometimes space */
@@ -455,7 +395,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
/* We will now try to extract the
* possible login information in a string like:
- * ftp://user:password@ftp.my.site:8021/README */
+ * ftp://user:password@ftp.site.example:8021/README */
ptr++;
/* if this is a known scheme, get some details */
@@ -1856,34 +1796,24 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
* If the existing contents is enough for a URL, allow a relative URL to
* replace it.
*/
- CURLcode result;
CURLUcode uc;
char *oldurl;
- char *redired_url;
if(!nalloc)
/* a blank URL is not a valid URL */
return CURLUE_MALFORMED_INPUT;
- /* if the new thing is absolute or the old one is not
- * (we could not get an absolute URL in 'oldurl'),
- * then replace the existing with the new. */
+ /* if the new thing is absolute or the old one is not (we could not get an
+ * absolute URL in 'oldurl'), then replace the existing with the new. */
if(Curl_is_absolute_url(part, NULL, 0,
- flags & (CURLU_GUESS_SCHEME|
- CURLU_DEFAULT_SCHEME))
+ flags & (CURLU_GUESS_SCHEME|CURLU_DEFAULT_SCHEME))
|| curl_url_get(u, CURLUPART_URL, &oldurl, flags)) {
return parseurl_and_replace(part, u, flags);
}
- /* apply the relative part to create a new URL
- * and replace the existing one with it. */
- result = concat_url(oldurl, part, &redired_url);
+ /* apply the relative part to create a new URL */
+ uc = redirect_url(oldurl, part, u, flags);
free(oldurl);
- if(result)
- return cc2cu(result);
-
- uc = parseurl_and_replace(redired_url, u, flags);
- free(redired_url);
return uc;
}
default: