diff --git a/src/uri.cc b/src/uri.cc index 6c4b4685..475b7663 100644 --- a/src/uri.cc +++ b/src/uri.cc @@ -238,6 +238,41 @@ bool parse(UriStruct& result, const std::string& uri) return true; } +std::string construct(const UriStruct& us) +{ + std::string res; + res += us.protocol; + res += "://"; + if(!us.username.empty()) { + res += util::percentEncode(us.username); + if(us.hasPassword) { + res += ":"; + res += util::percentEncode(us.password); + } + res += "@"; + } + if(us.ipv6LiteralAddress) { + res += "["; + res += us.host; + res += "]"; + } else { + res += us.host; + } + uint16_t defPort= FeatureConfig::getInstance()-> + getDefaultPort(us.protocol); + if(us.port != 0 && defPort != us.port) { + res += ":"; + res += util::uitos(us.port); + } + res += us.dir; + if(us.dir.empty() || us.dir[us.dir.size()-1] != '/') { + res += "/"; + } + res += us.file; + res += us.query; + return res; +} + } // namespace uri } // namespace aria2 diff --git a/src/uri.h b/src/uri.h index 48ed3562..c51be38e 100644 --- a/src/uri.h +++ b/src/uri.h @@ -67,6 +67,8 @@ struct UriStruct { // undefined. bool parse(UriStruct& result, const std::string& uri); +std::string construct(const UriStruct& us); + } // namespace uri } // namespace aria2 diff --git a/test/UriTest.cc b/test/UriTest.cc index 9c65cfb7..025f41ca 100644 --- a/test/UriTest.cc +++ b/test/UriTest.cc @@ -33,6 +33,7 @@ class UriTest:public CppUnit::TestFixture { CPPUNIT_TEST(testSetUri_zeroUsername); CPPUNIT_TEST(testSetUri_ipv6); CPPUNIT_TEST(testInnerLink); + CPPUNIT_TEST(testConstruct); CPPUNIT_TEST_SUITE_END(); public: @@ -60,6 +61,7 @@ public: void testSetUri_zeroUsername(); void testSetUri_ipv6(); void testInnerLink(); + void testConstruct(); }; @@ -384,6 +386,90 @@ void UriTest::testInnerLink() CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); } +void UriTest::testConstruct() +{ + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host/dir/file?q=abc#foo")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host/dir/file?q=abc"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host/dir/file"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host/dir/")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host/dir/"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host/dir")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host/dir"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host/")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host/"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host/"), + construct(us)); + } + { + UriStruct us; + us.protocol = "http"; + us.host = "host"; + us.file = "foo.xml"; + CPPUNIT_ASSERT_EQUAL(std::string("http://host/foo.xml"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host:80")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host/"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://host:8080")); + CPPUNIT_ASSERT_EQUAL(std::string("http://host:8080/"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "http://[::1]:8000/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("http://[::1]:8000/dir/file"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "ftp://user%40@host/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp://user%40@host/dir/file"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "ftp://user:@host/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp://user:@host/dir/file"), + construct(us)); + } + { + UriStruct us; + CPPUNIT_ASSERT(parse(us, "ftp://user:passwd%40@host/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp://user:passwd%40@host/dir/file"), + construct(us)); + } +} + } // namespace uri } // namespace aria2