Browse Source

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 năm trước cách đây
mục cha
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", ""));