From 2799c9f0ccee2e4a453ef1df5e3fa3d8547fae9e Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 1 Jun 2011 01:34:30 +0900 Subject: [PATCH] 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). --- src/Request.cc | 30 ++++++++++++------------------ test/RequestTest.cc | 8 ++++---- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/Request.cc b/src/Request.cc index 2fad4b19..6f0f50c1 100644 --- a/src/Request.cc +++ b/src/Request.cc @@ -88,26 +88,20 @@ std::string removeFragment(const std::string& uri) namespace { std::string percentEncode(const std::string& src) { - std::string result = src; - if(src.empty()) { - return result; - } - result += " "; - for(int index = src.size()-1; index >= 0; --index) { - const unsigned char c = result[index]; - // '/' is not percent encoded because src is expected to be a path. - if(!util::inRFC3986ReservedChars(c) && !util::inRFC3986UnreservedChars(c)) { - if(c == '%') { - if(!util::isHexDigit(result[index+1]) || - !util::isHexDigit(result[index+2])) { - result.replace(index, 1, "%25"); - } - } else { - result.replace(index, 1, fmt("%%%02X", c)); - } + 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, 0x1fu) || c >= 0x7fu || + // Chromium escapes following characters. Firefox4 escapes + // more. + c == ' ' || c == '"' || c == '<' || c == '>') { + result += fmt("%%%02X", c); + } else { + result += c; } } - result.erase(result.size()-2); return result; } } // namespace diff --git a/test/RequestTest.cc b/test/RequestTest.cc index 3427ee57..3b361532 100644 --- a/test/RequestTest.cc +++ b/test/RequestTest.cc @@ -102,13 +102,13 @@ void RequestTest::testSetUri17() 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%252%20%20space"), + CPPUNIT_ASSERT_EQUAL(std::string("/file%3Cwith%2%20%20space"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string("file%20with%20space;param%25"), + 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%252%20%20space" - "/file%20with%20space;param%25?a=/?"), + 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