]> git.saurik.com Git - apt.git/commitdiff
merged with apt--mvo
authorMichael Vogt <egon@tas>
Thu, 7 Dec 2006 10:45:13 +0000 (11:45 +0100)
committerMichael Vogt <egon@tas>
Thu, 7 Dec 2006 10:45:13 +0000 (11:45 +0100)
1  2 
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
doc/examples/configure-index

diff --combined apt-pkg/acquire-item.cc
index 6831abd545ce84da10e1efa67a53a29b8b913ea7,8ec4ba2c0b6c2b4d5fb229201e6b7e61a004d024..46c9d6c2c372cf938ecaaea22d2c7f86bdf48793
@@@ -24,8 -24,6 +24,8 @@@
  #include <apt-pkg/strutl.h>
  #include <apt-pkg/fileutl.h>
  #include <apt-pkg/md5.h>
 +#include <apt-pkg/sha1.h>
 +#include <apt-pkg/tagfile.h>
  
  #include <apti18n.h>
      
@@@ -33,7 -31,6 +33,7 @@@
  #include <unistd.h>
  #include <errno.h>
  #include <string>
 +#include <sstream>
  #include <stdio.h>
                                                                        /*}}}*/
  
@@@ -103,8 -100,7 +103,8 @@@ void pkgAcquire::Item::Done(string Mess
  {
     // We just downloaded something..
     string FileName = LookupTag(Message,"Filename");
 -   if (Complete == false && FileName == DestFile)
 +   // we only inform the Log class if it was actually not a local thing
 +   if (Complete == false && !Local && FileName == DestFile)
     {
        if (Owner->Log != 0)
         Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
@@@ -135,430 -131,14 +135,430 @@@ void pkgAcquire::Item::Rename(string Fr
  }
                                                                        /*}}}*/
  
 +
 +// AcqDiffIndex::AcqDiffIndex - Constructor                   
 +// ---------------------------------------------------------------------
 +/* Get the DiffIndex file first and see if there are patches availabe 
 + * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
 + * patches. If anything goes wrong in that process, it will fall back to
 + * the original packages file
 + */
 +pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
 +                               string URI,string URIDesc,string ShortDesc,
 +                               string ExpectedMD5)
 +   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc)
 +{
 +   
 +   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
 +
 +   Desc.Description = URIDesc + "/DiffIndex";
 +   Desc.Owner = this;
 +   Desc.ShortDesc = ShortDesc;
 +   Desc.URI = URI + ".diff/Index";
 +
 +   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 +   DestFile += URItoFileName(URI) + string(".DiffIndex");
 +
 +   if(Debug)
 +      std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
 +
 +   // look for the current package file
 +   CurrentPackagesFile = _config->FindDir("Dir::State::lists");
 +   CurrentPackagesFile += URItoFileName(RealURI);
 +
 +   // FIXME: this file:/ check is a hack to prevent fetching
 +   //        from local sources. this is really silly, and
 +   //        should be fixed cleanly as soon as possible
 +   if(!FileExists(CurrentPackagesFile) || 
 +      Desc.URI.substr(0,strlen("file:/")) == "file:/")
 +   {
 +      // we don't have a pkg file or we don't want to queue
 +      if(Debug)
 +       std::clog << "No index file, local or canceld by user" << std::endl;
 +      Failed("", NULL);
 +      return;
 +   }
 +
 +   if(Debug) 
 +      std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " 
 +              << CurrentPackagesFile << std::endl;
 +   
 +   QueueURI(Desc);
 +
 +}
 +
 +// AcqIndex::Custom600Headers - Insert custom request headers         /*{{{*/
 +// ---------------------------------------------------------------------
 +/* The only header we use is the last-modified header. */
 +string pkgAcqDiffIndex::Custom600Headers()
 +{
 +   string Final = _config->FindDir("Dir::State::lists");
 +   Final += URItoFileName(RealURI) + string(".IndexDiff");
 +   
 +   if(Debug)
 +      std::clog << "Custom600Header-IMS: " << Final << std::endl;
 +
 +   struct stat Buf;
 +   if (stat(Final.c_str(),&Buf) != 0)
 +      return "\nIndex-File: true";
 +   
 +   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 +}
 +
 +
 +bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
 +{
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile 
 +              << std::endl;
 +
 +   pkgTagSection Tags;
 +   string ServerSha1;
 +   vector<DiffInfo> available_patches;
 +   
 +   FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
 +   pkgTagFile TF(&Fd);
 +   if (_error->PendingError() == true)
 +      return false;
 +
 +   if(TF.Step(Tags) == true)
 +   {
 +      string local_sha1;
 +      bool found = false;
 +      DiffInfo d;
 +      string size;
 +
 +      string tmp = Tags.FindS("SHA1-Current");
 +      std::stringstream ss(tmp);
 +      ss >> ServerSha1;
 +
 +      FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
 +      SHA1Summation SHA1;
 +      SHA1.AddFD(fd.Fd(), fd.Size());
 +      local_sha1 = string(SHA1.Result());
 +
 +      if(local_sha1 == ServerSha1) 
 +      {
 +       // we have the same sha1 as the server
 +       if(Debug)
 +          std::clog << "Package file is up-to-date" << std::endl;
 +       // set found to true, this will queue a pkgAcqIndexDiffs with
 +       // a empty availabe_patches
 +       found = true;
 +      } 
 +      else 
 +      {
 +       if(Debug)
 +          std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
 +
 +       // check the historie and see what patches we need
 +       string history = Tags.FindS("SHA1-History");     
 +       std::stringstream hist(history);
 +       while(hist >> d.sha1 >> size >> d.file) 
 +       {
 +          d.size = atoi(size.c_str());
 +          // read until the first match is found
 +          if(d.sha1 == local_sha1) 
 +             found=true;
 +          // from that point on, we probably need all diffs
 +          if(found) 
 +          {
 +             if(Debug)
 +                std::clog << "Need to get diff: " << d.file << std::endl;
 +             available_patches.push_back(d);
 +          }
 +       }
 +      }
 +
 +      // we have something, queue the next diff
 +      if(found) 
 +      {
 +       // queue the diffs
 +       new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
 +                            ExpectedMD5, available_patches);
 +       Complete = false;
 +       Status = StatDone;
 +       Dequeue();
 +       return true;
 +      }
 +   }
 +
 +   // Nothing found, report and return false
 +   // Failing here is ok, if we return false later, the full
 +   // IndexFile is queued
 +   if(Debug)
 +      std::clog << "Can't find a patch in the index file" << std::endl;
 +   return false;
 +}
 +
 +void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 +{
 +   if(Debug)
 +      std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << std::endl
 +              << "Falling back to normal index file aquire" << std::endl;
 +
 +   new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc, 
 +                 ExpectedMD5);
 +
 +   Complete = false;
 +   Status = StatDone;
 +   Dequeue();
 +}
 +
 +void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
 +                         pkgAcquire::MethodConfig *Cnf)
 +{
 +   if(Debug)
 +      std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl;
 +
 +   Item::Done(Message,Size,Md5Hash,Cnf);
 +
 +   string FinalFile;
 +   FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
 +
 +   // sucess in downloading the index
 +   // rename the index
 +   FinalFile += string(".IndexDiff");
 +   if(Debug)
 +      std::clog << "Renaming: " << DestFile << " -> " << FinalFile 
 +              << std::endl;
 +   Rename(DestFile,FinalFile);
 +   chmod(FinalFile.c_str(),0644);
 +   DestFile = FinalFile;
 +
 +   if(!ParseDiffIndex(DestFile))
 +      return Failed("", NULL);
 +
 +   Complete = true;
 +   Status = StatDone;
 +   Dequeue();
 +   return;
 +}
 +
 +
 +
 +// AcqIndexDiffs::AcqIndexDiffs - Constructor                 
 +// ---------------------------------------------------------------------
 +/* The package diff is added to the queue. one object is constructed
 + * for each diff and the index
 + */
 +pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
 +                                 string URI,string URIDesc,string ShortDesc,
 +                                 string ExpectedMD5, vector<DiffInfo> diffs)
 +   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), 
 +     available_patches(diffs)
 +{
 +   
 +   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 +   DestFile += URItoFileName(URI);
 +
 +   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
 +
 +   Desc.Description = URIDesc;
 +   Desc.Owner = this;
 +   Desc.ShortDesc = ShortDesc;
 +
 +   if(available_patches.size() == 0) 
 +   {
 +      // we are done (yeah!)
 +      Finish(true);
 +   }
 +   else
 +   {
 +      // get the next diff
 +      State = StateFetchDiff;
 +      QueueNextDiff();
 +   }
 +}
 +
 +
 +void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 +{
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
 +              << "Falling back to normal index file aquire" << std::endl;
 +   new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, 
 +                 ExpectedMD5);
 +   Finish();
 +}
 +
 +
 +// helper that cleans the item out of the fetcher queue
 +void pkgAcqIndexDiffs::Finish(bool allDone)
 +{
 +   // we restore the original name, this is required, otherwise
 +   // the file will be cleaned
 +   if(allDone) 
 +   {
 +      DestFile = _config->FindDir("Dir::State::lists");
 +      DestFile += URItoFileName(RealURI);
 +
 +      // do the final md5sum checking
 +      MD5Summation sum;
 +      FileFd Fd(DestFile, FileFd::ReadOnly);
 +      sum.AddFD(Fd.Fd(), Fd.Size());
 +      Fd.Close();
 +      string MD5 = (string)sum.Result();
 +
 +      if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
 +      {
 +       Status = StatAuthError;
 +       ErrorText = _("MD5Sum mismatch");
 +       Rename(DestFile,DestFile + ".FAILED");
 +       Dequeue();
 +       return;
 +      }
 +
 +      // this is for the "real" finish
 +      Complete = true;
 +      Status = StatDone;
 +      Dequeue();
 +      if(Debug)
 +       std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl;
 +      return;
 +   }
 +
 +   if(Debug)
 +      std::clog << "Finishing: " << Desc.URI << std::endl;
 +   Complete = false;
 +   Status = StatDone;
 +   Dequeue();
 +   return;
 +}
 +
 +
 +
 +bool pkgAcqIndexDiffs::QueueNextDiff()
 +{
 +
 +   // calc sha1 of the just patched file
 +   string FinalFile = _config->FindDir("Dir::State::lists");
 +   FinalFile += URItoFileName(RealURI);
 +
 +   FileFd fd(FinalFile, FileFd::ReadOnly);
 +   SHA1Summation SHA1;
 +   SHA1.AddFD(fd.Fd(), fd.Size());
 +   string local_sha1 = string(SHA1.Result());
 +   if(Debug)
 +      std::clog << "QueueNextDiff: " 
 +              << FinalFile << " (" << local_sha1 << ")"<<std::endl;
 +
 +   // remove all patches until the next matching patch is found
 +   // this requires the Index file to be ordered
 +   for(vector<DiffInfo>::iterator I=available_patches.begin();
 +       available_patches.size() > 0 && 
 +        I != available_patches.end() &&
 +        (*I).sha1 != local_sha1; 
 +       I++) 
 +   {
 +      available_patches.erase(I);
 +   }
 +
 +   // error checking and falling back if no patch was found
 +   if(available_patches.size() == 0) 
 +   { 
 +      Failed("", NULL);
 +      return false;
 +   }
 +
 +   // queue the right diff
 +   Desc.URI = string(RealURI) + ".diff/" + available_patches[0].file + ".gz";
 +   Desc.Description = available_patches[0].file + string(".pdiff");
 +
 +   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
 +   DestFile += URItoFileName(RealURI + ".diff/" + available_patches[0].file);
 +
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
 +   
 +   QueueURI(Desc);
 +
 +   return true;
 +}
 +
 +
 +
 +void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
 +                          pkgAcquire::MethodConfig *Cnf)
 +{
 +   if(Debug)
 +      std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl;
 +
 +   Item::Done(Message,Size,Md5Hash,Cnf);
 +
 +   string FinalFile;
 +   FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
 +
 +   // sucess in downloading a diff, enter ApplyDiff state
 +   if(State == StateFetchDiff) 
 +   {
 +
 +      if(Debug)
 +       std::clog << "Sending to gzip method: " << FinalFile << std::endl;
 +
 +      string FileName = LookupTag(Message,"Filename");
 +      State = StateUnzipDiff;
 +      Local = true;
 +      Desc.URI = "gzip:" + FileName;
 +      DestFile += ".decomp";
 +      QueueURI(Desc);
 +      Mode = "gzip";
 +      return;
 +   } 
 +
 +   // sucess in downloading a diff, enter ApplyDiff state
 +   if(State == StateUnzipDiff) 
 +   {
 +
 +      // rred excepts the patch as $FinalFile.ed
 +      Rename(DestFile,FinalFile+".ed");
 +
 +      if(Debug)
 +       std::clog << "Sending to rred method: " << FinalFile << std::endl;
 +
 +      State = StateApplyDiff;
 +      Local = true;
 +      Desc.URI = "rred:" + FinalFile;
 +      QueueURI(Desc);
 +      Mode = "rred";
 +      return;
 +   } 
 +
 +
 +   // success in download/apply a diff, queue next (if needed)
 +   if(State == StateApplyDiff)
 +   {
 +      // remove the just applied patch
 +      available_patches.erase(available_patches.begin());
 +
 +      // move into place
 +      if(Debug) 
 +      {
 +       std::clog << "Moving patched file in place: " << std::endl
 +                 << DestFile << " -> " << FinalFile << std::endl;
 +      }
 +      Rename(DestFile,FinalFile);
 +      chmod(FinalFile.c_str(),0644);
 +
 +      // see if there is more to download
 +      if(available_patches.size() > 0) {
 +       new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
 +                            ExpectedMD5, available_patches);
 +       return Finish();
 +      } else 
 +       return Finish(true);
 +   }
 +}
 +
 +
  // AcqIndex::AcqIndex - Constructor                                   /*{{{*/
  // ---------------------------------------------------------------------
  /* The package file is added to the queue and a second class is 
     instantiated to fetch the revision file */   
  pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
                         string URI,string URIDesc,string ShortDesc,
 -                       string ExpectedMD5, string comprExt) :
 -   Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
 +                       string ExpectedMD5, string comprExt)
 +   Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
  {
     Decompression = false;
     Erase = false;
     if(comprExt.empty()) 
     {
        // autoselect the compression method
-       if(FileExists("/usr/bin/bzip2")) 
+       if(FileExists("/bin/bzip2")) 
         CompressionExtension = ".bz2";
        else 
         CompressionExtension = ".gz";
@@@ -604,7 -184,7 +604,7 @@@ string pkgAcqIndex::Custom600Headers(
  void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
  {
     // no .bz2 found, retry with .gz
-    if(Desc.URI.substr(Desc.URI.size()-3,Desc.URI.size()-1) == "bz2") {
+    if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") {
        Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz"; 
  
        // retry with a gzip one 
@@@ -710,7 -290,7 +710,7 @@@ void pkgAcqIndex::Done(string Message,u
     else
        Local = true;
     
-    string compExt = Desc.URI.substr(Desc.URI.size()-3,Desc.URI.size()-1);
+    string compExt = Desc.URI.substr(Desc.URI.size()-3);
     char *decompProg;
     if(compExt == "bz2") 
        decompProg = "bzip2";
@@@ -735,10 -315,9 +735,9 @@@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquir
                             const vector<IndexTarget*>* IndexTargets,
                             indexRecords* MetaIndexParser) :
     Item(Owner), RealURI(URI), MetaIndexURI(MetaIndexURI),
-    MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc)
+    MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
+    MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets)
  {
-    this->MetaIndexParser = MetaIndexParser;
-    this->IndexTargets = IndexTargets;
     DestFile = _config->FindDir("Dir::State::lists") + "partial/";
     DestFile += URItoFileName(URI);
  
        // File was already in place.  It needs to be re-verified
        // because Release might have changed, so Move it into partial
        Rename(Final,DestFile);
-       // unlink the file and do not try to use I-M-S and Last-Modified
-       // if the users proxy is broken
-       if(_config->FindB("Acquire::BrokenProxy", false) == true) {
-        std::cerr << "forcing re-get of the signature file as requested" << std::endl;
-        unlink(DestFile.c_str());
-       }
     }
  
     QueueURI(Desc);
@@@ -816,18 -389,19 +809,19 @@@ void pkgAcqMetaSig::Done(string Message
                                                                        /*}}}*/
  void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
  {
-    // Delete any existing sigfile, so that this source isn't
-    // mistakenly trusted
-    string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
-    unlink(Final.c_str());
  
-    // if we get a timeout if fail
+    // if we get a network error we fail gracefully
     if(LookupTag(Message,"FailReason") == "Timeout" || 
-       LookupTag(Message,"FailReason") == "TmpResolveFailure") {
+       LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
+       LookupTag(Message,"FailReason") == "ConnectionRefused") {
        Item::Failed(Message,Cnf);
        return;
     }
  
+    // Delete any existing sigfile when the acquire failed
+    string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+    unlink(Final.c_str());
     // queue a pkgAcqMetaIndex with no sigfile
     new pkgAcqMetaIndex(Owner, MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
                       "", IndexTargets, MetaIndexParser);
@@@ -850,11 -424,9 +844,9 @@@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcq
                                 string SigFile,
                                 const vector<struct IndexTarget*>* IndexTargets,
                                 indexRecords* MetaIndexParser) :
-   Item(Owner), RealURI(URI), SigFile(SigFile)
+    Item(Owner), RealURI(URI), SigFile(SigFile), AuthPass(false),
+    MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets), IMSHit(false)
  {
-    this->AuthPass = false;
-    this->MetaIndexParser = MetaIndexParser;
-    this->IndexTargets = IndexTargets;
     DestFile = _config->FindDir("Dir::State::lists") + "partial/";
     DestFile += URItoFileName(URI);
  
@@@ -946,6 -518,9 +938,9 @@@ void pkgAcqMetaIndex::RetrievalDone(str
        return;
     }
  
+    // see if the download was a IMSHit
+    IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false);
     Complete = true;
  
     string FinalFile = _config->FindDir("Dir::State::lists");
        // Move it into position
        Rename(DestFile,FinalFile);
     }
 +   chmod(FinalFile.c_str(),0644);
     DestFile = FinalFile;
  }
  
@@@ -975,7 -549,7 +970,7 @@@ void pkgAcqMetaIndex::AuthDone(string M
        return;
     }
  
-    if (!VerifyVendor())
+    if (!VerifyVendor(Message))
     {
        return;
     }
@@@ -1027,18 -601,13 +1022,18 @@@ void pkgAcqMetaIndex::QueueIndexes(boo
           }
        }
        
 -      // Queue Packages file
 -      new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 -                      (*Target)->ShortDesc, ExpectedIndexMD5);
 +      // Queue Packages file (either diff or full packages files, depending
 +      // on the users option)
 +      if(_config->FindB("Acquire::PDiffs",true) == true) 
 +       new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
 +                           (*Target)->ShortDesc, ExpectedIndexMD5);
 +      else 
 +       new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 +                          (*Target)->ShortDesc, ExpectedIndexMD5);
     }
  }
  
- bool pkgAcqMetaIndex::VerifyVendor()
+ bool pkgAcqMetaIndex::VerifyVendor(string Message)
  {
  //    // Maybe this should be made available from above so we don't have
  //    // to read and parse it every time?
  //          break;
  //       }
  //    }
+    string::size_type pos;
+    // check for missing sigs (that where not fatal because otherwise we had
+    // bombed earlier)
+    string missingkeys;
+    string msg = _("There is no public key available for the "
+                 "following key IDs:\n");
+    pos = Message.find("NO_PUBKEY ");
+    if (pos != std::string::npos)
+    {
+       string::size_type start = pos+strlen("NO_PUBKEY ");
+       string Fingerprint = Message.substr(start, Message.find("\n")-start);
+       missingkeys += (Fingerprint);
+    }
+    if(!missingkeys.empty())
+       _error->Warning("%s", string(msg+missingkeys).c_str());
  
     string Transformed = MetaIndexParser->GetExpectedDist();
  
        Transformed = "experimental";
     }
  
-    string::size_type pos = Transformed.rfind('/');
+    pos = Transformed.rfind('/');
     if (pos != string::npos)
     {
        Transformed = Transformed.substr(0, pos);
@@@ -1117,10 -702,30 +1128,30 @@@ void pkgAcqMetaIndex::Failed(string Mes
  {
     if (AuthPass == true)
     {
-       // gpgv method failed
+       // if we fail the authentication but got the file via a IMS-Hit 
+       // this means that the file wasn't downloaded and that it might be
+       // just stale (server problem, proxy etc). we delete what we have
+       // queue it again without i-m-s 
+       // alternatively we could just unlink the file and let the user try again
+       if (IMSHit)
+       {
+        Complete = false;
+        Local = false;
+        AuthPass = false;
+        unlink(DestFile.c_str());
+        DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+        DestFile += URItoFileName(RealURI);
+        Desc.URI = RealURI;
+        QueueURI(Desc);
+        return;
+       }
+       // gpgv method failed 
        _error->Warning("GPG error: %s: %s",
                        Desc.Description.c_str(),
                        LookupTag(Message,"Message").c_str());
     }
  
     // No Release file was present, or verification failed, so fall
@@@ -1196,6 -801,12 +1227,12 @@@ pkgAcqArchive::pkgAcqArchive(pkgAcquir
        }
     }
  
+    // "allow-unauthenticated" restores apts old fetching behaviour
+    // that means that e.g. unauthenticated file:// uris are higher
+    // priority than authenticated http:// uris
+    if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
+       Trusted = false;
     // Select a source
     if (QueueNext() == false && _error->PendingError() == false)
        _error->Error(_("I wasn't able to locate file for the %s package. "
@@@ -1428,13 -1039,19 +1465,19 @@@ void pkgAcqArchive::Finished(
  // ---------------------------------------------------------------------
  /* The file is added to the queue */
  pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,
-                      unsigned long Size,string Dsc,string ShortDesc) :
+                      unsigned long Size,string Dsc,string ShortDesc,
+                      const string &DestDir, const string &DestFilename) :
                         Item(Owner), Md5Hash(MD5)
  {
     Retries = _config->FindI("Acquire::Retries",0);
     
-    DestFile = flNotDir(URI);
-    
+    if(!DestFilename.empty())
+       DestFile = DestFilename;
+    else if(!DestDir.empty())
+       DestFile = DestDir + "/" + flNotDir(URI);
+    else
+       DestFile = flNotDir(URI);
     // Create the item
     Desc.URI = URI;
     Desc.Description = Dsc;
        else
         PartialSize = Buf.st_size;
     }
-    
     QueueURI(Desc);
  }
                                                                        /*}}}*/
diff --combined apt-pkg/acquire-item.h
index 3a6e93b1afd5a4da570795d7b4a6ddba126774f6,da1bea801d7310557691a9d2470ffa2bf033466b..3649d7a039bd2e92575ca6fa83954712cab1b88a
@@@ -82,70 -82,6 +82,70 @@@ class pkgAcquire::Ite
     virtual ~Item();
  };
  
 +// item for index diffs
 +
 +struct DiffInfo {
 +   string file;
 +   string sha1;
 +   unsigned long size;
 +};
 +
 +class pkgAcqDiffIndex : public pkgAcquire::Item
 +{
 + protected:
 +   bool Debug;
 +   pkgAcquire::ItemDesc Desc;
 +   string RealURI;
 +   string ExpectedMD5;
 +   string CurrentPackagesFile;
 +   string Description;
 +
 + public:
 +   // Specialized action members
 +   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
 +   virtual void Done(string Message,unsigned long Size,string Md5Hash,
 +                   pkgAcquire::MethodConfig *Cnf);
 +   virtual string DescURI() {return RealURI + "Index";};
 +   virtual string Custom600Headers();
 +
 +   // helpers
 +   bool ParseDiffIndex(string IndexDiffFile);
 +   
 +   pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc,
 +                 string ShortDesct, string ExpectedMD5);
 +};
 +
 +class pkgAcqIndexDiffs : public pkgAcquire::Item
 +{
 +   protected:
 +   bool Debug;
 +   pkgAcquire::ItemDesc Desc;
 +   string RealURI;
 +   string ExpectedMD5;
 +
 +   // this is the SHA-1 sum we expect after the patching
 +   string Description;
 +   vector<DiffInfo> available_patches;
 +   enum {StateFetchIndex,StateFetchDiff,StateUnzipDiff,StateApplyDiff} State;
 +
 +   public:
 +   
 +   // Specialized action members
 +   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
 +   virtual void Done(string Message,unsigned long Size,string Md5Hash,
 +                   pkgAcquire::MethodConfig *Cnf);
 +   virtual string DescURI() {return RealURI + "Index";};
 +
 +   // various helpers
 +   bool QueueNextDiff();
 +   bool ApplyDiff(string PatchFile);
 +   void Finish(bool allDone=false);
 +
 +   pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc,
 +                  string ShortDesct, string ExpectedMD5,
 +                  vector<DiffInfo> diffs=vector<DiffInfo>());
 +};
 +
  // Item class for index files
  class pkgAcqIndex : public pkgAcquire::Item
  {
@@@ -215,8 -151,10 +215,10 @@@ class pkgAcqMetaIndex : public pkgAcqui
     const vector<struct IndexTarget*>* IndexTargets;
     indexRecords* MetaIndexParser;
     bool AuthPass;
+    // required to deal gracefully with problems caused by incorrect ims hits
+    bool IMSHit; 
  
-    bool VerifyVendor();
+    bool VerifyVendor(string Message);
     void RetrievalDone(string Message);
     void AuthDone(string Message);
     void QueueIndexes(bool verify);
@@@ -288,9 -226,14 +290,14 @@@ class pkgAcqFile : public pkgAcquire::I
                     pkgAcquire::MethodConfig *Cnf);
     virtual string MD5Sum() {return Md5Hash;};
     virtual string DescURI() {return Desc.URI;};
-    
-    pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,unsigned long Size,
-                 string Desc,string ShortDesc);
+    // If DestFilename is empty, download to DestDir/<basename> if
+    // DestDir is non-empty, $CWD/<basename> otherwise.  If
+    // DestFilename is NOT empty, DestDir is ignored and DestFilename
+    // is the absolute name to which the file should be downloaded.
+    pkgAcqFile(pkgAcquire *Owner, string URI, string MD5, unsigned long Size,
+             string Desc, string ShortDesc,
+             const string &DestDir="", const string &DestFilename="");
  };
  
  #endif
index 965a09759da2a911dd73d4d153685df6c447c699,73e20aa435c7be50c4871cd7b7bf154e05c9640b..e58ba7b87c29c22bf42e2a71868ced8ef54d8958
@@@ -72,6 -72,11 +72,11 @@@ AP
       NoAct "false";
    };
  
+   Authentication
+   {
+      TrustCDROM "false";            // consider the CDROM always trusted
+   };
    GPGV
    {
       TrustedKeyring "/etc/apt/trusted.gpg";
@@@ -99,8 -104,6 +104,8 @@@ Acquir
    Queue-Mode "host";       // host|access
    Retries "0";
    Source-Symlinks "true";
 +
 +  PDiffs "true";     // try to get the IndexFile diffs
    
    // HTTP method configuration
    http 
      No-Cache "false";
      Max-Age "86400";     // 1 Day age on index files
      No-Store "false";    // Prevent the cache from storing archives    
+     Dl-Limit "7";        // 7Kb/sec maximum download rate
    };
  
    ftp
@@@ -233,6 -237,10 +239,10 @@@ DPk
     // Control the size of the command line passed to dpkg.
     MaxBytes 1024;
     MaxArgs 350;
+    // controls if apt will apport on the first dpkg error or if it 
+    // tries to install as many packages as possible
+    StopOnError "true";
  }
  
  /* Options you can set to see some debugging text They correspond to names
  Debug 
  {
    pkgProblemResolver "false";
+   pkgDepCache::AutoInstall "false"; // what packages apt install to satify dependencies
    pkgAcquire "false";
    pkgAcquire::Worker "false";
+   pkgAcquire::Auth "false";
    pkgDPkgPM "false";
    pkgDPkgProgressReporting "false";
    pkgOrderList "false";
+   BuildDeps "false";
    
    pkgInitialize "false";   // This one will dump the configuration space
    NoLocking "false";