mirror of
https://github.com/curl/curl.git
synced 2025-09-13 15:42:39 +03:00
urlapi: fix relative redirects to fragment-only
Using the URL API for a redirect URL when the redirected-to string starts with a hash, ie is only a fragment, the API would produce the wrong final URL. Adjusted test 1560 to test for several new redirect cases. Closes #13394
This commit is contained in:
parent
5fb018494d
commit
c37b694e46
67
lib/urlapi.c
67
lib/urlapi.c
|
@ -264,6 +264,7 @@ static CURLcode concat_url(char *base, const char *relurl, char **newurl)
|
||||||
const char *useurl = relurl;
|
const char *useurl = relurl;
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
CURLUcode uc;
|
CURLUcode uc;
|
||||||
|
bool skip_slash = FALSE;
|
||||||
*newurl = NULL;
|
*newurl = NULL;
|
||||||
|
|
||||||
/* protsep points to the start of the host name */
|
/* protsep points to the start of the host name */
|
||||||
|
@ -283,48 +284,50 @@ static CURLcode concat_url(char *base, const char *relurl, char **newurl)
|
||||||
*pathsep = 0;
|
*pathsep = 0;
|
||||||
|
|
||||||
/* we have a relative path to append to the last slash if there's one
|
/* we have a relative path to append to the last slash if there's one
|
||||||
available, or if the new URL is just a query string (starts with a
|
available, or the new URL is just a query string (starts with a '?') or
|
||||||
'?') we append the new one at the end of the entire currently worked
|
a fragment (starts with '#') we append the new one at the end of the
|
||||||
out URL */
|
current URL */
|
||||||
if(useurl[0] != '?') {
|
if((useurl[0] != '?') && (useurl[0] != '#')) {
|
||||||
pathsep = strrchr(protsep, '/');
|
pathsep = strrchr(protsep, '/');
|
||||||
if(pathsep)
|
if(pathsep)
|
||||||
*pathsep = 0;
|
*pathsep = 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if there's any slash after the host name, and if so, remember
|
/* Check if there's any slash after the host name, and if so, remember
|
||||||
that position instead */
|
that position instead */
|
||||||
pathsep = strchr(protsep, '/');
|
pathsep = strchr(protsep, '/');
|
||||||
if(pathsep)
|
if(pathsep)
|
||||||
protsep = pathsep + 1;
|
protsep = pathsep + 1;
|
||||||
else
|
else
|
||||||
protsep = NULL;
|
protsep = NULL;
|
||||||
|
|
||||||
/* now deal with one "./" or any amount of "../" in the newurl
|
/* now deal with one "./" or any amount of "../" in the newurl
|
||||||
and act accordingly */
|
and act accordingly */
|
||||||
|
|
||||||
if((useurl[0] == '.') && (useurl[1] == '/'))
|
if((useurl[0] == '.') && (useurl[1] == '/'))
|
||||||
useurl += 2; /* just skip the "./" */
|
useurl += 2; /* just skip the "./" */
|
||||||
|
|
||||||
while((useurl[0] == '.') &&
|
while((useurl[0] == '.') &&
|
||||||
(useurl[1] == '.') &&
|
(useurl[1] == '.') &&
|
||||||
(useurl[2] == '/')) {
|
(useurl[2] == '/')) {
|
||||||
level++;
|
level++;
|
||||||
useurl += 3; /* pass the "../" */
|
useurl += 3; /* pass the "../" */
|
||||||
}
|
}
|
||||||
|
|
||||||
if(protsep) {
|
if(protsep) {
|
||||||
while(level--) {
|
while(level--) {
|
||||||
/* cut off one more level from the right of the original URL */
|
/* cut off one more level from the right of the original URL */
|
||||||
pathsep = strrchr(protsep, '/');
|
pathsep = strrchr(protsep, '/');
|
||||||
if(pathsep)
|
if(pathsep)
|
||||||
*pathsep = 0;
|
*pathsep = 0;
|
||||||
else {
|
else {
|
||||||
*protsep = 0;
|
*protsep = 0;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
skip_slash = TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* We got a new absolute path for this server */
|
/* We got a new absolute path for this server */
|
||||||
|
@ -370,7 +373,7 @@ static CURLcode concat_url(char *base, const char *relurl, char **newurl)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* check if we need to append a slash */
|
/* check if we need to append a slash */
|
||||||
if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
|
if(('/' == useurl[0]) || (protsep && !*protsep) || skip_slash)
|
||||||
;
|
;
|
||||||
else {
|
else {
|
||||||
result = Curl_dyn_addn(&newest, "/", 1);
|
result = Curl_dyn_addn(&newest, "/", 1);
|
||||||
|
|
|
@ -1081,6 +1081,54 @@ static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct redircase set_url_list[] = {
|
static const struct redircase set_url_list[] = {
|
||||||
|
{"http://example.org/",
|
||||||
|
"../path/././../../moo",
|
||||||
|
"http://example.org/moo",
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/",
|
||||||
|
"//example.org/../path/../../",
|
||||||
|
"http://example.org/",
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/",
|
||||||
|
"///example.org/../path/../../",
|
||||||
|
"http://example.org/",
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
":23",
|
||||||
|
"http://example.org/foo/:23",
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
"\\x",
|
||||||
|
"http://example.org/foo/\\x",
|
||||||
|
/* WHATWG disagrees */
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
"#/",
|
||||||
|
"http://example.org/foo/bar#/",
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
"?/",
|
||||||
|
"http://example.org/foo/bar?/",
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
"#;?",
|
||||||
|
"http://example.org/foo/bar#;?",
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
"#",
|
||||||
|
"http://example.org/foo/bar",
|
||||||
|
/* This happens because the parser removes empty fragments */
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
"?",
|
||||||
|
"http://example.org/foo/bar",
|
||||||
|
/* This happens because the parser removes empty queries */
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
|
{"http://example.org/foo/bar",
|
||||||
|
"?#",
|
||||||
|
"http://example.org/foo/bar",
|
||||||
|
/* This happens because the parser removes empty queries and fragments */
|
||||||
|
0, 0, CURLUE_OK},
|
||||||
{"http://example.com/please/../gimme/%TESTNUMBER?foobar#hello",
|
{"http://example.com/please/../gimme/%TESTNUMBER?foobar#hello",
|
||||||
"http://example.net/there/it/is/../../tes t case=/%TESTNUMBER0002? yes no",
|
"http://example.net/there/it/is/../../tes t case=/%TESTNUMBER0002? yes no",
|
||||||
"http://example.net/there/tes%20t%20case=/%TESTNUMBER0002?+yes+no",
|
"http://example.net/there/tes%20t%20case=/%TESTNUMBER0002?+yes+no",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user