diff --git a/src/util.cc b/src/util.cc index 5c7d320d..8fbb66d8 100644 --- a/src/util.cc +++ b/src/util.cc @@ -81,6 +81,7 @@ #include "Logger.h" #include "Option.h" #include "DownloadContext.h" +#include "uri.h" #ifdef ENABLE_MESSAGE_DIGEST # include "MessageDigest.h" @@ -1583,6 +1584,31 @@ std::string safeStrerror(int errNum) return makeString(strerror(errNum)); } +std::string joinUri(const std::string& baseUri, const std::string& uri) +{ + uri::UriStruct us; + if(uri::parse(us, uri)) { + return uri; + } else { + uri::UriStruct bus; + if(!uri::parse(bus, baseUri)) { + return uri; + } + if(util::startsWith(uri, "/")) { + bus.dir.clear(); + } + bus.file.clear(); + bus.query.clear(); + std::string newUri = construct(bus); + if(util::startsWith(uri, "/")) { + newUri += uri.substr(1); + } else { + newUri += uri; + } + return newUri; + } +} + } // namespace util } // namespace aria2 diff --git a/src/util.h b/src/util.h index 939dc2b7..b632433a 100644 --- a/src/util.h +++ b/src/util.h @@ -324,6 +324,8 @@ std::string joinPath(InputIterator first, InputIterator last) return strjoin(elements.begin(), elements.end(), "/"); } +std::string joinUri(const std::string& baseUri, const std::string& uri); + // Parses INDEX=PATH format string. INDEX must be an unsigned // integer. std::map::value_type diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 02e884f1..48f5d6fa 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -71,6 +71,7 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testGetCidrPrefix); CPPUNIT_TEST(testInSameCidrBlock); CPPUNIT_TEST(testIsUtf8String); + CPPUNIT_TEST(testJoinUri); CPPUNIT_TEST_SUITE_END(); private: @@ -130,6 +131,7 @@ public: void testGetCidrPrefix(); void testInSameCidrBlock(); void testIsUtf8String(); + void testJoinUri(); }; @@ -1247,4 +1249,25 @@ void UtilTest::testIsUtf8String() CPPUNIT_ASSERT(!util::isUtf8(util::fromHex("00"))); } +void UtilTest::testJoinUri() +{ + CPPUNIT_ASSERT_EQUAL(std::string("http://host/dir/file"), + util::joinUri("http://base/d/f", + "http://host/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("http://base/dir/file"), + util::joinUri("http://base/d/f", + "/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("http://base/d/dir/file"), + util::joinUri("http://base/d/f", + "dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("http://base/d/"), + util::joinUri("http://base/d/f", + "")); + CPPUNIT_ASSERT_EQUAL(std::string("http://base/d/dir/file?q=k"), + util::joinUri("http://base/d/f", + "dir/file?q=k")); + CPPUNIT_ASSERT_EQUAL(std::string("dir/file"), + util::joinUri("baduri", "dir/file")); +} + } // namespace aria2