diff options
author | David Kalnischkies <kalnischkies@gmail.com> | 2013-08-19 00:00:23 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2014-05-09 13:06:27 +0200 |
commit | b3501edb7091ca3aa6c2d6d96dc667b8161dd2b9 (patch) | |
tree | 078d7f11b418e900e21f009275e74b51918c5961 /apt-pkg | |
parent | 1262d35895c930f3fa49d7b4182cdd7a4a841f74 (diff) |
use HashStringList in the acquire system
It is not very extensible to have the supported Hashes hardcoded
everywhere and especially if it is part of virtual method names.
It is also possible that a method does not support the 'best' hash
(yet), so we might end up not being able to verify a file even though we
have a common subset of supported hashes. And those are just two of the
cases in which it is handy to have a more dynamic selection.
The downside is that this is a MAJOR API break, but the HashStringList
has a string constructor for compatibility, so with a bit of luck the
few frontends playing with the acquire system directly are okay.
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire-item.cc | 202 | ||||
-rw-r--r-- | apt-pkg/acquire-item.h | 146 | ||||
-rw-r--r-- | apt-pkg/acquire-method.cc | 39 | ||||
-rw-r--r-- | apt-pkg/acquire-method.h | 9 | ||||
-rw-r--r-- | apt-pkg/acquire-worker.cc | 37 | ||||
-rw-r--r-- | apt-pkg/contrib/hashes.cc | 97 | ||||
-rw-r--r-- | apt-pkg/contrib/hashes.h | 84 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 2 | ||||
-rw-r--r-- | apt-pkg/deb/debrecords.cc | 41 | ||||
-rw-r--r-- | apt-pkg/deb/debrecords.h | 8 | ||||
-rw-r--r-- | apt-pkg/indexcopy.cc | 8 | ||||
-rw-r--r-- | apt-pkg/indexrecords.cc | 2 | ||||
-rw-r--r-- | apt-pkg/indexrecords.h | 12 | ||||
-rw-r--r-- | apt-pkg/pkgrecords.h | 26 |
14 files changed, 399 insertions, 314 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 913764f64..1156d6f33 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -50,6 +50,19 @@ using namespace std; +static void printHashSumComparision(std::string const &URI, HashStringList const &Expected, HashStringList const &Actual) /*{{{*/ +{ + if (_config->FindB("Debug::Acquire::HashSumMismatch", false) == false) + return; + std::cerr << std::endl << URI << ":" << std::endl << " Expected Hash: " << std::endl; + for (HashStringList::const_iterator hs = Expected.begin(); hs != Expected.end(); ++hs) + std::cerr << "\t- " << hs->toStr() << std::endl; + std::cerr << " Actual Hash: " << std::endl; + for (HashStringList::const_iterator hs = Actual.begin(); hs != Actual.end(); ++hs) + std::cerr << "\t- " << hs->toStr() << std::endl; +} + /*}}}*/ + // Acquire::Item::Item - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -118,7 +131,7 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size) // Acquire::Item::Done - Item downloaded OK /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgAcquire::Item::Done(string Message,unsigned long long Size,string /*Hash*/, +void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringList const &/*Hash*/, pkgAcquire::MethodConfig * /*Cnf*/) { // We just downloaded something.. @@ -229,8 +242,8 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode) possibly query additional files */ pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI, string const &URIDesc, string const &ShortDesc, - HashString const &ExpectedHash) - : Item(Owner), ExpectedHash(ExpectedHash) + HashStringList const &ExpectedHashes) + : Item(Owner), ExpectedHashes(ExpectedHashes) { /* XXX: Beware: Currently this class does nothing (of value) anymore ! */ Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false); @@ -252,7 +265,7 @@ pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI, // AcqSubIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -string pkgAcqSubIndex::Custom600Headers() +string pkgAcqSubIndex::Custom600Headers() const { string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(Desc.URI); @@ -275,7 +288,7 @@ void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)/* // No good Index is provided } /*}}}*/ -void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/ +void pkgAcqSubIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ pkgAcquire::MethodConfig *Cnf) { if(Debug) @@ -297,7 +310,7 @@ void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash, return; } - Item::Done(Message,Size,Md5Hash,Cnf); + Item::Done(Message, Size, Hashes, Cnf); string FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(Desc.URI); @@ -343,12 +356,11 @@ bool pkgAcqSubIndex::ParseIndex(string const &IndexFile) /*{{{*/ * the original packages file */ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, - IndexTarget const *Target, - HashString ExpectedHash, - indexRecords *MetaIndexParser) - : Item(Owner), ExpectedHash(ExpectedHash), Target(Target), + struct IndexTarget const * const Target, + HashStringList const &ExpectedHashes, + indexRecords *MetaIndexParser) + : Item(Owner), ExpectedHashes(ExpectedHashes), Target(Target), MetaIndexParser(MetaIndexParser) - { Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); @@ -393,7 +405,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -string pkgAcqDiffIndex::Custom600Headers() +string pkgAcqDiffIndex::Custom600Headers() const { string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI) + string(".IndexDiff"); @@ -447,7 +459,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ // list cleanup needs to know that this file as well as the already // present index is ours, so we create an empty diff to save it for us new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedHash, ServerSha1, available_patches); + ExpectedHashes, ServerSha1, available_patches); return true; } else @@ -533,12 +545,12 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ if (pdiff_merge == false) new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedHash, ServerSha1, available_patches); + ExpectedHashes, ServerSha1, available_patches); else { std::vector<pkgAcqIndexMergeDiffs*> *diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size()); for(size_t i = 0; i < available_patches.size(); ++i) - (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, RealURI, Description, Desc.ShortDesc, ExpectedHash, + (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, RealURI, Description, Desc.ShortDesc, ExpectedHashes, available_patches[i], diffs); } @@ -563,20 +575,20 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)/ std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl << "Falling back to normal index file acquire" << std::endl; - new pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser); + new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser); Complete = false; Status = StatDone; Dequeue(); } /*}}}*/ -void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/ +void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ pkgAcquire::MethodConfig *Cnf) { if(Debug) std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl; - Item::Done(Message,Size,Md5Hash,Cnf); + Item::Done(Message, Size, Hashes, Cnf); string FinalFile; FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI); @@ -607,10 +619,10 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,string Md5Hash */ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, string URI,string URIDesc,string ShortDesc, - HashString ExpectedHash, + HashStringList const &ExpectedHashes, string ServerSha1, vector<DiffInfo> diffs) - : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash), + : Item(Owner), RealURI(URI), ExpectedHashes(ExpectedHashes), available_patches(diffs), ServerSha1(ServerSha1) { @@ -642,7 +654,7 @@ void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/) std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl << "Falling back to normal index file acquire" << std::endl; new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, - ExpectedHash); + ExpectedHashes); Finish(); } /*}}}*/ @@ -656,7 +668,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone) DestFile = _config->FindDir("Dir::State::lists"); DestFile += URItoFileName(RealURI); - if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile)) + if(ExpectedHashes.usable() && !ExpectedHashes.VerifyFile(DestFile)) { RenameOnError(HashSumMismatch); Dequeue(); @@ -734,13 +746,13 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ return true; } /*}}}*/ -void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/ +void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringList const &Hashes, /*{{{*/ pkgAcquire::MethodConfig *Cnf) { if(Debug) std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; - Item::Done(Message,Size,Md5Hash,Cnf); + Item::Done(Message, Size, Hashes, Cnf); string FinalFile; FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI); @@ -783,7 +795,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has // see if there is more to download if(available_patches.empty() == false) { new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedHash, ServerSha1, available_patches); + ExpectedHashes, ServerSha1, available_patches); return Finish(); } else return Finish(true); @@ -793,10 +805,10 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner, string const &URI, string const &URIDesc, - string const &ShortDesc, HashString const &ExpectedHash, + string const &ShortDesc, HashStringList const &ExpectedHashes, DiffInfo const &patch, std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches) - : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash), + : Item(Owner), RealURI(URI), ExpectedHashes(ExpectedHashes), patch(patch),allPatches(allPatches), State(StateFetchDiff) { @@ -839,16 +851,16 @@ void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * /*C State = StateErrorDiff; std::clog << "Falling back to normal index file acquire" << std::endl; new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, - ExpectedHash); + ExpectedHashes); } /*}}}*/ -void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,string Md5Hash, /*{{{*/ +void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ pkgAcquire::MethodConfig *Cnf) { if(Debug) std::clog << "pkgAcqIndexMergeDiffs::Done(): " << Desc.URI << std::endl; - Item::Done(Message,Size,Md5Hash,Cnf); + Item::Done(Message,Size,Hashes,Cnf); string const FinalFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); @@ -884,7 +896,7 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,string M else if (State == StateApplyDiff) { // see if we really got the expected file - if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile)) + if(ExpectedHashes.usable() && !ExpectedHashes.VerifyFile(DestFile)) { RenameOnError(HashSumMismatch); return; @@ -921,8 +933,8 @@ void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,string M instantiated to fetch the revision file */ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, string URI,string URIDesc,string ShortDesc, - HashString ExpectedHash, string comprExt) - : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash), Target(0), + HashStringList const &ExpectedHashes, string comprExt) + : Item(Owner), RealURI(URI), ExpectedHashes(ExpectedHashes), Target(0), MetaIndexParser(0) { if(comprExt.empty() == true) @@ -940,14 +952,14 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, Init(URI, URIDesc, ShortDesc); } -pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target, - HashString const &ExpectedHash, indexRecords *MetaIndexParser) - : Item(Owner), RealURI(Target->URI), ExpectedHash(ExpectedHash) +pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, struct IndexTarget const * const Target, + HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser) + : Item(Owner), RealURI(Target->URI), ExpectedHashes(ExpectedHashes) { // autoselect the compression method std::vector<std::string> types = APT::Configuration::getCompressionTypes(); CompressionExtension = ""; - if (ExpectedHash.empty() == false) + if (ExpectedHashes.usable()) { for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t) if (*t == "uncompressed" || MetaIndexParser->Exists(string(Target->MetaKey).append(".").append(*t)) == true) @@ -1016,7 +1028,7 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &S // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -string pkgAcqIndex::Custom600Headers() +string pkgAcqIndex::Custom600Headers() const { string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); @@ -1062,22 +1074,17 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/ to the uncompressed version of the file. If this is so the file is copied into the partial directory. In all other cases the file is decompressed with a gzip uri. */ -void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, +void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, pkgAcquire::MethodConfig *Cfg) { - Item::Done(Message,Size,Hash,Cfg); + Item::Done(Message,Size,Hashes,Cfg); if (Decompression == true) { - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - { - std::cerr << std::endl << RealURI << ": Computed Hash: " << Hash; - std::cerr << " Expected Hash: " << ExpectedHash.toStr() << std::endl; - } - - if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash) + if (ExpectedHashes.usable() && ExpectedHashes != Hashes) { RenameOnError(HashSumMismatch); + printHashSumComparision(RealURI, ExpectedHashes, Hashes); return; } @@ -1199,12 +1206,12 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, /* The Translation file is added to the queue */ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, string URI,string URIDesc,string ShortDesc) - : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "") + : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashStringList(), "") { } -pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const *Target, - HashString const &ExpectedHash, indexRecords *MetaIndexParser) - : pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser) +pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, struct IndexTarget const * const Target, + HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser) + : pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser) { // load the filesize indexRecords::checkSum *Record = MetaIndexParser->Lookup(string(Target->MetaKey)); @@ -1214,7 +1221,7 @@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const *Target, /*}}}*/ // AcqIndexTrans::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- -string pkgAcqIndexTrans::Custom600Headers() +string pkgAcqIndexTrans::Custom600Headers() const { string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); @@ -1311,7 +1318,7 @@ pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -string pkgAcqMetaSig::Custom600Headers() +string pkgAcqMetaSig::Custom600Headers() const { struct stat Buf; if (stat(LastGoodSig.c_str(),&Buf) != 0) @@ -1320,10 +1327,10 @@ string pkgAcqMetaSig::Custom600Headers() return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); } -void pkgAcqMetaSig::Done(string Message,unsigned long long Size,string MD5, +void pkgAcqMetaSig::Done(string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cfg) { - Item::Done(Message,Size,MD5,Cfg); + Item::Done(Message, Size, Hashes, Cfg); string FileName = LookupTag(Message,"Filename"); if (FileName.empty() == true) @@ -1426,7 +1433,7 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, /*{{{*/ // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -string pkgAcqMetaIndex::Custom600Headers() +string pkgAcqMetaIndex::Custom600Headers() const { string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); @@ -1438,10 +1445,10 @@ string pkgAcqMetaIndex::Custom600Headers() return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); } /*}}}*/ -void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,string Hash, /*{{{*/ +void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ pkgAcquire::MethodConfig *Cfg) { - Item::Done(Message,Size,Hash,Cfg); + Item::Done(Message,Size,Hashes,Cfg); // MetaIndexes are done in two passes: one to download the // metaindex with an appropriate method, and a second to verify it @@ -1616,8 +1623,8 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ Target != IndexTargets->end(); ++Target) { - HashString ExpectedIndexHash; - indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey); + HashStringList ExpectedIndexHashes; + const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey); bool compressedAvailable = false; if (Record == NULL) { @@ -1640,14 +1647,16 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ } else { - ExpectedIndexHash = Record->Hash; + ExpectedIndexHashes = Record->Hashes; if (_config->FindB("Debug::pkgAcquire::Auth", false)) { - std::cerr << "Queueing: " << (*Target)->URI << std::endl; - std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl; + std::cerr << "Queueing: " << (*Target)->URI << std::endl + << "Expected Hash:" << std::endl; + for (HashStringList::const_iterator hs = ExpectedIndexHashes.begin(); hs != ExpectedIndexHashes.end(); ++hs) + std::cerr << "\t- " << hs->toStr() << std::endl; std::cerr << "For: " << Record->MetaKeyFilename << std::endl; } - if (verify == true && ExpectedIndexHash.empty() == true && (*Target)->IsOptional() == false) + if (verify == true && ExpectedIndexHashes.empty() == true && (*Target)->IsOptional() == false) { Status = StatAuthError; strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str()); @@ -1659,14 +1668,14 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ { if ((*Target)->IsSubIndex() == true) new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description, - (*Target)->ShortDesc, ExpectedIndexHash); + (*Target)->ShortDesc, ExpectedIndexHashes); else if (transInRelease == false || Record != NULL || compressedAvailable == true) { if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true && MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true) - new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser); + new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser); else - new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser); + new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHashes, MetaIndexParser); } continue; } @@ -1677,9 +1686,9 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ instead, but passing the required info to it is to much hassle */ if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false || MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true)) - new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser); + new pkgAcqDiffIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser); else - new pkgAcqIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser); + new pkgAcqIndex(Owner, *Target, ExpectedIndexHashes, MetaIndexParser); } } /*}}}*/ @@ -1868,7 +1877,7 @@ pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- // FIXME: this can go away once the InRelease file is used widely -string pkgAcqMetaClearSig::Custom600Headers() +string pkgAcqMetaClearSig::Custom600Headers() const { string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); @@ -2002,7 +2011,6 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, checking later. */ bool pkgAcqArchive::QueueNext() { - string const ForceHash = _config->Find("Acquire::ForceHash"); for (; Vf.end() == false; ++Vf) { // Ignore not source sources @@ -2023,31 +2031,10 @@ bool pkgAcqArchive::QueueNext() pkgRecords::Parser &Parse = Recs->Lookup(Vf); if (_error->PendingError() == true) return false; - + string PkgFile = Parse.FileName(); - if (ForceHash.empty() == false) - { - if(stringcasecmp(ForceHash, "sha512") == 0) - ExpectedHash = HashString("SHA512", Parse.SHA512Hash()); - else if(stringcasecmp(ForceHash, "sha256") == 0) - ExpectedHash = HashString("SHA256", Parse.SHA256Hash()); - else if (stringcasecmp(ForceHash, "sha1") == 0) - ExpectedHash = HashString("SHA1", Parse.SHA1Hash()); - else - ExpectedHash = HashString("MD5Sum", Parse.MD5Hash()); - } - else - { - string Hash; - if ((Hash = Parse.SHA512Hash()).empty() == false) - ExpectedHash = HashString("SHA512", Hash); - else if ((Hash = Parse.SHA256Hash()).empty() == false) - ExpectedHash = HashString("SHA256", Hash); - else if ((Hash = Parse.SHA1Hash()).empty() == false) - ExpectedHash = HashString("SHA1", Hash); - else - ExpectedHash = HashString("MD5Sum", Parse.MD5Hash()); - } + ExpectedHashes = Parse.Hashes(); + if (PkgFile.empty() == true) return _error->Error(_("The package index files are corrupted. No Filename: " "field for package %s."), @@ -2134,10 +2121,10 @@ bool pkgAcqArchive::QueueNext() // AcqArchive::Done - Finished fetching /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash, +void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList const &CalcHashes, pkgAcquire::MethodConfig *Cfg) { - Item::Done(Message,Size,CalcHash,Cfg); + Item::Done(Message, Size, CalcHashes, Cfg); // Check the size if (Size != Version->Size) @@ -2145,12 +2132,12 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash, RenameOnError(SizeMismatch); return; } - - // Check the hash + // FIXME: could this empty() check impose *any* sort of security issue? - if(ExpectedHash.empty() == false && ExpectedHash.toStr() != CalcHash) + if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes) { RenameOnError(HashSumMismatch); + printHashSumComparision(DestFile, ExpectedHashes, CalcHashes); return; } @@ -2222,7 +2209,7 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*}}}*/ // AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/ // --------------------------------------------------------------------- -APT_PURE bool pkgAcqArchive::IsTrusted() +APT_PURE bool pkgAcqArchive::IsTrusted() const { return Trusted; } @@ -2241,11 +2228,11 @@ void pkgAcqArchive::Finished() // AcqFile::pkgAcqFile - Constructor /*{{{*/ // --------------------------------------------------------------------- /* The file is added to the queue */ -pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash, +pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashes, unsigned long long Size,string Dsc,string ShortDesc, const string &DestDir, const string &DestFilename, bool IsIndexFile) : - Item(Owner), ExpectedHash(Hash), IsIndexFile(IsIndexFile) + Item(Owner), ExpectedHashes(Hashes), IsIndexFile(IsIndexFile) { Retries = _config->FindI("Acquire::Retries",0); @@ -2282,15 +2269,16 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash, // AcqFile::Done - Item downloaded OK /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgAcqFile::Done(string Message,unsigned long long Size,string CalcHash, +void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList const &CalcHashes, pkgAcquire::MethodConfig *Cnf) { - Item::Done(Message,Size,CalcHash,Cnf); + Item::Done(Message,Size,CalcHashes,Cnf); // Check the hash - if(!ExpectedHash.empty() && ExpectedHash.toStr() != CalcHash) + if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes) { RenameOnError(HashSumMismatch); + printHashSumComparision(DestFile, ExpectedHashes, CalcHashes); return; } @@ -2361,7 +2349,7 @@ void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf) // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -string pkgAcqFile::Custom600Headers() +string pkgAcqFile::Custom600Headers() const { if (IsIndexFile) return "\nIndex-File: true"; diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index eab5bb222..2c39be46c 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -211,12 +211,12 @@ class pkgAcquire::Item : public WeakPointable * \param Message Data from the acquire method. Use LookupTag() * to parse it. * \param Size The size of the object that was fetched. - * \param Hash The HashSum of the object that was fetched. + * \param Hashes The HashSums of the object that was fetched. * \param Cnf The method via which the object was fetched. * * \sa pkgAcqMethod */ - virtual void Done(std::string Message,unsigned long long Size,std::string Hash, + virtual void Done(std::string Message, unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); /** \brief Invoked when the worker starts to fetch this object. @@ -238,34 +238,35 @@ class pkgAcquire::Item : public WeakPointable * line, so they should (if nonempty) have a leading newline and * no trailing newline. */ - virtual std::string Custom600Headers() {return std::string();}; + virtual std::string Custom600Headers() const {return std::string();}; /** \brief A "descriptive" URI-like string. * * \return a URI that should be used to describe what is being fetched. */ - virtual std::string DescURI() = 0; + virtual std::string DescURI() const = 0; /** \brief Short item description. * * \return a brief description of the object being fetched. */ - virtual std::string ShortDesc() {return DescURI();} + virtual std::string ShortDesc() const {return DescURI();} /** \brief Invoked by the worker when the download is completely done. */ virtual void Finished() {}; - /** \brief HashSum + /** \brief HashSums * - * \return the HashSum of this object, if applicable; otherwise, an - * empty string. + * \return the HashSums of this object, if applicable; otherwise, an + * empty list. */ - virtual std::string HashSum() {return std::string();}; + virtual HashStringList HashSums() const {return HashStringList();}; + std::string HashSum() const {HashStringList const hashes = HashSums(); HashString const * const hs = hashes.find(NULL); return hs != NULL ? hs->toStr() : ""; }; /** \return the acquire process with which this item is associated. */ - pkgAcquire *GetOwner() {return Owner;}; + pkgAcquire *GetOwner() const {return Owner;}; /** \return \b true if this object is being fetched from a trusted source. */ - virtual bool IsTrusted() {return false;}; + virtual bool IsTrusted() const {return false;}; // report mirror problems /** \brief Report mirror problem @@ -338,17 +339,17 @@ class pkgAcqSubIndex : public pkgAcquire::Item /** \brief The item that is currently being downloaded. */ pkgAcquire::ItemDesc Desc; - /** \brief The Hash that this file should have after download + /** \brief The Hashes that this file should have after download */ - HashString ExpectedHash; + HashStringList ExpectedHashes; public: // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return Desc.URI;}; - virtual std::string Custom600Headers(); + virtual std::string DescURI() const {return Desc.URI;}; + virtual std::string Custom600Headers() const; virtual bool ParseIndex(std::string const &IndexFile); /** \brief Create a new pkgAcqSubIndex. @@ -361,10 +362,10 @@ class pkgAcqSubIndex : public pkgAcquire::Item * * \param ShortDesc A short description of the list file to download. * - * \param ExpectedHash The list file's MD5 signature. + * \param ExpectedHashes The list file's hashsums which are expected. */ pkgAcqSubIndex(pkgAcquire *Owner, std::string const &URI,std::string const &URIDesc, - std::string const &ShortDesc, HashString const &ExpectedHash); + std::string const &ShortDesc, HashStringList const &ExpectedHashes); }; /*}}}*/ /** \brief An item that is responsible for fetching an index file of {{{ @@ -390,10 +391,10 @@ class pkgAcqDiffIndex : public pkgAcquire::Item */ std::string RealURI; - /** \brief The Hash that the real index file should have after + /** \brief The Hashes that the real index file should have after * all patches have been applied. */ - HashString ExpectedHash; + HashStringList ExpectedHashes; /** \brief The index file which will be patched to generate the new * file. @@ -413,10 +414,10 @@ class pkgAcqDiffIndex : public pkgAcquire::Item public: // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "Index";}; - virtual std::string Custom600Headers(); + virtual std::string DescURI() const {return RealURI + "Index";}; + virtual std::string Custom600Headers() const; /** \brief Parse the Index file for a set of Packages diffs. * @@ -441,11 +442,11 @@ class pkgAcqDiffIndex : public pkgAcquire::Item * * \param ShortDesc A short description of the list file to download. * - * \param ExpectedHash The list file's MD5 signature. + * \param ExpectedHashes The list file's hashsums which are expected. */ pkgAcqDiffIndex(pkgAcquire *Owner, struct IndexTarget const * const Target, - HashString ExpectedHash, + HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser); }; /*}}}*/ @@ -479,10 +480,10 @@ class pkgAcqIndexMergeDiffs : public pkgAcquire::Item */ std::string RealURI; - /** \brief HashSum of the package index file that is being - * reconstructed. + /** \brief The Hashes that the real index file should have after + * all patches have been applied. */ - HashString ExpectedHash; + HashStringList ExpectedHashes; /** \brief description of the file being downloaded. */ std::string Description; @@ -516,10 +517,9 @@ class pkgAcqIndexMergeDiffs : public pkgAcquire::Item * outright; its arguments are ignored. */ virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - - virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "Index";}; + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, + pkgAcquire::MethodConfig *Cnf); + virtual std::string DescURI() const {return RealURI + "Index";}; /** \brief Create an index merge-diff item. * @@ -532,7 +532,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcquire::Item * * \param ShortDesc A brief description of this item. * - * \param ExpectedHash The expected md5sum of the completely + * \param ExpectedHashes The expected md5sum of the completely * reconstructed package index file; the index file will be tested * against this value when it is entirely reconstructed. * @@ -543,7 +543,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcquire::Item * check if it was the last one to complete the download step */ pkgAcqIndexMergeDiffs(pkgAcquire *Owner,std::string const &URI,std::string const &URIDesc, - std::string const &ShortDesc, HashString const &ExpectedHash, + std::string const &ShortDesc, HashStringList const &ExpectedHashes, DiffInfo const &patch, std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches); }; /*}}}*/ @@ -576,8 +576,8 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item /** \brief Handle tasks that must be performed after the item * finishes downloading. * - * Dequeues the item and checks the resulting file's md5sum - * against ExpectedHash after the last patch was applied. + * Dequeues the item and checks the resulting file's hashsums + * against ExpectedHashes after the last patch was applied. * There is no need to check the md5/sha1 after a "normal" * patch because QueueNextDiff() will check the sha1 later. * @@ -603,10 +603,10 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item */ std::string RealURI; - /** \brief The HashSum of the package index file that is being + /** \brief The HashSums of the package index file that is being * reconstructed. */ - HashString ExpectedHash; + HashStringList ExpectedHashes; /** A description of the file being downloaded. */ std::string Description; @@ -649,9 +649,9 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item */ virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "Index";}; + virtual std::string DescURI() const {return RealURI + "Index";}; /** \brief Create an index diff item. * @@ -667,7 +667,7 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item * * \param ShortDesc A brief description of this item. * - * \param ExpectedHash The expected md5sum of the completely + * \param ExpectedHashes The expected md5sum of the completely * reconstructed package index file; the index file will be tested * against this value when it is entirely reconstructed. * @@ -678,7 +678,7 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item * that depends on it. */ pkgAcqIndexDiffs(pkgAcquire *Owner,std::string URI,std::string URIDesc, - std::string ShortDesc, HashString ExpectedHash, + std::string ShortDesc, HashStringList const &ExpectedHashes, std::string ServerSha1, std::vector<DiffInfo> diffs=std::vector<DiffInfo>()); }; @@ -723,7 +723,7 @@ class pkgAcqIndex : public pkgAcquire::Item std::string RealURI; /** \brief The expected hashsum of the decompressed index file. */ - HashString ExpectedHash; + HashStringList ExpectedHashes; /** \brief The compression-related file extensions that are being * added to the downloaded file one by one if first fails (e.g., "gz bz2"). @@ -739,11 +739,11 @@ class pkgAcqIndex : public pkgAcquire::Item // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string Custom600Headers(); - virtual std::string DescURI() {return Desc.URI;}; - virtual std::string HashSum() {return ExpectedHash.toStr(); }; + virtual std::string Custom600Headers() const; + virtual std::string DescURI() const {return Desc.URI;}; + virtual HashStringList HashSums() const {return ExpectedHashes; }; /** \brief Create a pkgAcqIndex. * @@ -756,7 +756,7 @@ class pkgAcqIndex : public pkgAcquire::Item * * \param ShortDesc A brief description of this index file. * - * \param ExpectedHash The expected hashsum of this index file. + * \param ExpectedHashes The expected hashsum of this index file. * * \param compressExt The compression-related extension with which * this index file should be downloaded, or "" to autodetect @@ -765,10 +765,10 @@ class pkgAcqIndex : public pkgAcquire::Item * fallback is ".gz" or none. */ pkgAcqIndex(pkgAcquire *Owner,std::string URI,std::string URIDesc, - std::string ShortDesc, HashString ExpectedHash, + std::string ShortDesc, HashStringList const &ExpectedHashes, std::string compressExt=""); pkgAcqIndex(pkgAcquire *Owner, struct IndexTarget const * const Target, - HashString const &ExpectedHash, indexRecords *MetaIndexParser); + HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser); void Init(std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc); }; /*}}}*/ @@ -784,7 +784,7 @@ class pkgAcqIndexTrans : public pkgAcqIndex public: virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual std::string Custom600Headers(); + virtual std::string Custom600Headers() const; /** \brief Create a pkgAcqIndexTrans. * @@ -800,7 +800,7 @@ class pkgAcqIndexTrans : public pkgAcqIndex pkgAcqIndexTrans(pkgAcquire *Owner,std::string URI,std::string URIDesc, std::string ShortDesc); pkgAcqIndexTrans(pkgAcquire *Owner, struct IndexTarget const * const Target, - HashString const &ExpectedHash, indexRecords *MetaIndexParser); + HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser); }; /*}}}*/ /** \brief Information about an index file. */ /*{{{*/ @@ -904,10 +904,10 @@ class pkgAcqMetaSig : public pkgAcquire::Item // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string Custom600Headers(); - virtual std::string DescURI() {return RealURI; }; + virtual std::string Custom600Headers() const; + virtual std::string DescURI() const {return RealURI; }; /** \brief Create a new pkgAcqMetaSig. */ pkgAcqMetaSig(pkgAcquire *Owner,std::string URI,std::string URIDesc, std::string ShortDesc, @@ -1000,10 +1000,10 @@ class pkgAcqMetaIndex : public pkgAcquire::Item // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, std::string Hash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string Custom600Headers(); - virtual std::string DescURI() {return RealURI; }; + virtual std::string Custom600Headers() const; + virtual std::string DescURI() const {return RealURI; }; /** \brief Create a new pkgAcqMetaIndex. */ pkgAcqMetaIndex(pkgAcquire *Owner, @@ -1036,7 +1036,7 @@ class pkgAcqMetaClearSig : public pkgAcqMetaIndex public: void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual std::string Custom600Headers(); + virtual std::string Custom600Headers() const; /** \brief Create a new pkgAcqMetaClearSig. */ pkgAcqMetaClearSig(pkgAcquire *Owner, @@ -1073,7 +1073,7 @@ class pkgAcqArchive : public pkgAcquire::Item pkgRecords *Recs; /** \brief The hashsum of this package. */ - HashString ExpectedHash; + HashStringList ExpectedHashes; /** \brief A location in which the actual filename of the package * should be stored. @@ -1101,13 +1101,13 @@ class pkgAcqArchive : public pkgAcquire::Item public: virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size,std::string Hash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return Desc.URI;}; - virtual std::string ShortDesc() {return Desc.ShortDesc;}; + virtual std::string DescURI() const {return Desc.URI;}; + virtual std::string ShortDesc() const {return Desc.ShortDesc;}; virtual void Finished(); - virtual std::string HashSum() {return ExpectedHash.toStr(); }; - virtual bool IsTrusted(); + virtual HashStringList HashSums() const {return ExpectedHashes; }; + virtual bool IsTrusted() const; /** \brief Create a new pkgAcqArchive. * @@ -1144,7 +1144,7 @@ class pkgAcqFile : public pkgAcquire::Item pkgAcquire::ItemDesc Desc; /** \brief The hashsum of the file to download, if it is known. */ - HashString ExpectedHash; + HashStringList ExpectedHashes; /** \brief How many times to retry the download, set from * Acquire::Retries. @@ -1158,11 +1158,11 @@ class pkgAcqFile : public pkgAcquire::Item // Specialized action members virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size,std::string CalcHash, + virtual void Done(std::string Message,unsigned long long Size, HashStringList const &CalcHashes, pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return Desc.URI;}; - virtual std::string HashSum() {return ExpectedHash.toStr(); }; - virtual std::string Custom600Headers(); + virtual std::string DescURI() const {return Desc.URI;}; + virtual HashStringList HashSums() const { return ExpectedHashes; }; + virtual std::string Custom600Headers() const; /** \brief Create a new pkgAcqFile object. * @@ -1171,8 +1171,8 @@ class pkgAcqFile : public pkgAcquire::Item * * \param URI The URI to download. * - * \param Hash The hashsum of the file to download, if it is known; - * otherwise "". + * \param Hashes The hashsums of the file to download, if they are known; + * otherwise empty list. * * \param Size The size of the file to download, if it is known; * otherwise 0. @@ -1195,7 +1195,7 @@ class pkgAcqFile : public pkgAcquire::Item * is the absolute name to which the file should be downloaded. */ - pkgAcqFile(pkgAcquire *Owner, std::string URI, std::string Hash, unsigned long long Size, + pkgAcqFile(pkgAcquire *Owner, std::string URI, HashStringList const &Hashes, unsigned long long Size, std::string Desc, std::string ShortDesc, const std::string &DestDir="", const std::string &DestFilename="", bool IsIndexFile=false); diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index 746c553f1..58d214068 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -147,6 +147,16 @@ void pkgAcqMethod::URIStart(FetchResult &Res) // AcqMethod::URIDone - A URI is finished /*{{{*/ // --------------------------------------------------------------------- /* */ +static void printHashStringList(HashStringList const * const list) +{ + for (HashStringList::const_iterator hash = list->begin(); hash != list->end(); ++hash) + { + // very old compatibility name for MD5Sum + if (hash->HashType() == "MD5Sum") + std::cout << "MD5-Hash: " << hash->HashValue() << "\n"; + std::cout << hash->HashType() << "-Hash: " << hash->HashValue() << "\n"; + } +} void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt) { if (Queue == 0) @@ -164,15 +174,8 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt) if (Res.LastModified != 0) std::cout << "Last-Modified: " << TimeRFC1123(Res.LastModified) << "\n"; - if (Res.MD5Sum.empty() == false) - std::cout << "MD5-Hash: " << Res.MD5Sum << "\n" - << "MD5Sum-Hash: " << Res.MD5Sum << "\n"; - if (Res.SHA1Sum.empty() == false) - std::cout << "SHA1-Hash: " << Res.SHA1Sum << "\n"; - if (Res.SHA256Sum.empty() == false) - std::cout << "SHA256-Hash: " << Res.SHA256Sum << "\n"; - if (Res.SHA512Sum.empty() == false) - std::cout << "SHA512-Hash: " << Res.SHA512Sum << "\n"; + printHashStringList(&Res.Hashes); + if (UsedMirror.empty() == false) std::cout << "UsedMirror: " << UsedMirror << "\n"; if (Res.GPGVOutput.empty() == false) @@ -200,15 +203,8 @@ void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt) if (Alt->LastModified != 0) std::cout << "Alt-Last-Modified: " << TimeRFC1123(Alt->LastModified) << "\n"; - if (Alt->MD5Sum.empty() == false) - std::cout << "Alt-MD5-Hash: " << Alt->MD5Sum << "\n"; - if (Alt->SHA1Sum.empty() == false) - std::cout << "Alt-SHA1-Hash: " << Alt->SHA1Sum << "\n"; - if (Alt->SHA256Sum.empty() == false) - std::cout << "Alt-SHA256-Hash: " << Alt->SHA256Sum << "\n"; - if (Alt->SHA512Sum.empty() == false) - std::cout << "Alt-SHA512-Hash: " << Alt->SHA512Sum << "\n"; - + printHashStringList(&Alt->Hashes); + if (Alt->IMSHit == true) std::cout << "Alt-IMS-Hit: true\n"; } @@ -442,12 +438,9 @@ pkgAcqMethod::FetchResult::FetchResult() : LastModified(0), // --------------------------------------------------------------------- /* This hides the number of hashes we are supporting from the caller. It just deals with the hash class. */ -void pkgAcqMethod::FetchResult::TakeHashes(Hashes &Hash) +void pkgAcqMethod::FetchResult::TakeHashes(class Hashes &Hash) { - MD5Sum = Hash.MD5.Result(); - SHA1Sum = Hash.SHA1.Result(); - SHA256Sum = Hash.SHA256.Result(); - SHA512Sum = Hash.SHA512.Result(); + Hashes = Hash.GetHashStringList(); } /*}}}*/ void pkgAcqMethod::Dequeue() { /*{{{*/ diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 221ccf273..8a17a5fd5 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -20,6 +20,7 @@ #ifndef PKGLIB_ACQUIRE_METHOD_H #define PKGLIB_ACQUIRE_METHOD_H +#include <apt-pkg/hashes.h> #include <apt-pkg/macros.h> #include <stdarg.h> @@ -33,7 +34,6 @@ #include <apt-pkg/strutl.h> #endif -class Hashes; class pkgAcqMethod { protected: @@ -51,10 +51,7 @@ class pkgAcqMethod struct FetchResult { - std::string MD5Sum; - std::string SHA1Sum; - std::string SHA256Sum; - std::string SHA512Sum; + HashStringList Hashes; std::vector<std::string> GPGVOutput; time_t LastModified; bool IMSHit; @@ -62,7 +59,7 @@ class pkgAcqMethod unsigned long long Size; unsigned long long ResumePoint; - void TakeHashes(Hashes &Hash); + void TakeHashes(class Hashes &Hash); FetchResult(); }; diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 047a655ce..ec1b2fc46 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -326,25 +326,30 @@ bool pkgAcquire::Worker::RunMessages() Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize); // see if there is a hash to verify - string RecivedHash; - HashString expectedHash(Owner->HashSum()); - if(!expectedHash.empty()) + HashStringList RecivedHashes; + HashStringList expectedHashes = Owner->HashSums(); + for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs) { - string hashTag = expectedHash.HashType()+"-Hash"; - string hashSum = LookupTag(Message, hashTag.c_str()); - if(!hashSum.empty()) - RecivedHash = expectedHash.HashType() + ":" + hashSum; - if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) - { - clog << "201 URI Done: " << Owner->DescURI() << endl - << "RecivedHash: " << RecivedHash << endl - << "ExpectedHash: " << expectedHash.toStr() - << endl << endl; - } + std::string const tagname = hs->HashType() + "-Hash"; + std::string const hashsum = LookupTag(Message, tagname.c_str()); + if (hashsum.empty() == false) + RecivedHashes.push_back(HashString(hs->HashType(), hashsum)); + } + + if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) + { + std::clog << "201 URI Done: " << Owner->DescURI() << endl + << "RecivedHash:" << endl; + for (HashStringList::const_iterator hs = RecivedHashes.begin(); hs != RecivedHashes.end(); ++hs) + std::clog << "\t- " << hs->toStr() << std::endl; + std::clog << "ExpectedHash:" << endl; + for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs) + std::clog << "\t- " << hs->toStr() << std::endl; + std::clog << endl; } - Owner->Done(Message, ServerSize, RecivedHash.c_str(), Config); + Owner->Done(Message, ServerSize, RecivedHashes, Config); ItemDone(); - + // Log that we are done if (Log != 0) { diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index bb11a3fca..199e395f6 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -141,11 +141,21 @@ APT_PURE bool HashString::operator!=(HashString const &other) const } /*}}}*/ +bool HashStringList::usable() const /*{{{*/ +{ + if (empty() == true) + return false; + std::string const forcedType = _config->Find("Acquire::ForceHash", ""); + if (forcedType.empty() == true) + return true; + return find(forcedType) != NULL; +} + /*}}}*/ HashString const * HashStringList::find(char const * const type) const /*{{{*/ { if (type == NULL || type[0] == '\0') { - std::string forcedType = _config->Find("Acquire::ForceHash", ""); + std::string const forcedType = _config->Find("Acquire::ForceHash", ""); if (forcedType.empty() == false) return find(forcedType.c_str()); for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t) @@ -196,6 +206,15 @@ bool HashStringList::VerifyFile(std::string filename) const /*{{{*/ /*}}}*/ bool HashStringList::operator==(HashStringList const &other) const /*{{{*/ { + std::string const forcedType = _config->Find("Acquire::ForceHash", ""); + if (forcedType.empty() == false) + { + HashString const * const hs = other.find(forcedType); + HashString const * const ohs = other.find(forcedType); + if (hs == NULL || ohs == NULL) + return false; + return hs == ohs; + } short matches = 0; for (const_iterator hs = begin(); hs != end(); ++hs) { @@ -216,11 +235,28 @@ bool HashStringList::operator!=(HashStringList const &other) const } /*}}}*/ -// Hashes::AddFD - Add the contents of the FD /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5, - bool const addSHA1, bool const addSHA256, bool const addSHA512) +// Hashes::Add* - Add the contents of data or FD /*{{{*/ +bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, unsigned int const Hashes) +{ + bool Res = true; +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + if ((Hashes & MD5SUM) == MD5SUM) + Res &= MD5.Add(Data, Size); + if ((Hashes & SHA1SUM) == SHA1SUM) + Res &= SHA1.Add(Data, Size); + if ((Hashes & SHA256SUM) == SHA256SUM) + Res &= SHA256.Add(Data, Size); + if ((Hashes & SHA512SUM) == SHA512SUM) + Res &= SHA512.Add(Data, Size); +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + return Res; +} +bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes) { unsigned char Buf[64*64]; bool const ToEOF = (Size == UntilEOF); @@ -234,19 +270,12 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5, if (ToEOF && Res == 0) // EOF break; Size -= Res; - if (addMD5 == true) - MD5.Add(Buf,Res); - if (addSHA1 == true) - SHA1.Add(Buf,Res); - if (addSHA256 == true) - SHA256.Add(Buf,Res); - if (addSHA512 == true) - SHA512.Add(Buf,Res); + if (Add(Buf, Res, Hashes) == false) + return false; } return true; } -bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, bool const addMD5, - bool const addSHA1, bool const addSHA256, bool const addSHA512) +bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, unsigned int const Hashes) { unsigned char Buf[64*64]; bool const ToEOF = (Size == 0); @@ -265,15 +294,35 @@ bool Hashes::AddFD(FileFd &Fd,unsigned long long Size, bool const addMD5, else if (a == 0) // EOF break; Size -= a; - if (addMD5 == true) - MD5.Add(Buf, a); - if (addSHA1 == true) - SHA1.Add(Buf, a); - if (addSHA256 == true) - SHA256.Add(Buf, a); - if (addSHA512 == true) - SHA512.Add(Buf, a); + if (Add(Buf, a, Hashes) == false) + return false; } return true; } /*}}}*/ +HashStringList Hashes::GetHashStringList() +{ + HashStringList hashes; +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + hashes.push_back(HashString("MD5Sum", MD5.Result().Value())); + hashes.push_back(HashString("SHA1", SHA1.Result().Value())); + hashes.push_back(HashString("SHA256", SHA256.Result().Value())); + hashes.push_back(HashString("SHA512", SHA512.Result().Value())); +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + return hashes; +} +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #pragma GCC diagnostic ignored "-Wsuggest-attribute=const" +#endif +Hashes::Hashes() {} +Hashes::~Hashes() {} +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 490282209..caeba006d 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -114,6 +114,15 @@ class HashStringList */ bool empty() const { return list.empty(); } + /** has the list at least one good entry + * + * similar to #empty, but handles forced hashes. + * + * @return if no hash is forced, same result as #empty, + * if one is forced \b true if this has is available, \b false otherwise + */ + bool usable() const; + typedef std::vector<HashString>::const_iterator const_iterator; /** iterator to the first element */ @@ -128,8 +137,10 @@ class HashStringList /** compare two HashStringList for similarity. * * Two lists are similar if at least one hashtype is in both lists - * and the hashsum matches. All hashes are checked, if one doesn't - * match false is returned regardless of how many matched before. + * and the hashsum matches. All hashes are checked by default, + * if one doesn't match false is returned regardless of how many + * matched before. If a hash is forced, only this hash is compared, + * all others are ignored. */ bool operator==(HashStringList const &other) const; bool operator!=(HashStringList const &other) const; @@ -152,30 +163,63 @@ class HashStringList class Hashes { + /** \brief dpointer placeholder */ + void *d; + public: + /* those will disappear in the future as it is hard to add new ones this way. + * Use Add* to build the results and get them via GetHashStringList() instead */ + APT_DEPRECATED MD5Summation MD5; + APT_DEPRECATED SHA1Summation SHA1; + APT_DEPRECATED SHA256Summation SHA256; + APT_DEPRECATED SHA512Summation SHA512; - MD5Summation MD5; - SHA1Summation SHA1; - SHA256Summation SHA256; - SHA512Summation SHA512; - static const int UntilEOF = 0; - inline bool Add(const unsigned char *Data,unsigned long long Size) + bool Add(const unsigned char * const Data, unsigned long long const Size, unsigned int const Hashes = ~0); + inline bool Add(const char * const Data) + {return Add((unsigned char const * const)Data,strlen(Data));}; + inline bool Add(const unsigned char * const Beg,const unsigned char * const End) + {return Add(Beg,End-Beg);}; + + enum SupportedHashes { MD5SUM = (1 << 0), SHA1SUM = (1 << 1), SHA256SUM = (1 << 2), + SHA512SUM = (1 << 3) }; + bool AddFD(int const Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0); + bool AddFD(FileFd &Fd,unsigned long long Size = 0, unsigned int const Hashes = ~0); + + HashStringList GetHashStringList(); + +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + Hashes(); + virtual ~Hashes(); +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + + private: + APT_HIDDEN APT_CONST inline unsigned int boolsToFlag(bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512) { - return MD5.Add(Data,Size) && SHA1.Add(Data,Size) && SHA256.Add(Data,Size) && SHA512.Add(Data,Size); + unsigned int Hashes = ~0; + if (addMD5 == false) Hashes &= ~MD5SUM; + if (addSHA1 == false) Hashes &= ~SHA1SUM; + if (addSHA256 == false) Hashes &= ~SHA256SUM; + if (addSHA512 == false) Hashes &= ~SHA512SUM; + return Hashes; + } + + public: + APT_DEPRECATED bool AddFD(int const Fd, unsigned long long Size, bool const addMD5, + bool const addSHA1, bool const addSHA256, bool const addSHA512) { + return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512)); + }; + + APT_DEPRECATED bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5, + bool const addSHA1, bool const addSHA256, bool const addSHA512) { + return AddFD(Fd, Size, boolsToFlag(addMD5, addSHA1, addSHA256, addSHA512)); }; - inline bool Add(const char *Data) {return Add((unsigned char const *)Data,strlen(Data));}; - inline bool AddFD(int const Fd,unsigned long long Size = 0) - { return AddFD(Fd, Size, true, true, true, true); }; - bool AddFD(int const Fd, unsigned long long Size, bool const addMD5, - bool const addSHA1, bool const addSHA256, bool const addSHA512); - inline bool AddFD(FileFd &Fd,unsigned long long Size = 0) - { return AddFD(Fd, Size, true, true, true, true); }; - bool AddFD(FileFd &Fd, unsigned long long Size, bool const addMD5, - bool const addSHA1, bool const addSHA256, bool const addSHA512); - inline bool Add(const unsigned char *Beg,const unsigned char *End) - {return Add(Beg,End-Beg);}; }; #endif diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index b4839ada4..607dae882 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -258,7 +258,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const vector <struct IndexTarget *> *targets = ComputeIndexTargets(); for (vector <struct IndexTarget*>::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) { new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, - (*Target)->ShortDesc, HashString()); + (*Target)->ShortDesc, HashStringList()); } delete targets; diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 6063db5a8..b824e11b4 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -73,36 +73,17 @@ string debRecordParser::Homepage() return Section.FindS("Homepage"); } /*}}}*/ -// RecordParser::MD5Hash - Return the archive hash /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::MD5Hash() -{ - return Section.FindS("MD5Sum"); -} - /*}}}*/ -// RecordParser::SHA1Hash - Return the archive hash /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::SHA1Hash() -{ - return Section.FindS("SHA1"); -} - /*}}}*/ -// RecordParser::SHA256Hash - Return the archive hash /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::SHA256Hash() -{ - return Section.FindS("SHA256"); -} - /*}}}*/ -// RecordParser::SHA512Hash - Return the archive hash /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debRecordParser::SHA512Hash() -{ - return Section.FindS("SHA512"); +// RecordParser::Hashes - return the available archive hashes /*{{{*/ +HashStringList debRecordParser::Hashes() const +{ + HashStringList hashes; + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + std::string const hash = Section.FindS(*type); + if (hash.empty() == false) + hashes.push_back(HashString(*type, hash)); + } + return hashes; } /*}}}*/ // RecordParser::Maintainer - Return the maintainer email /*{{{*/ diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index d572bc5c2..90c88fefe 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -42,13 +42,11 @@ class debRecordParser : public pkgRecords::Parser // These refer to the archive file for the Version virtual std::string FileName(); - virtual std::string MD5Hash(); - virtual std::string SHA1Hash(); - virtual std::string SHA256Hash(); - virtual std::string SHA512Hash(); virtual std::string SourcePkg(); virtual std::string SourceVer(); - + + virtual HashStringList Hashes() const; + // These are some general stats about the package virtual std::string Maintainer(); virtual std::string ShortDesc(); diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 854ba1bd7..bb3b5d340 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -516,7 +516,7 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex) return false; } - if (!Record->Hash.VerifyFile(prefix+file)) + if (!Record->Hashes.VerifyFile(prefix+file)) { _error->Warning(_("Hash mismatch for: %s"),file.c_str()); return false; @@ -524,8 +524,10 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex) if(Debug == true) { - cout << "File: " << prefix+file << endl; - cout << "Expected Hash " << Record->Hash.toStr() << endl; + cout << "File: " << prefix+file << endl + << "Expected Hash " << endl; + for (HashStringList::const_iterator hs = Record->Hashes.begin(); hs != Record->Hashes.end(); ++hs) + std::cout << "\t- " << hs->toStr() << std::endl; } return true; diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index 68ebdce08..5dcaadd76 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -105,7 +105,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/ return false; indexRecords::checkSum *Sum = new indexRecords::checkSum; Sum->MetaKeyFilename = Name; - Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash); + Sum->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash)); Sum->Size = Size; Entries[Name] = Sum; } diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h index 2260a4ae1..14b03c4d5 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -55,11 +55,21 @@ class indexRecords virtual ~indexRecords(){}; }; +#if __GNUC__ >= 4 + // ensure that con- & de-structor don't trigger this warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif struct indexRecords::checkSum { std::string MetaKeyFilename; - HashString Hash; + HashStringList Hashes; unsigned long long Size; + + APT_DEPRECATED HashString Hash; }; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif #endif diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h index b5237b3a0..b0b449ae1 100644 --- a/apt-pkg/pkgrecords.h +++ b/apt-pkg/pkgrecords.h @@ -18,6 +18,8 @@ #define PKGLIB_PKGRECORDS_H #include <apt-pkg/pkgcache.h> +#include <apt-pkg/hashes.h> +#include <apt-pkg/macros.h> #include <string> #include <vector> @@ -56,13 +58,21 @@ class pkgRecords::Parser /*{{{*/ // These refer to the archive file for the Version virtual std::string FileName() {return std::string();}; - virtual std::string MD5Hash() {return std::string();}; - virtual std::string SHA1Hash() {return std::string();}; - virtual std::string SHA256Hash() {return std::string();}; - virtual std::string SHA512Hash() {return std::string();}; virtual std::string SourcePkg() {return std::string();}; virtual std::string SourceVer() {return std::string();}; + /** return all known hashes in this record. + * + * For authentication proposes packages come with hashsums which + * this method is supposed to parse and return so that clients can + * choose the hash to be used. + */ + virtual HashStringList Hashes() const { return HashStringList(); }; + APT_DEPRECATED std::string MD5Hash() const { return GetHashFromHashes("MD5Sum"); }; + APT_DEPRECATED std::string SHA1Hash() const { return GetHashFromHashes("SHA1"); }; + APT_DEPRECATED std::string SHA256Hash() const { return GetHashFromHashes("SHA256"); }; + APT_DEPRECATED std::string SHA512Hash() const { return GetHashFromHashes("SHA512"); }; + // These are some general stats about the package virtual std::string Maintainer() {return std::string();}; virtual std::string ShortDesc() {return std::string();}; @@ -77,6 +87,14 @@ class pkgRecords::Parser /*{{{*/ virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;}; virtual ~Parser() {}; + + private: + APT_HIDDEN std::string GetHashFromHashes(char const * const type) const + { + HashStringList const hashes = Hashes(); + HashString const * const hs = hashes.find(type); + return hs != NULL ? hs->HashValue() : ""; + }; }; /*}}}*/ #endif |