diff --git a/Foundation/include/Poco/URI.h b/Foundation/include/Poco/URI.h index 944b84cc5..4aa36fde8 100644 --- a/Foundation/include/Poco/URI.h +++ b/Foundation/include/Poco/URI.h @@ -246,10 +246,12 @@ public: /// URI-encodes the given string by escaping reserved and non-ASCII /// characters. The encoded string is appended to encodedStr. - static void decode(const std::string& str, std::string& decodedStr); + static void decode(const std::string& str, std::string& decodedStr, bool plusAsSpace = false); /// URI-decodes the given string by replacing percent-encoded /// characters with the actual character. The decoded string /// is appended to decodedStr. + /// When plusAsSpace is true, non-encoded plus signs in the query are decoded as spaces. + /// (http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1) protected: bool equals(const URI& uri) const; diff --git a/Foundation/src/URI.cpp b/Foundation/src/URI.cpp index cb30ca429..d0626f03a 100644 --- a/Foundation/src/URI.cpp +++ b/Foundation/src/URI.cpp @@ -595,14 +595,18 @@ void URI::encode(const std::string& str, const std::string& reserved, std::strin } -void URI::decode(const std::string& str, std::string& decodedStr) +void URI::decode(const std::string& str, std::string& decodedStr, bool plusAsSpace) { + bool inQuery = false; std::string::const_iterator it = str.begin(); std::string::const_iterator end = str.end(); while (it != end) { char c = *it++; - if (c == '%') + if (c == '?') inQuery = true; + // spaces may be encoded as plus signs in the query + if (inQuery && plusAsSpace && c == '+') c = ' '; + else if (c == '%') { if (it == end) throw SyntaxException("URI encoding: no hex digit following percent sign", str); char hi = *it++; diff --git a/Foundation/testsuite/src/URITest.cpp b/Foundation/testsuite/src/URITest.cpp index bcbfeff51..ca6433754 100644 --- a/Foundation/testsuite/src/URITest.cpp +++ b/Foundation/testsuite/src/URITest.cpp @@ -767,6 +767,26 @@ void URITest::testOther() } +void URITest::testEncodeDecode() +{ + std::string str; + URI::encode("http://google.com/search?q=hello+world#frag ment", "+#?", str); + assert (str == "http://google.com/search%3Fq=hello%2Bworld%23frag%20ment"); + + str = ""; + URI::encode("http://google.com/search?q=hello+world#frag ment", "", str); + assert (str == "http://google.com/search?q=hello+world#frag%20ment"); + + str = ""; + URI::decode("http://google.com/search?q=hello+world#frag%20ment", str, true); + assert (str == "http://google.com/search?q=hello world#frag ment"); + + str = ""; + URI::decode("http://google.com/search?q=hello%2Bworld#frag%20ment", str); + assert (str == "http://google.com/search?q=hello+world#frag ment"); +} + + void URITest::setUp() { } @@ -788,6 +808,7 @@ CppUnit::Test* URITest::suite() CppUnit_addTest(pSuite, URITest, testNormalize); CppUnit_addTest(pSuite, URITest, testResolve); CppUnit_addTest(pSuite, URITest, testSwap); + CppUnit_addTest(pSuite, URITest, testEncodeDecode); CppUnit_addTest(pSuite, URITest, testOther); return pSuite; diff --git a/Foundation/testsuite/src/URITest.h b/Foundation/testsuite/src/URITest.h index 0895403b8..fb5f63153 100644 --- a/Foundation/testsuite/src/URITest.h +++ b/Foundation/testsuite/src/URITest.h @@ -53,6 +53,7 @@ public: void testNormalize(); void testResolve(); void testSwap(); + void testEncodeDecode(); void testOther(); void setUp();