]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/acquire-item.cc
releasing version 0.8.16~exp3
[apt.git] / apt-pkg / acquire-item.cc
index 77600949317e49d704b8bc2a0cc26dcd0d496cd3..aa77824f815b186b441d04cebdcf1b435592978d 100644 (file)
@@ -17,7 +17,6 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/sourcelist.h>
-#include <apt-pkg/vendorlist.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
@@ -95,7 +94,7 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 // ---------------------------------------------------------------------
 /* Stash status and the file size. Note that setting Complete means 
    sub-phases of the acquire process such as decompresion are operating */
-void pkgAcquire::Item::Start(string /*Message*/,unsigned long Size)
+void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size)
 {
    Status = StatFetching;
    if (FileSize == 0 && Complete == false)
@@ -105,7 +104,7 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long Size)
 // Acquire::Item::Done - Item downloaded OK                            /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgAcquire::Item::Done(string Message,unsigned long Size,string Hash,
+void pkgAcquire::Item::Done(string Message,unsigned long long Size,string Hash,
                            pkgAcquire::MethodConfig *Cnf)
 {
    // We just downloaded something..
@@ -186,10 +185,8 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
                                                                        /*}}}*/
 // AcqSubIndex::AcqSubIndex - 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
+/* Get the Index file first and see if there are languages available
+ * If so, create a pkgAcqIndexTrans for the found language(s).
  */
 pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
                                 string const &URIDesc, string const &ShortDesc,
@@ -222,8 +219,8 @@ string pkgAcqSubIndex::Custom600Headers()
 
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
-      return "\nIndex-File: true";
-   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+      return "\nIndex-File: true\nFail-Ignore: true\n";
+   return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
                                                                        /*}}}*/
 void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)      /*{{{*/
@@ -248,7 +245,7 @@ void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)   /*{{{*
    }
 }
                                                                        /*}}}*/
-void pkgAcqSubIndex::Done(string Message,unsigned long Size,string Md5Hash,    /*{{{*/
+void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,       /*{{{*/
                           pkgAcquire::MethodConfig *Cnf)
 {
    if(Debug)
@@ -274,6 +271,14 @@ void pkgAcqSubIndex::Done(string Message,unsigned long Size,string Md5Hash,        /*{{
 
    string FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(Desc.URI);
 
+   /* Downloaded invalid transindex => Error (LP: #346386) (Closes: #627642) */
+   indexRecords SubIndexParser;
+   if (FileExists(DestFile) == true && !SubIndexParser.Load(DestFile)) {
+      Status = StatError;
+      ErrorText = SubIndexParser.ErrorText;
+      return;
+   }
+
    // sucess in downloading the index
    // rename the index
    if(Debug)
@@ -539,7 +544,7 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)  /*{{{
    Dequeue();
 }
                                                                        /*}}}*/
-void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,   /*{{{*/
+void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,string Md5Hash,      /*{{{*/
                           pkgAcquire::MethodConfig *Cnf)
 {
    if(Debug)
@@ -705,7 +710,7 @@ bool pkgAcqIndexDiffs::QueueNextDiff()                                      /*{{{*/
    return true;
 }
                                                                        /*}}}*/
-void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,  /*{{{*/
+void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Hash,     /*{{{*/
                            pkgAcquire::MethodConfig *Cnf)
 {
    if(Debug)
@@ -837,10 +842,16 @@ string pkgAcqIndex::Custom600Headers()
    if (_config->FindB("Acquire::GzipIndexes",false))
       Final += ".gz";
    
+   string msg = "\nIndex-File: true";
+   // FIXME: this really should use "IndexTarget::IsOptional()" but that
+   //        seems to be difficult without breaking ABI
+   if (ShortDesc().find("Translation") != 0)
+      msg += "\nFail-Ignore: true";
    struct stat Buf;
-   if (stat(Final.c_str(),&Buf) != 0)
-      return "\nIndex-File: true";
-   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+   if (stat(Final.c_str(),&Buf) == 0)
+      msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+
+   return msg;
 }
                                                                        /*}}}*/
 void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
@@ -870,7 +881,7 @@ 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 Size,string Hash,
+void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
                       pkgAcquire::MethodConfig *Cfg)
 {
    Item::Done(Message,Size,Hash,Cfg);
@@ -891,6 +902,30 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
         ReportMirrorFailure("HashChecksumFailure");
          return;
       }
+
+      /* Verify the index file for correctness (all indexes must
+       * have a Package field) (LP: #346386) (Closes: #627642) */
+      {
+        FileFd fd(DestFile, FileFd::ReadOnly);
+        pkgTagSection sec;
+        pkgTagFile tag(&fd);
+
+         // Only test for correctness if the file is not empty (empty is ok)
+         if (fd.Size() > 0) {
+            if (_error->PendingError() || !tag.Step(sec)) {
+               Status = StatError;
+               _error->DumpErrors();
+               Rename(DestFile,DestFile + ".FAILED");
+               return;
+            } else if (!sec.Exists("Package")) {
+               Status = StatError;
+               ErrorText = ("Encountered a section with no Package: header");
+               Rename(DestFile,DestFile + ".FAILED");
+               return;
+            }
+         }
+      }
+       
       // Done, move it into position
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
@@ -1004,8 +1039,8 @@ string pkgAcqIndexTrans::Custom600Headers()
 
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
-      return "\nFail-Ignore: true";
-   return "\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+      return "\nFail-Ignore: true\nIndex-File: true";
+   return "\nFail-Ignore: true\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
                                                                        /*}}}*/
 // AcqIndexTrans::Failed - Silence failure messages for missing files  /*{{{*/
@@ -1088,7 +1123,7 @@ string pkgAcqMetaSig::Custom600Headers()
    return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
 
-void pkgAcqMetaSig::Done(string Message,unsigned long Size,string MD5,
+void pkgAcqMetaSig::Done(string Message,unsigned long long Size,string MD5,
                         pkgAcquire::MethodConfig *Cfg)
 {
    Item::Done(Message,Size,MD5,Cfg);
@@ -1197,7 +1232,7 @@ string pkgAcqMetaIndex::Custom600Headers()
    return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
                                                                        /*}}}*/
-void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,      /*{{{*/
+void pkgAcqMetaIndex::Done(string Message,unsigned long long Size,string Hash, /*{{{*/
                           pkgAcquire::MethodConfig *Cfg)
 {
    Item::Done(Message,Size,Hash,Cfg);
@@ -1327,6 +1362,16 @@ void pkgAcqMetaIndex::AuthDone(string Message)                           /*{{{*/
                                                                        /*}}}*/
 void pkgAcqMetaIndex::QueueIndexes(bool verify)                                /*{{{*/
 {
+#if 0
+   /* Reject invalid, existing Release files (LP: #346386) (Closes: #627642)
+    * FIXME: Disabled; it breaks unsigned repositories without hashes */
+   if (!verify && FileExists(DestFile) && !MetaIndexParser->Load(DestFile))
+   {
+      Status = StatError;
+      ErrorText = MetaIndexParser->ErrorText;
+      return;
+   }
+#endif
    for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
         Target != IndexTargets->end();
         Target++)
@@ -1386,29 +1431,6 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)                          /*{{{*/
                                                                        /*}}}*/
 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?
-//    pkgVendorList List;
-//    List.ReadMainList();
-
-//    const Vendor* Vndr = NULL;
-//    for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
-//    {
-//       string::size_type pos = (*I).find("VALIDSIG ");
-//       if (_config->FindB("Debug::Vendor", false))
-//          std::cerr << "Looking for VALIDSIG in \"" << (*I) << "\": pos " << pos 
-//                    << std::endl;
-//       if (pos != std::string::npos)
-//       {
-//          string Fingerprint = (*I).substr(pos+sizeof("VALIDSIG"));
-//          if (_config->FindB("Debug::Vendor", false))
-//             std::cerr << "Looking for \"" << Fingerprint << "\" in vendor..." <<
-//                std::endl;
-//          Vndr = List.FindVendor(Fingerprint) != "";
-//          if (Vndr != NULL);
-//          break;
-//       }
-//    }
    string::size_type pos;
 
    // check for missing sigs (that where not fatal because otherwise we had
@@ -1451,8 +1473,10 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message)                       /*{{{*/
         // TRANSLATOR: The first %s is the URL of the bad Release file, the second is
         // the time since then the file is invalid - formated in the same way as in
         // the download progress display (e.g. 7d 3h 42min 1s)
-        return _error->Error(_("Release file expired, ignoring %s (invalid since %s)"),
-                             RealURI.c_str(), TimeToStr(invalid_since).c_str());
+        return _error->Error(
+            _("Release file for %s is expired (invalid since %s). "
+              "Updates for this repository will not be applied."),
+            RealURI.c_str(), TimeToStr(invalid_since).c_str());
    }
 
    if (_config->FindB("Debug::pkgAcquire::Auth", false)) 
@@ -1513,6 +1537,12 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
                         LookupTag(Message,"Message").c_str());
         RunScripts("APT::Update::Auth-Failure");
         return;
+      } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) {
+        /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */
+        _error->Error(_("GPG error: %s: %s"),
+                        Desc.Description.c_str(),
+                        LookupTag(Message,"Message").c_str());
+        return;
       } else {
         _error->Warning(_("GPG error: %s: %s"),
                         Desc.Description.c_str(),
@@ -1522,6 +1552,26 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       ReportMirrorFailure("GPGFailure");
    }
 
+   /* Always move the meta index, even if gpgv failed. This ensures
+    * that PackageFile objects are correctly filled in */
+   if (FileExists(DestFile)) {
+      string FinalFile = _config->FindDir("Dir::State::lists");
+      FinalFile += URItoFileName(RealURI);
+      /* InRelease files become Release files, otherwise
+       * they would be considered as trusted later on */
+      if (SigFile == DestFile) {
+        RealURI = RealURI.replace(RealURI.rfind("InRelease"), 9,
+                                      "Release");
+        FinalFile = FinalFile.replace(FinalFile.rfind("InRelease"), 9,
+                                      "Release");
+        SigFile = FinalFile;
+      }
+      Rename(DestFile,FinalFile);
+      chmod(FinalFile.c_str(),0644);
+
+      DestFile = FinalFile;
+   }
+
    // No Release file was present, or verification failed, so fall
    // back to queueing Packages files without verification
    QueueIndexes(false);
@@ -1540,6 +1590,21 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner,                /*{{{*/
    SigFile = DestFile;
 }
                                                                        /*}}}*/
+// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers        /*{{{*/
+// ---------------------------------------------------------------------
+// FIXME: this can go away once the InRelease file is used widely
+string pkgAcqMetaClearSig::Custom600Headers()
+{
+   string Final = _config->FindDir("Dir::State::lists");
+   Final += URItoFileName(RealURI);
+
+   struct stat Buf;
+   if (stat(Final.c_str(),&Buf) != 0)
+      return "\nIndex-File: true\nFail-Ignore: true\n";
+
+   return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+}
+                                                                       /*}}}*/
 void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
 {
    if (AuthPass == false)
@@ -1630,7 +1695,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
 
    // Select a source
    if (QueueNext() == false && _error->PendingError() == false)
-      _error->Error(_("I wasn't able to locate file for the %s package. "
+      _error->Error(_("I wasn't able to locate file for the %s package. "
                    "This might mean you need to manually fix this package."),
                    Version.ParentPkg().Name());
 }
@@ -1667,6 +1732,8 @@ bool pkgAcqArchive::QueueNext()
       string PkgFile = Parse.FileName();
       if (ForceHash.empty() == false)
       {
+        if(stringcasecmp(ForceHash, "sha512") == 0)
+           ExpectedHash = HashString("SHA512", Parse.SHA512Hash());
         if(stringcasecmp(ForceHash, "sha256") == 0)
            ExpectedHash = HashString("SHA256", Parse.SHA256Hash());
         else if (stringcasecmp(ForceHash, "sha1") == 0)
@@ -1677,7 +1744,9 @@ bool pkgAcqArchive::QueueNext()
       else
       {
         string Hash;
-        if ((Hash = Parse.SHA256Hash()).empty() == false)
+        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);
@@ -1701,7 +1770,7 @@ bool pkgAcqArchive::QueueNext()
       if (stat(FinalFile.c_str(),&Buf) == 0)
       {
         // Make sure the size matches
-        if ((unsigned)Buf.st_size == Version->Size)
+        if ((unsigned long long)Buf.st_size == Version->Size)
         {
            Complete = true;
            Local = true;
@@ -1720,7 +1789,7 @@ bool pkgAcqArchive::QueueNext()
       if (stat(FinalFile.c_str(),&Buf) == 0)
       {
         // Make sure the size matches
-        if ((unsigned)Buf.st_size == Version->Size)
+        if ((unsigned long long)Buf.st_size == Version->Size)
         {
            Complete = true;
            Local = true;
@@ -1740,7 +1809,7 @@ bool pkgAcqArchive::QueueNext()
       if (stat(DestFile.c_str(),&Buf) == 0)
       {
         // Hmm, the partial file is too big, erase it
-        if ((unsigned)Buf.st_size > Version->Size)
+        if ((unsigned long long)Buf.st_size > Version->Size)
            unlink(DestFile.c_str());
         else
            PartialSize = Buf.st_size;
@@ -1763,7 +1832,7 @@ bool pkgAcqArchive::QueueNext()
 // AcqArchive::Done - Finished fetching                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgAcqArchive::Done(string Message,unsigned long Size,string CalcHash,
+void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash,
                         pkgAcquire::MethodConfig *Cfg)
 {
    Item::Done(Message,Size,CalcHash,Cfg);
@@ -1874,7 +1943,7 @@ void pkgAcqArchive::Finished()
 // ---------------------------------------------------------------------
 /* The file is added to the queue */
 pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
-                      unsigned long Size,string Dsc,string ShortDesc,
+                      unsigned long long Size,string Dsc,string ShortDesc,
                       const string &DestDir, const string &DestFilename,
                        bool IsIndexFile) :
                        Item(Owner), ExpectedHash(Hash), IsIndexFile(IsIndexFile)
@@ -1902,7 +1971,7 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
    if (stat(DestFile.c_str(),&Buf) == 0)
    {
       // Hmm, the partial file is too big, erase it
-      if ((unsigned)Buf.st_size > Size)
+      if ((unsigned long long)Buf.st_size > Size)
         unlink(DestFile.c_str());
       else
         PartialSize = Buf.st_size;
@@ -1914,7 +1983,7 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string Hash,
 // AcqFile::Done - Item downloaded OK                                  /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgAcqFile::Done(string Message,unsigned long Size,string CalcHash,
+void pkgAcqFile::Done(string Message,unsigned long long Size,string CalcHash,
                      pkgAcquire::MethodConfig *Cnf)
 {
    Item::Done(Message,Size,CalcHash,Cnf);