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