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
pull/1/head
Tatsuhiro Tsujikawa 2010-02-27 14:24:15 +00:00
parent e8d091af18
commit 18d7eb5b77
7 changed files with 119 additions and 53 deletions

View File

@ -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> 2010-02-27 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Replaced null or control characters in file path with '_'. For Replaced null or control characters in file path with '_'. For

View File

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

View File

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

View File

@ -34,6 +34,7 @@
/* copyright --> */ /* copyright --> */
#include "messageDigest.h" #include "messageDigest.h"
#include "util.h" #include "util.h"
#include "array_fun.h"
namespace aria2 { namespace aria2 {
@ -43,27 +44,55 @@ const std::string MessageDigestContext::SHA256("sha-256");
const std::string MessageDigestContext::MD5("md-5"); 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 #ifdef HAVE_LIBSSL
MessageDigestContext::DigestAlgoMap::value_type("md5", EVP_md5()), DigestAlgoMap::value_type("md5", DigestAlgoEntry(EVP_md5(), STRENGTH_MD5)),
MessageDigestContext::DigestAlgoMap::value_type("sha-1", EVP_sha1()), DigestAlgoMap::value_type
MessageDigestContext::DigestAlgoMap::value_type("sha1", EVP_sha1()), ("sha-1", DigestAlgoEntry(EVP_sha1(), STRENGTH_SHA_1)),
DigestAlgoMap::value_type
("sha1", DigestAlgoEntry(EVP_sha1(), STRENGTH_SHA_1)),
# ifdef HAVE_EVP_SHA256 # ifdef HAVE_EVP_SHA256
MessageDigestContext::DigestAlgoMap::value_type("sha-256", EVP_sha256()), DigestAlgoMap::value_type
MessageDigestContext::DigestAlgoMap::value_type("sha256", EVP_sha256()), ("sha-256", DigestAlgoEntry(EVP_sha256(), STRENGTH_SHA_256)),
DigestAlgoMap::value_type
("sha256", DigestAlgoEntry(EVP_sha256(), STRENGTH_SHA_256)),
# endif // HAVE_EVP_SHA256 # endif // HAVE_EVP_SHA256
#elif HAVE_LIBGCRYPT #elif HAVE_LIBGCRYPT
MessageDigestContext::DigestAlgoMap::value_type("md5", GCRY_MD_MD5), DigestAlgoMap::value_type
MessageDigestContext::DigestAlgoMap::value_type("sha-1", GCRY_MD_SHA1), ("md5", DigestAlgoEntry(GCRY_MD_MD5, STRENGTH_MD5)),
MessageDigestContext::DigestAlgoMap::value_type("sha1", GCRY_MD_SHA1), DigestAlgoMap::value_type
MessageDigestContext::DigestAlgoMap::value_type("sha-256", GCRY_MD_SHA256), ("sha-1", DigestAlgoEntry(GCRY_MD_SHA1, STRENGTH_SHA_1)),
MessageDigestContext::DigestAlgoMap::value_type("sha256", GCRY_MD_SHA256), 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 #endif // HAVE_LIBGCRYPT
}; };
static const DigestAlgoMap algomap
MessageDigestContext::DigestAlgoMap (&digests[0], &digests[arrayLength(digests)]);
MessageDigestContext::digestAlgos(&digests[0], return algomap;
&digests[sizeof(digests)/sizeof(DigestAlgoMap::value_type)]); }
std::string MessageDigestContext::digestFinal() std::string MessageDigestContext::digestFinal()
{ {
@ -75,15 +104,52 @@ std::string MessageDigestContext::digestFinal()
return rawMDString; 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() std::string MessageDigestContext::getSupportedAlgoString()
{ {
const DigestAlgoMap& allAlgos = getDigestAlgos();
std::string algos; std::string algos;
for(DigestAlgoMap::const_iterator itr = digestAlgos.begin(); for(DigestAlgoMap::const_iterator itr = allAlgos.begin();
itr != digestAlgos.end(); ++itr) { itr != allAlgos.end(); ++itr) {
algos += (*itr).first; algos += (*itr).first;
algos += ", "; algos += ", ";
} }
return util::trim(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 } // namespace aria2

View File

@ -62,7 +62,6 @@ public:
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
typedef int DigestAlgo; typedef int DigestAlgo;
#endif // HAVE_LIBGCRYPT #endif // HAVE_LIBGCRYPT
typedef std::map<std::string, MessageDigestContext::DigestAlgo> DigestAlgoMap;
static const std::string SHA1; static const std::string SHA1;
@ -77,8 +76,6 @@ private:
gcry_md_hd_t ctx; gcry_md_hd_t ctx;
#endif // HAVE_LIBGCRYPT #endif // HAVE_LIBGCRYPT
DigestAlgo algo; DigestAlgo algo;
static DigestAlgoMap digestAlgos;
public: public:
MessageDigestContext():algo(getDigestAlgo(MessageDigestContext::SHA1)) MessageDigestContext():algo(getDigestAlgo(MessageDigestContext::SHA1))
{} {}
@ -93,26 +90,9 @@ public:
algo = getDigestAlgo(algostring); algo = getDigestAlgo(algostring);
} }
static bool supports(const std::string& 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 DigestAlgo getDigestAlgo(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 std::string getSupportedAlgoString(); static std::string getSupportedAlgoString();
@ -121,6 +101,11 @@ public:
return digestLength(getDigestAlgo(algostring)); 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(); std::string digestFinal();
#if defined(HAVE_OLD_LIBSSL) #if defined(HAVE_OLD_LIBSSL)

View File

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

View File

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