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 = getProtocol();
|
||||||
redirectedUri += ":";
|
redirectedUri += ":";
|
||||||
redirectedUri += uri;
|
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 {
|
} 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);
|
return parseUri(redirectedUri);
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,6 +358,8 @@ bool isNumber(InputIterator first, InputIterator last)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isAlpha(const char c);
|
||||||
|
|
||||||
bool isDigit(const char c);
|
bool isDigit(const char c);
|
||||||
|
|
||||||
bool isHexDigit(const char c);
|
bool isHexDigit(const char c);
|
||||||
|
|
|
@ -142,6 +142,12 @@ void RequestTest::testRedirectUri()
|
||||||
CPPUNIT_ASSERT(req.redirectUri("//host/to/file"));
|
CPPUNIT_ASSERT(req.redirectUri("//host/to/file"));
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("http://host/to/file"), req.getCurrentUri());
|
CPPUNIT_ASSERT_EQUAL(std::string("http://host/to/file"), req.getCurrentUri());
|
||||||
CPPUNIT_ASSERT_EQUAL(5, req.getRedirectCount());
|
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()
|
void RequestTest::testRedirectUri2()
|
||||||
|
|
Loading…
Reference in New Issue