summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-08-30 15:05:30 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-08-30 15:05:30 +0000
commitce25b54cfe3ba23408da19fcd87539bec879b943 (patch)
treeb60b7edf6f808aee791b72ecdc64131d3d36665d
parent19ae8f9d07ba6a8f1d3b6f501a01f9285b6875e9 (diff)
2009-08-31 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added support for IPv6 literal address in URI. Now aria2 can handle URI such as http://[::1]/ * src/HttpRequest.cc * src/HttpRequest.h * src/Request.cc * src/Request.h * test/HttpRequestTest.cc * test/OptionHandlerTest.cc * test/RequestTest.cc
-rw-r--r--ChangeLog12
-rw-r--r--src/HttpRequest.cc6
-rw-r--r--src/HttpRequest.h7
-rw-r--r--src/Request.cc48
-rw-r--r--src/Request.h14
-rw-r--r--test/HttpRequestTest.cc21
-rw-r--r--test/OptionHandlerTest.cc6
-rw-r--r--test/RequestTest.cc27
8 files changed, 117 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index 4da4f9e0..a13597dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2009-08-31 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
+
+ Added support for IPv6 literal address in URI. Now aria2 can
+ handle URI such as http://[::1]/
+ * src/HttpRequest.cc
+ * src/HttpRequest.h
+ * src/Request.cc
+ * src/Request.h
+ * test/HttpRequestTest.cc
+ * test/OptionHandlerTest.cc
+ * test/RequestTest.cc
+
2009-08-30 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that HTTP request header for XML-RPC request is not
diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc
index 3c4e8f06..63bdc557 100644
--- a/src/HttpRequest.cc
+++ b/src/HttpRequest.cc
@@ -117,7 +117,7 @@ bool HttpRequest::isRangeSatisfied(const RangeHandle& range) const
}
}
-std::string HttpRequest::getHostText(const std::string& host, uint16_t port) const
+static std::string getHostText(const std::string& host, uint16_t port)
{
std::string hosttext = host;
if(!(port == 80 || port == 443)) {
@@ -172,7 +172,7 @@ std::string HttpRequest::createRequest()
}
}
- strappend(requestLine, "Host: ", getHostText(getHost(), getPort()), "\r\n");
+ strappend(requestLine, "Host: ", getHostText(getURIHost(), getPort()), "\r\n");
requestLine += "Pragma: no-cache\r\n";
requestLine += "Cache-Control: no-cache\r\n";
@@ -235,7 +235,7 @@ std::string HttpRequest::createRequest()
std::string HttpRequest::createProxyRequest() const
{
assert(!_proxyRequest.isNull());
- std::string hostport = getHost();
+ std::string hostport = getURIHost();
strappend(hostport, ":", Util::uitos(getPort()));
std::string requestLine = "CONNECT ";
diff --git a/src/HttpRequest.h b/src/HttpRequest.h
index 18a0768b..b32b614b 100644
--- a/src/HttpRequest.h
+++ b/src/HttpRequest.h
@@ -83,8 +83,6 @@ private:
SharedHandle<Request> _proxyRequest;
- std::string getHostText(const std::string& host, uint16_t port) const;
-
std::string getProxyAuthString() const;
public:
HttpRequest();
@@ -149,6 +147,11 @@ public:
return request->getPreviousUrl();
}
+ std::string getURIHost() const
+ {
+ return request->getURIHost();
+ }
+
SharedHandle<Range> getRange() const;
/**
diff --git a/src/Request.cc b/src/Request.cc
index ee9d7c0a..e055811f 100644
--- a/src/Request.cc
+++ b/src/Request.cc
@@ -71,7 +71,8 @@ Request::Request():
_keepAliveHint(false),
_pipeliningHint(false),
_maxPipelinedRequest(1),
- method(METHOD_GET)
+ method(METHOD_GET),
+ _ipv6LiteralAddress(false)
{}
static std::string removeFragment(const std::string url)
@@ -160,6 +161,7 @@ bool Request::parseUrl(const std::string& url) {
_query = A2STR::NIL;
_username = A2STR::NIL;
_password = A2STR::NIL;
+ _ipv6LiteralAddress = false;
// find query part
std::string queryTemp;
std::string::size_type startQueryIndex = tempUrl.find("?");
@@ -193,22 +195,40 @@ bool Request::parseUrl(const std::string& url) {
_password = Util::urldecode(userPass.second);
hostPart.erase(0, atmarkp+1);
}
- std::pair<std::string, std::string> hostAndPort;
- Util::split(hostAndPort, hostPart, ':');
- host = hostAndPort.first;
- if(hostAndPort.second != A2STR::NIL) {
- try {
- unsigned int tempPort = Util::parseUInt(hostAndPort.second);
- if(65535 < tempPort) {
+ {
+ std::string::size_type colonpos;
+ // Detect IPv6 literal address in square brackets
+ if(Util::startsWith(hostPart, "[")) {
+ std::string::size_type rbracketpos = hostPart.find("]");
+ if(rbracketpos == std::string::npos) {
return false;
}
- port = tempPort;
- } catch(RecoverableException& e) {
- return false;
+ _ipv6LiteralAddress = true;
+ colonpos = hostPart.find(":", rbracketpos+1);
+ } else {
+ colonpos = hostPart.find_last_of(":");
+ }
+ if(colonpos == std::string::npos) {
+ colonpos = hostPart.size();
+ // If port is not specified, then we set it to default port of
+ // its protocol..
+ port = defPort;
+ } else {
+ try {
+ unsigned int tempPort = Util::parseUInt(hostPart.substr(colonpos+1));
+ if(65535 < tempPort) {
+ return false;
+ }
+ port = tempPort;
+ } catch(RecoverableException& e) {
+ return false;
+ }
+ }
+ if(_ipv6LiteralAddress) {
+ host = hostPart.substr(1, colonpos-2);
+ } else {
+ host = hostPart.substr(0, colonpos);
}
- } else {
- // If port is not specified, then we set it to default port of its protocol..
- port = defPort;
}
// find directory and file part
std::string::size_type direp = tempUrl.find_last_of("/");
diff --git a/src/Request.h b/src/Request.h
index cab16999..5c88cf62 100644
--- a/src/Request.h
+++ b/src/Request.h
@@ -41,6 +41,7 @@
#include "SharedHandle.h"
#include "PeerStat.h"
+#include "a2functional.h"
namespace aria2 {
@@ -82,6 +83,8 @@ private:
std::string _password;
+ bool _ipv6LiteralAddress;
+
SharedHandle<PeerStat> _peerStat;
bool parseUrl(const std::string& url);
@@ -116,10 +119,21 @@ public:
void setReferer(const std::string& url);
const std::string& getProtocol() const { return protocol; }
const std::string& getHost() const { return host; }
+ // Same as getHost(), but for IPv6 literal addresses, enclose them
+ // with square brackets and return.
+ std::string getURIHost() const
+ {
+ if(isIPv6LiteralAddress()) {
+ return strconcat("[", getHost(), "]");
+ } else {
+ return getHost();
+ }
+ }
uint16_t getPort() const { return port; }
const std::string& getDir() const { return dir; }
const std::string& getFile() const { return file;}
const std::string& getQuery() const { return _query; }
+ bool isIPv6LiteralAddress() const { return _ipv6LiteralAddress; }
void supportsPersistentConnection(bool f)
{
diff --git a/test/HttpRequestTest.cc b/test/HttpRequestTest.cc
index 2df09ccb..de65245c 100644
--- a/test/HttpRequestTest.cc
+++ b/test/HttpRequestTest.cc
@@ -28,6 +28,7 @@ class HttpRequestTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testCreateRequest_with_cookie);
CPPUNIT_TEST(testCreateRequest_query);
CPPUNIT_TEST(testCreateRequest_head);
+ CPPUNIT_TEST(testCreateRequest_ipv6LiteralAddr);
CPPUNIT_TEST(testCreateProxyRequest);
CPPUNIT_TEST(testIsRangeSatisfied);
CPPUNIT_TEST(testUserAgent);
@@ -53,6 +54,7 @@ public:
void testCreateRequest_with_cookie();
void testCreateRequest_query();
void testCreateRequest_head();
+ void testCreateRequest_ipv6LiteralAddr();
void testCreateProxyRequest();
void testIsRangeSatisfied();
void testUserAgent();
@@ -735,4 +737,23 @@ void HttpRequestTest::testEnableAcceptEncoding()
CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest());
}
+void HttpRequestTest::testCreateRequest_ipv6LiteralAddr()
+{
+ SharedHandle<Request> request(new Request());
+ request->setUrl("http://[::1]/path");
+ HttpRequest httpRequest;
+ httpRequest.disableContentEncoding();
+ httpRequest.setRequest(request);
+ httpRequest.setAuthConfigFactory(_authConfigFactory, _option.get());
+
+ CPPUNIT_ASSERT(httpRequest.createRequest().find("Host: [::1]") != std::string::npos);
+
+ SharedHandle<Request> proxy(new Request());
+ proxy->setUrl("http://proxy");
+ httpRequest.setProxyRequest(proxy);
+ std::string proxyRequest = httpRequest.createProxyRequest();
+ CPPUNIT_ASSERT(proxyRequest.find("Host: [::1]:80") != std::string::npos);
+ CPPUNIT_ASSERT(proxyRequest.find("CONNECT [::1]:80 ") != std::string::npos);
+}
+
} // namespace aria2
diff --git a/test/OptionHandlerTest.cc b/test/OptionHandlerTest.cc
index b99c91d3..e033600a 100644
--- a/test/OptionHandlerTest.cc
+++ b/test/OptionHandlerTest.cc
@@ -311,11 +311,7 @@ void OptionHandlerTest::testHttpProxyOptionHandler()
handler.parse(option, "http://proxy:8080");
CPPUNIT_ASSERT_EQUAL(std::string("http://proxy:8080"),
- option.get(PREF_HTTP_PROXY));
-
- handler.parse(option, "ftp://proxy:8080");
- CPPUNIT_ASSERT_EQUAL(std::string("http://ftp://proxy:8080"),
- option.get(PREF_HTTP_PROXY));
+ option.get(PREF_HTTP_PROXY));
try {
handler.parse(option, "http://bar:65536");
diff --git a/test/RequestTest.cc b/test/RequestTest.cc
index cc109372..61ad9d65 100644
--- a/test/RequestTest.cc
+++ b/test/RequestTest.cc
@@ -32,6 +32,7 @@ class RequestTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testSetUrl_usernamePassword);
CPPUNIT_TEST(testSetUrl_zeroUsername);
CPPUNIT_TEST(testSetUrl_supportsPersistentConnection);
+ CPPUNIT_TEST(testSetUrl_ipv6);
CPPUNIT_TEST(testRedirectUrl);
CPPUNIT_TEST(testRedirectUrl2);
CPPUNIT_TEST(testRedirectUrl_supportsPersistentConnection);
@@ -39,6 +40,7 @@ class RequestTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testResetUrl_supportsPersistentConnection);
CPPUNIT_TEST(testInnerLink);
CPPUNIT_TEST(testInnerLinkInReferer);
+ CPPUNIT_TEST(testGetURIHost);
CPPUNIT_TEST_SUITE_END();
public:
@@ -63,6 +65,7 @@ public:
void testSetUrl_usernamePassword();
void testSetUrl_zeroUsername();
void testSetUrl_supportsPersistentConnection();
+ void testSetUrl_ipv6();
void testRedirectUrl();
void testRedirectUrl2();
void testRedirectUrl_supportsPersistentConnection();
@@ -70,6 +73,7 @@ public:
void testResetUrl_supportsPersistentConnection();
void testInnerLink();
void testInnerLinkInReferer();
+ void testGetURIHost();
};
@@ -91,6 +95,7 @@ void RequestTest::testSetUrl1() {
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getQuery());
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getUsername());
CPPUNIT_ASSERT_EQUAL(std::string(""), req.getPassword());
+ CPPUNIT_ASSERT(!req.isIPv6LiteralAddress());
}
void RequestTest::testSetUrl2() {
@@ -483,4 +488,26 @@ void RequestTest::testRedirectUrl_supportsPersistentConnection()
CPPUNIT_ASSERT(req.supportsPersistentConnection());
}
+void RequestTest::testSetUrl_ipv6()
+{
+ Request req;
+ CPPUNIT_ASSERT(!req.setUrl("http://[::1"));
+ CPPUNIT_ASSERT(req.setUrl("http://[::1]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("::1"), req.getHost());
+
+ CPPUNIT_ASSERT(req.setUrl("http://[::1]:8000/dir/file"));
+ CPPUNIT_ASSERT_EQUAL(std::string("::1"), req.getHost());
+ CPPUNIT_ASSERT_EQUAL((uint16_t)8000, req.getPort());
+ CPPUNIT_ASSERT_EQUAL(std::string("/dir"), req.getDir());
+ CPPUNIT_ASSERT_EQUAL(std::string("file"), req.getFile());
+ CPPUNIT_ASSERT(req.isIPv6LiteralAddress());
+}
+
+void RequestTest::testGetURIHost()
+{
+ Request req;
+ CPPUNIT_ASSERT(req.setUrl("http://[::1]"));
+ CPPUNIT_ASSERT_EQUAL(std::string("[::1]"), req.getURIHost());
+}
+
} // namespace aria2