Selaa lähdekoodia

HttpHeader::fill() now stores header name in lowercase.

Find methods in HttpHeader won't lowercase argument, so use lowercase
letters to get HTTP header field.
Tatsuhiro Tsujikawa 14 vuotta sitten
vanhempi
commit
d17ea2837b

+ 71 - 56
src/HttpHeader.cc

@@ -39,56 +39,48 @@
 
 namespace aria2 {
 
-const std::string HttpHeader::LOCATION("Location");
+const std::string HttpHeader::LOCATION("location");
+const std::string HttpHeader::TRANSFER_ENCODING("transfer-encoding");
+const std::string HttpHeader::CONTENT_ENCODING("content-encoding");
+const std::string HttpHeader::CONTENT_DISPOSITION("content-disposition");
+const std::string HttpHeader::SET_COOKIE("set-cookie");
+const std::string HttpHeader::CONTENT_TYPE("content-type");
+const std::string HttpHeader::RETRY_AFTER("retry-after");
+const std::string HttpHeader::CONNECTION("connection");
+const std::string HttpHeader::CONTENT_LENGTH("content-length");
+const std::string HttpHeader::CONTENT_RANGE("content-range");
+const std::string HttpHeader::LAST_MODIFIED("last-modified");
+const std::string HttpHeader::ACCEPT_ENCODING("accept-encoding");
+const std::string HttpHeader::LINK("link");
+const std::string HttpHeader::DIGEST("digest");
+const std::string HttpHeader::PROXY_CONNECTION("proxy-connection");
+const std::string HttpHeader::AUTHORIZATION("authorization");
 
-const std::string HttpHeader::TRANSFER_ENCODING("Transfer-Encoding");
-
-const std::string HttpHeader::CONTENT_ENCODING("Content-Encoding");
-
-const std::string HttpHeader::CONTENT_DISPOSITION("Content-Disposition");
-
-const std::string HttpHeader::SET_COOKIE("Set-Cookie");
-
-const std::string HttpHeader::CONTENT_TYPE("Content-Type");
-
-const std::string HttpHeader::RETRY_AFTER("Retry-After");
-
-const std::string HttpHeader::CONNECTION("Connection");
-
-const std::string HttpHeader::CONTENT_LENGTH("Content-Length");
-
-const std::string HttpHeader::CONTENT_RANGE("Content-Range");
-
-const std::string HttpHeader::LAST_MODIFIED("Last-Modified");
-
-const std::string HttpHeader::ACCEPT_ENCODING("Accept-Encoding");
-
-const std::string HttpHeader::LINK("Link");
-
-const std::string HttpHeader::DIGEST("Digest");
-
-const char HttpHeader::HTTP_1_1[] = "HTTP/1.1";
-const char HttpHeader::CLOSE[] = "close";
-const char HttpHeader::CHUNKED[] = "chunked";
-const char HttpHeader::GZIP[] = "gzip";
-const char HttpHeader::DEFLATE[] = "deflate";
+const std::string HttpHeader::HTTP_1_1 = "HTTP/1.1";
+const std::string HttpHeader::CLOSE = "close";
+const std::string HttpHeader::KEEP_ALIVE = "keep-alive";
+const std::string HttpHeader::CHUNKED = "chunked";
+const std::string HttpHeader::GZIP = "gzip";
+const std::string HttpHeader::DEFLATE = "deflate";
 
 HttpHeader::HttpHeader() {}
 HttpHeader::~HttpHeader() {}
 
-void HttpHeader::put(const std::string& name, const std::string& value) {
-  std::multimap<std::string, std::string>::value_type vt
-    (util::toLower(name), value);
+void HttpHeader::put(const std::string& name, const std::string& value)
+{
+  std::multimap<std::string, std::string>::value_type vt(name, value);
   table_.insert(vt);
 }
 
-bool HttpHeader::defined(const std::string& name) const {
-  return table_.count(util::toLower(name)) >= 1;
+bool HttpHeader::defined(const std::string& name) const
+{
+  return table_.count(name);
 }
 
-const std::string& HttpHeader::getFirst(const std::string& name) const {
+const std::string& HttpHeader::find(const std::string& name) const
+{
   std::multimap<std::string, std::string>::const_iterator itr =
-    table_.find(util::toLower(name));
+    table_.find(name);
   if(itr == table_.end()) {
     return A2STR::NIL;
   } else {
@@ -96,35 +88,32 @@ const std::string& HttpHeader::getFirst(const std::string& name) const {
   }
 }
 
-std::vector<std::string> HttpHeader::get(const std::string& name) const
+std::vector<std::string> HttpHeader::findAll(const std::string& name) const
 {
   std::vector<std::string> v;
-  std::string n(util::toLower(name));
   std::pair<std::multimap<std::string, std::string>::const_iterator,
-    std::multimap<std::string, std::string>::const_iterator> itrpair =
-    table_.equal_range(n);
-  std::multimap<std::string, std::string>::const_iterator first = itrpair.first;
-  while(first != itrpair.second) {
-    v.push_back((*first).second);
-    ++first;
+            std::multimap<std::string, std::string>::const_iterator> itrpair =
+    table_.equal_range(name);
+  while(itrpair.first != itrpair.second) {
+    v.push_back((*itrpair.first).second);
+    ++itrpair.first;
   }
   return v;
 }
 
 std::pair<std::multimap<std::string, std::string>::const_iterator,
           std::multimap<std::string, std::string>::const_iterator>
-HttpHeader::getIterator(const std::string& name) const
+HttpHeader::equalRange(const std::string& name) const
 {
-  std::string n(util::toLower(name));
-  return table_.equal_range(n);
+  return table_.equal_range(name);
 }
 
-unsigned int HttpHeader::getFirstAsUInt(const std::string& name) const {
-  return getFirstAsULLInt(name);
+unsigned int HttpHeader::findAsUInt(const std::string& name) const {
+  return findAsULLInt(name);
 }
 
-uint64_t HttpHeader::getFirstAsULLInt(const std::string& name) const {
-  const std::string& value = getFirst(name);
+uint64_t HttpHeader::findAsULLInt(const std::string& name) const {
+  const std::string& value = find(name);
   if(value.empty()) {
     return 0;
   } else {
@@ -134,9 +123,9 @@ uint64_t HttpHeader::getFirstAsULLInt(const std::string& name) const {
 
 RangeHandle HttpHeader::getRange() const
 {
-  const std::string& rangeStr = getFirst(CONTENT_RANGE);
+  const std::string& rangeStr = find(CONTENT_RANGE);
   if(rangeStr.empty()) {
-    const std::string& clenStr = getFirst(CONTENT_LENGTH);
+    const std::string& clenStr = find(CONTENT_LENGTH);
     if(clenStr.empty()) {
       return SharedHandle<Range>(new Range());
     } else {
@@ -231,6 +220,7 @@ void HttpHeader::fill
         std::pair<std::string::const_iterator,
                   std::string::const_iterator> p = util::stripIter(first, sep);
         name.assign(p.first, p.second);
+        util::lowercase(name);
         p = util::stripIter(sep+1, j);
         value.assign(p.first, p.second);
       }
@@ -250,4 +240,29 @@ void HttpHeader::clearField()
   table_.clear();
 }
 
+int HttpHeader::getStatusCode() const
+{
+  return statusCode_;
+}
+
+void HttpHeader::setStatusCode(int code)
+{
+  statusCode_ = code;
+}
+
+const std::string& HttpHeader::getVersion() const
+{
+  return version_;
+}
+
+const std::string& HttpHeader::getMethod() const
+{
+  return method_;
+}
+
+const std::string& HttpHeader::getRequestPath() const
+{
+  return requestPath_;
+}
+
 } // namespace aria2

+ 21 - 48
src/HttpHeader.h

@@ -68,30 +68,21 @@ public:
 
   void put(const std::string& name, const std::string& value);
   bool defined(const std::string& name) const;
-  const std::string& getFirst(const std::string& name) const;
-  std::vector<std::string> get(const std::string& name) const;
+  const std::string& find(const std::string& name) const;
+  std::vector<std::string> findAll(const std::string& name) const;
   std::pair<std::multimap<std::string, std::string>::const_iterator,
             std::multimap<std::string, std::string>::const_iterator>
-  getIterator(const std::string& name) const;
-  unsigned int getFirstAsUInt(const std::string& name) const;
-  uint64_t getFirstAsULLInt(const std::string& name) const;
+  equalRange(const std::string& name) const;
+  unsigned int findAsUInt(const std::string& name) const;
+  uint64_t findAsULLInt(const std::string& name) const;
 
   SharedHandle<Range> getRange() const;
 
-  int getStatusCode() const
-  {
-    return statusCode_;
-  }
+  int getStatusCode() const;
 
-  void setStatusCode(int code)
-  {
-    statusCode_ = code;
-  }
+  void setStatusCode(int code);
 
-  const std::string& getVersion() const
-  {
-    return version_;
-  }
+  const std::string& getVersion() const;
 
   void setVersion(const std::string& version);
 
@@ -101,10 +92,7 @@ public:
     version_.assign(first, last);
   }
 
-  const std::string& getMethod() const
-  {
-    return method_;
-  }
+  const std::string& getMethod() const;
 
   void setMethod(const std::string& method);
 
@@ -114,10 +102,7 @@ public:
     method_.assign(first, last);
   }
 
-  const std::string& getRequestPath() const
-  {
-    return requestPath_;
-  }
+  const std::string& getRequestPath() const;
 
   void setRequestPath(const std::string& requestPath);
 
@@ -127,6 +112,8 @@ public:
     requestPath_.assign(first, last);
   }
 
+  // Parses header fields in [first, last). Field name is stored in
+  // lowercase.
   void fill
   (std::string::const_iterator first,
    std::string::const_iterator last);
@@ -135,42 +122,28 @@ public:
   void clearField();
 
   static const std::string LOCATION;
-
   static const std::string TRANSFER_ENCODING;
-  
   static const std::string CONTENT_ENCODING;
-
   static const std::string CONTENT_DISPOSITION;
-  
   static const std::string SET_COOKIE;
-  
   static const std::string CONTENT_TYPE;
-  
   static const std::string RETRY_AFTER;
-  
   static const std::string CONNECTION;
-
   static const std::string CONTENT_LENGTH;
-
   static const std::string CONTENT_RANGE;
-
   static const std::string LAST_MODIFIED;
-
   static const std::string ACCEPT_ENCODING;
-
   static const std::string LINK;
-
   static const std::string DIGEST;
-
-  static const char HTTP_1_1[];
-
-  static const char CLOSE[];
-
-  static const char CHUNKED[];
-  
-  static const char GZIP[];
-
-  static const char DEFLATE[];
+  static const std::string AUTHORIZATION;
+  static const std::string PROXY_CONNECTION;
+
+  static const std::string HTTP_1_1;
+  static const std::string CLOSE;
+  static const std::string KEEP_ALIVE;
+  static const std::string CHUNKED;
+  static const std::string GZIP;
+  static const std::string DEFLATE;
 };
 
 typedef SharedHandle<HttpHeader> HttpHeaderHandle;

+ 27 - 18
src/HttpResponse.cc

@@ -57,6 +57,7 @@
 #include "uri.h"
 #include "MetalinkHttpEntry.h"
 #include "base64.h"
+#include "array_fun.h"
 #ifdef ENABLE_MESSAGE_DIGEST
 #include "MessageDigest.h"
 #endif // ENABLE_MESSAGE_DIGEST
@@ -118,7 +119,7 @@ std::string HttpResponse::determinFilename() const
 {
   std::string contentDisposition =
     util::getContentDispositionFilename
-    (httpHeader_->getFirst(HttpHeader::CONTENT_DISPOSITION));
+    (httpHeader_->find(HttpHeader::CONTENT_DISPOSITION));
   if(contentDisposition.empty()) {
     std::string file =
       util::percentDecode(httpRequest_->getFile().begin(),
@@ -141,7 +142,7 @@ void HttpResponse::retrieveCookie()
   Time now;
   std::pair<std::multimap<std::string, std::string>::const_iterator,
             std::multimap<std::string, std::string>::const_iterator> r =
-    httpHeader_->getIterator(HttpHeader::SET_COOKIE);
+    httpHeader_->equalRange(HttpHeader::SET_COOKIE);
   for(; r.first != r.second; ++r.first) {
     httpRequest_->getCookieStorage()->parseAndStore
       ((*r.first).second, httpRequest_->getHost(), httpRequest_->getDir(),
@@ -177,7 +178,7 @@ void HttpResponse::processRedirect()
 
 const std::string& HttpResponse::getRedirectURI() const
 {
-  return httpHeader_->getFirst(HttpHeader::LOCATION);
+  return httpHeader_->find(HttpHeader::LOCATION);
 }
 
 bool HttpResponse::isTransferEncodingSpecified() const
@@ -188,7 +189,7 @@ bool HttpResponse::isTransferEncodingSpecified() const
 const std::string& HttpResponse::getTransferEncoding() const
 {
   // TODO See TODO in getTransferEncodingStreamFilter()
-  return httpHeader_->getFirst(HttpHeader::TRANSFER_ENCODING);
+  return httpHeader_->find(HttpHeader::TRANSFER_ENCODING);
 }
 
 SharedHandle<StreamFilter> HttpResponse::getTransferEncodingStreamFilter() const
@@ -211,7 +212,7 @@ bool HttpResponse::isContentEncodingSpecified() const
 
 const std::string& HttpResponse::getContentEncoding() const
 {
-  return httpHeader_->getFirst(HttpHeader::CONTENT_ENCODING);
+  return httpHeader_->find(HttpHeader::CONTENT_ENCODING);
 }
 
 SharedHandle<StreamFilter> HttpResponse::getContentEncodingStreamFilter() const
@@ -249,7 +250,7 @@ std::string HttpResponse::getContentType() const
   if(!httpHeader_) {
     return A2STR::NIL;
   } else {
-    const std::string& ctype = httpHeader_->getFirst(HttpHeader::CONTENT_TYPE);
+    const std::string& ctype = httpHeader_->find(HttpHeader::CONTENT_TYPE);
     std::string::const_iterator i = std::find(ctype.begin(), ctype.end(), ';');
     Scip p = util::stripIter(ctype.begin(), i);
     return std::string(p.first, p.second);
@@ -278,27 +279,35 @@ bool HttpResponse::hasRetryAfter() const
 
 time_t HttpResponse::getRetryAfter() const
 {
-  return httpHeader_->getFirstAsUInt(HttpHeader::RETRY_AFTER);
+  return httpHeader_->findAsUInt(HttpHeader::RETRY_AFTER);
 }
 
 Time HttpResponse::getLastModifiedTime() const
 {
-  return Time::parseHTTPDate(httpHeader_->getFirst(HttpHeader::LAST_MODIFIED));
+  return Time::parseHTTPDate(httpHeader_->find(HttpHeader::LAST_MODIFIED));
 }
 
 bool HttpResponse::supportsPersistentConnection() const
 {
-  std::string connection =
-    util::toLower(httpHeader_->getFirst(HttpHeader::CONNECTION));
-  std::string version = httpHeader_->getVersion();
-
+  const std::string& connection = httpHeader_->find(HttpHeader::CONNECTION);
+  const std::string& version = httpHeader_->getVersion();
+  const std::string& proxyConn =
+    httpHeader_->find(HttpHeader::PROXY_CONNECTION);
   return
-    connection.find(HttpHeader::CLOSE) == std::string::npos &&
+    util::strifind(connection.begin(),
+                   connection.end(),
+                   HttpHeader::CLOSE.begin(),
+                   HttpHeader::CLOSE.end()) == connection.end() &&
     (version == HttpHeader::HTTP_1_1 ||
-     connection.find("keep-alive") != std::string::npos) &&
+     util::strifind(connection.begin(),
+                    connection.end(),
+                    HttpHeader::KEEP_ALIVE.begin(),
+                    HttpHeader::KEEP_ALIVE.end()) != connection.end()) &&
     (!httpRequest_->isProxyRequestSet() ||
-     util::toLower(httpHeader_->getFirst("Proxy-Connection")).find("keep-alive")
-     != std::string::npos);
+     util::strifind(proxyConn.begin(),
+                    proxyConn.end(),
+                    HttpHeader::KEEP_ALIVE.begin(),
+                    HttpHeader::KEEP_ALIVE.end()) != proxyConn.end());
 }
 
 namespace {
@@ -368,7 +377,7 @@ void HttpResponse::getMetalinKHttpEntries
 {
   std::pair<std::multimap<std::string, std::string>::const_iterator,
             std::multimap<std::string, std::string>::const_iterator> p =
-    httpHeader_->getIterator(HttpHeader::LINK);
+    httpHeader_->equalRange(HttpHeader::LINK);
   for(; p.first != p.second; ++p.first) {
     MetalinkHttpEntry e;
     if(parseMetalinkHttpLink(e, (*p.first).second)) {
@@ -403,7 +412,7 @@ void HttpResponse::getDigest(std::vector<Checksum>& result) const
   using std::swap;
   std::pair<std::multimap<std::string, std::string>::const_iterator,
             std::multimap<std::string, std::string>::const_iterator> p =
-    httpHeader_->getIterator(HttpHeader::DIGEST);
+    httpHeader_->equalRange(HttpHeader::DIGEST);
   for(; p.first != p.second; ++p.first) {
     const std::string& s = (*p.first).second;
     std::string::const_iterator itr = s.begin();

+ 7 - 6
src/HttpServer.cc

@@ -90,11 +90,11 @@ SharedHandle<HttpHeader> HttpServer::receiveRequest()
     lastBody_.clear();
     lastBody_.str("");
     lastContentLength_ =
-      lastRequestHeader_->getFirstAsUInt(HttpHeader::CONTENT_LENGTH);
+      lastRequestHeader_->findAsUInt(HttpHeader::CONTENT_LENGTH);
     headerProcessor_->clear();
 
     std::string connection =
-      util::toLower(lastRequestHeader_->getFirst(HttpHeader::CONNECTION));
+      util::toLower(lastRequestHeader_->find(HttpHeader::CONNECTION));
     acceptsPersistentConnection_ =
       connection.find(HttpHeader::CLOSE) == std::string::npos &&
       (lastRequestHeader_->getVersion() == HttpHeader::HTTP_1_1 ||
@@ -102,14 +102,14 @@ SharedHandle<HttpHeader> HttpServer::receiveRequest()
 
     std::vector<Scip> acceptEncodings;
     const std::string& acceptEnc =
-      lastRequestHeader_->getFirst(HttpHeader::ACCEPT_ENCODING);
+      lastRequestHeader_->find(HttpHeader::ACCEPT_ENCODING);
     util::splitIter(acceptEnc.begin(), acceptEnc.end(),
                     std::back_inserter(acceptEncodings), ',', true);
-    const char A2_GZIP[] = "gzip";
     acceptsGZip_ = false;
     for(std::vector<Scip>::const_iterator i = acceptEncodings.begin(),
           eoi = acceptEncodings.end(); i != eoi; ++i) {
-      if(util::streq((*i).first, (*i).second, A2_GZIP, vend(A2_GZIP)-1)) {
+      if(util::strieq((*i).first, (*i).second,
+                      HttpHeader::GZIP.begin(), HttpHeader::GZIP.end())) {
         acceptsGZip_ = true;
         break;
       }
@@ -214,7 +214,8 @@ bool HttpServer::authenticate()
     return true;
   }
 
-  const std::string& authHeader = lastRequestHeader_->getFirst("Authorization");
+  const std::string& authHeader =
+    lastRequestHeader_->find(HttpHeader::AUTHORIZATION);
   if(authHeader.empty()) {
     return false;
   }

+ 4 - 2
src/LpdMessageReceiver.cc

@@ -94,8 +94,10 @@ SharedHandle<LpdMessage> LpdMessageReceiver::receiveMessage()
       return msg;
     }
     SharedHandle<HttpHeader> header = proc.getHttpRequestHeader();
-    const std::string& infoHashString = header->getFirst("Infohash");
-    uint16_t port = header->getFirstAsUInt("Port");
+    static const std::string A2_INFOHASH = "infohash";
+    static const std::string A2_PORT = "port";
+    const std::string& infoHashString = header->find(A2_INFOHASH);
+    uint16_t port = header->findAsUInt(A2_PORT);
     A2_LOG_INFO(fmt("LPD message received infohash=%s, port=%u from %s",
                     infoHashString.c_str(),
                     port,

+ 10 - 0
src/util.h

@@ -728,6 +728,16 @@ struct CaseCmp {
   }
 };
 
+template<typename InputIterator1, typename InputIterator2>
+InputIterator1 strifind
+(InputIterator1 first1,
+ InputIterator1 last1,
+ InputIterator2 first2,
+ InputIterator2 last2)
+{
+  return std::search(first1, last1, first2, last2, CaseCmp());
+}
+
 template<typename InputIterator1, typename InputIterator2>
 bool strieq
 (InputIterator1 first1,

+ 6 - 5
test/HttpHeaderProcessorTest.cc

@@ -114,12 +114,13 @@ void HttpHeaderProcessorTest::testGetHttpResponseHeader()
   CPPUNIT_ASSERT_EQUAL(200, header->getStatusCode());
   CPPUNIT_ASSERT_EQUAL(std::string("HTTP/1.1"), header->getVersion());
   CPPUNIT_ASSERT_EQUAL(std::string("Mon, 25 Jun 2007 16:04:59 GMT"),
-                       header->getFirst("Date"));
+                       header->find("date"));
   CPPUNIT_ASSERT_EQUAL(std::string("Apache/2.2.3 (Debian)"),
-                       header->getFirst("Server"));
-  CPPUNIT_ASSERT_EQUAL((uint64_t)9187ULL, header->getFirstAsULLInt("Content-Length"));
+                       header->find("server"));
+  CPPUNIT_ASSERT_EQUAL((uint64_t)9187ULL,
+                       header->findAsULLInt("content-length"));
   CPPUNIT_ASSERT_EQUAL(std::string("text/html; charset=UTF-8"),
-                       header->getFirst("Content-Type"));
+                       header->find("content-type"));
   CPPUNIT_ASSERT(!header->defined("entity"));
 }
 
@@ -223,7 +224,7 @@ void HttpHeaderProcessorTest::testGetHttpRequestHeader()
   CPPUNIT_ASSERT_EQUAL(std::string("GET"), httpHeader->getMethod());
   CPPUNIT_ASSERT_EQUAL(std::string("/index.html"),httpHeader->getRequestPath());
   CPPUNIT_ASSERT_EQUAL(std::string("HTTP/1.1"), httpHeader->getVersion());
-  CPPUNIT_ASSERT_EQUAL(std::string("close"),httpHeader->getFirst("Connection"));
+  CPPUNIT_ASSERT_EQUAL(std::string("close"),httpHeader->find("connection"));
   CPPUNIT_ASSERT(!httpHeader->defined("entity"));
 }
 

+ 21 - 21
test/HttpHeaderTest.cc

@@ -11,14 +11,14 @@ class HttpHeaderTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(HttpHeaderTest);
   CPPUNIT_TEST(testGetRange);
-  CPPUNIT_TEST(testGet);
+  CPPUNIT_TEST(testFindAll);
   CPPUNIT_TEST(testClearField);
   CPPUNIT_TEST(testFill);
   CPPUNIT_TEST_SUITE_END();
   
 public:
   void testGetRange();
-  void testGet();
+  void testFindAll();
   void testClearField();
   void testFill();
 };
@@ -30,7 +30,7 @@ void HttpHeaderTest::testGetRange()
 {
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range",
+    httpHeader.put("content-range",
                    "9223372036854775800-9223372036854775801/9223372036854775807");
     
     SharedHandle<Range> range = httpHeader.getRange();
@@ -41,7 +41,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range",
+    httpHeader.put("content-range",
                    "9223372036854775800-9223372036854775801/9223372036854775807");
      
     SharedHandle<Range> range = httpHeader.getRange();
@@ -52,7 +52,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range", "bytes */1024");
+    httpHeader.put("content-range", "bytes */1024");
 
     SharedHandle<Range> range = httpHeader.getRange();
 
@@ -62,7 +62,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range", "bytes 0-9/*");
+    httpHeader.put("content-range", "bytes 0-9/*");
 
     SharedHandle<Range> range = httpHeader.getRange();
 
@@ -72,7 +72,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range", "bytes */*");
+    httpHeader.put("content-range", "bytes */*");
 
     SharedHandle<Range> range = httpHeader.getRange();
 
@@ -82,7 +82,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range", "bytes 0");
+    httpHeader.put("content-range", "bytes 0");
 
     SharedHandle<Range> range = httpHeader.getRange();
 
@@ -92,7 +92,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range", "bytes 0/");
+    httpHeader.put("content-range", "bytes 0/");
 
     SharedHandle<Range> range = httpHeader.getRange();
 
@@ -102,7 +102,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range", "bytes 0-/3");
+    httpHeader.put("content-range", "bytes 0-/3");
     try {
       httpHeader.getRange();
       CPPUNIT_FAIL("Exception must be thrown");
@@ -112,7 +112,7 @@ void HttpHeaderTest::testGetRange()
   }
   {
     HttpHeader httpHeader;
-    httpHeader.put("Content-Range", "bytes -0/3");
+    httpHeader.put("content-range", "bytes -0/3");
     try {
       httpHeader.getRange();
       CPPUNIT_FAIL("Exception must be thrown");
@@ -122,14 +122,14 @@ void HttpHeaderTest::testGetRange()
   }
 }
 
-void HttpHeaderTest::testGet()
+void HttpHeaderTest::testFindAll()
 {
   HttpHeader h;
   h.put("A", "100");
-  h.put("a", "101");
+  h.put("A", "101");
   h.put("B", "200");
   
-  std::vector<std::string> r(h.get("A"));
+  std::vector<std::string> r(h.findAll("A"));
   CPPUNIT_ASSERT_EQUAL((size_t)2, r.size());
   CPPUNIT_ASSERT_EQUAL(std::string("100"), r[0]);
   CPPUNIT_ASSERT_EQUAL(std::string("101"), r[1]);
@@ -142,11 +142,11 @@ void HttpHeaderTest::testClearField()
   h.setVersion(HttpHeader::HTTP_1_1);
   h.put("Foo", "Bar");
   
-  CPPUNIT_ASSERT_EQUAL(std::string("Bar"), h.getFirst("Foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string("Bar"), h.find("Foo"));
 
   h.clearField();
 
-  CPPUNIT_ASSERT_EQUAL(std::string(""), h.getFirst("Foo"));
+  CPPUNIT_ASSERT_EQUAL(std::string(""), h.find("Foo"));
   CPPUNIT_ASSERT_EQUAL(200, h.getStatusCode());
   CPPUNIT_ASSERT_EQUAL(std::string(HttpHeader::HTTP_1_1), h.getVersion());
 }
@@ -164,15 +164,15 @@ void HttpHeaderTest::testFill()
   HttpHeader h;
   h.fill(s.begin(), s.end());
   CPPUNIT_ASSERT_EQUAL(std::string("aria2.sourceforge.net"),
-                       h.getFirst("Host"));
+                       h.find("host"));
   CPPUNIT_ASSERT_EQUAL(std::string("close"),
-                       h.getFirst("Connection"));
+                       h.find("connection"));
   CPPUNIT_ASSERT_EQUAL(std::string("text1 text2 text3"),
-                       h.getFirst("Multi-Line"));
+                       h.find("multi-line"));
   CPPUNIT_ASSERT_EQUAL(std::string("foo"),
-                       h.get("Duplicate")[0]);
+                       h.findAll("duplicate")[0]);
   CPPUNIT_ASSERT_EQUAL(std::string("bar"),
-                       h.get("Duplicate")[1]);
+                       h.findAll("duplicate")[1]);
 }
 
 } // namespace aria2

+ 53 - 53
test/HttpResponseTest.cc

@@ -109,7 +109,7 @@ void HttpResponseTest::testGetContentLength_contentLength()
   HttpResponse httpResponse;
 
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  httpHeader->put("Content-Length", "4294967296");
+  httpHeader->put("content-length", "4294967296");
 
   httpResponse.setHttpHeader(httpHeader);
 
@@ -121,13 +121,13 @@ void HttpResponseTest::testGetEntityLength()
   HttpResponse httpResponse;
 
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  httpHeader->put("Content-Length", "4294967296");
+  httpHeader->put("content-length", "4294967296");
 
   httpResponse.setHttpHeader(httpHeader);
 
   CPPUNIT_ASSERT_EQUAL((uint64_t)4294967296ULL, httpResponse.getEntityLength());
 
-  httpHeader->put("Content-Range", "bytes 1-4294967296/4294967297");
+  httpHeader->put("content-range", "bytes 1-4294967296/4294967297");
 
   CPPUNIT_ASSERT_EQUAL((uint64_t)4294967297ULL, httpResponse.getEntityLength());
 
@@ -165,7 +165,7 @@ void HttpResponseTest::testDeterminFilename_with_ContentDisposition_zero_length
 {
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  httpHeader->put("Content-Disposition", "attachment; filename=\"\"");
+  httpHeader->put("content-disposition", "attachment; filename=\"\"");
   SharedHandle<HttpRequest> httpRequest(new HttpRequest());
   SharedHandle<Request> request(new Request());
   request->setUri("http://localhost/archives/aria2-1.0.0.tar.bz2");
@@ -182,7 +182,7 @@ void HttpResponseTest::testDeterminFilename_with_ContentDisposition()
 {
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  httpHeader->put("Content-Disposition",
+  httpHeader->put("content-disposition",
                   "attachment; filename=\"aria2-current.tar.bz2\"");
   SharedHandle<HttpRequest> httpRequest(new HttpRequest());
   SharedHandle<Request> request(new Request());
@@ -211,7 +211,7 @@ void HttpResponseTest::testGetRedirectURI_with_Location()
 {
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
-  httpHeader->put("Location", "http://localhost/download/aria2-1.0.0.tar.bz2");
+  httpHeader->put("location", "http://localhost/download/aria2-1.0.0.tar.bz2");
   httpResponse.setHttpHeader(httpHeader);
 
   CPPUNIT_ASSERT_EQUAL
@@ -224,7 +224,7 @@ void HttpResponseTest::testIsRedirect()
   HttpResponse httpResponse;
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
   httpHeader->setStatusCode(200);
-  httpHeader->put("Location", "http://localhost/download/aria2-1.0.0.tar.bz2");
+  httpHeader->put("location", "http://localhost/download/aria2-1.0.0.tar.bz2");
 
   httpResponse.setHttpHeader(httpHeader);
 
@@ -244,7 +244,7 @@ void HttpResponseTest::testIsTransferEncodingSpecified()
 
   CPPUNIT_ASSERT(!httpResponse.isTransferEncodingSpecified());  
 
-  httpHeader->put("Transfer-Encoding", "chunked");
+  httpHeader->put("transfer-encoding", "chunked");
 
   CPPUNIT_ASSERT(httpResponse.isTransferEncodingSpecified());
 }
@@ -258,7 +258,7 @@ void HttpResponseTest::testGetTransferEncoding()
 
   CPPUNIT_ASSERT_EQUAL(std::string(""), httpResponse.getTransferEncoding());  
 
-  httpHeader->put("Transfer-Encoding", "chunked");
+  httpHeader->put("transfer-encoding", "chunked");
 
   CPPUNIT_ASSERT_EQUAL(std::string("chunked"),
                        httpResponse.getTransferEncoding());
@@ -273,7 +273,7 @@ void HttpResponseTest::testGetTransferEncodingStreamFilter()
 
   CPPUNIT_ASSERT(!httpResponse.getTransferEncodingStreamFilter());
 
-  httpHeader->put("Transfer-Encoding", "chunked");
+  httpHeader->put("transfer-encoding", "chunked");
 
   CPPUNIT_ASSERT(httpResponse.getTransferEncodingStreamFilter());
 }
@@ -287,7 +287,7 @@ void HttpResponseTest::testIsContentEncodingSpecified()
 
   CPPUNIT_ASSERT(!httpResponse.isContentEncodingSpecified());
 
-  httpHeader->put("Content-Encoding", "gzip");
+  httpHeader->put("content-encoding", "gzip");
 
   CPPUNIT_ASSERT(httpResponse.isContentEncodingSpecified());
 }
@@ -301,7 +301,7 @@ void HttpResponseTest::testGetContentEncoding()
 
   CPPUNIT_ASSERT_EQUAL(A2STR::NIL, httpResponse.getContentEncoding());
 
-  httpHeader->put("Content-Encoding", "gzip");
+  httpHeader->put("content-encoding", "gzip");
 
   CPPUNIT_ASSERT_EQUAL(std::string("gzip"), httpResponse.getContentEncoding());
 }
@@ -316,7 +316,7 @@ void HttpResponseTest::testGetContentEncodingStreamFilter()
   CPPUNIT_ASSERT(!httpResponse.getContentEncodingStreamFilter());
 
 #ifdef HAVE_ZLIB
-  httpHeader->put("Content-Encoding", "gzip");
+  httpHeader->put("content-encoding", "gzip");
   {
     SharedHandle<StreamFilter> filter =
       httpResponse.getContentEncodingStreamFilter();
@@ -326,7 +326,7 @@ void HttpResponseTest::testGetContentEncodingStreamFilter()
   }
   httpHeader.reset(new HttpHeader());
   httpResponse.setHttpHeader(httpHeader);
-  httpHeader->put("Content-Encoding", "deflate");
+  httpHeader->put("content-encoding", "deflate");
   {
     SharedHandle<StreamFilter> filter =
       httpResponse.getContentEncodingStreamFilter();
@@ -337,7 +337,7 @@ void HttpResponseTest::testGetContentEncodingStreamFilter()
 #endif // HAVE_ZLIB
   httpHeader.reset(new HttpHeader());
   httpResponse.setHttpHeader(httpHeader);
-  httpHeader->put("Content-Encoding", "bzip2");
+  httpHeader->put("content-encoding", "bzip2");
   {
     SharedHandle<StreamFilter> filter =
       httpResponse.getContentEncodingStreamFilter();
@@ -359,7 +359,7 @@ void HttpResponseTest::testValidateResponse()
   } catch(Exception& e) {
   }
 
-  httpHeader->put("Location", "http://localhost/archives/aria2-1.0.0.tar.bz2");
+  httpHeader->put("location", "http://localhost/archives/aria2-1.0.0.tar.bz2");
   try {
     httpResponse.validateResponse();
   } catch(Exception& e) {
@@ -384,7 +384,7 @@ void HttpResponseTest::testValidateResponse_good_range()
   httpRequest->setRequest(request);
   httpResponse.setHttpRequest(httpRequest);
   httpHeader->setStatusCode(206);
-  httpHeader->put("Content-Range", "bytes 1048576-10485760/10485760");
+  httpHeader->put("content-range", "bytes 1048576-10485760/10485760");
   
   try {
     httpResponse.validateResponse();
@@ -411,7 +411,7 @@ void HttpResponseTest::testValidateResponse_bad_range()
   httpRequest->setRequest(request);
   httpResponse.setHttpRequest(httpRequest);
   httpHeader->setStatusCode(206);
-  httpHeader->put("Content-Range", "bytes 0-10485760/10485761");
+  httpHeader->put("content-range", "bytes 0-10485760/10485761");
 
   try {
     httpResponse.validateResponse();
@@ -437,8 +437,8 @@ void HttpResponseTest::testValidateResponse_chunked()
   httpRequest->setRequest(request);
   httpResponse.setHttpRequest(httpRequest);
   httpHeader->setStatusCode(206);
-  httpHeader->put("Content-Range", "bytes 0-10485760/10485761");
-  httpHeader->put("Transfer-Encoding", "chunked");
+  httpHeader->put("content-range", "bytes 0-10485760/10485761");
+  httpHeader->put("transfer-encoding", "chunked");
 
   // if transfer-encoding is specified, then range validation is skipped.
   try {
@@ -471,7 +471,7 @@ void HttpResponseTest::testHasRetryAfter()
   SharedHandle<HttpHeader> httpHeader(new HttpHeader());
   httpResponse.setHttpHeader(httpHeader);
 
-  httpHeader->put("Retry-After", "60");
+  httpHeader->put("retry-after", "60");
 
   CPPUNIT_ASSERT(httpResponse.hasRetryAfter());
   CPPUNIT_ASSERT_EQUAL((time_t)60, httpResponse.getRetryAfter());
@@ -489,13 +489,13 @@ void HttpResponseTest::testProcessRedirect()
   httpRequest->setRequest(request);
   httpResponse.setHttpRequest(httpRequest);
   
-  httpHeader->put("Location", "http://mirror/aria2-1.0.0.tar.bz2");
+  httpHeader->put("location", "http://mirror/aria2-1.0.0.tar.bz2");
   httpResponse.processRedirect();
 
   httpHeader->clearField();
 
   // Test for percent-encode
-  httpHeader->put("Location", "http://example.org/white space#aria2");
+  httpHeader->put("location", "http://example.org/white space#aria2");
   httpResponse.processRedirect();
   CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/white%20space"),
                        request->getCurrentUri());
@@ -503,7 +503,7 @@ void HttpResponseTest::testProcessRedirect()
   httpHeader->clearField();
 
   // Give unsupported scheme
-  httpHeader->put("Location", "unsupported://mirror/aria2-1.0.0.tar.bz2");
+  httpHeader->put("location", "unsupported://mirror/aria2-1.0.0.tar.bz2");
   try {
     httpResponse.processRedirect();
     CPPUNIT_FAIL("DlRetryEx exception must be thrown.");
@@ -528,11 +528,11 @@ void HttpResponseTest::testRetrieveCookie()
   httpRequest->setCookieStorage(st);
   httpResponse.setHttpRequest(httpRequest);
 
-  httpHeader->put("Set-Cookie", "k1=v1; expires=Sun, 10-Jun-2007 11:00:00 GMT;"
+  httpHeader->put("set-cookie", "k1=v1; expires=Sun, 10-Jun-2007 11:00:00 GMT;"
                   "path=/; domain=.aria2.org;");
-  httpHeader->put("Set-Cookie", "k2=v2; expires=Sun, 01-Jan-38 00:00:00 GMT;"
+  httpHeader->put("set-cookie", "k2=v2; expires=Sun, 01-Jan-38 00:00:00 GMT;"
                   "path=/; domain=.aria2.org;");
-  httpHeader->put("Set-Cookie", "k3=v3;");
+  httpHeader->put("set-cookie", "k3=v3;");
 
   httpResponse.retrieveCookie();
 
@@ -554,19 +554,19 @@ void HttpResponseTest::testSupportsPersistentConnection()
 
   httpHeader->setVersion("HTTP/1.1");
   CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
-  httpHeader->put("Connection", "close");
+  httpHeader->put("connection", "close");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Connection", "keep-alive");
+  httpHeader->put("connection", "keep-alive");
   CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
 
   httpHeader->setVersion("HTTP/1.0");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
-  httpHeader->put("Connection", "close");
+  httpHeader->put("connection", "close");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Connection", "keep-alive");
+  httpHeader->put("connection", "keep-alive");
   CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
 
@@ -576,35 +576,35 @@ void HttpResponseTest::testSupportsPersistentConnection()
   
   httpHeader->setVersion("HTTP/1.1");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
-  httpHeader->put("Connection", "close");
+  httpHeader->put("connection", "close");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Connection", "keep-alive");
+  httpHeader->put("connection", "keep-alive");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Proxy-Connection", "keep-alive");
+  httpHeader->put("proxy-connection", "keep-alive");
   CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
-  httpHeader->put("Connection", "close");
+  httpHeader->put("connection", "close");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Proxy-Connection", "close");
+  httpHeader->put("proxy-connection", "close");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
 
   httpHeader->setVersion("HTTP/1.0");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
-  httpHeader->put("Connection", "close");
+  httpHeader->put("connection", "close");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Connection", "keep-alive");
+  httpHeader->put("connection", "keep-alive");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
-  httpHeader->put("Proxy-Connection", "keep-alive");
+  httpHeader->put("proxy-connection", "keep-alive");
   CPPUNIT_ASSERT(httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Proxy-Connection", "keep-alive");
+  httpHeader->put("proxy-connection", "keep-alive");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
-  httpHeader->put("Proxy-Connection", "close");
+  httpHeader->put("proxy-connection", "close");
   CPPUNIT_ASSERT(!httpResponse.supportsPersistentConnection());
   httpHeader->clearField();
 }
@@ -616,13 +616,13 @@ void HttpResponseTest::testGetMetalinKHttpEntries()
   httpResponse.setHttpHeader(httpHeader);
   SharedHandle<Option> option(new Option());
 
-  httpHeader->put("Link", "<http://uri1/>; rel=duplicate; pri=1; pref; geo=JP");
-  httpHeader->put("Link", "<http://uri2/>; rel=duplicate");
-  httpHeader->put("Link", "<http://uri3/>;;;;;;;;rel=duplicate;;;;;pri=2;;;;;");
-  httpHeader->put("Link", "<http://uri4/>;rel=duplicate;=pri=1;pref");
-  httpHeader->put("Link", "<http://describedby>; rel=describedby");
-  httpHeader->put("Link", "<http://norel/>");
-  httpHeader->put("Link", "<baduri>; rel=duplicate; pri=-1;");
+  httpHeader->put("link", "<http://uri1/>; rel=duplicate; pri=1; pref; geo=JP");
+  httpHeader->put("link", "<http://uri2/>; rel=duplicate");
+  httpHeader->put("link", "<http://uri3/>;;;;;;;;rel=duplicate;;;;;pri=2;;;;;");
+  httpHeader->put("link", "<http://uri4/>;rel=duplicate;=pri=1;pref");
+  httpHeader->put("link", "<http://describedby>; rel=describedby");
+  httpHeader->put("link", "<http://norel/>");
+  httpHeader->put("link", "<baduri>; rel=duplicate; pri=-1;");
   std::vector<MetalinkHttpEntry> result;
   httpResponse.getMetalinKHttpEntries(result, option);
   CPPUNIT_ASSERT_EQUAL((size_t)5, result.size());
@@ -667,11 +667,11 @@ void HttpResponseTest::testGetDigest()
   SharedHandle<Option> option(new Option());
   // Python binascii.hexlify(base64.b64decode(B64ED_HASH)) is handy to
   // retrieve ascii hex hash string.
-  httpHeader->put("Digest", "SHA-1=82AD8itGL/oYQ5BTPFANiYnp9oE=");
-  httpHeader->put("Digest", "NOT_SUPPORTED");
-  httpHeader->put("Digest", "SHA-224=rQdowoLHQJTMVZ3rF7vmYOIzUXlu7F+FcMbPnA==");
-  httpHeader->put("Digest", "SHA-224=6Ik6LNZ1iPy6cbmlKO4NHfvxzaiurmHilMyhGA==");
-  httpHeader->put("Digest",
+  httpHeader->put("digest", "SHA-1=82AD8itGL/oYQ5BTPFANiYnp9oE=");
+  httpHeader->put("digest", "NOT_SUPPORTED");
+  httpHeader->put("digest", "SHA-224=rQdowoLHQJTMVZ3rF7vmYOIzUXlu7F+FcMbPnA==");
+  httpHeader->put("digest", "SHA-224=6Ik6LNZ1iPy6cbmlKO4NHfvxzaiurmHilMyhGA==");
+  httpHeader->put("digest",
                   "SHA-256=+D8nGudz3G/kpkVKQeDrI3xD57v0UeQmzGCZOk03nsU=,"
                   "MD5=LJDK2+9ClF8Nz/K5WZd/+A==");
   std::vector<Checksum> result;

+ 18 - 0
test/UtilTest.cc

@@ -32,6 +32,7 @@ class UtilTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testSplitIterM);
   CPPUNIT_TEST(testStreq);
   CPPUNIT_TEST(testStrieq);
+  CPPUNIT_TEST(testStrifind);
   CPPUNIT_TEST(testEndsWith);
   CPPUNIT_TEST(testIendsWith);
   CPPUNIT_TEST(testReplace);
@@ -101,6 +102,7 @@ public:
   void testSplitIterM();
   void testStreq();
   void testStrieq();
+  void testStrifind();
   void testEndsWith();
   void testIendsWith();
   void testReplace();
@@ -734,6 +736,22 @@ void UtilTest::testStrieq()
   CPPUNIT_ASSERT(util::strieq(s1.begin(), s1.end(), s2.begin(), s2.end()));
 }
 
+void UtilTest::testStrifind()
+{
+  std::string s1, s2;
+  s1 = "yamagakani mukashi wo toheba hARU no tuki";
+  s2 = "HaRu";
+  CPPUNIT_ASSERT(util::strifind(s1.begin(), s1.end(), s2.begin(), s2.end())
+                 != s1.end());
+  s2 = "aki";
+  CPPUNIT_ASSERT(util::strifind(s1.begin(), s1.end(), s2.begin(), s2.end())
+                 == s1.end());
+  s1 = "h";
+  s2 = "HH";
+  CPPUNIT_ASSERT(util::strifind(s1.begin(), s1.end(), s2.begin(), s2.end())
+                 == s1.end());
+}
+
 void UtilTest::testReplace() {
   CPPUNIT_ASSERT_EQUAL(std::string("abc\n"), util::replace("abc\r\n", "\r", ""));
   CPPUNIT_ASSERT_EQUAL(std::string("abc"), util::replace("abc\r\n", "\r\n", ""));