Only percent-encode non-printable ASCII chars(0x00-0x1f), non-ASCII

chars(>0x7f), ' ', '"', '<' and '>' for URIs supplied by user and
remote server(usually Location header field).
pull/1/head
Tatsuhiro Tsujikawa 2011-06-01 01:34:30 +09:00
parent 74a049ddfc
commit 2799c9f0cc
2 changed files with 16 additions and 22 deletions

View File

@ -88,26 +88,20 @@ std::string removeFragment(const std::string& uri)
namespace { namespace {
std::string percentEncode(const std::string& src) std::string percentEncode(const std::string& src)
{ {
std::string result = src; std::string result;
if(src.empty()) { for(std::string::const_iterator i = src.begin(), eoi = src.end(); i != eoi;
return result; ++i) {
} // Non-Printable ASCII and non-ASCII chars + some ASCII chars.
result += " "; unsigned char c = *i;
for(int index = src.size()-1; index >= 0; --index) { if(in(c, 0x00u, 0x1fu) || c >= 0x7fu ||
const unsigned char c = result[index]; // Chromium escapes following characters. Firefox4 escapes
// '/' is not percent encoded because src is expected to be a path. // more.
if(!util::inRFC3986ReservedChars(c) && !util::inRFC3986UnreservedChars(c)) { c == ' ' || c == '"' || c == '<' || c == '>') {
if(c == '%') { result += fmt("%%%02X", c);
if(!util::isHexDigit(result[index+1]) || } else {
!util::isHexDigit(result[index+2])) { result += c;
result.replace(index, 1, "%25");
}
} else {
result.replace(index, 1, fmt("%%%02X", c));
}
} }
} }
result.erase(result.size()-2);
return result; return result;
} }
} // namespace } // namespace

View File

@ -102,13 +102,13 @@ void RequestTest::testSetUri17()
CPPUNIT_ASSERT(v); CPPUNIT_ASSERT(v);
CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol());
CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost()); CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost());
CPPUNIT_ASSERT_EQUAL(std::string("/file%3Cwith%252%20%20space"), CPPUNIT_ASSERT_EQUAL(std::string("/file%3Cwith%2%20%20space"),
req.getDir()); req.getDir());
CPPUNIT_ASSERT_EQUAL(std::string("file%20with%20space;param%25"), CPPUNIT_ASSERT_EQUAL(std::string("file%20with%20space;param%"),
req.getFile()); req.getFile());
CPPUNIT_ASSERT_EQUAL(std::string("?a=/?"), req.getQuery()); CPPUNIT_ASSERT_EQUAL(std::string("?a=/?"), req.getQuery());
CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file%3Cwith%252%20%20space" CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file%3Cwith%2%20%20space"
"/file%20with%20space;param%25?a=/?"), "/file%20with%20space;param%?a=/?"),
req.getCurrentUri()); req.getCurrentUri());
CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file<with%2 %20space" CPPUNIT_ASSERT_EQUAL(std::string("http://host:80/file<with%2 %20space"
"/file with space;param%?a=/?"), "/file with space;param%?a=/?"),