From bf9d99f291c9514cb4fe6bac4484aa575b713f18 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 10 Jan 2016 16:10:57 +0900 Subject: [PATCH] Send Want-Digest as per RFC 3230 --- src/HttpRequest.cc | 22 +++++++++++++++++- src/HttpRequest.h | 5 +++++ test/HttpRequestTest.cc | 49 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index 5cd1248a..b8bc630e 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -52,6 +52,7 @@ #include "array_fun.h" #include "Request.h" #include "DownloadHandlerConstants.h" +#include "MessageDigest.h" namespace aria2 { @@ -66,7 +67,8 @@ HttpRequest::HttpRequest() contentEncodingEnabled_(true), acceptMetalink_(false), noCache_(true), - acceptGzip_(false) + acceptGzip_(false), + noWantDigest_(false) { } @@ -249,6 +251,24 @@ std::string HttpRequest::createRequest() builtinHds.push_back( std::make_pair("If-Modified-Since:", ifModSinceHeader_)); } + if (!noWantDigest_) { + // Send Want-Digest header field with only limited hash algorithms: + // SHA-512, SHA-256, and SHA-1. + std::string wantDigest; + if (MessageDigest::supports("sha-512")) { + wantDigest += "SHA-512;q=1, "; + } + if (MessageDigest::supports("sha-256")) { + wantDigest += "SHA-256;q=1, "; + } + if (MessageDigest::supports("sha-1")) { + wantDigest += "SHA;q=0.1, "; + } + if (!wantDigest.empty()) { + wantDigest.erase(wantDigest.size() - 2); + builtinHds.emplace_back("Want-Digest:", wantDigest); + } + } for (std::vector>::const_iterator i = builtinHds.begin(), eoi = builtinHds.end(); diff --git a/src/HttpRequest.h b/src/HttpRequest.h index 2232671a..63260709 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -98,6 +98,9 @@ private: bool acceptGzip_; + // Don't send Want-Digest header field + bool noWantDigest_; + std::pair getProxyAuthString() const; public: @@ -228,6 +231,8 @@ public: // request is considered to be conditional if the client sent // "If-Modified-Since" or "If-None-Match" request-header field. bool conditionalRequest() const; + + void setNoWantDigest(bool b) { noWantDigest_ = b; } }; } // namespace aria2 diff --git a/test/HttpRequestTest.cc b/test/HttpRequestTest.cc index 31ca0687..65cd2f20 100644 --- a/test/HttpRequestTest.cc +++ b/test/HttpRequestTest.cc @@ -16,6 +16,7 @@ #include "util.h" #include "AuthConfig.h" #include "TestUtil.h" +#include "MessageDigest.h" namespace aria2 { @@ -31,6 +32,7 @@ class HttpRequestTest : public CppUnit::TestFixture { CPPUNIT_TEST(testCreateRequest_head); CPPUNIT_TEST(testCreateRequest_ipv6LiteralAddr); CPPUNIT_TEST(testCreateRequest_endOffsetOverride); + CPPUNIT_TEST(testCreateRequest_wantDigest); CPPUNIT_TEST(testCreateProxyRequest); CPPUNIT_TEST(testIsRangeSatisfied); CPPUNIT_TEST(testUserAgent); @@ -61,6 +63,7 @@ public: void testCreateRequest_head(); void testCreateRequest_ipv6LiteralAddr(); void testCreateRequest_endOffsetOverride(); + void testCreateRequest_wantDigest(); void testCreateProxyRequest(); void testIsRangeSatisfied(); void testUserAgent(); @@ -142,6 +145,7 @@ void HttpRequestTest::testCreateRequest() httpRequest.setFileEntry(fileEntry); httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); + httpRequest.setNoWantDigest(true); // remove "Connection: close" and add end byte range request->setPipeliningHint(true); @@ -339,6 +343,7 @@ void HttpRequestTest::testCreateRequest_ftp() httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); httpRequest.setProxyRequest(proxyRequest); + httpRequest.setNoWantDigest(true); std::string expectedText = "GET ftp://aria2user@localhost:8080/archives/aria2-1.0.0.tar.bz2" @@ -415,6 +420,7 @@ void HttpRequestTest::testCreateRequest_with_cookie() httpRequest.setCookieStorage(&st); httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); + httpRequest.setNoWantDigest(true); std::string expectedText = "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n" "User-Agent: aria2\r\n" @@ -511,6 +517,7 @@ void HttpRequestTest::testCreateRequest_query() httpRequest.setRequest(request); httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); + httpRequest.setNoWantDigest(true); std::string expectedText = "GET /wiki?id=9ad5109a-b8a5-4edf-9373-56a1c34ae138 HTTP/1.1\r\n" @@ -552,6 +559,7 @@ void HttpRequestTest::testCreateRequest_endOffsetOverride() httpRequest.setRequest(request); httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); + httpRequest.setNoWantDigest(true); auto p = std::make_shared(0, 1_m); auto segment = std::make_shared(1_m, p); httpRequest.setSegment(segment); @@ -586,6 +594,43 @@ void HttpRequestTest::testCreateRequest_endOffsetOverride() CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest()); } +void HttpRequestTest::testCreateRequest_wantDigest() +{ + auto request = std::make_shared(); + request->setUri("http://localhost/"); + HttpRequest httpRequest; + httpRequest.setRequest(request); + httpRequest.setAuthConfigFactory(authConfigFactory_.get()); + httpRequest.setOption(option_.get()); + + std::string wantDigest; + if (MessageDigest::supports("sha-512")) { + wantDigest += "SHA-512;q=1, "; + } + if (MessageDigest::supports("sha-256")) { + wantDigest += "SHA-256;q=1, "; + } + if (MessageDigest::supports("sha-1")) { + wantDigest += "SHA;q=0.1, "; + } + if (!wantDigest.empty()) { + wantDigest.erase(wantDigest.size() - 2); + } + + std::string expectedText = "GET / HTTP/1.1\r\n" + "User-Agent: aria2\r\n" + "Accept: */*\r\n" + "Host: localhost\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache\r\n" + "Connection: close\r\n" + "Want-Digest: " + + wantDigest + "\r\n" + "\r\n"; + + CPPUNIT_ASSERT_EQUAL(expectedText, httpRequest.createRequest()); +} + void HttpRequestTest::testCreateProxyRequest() { auto request = std::make_shared(); @@ -726,6 +771,7 @@ void HttpRequestTest::testUserAgent() httpRequest.setUserAgent("aria2 (Linux)"); httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); + httpRequest.setNoWantDigest(true); std::string expectedText = "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n" "User-Agent: aria2 (Linux)\r\n" @@ -764,6 +810,7 @@ void HttpRequestTest::testAddHeader() httpRequest.setOption(option_.get()); httpRequest.addHeader("X-ARIA2: v0.13\nX-ARIA2-DISTRIBUTE: enabled\n"); httpRequest.addHeader("Accept: text/html"); + httpRequest.setNoWantDigest(true); std::string expectedText = "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n" "User-Agent: aria2\r\n" "Host: localhost\r\n" @@ -789,6 +836,7 @@ void HttpRequestTest::testAcceptMetalink() httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); httpRequest.setAcceptMetalink(true); + httpRequest.setNoWantDigest(true); std::string expectedText = "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n" @@ -812,6 +860,7 @@ void HttpRequestTest::testEnableAcceptEncoding() httpRequest.setRequest(request); httpRequest.setAuthConfigFactory(authConfigFactory_.get()); httpRequest.setOption(option_.get()); + httpRequest.setNoWantDigest(true); std::string acceptEncodings; #ifdef HAVE_ZLIB