return output;
}
+SBuf
+AnyP::Uri::Decode(const SBuf &buf)
+{
+ SBuf output;
+ Parser::Tokenizer tok(buf);
+ while (!tok.atEnd()) {
+ SBuf token;
+ static const auto unencodedChars = CharacterSet("percent", "%").complement("unencoded");
+ if (tok.prefix(token, unencodedChars))
+ output.append(token);
+
+ // we are either at '%' or at end of input
+ if (tok.skip('%')) {
+ int64_t hex1 = 0, hex2 = 0;
+ if (tok.int64(hex1, 16, false, 1) && tok.int64(hex2, 16, false, 1))
+ output.append(static_cast<char>((hex1 << 4) | hex2));
+ else
+ throw TextException("invalid pct-encoded triplet", Here());
+ }
+ }
+ return output;
+}
+
const SBuf &
AnyP::Uri::Asterisk()
{
#include "squid.h"
#include "anyp/Uri.h"
+#include "base/CharacterSet.h"
+#include "base/TextException.h"
#include "compat/cppunit.h"
#include "debug/Stream.h"
+#include "sbuf/Stream.h"
#include "unitTestMain.h"
#include <cppunit/TestAssert.h>
CPPUNIT_TEST_SUITE(TestUri);
CPPUNIT_TEST(testConstructScheme);
CPPUNIT_TEST(testDefaultConstructor);
+ CPPUNIT_TEST(testEncoding);
CPPUNIT_TEST_SUITE_END();
protected:
void testConstructScheme();
void testDefaultConstructor();
+ void testEncoding();
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestUri);
delete urlPointer;
}
+void
+TestUri::testEncoding()
+{
+ const std::vector< std::pair<SBuf, SBuf> > basicTestCases = {
+ {SBuf(""), SBuf("")},
+ {SBuf("foo"), SBuf("foo")},
+ {SBuf("%"), SBuf("%25")},
+ {SBuf("%foo"), SBuf("%25foo")},
+ {SBuf("foo%"), SBuf("foo%25")},
+ {SBuf("fo%o"), SBuf("fo%25o")},
+ {SBuf("fo%%o"), SBuf("fo%25%25o")},
+ {SBuf("fo o"), SBuf("fo%20o")},
+ {SBuf("?1"), SBuf("%3F1")},
+ {SBuf("\377"), SBuf("%FF")},
+ {SBuf("fo\0o", 4), SBuf("fo%00o")},
+ };
+
+ for (const auto &testCase: basicTestCases) {
+ CPPUNIT_ASSERT_EQUAL(testCase.first, AnyP::Uri::Decode(testCase.second));
+ CPPUNIT_ASSERT_EQUAL(testCase.second, AnyP::Uri::Encode(testCase.first, CharacterSet::RFC3986_UNRESERVED()));
+ };
+
+ const auto invalidEncodings = {
+ SBuf("%"),
+ SBuf("%%"),
+ SBuf("%%%"),
+ SBuf("%1"),
+ SBuf("%1Z"),
+ SBuf("%1\000", 2),
+ SBuf("%1\377"),
+ SBuf("%\0002", 3),
+ SBuf("%\3772"),
+ };
+
+ for (const auto &invalidEncoding: invalidEncodings) {
+ // test various input positions of an invalid escape sequence
+ CPPUNIT_ASSERT_THROW(AnyP::Uri::Decode(invalidEncoding), TextException);
+ CPPUNIT_ASSERT_THROW(AnyP::Uri::Decode(ToSBuf("word", invalidEncoding)), TextException);
+ CPPUNIT_ASSERT_THROW(AnyP::Uri::Decode(ToSBuf(invalidEncoding, "word")), TextException);
+ CPPUNIT_ASSERT_THROW(AnyP::Uri::Decode(ToSBuf("word", invalidEncoding, "word")), TextException);
+ };
+}
+
int
main(int argc, char *argv[])
{