diff --git a/net/NetUtil.cpp b/net/NetUtil.cpp index b4fc162d1..3a3d7d8a4 100644 --- a/net/NetUtil.cpp +++ b/net/NetUtil.cpp @@ -8,6 +8,7 @@ #include #include "NetUtil.hpp" +#include #include "Socket.hpp" #if ENABLE_SSL && !MOBILEAPP @@ -90,4 +91,41 @@ connect(const std::string& host, const std::string& port, const bool isSSL, return socket; } +bool parseUri(std::string uri, std::string& scheme, std::string& host, std::string& port) +{ + const auto itScheme = uri.find("://"); + if (itScheme != uri.npos) + { + scheme = uri.substr(0, itScheme + 3); // Include the last slash. + uri = uri.substr(scheme.size()); // Remove the scheme. + } + else + { + // No scheme. + scheme.clear(); + } + + const auto itUrl = uri.find('/'); + if (itUrl != uri.npos) + { + // Remove the URL. + uri = uri.substr(0, itUrl); + } + + const auto itPort = uri.find(':'); + if (itPort != uri.npos) + { + host = uri.substr(0, itPort); + port = uri.substr(itPort + 1); // Skip the colon. + } + else + { + // No port, just hostname. + host = uri; + port.clear(); + } + + return !host.empty(); +} + } // namespace net \ No newline at end of file diff --git a/net/NetUtil.hpp b/net/NetUtil.hpp index 547f94a62..783f862aa 100644 --- a/net/NetUtil.hpp +++ b/net/NetUtil.hpp @@ -23,4 +23,9 @@ namespace net std::shared_ptr connect(const std::string& host, const std::string& port, const bool isSSL, const std::shared_ptr& protocolHandler); + +/// Decomposes a URI into its components. +/// Returns true if parsing was successful. +bool parseUri(std::string uri, std::string& scheme, std::string& host, std::string& port); + } // namespace net \ No newline at end of file diff --git a/test/WhiteBoxTests.cpp b/test/WhiteBoxTests.cpp index 404404376..b7ed8dd45 100644 --- a/test/WhiteBoxTests.cpp +++ b/test/WhiteBoxTests.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(testCSSVars); CPPUNIT_TEST(testStat); CPPUNIT_TEST(testStringCompare); + CPPUNIT_TEST(testParseUri); CPPUNIT_TEST_SUITE_END(); @@ -86,6 +88,7 @@ class WhiteBoxTests : public CPPUNIT_NS::TestFixture void testCSSVars(); void testStat(); void testStringCompare(); + void testParseUri(); }; void WhiteBoxTests::testLOOLProtocolFunctions() @@ -1788,6 +1791,51 @@ void WhiteBoxTests::testStringCompare() LOK_ASSERT(!Util::iequal("abc", 3, "abcd", 4)); } +void WhiteBoxTests::testParseUri() +{ + std::string scheme; + std::string host; + std::string port; + + scheme = "***"; + host = "***"; + port = "***"; + LOK_ASSERT(!net::parseUri(std::string(), scheme, host, port)); + LOK_ASSERT(scheme.empty()); + LOK_ASSERT(host.empty()); + LOK_ASSERT(port.empty()); + + LOK_ASSERT(net::parseUri("domain.com", scheme, host, port)); + LOK_ASSERT(scheme.empty()); + LOK_ASSERT_EQUAL(std::string("domain.com"), host); + LOK_ASSERT(port.empty()); + + LOK_ASSERT(net::parseUri("domain.com:88", scheme, host, port)); + LOK_ASSERT(scheme.empty()); + LOK_ASSERT_EQUAL(std::string("domain.com"), host); + LOK_ASSERT_EQUAL(std::string("88"), port); + + LOK_ASSERT(net::parseUri("http://domain.com", scheme, host, port)); + LOK_ASSERT_EQUAL(std::string("http://"), scheme); + LOK_ASSERT_EQUAL(std::string("domain.com"), host); + LOK_ASSERT(port.empty()); + + LOK_ASSERT(net::parseUri("https://domain.com:88", scheme, host, port)); + LOK_ASSERT_EQUAL(std::string("https://"), scheme); + LOK_ASSERT_EQUAL(std::string("domain.com"), host); + LOK_ASSERT_EQUAL(std::string("88"), port); + + LOK_ASSERT(net::parseUri("http://domain.com/path/to/file", scheme, host, port)); + LOK_ASSERT_EQUAL(std::string("http://"), scheme); + LOK_ASSERT_EQUAL(std::string("domain.com"), host); + LOK_ASSERT(port.empty()); + + LOK_ASSERT(net::parseUri("https://domain.com:88/path/to/file", scheme, host, port)); + LOK_ASSERT_EQUAL(std::string("https://"), scheme); + LOK_ASSERT_EQUAL(std::string("domain.com"), host); + LOK_ASSERT_EQUAL(std::string("88"), port); +} + CPPUNIT_TEST_SUITE_REGISTRATION(WhiteBoxTests); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */