]> git.saurik.com Git - apt.git/commitdiff
use HashStringList in the acquire system
authorDavid Kalnischkies <kalnischkies@gmail.com>
Sun, 18 Aug 2013 22:00:23 +0000 (00:00 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Fri, 9 May 2014 11:06:27 +0000 (13:06 +0200)
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.

20 files changed:
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
apt-pkg/acquire-method.cc
apt-pkg/acquire-method.h
apt-pkg/acquire-worker.cc
apt-pkg/contrib/hashes.cc
apt-pkg/contrib/hashes.h
apt-pkg/deb/debmetaindex.cc
apt-pkg/deb/debrecords.cc
apt-pkg/deb/debrecords.h
apt-pkg/indexcopy.cc
apt-pkg/indexrecords.cc
apt-pkg/indexrecords.h
apt-pkg/pkgrecords.h
cmdline/apt-get.cc
test/integration/test-apt-sources-deb822
test/integration/test-bug-722207-print-uris-even-if-very-quiet
test/integration/test-pdiff-usage
test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
test/libapt/hashsums_test.cc

index 913764f64ce04fdc91238a0f3066a4b29209bf50..1156d6f337a57db34d4e7fa64ac748f45bb01282 100644 (file)
 
 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";
index eab5bb2229e3a9c66d16742cfe3a5a5eddc00855..2c39be46c05e44f1da91492f31c36b9a89487290 100644 (file)
@@ -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);
index 746c553f1cc3cbea8d4518b7e8bca556b3eac825..58d214068ec3d1d86cfb21c2e470a2d4715ad158 100644 (file)
@@ -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() {                                         /*{{{*/
index 221ccf2737bbf8fedd173a863d8ddf945496fe40..8a17a5fd52fb832974ebec17210e5f28362f6229 100644 (file)
@@ -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();
    };
 
index 047a655ced6dbddb7e10e882ff6e1e4b83b6d3bf..ec1b2fc469be86573cf42768b6a2a8c79c042a67 100644 (file)
@@ -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)
            {
index bb11a3fcabc3a2508f9c6fcd0c364d5de1f21bd6..199e395f68142f6027fa35c17303e929a69767b6 100644 (file)
@@ -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
index 4902822095e5dacad14ae2811b005e8d24442049..caeba006d04d6a8b465ae613233ee0a607995e54 100644 (file)
@@ -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
index b4839ada4cfb6e2dfa37071546f6cbdbe22605b4..607dae882a453f2476c4d0dc5664ccc26a43cc0a 100644 (file)
@@ -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;
 
index 6063db5a8203d4a241aafd10dde4869092597100..b824e11b46b39700041b8e4c837e8468c38fe693 100644 (file)
@@ -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              /*{{{*/
index d572bc5c20b5605cafc775dfb99aabad2a1771a3..90c88fefea392faeedb4a14954828f652db217d0 100644 (file)
@@ -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();
index 854ba1bd7d871f272f581358281398d504faa544..bb3b5d340a5d60ca30a96a657fd0a5439a72ebae 100644 (file)
@@ -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;
index 68ebdce0886fb5065a3cec1e5297b49cbf160107..5dcaadd76de39de92df31e60c1120f84286694be 100644 (file)
@@ -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;
       }
index 2260a4ae1edb2202480cb46a58362bbf4adff007..14b03c4d5b2fa5814e6f36f39f4966ec8ec05094 100644 (file)
@@ -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
index b5237b3a08052ef337ed11e31644e3df7a948e16..b0b449ae14c69f4bf673965574926cb41e51831d 100644 (file)
@@ -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
index fc6223989f10e729df0ef80ab28af6fde71ebed0..3388351d9b29cf9a435ec0c4068d55e4a0517ede 100644 (file)
@@ -838,8 +838,7 @@ static bool DoSource(CommandLine &CmdL)
            }
 
         // see if we have a hash (Acquire::ForceHash is the only way to have none)
-        HashString const * const hs = I->Hashes.find(NULL);
-        if (hs == NULL && _config->FindB("APT::Get::AllowUnauthenticated",false) == false)
+        if (I->Hashes.usable() == false && _config->FindB("APT::Get::AllowUnauthenticated",false) == false)
         {
            ioprintf(c1out, "Skipping download of file '%s' as requested hashsum is not available for authentication\n",
                     localFile.c_str());
@@ -847,8 +846,7 @@ static bool DoSource(CommandLine &CmdL)
         }
 
         new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
-                       hs != NULL ? hs->toStr() : "", I->Size,
-                       Last->Index().SourceInfo(*Last,*I),Src);
+                       I->Hashes, I->Size, Last->Index().SourceInfo(*Last,*I), Src);
       }
    }
    
index 5f54b75315dfc5b68826681c7a83ea938e17d366..d8b2334ad707b9584eb75c15b6315e8d1bc860e6 100755 (executable)
@@ -23,14 +23,14 @@ Description: summay
 
 msgtest 'Test sources.list' 'old style'
 echo "deb http://ftp.debian.org/debian stable main" > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 "  aptget update --print-uris
 
 msgtest 'Test sources.list' 'simple deb822'
 echo "$BASE"  > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 "  aptget update --print-uris
 
 
@@ -39,29 +39,29 @@ msgtest 'Test deb822 with' 'two entries'
 echo "$BASE" > $SOURCES
 echo "" >> $SOURCES
 echo "$BASE" | sed  s/stable/unstable/  >> $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
-'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 :
+'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 "  aptget update --print-uris
 
 # two suite entries
 msgtest 'Test deb822 with' 'two Suite entries'
 echo "$BASE"  | sed -e "s/stable/stable unstable/" > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
-'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 :
+'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 "  aptget update --print-uris 
 
 msgtest 'Test deb822' 'architecture option'
 echo "$BASE" > $SOURCES
 echo "Architectures: amd64 armel" >> $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-amd64/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-amd64_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-amd64/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-amd64_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 "  aptget update --print-uris
 
 
@@ -85,19 +85,19 @@ testempty aptget update --print-uris
 # multiple URIs
 msgtest 'Test deb822 sources.list file which has' 'Multiple URIs work'
 echo "$BASE"  | sed -e 's#http://ftp.debian.org/debian#http://ftp.debian.org/debian http://ftp.de.debian.org/debian#' > $SOURCES
-testequal --nomsg  "'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.de.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.de.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg  "'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.de.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.de.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp.de.debian.org_debian_dists_stable_InRelease 0 
-'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 "  aptget update --print-uris 
 
 # multiple Type in one field
 msgtest 'Test deb822 sources.list file which has' 'Multiple Types work'
 echo "$BASE"  | sed -e 's#Types: deb#Types: deb deb-src#' > $SOURCES
-testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0 :
-'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 :
-'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 :
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0 
+'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 
 'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 "  aptget update --print-uris 
 
 # a Suite
@@ -107,6 +107,6 @@ Types: deb
 URIs: http://emacs.naquadah.org
 Suites: stable/
 EOF
-testequal --nomsg "'http://emacs.naquadah.org/stable/Packages.bz2' emacs.naquadah.org_stable_Packages 0 :
-'http://emacs.naquadah.org/stable/en.bz2' emacs.naquadah.org_stable_en 0 :
+testequal --nomsg "'http://emacs.naquadah.org/stable/Packages.bz2' emacs.naquadah.org_stable_Packages 0 
+'http://emacs.naquadah.org/stable/en.bz2' emacs.naquadah.org_stable_en 0 
 'http://emacs.naquadah.org/stable/InRelease' emacs.naquadah.org_stable_InRelease 0 "  aptget update --print-uris 
index f2d95da19d03e0b64be7b8c8bc7a0434f6d37f9f..9a5685703e6b2fbb01f12a64739500ef29c36107 100755 (executable)
@@ -16,10 +16,10 @@ setupaptarchive
 
 APTARCHIVE=$(readlink -f ./aptarchive)
 
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget upgrade -qq --print-uris
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget dist-upgrade -qq --print-uris
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget install apt -qq --print-uris
-testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 MD5Sum:" aptget download apt -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget upgrade -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget dist-upgrade -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget install apt -qq --print-uris
+testequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget download apt -qq --print-uris
 testequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e
 'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt -qq --print-uris
 testequal "'http://packages.debian.org/changelogs/pool/main/apt/apt_2/changelog'" aptget changelog apt -qq --print-uris
index afe1ad443d2e4d09a0b1ffa4ebe64cc7b084173d..74749d6abae16cd7f78536f42d1bba382bc487e9 100755 (executable)
@@ -13,12 +13,6 @@ changetowebserver
 
 PKGFILE="${TESTDIR}/$(echo "$(basename $0)" | sed 's#^test-#Packages-#')"
 
-echo '#!/bin/sh
-touch merge-was-used
-/usr/bin/diffindex-rred "$@"' > extrred
-chmod +x extrred
-echo 'Dir::Bin::rred "./extrred";' > rootdir/etc/apt/apt.conf.d/99rred
-
 wasmergeused() {
        msgtest 'Test for successful execution of' "$*"
        local OUTPUT=$(mktemp)
index 1a7db0adc36bc7ab63e058ba254aaf598bc123dd..8e50843f329cbeca6447c06c18a0b2176acddda8 100755 (executable)
@@ -22,7 +22,7 @@ Config-Item: Acquire::http::DependOnSTDIN=0
 600 Acquire URI
 URI: http://localhost:8080/holygrail
 Filename: knights-talking
-' | LD_LIBRARY_PATH=${BUILDDIRECTORY} ${METHODSDIR}/http >/dev/null 2>&1 && msgpass || msgfail
+' | runapt ${METHODSDIR}/http >/dev/null 2>&1 && msgpass || msgfail
 testfileequal knights-talking 'ni ni ni'
 
 ensure_n_canary_strings_in_dir() {
index ac7d4158276e1e4b33f74b29439fb095526d7cab..2159996ffcca15c9ca153fca7b089e175fa70dab 100644 (file)
@@ -1,5 +1,6 @@
 #include <config.h>
 
+#include <apt-pkg/configuration.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/sha1.h>
 #include <apt-pkg/sha2.h>
@@ -166,20 +167,26 @@ TEST(HashSumsTest, FileBased)
    {
       Hashes hashes;
       hashes.AddFD(fd.Fd());
-      EXPECT_EQ(md5.Value(), hashes.MD5.Result().Value());
-      EXPECT_EQ(sha1.Value(), hashes.SHA1.Result().Value());
-      EXPECT_EQ(sha256.Value(), hashes.SHA256.Result().Value());
-      EXPECT_EQ(sha512.Value(), hashes.SHA512.Result().Value());
+      HashStringList list = hashes.GetHashStringList();
+      EXPECT_FALSE(list.empty());
+      EXPECT_EQ(4, list.size());
+      EXPECT_EQ(md5.Value(), list.find("MD5Sum")->HashValue());
+      EXPECT_EQ(sha1.Value(), list.find("SHA1")->HashValue());
+      EXPECT_EQ(sha256.Value(), list.find("SHA256")->HashValue());
+      EXPECT_EQ(sha512.Value(), list.find("SHA512")->HashValue());
    }
    unsigned long sz = fd.FileSize();
    fd.Seek(0);
    {
       Hashes hashes;
       hashes.AddFD(fd.Fd(), sz);
-      EXPECT_EQ(md5.Value(), hashes.MD5.Result().Value());
-      EXPECT_EQ(sha1.Value(), hashes.SHA1.Result().Value());
-      EXPECT_EQ(sha256.Value(), hashes.SHA256.Result().Value());
-      EXPECT_EQ(sha512.Value(), hashes.SHA512.Result().Value());
+      HashStringList list = hashes.GetHashStringList();
+      EXPECT_FALSE(list.empty());
+      EXPECT_EQ(4, list.size());
+      EXPECT_EQ(md5.Value(), list.find("MD5Sum")->HashValue());
+      EXPECT_EQ(sha1.Value(), list.find("SHA1")->HashValue());
+      EXPECT_EQ(sha256.Value(), list.find("SHA256")->HashValue());
+      EXPECT_EQ(sha512.Value(), list.find("SHA512")->HashValue());
    }
    fd.Seek(0);
    {
@@ -260,3 +267,65 @@ TEST(HashSumsTest, FileBased)
    EXPECT_FALSE(similar == hashes);
    EXPECT_TRUE(similar != hashes);
 }
+TEST(HashSumsTest, HashStringList)
+{
+   _config->Clear("Acquire::ForceHash");
+
+   HashStringList list;
+   EXPECT_TRUE(list.empty());
+   EXPECT_FALSE(list.usable());
+   EXPECT_EQ(0, list.size());
+   EXPECT_EQ(NULL, list.find(NULL));
+   EXPECT_EQ(NULL, list.find(""));
+   EXPECT_EQ(NULL, list.find("MD5Sum"));
+
+   HashStringList list2;
+   EXPECT_FALSE(list == list2);
+   EXPECT_TRUE(list != list2);
+
+   Hashes hashes;
+   hashes.Add("The quick brown fox jumps over the lazy dog");
+   list = hashes.GetHashStringList();
+   EXPECT_FALSE(list.empty());
+   EXPECT_TRUE(list.usable());
+   EXPECT_EQ(4, list.size());
+   EXPECT_TRUE(NULL != list.find(NULL));
+   EXPECT_TRUE(NULL != list.find(""));
+   EXPECT_TRUE(NULL != list.find("MD5Sum"));
+   EXPECT_TRUE(NULL == list.find("ROT26"));
+
+   _config->Set("Acquire::ForceHash", "MD5Sum");
+   EXPECT_FALSE(list.empty());
+   EXPECT_TRUE(list.usable());
+   EXPECT_EQ(4, list.size());
+   EXPECT_TRUE(NULL != list.find(NULL));
+   EXPECT_TRUE(NULL != list.find(""));
+   EXPECT_TRUE(NULL != list.find("MD5Sum"));
+   EXPECT_TRUE(NULL == list.find("ROT26"));
+
+   _config->Set("Acquire::ForceHash", "ROT26");
+   EXPECT_FALSE(list.empty());
+   EXPECT_FALSE(list.usable());
+   EXPECT_EQ(4, list.size());
+   EXPECT_TRUE(NULL == list.find(NULL));
+   EXPECT_TRUE(NULL == list.find(""));
+   EXPECT_TRUE(NULL != list.find("MD5Sum"));
+   EXPECT_TRUE(NULL == list.find("ROT26"));
+
+   _config->Clear("Acquire::ForceHash");
+
+   list2.push_back(*list.find("MD5Sum"));
+   EXPECT_TRUE(list == list2);
+   EXPECT_FALSE(list != list2);
+
+   // introduce a mismatch to the list
+   list2.push_back(HashString("SHA1", "cacecbd74968bc90ea3342767e6b94f46ddbcafc"));
+   EXPECT_FALSE(list == list2);
+   EXPECT_TRUE(list != list2);
+
+   _config->Set("Acquire::ForceHash", "MD5Sum");
+   EXPECT_TRUE(list == list2);
+   EXPECT_FALSE(list != list2);
+
+   _config->Clear("Acquire::ForceHash");
+}