apt  2.2.4
About: Apt (Advanced Package Tool) is a management system for software packages (Debian/Ubuntu). Release series 2.2.
  Fossies Dox: apt-2.2.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

debmetaindex.cc
Go to the documentation of this file.
1 #include <config.h>
2 
3 #include <apt-pkg/acquire-item.h>
5 #include <apt-pkg/configuration.h>
6 #include <apt-pkg/debindexfile.h>
7 #include <apt-pkg/debmetaindex.h>
8 #include <apt-pkg/error.h>
9 #include <apt-pkg/fileutl.h>
10 #include <apt-pkg/gpgv.h>
11 #include <apt-pkg/hashes.h>
12 #include <apt-pkg/macros.h>
13 #include <apt-pkg/metaindex.h>
14 #include <apt-pkg/pkgcachegen.h>
15 #include <apt-pkg/sourcelist.h>
16 #include <apt-pkg/strutl.h>
17 #include <apt-pkg/tagfile.h>
18 
19 #include <algorithm>
20 #include <map>
21 #include <sstream>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 #include <string.h>
27 #include <sys/stat.h>
28 
29 #include <apti18n.h>
30 
31 static std::string transformFingergrpints(std::string finger) /*{{{*/
32 {
33  std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper);
34  if (finger.length() == 40)
35  {
36  if (finger.find_first_not_of("0123456789ABCDEF") == std::string::npos)
37  return finger;
38  }
39  else if (finger.length() == 41)
40  {
41  auto bang = finger.find_first_not_of("0123456789ABCDEF");
42  if (bang == 40 && finger[bang] == '!')
43  return finger;
44  }
45  return "";
46 }
47  /*}}}*/
48 static std::string transformFingergrpintsWithFilenames(std::string const &finger) /*{{{*/
49 {
50  // no check for existence as we could be chrooting later or such things
51  if (finger.empty() == false && finger[0] == '/')
52  return finger;
53  return transformFingergrpints(finger);
54 }
55  /*}}}*/
56 static std::string NormalizeSignedBy(std::string SignedBy, bool const SupportFilenames) /*{{{*/
57 {
58  // we could go all fancy and allow short/long/string matches as gpgv/apt-key does,
59  // but fingerprints are harder to fake than the others and this option is set once,
60  // not interactively all the time so easy to type is not really a concern.
61  std::transform(SignedBy.begin(), SignedBy.end(), SignedBy.begin(), [](char const c) {
62  return (isspace_ascii(c) == 0) ? c : ',';
63  });
64  auto fingers = VectorizeString(SignedBy, ',');
65  auto const isAnEmptyString = [](std::string const &s) { return s.empty(); };
66  fingers.erase(std::remove_if(fingers.begin(), fingers.end(), isAnEmptyString), fingers.end());
67  if (unlikely(fingers.empty()))
68  return "";
69  if (SupportFilenames)
70  std::transform(fingers.begin(), fingers.end(), fingers.begin(), transformFingergrpintsWithFilenames);
71  else
72  std::transform(fingers.begin(), fingers.end(), fingers.begin(), transformFingergrpints);
73  if (std::any_of(fingers.begin(), fingers.end(), isAnEmptyString))
74  return "";
75  std::stringstream os;
76  std::copy(fingers.begin(), fingers.end() - 1, std::ostream_iterator<std::string>(os, ","));
77  os << *fingers.rbegin();
78  return os.str();
79 }
80  /*}}}*/
81 
83 {
84  public:
86  {
87  std::string const sourcesEntry;
88  std::string const Name;
89  std::vector<std::string> const Targets;
90  std::vector<std::string> const Architectures;
91  std::vector<std::string> const Languages;
92  bool const UsePDiffs;
93  std::string const UseByHash;
94  };
95 
96  std::vector<debSectionEntry> DebEntries;
97  std::vector<debSectionEntry> DebSrcEntries;
98 
99  metaIndex::TriState CheckValidUntil;
102 
103  metaIndex::TriState CheckDate;
105  time_t NotBefore;
106 
107  std::vector<std::string> Architectures;
108  std::vector<std::string> NoSupportForAll;
109  std::vector<std::string> SupportedComponents;
110  std::map<std::string, std::string> const ReleaseOptions;
111 
112  explicit debReleaseIndexPrivate(std::map<std::string, std::string> const &Options) : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0), CheckDate(metaIndex::TRI_UNSET), DateMaxFuture(0), NotBefore(0), ReleaseOptions(Options) {}
113 };
114  /*}}}*/
115 // ReleaseIndex::MetaIndex* - display helpers /*{{{*/
116 std::string debReleaseIndex::MetaIndexInfo(const char *Type) const
117 {
118  std::string Info = ::URI::ArchiveOnly(URI) + ' ';
119  if (Dist[Dist.size() - 1] == '/')
120  {
121  if (Dist != "/")
122  Info += Dist;
123  }
124  else
125  Info += Dist;
126  Info += " ";
127  Info += Type;
128  return Info;
129 }
130 std::string debReleaseIndex::Describe() const
131 {
132  return MetaIndexInfo("Release");
133 }
134 
135 std::string debReleaseIndex::MetaIndexFile(const char *Type) const
136 {
137  return _config->FindDir("Dir::State::lists") +
139 }
140 static std::string constructMetaIndexURI(std::string URI, std::string const &Dist, char const * const Type)
141 {
142  if (Dist == "/")
143  ;
144  else if (Dist[Dist.size()-1] == '/')
145  URI += pkgAcquire::URIEncode(Dist);
146  else
147  URI += "dists/" + pkgAcquire::URIEncode(Dist) + "/";
148  return URI + pkgAcquire::URIEncode(Type);
149 }
150 std::string debReleaseIndex::MetaIndexURI(const char *Type) const
151 {
153 }
154  /*}}}*/
155 // ReleaseIndex Con- and Destructors /*{{{*/
156 debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, std::map<std::string, std::string> const &Options) :
157  metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate(Options))
158 {}
159 debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const pTrusted, std::map<std::string, std::string> const &Options) :
160  metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate(Options))
161 {
162  Trusted = pTrusted ? TRI_YES : TRI_NO;
163 }
165  if (d != NULL)
166  delete d;
167 }
168  /*}}}*/
169 // ReleaseIndex::GetIndexTargets /*{{{*/
170 static void GetIndexTargetsFor(char const * const Type, std::string const &URI, std::string const &Dist,
171  std::vector<debReleaseIndexPrivate::debSectionEntry> const &entries,
172  std::vector<IndexTarget> &IndexTargets, std::map<std::string, std::string> const &ReleaseOptions)
173 {
174  bool const flatArchive = (Dist[Dist.length() - 1] == '/');
175  std::string const baseURI = constructMetaIndexURI(URI, Dist, "");
176 
177  std::string DefCompressionTypes;
178  {
179  std::vector<std::string> types = APT::Configuration::getCompressionTypes();
180  if (types.empty() == false)
181  {
182  std::ostringstream os;
183  std::copy(types.begin(), types.end()-1, std::ostream_iterator<std::string>(os, " "));
184  os << *types.rbegin();
185  DefCompressionTypes = os.str();
186  }
187  }
188  std::string DefKeepCompressedAs;
189  {
190  std::vector<APT::Configuration::Compressor> comps = APT::Configuration::getCompressors();
191  if (comps.empty() == false)
192  {
193  std::sort(comps.begin(), comps.end(),
194  [](APT::Configuration::Compressor const &a, APT::Configuration::Compressor const &b) { return a.Cost < b.Cost; });
195  std::ostringstream os;
196  for (auto const &c : comps)
197  if (c.Cost != 0)
198  os << c.Extension.substr(1) << ' ';
199  DefKeepCompressedAs = os.str();
200  }
201  DefKeepCompressedAs += "uncompressed";
202  }
203 
204  std::vector<std::string> const NativeArchs = { _config->Find("APT::Architecture"), "implicit:all" };
205  bool const GzipIndex = _config->FindB("Acquire::GzipIndexes", false);
206  for (std::vector<debReleaseIndexPrivate::debSectionEntry>::const_iterator E = entries.begin(); E != entries.end(); ++E)
207  {
208  for (std::vector<std::string>::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T)
209  {
210 #define APT_T_CONFIG_STR(X, Y) _config->Find(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X), (Y))
211 #define APT_T_CONFIG_BOOL(X, Y) _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X), (Y))
212  std::string const tplMetaKey = APT_T_CONFIG_STR(flatArchive ? "flatMetaKey" : "MetaKey", "");
213  std::string const tplShortDesc = APT_T_CONFIG_STR("ShortDescription", "");
214  std::string const tplLongDesc = "$(SITE) " + APT_T_CONFIG_STR(flatArchive ? "flatDescription" : "Description", "");
215  std::string const tplIdentifier = APT_T_CONFIG_STR("Identifier", *T);
216  bool const IsOptional = APT_T_CONFIG_BOOL("Optional", true);
217  bool const KeepCompressed = APT_T_CONFIG_BOOL("KeepCompressed", GzipIndex);
218  bool const DefaultEnabled = APT_T_CONFIG_BOOL("DefaultEnabled", true);
219  bool const UsePDiffs = APT_T_CONFIG_BOOL("PDiffs", E->UsePDiffs);
220  std::string const UseByHash = APT_T_CONFIG_STR("By-Hash", E->UseByHash);
221  std::string const CompressionTypes = APT_T_CONFIG_STR("CompressionTypes", DefCompressionTypes);
222  std::string KeepCompressedAs = APT_T_CONFIG_STR("KeepCompressedAs", "");
223  std::string const FallbackOf = APT_T_CONFIG_STR("Fallback-Of", "");
224 #undef APT_T_CONFIG_BOOL
225 #undef APT_T_CONFIG_STR
226  if (tplMetaKey.empty())
227  continue;
228 
229  if (KeepCompressedAs.empty())
230  KeepCompressedAs = DefKeepCompressedAs;
231  else
232  {
233  std::vector<std::string> const defKeep = VectorizeString(DefKeepCompressedAs, ' ');
234  std::vector<std::string> const valKeep = VectorizeString(KeepCompressedAs, ' ');
235  std::vector<std::string> keep;
236  for (auto const &val : valKeep)
237  {
238  if (val.empty())
239  continue;
240  if (std::find(defKeep.begin(), defKeep.end(), val) == defKeep.end())
241  continue;
242  keep.push_back(val);
243  }
244  if (std::find(keep.begin(), keep.end(), "uncompressed") == keep.end())
245  keep.push_back("uncompressed");
246  std::ostringstream os;
247  std::copy(keep.begin(), keep.end()-1, std::ostream_iterator<std::string>(os, " "));
248  os << *keep.rbegin();
249  KeepCompressedAs = os.str();
250  }
251 
252  for (std::vector<std::string>::const_iterator L = E->Languages.begin(); L != E->Languages.end(); ++L)
253  {
254  if (*L == "none" && tplMetaKey.find("$(LANGUAGE)") != std::string::npos)
255  continue;
256 
257  for (std::vector<std::string>::const_iterator A = E->Architectures.begin(); A != E->Architectures.end(); ++A)
258  {
259  for (auto const &NativeArch: NativeArchs)
260  {
261  constexpr static auto BreakPoint = "$(NATIVE_ARCHITECTURE)";
262  // available in templates
263  std::map<std::string, std::string> Options;
264  Options.insert(ReleaseOptions.begin(), ReleaseOptions.end());
265  if (tplMetaKey.find("$(COMPONENT)") != std::string::npos)
266  Options.emplace("COMPONENT", E->Name);
267  if (tplMetaKey.find("$(LANGUAGE)") != std::string::npos)
268  Options.emplace("LANGUAGE", *L);
269  if (tplMetaKey.find("$(ARCHITECTURE)") != std::string::npos)
270  Options.emplace("ARCHITECTURE", (*A == "implicit:all") ? "all" : *A);
271  else if (tplMetaKey.find("$(NATIVE_ARCHITECTURE)") != std::string::npos)
272  Options.emplace("ARCHITECTURE", (NativeArch == "implicit:all") ? "all" : NativeArch);
273  if (tplMetaKey.find("$(NATIVE_ARCHITECTURE)") != std::string::npos)
274  Options.emplace("NATIVE_ARCHITECTURE", (NativeArch == "implicit:all") ? "all" : NativeArch);
275 
276  std::string MetaKey = tplMetaKey;
277  std::string ShortDesc = tplShortDesc;
278  std::string LongDesc = tplLongDesc;
279  std::string Identifier = tplIdentifier;
280  for (std::map<std::string, std::string>::const_iterator O = Options.begin(); O != Options.end(); ++O)
281  {
282  std::string const varname = "$(" + O->first + ")";
283  MetaKey = SubstVar(MetaKey, varname, O->second);
284  ShortDesc = SubstVar(ShortDesc, varname, O->second);
285  LongDesc = SubstVar(LongDesc, varname, O->second);
286  Identifier = SubstVar(Identifier, varname, O->second);
287  }
288 
289  {
290  auto const dup = std::find_if(IndexTargets.begin(), IndexTargets.end(), [&](IndexTarget const &IT) {
291  return MetaKey == IT.MetaKey && baseURI == IT.Option(IndexTarget::BASE_URI) &&
292  E->sourcesEntry == IT.Option(IndexTarget::SOURCESENTRY) && *T == IT.Option(IndexTarget::CREATED_BY);
293  });
294  if (dup != IndexTargets.end())
295  {
296  if (tplMetaKey.find(BreakPoint) == std::string::npos)
297  break;
298  continue;
299  }
300  }
301 
302  {
303  auto const dup = std::find_if(IndexTargets.begin(), IndexTargets.end(), [&](IndexTarget const &IT) {
304  return MetaKey == IT.MetaKey && baseURI == IT.Option(IndexTarget::BASE_URI) &&
305  E->sourcesEntry == IT.Option(IndexTarget::SOURCESENTRY) && *T != IT.Option(IndexTarget::CREATED_BY);
306  });
307  if (dup != IndexTargets.end())
308  {
309  std::string const dupT = dup->Option(IndexTarget::CREATED_BY);
310  std::string const dupEntry = dup->Option(IndexTarget::SOURCESENTRY);
311  //TRANSLATOR: an identifier like Packages; Releasefile key indicating
312  // a file like main/binary-amd64/Packages; another identifier like Contents;
313  // filename and linenumber of the sources.list entry currently parsed
314  _error->Warning(_("Target %s wants to acquire the same file (%s) as %s from source %s"),
315  T->c_str(), MetaKey.c_str(), dupT.c_str(), dupEntry.c_str());
316  if (tplMetaKey.find(BreakPoint) == std::string::npos)
317  break;
318  continue;
319  }
320  }
321 
322  {
323  auto const dup = std::find_if(IndexTargets.begin(), IndexTargets.end(), [&](IndexTarget const &T) {
324  return MetaKey == T.MetaKey && baseURI == T.Option(IndexTarget::BASE_URI) &&
325  E->sourcesEntry != T.Option(IndexTarget::SOURCESENTRY);
326  });
327  if (dup != IndexTargets.end())
328  {
329  std::string const dupEntry = dup->Option(IndexTarget::SOURCESENTRY);
330  if (T->find("legacy") == std::string::npos)
331  {
332  //TRANSLATOR: an identifier like Packages; Releasefile key indicating
333  // a file like main/binary-amd64/Packages; filename and linenumber of
334  // two sources.list entries
335  _error->Warning(_("Target %s (%s) is configured multiple times in %s and %s"),
336  T->c_str(), MetaKey.c_str(), dupEntry.c_str(), E->sourcesEntry.c_str());
337  }
338  if (tplMetaKey.find(BreakPoint) == std::string::npos)
339  break;
340  continue;
341  }
342  }
343 
344  // not available in templates, but in the indextarget
345  Options.insert(std::make_pair("IDENTIFIER", Identifier));
346  Options.insert(std::make_pair("TARGET_OF", Type));
347  Options.insert(std::make_pair("CREATED_BY", *T));
348  Options.insert(std::make_pair("FALLBACK_OF", FallbackOf));
349  Options.insert(std::make_pair("PDIFFS", UsePDiffs ? "yes" : "no"));
350  Options.insert(std::make_pair("BY_HASH", UseByHash));
351  Options.insert(std::make_pair("DEFAULTENABLED", DefaultEnabled ? "yes" : "no"));
352  Options.insert(std::make_pair("COMPRESSIONTYPES", CompressionTypes));
353  Options.insert(std::make_pair("KEEPCOMPRESSEDAS", KeepCompressedAs));
354  Options.insert(std::make_pair("SOURCESENTRY", E->sourcesEntry));
355 
356  bool IsOpt = IsOptional;
357  {
358  auto const arch = Options.find("ARCHITECTURE");
359  if (arch != Options.end() && arch->second == "all")
360  {
361  // one of them must be implicit:all then
362  if (*A != "all" && NativeArch != "all")
363  IsOpt = true;
364  else // user used arch=all explicitly
365  Options.emplace("Force-Support-For-All", "yes");
366  }
367  }
368 
369  IndexTarget Target(
370  MetaKey,
371  ShortDesc,
372  LongDesc,
373  baseURI + MetaKey,
374  IsOpt,
375  KeepCompressed,
376  Options
377  );
378  IndexTargets.push_back(Target);
379 
380  if (tplMetaKey.find(BreakPoint) == std::string::npos)
381  break;
382  }
383 
384  if (tplMetaKey.find("$(ARCHITECTURE)") == std::string::npos)
385  break;
386 
387  }
388 
389  if (tplMetaKey.find("$(LANGUAGE)") == std::string::npos)
390  break;
391 
392  }
393 
394  }
395  }
396 }
397 std::vector<IndexTarget> debReleaseIndex::GetIndexTargets() const
398 {
399  std::vector<IndexTarget> IndexTargets;
400  GetIndexTargetsFor("deb-src", URI, Dist, d->DebSrcEntries, IndexTargets, d->ReleaseOptions);
401  GetIndexTargetsFor("deb", URI, Dist, d->DebEntries, IndexTargets, d->ReleaseOptions);
402  return IndexTargets;
403 }
404  /*}}}*/
405 void debReleaseIndex::AddComponent(std::string const &sourcesEntry, /*{{{*/
406  bool const isSrc, std::string const &Name,
407  std::vector<std::string> const &Targets,
408  std::vector<std::string> const &Architectures,
409  std::vector<std::string> Languages,
410  bool const usePDiffs, std::string const &useByHash)
411 {
412  if (Languages.empty() == true)
413  Languages.push_back("none");
415  sourcesEntry, Name, Targets, Architectures, Languages, usePDiffs, useByHash
416  };
417  if (isSrc)
418  d->DebSrcEntries.push_back(entry);
419  else
420  d->DebEntries.push_back(entry);
421 }
422  /*}}}*/
423 std::string debReleaseIndex::ArchiveURI(std::string const &File) const /*{{{*/
424 {
425  if (File.empty())
426  return URI;
427  return URI + pkgAcquire::URIEncode(File);
428 }
429  /*}}}*/
430 
431 bool debReleaseIndex::Load(std::string const &Filename, std::string * const ErrorText)/*{{{*/
432 {
434  FileFd Fd;
435  if (OpenMaybeClearSignedFile(Filename, Fd) == false)
436  return false;
437 
438  pkgTagFile TagFile(&Fd, Fd.Size());
439  if (Fd.IsOpen() == false || Fd.Failed())
440  {
441  if (ErrorText != NULL)
442  strprintf(*ErrorText, _("Unable to parse Release file %s"),Filename.c_str());
443  return false;
444  }
445 
446  pkgTagSection Section;
447  const char *Start, *End;
448  if (TagFile.Step(Section) == false)
449  {
450  if (ErrorText != NULL)
451  strprintf(*ErrorText, _("No sections in Release file %s"), Filename.c_str());
452  return false;
453  }
454  // FIXME: find better tag name
455  SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false);
456 
457  Origin = Section.FindS("Origin");
458  Label = Section.FindS("Label");
459  Version = Section.FindS("Version");
460  Suite = Section.FindS("Suite");
461  Codename = Section.FindS("Codename");
462  ReleaseNotes = Section.FindS("Release-Notes");
463  {
464  std::string const archs = Section.FindS("Architectures");
465  if (archs.empty() == false)
466  d->Architectures = VectorizeString(archs, ' ');
467  }
468  {
469  std::string const targets = Section.FindS("No-Support-for-Architecture-all");
470  if (targets.empty() == false)
471  d->NoSupportForAll = VectorizeString(targets, ' ');
472  }
473  for (auto const &comp: VectorizeString(Section.FindS("Components"), ' '))
474  {
475  if (comp.empty())
476  continue;
477  auto const pos = comp.find_last_of('/');
478  if (pos != std::string::npos) // e.g. security.debian.org uses this style
479  d->SupportedComponents.push_back(comp.substr(pos + 1));
480  d->SupportedComponents.push_back(std::move(comp));
481  }
482  {
483  decltype(pkgCache::ReleaseFile::Flags) flags = 0;
484  Section.FindFlag("NotAutomatic", flags, pkgCache::Flag::NotAutomatic);
485  signed short defaultpin = 500;
487  {
488  Section.FindFlag("ButAutomaticUpgrades", flags, pkgCache::Flag::ButAutomaticUpgrades);
490  defaultpin = 100;
491  else
492  defaultpin = 1;
493  }
494  DefaultPin = defaultpin;
495  }
496 
497  bool FoundHashSum = false;
498  bool FoundStrongHashSum = false;
499  auto const SupportedHashes = HashString::SupportedHashes();
500  for (int i=0; SupportedHashes[i] != NULL; i++)
501  {
502  if (!Section.Find(SupportedHashes[i], Start, End))
503  continue;
504 
505  std::string Name;
506  std::string Hash;
507  unsigned long long Size;
508  while (Start < End)
509  {
510  if (!parseSumData(Start, End, Name, Hash, Size))
511  return false;
512 
513  HashString const hs(SupportedHashes[i], Hash);
514  if (Entries.find(Name) == Entries.end())
515  {
517  Sum->MetaKeyFilename = Name;
518  Sum->Size = Size;
519  Sum->Hashes.FileSize(Size);
520  Entries[Name] = Sum;
521  }
522  Entries[Name]->Hashes.push_back(hs);
523  FoundHashSum = true;
524  if (FoundStrongHashSum == false && hs.usable() == true)
525  FoundStrongHashSum = true;
526  }
527  }
528 
529  bool AuthPossible = false;
530  if(FoundHashSum == false)
531  _error->Warning(_("No Hash entry in Release file %s"), Filename.c_str());
532  else if(FoundStrongHashSum == false)
533  _error->Warning(_("No Hash entry in Release file %s which is considered strong enough for security purposes"), Filename.c_str());
534  else
535  AuthPossible = true;
536 
537  std::string const StrDate = Section.FindS("Date");
538  if (RFC1123StrToTime(StrDate, Date) == false)
539  {
540  _error->Warning( _("Invalid '%s' entry in Release file %s"), "Date", Filename.c_str());
541  Date = 0;
542  }
543 
544  bool CheckDate = _config->FindB("Acquire::Check-Date", true);
545  if (d->CheckDate == metaIndex::TRI_NO)
546  CheckDate = false;
547  else if (d->CheckDate == metaIndex::TRI_YES)
548  CheckDate = true;
549 
550  if (CheckDate)
551  {
552  auto const Label = GetLabel();
553  // get the user settings for this archive
554  time_t MaxFuture = d->DateMaxFuture;
555  if (MaxFuture == 0)
556  {
557  MaxFuture = _config->FindI("Acquire::Max-FutureTime", 10);
558  if (Label.empty() == false)
559  MaxFuture = _config->FindI(("Acquire::Max-FutureTime::" + Label).c_str(), MaxFuture);
560  }
561 
562  d->NotBefore = Date - MaxFuture;
563 
564  bool CheckValidUntil = _config->FindB("Acquire::Check-Valid-Until", true);
566  CheckValidUntil = false;
567  else if (d->CheckValidUntil == metaIndex::TRI_YES)
568  CheckValidUntil = true;
569 
570  if (CheckValidUntil == true)
571  {
572  std::string const StrValidUntil = Section.FindS("Valid-Until");
573 
574  // if we have a Valid-Until header in the Release file, use it as default
575  if (StrValidUntil.empty() == false)
576  {
577  if (RFC1123StrToTime(StrValidUntil, ValidUntil) == false)
578  {
579  if (ErrorText != NULL)
580  strprintf(*ErrorText, _("Invalid '%s' entry in Release file %s"), "Valid-Until", Filename.c_str());
581  return false;
582  }
583  }
584  auto const Label = GetLabel();
585  // get the user settings for this archive and use what expires earlier
586  time_t MaxAge = d->ValidUntilMax;
587  if (MaxAge == 0)
588  {
589  MaxAge = _config->FindI("Acquire::Max-ValidTime", 0);
590  if (Label.empty() == false)
591  MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge);
592  }
593  time_t MinAge = d->ValidUntilMin;
594  if (MinAge == 0)
595  {
596  MinAge = _config->FindI("Acquire::Min-ValidTime", 0);
597  if (Label.empty() == false)
598  MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge);
599  }
600 
601  if (MinAge != 0 || ValidUntil != 0 || MaxAge != 0)
602  {
603  if (MinAge != 0 && ValidUntil != 0)
604  {
605  time_t const min_date = Date + MinAge;
606  if (ValidUntil < min_date)
607  ValidUntil = min_date;
608  }
609  if (MaxAge != 0 && Date != 0)
610  {
611  time_t const max_date = Date + MaxAge;
612  if (ValidUntil == 0 || ValidUntil > max_date)
613  ValidUntil = max_date;
614  }
615  }
616  }
617  }
618 
619  /* as the Release file is parsed only after it was verified, the Signed-By field
620  does not effect the current, but the "next" Release file */
621  auto Sign = Section.FindS("Signed-By");
622  if (Sign.empty() == false)
623  {
624  SignedBy = NormalizeSignedBy(Sign, false);
625  if (SignedBy.empty() && ErrorText != NULL)
626  strprintf(*ErrorText, _("Invalid '%s' entry in Release file %s"), "Signed-By", Filename.c_str());
627  }
628 
629  if (AuthPossible)
631  return AuthPossible;
632 }
633  /*}}}*/
634 time_t debReleaseIndex::GetNotBefore() const /*{{{*/
635 {
636  return d->NotBefore;
637 }
638  /*}}}*/
640 {
641  if (Trusted == TRI_NO)
642  return new debReleaseIndex(URI, Dist, false, d->ReleaseOptions);
643  else if (Trusted == TRI_YES)
644  return new debReleaseIndex(URI, Dist, true, d->ReleaseOptions);
645  else
646  return new debReleaseIndex(URI, Dist, d->ReleaseOptions);
647 }
648  /*}}}*/
649 bool debReleaseIndex::parseSumData(const char *&Start, const char *End, /*{{{*/
650  std::string &Name, std::string &Hash, unsigned long long &Size)
651 {
652  Name = "";
653  Hash = "";
654  Size = 0;
655  /* Skip over the first blank */
656  while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r')
657  && Start < End)
658  Start++;
659  if (Start >= End)
660  return false;
661 
662  /* Move EntryEnd to the end of the first entry (the hash) */
663  const char *EntryEnd = Start;
664  while ((*EntryEnd != '\t' && *EntryEnd != ' ')
665  && EntryEnd < End)
666  EntryEnd++;
667  if (EntryEnd == End)
668  return false;
669 
670  Hash.append(Start, EntryEnd-Start);
671 
672  /* Skip over intermediate blanks */
673  Start = EntryEnd;
674  while (*Start == '\t' || *Start == ' ')
675  Start++;
676  if (Start >= End)
677  return false;
678 
679  EntryEnd = Start;
680  /* Find the end of the second entry (the size) */
681  while ((*EntryEnd != '\t' && *EntryEnd != ' ' )
682  && EntryEnd < End)
683  EntryEnd++;
684  if (EntryEnd == End)
685  return false;
686 
687  Size = strtoull (Start, NULL, 10);
688 
689  /* Skip over intermediate blanks */
690  Start = EntryEnd;
691  while (*Start == '\t' || *Start == ' ')
692  Start++;
693  if (Start >= End)
694  return false;
695 
696  EntryEnd = Start;
697  /* Find the end of the third entry (the filename) */
698  while ((*EntryEnd != '\t' && *EntryEnd != ' ' &&
699  *EntryEnd != '\n' && *EntryEnd != '\r')
700  && EntryEnd < End)
701  EntryEnd++;
702 
703  Name.append(Start, EntryEnd-Start);
704  Start = EntryEnd; //prepare for the next round
705  return true;
706 }
707  /*}}}*/
708 
709 bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/
710 {
711 #define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, false, d->ReleaseOptions)
713  APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), this);
714 #undef APT_TARGET
715  // special case for --print-uris
716  if (GetAll)
717  for (auto const &Target: GetIndexTargets())
718  if (Target.Option(IndexTarget::FALLBACK_OF).empty())
719  new pkgAcqIndex(Owner, TransactionManager, Target);
720 
721  return true;
722 }
723  /*}}}*/
724 // ReleaseIndex::Set* TriState options /*{{{*/
725 bool debReleaseIndex::SetTrusted(TriState const pTrusted)
726 {
727  if (Trusted == TRI_UNSET)
728  Trusted = pTrusted;
729  else if (Trusted != pTrusted)
730  // TRANSLATOR: The first is an option name from sources.list manpage, the other two URI and Suite
731  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), "Trusted", URI.c_str(), Dist.c_str());
732  return true;
733 }
734 bool debReleaseIndex::SetCheckValidUntil(TriState const pCheckValidUntil)
735 {
736  if (d->CheckValidUntil == TRI_UNSET)
737  d->CheckValidUntil = pCheckValidUntil;
738  else if (d->CheckValidUntil != pCheckValidUntil)
739  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), "Check-Valid-Until", URI.c_str(), Dist.c_str());
740  return true;
741 }
742 bool debReleaseIndex::SetValidUntilMin(time_t const Valid)
743 {
744  if (d->ValidUntilMin == 0)
745  d->ValidUntilMin = Valid;
746  else if (d->ValidUntilMin != Valid)
747  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), "Min-ValidTime", URI.c_str(), Dist.c_str());
748  return true;
749 }
750 bool debReleaseIndex::SetValidUntilMax(time_t const Valid)
751 {
752  if (d->ValidUntilMax == 0)
753  d->ValidUntilMax = Valid;
754  else if (d->ValidUntilMax != Valid)
755  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str());
756  return true;
757 }
758 bool debReleaseIndex::SetCheckDate(TriState const pCheckDate)
759 {
760  if (d->CheckDate == TRI_UNSET)
761  d->CheckDate = pCheckDate;
762  else if (d->CheckDate != pCheckDate)
763  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), "Check-Date", URI.c_str(), Dist.c_str());
764  return true;
765 }
766 bool debReleaseIndex::SetDateMaxFuture(time_t const DateMaxFuture)
767 {
768  if (d->DateMaxFuture == 0)
769  d->DateMaxFuture = DateMaxFuture;
770  else if (d->DateMaxFuture != DateMaxFuture)
771  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), "Date-Max-Future", URI.c_str(), Dist.c_str());
772  return true;
773 }
774 bool debReleaseIndex::SetSignedBy(std::string const &pSignedBy)
775 {
776  if (SignedBy.empty() == true && pSignedBy.empty() == false)
777  {
778  SignedBy = NormalizeSignedBy(pSignedBy, true);
779  if (SignedBy.empty())
780  _error->Error(_("Invalid value set for option %s regarding source %s %s (%s)"), "Signed-By", URI.c_str(), Dist.c_str(), "not a fingerprint");
781  }
782  else
783  {
784  auto const normalSignedBy = NormalizeSignedBy(pSignedBy, true);
785  if (normalSignedBy != SignedBy)
786  return _error->Error(_("Conflicting values set for option %s regarding source %s %s: %s != %s"), "Signed-By", URI.c_str(), Dist.c_str(), SignedBy.c_str(), normalSignedBy.c_str());
787  }
788  return true;
789 }
790  /*}}}*/
791 // ReleaseIndex::IsTrusted /*{{{*/
793 {
794  if (Trusted == TRI_YES)
795  return true;
796  else if (Trusted == TRI_NO)
797  return false;
798 
799 
800  if(_config->FindB("APT::Authentication::TrustCDROM", false))
801  if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
802  return true;
803 
804  if (FileExists(MetaIndexFile("Release.gpg")))
805  return true;
806 
807  return FileExists(MetaIndexFile("InRelease"));
808 }
809  /*}}}*/
810 bool debReleaseIndex::IsArchitectureSupported(std::string const &arch) const/*{{{*/
811 {
812  if (d->Architectures.empty())
813  return true;
814  return std::find(d->Architectures.begin(), d->Architectures.end(), arch) != d->Architectures.end();
815 }
816  /*}}}*/
818 {
819  if (target.Options.find("Force-Support-For-All") != target.Options.end())
820  return true;
821  if (IsArchitectureSupported("all") == false)
822  return false;
823  if (d->NoSupportForAll.empty())
824  return true;
825  return std::find(d->NoSupportForAll.begin(), d->NoSupportForAll.end(), target.Option(IndexTarget::CREATED_BY)) == d->NoSupportForAll.end();
826 }
827  /*}}}*/
828 bool debReleaseIndex::HasSupportForComponent(std::string const &component) const/*{{{*/
829 {
830  if (d->SupportedComponents.empty())
831  return true;
832  return std::find(d->SupportedComponents.begin(), d->SupportedComponents.end(), component) != d->SupportedComponents.end();
833 }
834  /*}}}*/
835 std::vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() /*{{{*/
836 {
837  if (Indexes != NULL)
838  return Indexes;
839 
840  Indexes = new std::vector<pkgIndexFile*>();
841  bool const istrusted = IsTrusted();
842  for (auto const &T: GetIndexTargets())
843  {
844  std::string const TargetName = T.Option(IndexTarget::CREATED_BY);
845  if (TargetName == "Packages")
846  Indexes->push_back(new debPackagesIndex(T, istrusted));
847  else if (TargetName == "Sources")
848  Indexes->push_back(new debSourcesIndex(T, istrusted));
849  else if (TargetName == "Translations")
850  Indexes->push_back(new debTranslationsIndex(T));
851  }
852  return Indexes;
853 }
854  /*}}}*/
855 std::map<std::string, std::string> debReleaseIndex::GetReleaseOptions()
856 {
857  return d->ReleaseOptions;
858 }
859 
860 static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile)/*{{{*/
861 {
862  ReleaseFile = That->MetaIndexFile("InRelease");
863  bool releaseExists = false;
864  if (FileExists(ReleaseFile) == true)
865  releaseExists = true;
866  else
867  {
868  ReleaseFile = That->MetaIndexFile("Release");
869  if (FileExists(ReleaseFile))
870  releaseExists = true;
871  }
872  return releaseExists;
873 }
874  /*}}}*/
875 bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/
876 {
877  std::string ReleaseFile;
878  bool const releaseExists = ReleaseFileName(this, ReleaseFile);
879 
880  ::URI Tmp(URI);
881  if (Gen.SelectReleaseFile(ReleaseFile, Tmp.Host) == false)
882  return _error->Error("Problem with SelectReleaseFile %s", ReleaseFile.c_str());
883 
884  if (releaseExists == false)
885  return true;
886 
887  FileFd Rel;
888  // Beware: The 'Release' file might be clearsigned in case the
889  // signature for an 'InRelease' file couldn't be checked
890  if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
891  return false;
892 
893  // Store the IMS information
894  pkgCache::RlsFileIterator File = Gen.GetCurRlsFile();
896  // Rel can't be used as this is potentially a temporary file
897  struct stat Buf;
898  if (stat(ReleaseFile.c_str(), &Buf) != 0)
899  return _error->Errno("fstat", "Unable to stat file %s", ReleaseFile.c_str());
900  File->Size = Buf.st_size;
901  File->mtime = Buf.st_mtime;
902 
903  pkgTagFile TagFile(&Rel, Rel.Size());
904  pkgTagSection Section;
905  if (Rel.IsOpen() == false || Rel.Failed() || TagFile.Step(Section) == false)
906  return false;
907 
908  std::string data;
909  #define APT_INRELEASE(TYPE, TAG, STORE) \
910  data = Section.FindS(TAG); \
911  if (data.empty() == false) \
912  { \
913  map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::TYPE, data); \
914  if (storage == 0) return false; \
915  STORE = storage; \
916  }
917  APT_INRELEASE(MIXED, "Suite", File->Archive)
918  APT_INRELEASE(VERSIONNUMBER, "Version", File->Version)
919  APT_INRELEASE(MIXED, "Origin", File->Origin)
920  APT_INRELEASE(MIXED, "Codename", File->Codename)
921  APT_INRELEASE(MIXED, "Label", File->Label)
922  #undef APT_INRELEASE
923  Section.FindFlag("NotAutomatic", File->Flags, pkgCache::Flag::NotAutomatic);
924  Section.FindFlag("ButAutomaticUpgrades", File->Flags, pkgCache::Flag::ButAutomaticUpgrades);
925 
926  return true;
927 }
928  /*}}}*/
929 // ReleaseIndex::FindInCache - Find this index /*{{{*/
931 {
932  std::string ReleaseFile;
933  bool const releaseExists = ReleaseFileName(this, ReleaseFile);
934 
936  for (; File.end() == false; ++File)
937  {
938  if (File->FileName == 0 || ReleaseFile != File.FileName())
939  continue;
940 
941  // empty means the file does not exist by "design"
942  if (ModifyCheck == false || (releaseExists == false && File->Size == 0))
943  return File;
944 
945  struct stat St;
946  if (stat(File.FileName(),&St) != 0)
947  {
948  if (_config->FindB("Debug::pkgCacheGen", false))
949  std::clog << "ReleaseIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
950  return pkgCache::RlsFileIterator(Cache);
951  }
952  if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
953  {
954  if (_config->FindB("Debug::pkgCacheGen", false))
955  std::clog << "ReleaseIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
956  << ") or mtime (" << St.st_mtime << " <> " << File->mtime
957  << ") doesn't match for " << File.FileName() << std::endl;
958  return pkgCache::RlsFileIterator(Cache);
959  }
960  return File;
961  }
962 
963  return File;
964 }
965  /*}}}*/
966 
968 {
969  static std::vector<std::string> getDefaultSetOf(std::string const &Name,
970  std::map<std::string, std::string> const &Options, std::vector<std::string> const &defaultValues)
971  {
972  auto const val = Options.find(Name);
973  if (val != Options.end())
974  return VectorizeString(val->second, ',');
975  return defaultValues;
976  }
977  static std::vector<std::string> applyPlusMinusOptions(std::string const &Name,
978  std::map<std::string, std::string> const &Options, std::vector<std::string> &&Values)
979  {
980  auto val = Options.find(Name + "+");
981  if (val != Options.end())
982  {
983  std::vector<std::string> const plus = VectorizeString(val->second, ',');
984  std::copy_if(plus.begin(), plus.end(), std::back_inserter(Values), [&Values](std::string const &v) {
985  return std::find(Values.begin(), Values.end(), v) == Values.end();
986  });
987  }
988  if ((val = Options.find(Name + "-")) != Options.end())
989  {
990  std::vector<std::string> const minus = VectorizeString(val->second, ',');
991  Values.erase(std::remove_if(Values.begin(), Values.end(), [&minus](std::string const &v) {
992  return std::find(minus.begin(), minus.end(), v) != minus.end();
993  }), Values.end());
994  }
995  return std::move(Values);
996  }
997  static std::vector<std::string> parsePlusMinusOptions(std::string const &Name,
998  std::map<std::string, std::string> const &Options, std::vector<std::string> const &defaultValues)
999  {
1000  return applyPlusMinusOptions(Name, Options, getDefaultSetOf(Name, Options, defaultValues));
1001  }
1002  static std::vector<std::string> parsePlusMinusArchOptions(std::string const &Name,
1003  std::map<std::string, std::string> const &Options)
1004  {
1005  auto Values = getDefaultSetOf(Name, Options, APT::Configuration::getArchitectures());
1006  // all is a very special architecture users shouldn't be concerned with explicitly
1007  // but if the user does, do not override the choice
1008  auto const val = Options.find(Name + "-");
1009  if (val != Options.end())
1010  {
1011  std::vector<std::string> const minus = VectorizeString(val->second, ',');
1012  if (std::find(minus.begin(), minus.end(), "all") != minus.end())
1013  return applyPlusMinusOptions(Name, Options, std::move(Values));
1014  }
1015  Values = applyPlusMinusOptions(Name, Options, std::move(Values));
1016  if (std::find(Values.begin(), Values.end(), "all") == Values.end())
1017  Values.push_back("implicit:all");
1018  return Values;
1019  }
1020  static std::vector<std::string> parsePlusMinusTargetOptions(char const * const Name,
1021  std::map<std::string, std::string> const &Options)
1022  {
1023  std::vector<std::string> const alltargets = _config->FindVector(std::string("Acquire::IndexTargets::") + Name, "", true);
1024  std::vector<std::string> deftargets;
1025  deftargets.reserve(alltargets.size());
1026  std::copy_if(alltargets.begin(), alltargets.end(), std::back_inserter(deftargets), [&](std::string const &t) {
1027  std::string c = "Acquire::IndexTargets::";
1028  c.append(Name).append("::").append(t).append("::DefaultEnabled");
1029  return _config->FindB(c, true);
1030  });
1031  std::vector<std::string> mytargets = parsePlusMinusOptions("target", Options, deftargets);
1032  for (auto const &target : alltargets)
1033  {
1034  std::map<std::string, std::string>::const_iterator const opt = Options.find(target);
1035  if (opt == Options.end())
1036  continue;
1037  auto const idMatch = [&](std::string const &t) {
1038  return target == _config->Find(std::string("Acquire::IndexTargets::") + Name + "::" + t + "::Identifier", t);
1039  };
1040  if (StringToBool(opt->second))
1041  std::copy_if(alltargets.begin(), alltargets.end(), std::back_inserter(mytargets), idMatch);
1042  else
1043  mytargets.erase(std::remove_if(mytargets.begin(), mytargets.end(), idMatch), mytargets.end());
1044  }
1045  // if we can't order it in a 1000 steps we give up… probably a cycle
1046  for (auto i = 0; i < 1000; ++i)
1047  {
1048  bool Changed = false;
1049  for (auto t = mytargets.begin(); t != mytargets.end(); ++t)
1050  {
1051  std::string const fallback = _config->Find(std::string("Acquire::IndexTargets::") + Name + "::" + *t + "::Fallback-Of");
1052  if (fallback.empty())
1053  continue;
1054  auto const faller = std::find(mytargets.begin(), mytargets.end(), fallback);
1055  if (faller == mytargets.end() || faller < t)
1056  continue;
1057  Changed = true;
1058  auto const tv = *t;
1059  mytargets.erase(t);
1060  mytargets.emplace_back(tv);
1061  break;
1062  }
1063  if (Changed == false)
1064  break;
1065  }
1066  // remove duplicates without changing the order (in first appearance)
1067  {
1068  std::set<std::string> seenOnce;
1069  mytargets.erase(std::remove_if(mytargets.begin(), mytargets.end(), [&](std::string const &t) {
1070  return seenOnce.insert(t).second == false;
1071  }), mytargets.end());
1072  }
1073  return mytargets;
1074  }
1075 
1076  metaIndex::TriState GetTriStateOption(std::map<std::string, std::string>const &Options, char const * const name) const
1077  {
1078  std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
1079  if (opt != Options.end())
1080  return StringToBool(opt->second, false) ? metaIndex::TRI_YES : metaIndex::TRI_NO;
1081  return metaIndex::TRI_DONTCARE;
1082  }
1083 
1084  static time_t GetTimeOption(std::map<std::string, std::string>const &Options, char const * const name)
1085  {
1086  std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
1087  if (opt == Options.end())
1088  return 0;
1089  return strtoull(opt->second.c_str(), NULL, 10);
1090  }
1091 
1092  static bool GetBoolOption(std::map<std::string, std::string> const &Options, char const * const name, bool const defVal)
1093  {
1094  std::map<std::string, std::string>::const_iterator const opt = Options.find(name);
1095  if (opt == Options.end())
1096  return defVal;
1097  return StringToBool(opt->second, defVal);
1098  }
1099 
1100  static std::vector<std::string> GetMapKeys(std::map<std::string, std::string> const &Options)
1101  {
1102  std::vector<std::string> ret;
1103  ret.reserve(Options.size());
1104  std::transform(Options.begin(), Options.end(), std::back_inserter(ret),
1105  [](auto &&O) { return O.first; });
1106  std::sort(ret.begin(), ret.end());
1107  return ret;
1108  }
1109 
1110  static bool MapsAreEqual(std::map<std::string, std::string> const &OptionsA,
1111  std::map<std::string, std::string> const &OptionsB,
1112  std::string const &URI, std::string const &Dist)
1113  {
1114  auto const KeysA = GetMapKeys(OptionsA);
1115  auto const KeysB = GetMapKeys(OptionsB);
1116  auto const m = std::mismatch(KeysA.begin(), KeysA.end(), KeysB.begin());
1117  if (m.first != KeysA.end())
1118  {
1119  if (std::find(KeysB.begin(), KeysB.end(), *m.first) == KeysB.end())
1120  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), m.first->c_str(), "<set>", "<unset>");
1121  else
1122  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), m.second->c_str(), "<set>", "<unset>");
1123  }
1124  if (m.second != KeysB.end())
1125  {
1126  if (std::find(KeysA.begin(), KeysA.end(), *m.second) == KeysA.end())
1127  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), m.first->c_str(), "<set>", "<unset>");
1128  else
1129  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), m.second->c_str(), "<set>", "<unset>");
1130  }
1131  for (auto&& key: KeysA)
1132  {
1133  if (key == "BASE_URI" || key == "REPO_URI" || key == "SITE" || key == "RELEASE")
1134  continue;
1135  auto const a = OptionsA.find(key);
1136  auto const b = OptionsB.find(key);
1137  if (unlikely(a == OptionsA.end() || b == OptionsB.end()) || a->second != b->second)
1138  return _error->Error(_("Conflicting values set for option %s regarding source %s %s"), key.c_str(), URI.c_str(), Dist.c_str());
1139  }
1140  return true;
1141  }
1142 
1143  static debReleaseIndex * GetDebReleaseIndexBy(std::vector<metaIndex *> &List, std::string const &URI,
1144  std::string const &Dist, std::map<std::string, std::string> const &Options)
1145  {
1146  std::map<std::string, std::string> ReleaseOptions{{
1147  {"BASE_URI", constructMetaIndexURI(URI, Dist, "")},
1148  {"REPO_URI", URI},
1149  {"SITE", ::URI::ArchiveOnly(URI)},
1150  {"RELEASE", (Dist == "/") ? "" : Dist},
1151  }};
1152  if (GetBoolOption(Options, "allow-insecure", _config->FindB("Acquire::AllowInsecureRepositories")))
1153  ReleaseOptions.emplace("ALLOW_INSECURE", "true");
1154  if (GetBoolOption(Options, "allow-weak", _config->FindB("Acquire::AllowWeakRepositories")))
1155  ReleaseOptions.emplace("ALLOW_WEAK", "true");
1156  if (GetBoolOption(Options, "allow-downgrade-to-insecure", _config->FindB("Acquire::AllowDowngradeToInsecureRepositories")))
1157  ReleaseOptions.emplace("ALLOW_DOWNGRADE_TO_INSECURE", "true");
1158 
1159  auto InReleasePath = Options.find("inrelease-path");
1160  if (InReleasePath != Options.end())
1161  ReleaseOptions.emplace("INRELEASE_PATH", InReleasePath->second);
1162 
1163  debReleaseIndex * Deb = nullptr;
1164  std::string const FileName = URItoFileName(constructMetaIndexURI(URI, Dist, "Release"));
1165  for (auto const &I: List)
1166  {
1167  // We only worry about debian entries here
1168  if (strcmp(I->GetType(), "deb") != 0)
1169  continue;
1170 
1171  auto const D = dynamic_cast<debReleaseIndex*>(I);
1172  if (unlikely(D == nullptr))
1173  continue;
1174 
1175  /* This check ensures that there will be only one Release file
1176  queued for all the Packages files and Sources files it
1177  corresponds to. */
1178  if (URItoFileName(D->MetaIndexURI("Release")) == FileName)
1179  {
1180  if (MapsAreEqual(ReleaseOptions, D->GetReleaseOptions(), URI, Dist) == false)
1181  return nullptr;
1182  Deb = D;
1183  break;
1184  }
1185  }
1186 
1187  // No currently created Release file indexes this entry, so we create a new one.
1188  if (Deb == nullptr)
1189  {
1190  Deb = new debReleaseIndex(URI, Dist, ReleaseOptions);
1191  List.push_back(Deb);
1192  }
1193  return Deb;
1194  }
1195 
1196  protected:
1197 
1198  bool CreateItemInternal(std::vector<metaIndex *> &List, std::string const &URI,
1199  std::string const &Dist, std::string const &Section,
1200  bool const &IsSrc, std::map<std::string, std::string> const &Options) const
1201  {
1202  auto const Deb = GetDebReleaseIndexBy(List, URI, Dist, Options);
1203  if (Deb == nullptr)
1204  return false;
1205 
1206  bool const UsePDiffs = GetBoolOption(Options, "pdiffs", _config->FindB("Acquire::PDiffs", true));
1207 
1208  std::string UseByHash = _config->Find("APT::Acquire::By-Hash", "yes");
1209  UseByHash = _config->Find("Acquire::By-Hash", UseByHash);
1210  {
1211  std::string const host = ::URI(URI).Host;
1212  if (host.empty() == false)
1213  {
1214  UseByHash = _config->Find("APT::Acquire::" + host + "::By-Hash", UseByHash);
1215  UseByHash = _config->Find("Acquire::" + host + "::By-Hash", UseByHash);
1216  }
1217  std::map<std::string, std::string>::const_iterator const opt = Options.find("by-hash");
1218  if (opt != Options.end())
1219  UseByHash = opt->second;
1220  }
1221 
1222  auto const entry = Options.find("sourceslist-entry");
1223  Deb->AddComponent(
1224  entry->second,
1225  IsSrc,
1226  Section,
1227  parsePlusMinusTargetOptions(Name, Options),
1228  parsePlusMinusArchOptions("arch", Options),
1229  parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)),
1230  UsePDiffs,
1231  UseByHash
1232  );
1233 
1234  if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false ||
1235  Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false ||
1236  Deb->SetValidUntilMax(GetTimeOption(Options, "valid-until-max")) == false ||
1237  Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false ||
1238  Deb->SetCheckDate(GetTriStateOption(Options, "check-date")) == false ||
1239  Deb->SetDateMaxFuture(GetTimeOption(Options, "date-max-future")) == false)
1240  return false;
1241 
1242  std::map<std::string, std::string>::const_iterator const signedby = Options.find("signed-by");
1243  if (signedby == Options.end())
1244  {
1245  bool alreadySet = false;
1246  std::string filename;
1247  if (ReleaseFileName(Deb, filename))
1248  {
1249  auto OldDeb = Deb->UnloadedClone();
1250  _error->PushToStack();
1251  OldDeb->Load(filename, nullptr);
1252  bool const goodLoad = _error->PendingError() == false;
1253  _error->RevertToStack();
1254  if (goodLoad)
1255  {
1256  if (OldDeb->GetValidUntil() > 0)
1257  {
1258  time_t const invalid_since = time(NULL) - OldDeb->GetValidUntil();
1259  if (invalid_since <= 0)
1260  {
1261  Deb->SetSignedBy(OldDeb->GetSignedBy());
1262  alreadySet = true;
1263  }
1264  }
1265  }
1266  delete OldDeb;
1267  }
1268  if (alreadySet == false && Deb->SetSignedBy("") == false)
1269  return false;
1270  }
1271  else
1272  {
1273  if (Deb->SetSignedBy(signedby->second) == false)
1274  return false;
1275  }
1276 
1277  return true;
1278  }
1279 
1280  debSLTypeDebian(char const * const Name, char const * const Label) : Type(Name, Label)
1281  {
1282  }
1283 };
1284  /*}}}*/
1286 {
1287  public:
1288 
1289  bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
1290  std::string const &Dist, std::string const &Section,
1291  std::map<std::string, std::string> const &Options) const APT_OVERRIDE
1292  {
1293  return CreateItemInternal(List, URI, Dist, Section, false, Options);
1294  }
1295 
1296  debSLTypeDeb() : debSLTypeDebian("deb", "Debian binary tree")
1297  {
1298  }
1299 };
1300  /*}}}*/
1302 {
1303  public:
1304 
1305  bool CreateItem(std::vector<metaIndex *> &List, std::string const &URI,
1306  std::string const &Dist, std::string const &Section,
1307  std::map<std::string, std::string> const &Options) const APT_OVERRIDE
1308  {
1309  return CreateItemInternal(List, URI, Dist, Section, true, Options);
1310  }
1311 
1312  debSLTypeDebSrc() : debSLTypeDebian("deb-src", "Debian source tree")
1313  {
1314  }
1315 };
1316  /*}}}*/
1317 
strprintf(m, msg, repo.c_str())
static bool std::string const metaIndex const *const pkgAcqMetaClearSig *const pkgAcquire::Item *const I
static bool std::string const metaIndex const *const pkgAcqMetaClearSig *const TransactionManager
bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &MessageFile)
open a file which might be clear-signed
Definition: gpgv.cc:538
int FindI(const char *Name, int const &Default=0) const
std::vector< std::string > FindVector(const char *Name, std::string const &Default="", bool const Keys=false) const
std::string Find(const char *Name, const char *Default=0) const
bool FindB(const char *Name, bool const &Default=false) const
std::string FindDir(const char *Name, const char *Default=0) const
Definition: fileutl.h:39
bool IsOpen()
Definition: fileutl.h:150
bool Failed()
Definition: fileutl.h:151
unsigned long long Size()
Definition: fileutl.cc:2967
unsigned long long FileSize() const
Definition: hashes.cc:210
bool usable() const
Definition: hashes.cc:153
static APT_PURE const char ** SupportedHashes()
Definition: hashes.cc:135
Information about an index file.
Definition: indexfile.h:39
@ SOURCESENTRY
Definition: indexfile.h:85
Definition: strutl.h:193
static std::string ArchiveOnly(const std::string &URI)
Definition: strutl.cc:1798
std::string Host
Definition: strutl.h:201
debReleaseIndexPrivate(std::map< std::string, std::string > const &Options)
metaIndex::TriState CheckDate
std::vector< std::string > SupportedComponents
metaIndex::TriState CheckValidUntil
Definition: debmetaindex.cc:99
std::vector< std::string > NoSupportForAll
std::vector< debSectionEntry > DebSrcEntries
Definition: debmetaindex.cc:97
std::vector< debSectionEntry > DebEntries
Definition: debmetaindex.cc:96
std::map< std::string, std::string > const ReleaseOptions
std::vector< std::string > Architectures
debReleaseIndex(std::string const &URI, std::string const &Dist, std::map< std::string, std::string > const &Options)
bool SetSignedBy(std::string const &SignedBy)
virtual ~debReleaseIndex()
bool SetTrusted(TriState const Trusted)
virtual bool Merge(pkgCacheGenerator &Gen, OpProgress *Prog) const APT_OVERRIDE
APT_HIDDEN bool parseSumData(const char *&Start, const char *End, std::string &Name, std::string &Hash, unsigned long long &Size)
bool IsArchitectureSupported(std::string const &arch) const override
bool SetValidUntilMin(time_t const Valid)
bool SetCheckValidUntil(TriState const Trusted)
virtual std::string ArchiveURI(std::string const &File) const APT_OVERRIDE
bool SetDateMaxFuture(time_t const DateMaxFuture)
virtual bool IsTrusted() const APT_OVERRIDE
debReleaseIndexPrivate *const d
Definition: debmetaindex.h:21
bool IsArchitectureAllSupportedFor(IndexTarget const &target) const override
bool HasSupportForComponent(std::string const &component) const override
virtual std::string Describe() const APT_OVERRIDE
void AddComponent(std::string const &sourcesEntry, bool const isSrc, std::string const &Name, std::vector< std::string > const &Targets, std::vector< std::string > const &Architectures, std::vector< std::string > Languages, bool const usePDiffs, std::string const &useByHash)
virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) APT_OVERRIDE
std::map< std::string, std::string > GetReleaseOptions()
APT_HIDDEN std::string MetaIndexFile(const char *Types) const
virtual metaIndex * UnloadedClone() const APT_OVERRIDE
bool SetValidUntilMax(time_t const Valid)
virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const APT_OVERRIDE
APT_HIDDEN std::string MetaIndexInfo(const char *Type) const
virtual std::vector< IndexTarget > GetIndexTargets() const APT_OVERRIDE
bool SetCheckDate(TriState const CheckDate)
virtual bool Load(std::string const &Filename, std::string *const ErrorText) APT_OVERRIDE
APT_PURE time_t GetNotBefore() const override
virtual std::vector< pkgIndexFile * > * GetIndexFiles() APT_OVERRIDE
APT_HIDDEN std::string MetaIndexURI(const char *Type) const
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 APT_OVERRIDE
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 APT_OVERRIDE
bool CreateItemInternal(std::vector< metaIndex * > &List, std::string const &URI, std::string const &Dist, std::string const &Section, bool const &IsSrc, std::map< std::string, std::string > const &Options) const
static std::vector< std::string > parsePlusMinusArchOptions(std::string const &Name, std::map< std::string, std::string > const &Options)
debSLTypeDebian(char const *const Name, char const *const Label)
static std::vector< std::string > parsePlusMinusOptions(std::string const &Name, std::map< std::string, std::string > const &Options, std::vector< std::string > const &defaultValues)
static time_t GetTimeOption(std::map< std::string, std::string >const &Options, char const *const name)
static std::vector< std::string > parsePlusMinusTargetOptions(char const *const Name, std::map< std::string, std::string > const &Options)
static debReleaseIndex * GetDebReleaseIndexBy(std::vector< metaIndex * > &List, std::string const &URI, std::string const &Dist, std::map< std::string, std::string > const &Options)
static bool GetBoolOption(std::map< std::string, std::string > const &Options, char const *const name, bool const defVal)
static std::vector< std::string > applyPlusMinusOptions(std::string const &Name, std::map< std::string, std::string > const &Options, std::vector< std::string > &&Values)
static std::vector< std::string > getDefaultSetOf(std::string const &Name, std::map< std::string, std::string > const &Options, std::vector< std::string > const &defaultValues)
static bool MapsAreEqual(std::map< std::string, std::string > const &OptionsA, std::map< std::string, std::string > const &OptionsB, std::string const &URI, std::string const &Dist)
metaIndex::TriState GetTriStateOption(std::map< std::string, std::string >const &Options, char const *const name) const
static std::vector< std::string > GetMapKeys(std::map< std::string, std::string > const &Options)
std::string ReleaseNotes
Definition: metaindex.h:51
std::string Suite
Definition: metaindex.h:45
signed short DefaultPin
Definition: metaindex.h:50
std::string Dist
Definition: metaindex.h:40
TriState Trusted
Definition: metaindex.h:41
std::string GetLabel() const
Definition: metaindex.cc:61
std::string Codename
Definition: metaindex.h:46
std::string Version
Definition: metaindex.h:49
std::string Origin
Definition: metaindex.h:47
std::string SignedBy
Definition: metaindex.h:42
time_t ValidUntil
Definition: metaindex.h:53
time_t Date
Definition: metaindex.h:52
std::vector< pkgIndexFile * > * Indexes
Definition: metaindex.h:36
const char * GetType() const
Definition: metaindex.cc:57
TriState LoadedSuccessfully
Definition: metaindex.h:56
bool SupportsAcquireByHash
Definition: metaindex.h:54
std::map< std::string, checkSum * > Entries
Definition: metaindex.h:55
std::string Label
Definition: metaindex.h:48
const char * Type
Definition: metaindex.h:38
An acquire item that is responsible for fetching an index {{{ file (e.g., Packages or Sources).
Definition: acquire-item.h:618
An item responsible for downloading clearsigned metaindexes {{{.
Definition: acquire-item.h:560
Represents the process by which a pkgAcquire object should retrieve a file or a collection of files.
Definition: acquire-item.h:59
static APT_HIDDEN std::string URIEncode(std::string const &part)
Definition: acquire.cc:54
RlsFileIterator RlsFileBegin()
Definition: pkgcache.h:818
bool Step(pkgTagSection &Section)
Definition: tagfile.cc:204
APT_HIDDEN bool FindB(Key key, bool Default=false) const
Definition: tagfile.cc:835
std::string FindS(APT::StringView sv) const
Definition: tagfile.h:70
APT_HIDDEN bool Find(Key key, const char *&Start, const char *&End) const
Definition: tagfile.cc:690
APT_HIDDEN bool FindFlag(Key key, uint8_t &Flags, uint8_t const Flag) const
Definition: tagfile.cc:858
Configuration * _config
static void GetIndexTargetsFor(char const *const Type, std::string const &URI, std::string const &Dist, std::vector< debReleaseIndexPrivate::debSectionEntry > const &entries, std::vector< IndexTarget > &IndexTargets, std::map< std::string, std::string > const &ReleaseOptions)
APT_HIDDEN debSLTypeDeb _apt_DebType
APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType
#define APT_TARGET(X)
#define APT_INRELEASE(TYPE, TAG, STORE)
#define APT_T_CONFIG_BOOL(X, Y)
#define APT_T_CONFIG_STR(X, Y)
static std::string NormalizeSignedBy(std::string SignedBy, bool const SupportFilenames)
Definition: debmetaindex.cc:56
static std::string transformFingergrpints(std::string finger)
Definition: debmetaindex.cc:31
static std::string transformFingergrpintsWithFilenames(std::string const &finger)
Definition: debmetaindex.cc:48
static std::string constructMetaIndexURI(std::string URI, std::string const &Dist, char const *const Type)
static bool ReleaseFileName(debReleaseIndex const *const That, std::string &ReleaseFile)
bool FileExists(string File)
Definition: fileutl.cc:326
#define APT_OVERRIDE
Definition: macros.h:111
#define APT_HIDDEN
Definition: macros.h:78
TRI_DONTCARE
Definition: metaindex.h:31
TRI_YES
Definition: metaindex.h:31
TRI_NO
Definition: metaindex.h:31
APT_PUBLIC std::vector< std::string > const getArchitectures(bool const &Cached=true)
Returns a vector of Architectures we support.
APT_PUBLIC std::vector< std::string > const getCompressionTypes(bool const &Cached=true)
Returns a vector of usable Compression Types.
APT_PUBLIC std::vector< Compressor > const getCompressors(bool const Cached=true)
Return a vector of Compressors supported for data.tar's.
APT_PUBLIC std::vector< std::string > const getLanguages(bool const &All=false, bool const &Cached=true, char const **const Locale=0)
Returns a vector of Language Codes.
Representation of supported compressors.
std::vector< std::string > const Targets
Definition: debmetaindex.cc:89
std::vector< std::string > const Languages
Definition: debmetaindex.cc:91
std::vector< std::string > const Architectures
Definition: debmetaindex.cc:90
unsigned long long Size
Definition: metaindex.h:27
HashStringList Hashes
Definition: metaindex.h:26
std::string MetaKeyFilename
Definition: metaindex.h:25
@ ButAutomaticUpgrades
Definition: pkgcache.h:203
map_flags_t Flags
Definition: pkgcache.h:533
int StringToBool(const string &Text, int Default)
Definition: strutl.cc:820
string SubstVar(const string &Str, const string &Subst, const string &Contents)
Definition: strutl.cc:502
string URItoFileName(const string &URI)
Definition: strutl.cc:553
bool RFC1123StrToTime(std::string const &str, time_t &time)
Definition: strutl.cc:1040
vector< string > VectorizeString(string const &haystack, char const &split)
Definition: strutl.cc:1308