diff --git a/ChangeLog b/ChangeLog index 822bc572..f02a9831 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2010-09-11 Tatsuhiro Tsujikawa + + Moved URI parser code to uri.h, uri.cc to provide fast URI parser + without Request object initialization. + * src/Makefile.am + * src/Request.cc + * src/uri.cc + * src/uri.h + * test/Makefile.am + * test/RequestTest.cc + * test/UriTest.cc + 2010-09-10 Tatsuhiro Tsujikawa Store last error of removed download result so that it can be used diff --git a/src/Makefile.am b/src/Makefile.am index 813c96a1..f9a9818e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -211,7 +211,8 @@ SRCS = Socket.h\ SinkStreamFilter.cc SinkStreamFilter.h\ GZipDecodingStreamFilter.cc GZipDecodingStreamFilter.h\ ChunkedDecodingStreamFilter.cc ChunkedDecodingStreamFilter.h\ - NullSinkStreamFilter.cc NullSinkStreamFilter.h + NullSinkStreamFilter.cc NullSinkStreamFilter.h\ + uri.cc uri.h if ENABLE_XML_RPC SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\ diff --git a/src/Makefile.in b/src/Makefile.in index af897bba..a354543f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -446,7 +446,7 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ StreamFilter.h SinkStreamFilter.cc SinkStreamFilter.h \ GZipDecodingStreamFilter.cc GZipDecodingStreamFilter.h \ ChunkedDecodingStreamFilter.cc ChunkedDecodingStreamFilter.h \ - NullSinkStreamFilter.cc NullSinkStreamFilter.h \ + NullSinkStreamFilter.cc NullSinkStreamFilter.h uri.cc uri.h \ XmlRpcRequestParserController.cc \ XmlRpcRequestParserController.h \ XmlRpcRequestParserStateMachine.cc \ @@ -890,7 +890,7 @@ am__objects_32 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ StreamFilter.$(OBJEXT) SinkStreamFilter.$(OBJEXT) \ GZipDecodingStreamFilter.$(OBJEXT) \ ChunkedDecodingStreamFilter.$(OBJEXT) \ - NullSinkStreamFilter.$(OBJEXT) $(am__objects_1) \ + NullSinkStreamFilter.$(OBJEXT) uri.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ @@ -1238,17 +1238,18 @@ SRCS = Socket.h SocketCore.cc SocketCore.h BinaryStream.h Command.cc \ StreamFilter.h SinkStreamFilter.cc SinkStreamFilter.h \ GZipDecodingStreamFilter.cc GZipDecodingStreamFilter.h \ ChunkedDecodingStreamFilter.cc ChunkedDecodingStreamFilter.h \ - NullSinkStreamFilter.cc NullSinkStreamFilter.h $(am__append_1) \ - $(am__append_2) $(am__append_3) $(am__append_4) \ - $(am__append_5) $(am__append_6) $(am__append_7) \ - $(am__append_8) $(am__append_9) $(am__append_10) \ - $(am__append_11) $(am__append_12) $(am__append_13) \ - $(am__append_14) $(am__append_15) $(am__append_16) \ - $(am__append_17) $(am__append_18) $(am__append_19) \ - $(am__append_20) $(am__append_21) $(am__append_22) \ - $(am__append_23) $(am__append_24) $(am__append_25) \ - $(am__append_26) $(am__append_27) $(am__append_28) \ - $(am__append_29) $(am__append_30) $(am__append_31) + NullSinkStreamFilter.cc NullSinkStreamFilter.h uri.cc uri.h \ + $(am__append_1) $(am__append_2) $(am__append_3) \ + $(am__append_4) $(am__append_5) $(am__append_6) \ + $(am__append_7) $(am__append_8) $(am__append_9) \ + $(am__append_10) $(am__append_11) $(am__append_12) \ + $(am__append_13) $(am__append_14) $(am__append_15) \ + $(am__append_16) $(am__append_17) $(am__append_18) \ + $(am__append_19) $(am__append_20) $(am__append_21) \ + $(am__append_22) $(am__append_23) $(am__append_24) \ + $(am__append_25) $(am__append_26) $(am__append_27) \ + $(am__append_28) $(am__append_29) $(am__append_30) \ + $(am__append_31) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @@ -1682,6 +1683,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prefs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strptime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timegm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uri.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version_usage.Po@am__quote@ diff --git a/src/Request.cc b/src/Request.cc index 1eb7c4e7..1e7e3d3b 100644 --- a/src/Request.cc +++ b/src/Request.cc @@ -41,6 +41,7 @@ #include "StringFormat.h" #include "A2STR.h" #include "a2functional.h" +#include "uri.h" namespace aria2 { @@ -147,161 +148,23 @@ bool Request::redirectUri(const std::string& uri) { } bool Request::parseUri(const std::string& srcUri) { - const std::string uri = percentEncode(removeFragment(srcUri)); - currentUri_ = uri; - host_ = A2STR::NIL; - port_ = 0; - dir_ = A2STR::NIL; - file_ = A2STR::NIL; - query_ = A2STR::NIL; - username_ = A2STR::NIL; - password_ = A2STR::NIL; - hasPassword_ = false; - ipv6LiteralAddress_ = false; - - // http://user:password@aria2.sourceforge.net:80/dir/file?query - // | || || | | | - // | || hostLast| | | | - // | || portFirst| | | - // authorityFirst || authorityLast | | - // || | | | - // userInfoLast | | | - // | | | | - // hostPortFirst | | | - // | | | - // dirFirst dirLast| - // | - // queryFirst - - // find query part - std::string::const_iterator queryFirst = uri.begin(); - for(; queryFirst != uri.end(); ++queryFirst) { - if(*queryFirst == '?') break; - } - query_ = std::string(queryFirst, uri.end()); - // find protocol - std::string::size_type protocolOffset = uri.find("://"); - if(protocolOffset == std::string::npos) return false; - protocol_ = std::string(uri.begin(), uri.begin()+protocolOffset); - uint16_t defPort; - if((defPort = FeatureConfig::getInstance()->getDefaultPort(protocol_)) == 0) { + currentUri_ = percentEncode(removeFragment(srcUri)); + uri::UriStruct us; + if(uri::parse(us, currentUri_)) { + protocol_.swap(us.protocol); + host_.swap(us.host); + port_ = us.port; + dir_.swap(us.dir); + file_.swap(us.file); + query_.swap(us.query); + username_.swap(us.username); + password_.swap(us.password); + hasPassword_ = us.hasPassword; + ipv6LiteralAddress_ = us.ipv6LiteralAddress; + return true; + } else { return false; } - // find authority - std::string::const_iterator authorityFirst = uri.begin()+protocolOffset+3; - std::string::const_iterator authorityLast = authorityFirst; - for(; authorityLast != queryFirst; ++authorityLast) { - if(*authorityLast == '/') break; - } - if(authorityFirst == authorityLast) { - // No authority found - return false; - } - // find userinfo(username and password) in authority if they exist - std::string::const_iterator userInfoLast = authorityLast; - std::string::const_iterator hostPortFirst = authorityFirst; - for(; userInfoLast != authorityFirst-1; --userInfoLast) { - if(*userInfoLast == '@') { - hostPortFirst = userInfoLast; - ++hostPortFirst; - std::string::const_iterator userLast = authorityFirst; - for(; userLast != userInfoLast; ++userLast) { - if(*userLast == ':') { - password_ = util::percentDecode(std::string(userLast+1,userInfoLast)); - hasPassword_ = true; - break; - } - } - username_ = util::percentDecode(std::string(authorityFirst, userLast)); - break; - } - } - std::string::const_iterator hostLast = hostPortFirst; - std::string::const_iterator portFirst = authorityLast; - if(*hostPortFirst == '[') { - // Detected IPv6 literal address in square brackets - for(; hostLast != authorityLast; ++hostLast) { - if(*hostLast == ']') { - ++hostLast; - if(hostLast == authorityLast) { - ipv6LiteralAddress_ = true; - } else { - if(*hostLast == ':') { - portFirst = hostLast; - ++portFirst; - ipv6LiteralAddress_ = true; - } - } - break; - } - } - if(!ipv6LiteralAddress_) { - return false; - } - } else { - for(; hostLast != authorityLast; ++hostLast) { - if(*hostLast == ':') { - portFirst = hostLast; - ++portFirst; - break; - } - } - } - if(hostPortFirst == hostLast) { - // No host - return false; - } - if(portFirst == authorityLast) { - // If port is not specified, then we set it to default port of - // its protocol.. - port_ = defPort; - } else { - uint32_t tempPort; - if(util::parseUIntNoThrow(tempPort, std::string(portFirst, authorityLast))){ - if(65535 < tempPort) { - return false; - } - port_ = tempPort; - } else { - return false; - } - } - if(ipv6LiteralAddress_) { - host_ = std::string(hostPortFirst+1, hostLast-1); - } else { - host_ = std::string(hostPortFirst, hostLast); - } - // find directory and file part - std::string::const_iterator dirLast = authorityLast; - for(std::string::const_iterator i = authorityLast; - i != queryFirst; ++i) { - if(*i == '/') { - dirLast = i; - } - } - if(dirLast != queryFirst) { - file_ = std::string(dirLast+1, queryFirst); - } - // Erase duplicated slashes. - std::string::const_iterator dirFirst = authorityLast; - for(; dirFirst != dirLast; ++dirFirst) { - if(*dirFirst != '/') { - --dirFirst; - break; - } - } - for(; dirLast != dirFirst; --dirLast) { - if(*dirLast != '/') { - ++dirLast; - break; - } - } - if(dirFirst == dirLast) { - dir_ = A2STR::SLASH_C; - } else { - dir_ = std::string(dirFirst, dirLast); - } - return true; } void Request::resetRedirectCount() diff --git a/src/uri.cc b/src/uri.cc new file mode 100644 index 00000000..cee5589a --- /dev/null +++ b/src/uri.cc @@ -0,0 +1,207 @@ +/* */ +#include "uri.h" +#include "A2STR.h" +#include "FeatureConfig.h" +#include "util.h" + +namespace aria2 { + +namespace uri { + +bool parse(UriStruct& result, const std::string& uri) +{ + // http://user:password@aria2.sourceforge.net:80/dir/file?query#fragment + // | || || | | | | + // | || hostLast| | | | | + // | || portFirst| | | | + // authorityFirst || authorityLast | | | + // || | | | | + // userInfoLast | | | | + // | | | | | + // hostPortFirst | | | | + // | | | | + // dirFirst dirLast| | + // | | + // queryFirst fragmentFirst + + // find fragment part + std::string::const_iterator fragmentFirst = uri.begin(); + for(; fragmentFirst != uri.end(); ++fragmentFirst) { + if(*fragmentFirst == '#') break; + } + // find query part + std::string::const_iterator queryFirst = uri.begin(); + for(; queryFirst != fragmentFirst; ++queryFirst) { + if(*queryFirst == '?') break; + } + result.query = std::string(queryFirst, fragmentFirst); + // find protocol + std::string::size_type protocolOffset = uri.find("://"); + if(protocolOffset == std::string::npos) return false; + result.protocol = std::string(uri.begin(), uri.begin()+protocolOffset); + uint16_t defPort; + if((defPort = FeatureConfig::getInstance()-> + getDefaultPort(result.protocol)) == 0) { + return false; + } + // find authority + std::string::const_iterator authorityFirst = uri.begin()+protocolOffset+3; + std::string::const_iterator authorityLast = authorityFirst; + for(; authorityLast != queryFirst; ++authorityLast) { + if(*authorityLast == '/') break; + } + if(authorityFirst == authorityLast) { + // No authority found + return false; + } + // find userinfo(username and password) in authority if they exist + result.username = A2STR::NIL; + result.password = A2STR::NIL; + result.hasPassword = false; + std::string::const_iterator userInfoLast = authorityLast; + std::string::const_iterator hostPortFirst = authorityFirst; + for(; userInfoLast != authorityFirst-1; --userInfoLast) { + if(*userInfoLast == '@') { + hostPortFirst = userInfoLast; + ++hostPortFirst; + std::string::const_iterator userLast = authorityFirst; + for(; userLast != userInfoLast; ++userLast) { + if(*userLast == ':') { + result.password = + util::percentDecode(std::string(userLast+1,userInfoLast)); + result.hasPassword = true; + break; + } + } + result.username = + util::percentDecode(std::string(authorityFirst, userLast)); + break; + } + } + std::string::const_iterator hostLast = hostPortFirst; + std::string::const_iterator portFirst = authorityLast; + result.ipv6LiteralAddress = false; + if(*hostPortFirst == '[') { + // Detected IPv6 literal address in square brackets + for(; hostLast != authorityLast; ++hostLast) { + if(*hostLast == ']') { + ++hostLast; + if(hostLast == authorityLast) { + result.ipv6LiteralAddress = true; + } else { + if(*hostLast == ':') { + portFirst = hostLast; + ++portFirst; + result.ipv6LiteralAddress = true; + } + } + break; + } + } + if(!result.ipv6LiteralAddress) { + return false; + } + } else { + for(; hostLast != authorityLast; ++hostLast) { + if(*hostLast == ':') { + portFirst = hostLast; + ++portFirst; + break; + } + } + } + if(hostPortFirst == hostLast) { + // No host + return false; + } + if(portFirst == authorityLast) { + // If port is not specified, then we set it to default port of + // its protocol.. + result.port = defPort; + } else { + uint32_t tempPort; + if(util::parseUIntNoThrow(tempPort, std::string(portFirst, authorityLast))){ + if(65535 < tempPort) { + return false; + } + result.port = tempPort; + } else { + return false; + } + } + if(result.ipv6LiteralAddress) { + result.host = std::string(hostPortFirst+1, hostLast-1); + } else { + result.host = std::string(hostPortFirst, hostLast); + } + // find directory and file part + std::string::const_iterator dirLast = authorityLast; + for(std::string::const_iterator i = authorityLast; + i != queryFirst; ++i) { + if(*i == '/') { + dirLast = i; + } + } + if(dirLast == queryFirst) { + result.file = A2STR::NIL; + } else { + result.file = std::string(dirLast+1, queryFirst); + } + // Erase duplicated slashes. + std::string::const_iterator dirFirst = authorityLast; + for(; dirFirst != dirLast; ++dirFirst) { + if(*dirFirst != '/') { + --dirFirst; + break; + } + } + for(; dirLast != dirFirst; --dirLast) { + if(*dirLast != '/') { + ++dirLast; + break; + } + } + if(dirFirst == dirLast) { + result.dir = A2STR::SLASH_C; + } else { + result.dir = std::string(dirFirst, dirLast); + } + return true; +} + +} // namespace uri + +} // namespace aria2 diff --git a/src/uri.h b/src/uri.h new file mode 100644 index 00000000..97ed7ac6 --- /dev/null +++ b/src/uri.h @@ -0,0 +1,71 @@ +/* */ +#ifndef D_URI_H +#define D_URI_H + +#include "common.h" + +#include +#include "A2STR.h" + +namespace aria2 { + +namespace uri { + +struct UriStruct { + std::string protocol; + std::string host; + uint16_t port; + std::string dir; + std::string file; + std::string query; + std::string username; + std::string password; + bool hasPassword; + bool ipv6LiteralAddress; + + UriStruct():port(0), hasPassword(false), ipv6LiteralAddress(false) {} +}; + +// Splits URI uri into components and stores them into result. On +// success returns true. Otherwise returns false and result is +// undefined. +bool parse(UriStruct& result, const std::string& uri); + +} // namespace uri + +} // namespace aria2 + +#endif // D_URI_H diff --git a/test/Makefile.am b/test/Makefile.am index 9871cc21..50d0b394 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -74,7 +74,8 @@ aria2c_SOURCES = AllTest.cc\ SessionSerializerTest.cc\ ValueBaseTest.cc\ ChunkedDecodingStreamFilterTest.cc\ - GZipDecodingStreamFilterTest.cc + GZipDecodingStreamFilterTest.cc\ + UriTest.cc if ENABLE_XML_RPC aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc\ diff --git a/test/Makefile.in b/test/Makefile.in index c6717271..726fb8e9 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -214,7 +214,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ a2algoTest.cc bitfieldTest.cc DownloadContextTest.cc \ SessionSerializerTest.cc ValueBaseTest.cc \ ChunkedDecodingStreamFilterTest.cc \ - GZipDecodingStreamFilterTest.cc \ + GZipDecodingStreamFilterTest.cc UriTest.cc \ XmlRpcRequestParserControllerTest.cc \ XmlRpcRequestProcessorTest.cc XmlRpcMethodTest.cc \ FallocFileAllocationIteratorTest.cc GZipDecoderTest.cc \ @@ -408,9 +408,10 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \ DownloadContextTest.$(OBJEXT) SessionSerializerTest.$(OBJEXT) \ ValueBaseTest.$(OBJEXT) \ ChunkedDecodingStreamFilterTest.$(OBJEXT) \ - GZipDecodingStreamFilterTest.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) \ - $(am__objects_5) $(am__objects_6) $(am__objects_7) + GZipDecodingStreamFilterTest.$(OBJEXT) UriTest.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) \ + $(am__objects_7) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1) @@ -645,7 +646,7 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \ a2algoTest.cc bitfieldTest.cc DownloadContextTest.cc \ SessionSerializerTest.cc ValueBaseTest.cc \ ChunkedDecodingStreamFilterTest.cc \ - GZipDecodingStreamFilterTest.cc $(am__append_1) \ + GZipDecodingStreamFilterTest.cc UriTest.cc $(am__append_1) \ $(am__append_2) $(am__append_3) $(am__append_4) \ $(am__append_5) $(am__append_6) $(am__append_7) @@ -900,6 +901,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTMetadataRequestTrackerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTPexExtensionMessageTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParserTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ValueBaseTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XORCloserTest.Po@am__quote@ diff --git a/test/RequestTest.cc b/test/RequestTest.cc index 016e1e01..3427ee57 100644 --- a/test/RequestTest.cc +++ b/test/RequestTest.cc @@ -5,6 +5,7 @@ #include "Netrc.h" #include "DefaultAuthResolver.h" #include "NetrcAuthResolver.h" +#include "uri.h" namespace aria2 { @@ -13,29 +14,9 @@ class RequestTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(RequestTest); CPPUNIT_TEST(testSetUri1); CPPUNIT_TEST(testSetUri2); - CPPUNIT_TEST(testSetUri3); - CPPUNIT_TEST(testSetUri4); - CPPUNIT_TEST(testSetUri5); - CPPUNIT_TEST(testSetUri6); CPPUNIT_TEST(testSetUri7); - CPPUNIT_TEST(testSetUri8); - CPPUNIT_TEST(testSetUri9); - CPPUNIT_TEST(testSetUri10); - CPPUNIT_TEST(testSetUri11); - CPPUNIT_TEST(testSetUri12); - CPPUNIT_TEST(testSetUri13); - CPPUNIT_TEST(testSetUri14); - CPPUNIT_TEST(testSetUri15); - CPPUNIT_TEST(testSetUri16); CPPUNIT_TEST(testSetUri17); - CPPUNIT_TEST(testSetUri18); - CPPUNIT_TEST(testSetUri19); - CPPUNIT_TEST(testSetUri20); - CPPUNIT_TEST(testSetUri_username); - CPPUNIT_TEST(testSetUri_usernamePassword); - CPPUNIT_TEST(testSetUri_zeroUsername); CPPUNIT_TEST(testSetUri_supportsPersistentConnection); - CPPUNIT_TEST(testSetUri_ipv6); CPPUNIT_TEST(testRedirectUri); CPPUNIT_TEST(testRedirectUri2); CPPUNIT_TEST(testRedirectUri_supportsPersistentConnection); @@ -49,29 +30,9 @@ class RequestTest:public CppUnit::TestFixture { public: void testSetUri1(); void testSetUri2(); - void testSetUri3(); - void testSetUri4(); - void testSetUri5(); - void testSetUri6(); void testSetUri7(); - void testSetUri8(); - void testSetUri9(); - void testSetUri10(); - void testSetUri11(); - void testSetUri12(); - void testSetUri13(); - void testSetUri14(); - void testSetUri15(); - void testSetUri16(); void testSetUri17(); - void testSetUri18(); - void testSetUri19(); - void testSetUri20(); - void testSetUri_username(); - void testSetUri_usernamePassword(); - void testSetUri_zeroUsername(); void testSetUri_supportsPersistentConnection(); - void testSetUri_ipv6(); void testRedirectUri(); void testRedirectUri2(); void testRedirectUri_supportsPersistentConnection(); @@ -90,8 +51,10 @@ void RequestTest::testSetUri1() { bool v = req.setUri("http://aria.rednoah.com/"); CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http://aria.rednoah.com/"), req.getUri()); - CPPUNIT_ASSERT_EQUAL(std::string("http://aria.rednoah.com/"), req.getCurrentUri()); + CPPUNIT_ASSERT_EQUAL(std::string("http://aria.rednoah.com/"), + req.getUri()); + CPPUNIT_ASSERT_EQUAL(std::string("http://aria.rednoah.com/"), + req.getCurrentUri()); CPPUNIT_ASSERT_EQUAL(std::string(""), req.getPreviousUri()); CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); CPPUNIT_ASSERT_EQUAL((uint16_t)80, req.getPort()); @@ -112,7 +75,8 @@ void RequestTest::testSetUri2() { CPPUNIT_ASSERT(v); // referer is unchaged - CPPUNIT_ASSERT_EQUAL(std::string("http://aria.rednoah.com:8080"), req.getReferer()); + CPPUNIT_ASSERT_EQUAL(std::string("http://aria.rednoah.com:8080"), + req.getReferer()); // previousUri must equal to referer; CPPUNIT_ASSERT_EQUAL(req.getReferer(), req.getPreviousUri()); CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); @@ -123,58 +87,6 @@ void RequestTest::testSetUri2() { CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery()); } -void RequestTest::testSetUri3() { - Request req; - bool v = req.setUri("http://aria.rednoah.com/aria2/index.html"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL((uint16_t)80, req.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/aria2"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string("index.html"), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery()); -} - -void RequestTest::testSetUri4() { - Request req; - bool v = req.setUri("http://aria.rednoah.com/aria2/aria3/index.html"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL((uint16_t)80, req.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/aria2/aria3"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string("index.html"), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery()); -} - -void RequestTest::testSetUri5() { - Request req; - bool v = req.setUri("http://aria.rednoah.com/aria2/aria3/"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL((uint16_t)80, req.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/aria2/aria3"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery()); -} - -void RequestTest::testSetUri6() { - Request req; - bool v = req.setUri("http://aria.rednoah.com/aria2/aria3"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL((uint16_t)80, req.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/aria2"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string("aria3"), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery()); -} - void RequestTest::testSetUri7() { Request req; bool v = req.setUri("http://"); @@ -182,111 +94,18 @@ void RequestTest::testSetUri7() { CPPUNIT_ASSERT(!v); } -void RequestTest::testSetUri8() { - Request req; - bool v = req.setUri("http:/aria.rednoah.com"); - - CPPUNIT_ASSERT(!v); -} - -void RequestTest::testSetUri9() { - Request req; - bool v = req.setUri("h"); - - CPPUNIT_ASSERT(!v); -} - -void RequestTest::testSetUri10() { - Request req; - bool v = req.setUri(""); - - CPPUNIT_ASSERT(!v); -} - -void RequestTest::testSetUri11() { - Request req; - bool v = req.setUri("http://host?query/"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string("?query/"), req.getQuery()); -} - -void RequestTest::testSetUri12() { - Request req; - bool v = req.setUri("http://host?query"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string("?query"), req.getQuery()); -} - -void RequestTest::testSetUri13() { - Request req; - bool v = req.setUri("http://host/?query"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string("?query"), req.getQuery()); -} - -void RequestTest::testSetUri14() { - Request req; - bool v = req.setUri("http://host:8080/abc?query"); - - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost()); - CPPUNIT_ASSERT_EQUAL((uint16_t)8080, req.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string("abc"), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string("?query"), req.getQuery()); -} - -void RequestTest::testSetUri15() -{ - Request req; - // 2 slashes after host name and dir - bool v = req.setUri("http://host//dir1/dir2//file"); - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/dir1/dir2"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string("file"), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery()); -} - -void RequestTest::testSetUri16() -{ - Request req; - // 2 slashes before file - bool v = req.setUri("http://host//file"); - CPPUNIT_ASSERT(v); - CPPUNIT_ASSERT_EQUAL(std::string("http"), req.getProtocol()); - CPPUNIT_ASSERT_EQUAL(std::string("host"), req.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/"), req.getDir()); - CPPUNIT_ASSERT_EQUAL(std::string("file"), req.getFile()); - CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery()); -} - void RequestTest::testSetUri17() { Request req; - bool v = req.setUri("http://host:80/file + +namespace aria2 { + +namespace uri { + +class UriTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(UriTest); + CPPUNIT_TEST(testSetUri1); + CPPUNIT_TEST(testSetUri2); + CPPUNIT_TEST(testSetUri3); + CPPUNIT_TEST(testSetUri4); + CPPUNIT_TEST(testSetUri5); + CPPUNIT_TEST(testSetUri6); + CPPUNIT_TEST(testSetUri7); + CPPUNIT_TEST(testSetUri8); + CPPUNIT_TEST(testSetUri9); + CPPUNIT_TEST(testSetUri10); + CPPUNIT_TEST(testSetUri11); + CPPUNIT_TEST(testSetUri12); + CPPUNIT_TEST(testSetUri13); + CPPUNIT_TEST(testSetUri14); + CPPUNIT_TEST(testSetUri15); + CPPUNIT_TEST(testSetUri16); + CPPUNIT_TEST(testSetUri18); + CPPUNIT_TEST(testSetUri19); + CPPUNIT_TEST(testSetUri20); + CPPUNIT_TEST(testSetUri_username); + CPPUNIT_TEST(testSetUri_usernamePassword); + CPPUNIT_TEST(testSetUri_zeroUsername); + CPPUNIT_TEST(testSetUri_ipv6); + CPPUNIT_TEST(testInnerLink); + CPPUNIT_TEST_SUITE_END(); + +public: + void testSetUri1(); + void testSetUri2(); + void testSetUri3(); + void testSetUri4(); + void testSetUri5(); + void testSetUri6(); + void testSetUri7(); + void testSetUri8(); + void testSetUri9(); + void testSetUri10(); + void testSetUri11(); + void testSetUri12(); + void testSetUri13(); + void testSetUri14(); + void testSetUri15(); + void testSetUri16(); + void testSetUri18(); + void testSetUri19(); + void testSetUri20(); + void testSetUri_username(); + void testSetUri_usernamePassword(); + void testSetUri_zeroUsername(); + void testSetUri_ipv6(); + void testInnerLink(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( UriTest ); + +void UriTest::testSetUri1() +{ + UriStruct us; + bool v = parse(us, "http://aria.rednoah.com/"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)80, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.username); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.password); + CPPUNIT_ASSERT(!us.ipv6LiteralAddress); +} + +void UriTest::testSetUri2() +{ + UriStruct us; + bool v = parse(us, "http://aria.rednoah.com:8080/index.html"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)8080, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("index.html"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +void UriTest::testSetUri3() +{ + UriStruct us; + bool v = parse(us, "http://aria.rednoah.com/aria2/index.html"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)80, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/aria2"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("index.html"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +void UriTest::testSetUri4() +{ + UriStruct us; + bool v = parse(us, "http://aria.rednoah.com/aria2/aria3/index.html"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)80, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/aria2/aria3"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("index.html"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +void UriTest::testSetUri5() +{ + UriStruct us; + bool v = parse(us, "http://aria.rednoah.com/aria2/aria3/"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)80, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/aria2/aria3"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +void UriTest::testSetUri6() +{ + UriStruct us; + bool v = parse(us, "http://aria.rednoah.com/aria2/aria3"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)80, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("aria.rednoah.com"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/aria2"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("aria3"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +void UriTest::testSetUri7() +{ + UriStruct us; + bool v = parse(us, "http://"); + + CPPUNIT_ASSERT(!v); +} + +void UriTest::testSetUri8() +{ + UriStruct us; + bool v = parse(us, "http:/aria.rednoah.com"); + + CPPUNIT_ASSERT(!v); +} + +void UriTest::testSetUri9() +{ + UriStruct us; + bool v = parse(us, "h"); + + CPPUNIT_ASSERT(!v); +} + +void UriTest::testSetUri10() +{ + UriStruct us; + bool v = parse(us, ""); + + CPPUNIT_ASSERT(!v); +} + +void UriTest::testSetUri11() +{ + UriStruct us; + bool v = parse(us, "http://host?query/"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL(std::string("host"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.file); + CPPUNIT_ASSERT_EQUAL(std::string("?query/"), us.query); +} + +void UriTest::testSetUri12() +{ + UriStruct us; + bool v = parse(us, "http://host?query"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL(std::string("host"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.file); + CPPUNIT_ASSERT_EQUAL(std::string("?query"), us.query); +} + +void UriTest::testSetUri13() +{ + UriStruct us; + bool v = parse(us, "http://host/?query"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL(std::string("host"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.file); + CPPUNIT_ASSERT_EQUAL(std::string("?query"), us.query); +} + +void UriTest::testSetUri14() +{ + UriStruct us; + bool v = parse(us, "http://host:8080/abc?query"); + + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL(std::string("host"), us.host); + CPPUNIT_ASSERT_EQUAL((uint16_t)8080, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("/"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("abc"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string("?query"), us.query); +} + +void UriTest::testSetUri15() +{ + UriStruct us; + // 2 slashes after host name and dir + bool v = parse(us, "http://host//dir1/dir2//file"); + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL(std::string("host"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/dir1/dir2"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("file"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +void UriTest::testSetUri16() +{ + UriStruct us; + // 2 slashes before file + bool v = parse(us, "http://host//file"); + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("http"), us.protocol); + CPPUNIT_ASSERT_EQUAL(std::string("host"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("file"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +void UriTest::testSetUri18() +{ + UriStruct us; + bool v = parse(us, "http://1/"); + + CPPUNIT_ASSERT(v); +} + +void UriTest::testSetUri19() +{ + UriStruct us; + // No host + bool v = parse(us, "http://user@"); + + CPPUNIT_ASSERT(!v); +} + +void UriTest::testSetUri20() +{ + UriStruct us; + bool v; + // Invalid port + v = parse(us, "http://localhost:65536"); + CPPUNIT_ASSERT(!v); + v = parse(us, "http://localhost:65535"); + CPPUNIT_ASSERT(v); + v = parse(us, "http://localhost:-80"); + CPPUNIT_ASSERT(!v); +} + +void UriTest::testSetUri_zeroUsername() +{ + UriStruct us; + CPPUNIT_ASSERT(parse(us, "ftp://@localhost/download/aria2-1.0.0.tar.bz2")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/download"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.username); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.password); + + CPPUNIT_ASSERT(parse(us, "ftp://:@localhost/download/aria2-1.0.0.tar.bz2")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/download"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.username); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.password); + + CPPUNIT_ASSERT(parse(us, + "ftp://:pass@localhost/download/aria2-1.0.0.tar.bz2")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/download"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.username); + CPPUNIT_ASSERT_EQUAL(std::string("pass"), us.password); + +} + +void UriTest::testSetUri_username() +{ + UriStruct us; + CPPUNIT_ASSERT + (parse(us, "ftp://aria2@user@localhost/download/aria2-1.0.0.tar.bz2")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/download"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string("aria2@user"), us.username); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.password); +} + +void UriTest::testSetUri_usernamePassword() +{ + UriStruct us; + CPPUNIT_ASSERT(parse(us, + "ftp://aria2@user%40:aria2@pass%40@localhost/download/" + "aria2-1.0.0.tar.bz2")); + CPPUNIT_ASSERT_EQUAL(std::string("ftp"), us.protocol); + CPPUNIT_ASSERT_EQUAL((uint16_t)21, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("localhost"), us.host); + CPPUNIT_ASSERT_EQUAL(std::string("/download"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string("aria2@user@"), us.username); + CPPUNIT_ASSERT_EQUAL(std::string("aria2@pass@"), us.password); + + // make sure that after new uri is set, username and password are updated. + CPPUNIT_ASSERT(parse(us, "ftp://localhost/download/aria2-1.0.0.tar.bz2")); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.username); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.password); +} + +void UriTest::testSetUri_ipv6() +{ + UriStruct us; + CPPUNIT_ASSERT(!parse(us, "http://[::1")); + CPPUNIT_ASSERT(parse(us, "http://[::1]")); + CPPUNIT_ASSERT_EQUAL(std::string("::1"), us.host); + + CPPUNIT_ASSERT(parse(us, "http://[::1]:8000/dir/file")); + CPPUNIT_ASSERT_EQUAL(std::string("::1"), us.host); + CPPUNIT_ASSERT_EQUAL((uint16_t)8000, us.port); + CPPUNIT_ASSERT_EQUAL(std::string("/dir"), us.dir); + CPPUNIT_ASSERT_EQUAL(std::string("file"), us.file); + CPPUNIT_ASSERT(us.ipv6LiteralAddress); +} + +void UriTest::testInnerLink() +{ + UriStruct us; + bool v = parse(us, "http://aria.rednoah.com/index.html#download"); + CPPUNIT_ASSERT(v); + CPPUNIT_ASSERT_EQUAL(std::string("index.html"), us.file); + CPPUNIT_ASSERT_EQUAL(std::string(""), us.query); +} + +} // namespace uri + +} // namespace aria2