#include <apt-pkg/acquire-item.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/aptconfiguration.h>
-#include <apt-pkg/indexrecords.h>
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/hashes.h>
#include <apt-pkg/metaindex.h>
#include <string>
#include <utility>
#include <vector>
-#include <set>
#include <algorithm>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <unistd.h>
#include <string.h>
#include <apti18n.h>
std::vector<debSectionEntry> DebEntries;
std::vector<debSectionEntry> DebSrcEntries;
- debReleaseIndex::TriState Trusted;
+ metaIndex::TriState CheckValidUntil;
+ time_t ValidUntilMin;
+ time_t ValidUntilMax;
- debReleaseIndexPrivate() : Trusted(debReleaseIndex::TRI_UNSET) {}
- debReleaseIndexPrivate(bool const pTrusted) : Trusted(pTrusted ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) {}
+ debReleaseIndexPrivate() : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0) {}
};
/*}}}*/
// ReleaseIndex::MetaIndex* - display helpers /*{{{*/
return Res;
}
/*}}}*/
-std::string debReleaseIndex::LocalFileName() const /*{{{*/
-{
- // see if we have a InRelease file
- std::string PathInRelease = MetaIndexFile("InRelease");
- if (FileExists(PathInRelease))
- return PathInRelease;
-
- // and if not return the normal one
- if (FileExists(PathInRelease))
- return MetaIndexFile("Release");
-
- return "";
-}
- /*}}}*/
// ReleaseIndex Con- and Destructors /*{{{*/
debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist) :
metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate())
{}
-debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted) :
- metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate(Trusted))
-{}
+debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const pTrusted) :
+ metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate())
+{
+ Trusted = pTrusted ? TRI_YES : TRI_NO;
+}
debReleaseIndex::~debReleaseIndex() {
if (d != NULL)
delete d;
std::string const Release = (Dist == "/") ? "" : Dist;
std::string const Site = ::URI::ArchiveOnly(URI);
+ bool const GzipIndex = _config->FindB("Acquire::GzipIndexes", false);
for (std::vector<debReleaseIndexPrivate::debSectionEntry>::const_iterator E = entries.begin(); E != entries.end(); ++E)
{
for (std::vector<std::string>::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T)
{
-#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::" + (X))
+#define APT_T_CONFIG(X) _config->Find(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X))
std::string const tplMetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey");
std::string const tplShortDesc = APT_T_CONFIG("ShortDescription");
- std::string const tplLongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description");
- bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true);
+ std::string const tplLongDesc = "$(SITE) " + APT_T_CONFIG(flatArchive ? "flatDescription" : "Description");
+ bool const IsOptional = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::Optional", true);
+ bool const KeepCompressed = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::KeepCompressed", GzipIndex);
#undef APT_T_CONFIG
if (tplMetaKey.empty())
continue;
Options.insert(std::make_pair("ARCHITECTURE", *A));
Options.insert(std::make_pair("BASE_URI", baseURI));
Options.insert(std::make_pair("REPO_URI", URI));
- Options.insert(std::make_pair("TARGET_OF", "deb-src"));
+ Options.insert(std::make_pair("TARGET_OF", Type));
Options.insert(std::make_pair("CREATED_BY", *T));
std::string MetaKey = tplMetaKey;
LongDesc,
Options.find("BASE_URI")->second + MetaKey,
IsOptional,
+ KeepCompressed,
Options
);
IndexTargets.push_back(Target);
}
/*}}}*/
+bool debReleaseIndex::Load(std::string const &Filename, std::string * const ErrorText)/*{{{*/
+{
+ LoadedSuccessfully = TRI_NO;
+ FileFd Fd;
+ if (OpenMaybeClearSignedFile(Filename, Fd) == false)
+ return false;
+
+ pkgTagFile TagFile(&Fd, Fd.Size());
+ if (_error->PendingError() == true)
+ {
+ if (ErrorText != NULL)
+ strprintf(*ErrorText, _("Unable to parse Release file %s"),Filename.c_str());
+ return false;
+ }
+
+ pkgTagSection Section;
+ const char *Start, *End;
+ if (TagFile.Step(Section) == false)
+ {
+ if (ErrorText != NULL)
+ strprintf(*ErrorText, _("No sections in Release file %s"), Filename.c_str());
+ return false;
+ }
+ // FIXME: find better tag name
+ SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false);
+
+ Suite = Section.FindS("Suite");
+ Codename = Section.FindS("Codename");
+
+ bool FoundHashSum = false;
+ for (int i=0;HashString::SupportedHashes()[i] != NULL; i++)
+ {
+ if (!Section.Find(HashString::SupportedHashes()[i], Start, End))
+ continue;
+
+ std::string Name;
+ std::string Hash;
+ unsigned long long Size;
+ while (Start < End)
+ {
+ if (!parseSumData(Start, End, Name, Hash, Size))
+ return false;
+
+ if (Entries.find(Name) == Entries.end())
+ {
+ metaIndex::checkSum *Sum = new metaIndex::checkSum;
+ Sum->MetaKeyFilename = Name;
+ Sum->Size = Size;
+ Sum->Hashes.FileSize(Size);
+ APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);)
+ Entries[Name] = Sum;
+ }
+ Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
+ FoundHashSum = true;
+ }
+ }
+
+ if(FoundHashSum == false)
+ {
+ if (ErrorText != NULL)
+ strprintf(*ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
+ return false;
+ }
-bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const/*{{{*/
+ std::string const StrDate = Section.FindS("Date");
+ if (RFC1123StrToTime(StrDate.c_str(), Date) == false)
+ {
+ if (ErrorText != NULL)
+ strprintf(*ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str());
+ return false;
+ }
+
+ bool CheckValidUntil = _config->FindB("Acquire::Check-Valid-Until", true);
+ if (d->CheckValidUntil == metaIndex::TRI_NO)
+ CheckValidUntil = false;
+ else if (d->CheckValidUntil == metaIndex::TRI_YES)
+ CheckValidUntil = true;
+
+ if (CheckValidUntil == true)
+ {
+ std::string const Label = Section.FindS("Label");
+ std::string const StrValidUntil = Section.FindS("Valid-Until");
+
+ // if we have a Valid-Until header in the Release file, use it as default
+ if (StrValidUntil.empty() == false)
+ {
+ if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false)
+ {
+ if (ErrorText != NULL)
+ strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str());
+ return false;
+ }
+ }
+ // get the user settings for this archive and use what expires earlier
+ time_t MaxAge = d->ValidUntilMax;
+ if (MaxAge == 0)
+ {
+ MaxAge = _config->FindI("Acquire::Max-ValidTime", 0);
+ if (Label.empty() == false)
+ MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge);
+ }
+ time_t MinAge = d->ValidUntilMin;
+ if (MinAge == 0)
+ {
+ MinAge = _config->FindI("Acquire::Min-ValidTime", 0);
+ if (Label.empty() == false)
+ MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge);
+ }
+
+ if (MinAge != 0 && ValidUntil != 0) {
+ time_t const min_date = Date + MinAge;
+ if (ValidUntil < min_date)
+ ValidUntil = min_date;
+ }
+ if (MaxAge != 0) {
+ time_t const max_date = Date + MaxAge;
+ if (ValidUntil == 0 || ValidUntil > max_date)
+ ValidUntil = max_date;
+ }
+ }
+
+ LoadedSuccessfully = TRI_YES;
+ return true;
+}
+ /*}}}*/
+metaIndex * debReleaseIndex::UnloadedClone() const /*{{{*/
+{
+ if (Trusted == TRI_NO)
+ return new debReleaseIndex(URI, Dist, false);
+ else if (Trusted == TRI_YES)
+ return new debReleaseIndex(URI, Dist, true);
+ else
+ return new debReleaseIndex(URI, Dist);
+}
+ /*}}}*/
+bool debReleaseIndex::parseSumData(const char *&Start, const char *End, /*{{{*/
+ std::string &Name, std::string &Hash, unsigned long long &Size)
{
- indexRecords * const iR = new indexRecords(Dist);
- if (d->Trusted == TRI_YES)
- iR->SetTrusted(true);
- else if (d->Trusted == TRI_NO)
- iR->SetTrusted(false);
+ Name = "";
+ Hash = "";
+ Size = 0;
+ /* Skip over the first blank */
+ while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r')
+ && Start < End)
+ Start++;
+ if (Start >= End)
+ return false;
- // special case for --print-uris
+ /* Move EntryEnd to the end of the first entry (the hash) */
+ const char *EntryEnd = Start;
+ while ((*EntryEnd != '\t' && *EntryEnd != ' ')
+ && EntryEnd < End)
+ EntryEnd++;
+ if (EntryEnd == End)
+ return false;
+
+ Hash.append(Start, EntryEnd-Start);
+
+ /* Skip over intermediate blanks */
+ Start = EntryEnd;
+ while (*Start == '\t' || *Start == ' ')
+ Start++;
+ if (Start >= End)
+ return false;
+
+ EntryEnd = Start;
+ /* Find the end of the second entry (the size) */
+ while ((*EntryEnd != '\t' && *EntryEnd != ' ' )
+ && EntryEnd < End)
+ EntryEnd++;
+ if (EntryEnd == End)
+ return false;
+
+ Size = strtoull (Start, NULL, 10);
+
+ /* Skip over intermediate blanks */
+ Start = EntryEnd;
+ while (*Start == '\t' || *Start == ' ')
+ Start++;
+ if (Start >= End)
+ return false;
+
+ EntryEnd = Start;
+ /* Find the end of the third entry (the filename) */
+ while ((*EntryEnd != '\t' && *EntryEnd != ' ' &&
+ *EntryEnd != '\n' && *EntryEnd != '\r')
+ && EntryEnd < End)
+ EntryEnd++;
+
+ Name.append(Start, EntryEnd-Start);
+ Start = EntryEnd; //prepare for the next round
+ return true;
+}
+ /*}}}*/
+
+bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/
+{
std::vector<IndexTarget> const targets = GetIndexTargets();
-#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map<std::string,std::string>())
+#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, false, std::map<std::string,std::string>())
pkgAcqMetaClearSig * const TransactionManager = new pkgAcqMetaClearSig(Owner,
APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"),
- targets, iR);
+ targets, this);
#undef APT_TARGET
+ // special case for --print-uris
if (GetAll)
{
for (std::vector<IndexTarget>::const_iterator Target = targets.begin(); Target != targets.end(); ++Target)
return true;
}
/*}}}*/
-// ReleaseIndex::IsTrusted /*{{{*/
-bool debReleaseIndex::SetTrusted(TriState const Trusted)
+// ReleaseIndex::Set* TriState options /*{{{*/
+bool debReleaseIndex::SetTrusted(TriState const pTrusted)
{
- if (d->Trusted == TRI_UNSET)
- d->Trusted = Trusted;
- else if (d->Trusted != Trusted)
+ if (Trusted == TRI_UNSET)
+ Trusted = pTrusted;
+ else if (Trusted != pTrusted)
// TRANSLATOR: The first is an option name from sources.list manpage, the other two URI and Suite
return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str());
return true;
}
+bool debReleaseIndex::SetCheckValidUntil(TriState const pCheckValidUntil)
+{
+ if (d->CheckValidUntil == TRI_UNSET)
+ d->CheckValidUntil = pCheckValidUntil;
+ else if (d->CheckValidUntil != pCheckValidUntil)
+ return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Check-Valid-Until", URI.c_str(), Dist.c_str());
+ return true;
+}
+bool debReleaseIndex::SetValidUntilMin(time_t const Valid)
+{
+ if (d->ValidUntilMin == 0)
+ d->ValidUntilMin = Valid;
+ else if (d->ValidUntilMin != Valid)
+ return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Min-ValidTime", URI.c_str(), Dist.c_str());
+ return true;
+}
+bool debReleaseIndex::SetValidUntilMax(time_t const Valid)
+{
+ if (d->ValidUntilMax == 0)
+ d->ValidUntilMax = Valid;
+ else if (d->ValidUntilMax != Valid)
+ return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str());
+ return true;
+}
+bool debReleaseIndex::SetSignedBy(std::string const &pSignedBy)
+{
+ if (SignedBy.empty() == true && pSignedBy.empty() == false)
+ {
+ if (pSignedBy[0] == '/') // no check for existence as we could be chrooting later or such things
+ ; // absolute path to a keyring file
+ else
+ {
+ // we could go all fancy and allow short/long/string matches as gpgv/apt-key does,
+ // but fingerprints are harder to fake than the others and this option is set once,
+ // not interactively all the time so easy to type is not really a concern.
+ std::string finger = pSignedBy;
+ finger.erase(std::remove(finger.begin(), finger.end(), ' '), finger.end());
+ std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper);
+ if (finger.length() != 40 || finger.find_first_not_of("0123456789ABCDEF") != std::string::npos)
+ return _error->Error(_("Invalid value set for option %s concerning source %s %s (%s)"), "Signed-By", URI.c_str(), Dist.c_str(), "not a fingerprint");
+ }
+ SignedBy = pSignedBy;
+ }
+ else if (SignedBy != pSignedBy)
+ return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Signed-By", URI.c_str(), Dist.c_str());
+ return true;
+}
+ /*}}}*/
+// ReleaseIndex::IsTrusted /*{{{*/
bool debReleaseIndex::IsTrusted() const
{
- if (d->Trusted == TRI_YES)
+ if (Trusted == TRI_YES)
return true;
- else if (d->Trusted == TRI_NO)
+ else if (Trusted == TRI_NO)
return false;
/*}}}*/
class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/
{
+ metaIndex::TriState GetTriStateOption(std::map<std::string, std::string>const &Options, char const * const name) const
+ {
+ std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
+ if (opt != Options.end())
+ return StringToBool(opt->second, false) ? metaIndex::TRI_YES : metaIndex::TRI_NO;
+ return metaIndex::TRI_DONTCARE;
+ }
+
+ time_t GetTimeOption(std::map<std::string, std::string>const &Options, char const * const name) const
+ {
+ std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
+ if (opt == Options.end())
+ return 0;
+ return strtoull(opt->second.c_str(), NULL, 10);
+ }
+
protected:
bool CreateItemInternal(std::vector<metaIndex *> &List, std::string const &URI,
List.push_back(Deb);
}
+ std::vector<std::string> const alltargets = _config->FindVector(std::string("Acquire::IndexTargets::") + Name, "", true);
+ std::vector<std::string> mytargets = parsePlusMinusOptions("target", Options, alltargets);
+ if (mytargets.empty() == false)
+ for (auto const &target : alltargets)
+ {
+ std::map<std::string, std::string>::const_iterator const opt = Options.find(target);
+ if (opt == Options.end())
+ continue;
+ auto const tarItr = std::find(mytargets.begin(), mytargets.end(), target);
+ bool const optValue = StringToBool(opt->second);
+ if (optValue == true && tarItr == mytargets.end())
+ mytargets.push_back(target);
+ else if (optValue == false && tarItr != mytargets.end())
+ mytargets.erase(std::remove(mytargets.begin(), mytargets.end(), target), mytargets.end());
+ }
Deb->AddComponent(
IsSrc,
Section,
- parsePlusMinusOptions("target", Options, _config->FindVector(std::string("APT::Acquire::Targets::") + Name, "", true)),
+ mytargets,
parsePlusMinusOptions("arch", Options, APT::Configuration::getArchitectures()),
parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true))
);
- std::map<std::string, std::string>::const_iterator const trusted = Options.find("trusted");
- if (trusted != Options.end())
+ if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false ||
+ Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false ||
+ Deb->SetValidUntilMax(GetTimeOption(Options, "valid-until-max")) == false ||
+ Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false)
+ return false;
+
+ std::map<std::string, std::string>::const_iterator const signedby = Options.find("signed-by");
+ if (signedby == Options.end())
{
- if (Deb->SetTrusted(StringToBool(trusted->second, false) ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) == false)
+ if (Deb->SetSignedBy("") == false)
+ return false;
+ }
+ else
+ {
+ if (Deb->SetSignedBy(signedby->second) == false)
return false;
}
- else if (Deb->SetTrusted(debReleaseIndex::TRI_DONTCARE) == false)
- return false;
return true;
}
bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
std::string const &Dist, std::string const &Section,
- std::map<std::string, std::string> const &Options) const
+ std::map<std::string, std::string> const &Options) const APT_OVERRIDE
{
return CreateItemInternal(List, URI, Dist, Section, false, Options);
}
bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
std::string const &Dist, std::string const &Section,
- std::map<std::string, std::string> const &Options) const
+ std::map<std::string, std::string> const &Options) const APT_OVERRIDE
{
return CreateItemInternal(List, URI, Dist, Section, true, Options);
}
};
/*}}}*/
-debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile) /*{{{*/
- : metaIndex(DebFile, "local-uri", "deb-dist"), d(NULL), DebFile(DebFile)
-{
- DebIndex = new debDebPkgFileIndex(DebFile);
- Indexes = new std::vector<pkgIndexFile *>();
- Indexes->push_back(DebIndex);
-}
-debDebFileMetaIndex::~debDebFileMetaIndex() {}
- /*}}}*/
-class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type /*{{{*/
-{
- public:
-
- bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
- std::string const &/*Dist*/, std::string const &/*Section*/,
- std::map<std::string, std::string> const &/*Options*/) const
- {
- metaIndex *mi = new debDebFileMetaIndex(URI);
- List.push_back(mi);
- return true;
- }
-
- debSLTypeDebFile() : Type("deb-file", "Debian local deb file")
- {
- }
-};
- /*}}}*/
-
APT_HIDDEN debSLTypeDeb _apt_DebType;
APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType;
-APT_HIDDEN debSLTypeDebFile _apt_DebFileType;