]> git.saurik.com Git - apt.git/commitdiff
Merge remote-tracking branch 'donkult/debian/experimental' into debian/experimental
authorMichael Vogt <mvo@debian.org>
Wed, 14 May 2014 16:04:48 +0000 (18:04 +0200)
committerMichael Vogt <mvo@debian.org>
Wed, 14 May 2014 16:04:48 +0000 (18:04 +0200)
Conflicts:
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h

52 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/aptconfiguration.cc
apt-pkg/contrib/hashes.cc
apt-pkg/contrib/hashes.h
apt-pkg/deb/deblistparser.cc
apt-pkg/deb/deblistparser.h
apt-pkg/deb/debmetaindex.cc
apt-pkg/deb/debrecords.cc
apt-pkg/deb/debrecords.h
apt-pkg/deb/debsrcrecords.cc
apt-pkg/indexcopy.cc
apt-pkg/indexrecords.cc
apt-pkg/indexrecords.h
apt-pkg/pkgcache.cc
apt-pkg/pkgcache.h
apt-pkg/pkgcachegen.cc
apt-pkg/pkgcachegen.h
apt-pkg/pkgrecords.h
apt-pkg/srcrecords.h
apt-pkg/tagfile.cc
apt-pkg/tagfile.h
apt-private/acqprogress.cc
cmdline/apt-extracttemplates.cc
cmdline/apt-get.cc
doc/apt.conf.5.xml
ftparchive/cachedb.cc
ftparchive/cachedb.h
ftparchive/writer.cc
ftparchive/writer.h
methods/server.cc
methods/server.h
test/integration/framework
test/integration/test-apt-ftparchive-cachedb
test/integration/test-apt-ftparchive-src-cachedb
test/integration/test-apt-sources-deb822
test/integration/test-bug-595691-empty-and-broken-archive-files
test/integration/test-bug-712435-missing-descriptions
test/integration/test-bug-722207-print-uris-even-if-very-quiet
test/integration/test-bug-745036-new-foreign-invalidates-cache [new file with mode: 0755]
test/integration/test-bug-747261-arch-specific-conflicts [new file with mode: 0755]
test/integration/test-debsrc-hashes [deleted file]
test/integration/test-http-pipeline-messup [new file with mode: 0755]
test/integration/test-kernel-helper-autoremove
test/integration/test-pdiff-usage
test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum [new file with mode: 0755]
test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
test/libapt/hashsums_test.cc
test/libapt/tagfile_test.cc

index b3d67de2cd3cec95ff2a4d55ff7ad8e3c6b0201e..99013d649eb591d765a7803ca741e32912696e67 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                                   /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-pkgAcquire::Item::Item(pkgAcquire *Owner) : Owner(Owner), FileSize(0),
-                       PartialSize(0), Mode(0), ID(0), Complete(false), 
-                       Local(false), QueueCounter(0), 
-                       ExpectedAdditionalItems(0)
+pkgAcquire::Item::Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes) :
+   Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false),
+   Local(false), QueueCounter(0), ExpectedAdditionalItems(0),
+   ExpectedHashes(ExpectedHashes)
 {
    Owner->Add(this);
    Status = StatIdle;
@@ -118,7 +129,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 +240,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)
 {
    /* XXX: Beware: Currently this class does nothing (of value) anymore ! */
    Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
@@ -252,7 +263,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 +286,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 +308,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,10 +354,10 @@ bool pkgAcqSubIndex::ParseIndex(string const &IndexFile)          /*{{{*/
  * the original packages file
  */
 pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
-                                 IndexTarget const *Target,
-                                HashString ExpectedHash,
+                                 IndexTarget const * const Target,
+                                HashStringList const &ExpectedHashes,
                                  indexRecords *MetaIndexParser)
-   : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser)
+   : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser)
 {
    
    Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
@@ -391,7 +402,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");
@@ -444,7 +455,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)          /*{{{*/
            std::clog << "Package file is up-to-date" << std::endl;
         // 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, Target, ExpectedHash, MetaIndexParser, 
+        new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser, 
                               ServerSha1, available_patches);
         return true;
       }
@@ -531,7 +542,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)          /*{{{*/
 
         if (pdiff_merge == false)
          {
-           new pkgAcqIndexDiffs(Owner, Target, ExpectedHash, MetaIndexParser,
+           new pkgAcqIndexDiffs(Owner, Target, ExpectedHashes, MetaIndexParser,
                                  ServerSha1, available_patches);
          }
          else
@@ -539,7 +550,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)          /*{{{*/
            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, Target,
-                                                       ExpectedHash,
+                                                       ExpectedHashes,
                                                        MetaIndexParser,
                                                        available_patches[i],
                                                        diffs);
@@ -566,20 +577,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);
@@ -610,11 +621,11 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,string Md5Hash
  */
 pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
                                    struct IndexTarget const * const Target,
-                                   HashString ExpectedHash,
+                                   HashStringList const &ExpectedHashes,
                                    indexRecords *MetaIndexParser,
                                   string ServerSha1,
                                   vector<DiffInfo> diffs)
-   : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser),
+   : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
      available_patches(diffs), ServerSha1(ServerSha1)
 {
    
@@ -646,7 +657,7 @@ void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * /*Cnf*/)
    if(Debug)
       std::clog << "pkgAcqIndexDiffs 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);
    Finish();
 }
                                                                        /*}}}*/
@@ -660,7 +671,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone)
       DestFile = _config->FindDir("Dir::State::lists");
       DestFile += URItoFileName(RealURI);
 
-      if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
+      if(HashSums().usable() && !HashSums().VerifyFile(DestFile))
       {
         RenameOnError(HashSumMismatch);
         Dequeue();
@@ -738,13 +749,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);
@@ -787,7 +798,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, Target,
-                             ExpectedHash, MetaIndexParser,
+                             ExpectedHashes, MetaIndexParser,
                               ServerSha1, available_patches);
         return Finish();
       } else 
@@ -798,11 +809,11 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has
 // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor                        /*{{{*/
 pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
                                              struct IndexTarget const * const Target,
-                                             HashString ExpectedHash,
+                                             HashStringList const &ExpectedHashes,
                                              indexRecords *MetaIndexParser,
                                              DiffInfo const &patch,
                                              std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
-   : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser),
+   : pkgAcqBaseIndex(Owner, Target, ExpectedHashes, MetaIndexParser),
      patch(patch), allPatches(allPatches), State(StateFetchDiff)
 {
 
@@ -845,16 +856,16 @@ void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * /*C
    // first failure means we should fallback
    State = StateErrorDiff;
    std::clog << "Falling back to normal index file acquire" << std::endl;
-   new pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser);
+   new pkgAcqIndex(Owner, Target, ExpectedHashes, MetaIndexParser);
 }
                                                                        /*}}}*/
-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);
 
@@ -890,7 +901,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;
@@ -927,7 +938,7 @@ 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)
+                        HashStringList const  &ExpectedHash, string comprExt)
    : pkgAcqBaseIndex(Owner, NULL, ExpectedHash, NULL), RealURI(URI)
 {
    if(comprExt.empty() == true)
@@ -946,14 +957,15 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
    Init(URI, URIDesc, ShortDesc);
 }
 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
-                        HashString const &ExpectedHash, indexRecords *MetaIndexParser)
+                        HashStringList const &ExpectedHash, 
+                         indexRecords *MetaIndexParser)
    : pkgAcqBaseIndex(Owner, Target, ExpectedHash, MetaIndexParser), 
      RealURI(Target->URI)
 {
    // 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)
@@ -1018,7 +1030,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);
@@ -1064,22 +1076,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;
       }
 
@@ -1201,12 +1208,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, 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));
@@ -1216,7 +1223,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);
@@ -1260,7 +1267,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,                           /*{{{*/
                             string MetaIndexShortDesc,
                             const vector<IndexTarget*>* IndexTargets,
                             indexRecords* MetaIndexParser) :
-   Item(Owner), RealURI(URI), MetaIndexURI(MetaIndexURI),
+   Item(Owner, HashStringList()), RealURI(URI), MetaIndexURI(MetaIndexURI),
    MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
    MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets)
 {
@@ -1313,7 +1320,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)
@@ -1322,10 +1329,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)
@@ -1405,9 +1412,9 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
 pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner,                    /*{{{*/
                                 string URI,string URIDesc,string ShortDesc,
                                 string SigFile,
-                                const vector<struct IndexTarget*>* IndexTargets,
+                                const vector<IndexTarget*>* IndexTargets,
                                 indexRecords* MetaIndexParser) :
-   Item(Owner), RealURI(URI), SigFile(SigFile), IndexTargets(IndexTargets),
+   Item(Owner, HashStringList()), RealURI(URI), SigFile(SigFile), IndexTargets(IndexTargets),
    MetaIndexParser(MetaIndexParser), AuthPass(false), IMSHit(false)
 {
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
@@ -1428,7 +1435,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);
@@ -1440,10 +1447,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
@@ -1614,12 +1621,12 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)                         /*{{{*/
    // at this point the real Items are loaded in the fetcher
    ExpectedAdditionalItems = 0;
 
-   for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
+   for (vector <IndexTarget*>::const_iterator Target = IndexTargets->begin();
         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)
       {
@@ -1642,14 +1649,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());
@@ -1661,14 +1670,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;
       }
@@ -1679,9 +1688,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);
    }
 }
                                                                        /*}}}*/
@@ -1834,7 +1843,7 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner,         /*{{{*/
                string const &URI, string const &URIDesc, string const &ShortDesc,
                string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc,
                string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc,
-               const vector<struct IndexTarget*>* IndexTargets,
+               const vector<IndexTarget*>* IndexTargets,
                indexRecords* MetaIndexParser) :
        pkgAcqMetaIndex(Owner, URI, URIDesc, ShortDesc, "", IndexTargets, MetaIndexParser),
        MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
@@ -1870,7 +1879,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);
@@ -1919,7 +1928,7 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
 pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
                             pkgRecords *Recs,pkgCache::VerIterator const &Version,
                             string &StoreFilename) :
-               Item(Owner), Version(Version), Sources(Sources), Recs(Recs), 
+               Item(Owner, HashStringList()), Version(Version), Sources(Sources), Recs(Recs), 
                StoreFilename(StoreFilename), Vf(Version.FileList()), 
               Trusted(false)
 {
@@ -2004,7 +2013,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
@@ -2025,31 +2033,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."),
@@ -2136,10 +2123,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)
@@ -2147,12 +2134,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;
    }
 
@@ -2224,7 +2211,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;
 }
@@ -2243,11 +2230,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, Hashes), IsIndexFile(IsIndexFile)
 {
    Retries = _config->FindI("Acquire::Retries",0);
    
@@ -2284,15 +2271,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;
    }
    
@@ -2363,7 +2351,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 35cd78afcfa02b00d4a33a87590f162207d63213..3d863874cdc1e9dad16e81f570197a870e49c8f4 100644 (file)
@@ -46,6 +46,7 @@
 class indexRecords;
 class pkgRecords;
 class pkgSourceList;
+class IndexTarget;
 
 /** \brief Represents the process by which a pkgAcquire object should  {{{
  *  retrieve a file or a collection of files.
@@ -211,12 +212,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 +239,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();};
+   HashStringList HashSums() const {return ExpectedHashes;};
+   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
@@ -284,12 +286,10 @@ class pkgAcquire::Item : public WeakPointable
     *  process, but does not place it into any fetch queues (you must
     *  manually invoke QueueURI() to do so).
     *
-    *  Initializes all fields of the item other than Owner to 0,
-    *  false, or the empty string.
-    *
     *  \param Owner The new owner of this item.
+    *  \param ExpectedHashes of the file represented by this item
     */
-   Item(pkgAcquire *Owner);
+   Item(pkgAcquire *Owner, HashStringList const &ExpectedHashes);
 
    /** \brief Remove this item from its owner's queue by invoking
     *  pkgAcquire::Remove.
@@ -309,6 +309,12 @@ class pkgAcquire::Item : public WeakPointable
     * \param state respresenting the error we encountered
     */
    bool RenameOnError(RenameOnErrorState const state);
+
+   /** \brief The HashSums of the item is supposed to have than done */
+   HashStringList ExpectedHashes;
+
+   /** \brief The item that is currently being downloaded. */
+   pkgAcquire::ItemDesc Desc;
 };
                                                                        /*}}}*/
 /** \brief Information about an index patch (aka diff). */             /*{{{*/
@@ -335,20 +341,13 @@ class pkgAcqSubIndex : public pkgAcquire::Item
    /** \brief If \b true, debugging information will be written to std::clog. */
    bool Debug;
 
-   /** \brief The item that is currently being downloaded. */
-   pkgAcquire::ItemDesc Desc;
-
-   /** \brief The Hash that this file should have after download
-    */
-   HashString ExpectedHash;
-
  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 +360,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);
 };
                                                                        /*}}}*/
 
@@ -379,16 +378,13 @@ class pkgAcqBaseIndex : public pkgAcquire::Item
    const struct IndexTarget * Target;
    indexRecords *MetaIndexParser;
 
-   /** \brief The Hash that this file should have after download
-    */
-   HashString ExpectedHash;
-
    pkgAcqBaseIndex(pkgAcquire *Owner,
                    struct IndexTarget const * const Target,
-                   HashString ExpectedHash,
+                   HashStringList const &ExpectedHashes,
                    indexRecords *MetaIndexParser)
-      : Item(Owner), Target(Target), MetaIndexParser(MetaIndexParser),
-        ExpectedHash(ExpectedHash) {};
+      : Item(Owner, ExpectedHashes), Target(Target), 
+        MetaIndexParser(MetaIndexParser) {};
+
 };
                                                                        /*}}}*/
 /** \brief An item that is responsible for fetching an index file of   {{{
@@ -406,9 +402,6 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
    /** \brief If \b true, debugging information will be written to std::clog. */
    bool Debug;
 
-   /** \brief The item that is currently being downloaded. */
-   pkgAcquire::ItemDesc Desc;
-
    /** \brief The URI of the index file to recreate at our end (either
     *  by downloading it or by applying partial patches).
     */
@@ -427,10 +420,10 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
  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.
     *
@@ -455,11 +448,11 @@ class pkgAcqDiffIndex : public pkgAcqBaseIndex
     *
     *  \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);
 };
                                                                        /*}}}*/
@@ -483,11 +476,6 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
     */
    bool Debug;
 
-   /** \brief description of the item that is currently being
-    *  downloaded.
-    */
-   pkgAcquire::ItemDesc Desc;
-
    /** \brief URI of the package index file that is being
     *  reconstructed.
     */
@@ -525,10 +513,9 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
     *  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.
     *
@@ -541,7 +528,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
     *
     *  \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.
     *
@@ -553,7 +540,7 @@ class pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
     */
    pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
                          struct IndexTarget const * const Target,
-                         HashString ExpectedHash,
+                         HashStringList const &ExpectedHash,
                          indexRecords *MetaIndexParser,
                          DiffInfo const &patch, 
                          std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches);
@@ -588,8 +575,8 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
    /** \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.
     *
@@ -605,11 +592,6 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     */
    bool Debug;
 
-   /** \brief A description of the item that is currently being
-    *  downloaded.
-    */
-   pkgAcquire::ItemDesc Desc;
-
    /** \brief The URI of the package index file that is being
     *  reconstructed.
     */
@@ -656,9 +638,9 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     */
    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.
     *
@@ -674,7 +656,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     *
     *  \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.
     *
@@ -686,7 +668,7 @@ class pkgAcqIndexDiffs : public pkgAcqBaseIndex
     */
    pkgAcqIndexDiffs(pkgAcquire *Owner,
                     struct IndexTarget const * const Target,
-                    HashString ExpectedHash,
+                    HashStringList const &ExpectedHash,
                     indexRecords *MetaIndexParser,
                    std::string ServerSha1,
                    std::vector<DiffInfo> diffs=std::vector<DiffInfo>());
@@ -721,11 +703,6 @@ class pkgAcqIndex : public pkgAcqBaseIndex
    //        the downloaded file contains the expected tag
    bool Verify;
 
-   /** \brief The download request that is currently being
-    *   processed.
-    */
-   pkgAcquire::ItemDesc Desc;
-
    /** \brief The object that is actually being fetched (minus any
     *  compression-related extensions).
     */
@@ -740,11 +717,10 @@ class pkgAcqIndex : public pkgAcqBaseIndex
    
    // 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;};
 
    /** \brief Create a pkgAcqIndex.
     *
@@ -757,7 +733,7 @@ class pkgAcqIndex : public pkgAcqBaseIndex
     *
     *  \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
@@ -766,11 +742,11 @@ class pkgAcqIndex : public pkgAcqBaseIndex
     *  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,
+               HashStringList const &ExpectedHash,
                indexRecords *MetaIndexParser);
    void Init(std::string const &URI, std::string const &URIDesc,
              std::string const &ShortDesc);
@@ -788,7 +764,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.
     *
@@ -803,8 +779,8 @@ 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);
+   pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const * const Target,
+                   HashStringList const &ExpectedHashes, indexRecords *MetaIndexParser);
 };
                                                                        /*}}}*/
 /** \brief Information about an index file. */                         /*{{{*/
@@ -872,9 +848,6 @@ class pkgAcqMetaSig : public pkgAcquire::Item
    /** \brief The last good signature file */
    std::string LastGoodSig;
 
-   /** \brief The fetch request that is currently being processed. */
-   pkgAcquire::ItemDesc Desc;
-
    /** \brief The URI of the signature file.  Unlike Desc.URI, this is
     *  never modified; it is used to determine the file that is being
     *  downloaded.
@@ -902,21 +875,21 @@ class pkgAcqMetaSig : public pkgAcquire::Item
     *
     *  \todo Why a list of pointers instead of a list of structs?
     */
-   const std::vector<struct IndexTarget*>* IndexTargets;
+   const std::vector<IndexTarget*>* IndexTargets;
 
    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 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,
                 std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc,
-                const std::vector<struct IndexTarget*>* IndexTargets,
+                const std::vector<IndexTarget*>* IndexTargets,
                 indexRecords* MetaIndexParser);
    virtual ~pkgAcqMetaSig();
 };
@@ -934,9 +907,6 @@ class pkgAcqMetaSig : public pkgAcquire::Item
 class pkgAcqMetaIndex : public pkgAcquire::Item
 {
    protected:
-   /** \brief The fetch command that is currently being processed. */
-   pkgAcquire::ItemDesc Desc;
-
    /** \brief The URI that is actually being downloaded; never
     *  modified by pkgAcqMetaIndex.
     */
@@ -950,7 +920,7 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
    std::string SigFile;
 
    /** \brief The index files to download. */
-   const std::vector<struct IndexTarget*>* IndexTargets;
+   const std::vector<IndexTarget*>* IndexTargets;
 
    /** \brief The parser for the meta-index file. */
    indexRecords* MetaIndexParser;
@@ -1004,16 +974,16 @@ 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,
                   std::string URI,std::string URIDesc, std::string ShortDesc,
                   std::string SigFile,
-                  const std::vector<struct IndexTarget*>* IndexTargets,
+                  const std::vector<IndexTarget*>* IndexTargets,
                   indexRecords* MetaIndexParser);
 };
                                                                        /*}}}*/
@@ -1040,14 +1010,14 @@ 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,
                std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc,
                std::string const &MetaIndexURI, std::string const &MetaIndexURIDesc, std::string const &MetaIndexShortDesc,
                std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc,
-               const std::vector<struct IndexTarget*>* IndexTargets,
+               const std::vector<IndexTarget*>* IndexTargets,
                indexRecords* MetaIndexParser);
    virtual ~pkgAcqMetaClearSig();
 };
@@ -1063,9 +1033,6 @@ class pkgAcqArchive : public pkgAcquire::Item
    /** \brief The package version being fetched. */
    pkgCache::VerIterator Version;
 
-   /** \brief The fetch command that is currently being processed. */
-   pkgAcquire::ItemDesc Desc;
-
    /** \brief The list of sources from which to pick archives to
     *  download this package from.
     */
@@ -1076,9 +1043,6 @@ class pkgAcqArchive : public pkgAcquire::Item
     */
    pkgRecords *Recs;
 
-   /** \brief The hashsum of this package. */
-   HashString ExpectedHash;
-
    /** \brief A location in which the actual filename of the package
     *  should be stored.
     */
@@ -1105,13 +1069,12 @@ 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 bool IsTrusted() const;
    
    /** \brief Create a new pkgAcqArchive.
     *
@@ -1144,12 +1107,6 @@ class pkgAcqArchive : public pkgAcquire::Item
  */
 class pkgAcqFile : public pkgAcquire::Item
 {
-   /** \brief The currently active download process. */
-   pkgAcquire::ItemDesc Desc;
-
-   /** \brief The hashsum of the file to download, if it is known. */
-   HashString ExpectedHash;
-
    /** \brief How many times to retry the download, set from
     *  Acquire::Retries.
     */
@@ -1162,11 +1119,10 @@ 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 std::string Custom600Headers() const;
 
    /** \brief Create a new pkgAcqFile object.
     *
@@ -1175,8 +1131,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.
@@ -1199,7 +1155,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..e4a937d1dd6de8b363998a43b24abaf48e3a2a0a 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";
    }
@@ -355,6 +351,15 @@ int pkgAcqMethod::Run(bool Single)
               Tmp->LastModified = 0;
            Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
            Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false);
+           Tmp->ExpectedHashes = HashStringList();
+           for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+           {
+              std::string tag = "Expected-";
+              tag.append(*t);
+              std::string const hash = LookupTag(Message, tag.c_str());
+              if (hash.empty() == false)
+                 Tmp->ExpectedHashes.push_back(HashString(*t, hash));
+           }
            Tmp->Next = 0;
            
            // Append it to the list
@@ -442,12 +447,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..cbf79f8609be84b6d72e204e983095696f1ce258 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:
@@ -47,14 +47,12 @@ class pkgAcqMethod
       time_t LastModified;
       bool IndexFile;
       bool FailIgnore;
+      HashStringList ExpectedHashes;
    };
    
    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 +60,7 @@ class pkgAcqMethod
       unsigned long long Size;
       unsigned long long ResumePoint;
       
-      void TakeHashes(Hashes &Hash);
+      void TakeHashes(class Hashes &Hash);
       FetchResult();
    };
 
index 047a655ced6dbddb7e10e882ff6e1e4b83b6d3bf..54be8e99fbda4d63f95b5e620477287cadcf92f2 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)
            {
@@ -525,6 +530,9 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
    Message.reserve(300);
    Message += "URI: " + Item->URI;
    Message += "\nFilename: " + Item->Owner->DestFile;
+   HashStringList const hsl = Item->Owner->HashSums();
+   for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs)
+      Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue();
    Message += Item->Owner->Custom600Headers();
    Message += "\n\n";
    
index 9982759c634d7cda87fc16df3d1e803925395114..94b6bc2468b8b5ef0e045dd4df7221afc58589fd 100644 (file)
@@ -540,7 +540,7 @@ std::string const Configuration::getBuildProfilesString() {
                return "";
        std::vector<std::string>::const_iterator p = profiles.begin();
        std::string list = *p;
-       for (; p != profiles.end(); ++p)
+       for (++p; p != profiles.end(); ++p)
           list.append(",").append(*p);
        return list;
 }
index 15f83615d7e3ccfba2a83d8ea1c37faa41b47a22..199e395f68142f6027fa35c17303e929a69767b6 100644 (file)
@@ -27,7 +27,7 @@
 #include <iostream>
                                                                        /*}}}*/
 
-const char* HashString::_SupportedHashes[] = 
+const char * HashString::_SupportedHashes[] =
 {
    "SHA512", "SHA256", "SHA1", "MD5Sum", NULL
 };
@@ -42,11 +42,16 @@ HashString::HashString(std::string Type, std::string Hash) : Type(Type), Hash(Ha
 
 HashString::HashString(std::string StringedHash)                       /*{{{*/
 {
-   // legacy: md5sum without "MD5Sum:" prefix
-   if (StringedHash.find(":") == std::string::npos && StringedHash.size() == 32)
+   if (StringedHash.find(":") == std::string::npos)
    {
-      Type = "MD5Sum";
-      Hash = StringedHash;
+      // legacy: md5sum without "MD5Sum:" prefix
+      if (StringedHash.size() == 32)
+      {
+        Type = "MD5Sum";
+        Hash = StringedHash;
+      }
+      if(_config->FindB("Debug::Hashes",false) == true)
+        std::clog << "HashString(string): invalid StringedHash " << StringedHash << std::endl;
       return;
    }
    std::string::size_type pos = StringedHash.find(":");
@@ -82,25 +87,25 @@ std::string HashString::GetHashForFile(std::string filename) const      /*{{{*/
    std::string fileHash;
 
    FileFd Fd(filename, FileFd::ReadOnly);
-   if(Type == "MD5Sum")
+   if(strcasecmp(Type.c_str(), "MD5Sum") == 0)
    {
       MD5Summation MD5;
       MD5.AddFD(Fd);
       fileHash = (std::string)MD5.Result();
    }
-   else if (Type == "SHA1")
+   else if (strcasecmp(Type.c_str(), "SHA1") == 0)
    {
       SHA1Summation SHA1;
       SHA1.AddFD(Fd);
       fileHash = (std::string)SHA1.Result();
    }
-   else if (Type == "SHA256")
+   else if (strcasecmp(Type.c_str(), "SHA256") == 0)
    {
       SHA256Summation SHA256;
       SHA256.AddFD(Fd);
       fileHash = (std::string)SHA256.Result();
    }
-   else if (Type == "SHA512")
+   else if (strcasecmp(Type.c_str(), "SHA512") == 0)
    {
       SHA512Summation SHA512;
       SHA512.AddFD(Fd);
@@ -111,26 +116,147 @@ std::string HashString::GetHashForFile(std::string filename) const      /*{{{*/
    return fileHash;
 }
                                                                        /*}}}*/
-const char** HashString::SupportedHashes()
+const char** HashString::SupportedHashes()                             /*{{{*/
 {
    return _SupportedHashes;
 }
-
-APT_PURE bool HashString::empty() const
+                                                                       /*}}}*/
+APT_PURE bool HashString::empty() const                                        /*{{{*/
 {
    return (Type.empty() || Hash.empty());
 }
+                                                                       /*}}}*/
+std::string HashString::toStr() const                                  /*{{{*/
+{
+   return Type + ":" + Hash;
+}
+                                                                       /*}}}*/
+APT_PURE bool HashString::operator==(HashString const &other) const    /*{{{*/
+{
+   return (strcasecmp(Type.c_str(), other.Type.c_str()) == 0 && Hash == other.Hash);
+}
+APT_PURE bool HashString::operator!=(HashString const &other) const
+{
+   return !(*this == other);
+}
+                                                                       /*}}}*/
+
+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 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)
+        for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs)
+           if (strcasecmp(hs->HashType().c_str(), *t) == 0)
+              return &*hs;
+      return NULL;
+   }
+   for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs)
+      if (strcasecmp(hs->HashType().c_str(), type) == 0)
+        return &*hs;
+   return NULL;
+}
+                                                                       /*}}}*/
+bool HashStringList::supported(char const * const type)                        /*{{{*/
+{
+   for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+      if (strcasecmp(*t, type) == 0)
+        return true;
+   return false;
+}
+                                                                       /*}}}*/
+bool HashStringList::push_back(const HashString &hashString)           /*{{{*/
+{
+   if (hashString.HashType().empty() == true ||
+        hashString.HashValue().empty() == true ||
+        supported(hashString.HashType().c_str()) == false)
+      return false;
+
+   // ensure that each type is added only once
+   HashString const * const hs = find(hashString.HashType().c_str());
+   if (hs != NULL)
+      return *hs == hashString;
 
-std::string HashString::toStr() const
+   list.push_back(hashString);
+   return true;
+}
+                                                                       /*}}}*/
+bool HashStringList::VerifyFile(std::string filename) const            /*{{{*/
 {
-   return Type + std::string(":") + Hash;
+   if (list.empty() == true)
+      return false;
+   HashString const * const hs = find(NULL);
+   if (hs == NULL || hs->VerifyFile(filename) == false)
+      return false;
+   return true;
 }
+                                                                       /*}}}*/
+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)
+   {
+      HashString const * const ohs = other.find(hs->HashType());
+      if (ohs == NULL)
+        continue;
+      if (*hs != *ohs)
+        return false;
+      ++matches;
+   }
+   if (matches == 0)
+      return false;
+   return true;
+}
+bool HashStringList::operator!=(HashStringList const &other) const
+{
+   return !(*this == other);
+}
+                                                                       /*}}}*/
 
-// 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);
@@ -144,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);
@@ -175,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 7a62f8a8fc687698a0e9c675e3adad94c03a68a4..caeba006d04d6a8b465ae613233ee0a607995e54 100644 (file)
@@ -17,6 +17,7 @@
 #include <apt-pkg/md5.h>
 #include <apt-pkg/sha1.h>
 #include <apt-pkg/sha2.h>
+#include <apt-pkg/macros.h>
 
 #include <cstring>
 #include <string>
@@ -41,7 +42,7 @@ class HashString
  protected:
    std::string Type;
    std::string Hash;
-   static const char* _SupportedHashes[10];
+   static const char * _SupportedHashes[10];
 
    // internal helper
    std::string GetHashForFile(std::string filename) const;
@@ -52,7 +53,8 @@ class HashString
    HashString();
 
    // get hash type used
-   std::string HashType() { return Type; };
+   std::string HashType() const { return Type; };
+   std::string HashValue() const { return Hash; };
 
    // verify the given filename against the currently loaded hash
    bool VerifyFile(std::string filename) const;
@@ -64,37 +66,160 @@ class HashString
    // helper
    std::string toStr() const;                    // convert to str as "type:hash"
    bool empty() const;
+   bool operator==(HashString const &other) const;
+   bool operator!=(HashString const &other) const;
 
    // return the list of hashes we support
    static APT_CONST const char** SupportedHashes();
 };
 
+class HashStringList
+{
+   public:
+   /** find best hash if no specific one is requested
+    *
+    * @param type of the checksum to return, can be \b NULL
+    * @return If type is \b NULL (or the empty string) it will
+    *  return the 'best' hash; otherwise the hash which was
+    *  specifically requested. If no hash is found \b NULL will be returned.
+    */
+   HashString const * find(char const * const type) const;
+   HashString const * find(std::string const &type) const { return find(type.c_str()); }
+   /** check if the given hash type is supported
+    *
+    * @param type to check
+    * @return true if supported, otherwise false
+    */
+   static APT_PURE bool supported(char const * const type);
+   /** add the given #HashString to the list
+    *
+    * @param hashString to add
+    * @return true if the hash is added because it is supported and
+    *  not already a different hash of the same type included, otherwise false
+    */
+   bool push_back(const HashString &hashString);
+   /** @return size of the list of HashStrings */
+   size_t size() const { return list.size(); }
+
+   /** take the 'best' hash and verify file with it
+    *
+    * @param filename to verify
+    * @return true if the file matches the hashsum, otherwise false
+    */
+   bool VerifyFile(std::string filename) const;
+
+   /** is the list empty ?
+    *
+    * @return \b true if the list is empty, otherwise \b false
+    */
+   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 */
+   const_iterator begin() const { return list.begin(); }
+
+   /** iterator to the end element */
+   const_iterator end() const { return list.end(); }
+
+   /** start fresh with a clear list */
+   void clear() { list.clear(); }
+
+   /** 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 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;
+
+   HashStringList() {}
+
+   // simplifying API-compatibility constructors
+   HashStringList(std::string const &hash) {
+      if (hash.empty() == false)
+        list.push_back(HashString(hash));
+   }
+   HashStringList(char const * const hash) {
+      if (hash != NULL && hash[0] != '\0')
+        list.push_back(HashString(hash));
+   }
+
+   private:
+   std::vector<HashString> list;
+};
+
 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 d5e3ccb655db9cfccbfdb4da64350c9845d6f5c7..40d3321966af2dc306539655b22f346b574d35c1 100644 (file)
@@ -194,35 +194,31 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
 /* This is to return the string describing the package in debian
    form. If this returns the blank string then the entry is assumed to
    only describe package properties */
-string debListParser::Description()
+string debListParser::Description(std::string const &lang)
 {
-   string const lang = DescriptionLanguage();
    if (lang.empty())
       return Section.FindS("Description");
    else
       return Section.FindS(string("Description-").append(lang).c_str());
 }
-                                                                        /*}}}*/
-// ListParser::DescriptionLanguage - Return the description lang string        /*{{{*/
-// ---------------------------------------------------------------------
-/* This is to return the string describing the language of
-   description. If this returns the blank string then the entry is
-   assumed to describe original description. */
-string debListParser::DescriptionLanguage()
+                                                                       /*}}}*/
+// ListParser::AvailableDescriptionLanguages                           /*{{{*/
+std::vector<std::string> debListParser::AvailableDescriptionLanguages()
 {
-   if (Section.FindS("Description").empty() == false)
-      return "";
-
-   std::vector<string> const lang = APT::Configuration::getLanguages(true);
-   for (std::vector<string>::const_iterator l = lang.begin();
-       l != lang.end(); ++l)
-      if (Section.FindS(string("Description-").append(*l).c_str()).empty() == false)
-        return *l;
-
-   return "";
+   std::vector<std::string> const understood = APT::Configuration::getLanguages();
+   std::vector<std::string> avail;
+   if (Section.Exists("Description") == true)
+      avail.push_back("");
+   for (std::vector<std::string>::const_iterator lang = understood.begin(); lang != understood.end(); ++lang)
+   {
+      std::string const tagname = "Description-" + *lang;
+      if (Section.Exists(tagname.c_str()) == true)
+        avail.push_back(*lang);
+   }
+   return avail;
 }
-                                                                        /*}}}*/
-// ListParser::Description - Return the description_md5 MD5SumValue    /*{{{*/
+                                                                       /*}}}*/
+// ListParser::Description_md5 - Return the description_md5 MD5SumValue        /*{{{*/
 // ---------------------------------------------------------------------
 /* This is to return the md5 string to allow the check if it is the right
    description. If no Description-md5 is found in the section it will be
@@ -233,7 +229,7 @@ MD5SumValue debListParser::Description_md5()
    string const value = Section.FindS("Description-md5");
    if (value.empty() == true)
    {
-      std::string const desc = Description() + "\n";
+      std::string const desc = Description("") + "\n";
       if (desc == "\n")
         return MD5SumValue();
 
index 92ec048b1086fa727a6fcdb1237a972197456435..5a2282f9c7c89d413c702ad4703ac43dc6c6aa60 100644 (file)
@@ -68,8 +68,8 @@ class debListParser : public pkgCacheGenerator::ListParser
    virtual bool ArchitectureAll();
    virtual std::string Version();
    virtual bool NewVersion(pkgCache::VerIterator &Ver);
-   virtual std::string Description();
-   virtual std::string DescriptionLanguage();
+   virtual std::string Description(std::string const &lang);
+   virtual std::vector<std::string> AvailableDescriptionLanguages();
    virtual MD5SumValue Description_md5();
    virtual unsigned short VersionHash();
 #if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
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..d2c04d8b281d29caaa7f71254f2ee7ca5d0ccfa8 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()
+// RecordParser::Hashes - return the available archive hashes          /*{{{*/
+HashStringList debRecordParser::Hashes() const
 {
-   return Section.FindS("SHA512");
+   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              /*{{{*/
@@ -125,10 +106,12 @@ string debRecordParser::RecordField(const char *fieldName)
 // RecordParser::ShortDesc - Return a 1 line description               /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-string debRecordParser::ShortDesc()
+string debRecordParser::ShortDesc(std::string const &lang)
 {
-   string Res = LongDesc();
-   string::size_type Pos = Res.find('\n');
+   string const Res = LongDesc(lang);
+   if (Res.empty() == true)
+      return "";
+   string::size_type const Pos = Res.find('\n');
    if (Pos == string::npos)
       return Res;
    return string(Res,0,Pos);
@@ -137,26 +120,44 @@ string debRecordParser::ShortDesc()
 // RecordParser::LongDesc - Return a longer description                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-string debRecordParser::LongDesc()
-{
-  string orig, dest;
+string debRecordParser::LongDesc(std::string const &lang)
+{
+   string orig;
+   if (lang.empty() == true)
+   {
+      std::vector<string> const lang = APT::Configuration::getLanguages();
+      for (std::vector<string>::const_iterator l = lang.begin();
+           l != lang.end(); ++l)
+      {
+        std::string const tagname = "Description-" + *l;
+        orig = Section.FindS(tagname.c_str());
+        if (orig.empty() == false)
+           break;
+        else if (*l == "en")
+        {
+           orig = Section.FindS("Description");
+           if (orig.empty() == false)
+              break;
+        }
+      }
+      if (orig.empty() == true)
+        orig = Section.FindS("Description");
+   }
+   else
+   {
+      std::string const tagname = "Description-" + lang;
+      orig = Section.FindS(tagname.c_str());
+      if (orig.empty() == true && lang == "en")
+        orig = Section.FindS("Description");
+   }
 
-  if (!Section.FindS("Description").empty())
-     orig = Section.FindS("Description").c_str();
-  else
-  {
-     std::vector<string> const lang = APT::Configuration::getLanguages();
-     for (std::vector<string>::const_iterator l = lang.begin();
-         orig.empty() && l != lang.end(); ++l)
-       orig = Section.FindS(string("Description-").append(*l).c_str());
-  }
+   char const * const codeset = nl_langinfo(CODESET);
+   if (strcmp(codeset,"UTF-8") != 0) {
+      string dest;
+      UTF8ToCodeset(codeset, orig, &dest);
+      return dest;
+   }
 
-  char const * const codeset = nl_langinfo(CODESET);
-  if (strcmp(codeset,"UTF-8") != 0) {
-     UTF8ToCodeset(codeset, orig, &dest);
-     orig = dest;
-   }    
-  
    return orig;
 }
                                                                        /*}}}*/
index d572bc5c20b5605cafc775dfb99aabad2a1771a3..2bd3f3c8f901ae04594de3edf1f13844f1e8268e 100644 (file)
@@ -42,17 +42,15 @@ 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();
-   virtual std::string LongDesc();
+   virtual std::string ShortDesc(std::string const &lang);
+   virtual std::string LongDesc(std::string const &lang);
    virtual std::string Name();
    virtual std::string Homepage();
 
index 7b9a828d3fba5a5d6902748bf9b6400bfeee0c1d..bf5e56ec9ee4dc8e98b78c93bbb23fcb92b53102 100644 (file)
@@ -124,85 +124,113 @@ bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List)
 {
    List.erase(List.begin(),List.end());
 
-   // map from the Hashsum field to the hashsum function,
-   // unfortunately this is not a 1:1 mapping from
-   // Hashes::SupporedHashes as e.g. Files is a historic name for the md5
-   const std::pair<const char*, const char*> SourceHashFields[] = {
-      std::make_pair( "Checksums-Sha512",  "SHA512"),
-      std::make_pair( "Checksums-Sha256",  "SHA256"),
-      std::make_pair( "Checksums-Sha1",  "SHA1"),
-      std::make_pair( "Files",  "MD5Sum"),      // historic Name
-   };
-   
-   for (unsigned int i=0;
-        i < sizeof(SourceHashFields)/sizeof(SourceHashFields[0]);
-        i++)
-   {
-      string Files = Sect.FindS(SourceHashFields[i].first);
-      if (Files.empty() == true)
-         continue;
+   // Stash the / terminated directory prefix
+   string Base = Sect.FindS("Directory");
+   if (Base.empty() == false && Base[Base.length()-1] != '/')
+      Base += '/';
 
-      // Stash the / terminated directory prefix
-      string Base = Sect.FindS("Directory");
-      if (Base.empty() == false && Base[Base.length()-1] != '/')
-         Base += '/';
+   std::vector<std::string> const compExts = APT::Configuration::getCompressorExtensions();
 
-      std::vector<std::string> const compExts = APT::Configuration::getCompressorExtensions();
+   for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
+   {
+      // derive field from checksum type
+      std::string checksumField("Checksums-");
+      if (strcmp(*type, "MD5Sum") == 0)
+        checksumField = "Files"; // historic name for MD5 checksums
+      else
+        checksumField.append(*type);
+
+      string const Files = Sect.FindS(checksumField.c_str());
+      if (Files.empty() == true)
+        continue;
 
       // Iterate over the entire list grabbing each triplet
       const char *C = Files.c_str();
       while (*C != 0)
-      {   
-         pkgSrcRecords::File F;
-         string Size;
-         
-         // Parse each of the elements
-         std::string RawHash;
-         if (ParseQuoteWord(C, RawHash) == false ||
-             ParseQuoteWord(C, Size) == false ||
-             ParseQuoteWord(C, F.Path) == false)
-            return _error->Error("Error parsing '%s' record", 
-                                 SourceHashFields[i].first);
-         // assign full hash string
-         F.Hash = HashString(SourceHashFields[i].second, RawHash).toStr();
-         // API compat hack 
-         if(strcmp(SourceHashFields[i].second, "MD5Sum") == 0)
-            F.MD5Hash = RawHash;
-         
-         // Parse the size and append the directory
-         F.Size = atoi(Size.c_str());
-         F.Path = Base + F.Path;
-         
-         // Try to guess what sort of file it is we are getting.
-         string::size_type Pos = F.Path.length()-1;
-         while (1)
-         {
-            string::size_type Tmp = F.Path.rfind('.',Pos);
-            if (Tmp == string::npos)
-               break;
-            if (F.Type == "tar") {
-               // source v3 has extension 'debian.tar.*' instead of 'diff.*'
-               if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
-                  F.Type = "diff";
-               break;
-            }
-            F.Type = string(F.Path,Tmp+1,Pos-Tmp);
-            
-            if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
-                F.Type == "tar")
-            {
-               Pos = Tmp-1;
-               continue;
-            }
-        
-            break;
-         }
-      
-         List.push_back(F);
+      {
+        string hash, size, path;
+
+        // Parse each of the elements
+        if (ParseQuoteWord(C, hash) == false ||
+              ParseQuoteWord(C, size) == false ||
+              ParseQuoteWord(C, path) == false)
+           return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str());
+
+        HashString const hashString(*type, hash);
+        if (Base.empty() == false)
+           path = Base + path;
+
+        // look if we have a record for this file already
+        std::vector<pkgSrcRecords::File>::iterator file = List.begin();
+        for (; file != List.end(); ++file)
+           if (file->Path == path)
+              break;
+
+        // we have it already, store the new hash and be done
+        if (file != List.end())
+        {
+#if __GNUC__ >= 4
+       // set for compatibility only, so warn users not us
+       #pragma GCC diagnostic push
+       #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+           if (checksumField == "Files")
+              file->MD5Hash = hash;
+#if __GNUC__ >= 4
+       #pragma GCC diagnostic pop
+#endif
+           // an error here indicates that we have two different hashes for the same file
+           if (file->Hashes.push_back(hashString) == false)
+              return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str());
+           continue;
+        }
+
+        // we haven't seen this file yet
+        pkgSrcRecords::File F;
+        F.Path = path;
+        F.Size = strtoull(size.c_str(), NULL, 10);
+        F.Hashes.push_back(hashString);
+
+#if __GNUC__ >= 4
+       // set for compatibility only, so warn users not us
+       #pragma GCC diagnostic push
+       #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+        if (checksumField == "Files")
+           F.MD5Hash = hash;
+#if __GNUC__ >= 4
+       #pragma GCC diagnostic pop
+#endif
+
+        // Try to guess what sort of file it is we are getting.
+        string::size_type Pos = F.Path.length()-1;
+        while (1)
+        {
+           string::size_type Tmp = F.Path.rfind('.',Pos);
+           if (Tmp == string::npos)
+              break;
+           if (F.Type == "tar") {
+              // source v3 has extension 'debian.tar.*' instead of 'diff.*'
+              if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
+                 F.Type = "diff";
+              break;
+           }
+           F.Type = string(F.Path,Tmp+1,Pos-Tmp);
+
+           if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
+                 F.Type == "tar")
+           {
+              Pos = Tmp-1;
+              continue;
+           }
+
+           break;
+        }
+        List.push_back(F);
       }
-      break;
    }
-   return (List.size() > 0);
+
+   return true;
 }
                                                                        /*}}}*/
 // SrcRecordParser::~SrcRecordParser - Destructor                      /*{{{*/
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 5088712a27c871ba6dbcc9c455a01ad7d8581f9a..2b615363487ef34d6ebca301d9c75283f31769f1 100644 (file)
@@ -168,15 +168,23 @@ bool pkgCache::ReMap(bool const &Errorchecks)
    if (Map.Size() < HeaderP->CacheFileSize)
       return _error->Error(_("The package cache file is corrupted, it is too small"));
 
+   if (HeaderP->VerSysName == 0 || HeaderP->Architecture == 0 || HeaderP->Architectures == 0)
+      return _error->Error(_("The package cache file is corrupted"));
+
    // Locate our VS..
-   if (HeaderP->VerSysName == 0 ||
-       (VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
+   if ((VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
       return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
 
-   // Chcek the arhcitecture
-   if (HeaderP->Architecture == 0 ||
-       _config->Find("APT::Architecture") != StrP + HeaderP->Architecture)
-      return _error->Error(_("The package cache was built for a different architecture"));
+   // Check the architecture
+   std::vector<std::string> archs = APT::Configuration::getArchitectures();
+   std::vector<std::string>::const_iterator a = archs.begin();
+   std::string list = *a;
+   for (++a; a != archs.end(); ++a)
+      list.append(",").append(*a);
+   if (_config->Find("APT::Architecture") != StrP + HeaderP->Architecture ||
+        list != StrP + HeaderP->Architectures)
+      return _error->Error(_("The package cache was built for different architectures: %s vs %s"), StrP + HeaderP->Architectures, list.c_str());
+
    return true;
 }
                                                                        /*}}}*/
@@ -822,7 +830,7 @@ int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
 // VerIterator::Downloadable - Checks if the version is downloadable   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgCache::VerIterator::Downloadable() const
+APT_PURE bool pkgCache::VerIterator::Downloadable() const
 {
    VerFileIterator Files = FileList();
    for (; Files.end() == false; ++Files)
@@ -835,7 +843,7 @@ bool pkgCache::VerIterator::Downloadable() const
 // ---------------------------------------------------------------------
 /* This checks to see if any of the versions files are not NotAutomatic. 
    True if this version is selectable for automatic installation. */
-bool pkgCache::VerIterator::Automatic() const
+APT_PURE bool pkgCache::VerIterator::Automatic() const
 {
    VerFileIterator Files = FileList();
    for (; Files.end() == false; ++Files)
index 151de7d25e89dcdf3aba96b9a3615ccbbef07ba3..22dc6218cd85811f53a70e6e6e295e2ae4553156 100644 (file)
@@ -286,8 +286,10 @@ struct pkgCache::Header
    map_ptrloc StringList;
    /** \brief String representing the version system used */
    map_ptrloc VerSysName;
-   /** \brief Architecture(s) the cache was built against */
+   /** \brief native architecture the cache was built against */
    map_ptrloc Architecture;
+   /** \brief all architectures the cache was built against */
+   map_ptrloc Architectures;
    /** \brief The maximum size of a raw entry from the original Package file */
    unsigned long MaxVerFileSize;
    /** \brief The maximum size of a raw entry from the original Translation file */
index 810f0b0225061597b29e278d0c9c713704940e9c..ac1cea0eb60f804d3d30235ed1f3d5a5f0246fab 100644 (file)
@@ -74,13 +74,31 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
       // Starting header
       *Cache.HeaderP = pkgCache::Header();
       map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
+      if (unlikely(idxVerSysName == 0))
+        return;
       Cache.HeaderP->VerSysName = idxVerSysName;
       // this pointer is set in ReMap, but we need it now for WriteUniqString
       Cache.StringItemP = (pkgCache::StringItem *)Map.Data();
       map_ptrloc const idxArchitecture = WriteUniqString(_config->Find("APT::Architecture"));
-      Cache.HeaderP->Architecture = idxArchitecture;
-      if (unlikely(idxVerSysName == 0 || idxArchitecture == 0))
+      if (unlikely(idxArchitecture == 0))
         return;
+      Cache.HeaderP->Architecture = idxArchitecture;
+
+      std::vector<std::string> archs = APT::Configuration::getArchitectures();
+      if (archs.size() > 1)
+      {
+        std::vector<std::string>::const_iterator a = archs.begin();
+        std::string list = *a;
+        for (++a; a != archs.end(); ++a)
+           list.append(",").append(*a);
+        map_ptrloc const idxArchitectures = WriteStringInMap(list);
+        if (unlikely(idxArchitectures == 0))
+           return;
+        Cache.HeaderP->Architectures = idxArchitectures;
+      }
+      else
+        Cache.HeaderP->Architectures = idxArchitecture;
+
       Cache.ReMap();
    }
    else
@@ -302,10 +320,9 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
 
    // Find the right version to write the description
    MD5SumValue CurMd5 = List.Description_md5();
-   if (CurMd5.Value().empty() == true || List.Description().empty() == true)
+   if (CurMd5.Value().empty() == true && List.Description("").empty() == true)
       return true;
-   std::string CurLang = List.DescriptionLanguage();
-
+   std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
    for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
    {
       pkgCache::DescIterator VerDesc = Ver.DescriptionList();
@@ -314,31 +331,16 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
       if (VerDesc.end() == true || MD5SumValue(VerDesc.md5()) != CurMd5)
         continue;
 
-      // don't add a new description if we have one for the given
-      // md5 && language
-      if (IsDuplicateDescription(VerDesc, CurMd5, CurLang) == true)
-        continue;
-
-      pkgCache::DescIterator Desc;
-      Dynamic<pkgCache::DescIterator> DynDesc(Desc);
-
-      map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, VerDesc->md5sum);
-      if (unlikely(descindex == 0 && _error->PendingError()))
-        return _error->Error(_("Error occurred while processing %s (%s%d)"),
-                             Pkg.Name(), "NewDescription", 1);
-
-      Desc->ParentPkg = Pkg.Index();
-
-      // we add at the end, so that the start is constant as we need
-      // that to be able to efficiently share these lists
-      VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
-      for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
-      map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
-      *LastNextDesc = descindex;
+      map_ptrloc md5idx = VerDesc->md5sum;
+      for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
+      {
+        // don't add a new description if we have one for the given
+        // md5 && language
+        if (IsDuplicateDescription(VerDesc, CurMd5, *CurLang) == true)
+           continue;
 
-      if (NewFileDesc(Desc,List) == false)
-        return _error->Error(_("Error occurred while processing %s (%s%d)"),
-                             Pkg.Name(), "NewFileDesc", 1);
+        AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx);
+      }
 
       // we can stop here as all "same" versions will share the description
       break;
@@ -486,11 +488,10 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
       return true;
    }
 
-   /* Record the Description (it is not translated) */
+   /* Record the Description(s) based on their master md5sum */
    MD5SumValue CurMd5 = List.Description_md5();
-   if (CurMd5.Value().empty() == true || List.Description().empty() == true)
+   if (CurMd5.Value().empty() == true && List.Description("").empty() == true)
       return true;
-   std::string CurLang = List.DescriptionLanguage();
 
    /* Before we add a new description we first search in the group for
       a version with a description of the same MD5 - if so we reuse this
@@ -501,28 +502,44 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
       for (pkgCache::VerIterator V = P.VersionList();
           V.end() == false; ++V)
       {
-        if (IsDuplicateDescription(V.DescriptionList(), CurMd5, "") == false)
+        if (V->DescriptionList == 0 || MD5SumValue(V.DescriptionList().md5()) != CurMd5)
            continue;
         Ver->DescriptionList = V->DescriptionList;
-        return true;
       }
    }
 
-   // We haven't found reusable descriptions, so add the first description
-   pkgCache::DescIterator Desc = Ver.DescriptionList();
+   // We haven't found reusable descriptions, so add the first description(s)
+   map_ptrloc md5idx = Ver->DescriptionList == 0 ? 0 : Ver.DescriptionList()->md5sum;
+   std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
+   for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
+      if (AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx) == false)
+        return false;
+   return true;
+}
+                                                                       /*}}}*/
+bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver, std::string const &lang, MD5SumValue const &CurMd5, map_ptrloc &md5idx) /*{{{*/
+{
+   pkgCache::DescIterator Desc;
    Dynamic<pkgCache::DescIterator> DynDesc(Desc);
 
-   map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, 0);
+   map_ptrloc const descindex = NewDescription(Desc, lang, CurMd5, md5idx);
    if (unlikely(descindex == 0 && _error->PendingError()))
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
-                          Pkg.Name(), "NewDescription", 2);
+           Ver.ParentPkg().Name(), "NewDescription", 1);
+
+   md5idx = Desc->md5sum;
+   Desc->ParentPkg = Ver.ParentPkg().Index();
 
-   Desc->ParentPkg = Pkg.Index();
-   Ver->DescriptionList = descindex;
+   // we add at the end, so that the start is constant as we need
+   // that to be able to efficiently share these lists
+   pkgCache::DescIterator VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
+   for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
+   map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
+   *LastNextDesc = descindex;
 
    if (NewFileDesc(Desc,List) == false)
       return _error->Error(_("Error occurred while processing %s (%s%d)"),
-                          Pkg.Name(), "NewFileDesc", 2);
+           Ver.ParentPkg().Name(), "NewFileDesc", 1);
 
    return true;
 }
index 1e1a710267341f72f8747286213e27138e4eb8a7..d275c1e4290ee9f22b0558fae9871cb16146c827 100644 (file)
@@ -125,6 +125,9 @@ class pkgCacheGenerator                                                     /*{{{*/
    APT_HIDDEN bool AddImplicitDepends(pkgCache::GrpIterator &G, pkgCache::PkgIterator &P,
                           pkgCache::VerIterator &V);
    APT_HIDDEN bool AddImplicitDepends(pkgCache::VerIterator &V, pkgCache::PkgIterator &D);
+
+   APT_HIDDEN bool AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver,
+        std::string const &lang, MD5SumValue const &CurMd5, map_ptrloc &md5idx);
 };
                                                                        /*}}}*/
 // This is the abstract package list parser class.                     /*{{{*/
@@ -160,8 +163,8 @@ class pkgCacheGenerator::ListParser
    virtual bool ArchitectureAll() = 0;
    virtual std::string Version() = 0;
    virtual bool NewVersion(pkgCache::VerIterator &Ver) = 0;
-   virtual std::string Description() = 0;
-   virtual std::string DescriptionLanguage() = 0;
+   virtual std::string Description(std::string const &lang) = 0;
+   virtual std::vector<std::string> AvailableDescriptionLanguages() = 0;
    virtual MD5SumValue Description_md5() = 0;
    virtual unsigned short VersionHash() = 0;
    /** compare currently parsed version with given version
index b5237b3a08052ef337ed11e31644e3df7a948e16..a902da8b881abf6a80c2db73eeac8eb08f709563 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,17 +58,39 @@ 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();};
-   virtual std::string LongDesc() {return std::string();};
+   /** return short description in language from record.
+    *
+    * @see #LongDesc
+    */
+   virtual std::string ShortDesc(std::string const &/*lang*/) {return std::string();};
+   /** return long description in language from record.
+    *
+    * If \b lang is empty the "best" available language will be
+    * returned as determined by the APT::Languages configuration.
+    * If a (requested) language can't be found in this record an empty
+    * string will be returned.
+    */
+   virtual std::string LongDesc(std::string const &/*lang*/) {return std::string();};
+   std::string ShortDesc() {return ShortDesc("");};
+   std::string LongDesc() {return LongDesc("");};
+
    virtual std::string Name() {return std::string();};
    virtual std::string Homepage() {return std::string();}
 
@@ -77,6 +101,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 58a5e242fda88ed24b8b4ac61a5a30921f96a65e..69b3cfd9996c1e34182f2feff57ba172485152a6 100644 (file)
@@ -14,6 +14,7 @@
 #define PKGLIB_SRCRECORDS_H
 
 #include <apt-pkg/macros.h>
+#include <apt-pkg/hashes.h>
 
 #include <string>
 #include <vector>
@@ -29,16 +30,24 @@ class pkgSrcRecords
 {
    public:
 
+#if __GNUC__ >= 4
+       // ensure that con- & de-structor don't trigger this warning
+       #pragma GCC diagnostic push
+       #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
    // Describes a single file
    struct File
    {
-      std::string MD5Hash;
-      std::string Hash;
-      unsigned long Size;
       std::string Path;
       std::string Type;
+      unsigned long long Size;
+      HashStringList Hashes;
+      APT_DEPRECATED std::string MD5Hash;
    };
-   
+#if __GNUC__ >= 4
+       #pragma GCC diagnostic pop
+#endif
+
    // Abstract parser for each source record
    class Parser
    {
index 009ed7d744d2f3b9977ae07136453e4c10ad5589..52f4da2d5864fe5dd459d568b474176e15b20931 100644 (file)
@@ -47,6 +47,22 @@ public:
    unsigned long long Size;
 };
 
+static unsigned long AlphaHash(const char *Text, size_t Length)                /*{{{*/
+{
+   /* This very simple hash function for the last 8 letters gives
+      very good performance on the debian package files */
+   if (Length > 8)
+   {
+    Text += (Length - 8);
+    Length = 8;
+   }
+   unsigned long Res = 0;
+   for (size_t i = 0; i < Length; ++i)
+      Res = ((unsigned long)(Text[i]) & 0xDF) ^ (Res << 1);
+   return Res & 0xFF;
+}
+                                                                       /*}}}*/
+
 // TagFile::pkgTagFile - Constructor                                   /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -139,18 +155,23 @@ bool pkgTagFile::Resize(unsigned long long const newSize)
  */
 bool pkgTagFile::Step(pkgTagSection &Tag)
 {
-   while (Tag.Scan(d->Start,d->End - d->Start) == false)
+   if(Tag.Scan(d->Start,d->End - d->Start) == false)
    {
-      if (Fill() == false)
-        return false;
-      
-      if(Tag.Scan(d->Start,d->End - d->Start))
-        break;
+      do
+      {
+        if (Fill() == false)
+           return false;
+
+        if(Tag.Scan(d->Start,d->End - d->Start, false))
+           break;
+
+        if (Resize() == false)
+           return _error->Error(_("Unable to parse package file %s (1)"),
+                 d->Fd.Name().c_str());
 
-      if (Resize() == false)
-        return _error->Error(_("Unable to parse package file %s (1)"),
-                              d->Fd.Name().c_str());
+      } while (Tag.Scan(d->Start,d->End - d->Start, false) == false);
    }
+
    d->Start += Tag.size();
    d->iOffset += Tag.size();
 
@@ -244,7 +265,7 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
    if (Fill() == false)
       return false;
    
-   if (Tag.Scan(d->Start, d->End - d->Start) == false)
+   if (Tag.Scan(d->Start, d->End - d->Start, false) == false)
       return _error->Error(_("Unable to parse package file %s (2)"),d->Fd.Name().c_str());
    
    return true;
@@ -254,27 +275,46 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
 // ---------------------------------------------------------------------
 /* */
 pkgTagSection::pkgTagSection()
-   : Section(0), TagCount(0), d(NULL), Stop(0)
+   : Section(0), d(NULL), Stop(0)
 {
-   memset(&Indexes, 0, sizeof(Indexes));
-   memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+   memset(&LookupTable, 0, sizeof(LookupTable));
 }
                                                                        /*}}}*/
 // TagSection::Scan - Scan for the end of the header information       /*{{{*/
-// ---------------------------------------------------------------------
-/* This looks for the first double new line in the data stream.
-   It also indexes the tags in the section. */
-bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
+bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength, bool const Restart)
 {
+   Section = Start;
    const char *End = Start + MaxLength;
-   Stop = Section = Start;
-   memset(AlphaIndexes,0,sizeof(AlphaIndexes));
+
+   if (Restart == false && Tags.empty() == false)
+   {
+      Stop = Section + Tags.back().StartTag;
+      if (End <= Stop)
+        return false;
+      Stop = (const char *)memchr(Stop,'\n',End - Stop);
+      if (Stop == NULL)
+        return false;
+      ++Stop;
+   }
+   else
+   {
+      Stop = Section;
+      if (Tags.empty() == false)
+      {
+        memset(&LookupTable, 0, sizeof(LookupTable));
+        Tags.clear();
+      }
+      Tags.reserve(0x100);
+   }
+   size_t TagCount = Tags.size();
 
    if (Stop == 0)
       return false;
 
-   TagCount = 0;
-   while (TagCount+1 < sizeof(Indexes)/sizeof(Indexes[0]) && Stop < End)
+   TagData lastTagData(0);
+   lastTagData.EndTag = 0;
+   unsigned long lastTagHash = 0;
+   while (Stop < End)
    {
       TrimRecord(true,End);
 
@@ -286,12 +326,39 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
       // Start a new index and add it to the hash
       if (isspace(Stop[0]) == 0)
       {
-        Indexes[TagCount++] = Stop - Section;
-        AlphaIndexes[AlphaHash(Stop,End)] = TagCount;
+        // store the last found tag
+        if (lastTagData.EndTag != 0)
+        {
+           if (LookupTable[lastTagHash] != 0)
+              lastTagData.NextInBucket = LookupTable[lastTagHash];
+           LookupTable[lastTagHash] = TagCount;
+           Tags.push_back(lastTagData);
+        }
+
+        ++TagCount;
+        lastTagData = TagData(Stop - Section);
+        // find the colon separating tag and value
+        char const * Colon = (char const *) memchr(Stop, ':', End - Stop);
+        if (Colon == NULL)
+           return false;
+        // find the end of the tag (which might or might not be the colon)
+        char const * EndTag = Colon;
+        --EndTag;
+        for (; EndTag > Stop && isspace(*EndTag) != 0; --EndTag)
+           ;
+        ++EndTag;
+        lastTagData.EndTag = EndTag - Section;
+        lastTagHash = AlphaHash(Stop, EndTag - Stop);
+        // find the beginning of the value
+        Stop = Colon + 1;
+        for (; isspace(*Stop) != 0; ++Stop);
+        if (Stop >= End)
+           return false;
+        lastTagData.StartValue = Stop - Section;
       }
 
       Stop = (const char *)memchr(Stop,'\n',End - Stop);
-      
+
       if (Stop == 0)
         return false;
 
@@ -302,7 +369,16 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
       // Double newline marks the end of the record
       if (Stop+1 < End && Stop[1] == '\n')
       {
-        Indexes[TagCount] = Stop - Section;
+        if (lastTagData.EndTag != 0)
+        {
+           if (LookupTable[lastTagHash] != 0)
+              lastTagData.NextInBucket = LookupTable[lastTagHash];
+           LookupTable[lastTagHash] = TagCount;
+           Tags.push_back(lastTagData);
+        }
+
+        TagData const td(Stop - Section);
+        Tags.push_back(td);
         TrimRecord(false,End);
         return true;
       }
@@ -331,8 +407,8 @@ void pkgTagSection::Trim()
    for (; Stop > Section + 2 && (Stop[-2] == '\n' || Stop[-2] == '\r'); Stop--);
 }
                                                                        /*}}}*/
-// TagSection::Exists - return True if a tag exists                    /*{{{*/
-bool pkgTagSection::Exists(const char* const Tag)
+// TagSection::Exists - return True if a tag exists                    /*{{{*/
+bool pkgTagSection::Exists(const char* const Tag) const
 {
    unsigned int tmp;
    return Find(Tag, tmp);
@@ -343,73 +419,43 @@ bool pkgTagSection::Exists(const char* const Tag)
 /* This searches the section for a tag that matches the given string. */
 bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const
 {
-   unsigned int Length = strlen(Tag);
-   unsigned int I = AlphaIndexes[AlphaHash(Tag)];
-   if (I == 0)
+   size_t const Length = strlen(Tag);
+   unsigned int Bucket = LookupTable[AlphaHash(Tag, Length)];
+   if (Bucket == 0)
       return false;
-   I--;
-   
-   for (unsigned int Counter = 0; Counter != TagCount; Counter++, 
-       I = (I+1)%TagCount)
+
+   for (; Bucket != 0; Bucket = Tags[Bucket - 1].NextInBucket)
    {
-      const char *St;
-      St = Section + Indexes[I];
-      if (strncasecmp(Tag,St,Length) != 0)
+      if ((Tags[Bucket - 1].EndTag - Tags[Bucket - 1].StartTag) != Length)
         continue;
 
-      // Make sure the colon is in the right place
-      const char *C = St + Length;
-      for (; isspace(*C) != 0; C++);
-      if (*C != ':')
+      char const * const St = Section + Tags[Bucket - 1].StartTag;
+      if (strncasecmp(Tag,St,Length) != 0)
         continue;
-      Pos = I;
+
+      Pos = Bucket - 1;
       return true;
    }
 
    Pos = 0;
    return false;
 }
-                                                                       /*}}}*/
-// TagSection::Find - Locate a tag                                     /*{{{*/
-// ---------------------------------------------------------------------
-/* This searches the section for a tag that matches the given string. */
 bool pkgTagSection::Find(const char *Tag,const char *&Start,
                         const char *&End) const
 {
-   unsigned int Length = strlen(Tag);
-   unsigned int I = AlphaIndexes[AlphaHash(Tag)];
-   if (I == 0)
+   unsigned int Pos;
+   if (Find(Tag, Pos) == false)
       return false;
-   I--;
-   
-   for (unsigned int Counter = 0; Counter != TagCount; Counter++, 
-       I = (I+1)%TagCount)
-   {
-      const char *St;
-      St = Section + Indexes[I];
-      if (strncasecmp(Tag,St,Length) != 0)
-        continue;
-      
-      // Make sure the colon is in the right place
-      const char *C = St + Length;
-      for (; isspace(*C) != 0; C++);
-      if (*C != ':')
-        continue;
 
-      // Strip off the gunk from the start end
-      Start = C;
-      End = Section + Indexes[I+1];
-      if (Start >= End)
-        return _error->Error("Internal parsing error");
-      
-      for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++);
-      for (; isspace(End[-1]) != 0 && End > Start; End--);
-      
-      return true;
-   }
-   
-   Start = End = 0;
-   return false;
+   Start = Section + Tags[Pos].StartValue;
+   // Strip off the gunk from the end
+   End = Section + Tags[Pos + 1].StartTag;
+   if (unlikely(Start > End))
+      return _error->Error("Internal parsing error");
+
+   for (; isspace(End[-1]) != 0 && End > Start; --End);
+
+   return true;
 }
                                                                        /*}}}*/
 // TagSection::FindS - Find a string                                   /*{{{*/
@@ -504,6 +550,13 @@ bool pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag,
    return true;
 }
                                                                        /*}}}*/
+APT_PURE unsigned int pkgTagSection::Count() const {                   /*{{{*/
+   if (Tags.empty() == true)
+      return 0;
+   // the last element is just marking the end and isn't a real one
+   return Tags.size() - 1;
+}
+                                                                       /*}}}*/
 // TFRewrite - Rewrite a control record                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* This writes the control record to stdout rewriting it as necessary. The
index d1a24ba45132580d0d3848afe98323e5fa8512d9..b0cfab75986edc6d769e39bfe7328ecf3460b815 100644 (file)
@@ -25,6 +25,8 @@
 #include <stdio.h>
 
 #include <string>
+#include <vector>
+#include <list>
 
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/fileutl.h>
@@ -35,23 +37,20 @@ class FileFd;
 class pkgTagSection
 {
    const char *Section;
-   // We have a limit of 256 tags per section.
-   unsigned int Indexes[256];
-   unsigned int AlphaIndexes[0x100];
-   unsigned int TagCount;
+   struct TagData {
+      unsigned int StartTag;
+      unsigned int EndTag;
+      unsigned int StartValue;
+      unsigned int NextInBucket;
+
+      TagData(unsigned int const StartTag) : StartTag(StartTag), NextInBucket(0) {}
+   };
+   std::vector<TagData> Tags;
+   unsigned int LookupTable[0x100];
+
    // dpointer placeholder (for later in case we need it)
    void *d;
 
-   /* This very simple hash function for the last 8 letters gives
-      very good performance on the debian package files */
-   inline static unsigned long AlphaHash(const char *Text, const char *End = 0)
-   {
-      unsigned long Res = 0;
-      for (; Text != End && *Text != ':' && *Text != 0; Text++)
-        Res = ((unsigned long)(*Text) & 0xDF) ^ (Res << 1);
-      return Res & 0xFF;
-   }
-
    protected:
    const char *Stop;
 
@@ -69,17 +68,39 @@ class pkgTagSection
                 unsigned long Flag) const;
    bool static FindFlag(unsigned long &Flags, unsigned long Flag,
                                const char* Start, const char* Stop);
-   bool Scan(const char *Start,unsigned long MaxLength);
+
+   /** \brief searches the boundaries of the current section
+    *
+    * While parameter Start marks the beginning of the section, this method
+    * will search for the first double newline in the data stream which marks
+    * the end of the section. It also does a first pass over the content of
+    * the section parsing it as encountered for processing later on by Find
+    *
+    * @param Start is the beginning of the section
+    * @param MaxLength is the size of valid data in the stream pointed to by Start
+    * @param Restart if enabled internal state will be cleared, otherwise it is
+    *  assumed that now more data is available in the stream and the parsing will
+    *  start were it encountered insufficent data the last time.
+    *
+    * @return \b true if section end was found, \b false otherwise.
+    *  Beware that internal state will be inconsistent if \b false is returned!
+    */
+   APT_MUSTCHECK bool Scan(const char *Start, unsigned long MaxLength, bool const Restart = true);
    inline unsigned long size() const {return Stop - Section;};
    void Trim();
    virtual void TrimRecord(bool BeforeRecord, const char* &End);
-   
-   inline unsigned int Count() const {return TagCount;};
-   bool Exists(const char* const Tag);
+
+   /** \brief amount of Tags in the current section
+    *
+    * Note: if a Tag is mentioned repeatly it will be counted multiple
+    * times, but only the last occurance is available via Find methods.
+    */
+   unsigned int Count() const;
+   bool Exists(const char* const Tag) const;
+
    inline void Get(const char *&Start,const char *&Stop,unsigned int I) const
-                   {Start = Section + Indexes[I]; Stop = Section + Indexes[I+1];}
-           
+                   {Start = Section + Tags[I].StartTag; Stop = Section + Tags[I+1].StartTag;}
+
    inline void GetSection(const char *&Start,const char *&Stop) const
    {
       Start = Section;
index 4bcfd8f0040dd06a75a1ab836920b71d102f51d1..17a12799cf6dbb0430677af5b99fc337af3d5fb5 100644 (file)
@@ -140,6 +140,9 @@ void AcqTextStatus::Stop()
    if (Quiet <= 0)
       cout << '\r' << BlankLine << '\r' << flush;
 
+   if (_config->FindB("quiet::NoStatistic", false) == true)
+      return;
+
    if (FetchedBytes != 0 && _error->PendingError() == false)
       ioprintf(cout,_("Fetched %sB in %s (%sB/s)\n"),
               SizeToStr(FetchedBytes).c_str(),
index e4428e05154e26ad2b4cef7d36a0423965702242..7be59b9f81cae3cf7b1b7a2002fa843b308209e4 100644 (file)
@@ -103,10 +103,12 @@ bool DebFile::DoItem(Item &I, int &Fd)
        if (strcmp(I.Name, "control") == 0)
        {
                delete [] Control;
-               Control = new char[I.Size+1];
-               Control[I.Size] = 0;
+               Control = new char[I.Size+3];
+               Control[I.Size] = '\n';
+               Control[I.Size + 1] = '\n';
+               Control[I.Size + 2] = '\0';
                Which = IsControl;
-               ControlLen = I.Size;
+               ControlLen = I.Size + 3;
                // make it call the Process method below. this is so evil
                Fd = -2;
        }
@@ -162,9 +164,10 @@ bool DebFile::Process(Item &/*I*/, const unsigned char *data,
 bool DebFile::ParseInfo()
 {
        if (Control == NULL) return false;
-       
+
        pkgTagSection Section;
-       Section.Scan(Control, ControlLen);
+       if (Section.Scan(Control, ControlLen) == false)
+               return false;
 
        Package = Section.FindS("Package");
        Version = GetInstalledVer(Package);
index 1148dbbf38bb73686f2adf5e20a7b4fe64a12e45..3388351d9b29cf9a435ec0c4068d55e4a0517ede 100644 (file)
@@ -828,20 +828,25 @@ static bool DoSource(CommandLine &CmdL)
         queued.insert(Last->Index().ArchiveURI(I->Path));
 
         // check if we have a file with that md5 sum already localy
-        if(!I->Hash.empty() && FileExists(flNotDir(I->Path)))  
-        {
-            HashString hash_string = HashString(I->Hash);
-            if(hash_string.VerifyFile(flNotDir(I->Path)))
+        std::string localFile = flNotDir(I->Path);
+        if (FileExists(localFile) == true)
+           if(I->Hashes.VerifyFile(localFile) == true)
            {
               ioprintf(c1out,_("Skipping already downloaded file '%s'\n"),
-                       flNotDir(I->Path).c_str());
+                       localFile.c_str());
               continue;
            }
+
+        // see if we have a hash (Acquire::ForceHash is the only way to have none)
+        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());
+           continue;
         }
 
         new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
-                       I->Hash,I->Size,
-                       Last->Index().SourceInfo(*Last,*I),Src);
+                       I->Hashes, I->Size, Last->Index().SourceInfo(*Last,*I), Src);
       }
    }
    
index fcbf20dac0d17ac8bcd75a4878bc107e28484cdd..21878e2626d7f0eb354585e30a70cb1ef04f0bbe 100644 (file)
@@ -390,9 +390,9 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      <para>The setting <literal>Acquire::http::Pipeline-Depth</literal> can be used to
      enable HTTP pipelining (RFC 2616 section 8.1.2.2) which can be beneficial e.g. on
      high-latency connections. It specifies how many requests are sent in a pipeline.
-     Previous APT versions had a default of 10 for this setting, but the default value
-     is now 0 (= disabled) to avoid problems with the ever-growing amount of webservers
-     and proxies which choose to not conform to the HTTP/1.1 specification.</para>
+     APT tries to detect and workaround misbehaving webservers and proxies at runtime, but
+     if you know that yours does not conform to the HTTP/1.1 specification pipelining can
+     be disabled by setting the value to 0. It is enabled by default with the value 10.</para>
 
      <para><literal>Acquire::http::AllowRedirect</literal> controls whether APT will follow
      redirects, which is enabled by default.</para>
index e56deae1e7556bebaff869164c8d826d5dd574e9..be54ea62c1128ec83cc4d547c142a1b50922418d 100644 (file)
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/debfile.h>
 #include <apt-pkg/gpgv.h>
+#include <apt-pkg/hashes.h>
 
 #include <netinet/in.h>       // htonl, etc
 #include <ctype.h>
 #include <stddef.h>
 #include <sys/stat.h>
+#include <strings.h>
 
 #include "cachedb.h"
 
@@ -206,15 +208,10 @@ bool CacheDB::GetCurStat()
                                                                        /*}}}*/
 // CacheDB::GetFileInfo - Get all the info about the file              /*{{{*/
 // ---------------------------------------------------------------------
-bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl, 
-                          bool const &DoContents,
-                          bool const &GenContentsOnly, 
-                          bool const &DoSource,
-                          bool const &DoMD5, bool const &DoSHA1,
-                          bool const &DoSHA256, bool const &DoSHA512, 
+bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl, bool const &DoContents,
+                               bool const &GenContentsOnly, bool const DoSource, unsigned int const DoHashes,
                           bool const &checkMtime)
 {
-   bool result = true;
    this->FileName = FileName;
 
    if (GetCurStat() == false)
@@ -222,31 +219,28 @@ bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl,
    OldStat = CurStat;
 
    if (GetFileStat(checkMtime) == false)
-      return false;    
+      return false;
 
    /* if mtime changed, update CurStat from disk */
    if (checkMtime == true && OldStat.mtime != CurStat.mtime)
       CurStat.Flags = FlSize;
 
    Stats.Bytes += CurStat.FileSize;
-   Stats.Packages++;
+   ++Stats.Packages;
 
    if ((DoControl && LoadControl() == false)
-       || (DoContents && LoadContents(GenContentsOnly) == false)
-       || (DoSource && LoadSource() == false)
-       || (DoMD5 && GetMD5(false) == false)
-       || (DoSHA1 && GetSHA1(false) == false)
-       || (DoSHA256 && GetSHA256(false) == false)
-       || (DoSHA512 && GetSHA512(false) == false) )
+        || (DoContents && LoadContents(GenContentsOnly) == false)
+        || (DoSource && LoadSource() == false)
+        || (DoHashes != 0 && GetHashes(false, DoHashes) == false)
+      )
    {
-      result = false;
+      return false;
    }
-    
-   return result;
+
+   return true;
 }
                                                                        /*}}}*/
-
-bool CacheDB::LoadSource()
+bool CacheDB::LoadSource()                                             /*{{{*/
 {
    // Try to read the control information out of the DB.
    if ((CurStat.Flags & FlSource) == FlSource)
@@ -276,7 +270,7 @@ bool CacheDB::LoadSource()
 
    return true;
 }
-
+                                                                       /*}}}*/
 // CacheDB::LoadControl - Load Control information                     /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -345,7 +339,7 @@ bool CacheDB::LoadContents(bool const &GenOnly)
    return true;
 }
                                                                        /*}}}*/
-
+// CacheDB::GetHashes - Get the hashs                                  /*{{{*/
 static std::string bytes2hex(uint8_t *bytes, size_t length) {
    char buf[3];
    std::string space;
@@ -375,125 +369,59 @@ static void hex2bytes(uint8_t *bytes, const char *hex, int length) {
       bytes++;
    } 
 }
-
-// CacheDB::GetMD5 - Get the MD5 hash                                  /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetMD5(bool const &GenOnly)
+bool CacheDB::GetHashes(bool const GenOnly, unsigned int const DoHashes)
 {
-   // Try to read the control information out of the DB.
-   if ((CurStat.Flags & FlMD5) == FlMD5)
-   {
-      if (GenOnly == true)
-        return true;
-      
-      MD5Res = bytes2hex(CurStat.MD5, sizeof(CurStat.MD5));
-        return true;
-   }
-   
-   Stats.MD5Bytes += CurStat.FileSize;
-        
-   if (OpenFile() == false)
-      return false;
+   unsigned int FlHashes = DoHashes & (Hashes::MD5SUM | Hashes::SHA1SUM | Hashes::SHA256SUM | Hashes::SHA512SUM);
+   HashesList.clear();
 
-   MD5Summation MD5;
-   if (Fd->Seek(0) == false || MD5.AddFD(*Fd, CurStat.FileSize) == false)
-      return false;
-   
-   MD5Res = MD5.Result();
-   hex2bytes(CurStat.MD5, MD5Res.data(), sizeof(CurStat.MD5));
-      CurStat.Flags |= FlMD5;
-   return true;
-}
-                                                                       /*}}}*/
-// CacheDB::GetSHA1 - Get the SHA1 hash                                        /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA1(bool const &GenOnly)
-{
-   // Try to read the control information out of the DB.
-   if ((CurStat.Flags & FlSHA1) == FlSHA1)
+   if (FlHashes != 0)
    {
-      if (GenOnly == true)
-        return true;
+      if (OpenFile() == false)
+        return false;
 
-      SHA1Res = bytes2hex(CurStat.SHA1, sizeof(CurStat.SHA1));
-      return true;
-   }
-   
-   Stats.SHA1Bytes += CurStat.FileSize;
-        
-   if (OpenFile() == false)
-      return false;
+      Hashes hashes;
+      if (Fd->Seek(0) == false || hashes.AddFD(*Fd, CurStat.FileSize, FlHashes) == false)
+        return false;
 
-   SHA1Summation SHA1;
-   if (Fd->Seek(0) == false || SHA1.AddFD(*Fd, CurStat.FileSize) == false)
-      return false;
-   
-   SHA1Res = SHA1.Result();
-   hex2bytes(CurStat.SHA1, SHA1Res.data(), sizeof(CurStat.SHA1));
-   CurStat.Flags |= FlSHA1;
-   return true;
-}
-                                                                       /*}}}*/
-// CacheDB::GetSHA256 - Get the SHA256 hash                            /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA256(bool const &GenOnly)
-{
-   // Try to read the control information out of the DB.
-   if ((CurStat.Flags & FlSHA256) == FlSHA256)
-   {
-      if (GenOnly == true)
-        return true;
-
-      SHA256Res = bytes2hex(CurStat.SHA256, sizeof(CurStat.SHA256));
-      return true;
+      HashStringList hl = hashes.GetHashStringList();
+      for (HashStringList::const_iterator hs = hl.begin(); hs != hl.end(); ++hs)
+      {
+        HashesList.push_back(*hs);
+        if (strcasecmp(hs->HashType().c_str(), "SHA512") == 0)
+        {
+           Stats.SHA512Bytes += CurStat.FileSize;
+           hex2bytes(CurStat.SHA512, hs->HashValue().data(), sizeof(CurStat.SHA512));
+           CurStat.Flags |= FlSHA512;
+        }
+        else if (strcasecmp(hs->HashType().c_str(), "SHA256") == 0)
+        {
+           Stats.SHA256Bytes += CurStat.FileSize;
+           hex2bytes(CurStat.SHA256, hs->HashValue().data(), sizeof(CurStat.SHA256));
+           CurStat.Flags |= FlSHA256;
+        }
+        else if (strcasecmp(hs->HashType().c_str(), "SHA1") == 0)
+        {
+           Stats.SHA1Bytes += CurStat.FileSize;
+           hex2bytes(CurStat.SHA1, hs->HashValue().data(), sizeof(CurStat.SHA1));
+           CurStat.Flags |= FlSHA1;
+        }
+        else if (strcasecmp(hs->HashType().c_str(), "MD5Sum") == 0)
+        {
+           Stats.MD5Bytes += CurStat.FileSize;
+           hex2bytes(CurStat.MD5, hs->HashValue().data(), sizeof(CurStat.MD5));
+           CurStat.Flags |= FlMD5;
+        }
+        else
+           return _error->Error("Got unknown unrequested hashtype %s", hs->HashType().c_str());
+      }
    }
-   
-   Stats.SHA256Bytes += CurStat.FileSize;
-        
-   if (OpenFile() == false)
-      return false;
-
-   SHA256Summation SHA256;
-   if (Fd->Seek(0) == false || SHA256.AddFD(*Fd, CurStat.FileSize) == false)
-      return false;
-   
-   SHA256Res = SHA256.Result();
-   hex2bytes(CurStat.SHA256, SHA256Res.data(), sizeof(CurStat.SHA256));
-   CurStat.Flags |= FlSHA256;
-   return true;
-}
-                                                                       /*}}}*/
-// CacheDB::GetSHA256 - Get the SHA256 hash                            /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA512(bool const &GenOnly)
-{
-   // Try to read the control information out of the DB.
-   if ((CurStat.Flags & FlSHA512) == FlSHA512)
-   {
-      if (GenOnly == true)
-        return true;
-
-      SHA512Res = bytes2hex(CurStat.SHA512, sizeof(CurStat.SHA512));
+   if (GenOnly == true)
       return true;
-   }
-   
-   Stats.SHA512Bytes += CurStat.FileSize;
-        
-   if (OpenFile() == false)
-      return false;
 
-   SHA512Summation SHA512;
-   if (Fd->Seek(0) == false || SHA512.AddFD(*Fd, CurStat.FileSize) == false)
-      return false;
-   
-   SHA512Res = SHA512.Result();
-   hex2bytes(CurStat.SHA512, SHA512Res.data(), sizeof(CurStat.SHA512));
-   CurStat.Flags |= FlSHA512;
-   return true;
+   return HashesList.push_back(HashString("MD5Sum", bytes2hex(CurStat.MD5, sizeof(CurStat.MD5)))) &&
+      HashesList.push_back(HashString("SHA1", bytes2hex(CurStat.SHA1, sizeof(CurStat.SHA1)))) &&
+      HashesList.push_back(HashString("SHA256", bytes2hex(CurStat.SHA256, sizeof(CurStat.SHA256)))) &&
+      HashesList.push_back(HashString("SHA512", bytes2hex(CurStat.SHA512, sizeof(CurStat.SHA512))));
 }
                                                                        /*}}}*/
 // CacheDB::Finish - Write back the cache structure                    /*{{{*/
index 54a27494487e8f8641376bcebe854b72a572bc6d..14dba55784c715c9489ca7fc04f837ec537b4ad4 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef CACHEDB_H
 #define CACHEDB_H
 
+#include <apt-pkg/hashes.h>
 #include <apt-pkg/debfile.h>
 
 #include <db.h>
@@ -90,11 +91,8 @@ class CacheDB
    bool LoadControl();
    bool LoadContents(bool const &GenOnly);
    bool LoadSource();
-   bool GetMD5(bool const &GenOnly);
-   bool GetSHA1(bool const &GenOnly);
-   bool GetSHA256(bool const &GenOnly);
-   bool GetSHA512(bool const &GenOnly);
-   
+   bool GetHashes(bool const GenOnly, unsigned int const DoHashes);
+
    // Stat info stored in the DB, Fixed types since it is written to disk.
    enum FlagList {FlControl = (1<<0),FlMD5=(1<<1),FlContents=(1<<2),
                   FlSize=(1<<3), FlSHA1=(1<<4), FlSHA256=(1<<5), 
@@ -124,12 +122,8 @@ class CacheDB
    debDebFile::MemControlExtract Control;
    ContentsExtract Contents;
    DscExtract Dsc;
+   HashStringList HashesList;
 
-   std::string MD5Res;
-   std::string SHA1Res;
-   std::string SHA256Res;
-   std::string SHA512Res;
-   
    // Runtime statistics
    struct Stats
    {
@@ -165,16 +159,13 @@ class CacheDB
    bool SetFile(std::string const &FileName,struct stat St,FileFd *Fd);
 
    // terrible old overloaded interface
-   bool GetFileInfo(std::string const &FileName, 
-                    bool const &DoControl, 
-                    bool const &DoContents, 
-                    bool const &GenContentsOnly, 
-                    bool const &DoSource,
-                   bool const &DoMD5, 
-                    bool const &DoSHA1, 
-                    bool const &DoSHA256, 
-                    bool const &DoSHA512, 
-                    bool const &checkMtime = false);
+   bool GetFileInfo(std::string const &FileName,
+        bool const &DoControl,
+        bool const &DoContents,
+        bool const &GenContentsOnly,
+        bool const DoSource,
+        unsigned int const DoHashes,
+        bool const &checkMtime = false);
 
    bool Finish();   
    
index 7c1c9cc03782a4e053a17343a780046f069d076a..db617e92ac9bfd43bd0f9aa3cf98a85023f34acf 100644 (file)
@@ -54,29 +54,42 @@ FTWScanner *FTWScanner::Owner;
 // SetTFRewriteData - Helper for setting rewrite lists                 /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-inline void SetTFRewriteData(struct TFRewriteData &tfrd,
-                            const char *tag,
+static inline TFRewriteData SetTFRewriteData(const char *tag,
                             const char *rewrite,
                             const char *newtag = 0)
 {
-    tfrd.Tag = tag;
-    tfrd.Rewrite = rewrite;
-    tfrd.NewTag = newtag;
+   TFRewriteData tfrd;
+   tfrd.Tag = tag;
+   tfrd.Rewrite = rewrite;
+   tfrd.NewTag = newtag;
+   return tfrd;
+}
+                                                                       /*}}}*/
+// ConfigToDoHashes - which hashes to generate                         /*{{{*/
+static void SingleConfigToDoHashes(unsigned int &DoHashes, std::string const &Conf, unsigned int const Flag)
+{
+   if (_config->FindB(Conf, true) == true)
+      DoHashes |= Flag;
+   else
+      DoHashes &= ~Flag;
+}
+static void ConfigToDoHashes(unsigned int &DoHashes, std::string const &Conf)
+{
+   SingleConfigToDoHashes(DoHashes, Conf + "::MD5", Hashes::MD5SUM);
+   SingleConfigToDoHashes(DoHashes, Conf + "::SHA1", Hashes::SHA1SUM);
+   SingleConfigToDoHashes(DoHashes, Conf + "::SHA256", Hashes::SHA256SUM);
+   SingleConfigToDoHashes(DoHashes, Conf + "::SHA512", Hashes::SHA512SUM);
 }
                                                                        /*}}}*/
 
 // FTWScanner::FTWScanner - Constructor                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-FTWScanner::FTWScanner(string const &Arch): Arch(Arch)
+FTWScanner::FTWScanner(string const &Arch): Arch(Arch), DoHashes(~0)
 {
    ErrorPrinted = false;
    NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
-
-   DoMD5 = _config->FindB("APT::FTPArchive::MD5",true);
-   DoSHA1 = _config->FindB("APT::FTPArchive::SHA1",true);
-   DoSHA256 = _config->FindB("APT::FTPArchive::SHA256",true);
-   DoSHA512 = _config->FindB("APT::FTPArchive::SHA512",true);
+   ConfigToDoHashes(DoHashes, "APT::FTPArchive");
 }
                                                                        /*}}}*/
 // FTWScanner::Scanner - FTW Scanner                                   /*{{{*/
@@ -327,10 +340,7 @@ PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string c
    DeLinkLimit = 0;
 
    // Process the command line options
-   DoMD5 = _config->FindB("APT::FTPArchive::Packages::MD5",DoMD5);
-   DoSHA1 = _config->FindB("APT::FTPArchive::Packages::SHA1",DoSHA1);
-   DoSHA256 = _config->FindB("APT::FTPArchive::Packages::SHA256",DoSHA256);
-   DoSHA512 = _config->FindB("APT::FTPArchive::Packages::SHA512",DoSHA512);
+   ConfigToDoHashes(DoHashes, "APT::FTPArchive::Packages");
    DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false);
    DoContents = _config->FindB("APT::FTPArchive::Contents",true);
    NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false);
@@ -385,12 +395,12 @@ bool FTWScanner::SetExts(string const &Vals)
 bool PackagesWriter::DoPackage(string FileName)
 {      
    // Pull all the data we need form the DB
-   if (Db.GetFileInfo(FileName, 
-                      true,   /* DoControl */
-                      DoContents, 
-                      true,   /* GenContentsOnly */
-                      false,  /* DoSource */
-                      DoMD5, DoSHA1, DoSHA256, DoSHA512, DoAlwaysStat) == false)
+   if (Db.GetFileInfo(FileName,
+           true, /* DoControl */
+           DoContents,
+           true, /* GenContentsOnly */
+           false, /* DoSource */
+           DoHashes, DoAlwaysStat) == false)
    {
      return false;
    }
@@ -454,30 +464,27 @@ bool PackagesWriter::DoPackage(string FileName)
    }
 
    // This lists all the changes to the fields we are going to make.
-   // (7 hardcoded + maintainer + suggests + end marker)
-   TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1+1];
-
-   unsigned int End = 0;
-   SetTFRewriteData(Changes[End++], "Size", Size);
-   if (DoMD5 == true)
-      SetTFRewriteData(Changes[End++], "MD5sum", Db.MD5Res.c_str());
-   if (DoSHA1 == true)
-      SetTFRewriteData(Changes[End++], "SHA1", Db.SHA1Res.c_str());
-   if (DoSHA256 == true)
-      SetTFRewriteData(Changes[End++], "SHA256", Db.SHA256Res.c_str());
-   if (DoSHA512 == true)
-      SetTFRewriteData(Changes[End++], "SHA512", Db.SHA512Res.c_str());
-   SetTFRewriteData(Changes[End++], "Filename", NewFileName.c_str());
-   SetTFRewriteData(Changes[End++], "Priority", OverItem->Priority.c_str());
-   SetTFRewriteData(Changes[End++], "Status", 0);
-   SetTFRewriteData(Changes[End++], "Optional", 0);
+   std::vector<TFRewriteData> Changes;
+
+   Changes.push_back(SetTFRewriteData("Size", Size));
+   for (HashStringList::const_iterator hs = Db.HashesList.begin(); hs != Db.HashesList.end(); ++hs)
+   {
+      if (hs->HashType() == "MD5Sum")
+        Changes.push_back(SetTFRewriteData("MD5sum", hs->HashValue().c_str()));
+      else
+        Changes.push_back(SetTFRewriteData(hs->HashType().c_str(), hs->HashValue().c_str()));
+   }
+   Changes.push_back(SetTFRewriteData("Filename", NewFileName.c_str()));
+   Changes.push_back(SetTFRewriteData("Priority", OverItem->Priority.c_str()));
+   Changes.push_back(SetTFRewriteData("Status", 0));
+   Changes.push_back(SetTFRewriteData("Optional", 0));
 
    string DescriptionMd5;
    if (LongDescription == false) {
       MD5Summation descmd5;
       descmd5.Add(desc.c_str());
       DescriptionMd5 = descmd5.Result().Value();
-      SetTFRewriteData(Changes[End++], "Description-md5", DescriptionMd5.c_str());
+      Changes.push_back(SetTFRewriteData("Description-md5", DescriptionMd5.c_str()));
       if (TransWriter != NULL)
         TransWriter->DoPackage(Package, desc, DescriptionMd5);
    }
@@ -492,12 +499,12 @@ bool PackagesWriter::DoPackage(string FileName)
         NewLine(1);
         ioprintf(c1out, _("  %s maintainer is %s not %s\n"),
               Package.c_str(), Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str());
-      }      
+      }
    }
-   
+
    if (NewMaint.empty() == false)
-      SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
-   
+      Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str()));
+
    /* Get rid of the Optional tag. This is an ugly, ugly, ugly hack that
       dpkg-scanpackages does. Well sort of. dpkg-scanpackages just does renaming
       but dpkg does this append bit. So we do the append bit, at least that way the
@@ -508,17 +515,17 @@ bool PackagesWriter::DoPackage(string FileName)
    {
       if (Tags.FindS("Suggests").empty() == false)
         OptionalStr = Tags.FindS("Suggests") + ", " + OptionalStr;
-      SetTFRewriteData(Changes[End++], "Suggests", OptionalStr.c_str());
+      Changes.push_back(SetTFRewriteData("Suggests", OptionalStr.c_str()));
    }
 
-   for (map<string,string>::const_iterator I = OverItem->FieldOverride.begin(); 
+   for (map<string,string>::const_iterator I = OverItem->FieldOverride.begin();
         I != OverItem->FieldOverride.end(); ++I)
-      SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
+      Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str()));
 
-   SetTFRewriteData(Changes[End++], 0, 0);
+   Changes.push_back(SetTFRewriteData( 0, 0));
 
    // Rewrite and store the fields.
-   if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes) == false)
+   if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes.data()) == false)
       return false;
    fprintf(Output,"\n");
 
@@ -589,10 +596,7 @@ SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string c
    BufSize = 0;
    
    // Process the command line options
-   DoMD5 = _config->FindB("APT::FTPArchive::Sources::MD5",DoMD5);
-   DoSHA1 = _config->FindB("APT::FTPArchive::Sources::SHA1",DoSHA1);
-   DoSHA256 = _config->FindB("APT::FTPArchive::Sources::SHA256",DoSHA256);
-   DoSHA512 = _config->FindB("APT::FTPArchive::Sources::SHA512",DoSHA512);
+   ConfigToDoHashes(DoHashes, "APT::FTPArchive::Sources");
    NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false);
    DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false);
 
@@ -614,17 +618,25 @@ SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string c
 }
                                                                        /*}}}*/
 // SourcesWriter::DoPackage - Process a single package                 /*{{{*/
-// ---------------------------------------------------------------------
-/* */
+static std::ostream& addDscHash(std::ostream &out, unsigned int const DoHashes,
+      Hashes::SupportedHashes const DoIt, pkgTagSection &Tags, char const * const FieldName,
+      HashString const * const Hash, unsigned long long Size, std::string FileName)
+{
+   if ((DoHashes & DoIt) != DoIt || Tags.Exists(FieldName) == false || Hash == NULL)
+      return out;
+   out << "\n " << Hash->HashValue() << " " << Size << " " << FileName
+      << "\n " << Tags.FindS(FieldName);
+   return out;
+}
 bool SourcesWriter::DoPackage(string FileName)
 {
    // Pull all the data we need form the DB
    if (Db.GetFileInfo(FileName,
-                      false,  /* DoControl */
-                      false,  /* DoContents */
-                      false,  /* GenContentsOnly */
-                      true,   /* DoSource */
-                      DoMD5, DoSHA1, DoSHA256, DoSHA512, DoAlwaysStat) == false)
+           false, /* DoControl */
+           false, /* DoContents */
+           false, /* GenContentsOnly */
+           true, /* DoSource */
+           DoHashes, DoAlwaysStat) == false)
    {
       return false;
    }
@@ -712,29 +724,19 @@ bool SourcesWriter::DoPackage(string FileName)
         *SOverItem = *OverItem;
       }
    }
-   
+
    // Add the dsc to the files hash list
    string const strippedName = flNotDir(FileName);
    std::ostringstream ostreamFiles;
-   if (DoMD5 == true && Tags.Exists("Files"))
-      ostreamFiles << "\n " << Db.MD5Res.c_str() << " " << St.st_size << " "
-                  << strippedName << "\n " << Tags.FindS("Files");
+   addDscHash(ostreamFiles, DoHashes, Hashes::MD5SUM, Tags, "Files", Db.HashesList.find("MD5Sum"), St.st_size, strippedName);
    string const Files = ostreamFiles.str();
 
    std::ostringstream ostreamSha1;
-   if (DoSHA1 == true && Tags.Exists("Checksums-Sha1"))
-      ostreamSha1 << "\n " << string(Db.SHA1Res.c_str()) << " " << St.st_size << " "
-                  << strippedName << "\n " << Tags.FindS("Checksums-Sha1");
-
+   addDscHash(ostreamSha1, DoHashes, Hashes::SHA1SUM, Tags, "Checksums-Sha1", Db.HashesList.find("SHA1"), St.st_size, strippedName);
    std::ostringstream ostreamSha256;
-   if (DoSHA256 == true && Tags.Exists("Checksums-Sha256"))
-      ostreamSha256 << "\n " << string(Db.SHA256Res.c_str()) << " " << St.st_size << " "
-                  << strippedName << "\n " << Tags.FindS("Checksums-Sha256");
-
+   addDscHash(ostreamSha256, DoHashes, Hashes::SHA256SUM, Tags, "Checksums-Sha256", Db.HashesList.find("SHA256"), St.st_size, strippedName);
    std::ostringstream ostreamSha512;
-   if (DoSHA512 == true && Tags.Exists("Checksums-Sha512"))
-      ostreamSha512 << "\n " << string(Db.SHA512Res.c_str()) << " " << St.st_size << " "
-                  << strippedName << "\n " << Tags.FindS("Checksums-Sha512");
+   addDscHash(ostreamSha512, DoHashes, Hashes::SHA512SUM, Tags, "Checksums-Sha512", Db.HashesList.find("SHA512"), St.st_size, strippedName);
 
    // Strip the DirStrip prefix from the FileName and add the PathPrefix
    string NewFileName;
@@ -766,35 +768,54 @@ bool SourcesWriter::DoPackage(string FileName)
       string OriginalPath = Directory + ParseJnk;
 
       // Add missing hashes to source files
-      if ((DoSHA1 == true && !Tags.Exists("Checksums-Sha1")) ||
-          (DoSHA256 == true && !Tags.Exists("Checksums-Sha256")) ||
-          (DoSHA512 == true && !Tags.Exists("Checksums-Sha512")))
+      if (((DoHashes & Hashes::SHA1SUM) == Hashes::SHA1SUM && !Tags.Exists("Checksums-Sha1")) ||
+          ((DoHashes & Hashes::SHA256SUM) == Hashes::SHA256SUM && !Tags.Exists("Checksums-Sha256")) ||
+          ((DoHashes & Hashes::SHA512SUM) == Hashes::SHA512SUM && !Tags.Exists("Checksums-Sha512")))
       {
-         if (Db.GetFileInfo(OriginalPath, 
+         if (Db.GetFileInfo(OriginalPath,
                             false, /* DoControl */
                             false, /* DoContents */
                             false, /* GenContentsOnly */
                             false, /* DoSource */
-                            DoMD5, DoSHA1, DoSHA256, DoSHA512,
+                            DoHashes,
                             DoAlwaysStat) == false)
          {
             return _error->Error("Error getting file info");
          }
 
-         if (DoSHA1 == true && !Tags.Exists("Checksums-Sha1"))
-            ostreamSha1 << "\n " << string(Db.SHA1Res) << " "
-               << Db.GetFileSize() << " " << ParseJnk;
-
-         if (DoSHA256 == true && !Tags.Exists("Checksums-Sha256"))
-            ostreamSha256 << "\n " << string(Db.SHA256Res) << " "
-               << Db.GetFileSize() << " " << ParseJnk;
-
-         if (DoSHA512 == true && !Tags.Exists("Checksums-Sha512"))
-            ostreamSha512 << "\n " << string(Db.SHA512Res) << " "
-               << Db.GetFileSize() << " " << ParseJnk;
+         for (HashStringList::const_iterator hs = Db.HashesList.begin(); hs != Db.HashesList.end(); ++hs)
+        {
+           if (hs->HashType() == "MD5Sum")
+              continue;
+           char const * fieldname;
+           std::ostream * out;
+           if (hs->HashType() == "SHA1")
+           {
+              fieldname = "Checksums-Sha1";
+              out = &ostreamSha1;
+           }
+           else if (hs->HashType() == "SHA256")
+           {
+              fieldname = "Checksums-Sha256";
+              out = &ostreamSha256;
+           }
+           else if (hs->HashType() == "SHA512")
+           {
+              fieldname = "Checksums-Sha512";
+              out = &ostreamSha512;
+           }
+           else
+           {
+              _error->Warning("Ignoring unknown Checksumtype %s in SourcesWriter::DoPackages", hs->HashType().c_str());
+              continue;
+           }
+           if (Tags.Exists(fieldname) == true)
+              continue;
+           (*out) << "\n " << hs->HashValue() << " " << Db.GetFileSize() << " " << ParseJnk;
+        }
 
-         // write back the GetFileInfo() stats data 
-         Db.Finish();
+        // write back the GetFileInfo() stats data 
+        Db.Finish();
       }
 
       // Perform the delinking operation
@@ -820,22 +841,21 @@ bool SourcesWriter::DoPackage(string FileName)
 
    // This lists all the changes to the fields we are going to make.
    // (5 hardcoded + checksums + maintainer + end marker)
-   TFRewriteData Changes[5+2+1+SOverItem->FieldOverride.size()+1];
+   std::vector<TFRewriteData> Changes;
 
-   unsigned int End = 0;
-   SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
+   Changes.push_back(SetTFRewriteData("Source",Package.c_str(),"Package"));
    if (Files.empty() == false)
-      SetTFRewriteData(Changes[End++],"Files",Files.c_str());
+      Changes.push_back(SetTFRewriteData("Files",Files.c_str()));
    if (ChecksumsSha1.empty() == false)
-      SetTFRewriteData(Changes[End++],"Checksums-Sha1",ChecksumsSha1.c_str());
+      Changes.push_back(SetTFRewriteData("Checksums-Sha1",ChecksumsSha1.c_str()));
    if (ChecksumsSha256.empty() == false)
-      SetTFRewriteData(Changes[End++],"Checksums-Sha256",ChecksumsSha256.c_str());
+      Changes.push_back(SetTFRewriteData("Checksums-Sha256",ChecksumsSha256.c_str()));
    if (ChecksumsSha512.empty() == false)
-      SetTFRewriteData(Changes[End++],"Checksums-Sha512",ChecksumsSha512.c_str());
+      Changes.push_back(SetTFRewriteData("Checksums-Sha512",ChecksumsSha512.c_str()));
    if (Directory != "./")
-      SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
-   SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
-   SetTFRewriteData(Changes[End++],"Status",0);
+      Changes.push_back(SetTFRewriteData("Directory",Directory.c_str()));
+   Changes.push_back(SetTFRewriteData("Priority",BestPrio.c_str()));
+   Changes.push_back(SetTFRewriteData("Status",0));
 
    // Rewrite the maintainer field if necessary
    bool MaintFailed;
@@ -850,16 +870,16 @@ bool SourcesWriter::DoPackage(string FileName)
       }      
    }
    if (NewMaint.empty() == false)
-      SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
+      Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str()));
    
    for (map<string,string>::const_iterator I = SOverItem->FieldOverride.begin(); 
         I != SOverItem->FieldOverride.end(); ++I)
-      SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
+      Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str()));
 
-   SetTFRewriteData(Changes[End++], 0, 0);
+   Changes.push_back(SetTFRewriteData(0, 0));
       
    // Rewrite and store the fields.
-   if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes) == false)
+   if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes.data()) == false)
       return false;
    fprintf(Output,"\n");
 
@@ -886,15 +906,13 @@ ContentsWriter::ContentsWriter(string const &DB, string const &Arch) :
    determine what the package name is. */
 bool ContentsWriter::DoPackage(string FileName, string Package)
 {
-   if (!Db.GetFileInfo(FileName, 
-                       Package.empty(), /* DoControl */
-                       true,            /* DoContents */
-                       false,           /* GenContentsOnly */
-                       false,           /* DoSource */
-                       false,           /* DoMD5 */
-                       false,           /* DoSHA1 */
-                       false,           /* DoSHA256 */
-                       false))          /* DoSHA512 */
+   if (!Db.GetFileInfo(FileName,
+           Package.empty(), /* DoControl */
+           true, /* DoContents */
+           false, /* GenContentsOnly */
+           false, /* DoSource */
+           0, /* DoHashes */
+           false /* checkMtime */))
    {
       return false;
    }
@@ -1030,9 +1048,7 @@ ReleaseWriter::ReleaseWriter(string const &/*DB*/)
       fprintf(Output, "%s: %s\n", (*I).first.c_str(), Value.c_str());
    }
 
-   DoMD5 = _config->FindB("APT::FTPArchive::Release::MD5",DoMD5);
-   DoSHA1 = _config->FindB("APT::FTPArchive::Release::SHA1",DoSHA1);
-   DoSHA256 = _config->FindB("APT::FTPArchive::Release::SHA256",DoSHA256);
+   ConfigToDoHashes(DoHashes, "APT::FTPArchive::Release");
 }
                                                                        /*}}}*/
 // ReleaseWriter::DoPackage - Process a single package                 /*{{{*/
@@ -1066,15 +1082,8 @@ bool ReleaseWriter::DoPackage(string FileName)
    CheckSums[NewFileName].size = fd.Size();
 
    Hashes hs;
-   hs.AddFD(fd, 0, DoMD5, DoSHA1, DoSHA256, DoSHA512);
-   if (DoMD5 == true)
-      CheckSums[NewFileName].MD5 = hs.MD5.Result();
-   if (DoSHA1 == true)
-      CheckSums[NewFileName].SHA1 = hs.SHA1.Result();
-   if (DoSHA256 == true)
-      CheckSums[NewFileName].SHA256 = hs.SHA256.Result();
-   if (DoSHA512 == true)
-      CheckSums[NewFileName].SHA512 = hs.SHA512.Result();
+   hs.AddFD(fd, 0, DoHashes);
+   CheckSums[NewFileName].Hashes = hs.GetHashStringList();
    fd.Close();
 
    return true;
@@ -1083,54 +1092,29 @@ bool ReleaseWriter::DoPackage(string FileName)
                                                                        /*}}}*/
 // ReleaseWriter::Finish - Output the checksums                                /*{{{*/
 // ---------------------------------------------------------------------
-void ReleaseWriter::Finish()
+static void printChecksumTypeRecord(FILE * const Output, char const * const Type, map<string, ReleaseWriter::CheckSum> const &CheckSums)
 {
-   if (DoMD5 == true)
-   {
-      fprintf(Output, "MD5Sum:\n");
-      for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
-         I != CheckSums.end(); ++I)
-      {
-        fprintf(Output, " %s %16llu %s\n",
-                (*I).second.MD5.c_str(),
-                (*I).second.size,
-                (*I).first.c_str());
-      }
-   }
-   if (DoSHA1 == true)
-   {
-      fprintf(Output, "SHA1:\n");
-      for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
-         I != CheckSums.end(); ++I)
-      {
-        fprintf(Output, " %s %16llu %s\n",
-                (*I).second.SHA1.c_str(),
-                (*I).second.size,
-                (*I).first.c_str());
-      }
-   }
-   if (DoSHA256 == true)
-   {
-      fprintf(Output, "SHA256:\n");
-      for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
+      fprintf(Output, "%s:\n", Type);
+      for(map<string,ReleaseWriter::CheckSum>::const_iterator I = CheckSums.begin();
          I != CheckSums.end(); ++I)
       {
+        HashString const * const hs = I->second.Hashes.find(Type);
+        if (hs == NULL)
+           continue;
         fprintf(Output, " %s %16llu %s\n",
-                (*I).second.SHA256.c_str(),
+                hs->HashValue().c_str(),
                 (*I).second.size,
                 (*I).first.c_str());
       }
-   }
-
-   fprintf(Output, "SHA512:\n");
-   for(map<string,struct CheckSum>::const_iterator I = CheckSums.begin();
-       I != CheckSums.end();
-       ++I)
-   {
-      fprintf(Output, " %s %16llu %s\n",
-              (*I).second.SHA512.c_str(),
-              (*I).second.size,
-              (*I).first.c_str());
-   }
-
+}
+void ReleaseWriter::Finish()
+{
+   if ((DoHashes & Hashes::MD5SUM) == Hashes::MD5SUM)
+      printChecksumTypeRecord(Output, "MD5Sum", CheckSums);
+   if ((DoHashes & Hashes::SHA1SUM) == Hashes::SHA1SUM)
+      printChecksumTypeRecord(Output, "SHA1", CheckSums);
+   if ((DoHashes & Hashes::SHA256SUM) == Hashes::SHA256SUM)
+      printChecksumTypeRecord(Output, "SHA256", CheckSums);
+   if ((DoHashes & Hashes::SHA512SUM) == Hashes::SHA512SUM)
+      printChecksumTypeRecord(Output, "SHA512", CheckSums);
 }
index b1a653e7daafc8c8cd6b5b5ea8389ba9c4ab9562..c62d4addf91793b1c6182820300db70f0332f1df 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef WRITER_H
 #define WRITER_H
 
+#include <apt-pkg/hashes.h>
+
 #include <string>
 #include <stdio.h>
 #include <iostream>
@@ -61,10 +63,7 @@ class FTWScanner
    }
    
    public:
-   bool DoMD5;
-   bool DoSHA1;
-   bool DoSHA256;
-   bool DoSHA512;
+   unsigned int DoHashes;
 
    unsigned long DeLinkLimit;
    string InternalPrefix;
@@ -195,17 +194,14 @@ public:
    string PathPrefix;
    string DirStrip;
 
-protected:
    struct CheckSum
    {
-      string MD5;
-      string SHA1;
-      string SHA256;
-      string SHA512;
+      HashStringList Hashes;
       // Limited by FileFd::Size()
       unsigned long long size;
       ~CheckSum() {};
    };
+protected:
    map<string,struct CheckSum> CheckSums;
 };
 
index 5a13f18a7b7a527db033c3e286870e9e4e99eec6..c91d3b21822f24c5a6515f548e65d290d4f60eb9 100644 (file)
@@ -392,9 +392,16 @@ bool ServerMethod::Fetch(FetchItem *)
    for (FetchItem *I = Queue; I != 0 && Depth < (signed)PipelineDepth; 
        I = I->Next, Depth++)
    {
-      // If pipelining is disabled, we only queue 1 request
-      if (Server->Pipeline == false && Depth >= 0)
-        break;
+      if (Depth >= 0)
+      {
+        // If pipelining is disabled, we only queue 1 request
+        if (Server->Pipeline == false)
+           break;
+        // if we have no hashes, do at most one such request
+        // as we can't fixup pipeling misbehaviors otherwise
+        else if (I->ExpectedHashes.usable() == false)
+           break;
+      }
       
       // Make sure we stick with the same server
       if (Server->Comp(I->Uri) == false)
@@ -546,7 +553,38 @@ int ServerMethod::Loop()
            // Send status to APT
            if (Result == true)
            {
-              Res.TakeHashes(*Server->GetHashes());
+              Hashes * const resultHashes = Server->GetHashes();
+              HashStringList const hashList = resultHashes->GetHashStringList();
+              if (PipelineDepth != 0 && Queue->ExpectedHashes.usable() == true && Queue->ExpectedHashes != hashList)
+              {
+                 // we did not get the expected hash… mhhh:
+                 // could it be that server/proxy messed up pipelining?
+                 FetchItem * BeforeI = Queue;
+                 for (FetchItem *I = Queue->Next; I != 0 && I != QueueBack; I = I->Next)
+                 {
+                    if (I->ExpectedHashes.usable() == true && I->ExpectedHashes == hashList)
+                    {
+                       // yes, he did! Disable pipelining and rewrite queue
+                       if (Server->Pipeline == true)
+                       {
+                          // FIXME: fake a warning message as we have no proper way of communicating here
+                          std::string out;
+                          strprintf(out, _("Automatically disabled %s due to incorrect response from server/proxy. (man 5 apt.conf)"), "Acquire::http::PipelineDepth");
+                          std::cerr << "W: " << out << std::endl;
+                          Server->Pipeline = false;
+                          // we keep the PipelineDepth value so that the rest of the queue can be fixed up as well
+                       }
+                       Rename(Res.Filename, I->DestFile);
+                       Res.Filename = I->DestFile;
+                       BeforeI->Next = I->Next;
+                       I->Next = Queue;
+                       Queue = I;
+                       break;
+                    }
+                    BeforeI = I;
+                 }
+              }
+              Res.TakeHashes(*resultHashes);
               URIDone(Res);
            }
            else
index 0f45ab99493de740159715e7d3488cfdc5081512..5299b3954f62d44c4ee8a1825fdd00194be9fef2 100644 (file)
@@ -140,7 +140,7 @@ class ServerMethod : public pkgAcqMethod
    virtual ServerState * CreateServerState(URI uri) = 0;
    virtual void RotateDNS() = 0;
 
-   ServerMethod(const char *Ver,unsigned long Flags = 0) : pkgAcqMethod(Ver, Flags), Server(NULL), File(NULL), PipelineDepth(0), AllowRedirect(false), Debug(false) {};
+   ServerMethod(const char *Ver,unsigned long Flags = 0) : pkgAcqMethod(Ver, Flags), Server(NULL), File(NULL), PipelineDepth(10), AllowRedirect(false), Debug(false) {};
    virtual ~ServerMethod() {};
 };
 
index ab1274d9cb47567c12acffe69cef0a311209f143..b469fd3f6e2db6f905dba1fbecfa4f6ecf6a775f 100644 (file)
@@ -36,7 +36,7 @@ msgndebug() { echo -n "${CDEBUG}D: $1${CNORMAL}"; }
 msgtest() {
        while [ -n "$1" ]; do
                echo -n "${CINFO}$1${CCMD} "
-               echo -n "$(echo "$2" | sed -e 's/^aptc/apt-c/' -e 's/^aptg/apt-g/' -e 's/^aptf/apt-f/')${CINFO} "
+               echo -n "$(echo "$2" | sed -e 's#^apt\([cgfs]\)#apt-\1#')${CINFO} "
                shift
                if [ -n "$1" ]; then shift; else break; fi
        done
@@ -102,10 +102,10 @@ runapt() {
        local CMD="$1"
        shift
        case $CMD in
-       sh|aptitude|*/*) ;;
+       sh|aptitude|*/*|command) ;;
        *) CMD="${BUILDDIRECTORY}/$CMD";;
        esac
-       MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${BUILDDIRECTORY} $CMD "$@"
+       MALLOC_PERTURB_=21 MALLOC_CHECK_=2 APT_CONFIG="$(getaptconfig)" LD_LIBRARY_PATH=${LIBRARYPATH} $CMD "$@"
 }
 aptconfig() { runapt apt-config "$@"; }
 aptcache() { runapt apt-cache "$@"; }
@@ -114,6 +114,7 @@ aptget() { runapt apt-get "$@"; }
 aptftparchive() { runapt apt-ftparchive "$@"; }
 aptkey() { runapt apt-key "$@"; }
 aptmark() { runapt apt-mark "$@"; }
+aptsortpkgs() { runapt apt-sortpkgs "$@"; }
 apt() { runapt apt "$@"; }
 apthelper() { runapt "${APTHELPERBINDIR}/apt-helper" "$@"; }
 aptwebserver() { runapt "${APTWEBSERVERBINDIR}/aptwebserver" "$@"; }
@@ -127,11 +128,9 @@ dpkgcheckbuilddeps() {
        command dpkg-checkbuilddeps --admindir=${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg "$@"
 }
 gdb() {
-       echo "gdb: run »$*«"
-       CMD="$1"
+       local CMD="$1"
        shift
-
-       APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${LIBRARYPATH} command gdb ${BUILDDIRECTORY}/$CMD --args ${BUILDDIRECTORY}/$CMD "$@"
+       runapt command gdb --quiet -ex run "${BUILDDIRECTORY}/$CMD" --args "${BUILDDIRECTORY}/$CMD" "$@"
 }
 gpg() {
        # see apt-key for the whole trickery. Setup is done in setupenvironment
@@ -226,6 +225,7 @@ setupenvironment() {
        fi
        echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
        echo 'quiet::NoUpdate "true";' >> aptconfig.conf
+       echo 'quiet::NoStatistic "true";' >> aptconfig.conf
        echo "Acquire::https::CaInfo \"${TESTDIR}/apt.pem\";" > rootdir/etc/apt/apt.conf.d/99https
         echo "Apt::Cmd::Disable-Script-Warning \"1\";" > rootdir/etc/apt/apt.conf.d/apt-binary
        configcompression '.' 'gz' #'bz2' 'lzma' 'xz'
index 147272a2c4d0f5599b0bfb1b60f779514ef7eea9..0e1986bcd0c407573eeb3f192e4b10d3346b7ddc 100755 (executable)
@@ -5,7 +5,7 @@ ensure_correct_packages_file() {
     testequal "Package: foo
 Priority: optional
 Section: others
-Installed-Size: 29
+$(dpkg-deb -I ./aptarchive/pool/main/foo_1_i386.deb | grep 'Installed-Size:' | sed 's#^ ##')
 Maintainer: Joe Sixpack <joe@example.org>
 Architecture: i386
 Version: 1
@@ -25,7 +25,7 @@ usr/share/doc/foo/copyright                               others/foo" cat ./aptarchive/dists/test/Conte
 TESTDIR=$(readlink -f $(dirname $0))
 . $TESTDIR/framework
 setupenvironment
-configarchitecture "i386"
+configarchitecture 'i386'
 
 mkdir -p aptarchive/dists/test/main/i18n/
 mkdir -p aptarchive/dists/test/main/source/
index 1af193632192561027701b087753daaa7d3b8c17..e7b148530eec5cceefe5b64f0632311243835f18 100755 (executable)
@@ -3,9 +3,9 @@ set -e
 
 assert_correct_sources_file() {
     testequal "Package: bar
-Binary: bar
-Version: 1.0
 Architecture: all
+Version: 1.0
+Binary: bar
 Format: 3.0 (native)
 Directory: pool/main
 Files:
@@ -24,9 +24,9 @@ Checksums-Sha512:
  cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e 0 bar_1.0.tar.gz
 
 Package: foo
-Binary: foo
-Version: 1.0
 Architecture: all
+Version: 1.0
+Binary: foo
 Format: 3.0 (native)
 Directory: pool/main
 Files:
@@ -43,7 +43,7 @@ Checksums-Sha256:
 Checksums-Sha512:
  3da0240fd764657c2f3661b4d750578a9a99b0580591b133756379d48117ebda87a5ed2467f513200d6e7eaf51422cbe91c15720eef7fb4bba2cc8ff81ebc547 171 foo_1.0.dsc
  cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e 0 foo_1.0.tar.gz
-" cat ./aptarchive/dists/test/main/source/Sources
+" aptsortpkgs ./aptarchive/dists/test/main/source/Sources
 }
 
 create_source_files() {
@@ -177,6 +177,11 @@ assert_correct_sources_file
 mkdir aptarchive/pool/invalid
 printf "meep" > aptarchive/pool/invalid/invalid_1.0.dsc
 testequal "
+E: Could not find a record in the DSC 'aptarchive/pool/invalid/invalid_1.0.dsc'" aptftparchive sources aptarchive/pool/invalid
+rm -f aptarchive/pool/invalid/invalid_1.0.dsc
+
+printf "meep: yes" > aptarchive/pool/invalid/invalid_1.0.dsc
+testequal "
 E: Could not find a Source entry in the DSC 'aptarchive/pool/invalid/invalid_1.0.dsc'" aptftparchive sources aptarchive/pool/invalid
 rm -f aptarchive/pool/invalid/invalid_1.0.dsc
 
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 a05ed5fa6eacc8ba8af3b30ffbdf39dc5fcda7ea..8da0a52d232e31e2c3711065608e951da52ae1e7 100755 (executable)
@@ -13,7 +13,7 @@ setupflataptarchive
 testaptgetupdate() {
        rm -rf rootdir/var/lib/apt
        aptget update 2>> testaptgetupdate.diff >> testaptgetupdate.diff || true
-       sed -i -e '/^Fetched / d' -e '/Ign / d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff
+       sed -i -e '/Ign / d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff
        GIVEN="$1"
        shift
        msgtest "Test for correctness of" "apt-get update with $*"
index 53ecbbeb3afedaf630ea4d18834f2985e2b11a5f..7a35187452482e209557d3032c87be4ed5679ac4 100755 (executable)
@@ -87,13 +87,10 @@ $DESCRIPTION
 Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 " aptcache show apt-normal
 
-# displaying the translated Description would be equally valid,
-# but we assume only one description is in a Packages file and
-# so we prefer "Description" over "Description-*" currently.
 for variant in 'below' 'middle' 'top'; do
        testequal "Package: apt-both-$variant
 $PACKAGESTANZA
-$DESCRIPTION
+$TRANSDESCRIPTION
 Description-md5: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
 " aptcache show apt-both-$variant
 done
@@ -122,7 +119,7 @@ X-Some-Flag: yes
 
 testequal "Package: apt-intermixed2
 $PACKAGESTANZA
-$DESCRIPTION
+$TRANSDESCRIPTION
 Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 X-Some-Flag: yes
 X-Foo-Flag: Something with a Description
@@ -131,7 +128,7 @@ X-Bar-Flag: no
 
 testequal "Package: apt-intermixed3
 $PACKAGESTANZA
-$DESCRIPTION
+$TRANSDESCRIPTION
 Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 X-Some-Flag: yes
 X-Foo-Flag: Something with a Description
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
diff --git a/test/integration/test-bug-745036-new-foreign-invalidates-cache b/test/integration/test-bug-745036-new-foreign-invalidates-cache
new file mode 100755 (executable)
index 0000000..490cbec
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+insertpackage 'unstable' 'cool-foo' 'amd64' '1.0' 'Depends: foo'
+insertpackage 'unstable' 'foo' 'amd64' '1.0' 'Multi-Arch: foreign'
+insertinstalledpackage 'cool-foo' 'amd64' '1.0' 'Depends: foo'
+insertinstalledpackage 'foo' 'amd64' '1.0' 'Multi-Arch: foreign'
+
+setupaptarchive
+
+testsuccess aptget check -s
+
+configarchitecture 'amd64' 'i386'
+testequal 'E: The package cache was built for different architectures: amd64 vs amd64,i386' aptget check -s -o pkgCacheFile::Generate=false
+
+testsuccess aptget check -s
+
+insertinstalledpackage 'awesome-foo' 'i386' '1.0' 'Depends: foo'
+
+testsuccess aptget check -s
+
+testsuccess aptget update --no-download
+
+testsuccess aptget check -s
diff --git a/test/integration/test-bug-747261-arch-specific-conflicts b/test/integration/test-bug-747261-arch-specific-conflicts
new file mode 100755 (executable)
index 0000000..be971b8
--- /dev/null
@@ -0,0 +1,51 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64' 'sparc' 'armel'
+
+msgtest 'Check that dpkg supports' 'arch-specific dependencies'
+set +e
+# this fails always, the question is just how it fails
+dpkg-checkbuilddeps -d 'foobar:barfoo' /dev/null 2>/dev/null >/dev/null
+RETURNCODE=$?
+set -e
+if [ "$RETURNCODE" != '1' ]; then
+       dpkg-checkbuilddeps -d 'foobar:barfoo' /dev/null || true
+       echo "Command had returncode: $RETURNCODE"
+       msgskip
+       exit 0
+else
+       msgpass
+fi
+
+buildsimplenativepackage 'libc6' 'amd64,sparc,armel' '1' 'stable' 'Multi-Arch: same'
+buildsimplenativepackage 'libc6-i386' 'amd64' '1' 'stable' 'Conflicts: libc6:sparc'
+
+setupaptarchive
+
+testsuccess aptget install 'libc6:amd64' 'libc6:sparc' -y
+testdpkginstalled 'libc6:amd64' 'libc6:sparc'
+testdpkgnotinstalled 'libc6-i386' 'libc6:armel'
+
+testsuccess aptget install libc6-i386 -y
+testdpkginstalled 'libc6:amd64' 'libc6-i386'
+testdpkgnotinstalled 'libc6:sparc' 'libc6:armel'
+
+testsuccess aptget install libc6:armel -y
+testdpkginstalled 'libc6:amd64' 'libc6:armel' 'libc6-i386'
+testdpkgnotinstalled 'libc6:sparc'
+
+testsuccess aptget install libc6:sparc -y
+testdpkginstalled 'libc6:amd64' 'libc6:armel' 'libc6:sparc'
+testdpkgnotinstalled 'libc6-i386'
+
+testsuccess aptget purge 'libc6:*' 'libc6-i386' -y
+testdpkgnotinstalled 'libc6:amd64' 'libc6:armel' 'libc6:sparc' 'libc6-i386'
+
+# check that (the actually simpler) single arch is fine, too
+configarchitecture 'amd64'
+testfailure aptget install libc6:sparc -s
+testsuccess aptget install libc6 libc6-i386 -y
diff --git a/test/integration/test-debsrc-hashes b/test/integration/test-debsrc-hashes
deleted file mode 100755 (executable)
index 5e91723..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-set -e
-
-TESTDIR=$(readlink -f $(dirname $0))
-. $TESTDIR/framework
-
-setupenvironment
-configarchitecture "i386"
-
-# pkg-sha256-bad has a bad SHA sum, but good MD5 sum.  If apt is
-# checking the best available hash (as it should), this will trigger
-# a hash mismatch.
-
-cat > aptarchive/Sources <<EOF
-Package: pkg-md5-ok
-Binary: pkg-md5-ok
-Version: 1.0
-Maintainer: Joe Sixpack <joe@example.org>
-Architecture: i386
-Files:
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-ok_1.0.dsc
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-md5-ok_1.0.tar.gz
-
-Package: pkg-sha256-ok
-Binary: pkg-sha256-ok
-Version: 1.0
-Maintainer: Joe Sixpack <joe@example.org>
-Architecture: i386
-Files:
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-ok_1.0.dsc
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-ok_1.0.tar.gz
-Checksums-Sha1:
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-ok_1.0.dsc
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-ok_1.0.tar.gz
-Checksums-Sha256:
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-ok_1.0.dsc
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 pkg-sha256-ok_1.0.tar.gz
-
-Package: pkg-sha256-bad
-Binary: pkg-sha256-bad
-Version: 1.0
-Maintainer: Joe Sixpack <joe@example.org>
-Architecture: i386
-Files:
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-bad_1.0.dsc
- d41d8cd98f00b204e9800998ecf8427e 0 pkg-sha256-bad_1.0.tar.gz
-Checksums-Sha1:
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-bad_1.0.dsc
- da39a3ee5e6b4b0d3255bfef95601890afd80709 0 pkg-sha256-bad_1.0.tar.gz
-Checksums-Sha256:
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0 pkg-sha256-bad_1.0.dsc
- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0 pkg-sha256-bad_1.0.tar.gz
-EOF
-
-# create fetchable files
-for x in "pkg-md5-ok" "pkg-sha256-ok" "pkg-sha256-bad"; do
-    touch aptarchive/${x}_1.0.dsc
-    touch aptarchive/${x}_1.0.tar.gz
-done
-
-testok() {
-    msgtest "Test for hash ok of" "$*"
-    $* 2>&1 | grep "Download complete" > /dev/null && msgpass || msgfail
-}
-
-testmismatch() {
-    msgtest "Test for hash mismatch of" "$*"
-    $* 2>&1 | grep "Hash Sum mismatch" > /dev/null && msgpass || msgfail
-}
-
-setupaptarchive
-changetowebserver
-aptget update -qq
-
-testok aptget source -d pkg-md5-ok
-testok aptget source -d pkg-sha256-ok
-testmismatch aptget source -d pkg-sha256-bad
diff --git a/test/integration/test-http-pipeline-messup b/test/integration/test-http-pipeline-messup
new file mode 100755 (executable)
index 0000000..9c59e18
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+buildsimplenativepackage 'pkga' 'all' '1.0' 'stable'
+buildsimplenativepackage 'pkgb' 'all' '1.0' 'stable'
+buildsimplenativepackage 'pkgc' 'all' '1.0' 'stable'
+buildsimplenativepackage 'pkgd' 'all' '1.0' 'stable'
+
+setupaptarchive --no-update
+
+# simulate (and be a predictable) pipeline mess-up by the server/proxy
+changetowebserver \
+       -o 'aptwebserver::overwrite::.*pkga.*::filename=/pool/pkgd_1.0_all.deb' \
+       -o 'aptwebserver::overwrite::.*pkgc.*::filename=/pool/pkgb_1.0_all.deb' \
+       -o 'aptwebserver::overwrite::.*pkgb.*::filename=/pool/pkgc_1.0_all.deb' \
+       -o 'aptwebserver::overwrite::.*pkgd.*::filename=/pool/pkga_1.0_all.deb'
+
+testsuccess aptget update -o Debug::Acquire::http=1 -o Debug::pkgAcquire::Worker=1
+
+# messup is bigger than pipeline: checks if fixup isn't trying to hard
+testfailure aptget download pkga pkgb pkgc pkgd "$@" -o Acquire::http::Pipeline-Depth=2
+testfailure test -f pkga_1.0_all.deb
+
+# ensure that pipeling is enabled for rest of this test
+echo 'Acquire::http::Pipeline-Depth 10;' > rootdir/etc/apt/apt.conf.d/99enable-pipeline
+
+# the output is a bit strange: it looks like it has downloaded pkga 4 times
+testsuccess aptget download pkga pkgb pkgc pkgd -o Debug::Acquire::http=1 -o Debug::pkgAcquire::Worker=1
+for pkg in 'pkga' 'pkgb' 'pkgc' 'pkgd'; do
+       testsuccess test -f ${pkg}_1.0_all.deb
+       testsuccess cmp incoming/${pkg}_1.0_all.deb ${pkg}_1.0_all.deb
+       rm -f ${pkg}_1.0_all.deb
+done
+
+# while hashes will pass (as none are available), sizes will not match, so failure
+# checks that no hashes means that pipeline depth is ignored as we can't fixup
+testfailure aptget download pkga pkgb pkgc pkgd "$@" --allow-unauthenticated -o Acquire::ForceHash=ROT26
index c51caa7581f345971281f3b01283aca1fcaeb739..22c36890be4fa61690abc2a6c9faf296482fe871 100755 (executable)
@@ -9,7 +9,7 @@ configarchitecture 'amd64'
 # the executed script would use the installed apt-config,
 # which is outside of our control
 msgtest 'Check that the installed apt-config supports' '--no-empty'
-if apt-config dump --no-empty >/dev/null 2>&1; then
+if /usr/bin/apt-config dump --no-empty >/dev/null 2>&1; then
        msgpass
 else
        msgskip
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)
diff --git a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum
new file mode 100755 (executable)
index 0000000..8c9c9c7
--- /dev/null
@@ -0,0 +1,262 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture 'native'
+
+cat > aptarchive/Sources <<EOF
+Package: pkg-md5-ok
+Binary: pkg-md5-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-ok_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-ok_1.0.tar.gz
+
+Package: pkg-sha256-ok
+Binary: pkg-sha256-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-sha256-ok_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-sha256-ok_1.0.tar.gz
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-sha256-ok_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-sha256-ok_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-sha256-ok_1.0.dsc
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-sha256-ok_1.0.tar.gz
+
+Package: pkg-sha256-bad
+Binary: pkg-sha256-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-sha256-bad_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-sha256-bad_1.0.tar.gz
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-sha256-bad_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-sha256-bad_1.0.tar.gz
+Checksums-Sha256:
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-sha256-bad_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-sha256-bad_1.0.tar.gz
+
+Package: pkg-no-md5
+Binary: pkg-no-md5
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-no-md5_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-no-md5_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-no-md5_1.0.dsc
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-no-md5_1.0.tar.gz
+
+Package: pkg-mixed-ok
+Binary: pkg-mixed-ok
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-mixed-ok_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-mixed-ok_1.0.dsc
+
+Package: pkg-mixed-sha1-bad
+Binary: pkg-mixed-sha1-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-mixed-sha1-bad_1.0.dsc
+Checksums-Sha256:
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-mixed-sha1-bad_1.0.tar.gz
+
+Package: pkg-mixed-sha2-bad
+Binary: pkg-mixed-sha2-bad
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-mixed-sha2-bad_1.0.dsc
+Checksums-Sha256:
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-mixed-sha2-bad_1.0.tar.gz
+
+Package: pkg-md5-disagree
+Binary: pkg-md5-disagree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-disagree_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-disagree_1.0.tar.gz
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-md5-disagree_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-md5-disagree_1.0.tar.gz
+
+Package: pkg-md5-agree
+Binary: pkg-md5-agree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-agree_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-agree_1.0.tar.gz
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-md5-agree_1.0.tar.gz
+ 9604ba9427a280db542279d9ed78400b 3 pkg-md5-agree_1.0.dsc
+
+Package: pkg-sha256-disagree
+Binary: pkg-sha256-disagree
+Version: 1.0
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Files:
+ 9604ba9427a280db542279d9ed78400b 3 pkg-sha256-disagree_1.0.dsc
+ db5570bf61464b46e2bde31ed61a7dc6 3 pkg-sha256-disagree_1.0.tar.gz
+Checksums-Sha1:
+ 324f464e6151a92cf57b26ef95dcfcf2059a8c44 3 pkg-sha256-disagree_1.0.dsc
+ 680254bad1d7ca0d65ec46aaa315d363abf6a50a 3 pkg-sha256-disagree_1.0.tar.gz
+Checksums-Sha256:
+ 943d3bf22ac661fb0f59bc4ff68cc12b04ff17a838dfcc2537008eb9c7f3770a 3 pkg-sha256-disagree_1.0.dsc
+ 90aebae315675cbf04612de4f7d5874850f48e0b8dd82becbeaa47ca93f5ebfb 3 pkg-sha256-disagree_1.0.tar.gz
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 3 pkg-sha256-disagree_1.0.dsc
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3 pkg-sha256-disagree_1.0.tar.gz
+EOF
+
+# create fetchable files
+for x in 'pkg-md5-ok' 'pkg-sha256-ok' 'pkg-sha256-bad' 'pkg-no-md5' \
+        'pkg-mixed-ok' 'pkg-mixed-sha1-bad' 'pkg-mixed-sha2-bad' \
+        'pkg-md5-agree' 'pkg-md5-disagree' 'pkg-sha256-disagree'; do
+       echo -n 'dsc' > aptarchive/${x}_1.0.dsc
+       echo -n 'tar' > aptarchive/${x}_1.0.tar.gz
+done
+
+setupaptarchive
+changetowebserver
+testsuccess aptget update
+
+testok() {
+       rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+       testequal "Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/  $1 1.0 (dsc) [3 B]
+Get:2 http://localhost:8080/  $1 1.0 (tar) [3 B]
+Download complete and in download only mode" aptget source -d "$@"
+       msgtest 'Files were successfully downloaded for' "$1"
+       testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+       rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+}
+
+testkeep() {
+       echo -n 'dsc' > ${1}_1.0.dsc
+       echo -n 'tar' > ${1}_1.0.tar.gz
+       testequal "Reading package lists...
+Building dependency tree...
+Skipping already downloaded file '${1}_1.0.dsc'
+Skipping already downloaded file '${1}_1.0.tar.gz'
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d "$@"
+       msgtest 'Files already downloaded are kept for' "$1"
+       testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+       rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+}
+
+testmismatch() {
+       rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+       testequal "Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/  $1 1.0 (dsc) [3 B]
+Get:2 http://localhost:8080/  $1 1.0 (tar) [3 B]
+E: Failed to fetch http://localhost:8080/${1}_1.0.dsc  Hash Sum mismatch
+
+E: Failed to fetch http://localhost:8080/${1}_1.0.tar.gz  Hash Sum mismatch
+
+E: Failed to fetch some archives." aptget source -d "$@"
+       msgtest 'Files were not download as they have hashsum mismatches for' "$1"
+       testfailure --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+
+       rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+       testequal "Reading package lists...
+Building dependency tree...
+Skipping download of file 'pkg-sha256-bad_1.0.dsc' as requested hashsum is not available for authentication
+Skipping download of file 'pkg-sha256-bad_1.0.tar.gz' as requested hashsum is not available for authentication
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d "$@" -o Acquire::ForceHash=ROT26
+       msgtest 'Files were not download as hash is unavailable for' "$1"
+       testfailure --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+
+       rm -f ${1}_1.0.dsc ${1}_1.0.tar.gz
+       testequal "Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/  $1 1.0 (dsc) [3 B]
+Get:2 http://localhost:8080/  $1 1.0 (tar) [3 B]
+Download complete and in download only mode" aptget source --allow-unauthenticated -d "$@" -o Acquire::ForceHash=ROT26
+       msgtest 'Files were downloaded unauthenticated as user allowed it' "$1"
+       testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz
+}
+
+testok pkg-md5-ok
+testkeep pkg-md5-ok
+testok pkg-sha256-ok
+testkeep pkg-sha256-ok
+
+# pkg-sha256-bad has a bad SHA sum, but good MD5 sum.  If apt is
+# checking the best available hash (as it should), this will trigger
+# a hash mismatch.
+testmismatch pkg-sha256-bad
+testmismatch pkg-sha256-bad
+testok pkg-sha256-bad -o Acquire::ForceHash=MD5Sum
+
+# not having MD5 sum doesn't mean the file doesn't exist at all …
+testok pkg-no-md5
+testok pkg-no-md5 -o Acquire::ForceHash=SHA256
+testequal "Reading package lists...
+Building dependency tree...
+Skipping download of file 'pkg-no-md5_1.0.dsc' as requested hashsum is not available for authentication
+Skipping download of file 'pkg-no-md5_1.0.tar.gz' as requested hashsum is not available for authentication
+Need to get 0 B of source archives.
+Download complete and in download only mode" aptget source -d pkg-no-md5 -o Acquire::ForceHash=MD5Sum
+msgtest 'Files were not download as MD5 is not available for this package' 'pkg-no-md5'
+testfailure --nomsg test -e pkg-no-md5_1.0.dsc -a -e pkg-no-md5_1.0.tar.gz
+
+# deal with cases in which we haven't for all files the same checksum type
+# mostly pathologic as this shouldn't happen, but just to be sure
+testok pkg-mixed-ok
+testequal 'Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/  pkg-mixed-sha1-bad 1.0 (tar) [3 B]
+Get:2 http://localhost:8080/  pkg-mixed-sha1-bad 1.0 (dsc) [3 B]
+E: Failed to fetch http://localhost:8080/pkg-mixed-sha1-bad_1.0.dsc  Hash Sum mismatch
+
+E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha1-bad
+msgtest 'Only tar file is downloaded as the dsc has hashsum mismatch' 'pkg-mixed-sha1-bad'
+testsuccess --nomsg test ! -e pkg-mixed-sha1-bad_1.0.dsc -a -e pkg-mixed-sha1-bad_1.0.tar.gz
+testequal 'Reading package lists...
+Building dependency tree...
+Need to get 6 B of source archives.
+Get:1 http://localhost:8080/  pkg-mixed-sha2-bad 1.0 (tar) [3 B]
+Get:2 http://localhost:8080/  pkg-mixed-sha2-bad 1.0 (dsc) [3 B]
+E: Failed to fetch http://localhost:8080/pkg-mixed-sha2-bad_1.0.tar.gz  Hash Sum mismatch
+
+E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha2-bad
+msgtest 'Only dsc file is downloaded as the tar has hashsum mismatch' 'pkg-mixed-sha2-bad'
+testsuccess --nomsg test -e pkg-mixed-sha2-bad_1.0.dsc -a ! -e pkg-mixed-sha2-bad_1.0.tar.gz
+
+# it gets even more pathologic: multiple entries for one file, some even disagreeing!
+testok pkg-md5-agree
+testequal 'Reading package lists...
+Building dependency tree...
+E: Error parsing checksum in Files of source package pkg-md5-disagree' aptget source -d pkg-md5-disagree
+testequal 'Reading package lists...
+Building dependency tree...
+E: Error parsing checksum in Checksums-SHA256 of source package pkg-sha256-disagree' aptget source -d pkg-sha256-disagree
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 c06d85e037a8d4191ab1b5eb29aa3781456e926c..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);
    {
@@ -207,16 +214,118 @@ TEST(HashSumsTest, FileBased)
    }
    fd.Close();
 
-   {
-      HashString sha2("SHA256", sha256.Value());
-      EXPECT_TRUE(sha2.VerifyFile(__FILE__));
-   }
-   {
-      HashString sha2("SHA512", sha512.Value());
-      EXPECT_TRUE(sha2.VerifyFile(__FILE__));
-   }
-   {
-      HashString sha2("SHA256:" + sha256.Value());
-      EXPECT_TRUE(sha2.VerifyFile(__FILE__));
-   }
+   HashString sha2file("SHA512", sha512.Value());
+   EXPECT_TRUE(sha2file.VerifyFile(__FILE__));
+   HashString sha2wrong("SHA512", "00000000000");
+   EXPECT_FALSE(sha2wrong.VerifyFile(__FILE__));
+   EXPECT_EQ(sha2file, sha2file);
+   EXPECT_TRUE(sha2file == sha2file);
+   EXPECT_NE(sha2file, sha2wrong);
+   EXPECT_TRUE(sha2file != sha2wrong);
+
+   HashString sha2big("SHA256", sha256.Value());
+   EXPECT_TRUE(sha2big.VerifyFile(__FILE__));
+   HashString sha2small("sha256:" + sha256.Value());
+   EXPECT_TRUE(sha2small.VerifyFile(__FILE__));
+   EXPECT_EQ(sha2big, sha2small);
+   EXPECT_TRUE(sha2big == sha2small);
+   EXPECT_FALSE(sha2big != sha2small);
+
+   HashStringList hashes;
+   EXPECT_TRUE(hashes.empty());
+   EXPECT_TRUE(hashes.push_back(sha2file));
+   EXPECT_FALSE(hashes.empty());
+   EXPECT_EQ(1, hashes.size());
+
+   HashStringList wrong;
+   EXPECT_TRUE(wrong.push_back(sha2wrong));
+   EXPECT_NE(wrong, hashes);
+   EXPECT_FALSE(wrong == hashes);
+   EXPECT_TRUE(wrong != hashes);
+
+   HashStringList similar;
+   EXPECT_TRUE(similar.push_back(sha2big));
+   EXPECT_NE(similar, hashes);
+   EXPECT_FALSE(similar == hashes);
+   EXPECT_TRUE(similar != hashes);
+
+   EXPECT_TRUE(hashes.push_back(sha2big));
+   EXPECT_EQ(2, hashes.size());
+   EXPECT_TRUE(hashes.push_back(sha2small));
+   EXPECT_EQ(2, hashes.size());
+   EXPECT_FALSE(hashes.push_back(sha2wrong));
+   EXPECT_EQ(2, hashes.size());
+   EXPECT_TRUE(hashes.VerifyFile(__FILE__));
+
+   EXPECT_EQ(similar, hashes);
+   EXPECT_TRUE(similar == hashes);
+   EXPECT_FALSE(similar != hashes);
+   similar.clear();
+   EXPECT_TRUE(similar.empty());
+   EXPECT_EQ(0, similar.size());
+   EXPECT_NE(similar, hashes);
+   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");
 }
index 1bac75b55add725a26022f8ef5fe2bad065c798b..df618ea1617183f64e5963b5e2b3fb5b870edd71 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sstream>
 
 #include <gtest/gtest.h>
 
@@ -34,3 +35,181 @@ TEST(TagFileTest,SingleField)
    // There is only one section in this tag file
    EXPECT_FALSE(tfile.Step(section));
 }
+
+TEST(TagFileTest,MultipleSections)
+{
+   FileFd fd;
+   createTemporaryFile("bigsection", fd, NULL, "Package: pkgA\n"
+        "Version: 1\n"
+        "Size: 100\n"
+        "Description: aaa\n"
+        " aaa\n"
+        "\n"
+        "Package: pkgB\n"
+        "Version: 1\n"
+        "Flag: no\n"
+        "Description: bbb\n"
+        "\n"
+        "Package: pkgC\n"
+        "Version: 2\n"
+        "Flag: yes\n"
+        "Description:\n"
+        " ccc\n"
+        );
+
+   pkgTagFile tfile(&fd);
+   pkgTagSection section;
+   EXPECT_FALSE(section.Exists("Version"));
+
+   EXPECT_TRUE(tfile.Step(section));
+   EXPECT_EQ(4, section.Count());
+   EXPECT_TRUE(section.Exists("Version"));
+   EXPECT_TRUE(section.Exists("Package"));
+   EXPECT_TRUE(section.Exists("Size"));
+   EXPECT_FALSE(section.Exists("Flag"));
+   EXPECT_TRUE(section.Exists("Description"));
+   EXPECT_EQ("pkgA", section.FindS("Package"));
+   EXPECT_EQ("1", section.FindS("Version"));
+   EXPECT_EQ(1, section.FindULL("Version"));
+   EXPECT_EQ(100, section.FindULL("Size"));
+   unsigned long Flags = 1;
+   EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+   EXPECT_EQ(1, Flags);
+   Flags = 0;
+   EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+   EXPECT_EQ(0, Flags);
+   EXPECT_EQ("aaa\n aaa", section.FindS("Description"));
+
+
+   EXPECT_TRUE(tfile.Step(section));
+   EXPECT_EQ(4, section.Count());
+   EXPECT_TRUE(section.Exists("Version"));
+   EXPECT_TRUE(section.Exists("Package"));
+   EXPECT_FALSE(section.Exists("Size"));
+   EXPECT_TRUE(section.Exists("Flag"));
+   EXPECT_TRUE(section.Exists("Description"));
+   EXPECT_EQ("pkgB", section.FindS("Package"));
+   EXPECT_EQ("1", section.FindS("Version"));
+   EXPECT_EQ(1, section.FindULL("Version"));
+   EXPECT_EQ(0, section.FindULL("Size"));
+   Flags = 1;
+   EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+   EXPECT_EQ(0, Flags);
+   Flags = 0;
+   EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+   EXPECT_EQ(0, Flags);
+   EXPECT_EQ("bbb", section.FindS("Description"));
+
+   EXPECT_TRUE(tfile.Step(section));
+   EXPECT_EQ(4, section.Count());
+   EXPECT_TRUE(section.Exists("Version"));
+   EXPECT_TRUE(section.Exists("Package"));
+   EXPECT_FALSE(section.Exists("Size"));
+   EXPECT_TRUE(section.Exists("Flag"));
+   EXPECT_TRUE(section.Exists("Description"));
+   EXPECT_EQ("pkgC", section.FindS("Package"));
+   EXPECT_EQ("2", section.FindS("Version"));
+   EXPECT_EQ(2, section.FindULL("Version"));
+   Flags = 0;
+   EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+   EXPECT_EQ(1, Flags);
+   Flags = 1;
+   EXPECT_TRUE(section.FindFlag("Flag", Flags, 1));
+   EXPECT_EQ(1, Flags);
+   EXPECT_EQ("ccc", section.FindS("Description"));
+
+   // There is no section left in this tag file
+   EXPECT_FALSE(tfile.Step(section));
+}
+
+TEST(TagFileTest,BigSection)
+{
+   size_t const count = 500;
+   std::stringstream content;
+   for (size_t i = 0; i < count; ++i)
+      content << "Field-" << i << ": " << (2000 + i) << std::endl;
+
+   FileFd fd;
+   createTemporaryFile("bigsection", fd, NULL, content.str().c_str());
+
+   pkgTagFile tfile(&fd);
+   pkgTagSection section;
+   EXPECT_TRUE(tfile.Step(section));
+
+   EXPECT_EQ(count, section.Count());
+   for (size_t i = 0; i < count; ++i)
+   {
+      std::stringstream name;
+      name << "Field-" << i;
+      EXPECT_TRUE(section.Exists(name.str().c_str())) << name.str() << " does not exist";
+      EXPECT_EQ((2000 + i), section.FindULL(name.str().c_str()));
+   }
+
+   // There is only one section in this tag file
+   EXPECT_FALSE(tfile.Step(section));
+}
+
+TEST(TagFileTest, PickedUpFromPreviousCall)
+{
+   size_t const count = 500;
+   std::stringstream contentstream;
+   for (size_t i = 0; i < count; ++i)
+      contentstream << "Field-" << i << ": " << (2000 + i) << std::endl;
+   contentstream << std::endl << std::endl;
+   std::string content = contentstream.str();
+
+   pkgTagSection section;
+   EXPECT_FALSE(section.Scan(content.c_str(), content.size()/2));
+   EXPECT_NE(0, section.Count());
+   EXPECT_NE(count, section.Count());
+   EXPECT_TRUE(section.Scan(content.c_str(), content.size(), false));
+   EXPECT_EQ(count, section.Count());
+
+   for (size_t i = 0; i < count; ++i)
+   {
+      std::stringstream name;
+      name << "Field-" << i;
+      EXPECT_TRUE(section.Exists(name.str().c_str())) << name.str() << " does not exist";
+      EXPECT_EQ((2000 + i), section.FindULL(name.str().c_str()));
+   }
+}
+
+TEST(TagFileTest, SpacesEverywhere)
+{
+   std::string content =
+      "Package: pkgA\n"
+      "Package: pkgB\n"
+      "NoSpaces:yes\n"
+      "TagSpaces\t    :yes\n"
+      "ValueSpaces:   \tyes\n"
+      "BothSpaces     \t:\t   yes\n"
+      "TrailingSpaces: yes\t   \n"
+      "Naming Space: yes\n"
+      "Naming  Spaces: yes\n"
+      "Package    :   pkgC    \n"
+      "Multi-Colon::yes:\n"
+      "\n\n";
+
+   pkgTagSection section;
+   EXPECT_TRUE(section.Scan(content.c_str(), content.size()));
+   EXPECT_TRUE(section.Exists("Package"));
+   EXPECT_TRUE(section.Exists("NoSpaces"));
+   EXPECT_TRUE(section.Exists("TagSpaces"));
+   EXPECT_TRUE(section.Exists("ValueSpaces"));
+   EXPECT_TRUE(section.Exists("BothSpaces"));
+   EXPECT_TRUE(section.Exists("TrailingSpaces"));
+   EXPECT_TRUE(section.Exists("Naming Space"));
+   EXPECT_TRUE(section.Exists("Naming  Spaces"));
+   EXPECT_TRUE(section.Exists("Multi-Colon"));
+   EXPECT_EQ("pkgC", section.FindS("Package"));
+   EXPECT_EQ("yes", section.FindS("NoSpaces"));
+   EXPECT_EQ("yes", section.FindS("TagSpaces"));
+   EXPECT_EQ("yes", section.FindS("ValueSpaces"));
+   EXPECT_EQ("yes", section.FindS("BothSpaces"));
+   EXPECT_EQ("yes", section.FindS("TrailingSpaces"));
+   EXPECT_EQ("yes", section.FindS("Naming Space"));
+   EXPECT_EQ("yes", section.FindS("Naming  Spaces"));
+   EXPECT_EQ(":yes:", section.FindS("Multi-Colon"));
+   // overridden values are still present, but not really accessible
+   EXPECT_EQ(11, section.Count());
+}