Percent-encode non-printable ASCII and non-ASCII chars in FileEntry.

Percent-encode non-printable ASCII and non-ASCII chars in URI using
util::percentEncodeMini() when URI is added to FileEntry.  Removed
percent-encode from Request. Also do percent-encoding when setting
referer and redirected URI.
pull/1/head
Tatsuhiro Tsujikawa 2011-08-07 20:46:04 +09:00
parent 491e8bc519
commit 7368c9c9d8
8 changed files with 58 additions and 57 deletions

View File

@ -155,7 +155,7 @@ FileEntry::getRequest
req.reset();
continue;
}
req->setReferer(referer);
req->setReferer(util::percentEncodeMini(referer));
req->setMethod(method);
spentUris_.push_back(uri);
inFlightRequests_.push_back(req);
@ -518,8 +518,9 @@ size_t FileEntry::setUris(const std::vector<std::string>& uris)
bool FileEntry::addUri(const std::string& uri)
{
uri::UriStruct us;
if(uri::parse(us, uri)) {
uris_.push_back(uri);
std::string peUri = util::percentEncodeMini(uri);
if(uri::parse(us, peUri)) {
uris_.push_back(peUri);
return true;
} else {
return false;
@ -529,9 +530,10 @@ bool FileEntry::addUri(const std::string& uri)
bool FileEntry::insertUri(const std::string& uri, size_t pos)
{
uri::UriStruct us;
if(uri::parse(us, uri)) {
std::string peUri = util::percentEncodeMini(uri);
if(uri::parse(us, peUri)) {
pos = std::min(pos, uris_.size());
uris_.insert(uris_.begin()+pos, uri);
uris_.insert(uris_.begin()+pos, peUri);
return true;
} else {
return false;

View File

@ -160,7 +160,8 @@ bool HttpResponse::isRedirect() const
void HttpResponse::processRedirect()
{
if(httpRequest_->getRequest()->redirectUri(getRedirectURI())) {
if(httpRequest_->getRequest()->redirectUri
(util::percentEncodeMini(getRedirectURI()))) {
A2_LOG_INFO(fmt(MSG_REDIRECT,
cuid_,
httpRequest_->getRequest()->getCurrentUri().c_str()));

View File

@ -85,27 +85,6 @@ std::string removeFragment(const std::string& uri)
}
} // namespace
namespace {
std::string percentEncode(const std::string& src)
{
std::string result;
for(std::string::const_iterator i = src.begin(), eoi = src.end(); i != eoi;
++i) {
// Non-Printable ASCII and non-ASCII chars + some ASCII chars.
unsigned char c = *i;
if(in(c, 0x00u, 0x20u) || c >= 0x7fu ||
// Chromium escapes following characters. Firefox4 escapes
// more.
c == '"' || c == '<' || c == '>') {
result += fmt("%%%02X", c);
} else {
result += c;
}
}
return result;
}
} // namespace
bool Request::setUri(const std::string& uri) {
supportsPersistentConnection_ = true;
uri_ = uri;
@ -121,7 +100,7 @@ bool Request::resetUri() {
void Request::setReferer(const std::string& uri)
{
referer_ = previousUri_ = percentEncode(removeFragment(uri));
referer_ = previousUri_ = removeFragment(uri);
}
bool Request::redirectUri(const std::string& uri) {
@ -145,7 +124,7 @@ bool Request::redirectUri(const std::string& uri) {
}
bool Request::parseUri(const std::string& srcUri) {
currentUri_ = percentEncode(removeFragment(srcUri));
currentUri_ = removeFragment(srcUri);
uri::UriStruct us;
if(uri::parse(us, currentUri_)) {
protocol_.swap(us.protocol);

View File

@ -447,6 +447,25 @@ std::string percentEncode(const std::string& target)
target.size());
}
std::string percentEncodeMini(const std::string& src)
{
std::string result;
for(std::string::const_iterator i = src.begin(), eoi = src.end(); i != eoi;
++i) {
// Non-Printable ASCII and non-ASCII chars + some ASCII chars.
unsigned char c = *i;
if(in(c, 0x00u, 0x20u) || c >= 0x7fu ||
// Chromium escapes following characters. Firefox4 escapes
// more.
c == '"' || c == '<' || c == '>') {
result += fmt("%%%02X", c);
} else {
result += c;
}
}
return result;
}
std::string torrentPercentEncode(const unsigned char* target, size_t len) {
std::string dest;
for(size_t i = 0; i < len; ++i) {

View File

@ -170,6 +170,8 @@ std::string percentEncode(const unsigned char* target, size_t len);
std::string percentEncode(const std::string& target);
std::string percentEncodeMini(const std::string& target);
bool inRFC3986ReservedChars(const char c);
bool inRFC3986UnreservedChars(const char c);

View File

@ -218,6 +218,15 @@ void FileEntryTest::testAddUri()
FileEntry file;
CPPUNIT_ASSERT(file.addUri("http://good"));
CPPUNIT_ASSERT(!file.addUri("bad"));
// Test for percent-encode
CPPUNIT_ASSERT(file.addUri("http://host:80/file<with%2 %20space/"
"file with space;param%?a=/?"));
CPPUNIT_ASSERT_EQUAL(std::string("http://host:80"
"/file%3Cwith%2%20%20space/"
"file%20with%20space;param%"
"?a=/?"),
file.getRemainingUris()[1]);
}
void FileEntryTest::testAddUris()
@ -239,6 +248,15 @@ void FileEntryTest::testInsertUri()
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/3"), uris[1]);
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/1"), uris[2]);
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/4"), uris[3]);
// Test for percent-encode
CPPUNIT_ASSERT(file.insertUri("http://host:80/file<with%2 %20space/"
"file with space;param%?a=/?", 0));
CPPUNIT_ASSERT_EQUAL(std::string("http://host:80"
"/file%3Cwith%2%20%20space/"
"file%20with%20space;param%"
"?a=/?"),
file.getRemainingUris()[0]);
}
void FileEntryTest::testRemoveUri()

View File

@ -494,6 +494,14 @@ void HttpResponseTest::testProcessRedirect()
httpHeader->clearField();
// Test for percent-encode
httpHeader->put("Location", "http://example.org/white space#aria2");
httpResponse.processRedirect();
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/white%20space"),
request->getCurrentUri());
httpHeader->clearField();
// Give unsupported scheme
httpHeader->put("Location", "unsupported://mirror/aria2-1.0.0.tar.bz2");
try {

View File

@ -15,7 +15,6 @@ class RequestTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testSetUri1);
CPPUNIT_TEST(testSetUri2);
CPPUNIT_TEST(testSetUri7);
CPPUNIT_TEST(testSetUri17);
CPPUNIT_TEST(testSetUri_supportsPersistentConnection);
CPPUNIT_TEST(testRedirectUri);
CPPUNIT_TEST(testRedirectUri2);
@ -31,7 +30,6 @@ public:
void testSetUri1();
void testSetUri2();
void testSetUri7();
void testSetUri17();
void testSetUri_supportsPersistentConnection();
void testRedirectUri();
void testRedirectUri2();
@ -94,27 +92,6 @@ void RequestTest::testSetUri7() {
CPPUNIT_ASSERT(!v);
}
void RequestTest::testSetUri17()
{
Request req;
bool v = req.setUri("http://host:80/file<with%2 %20space/"
"file with space;param%?a=/?");
CPPUNIT_ASSERT(v);
CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol());
CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost());
CPPUNIT_ASSERT_EQUAL(std::string("/file%3Cwith%2%20%20space"),
req.getDir());
CPPUNIT_ASSERT_EQUAL(std::string("file%20with%20space;param%"),
req.getFile());
CPPUNIT_ASSERT_EQUAL(std::string("?a=/?"), req.getQuery());
CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file%3Cwith%2%20%20space"
"/file%20with%20space;param%?a=/?"),
req.getCurrentUri());
CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file<with%2 %20space"
"/file with space;param%?a=/?"),
req.getUri());
}
void RequestTest::testRedirectUri()
{
Request req;
@ -155,11 +132,6 @@ void RequestTest::testRedirectUri()
"relativepath/to/file"),
req.getCurrentUri());
CPPUNIT_ASSERT_EQUAL((unsigned int)3, req.getRedirectCount());
// White space in path and fragment is appended.
CPPUNIT_ASSERT(req.redirectUri("http://example.org/white space#aria2"));
CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/white%20space"),
req.getCurrentUri());
}
void RequestTest::testRedirectUri2()