Quellcode durchsuchen

2010-02-27 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Added MessageDigest::isStronger(). Now aria2 selects stronger hash
	algorithm in Metalink properly
	* src/MetalinkParserController.cc
	* src/MetalinkParserController.h
	* src/messageDigest.cc
	* src/messageDigest.h
	* test/MetalinkProcessorTest.cc
	* test/metalink4.xml
Tatsuhiro Tsujikawa vor 15 Jahren
Ursprung
Commit
18d7eb5b77

+ 11 - 0
ChangeLog

@@ -1,3 +1,14 @@
+2010-02-27  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Added MessageDigest::isStronger(). Now aria2 selects stronger hash
+	algorithm in Metalink properly
+	* src/MetalinkParserController.cc
+	* src/MetalinkParserController.h
+	* src/messageDigest.cc
+	* src/messageDigest.h
+	* test/MetalinkProcessorTest.cc
+	* test/metalink4.xml
+
 2010-02-27  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Replaced null or control characters in file path with '_'.  For

+ 10 - 10
src/MetalinkParserController.cc

@@ -54,8 +54,6 @@
 
 namespace aria2 {
 
-const std::string MetalinkParserController::SHA1("sha1");// Metalink3Spec
-
 MetalinkParserController::MetalinkParserController():
   _metalinker(new Metalinker())
 {}
@@ -293,10 +291,8 @@ void MetalinkParserController::commitChecksumTransaction()
     return;
   }
   if(_tEntry->checksum.isNull() ||
-     // Metalink3Spec
-     (_tEntry->checksum->getAlgo() != MetalinkParserController::SHA1 &&
-      // Metalink4Spec
-      _tEntry->checksum->getAlgo() != MessageDigestContext::SHA1)) {
+     MessageDigestContext::isStronger(_tChecksum->getAlgo(),
+                                      _tEntry->checksum->getAlgo())) {
     _tEntry->checksum = _tChecksum;
   }
   _tChecksum.reset();
@@ -366,7 +362,8 @@ void MetalinkParserController::commitChunkChecksumTransactionV4()
     return;
   }
   if(_tEntry->chunkChecksum.isNull() ||
-     _tEntry->chunkChecksum->getAlgo() != MessageDigestContext::SHA1) {
+     MessageDigestContext::isStronger(_tChunkChecksumV4->getAlgo(),
+                                      _tEntry->chunkChecksum->getAlgo())) {
     std::deque<std::string> checksums(_tempChunkChecksumsV4.begin(),
 				      _tempChunkChecksumsV4.end());
     _tChunkChecksumV4->setChecksums(checksums);
@@ -469,11 +466,14 @@ void MetalinkParserController::commitChunkChecksumTransaction()
     return;
   }
   if(_tEntry->chunkChecksum.isNull() ||
-     _tEntry->chunkChecksum->getAlgo() != MetalinkParserController::SHA1) {
-    std::sort(_tempChunkChecksums.begin(), _tempChunkChecksums.end(), Ascend1st<std::pair<size_t, std::string> >());
+     MessageDigestContext::isStronger(_tChunkChecksum->getAlgo(),
+                                      _tEntry->chunkChecksum->getAlgo())) {
+    std::sort(_tempChunkChecksums.begin(), _tempChunkChecksums.end(),
+              Ascend1st<std::pair<size_t, std::string> >());
     std::deque<std::string> checksums;
     std::transform(_tempChunkChecksums.begin(), _tempChunkChecksums.end(),
-                   std::back_inserter(checksums), select2nd<std::pair<size_t, std::string> >());
+                   std::back_inserter(checksums),
+                   select2nd<std::pair<size_t, std::string> >());
     _tChunkChecksum->setChecksums(checksums);
     _tEntry->chunkChecksum = _tChunkChecksum;
   }

+ 0 - 2
src/MetalinkParserController.h

@@ -81,8 +81,6 @@ private:
 #endif // ENABLE_MESSAGE_DIGEST
 
   SharedHandle<Signature> _tSignature;
-
-  static const std::string SHA1;
 public:
   MetalinkParserController();
 

+ 84 - 18
src/messageDigest.cc

@@ -34,6 +34,7 @@
 /* copyright --> */
 #include "messageDigest.h"
 #include "util.h"
+#include "array_fun.h"
 
 namespace aria2 {
 
@@ -43,27 +44,55 @@ const std::string MessageDigestContext::SHA256("sha-256");
 
 const std::string MessageDigestContext::MD5("md-5");
 
-static MessageDigestContext::DigestAlgoMap::value_type digests[] = {
+namespace {
+struct DigestAlgoEntry {
+  MessageDigestContext::DigestAlgo algo;
+  int strength;
+  DigestAlgoEntry(const MessageDigestContext::DigestAlgo& algo, int strength):
+    algo(algo), strength(strength) {}
+};
+}
+
+typedef std::map<std::string, DigestAlgoEntry>
+DigestAlgoMap;
+
+static const DigestAlgoMap& getDigestAlgos()
+{
+  enum AlgoStrength {
+    STRENGTH_MD5 = 0,
+    STRENGTH_SHA_1 = 1,
+    STRENGTH_SHA_256 = 2
+  };
+  static const DigestAlgoMap::value_type digests[] = {
 #ifdef HAVE_LIBSSL
-  MessageDigestContext::DigestAlgoMap::value_type("md5", EVP_md5()),
-  MessageDigestContext::DigestAlgoMap::value_type("sha-1", EVP_sha1()),
-  MessageDigestContext::DigestAlgoMap::value_type("sha1", EVP_sha1()),
+    DigestAlgoMap::value_type("md5", DigestAlgoEntry(EVP_md5(), STRENGTH_MD5)),
+    DigestAlgoMap::value_type
+    ("sha-1", DigestAlgoEntry(EVP_sha1(), STRENGTH_SHA_1)),
+    DigestAlgoMap::value_type
+    ("sha1", DigestAlgoEntry(EVP_sha1(), STRENGTH_SHA_1)),
 # ifdef HAVE_EVP_SHA256
-  MessageDigestContext::DigestAlgoMap::value_type("sha-256", EVP_sha256()),
-  MessageDigestContext::DigestAlgoMap::value_type("sha256", EVP_sha256()),
+    DigestAlgoMap::value_type
+    ("sha-256", DigestAlgoEntry(EVP_sha256(), STRENGTH_SHA_256)),
+    DigestAlgoMap::value_type
+    ("sha256", DigestAlgoEntry(EVP_sha256(), STRENGTH_SHA_256)),
 # endif // HAVE_EVP_SHA256
 #elif HAVE_LIBGCRYPT
-  MessageDigestContext::DigestAlgoMap::value_type("md5", GCRY_MD_MD5),
-  MessageDigestContext::DigestAlgoMap::value_type("sha-1", GCRY_MD_SHA1),
-  MessageDigestContext::DigestAlgoMap::value_type("sha1", GCRY_MD_SHA1),
-  MessageDigestContext::DigestAlgoMap::value_type("sha-256", GCRY_MD_SHA256),
-  MessageDigestContext::DigestAlgoMap::value_type("sha256", GCRY_MD_SHA256),
+    DigestAlgoMap::value_type
+    ("md5", DigestAlgoEntry(GCRY_MD_MD5, STRENGTH_MD5)),
+    DigestAlgoMap::value_type
+    ("sha-1", DigestAlgoEntry(GCRY_MD_SHA1, STRENGTH_SHA_1)),
+    DigestAlgoMap::value_type
+    ("sha1", DigestAlgoEntry(GCRY_MD_SHA1, STRENGTH_SHA_1)),
+    DigestAlgoMap::value_type
+    ("sha-256", DigestAlgoEntry(GCRY_MD_SHA256, STRENGTH_SHA_256)),
+    DigestAlgoMap::value_type
+    ("sha256", DigestAlgoEntry(GCRY_MD_SHA256, STRENGTH_SHA_256)),
 #endif // HAVE_LIBGCRYPT
-};
-
-MessageDigestContext::DigestAlgoMap
-MessageDigestContext::digestAlgos(&digests[0],
-                                  &digests[sizeof(digests)/sizeof(DigestAlgoMap::value_type)]);
+  };
+  static const DigestAlgoMap algomap
+    (&digests[0], &digests[arrayLength(digests)]);  
+  return algomap;
+}
 
 std::string MessageDigestContext::digestFinal()
 {
@@ -75,15 +104,52 @@ std::string MessageDigestContext::digestFinal()
   return rawMDString;
 }
 
+bool MessageDigestContext::supports(const std::string& algostring)
+{
+  const DigestAlgoMap& allAlgos = getDigestAlgos();
+  DigestAlgoMap::const_iterator itr = allAlgos.find(algostring);
+  if(itr == allAlgos.end()) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+MessageDigestContext::DigestAlgo
+MessageDigestContext::getDigestAlgo(const std::string& algostring)
+{
+  const DigestAlgoMap& allAlgos = getDigestAlgos();
+  DigestAlgoMap::const_iterator itr = allAlgos.find(algostring);
+  if(itr == allAlgos.end()) {
+    throw DL_ABORT_EX
+      (StringFormat("Digest algorithm %s is not supported.",
+                    algostring.c_str()).str());
+  }
+  return (*itr).second.algo;
+}
+
 std::string MessageDigestContext::getSupportedAlgoString()
 {
+  const DigestAlgoMap& allAlgos = getDigestAlgos();
   std::string algos;
-  for(DigestAlgoMap::const_iterator itr = digestAlgos.begin();
-      itr != digestAlgos.end(); ++itr) {
+  for(DigestAlgoMap::const_iterator itr = allAlgos.begin();
+      itr != allAlgos.end(); ++itr) {
     algos += (*itr).first;
     algos += ", ";
   }
   return util::trim(algos, ", ");
 }
 
+bool MessageDigestContext::isStronger
+(const std::string& lhs, const std::string& rhs)
+{
+  const DigestAlgoMap& allAlgos = getDigestAlgos();
+  DigestAlgoMap::const_iterator lhsitr = allAlgos.find(lhs);
+  DigestAlgoMap::const_iterator rhsitr = allAlgos.find(rhs);
+  if(lhsitr == allAlgos.end() || rhsitr == allAlgos.end()) {
+    return false;
+  }
+  return (*lhsitr).second.strength > (*rhsitr).second.strength;
+}
+
 } // namespace aria2

+ 7 - 22
src/messageDigest.h

@@ -62,7 +62,6 @@ public:
 #ifdef HAVE_LIBGCRYPT
   typedef int DigestAlgo;
 #endif // HAVE_LIBGCRYPT
-  typedef std::map<std::string, MessageDigestContext::DigestAlgo> DigestAlgoMap;
 
   static const std::string SHA1;
 
@@ -77,8 +76,6 @@ private:
   gcry_md_hd_t ctx;
 #endif // HAVE_LIBGCRYPT  
   DigestAlgo algo;
-
-  static DigestAlgoMap digestAlgos;
 public:
   MessageDigestContext():algo(getDigestAlgo(MessageDigestContext::SHA1))
   {}
@@ -93,26 +90,9 @@ public:
     algo = getDigestAlgo(algostring);
   }
 
-  static bool supports(const std::string& algostring)
-  {
-    DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring);
-    if(itr == digestAlgos.end()) {
-      return false;
-    } else {
-      return true;
-    }
-  }
+  static bool supports(const std::string& algostring);
 
-  static DigestAlgo getDigestAlgo(const std::string& algostring)
-  {
-    DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring);
-    if(itr == digestAlgos.end()) {
-      throw DL_ABORT_EX
-        (StringFormat("Digest algorithm %s is not supported.",
-                      algostring.c_str()).str());
-    }
-    return (*itr).second;
-  }
+  static DigestAlgo getDigestAlgo(const std::string& algostring);
 
   static std::string getSupportedAlgoString();
 
@@ -121,6 +101,11 @@ public:
     return digestLength(getDigestAlgo(algostring));
   }
 
+  // Returns true if hash algorithm specified by lhs is stronger than
+  // the one specified by rhs. If either lhs or rhs is not supported
+  // or both are not supported, returns false.
+  static bool isStronger(const std::string& lhs, const std::string& rhs);
+
   std::string digestFinal();
 
 #if defined(HAVE_OLD_LIBSSL)

+ 1 - 1
test/MetalinkProcessorTest.cc

@@ -96,7 +96,7 @@ void MetalinkProcessorTest::testParseFileV4()
   CPPUNIT_ASSERT(!e->checksum.isNull());
   CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), e->checksum->getAlgo());
   CPPUNIT_ASSERT(!e->chunkChecksum.isNull());
-  CPPUNIT_ASSERT_EQUAL(std::string("sha-1"), e->chunkChecksum->getAlgo());
+  CPPUNIT_ASSERT_EQUAL(std::string("sha-256"), e->chunkChecksum->getAlgo());
   CPPUNIT_ASSERT_EQUAL((size_t)262144, e->chunkChecksum->getChecksumLength());
   CPPUNIT_ASSERT_EQUAL((size_t)3, e->chunkChecksum->countChecksum());
   CPPUNIT_ASSERT_EQUAL(std::string("metalinkhash1"),

+ 6 - 0
test/metalink4.xml

@@ -7,12 +7,18 @@
     <version>1.0</version>
     <language>en</language>
     <description>A description of the example file for download.</description>
+    <hash type="md5">80bc95fd391772fa61c91ed68567f0980bb45fd9</hash>
     <hash type="sha-1">80bc95fd391772fa61c91ed68567f0980bb45fd9</hash>
     <pieces length="262144" type="sha-1">
       <hash>metalinkhash1</hash>
       <hash>metalinkhash2</hash>
       <hash>metalinkhash3</hash>
     </pieces>
+    <pieces length="262144" type="sha-256">
+      <hash>metalinkhash1</hash>
+      <hash>metalinkhash2</hash>
+      <hash>metalinkhash3</hash>
+    </pieces>
     <url location="de" priority="1">ftp://ftp.example.com/example.ext</url>
     <url location="fr" priority="1">http://example.com/example.ext</url>
     <metaurl mediatype="torrent" priority="2">http://example.com/example.ext.torrent</metaurl>