mirror of https://github.com/aria2/aria2
Check scheme part in redirected URI more strictly.
The previous implementation mistakenly sees '/abspath?uri=http://foo' as an absolute URI because it contains '://', but actually it is not. This change checks scheme part is constructed in the allowed character set described in RFC 3986 Section 3.1.pull/12/head
parent
9e302b86df
commit
b7dbcea58b
|
@ -114,23 +114,41 @@ bool Request::redirectUri(const std::string& uri) {
|
|||
redirectedUri = getProtocol();
|
||||
redirectedUri += ":";
|
||||
redirectedUri += uri;
|
||||
} else if(uri.find("://") == std::string::npos) {
|
||||
// rfc2616 requires absolute URI should be provided by Location header
|
||||
// field, but some servers don't obey this rule.
|
||||
// UPDATE: draft-ietf-httpbis-p2-semantics-18 now allows this.
|
||||
uri::UriStruct rus(us_);
|
||||
rus.query.clear();
|
||||
rus.file.clear();
|
||||
size_t offset = 0;
|
||||
if(uri[0] == '/') {
|
||||
// abosulute path
|
||||
rus.dir.clear();
|
||||
offset = 1;
|
||||
}
|
||||
redirectedUri = uri::construct(rus);
|
||||
redirectedUri.append(uri.begin()+offset, uri.end());
|
||||
} else {
|
||||
redirectedUri = uri;
|
||||
std::string::size_type schemeEnd = uri.find("://");
|
||||
bool absUri;
|
||||
if(schemeEnd == std::string::npos) {
|
||||
absUri = false;
|
||||
} else {
|
||||
absUri = true;
|
||||
// Check that scheme is acceptable one.
|
||||
for(size_t i = 0; i < schemeEnd; ++i) {
|
||||
char c = uri[i];
|
||||
if(!util::isAlpha(c) && !util::isDigit(c) &&
|
||||
c != '+' && c != '-' && c != '.') {
|
||||
absUri = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(absUri) {
|
||||
redirectedUri = uri;
|
||||
} else {
|
||||
// rfc2616 requires absolute URI should be provided by Location header
|
||||
// field, but some servers don't obey this rule.
|
||||
// UPDATE: draft-ietf-httpbis-p2-semantics-18 now allows this.
|
||||
uri::UriStruct rus(us_);
|
||||
rus.query.clear();
|
||||
rus.file.clear();
|
||||
size_t offset = 0;
|
||||
if(uri[0] == '/') {
|
||||
// abosulute path
|
||||
rus.dir.clear();
|
||||
offset = 1;
|
||||
}
|
||||
redirectedUri = uri::construct(rus);
|
||||
redirectedUri.append(uri.begin()+offset, uri.end());
|
||||
}
|
||||
}
|
||||
return parseUri(redirectedUri);
|
||||
}
|
||||
|
|
|
@ -358,6 +358,8 @@ bool isNumber(InputIterator first, InputIterator last)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool isAlpha(const char c);
|
||||
|
||||
bool isDigit(const char c);
|
||||
|
||||
bool isHexDigit(const char c);
|
||||
|
|
|
@ -142,6 +142,12 @@ void RequestTest::testRedirectUri()
|
|||
CPPUNIT_ASSERT(req.redirectUri("//host/to/file"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("http://host/to/file"), req.getCurrentUri());
|
||||
CPPUNIT_ASSERT_EQUAL(5, req.getRedirectCount());
|
||||
|
||||
// http:// in query part
|
||||
CPPUNIT_ASSERT(req.redirectUri("/abspath?uri=http://foo"));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("http://host/abspath?uri=http://foo"),
|
||||
req.getCurrentUri());
|
||||
CPPUNIT_ASSERT_EQUAL(6, req.getRedirectCount());
|
||||
}
|
||||
|
||||
void RequestTest::testRedirectUri2()
|
||||
|
|
Loading…
Reference in New Issue