+
+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
+ // 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();
+
+ if (Transformed == "../project/experimental")
+ {
+ Transformed = "experimental";
+ }
+
+ pos = Transformed.rfind('/');
+ if (pos != string::npos)
+ {
+ Transformed = Transformed.substr(0, pos);
+ }
+
+ if (Transformed == ".")
+ {
+ Transformed = "";
+ }
+
+ if (_config->FindB("Debug::pkgAcquire::Auth", false))
+ {
+ std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl;
+ std::cerr << "Expecting Dist: " << MetaIndexParser->GetExpectedDist() << std::endl;
+ std::cerr << "Transformed Dist: " << Transformed << std::endl;
+ }
+
+ if (MetaIndexParser->CheckDist(Transformed) == false)
+ {
+ // This might become fatal one day
+// Status = StatAuthError;
+// ErrorText = "Conflicting distribution; expected "
+// + MetaIndexParser->GetExpectedDist() + " but got "
+// + MetaIndexParser->GetDist();
+// return false;
+ if (!Transformed.empty())
+ {
+ _error->Warning("Conflicting distribution: %s (expected %s but got %s)",
+ Desc.Description.c_str(),
+ Transformed.c_str(),
+ MetaIndexParser->GetDist().c_str());
+ }
+ }
+
+ return true;
+}
+ /*}}}*/
+// pkgAcqMetaIndex::Failed - no Release file present or no signature
+// file present /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+ if (AuthPass == true)
+ {
+ // 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
+ // back to queueing Packages files without verification
+ QueueIndexes(false);
+}
+
+ /*}}}*/
+
+// AcqArchive::AcqArchive - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* This just sets up the initial fetch environment and queues the first
+ possibilitiy */
+pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
+ pkgRecords *Recs,pkgCache::VerIterator const &Version,
+ string &StoreFilename) :
+ Item(Owner), Version(Version), Sources(Sources), Recs(Recs),
+ StoreFilename(StoreFilename), Vf(Version.FileList()),
+ Trusted(false)
+{
+ Retries = _config->FindI("Acquire::Retries",0);
+
+ if (Version.Arch() == 0)
+ {
+ _error->Error(_("I wasn't able to locate a file for the %s package. "
+ "This might mean you need to manually fix this package. "
+ "(due to missing arch)"),
+ Version.ParentPkg().Name());
+ return;
+ }
+
+ /* We need to find a filename to determine the extension. We make the
+ assumption here that all the available sources for this version share
+ the same extension.. */
+ // Skip not source sources, they do not have file fields.
+ for (; Vf.end() == false; Vf++)
+ {
+ if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0)
+ continue;
+ break;
+ }
+
+ // Does not really matter here.. we are going to fail out below
+ if (Vf.end() != true)
+ {
+ // If this fails to get a file name we will bomb out below.
+ pkgRecords::Parser &Parse = Recs->Lookup(Vf);
+ if (_error->PendingError() == true)
+ return;
+
+ // Generate the final file name as: package_version_arch.foo
+ StoreFilename = QuoteString(Version.ParentPkg().Name(),"_:") + '_' +
+ QuoteString(Version.VerStr(),"_:") + '_' +
+ QuoteString(Version.Arch(),"_:.") +
+ "." + flExtension(Parse.FileName());
+ }
+
+ // check if we have one trusted source for the package. if so, switch
+ // to "TrustedOnly" mode
+ for (pkgCache::VerFileIterator i = Version.FileList(); i.end() == false; i++)
+ {
+ pkgIndexFile *Index;
+ if (Sources->FindIndex(i.File(),Index) == false)
+ continue;
+ if (_config->FindB("Debug::pkgAcquire::Auth", false))
+ {
+ std::cerr << "Checking index: " << Index->Describe()
+ << "(Trusted=" << Index->IsTrusted() << ")\n";
+ }
+ if (Index->IsTrusted()) {
+ Trusted = true;
+ break;
+ }
+ }
+
+ // "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. "
+ "This might mean you need to manually fix this package."),
+ Version.ParentPkg().Name());
+}
+ /*}}}*/
+// AcqArchive::QueueNext - Queue the next file source /*{{{*/
+// ---------------------------------------------------------------------
+/* This queues the next available file version for download. It checks if
+ the archive is already available in the cache and stashs the MD5 for
+ checking later. */
+bool pkgAcqArchive::QueueNext()
+{
+ for (; Vf.end() == false; Vf++)
+ {
+ // Ignore not source sources
+ if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0)
+ continue;
+
+ // Try to cross match against the source list
+ pkgIndexFile *Index;
+ if (Sources->FindIndex(Vf.File(),Index) == false)
+ continue;
+
+ // only try to get a trusted package from another source if that source
+ // is also trusted
+ if(Trusted && !Index->IsTrusted())
+ continue;
+
+ // Grab the text package record
+ pkgRecords::Parser &Parse = Recs->Lookup(Vf);
+ if (_error->PendingError() == true)
+ return false;
+
+ string PkgFile = Parse.FileName();
+ MD5 = Parse.MD5Hash();
+ if (PkgFile.empty() == true)
+ return _error->Error(_("The package index files are corrupted. No Filename: "
+ "field for package %s."),
+ Version.ParentPkg().Name());
+
+ Desc.URI = Index->ArchiveURI(PkgFile);
+ Desc.Description = Index->ArchiveInfo(Version);
+ Desc.Owner = this;
+ Desc.ShortDesc = Version.ParentPkg().Name();
+
+ // See if we already have the file. (Legacy filenames)
+ FileSize = Version->Size;
+ string FinalFile = _config->FindDir("Dir::Cache::Archives") + flNotDir(PkgFile);
+ struct stat Buf;
+ if (stat(FinalFile.c_str(),&Buf) == 0)
+ {
+ // Make sure the size matches
+ if ((unsigned)Buf.st_size == Version->Size)
+ {
+ Complete = true;
+ Local = true;
+ Status = StatDone;
+ StoreFilename = DestFile = FinalFile;
+ return true;
+ }
+
+ /* Hmm, we have a file and its size does not match, this means it is
+ an old style mismatched arch */
+ unlink(FinalFile.c_str());
+ }
+
+ // Check it again using the new style output filenames
+ FinalFile = _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename);
+ if (stat(FinalFile.c_str(),&Buf) == 0)
+ {
+ // Make sure the size matches
+ if ((unsigned)Buf.st_size == Version->Size)
+ {
+ Complete = true;
+ Local = true;
+ Status = StatDone;
+ StoreFilename = DestFile = FinalFile;
+ return true;
+ }
+
+ /* Hmm, we have a file and its size does not match, this shouldnt
+ happen.. */
+ unlink(FinalFile.c_str());
+ }
+
+ DestFile = _config->FindDir("Dir::Cache::Archives") + "partial/" + flNotDir(StoreFilename);
+
+ // Check the destination file
+ if (stat(DestFile.c_str(),&Buf) == 0)
+ {
+ // Hmm, the partial file is too big, erase it
+ if ((unsigned)Buf.st_size > Version->Size)
+ unlink(DestFile.c_str());
+ else
+ PartialSize = Buf.st_size;
+ }
+
+ // Create the item
+ Local = false;
+ Desc.URI = Index->ArchiveURI(PkgFile);
+ Desc.Description = Index->ArchiveInfo(Version);
+ Desc.Owner = this;
+ Desc.ShortDesc = Version.ParentPkg().Name();
+ QueueURI(Desc);
+
+ Vf++;
+ return true;
+ }
+ return false;
+}