+ /*}}}*/
+
+APT_PURE static bool IsConfigured(const char *name, const char *what)
+{
+ std::string option;
+ strprintf(option, "APT::Hashes::%s::%s", name, what);
+ return _config->FindB(option, false);
+}
+
+APT_PURE bool HashString::usable() const /*{{{*/
+{
+ return (
+ (Type != "Checksum-FileSize") &&
+ //(Type != "MD5Sum") &&
+ //(Type != "SHA1") &&
+ !IsConfigured(Type.c_str(), "Untrusted")
+ );
+}
+ /*}}}*/
+std::string HashString::toStr() const /*{{{*/
+{
+ return Type + ":" + Hash;
+}
+ /*}}}*/
+APT_PURE bool HashString::operator==(HashString const &other) const /*{{{*/
+{
+ return (strcasecmp(Type.c_str(), other.Type.c_str()) == 0 && Hash == other.Hash);
+}
+APT_PURE bool HashString::operator!=(HashString const &other) const
+{
+ return !(*this == other);
+}
+ /*}}}*/
+
+bool HashStringList::usable() const /*{{{*/
+{
+ if (empty() == true)
+ return false;
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
+ if (forcedType.empty() == true)
+ {
+ // See if there is at least one usable hash
+ for (auto const &hs: list)
+ if (hs.usable())
+ return true;
+ return false;
+ }
+ return find(forcedType) != NULL;
+}
+ /*}}}*/
+HashString const * HashStringList::find(char const * const type) const /*{{{*/
+{
+ if (type == NULL || type[0] == '\0')
+ {
+ std::string const forcedType = _config->Find("Acquire::ForceHash", "");
+ if (forcedType.empty() == false)
+ return find(forcedType.c_str());
+ for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+ for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs)
+ if (strcasecmp(hs->HashType().c_str(), *t) == 0)
+ return &*hs;
+ return NULL;
+ }
+ for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs)
+ if (strcasecmp(hs->HashType().c_str(), type) == 0)
+ return &*hs;
+ return NULL;
+}
+ /*}}}*/
+unsigned long long HashStringList::FileSize() const /*{{{*/
+{
+ HashString const * const hsf = find("Checksum-FileSize");
+ if (hsf == NULL)
+ return 0;
+ std::string const hv = hsf->HashValue();
+ return strtoull(hv.c_str(), NULL, 10);
+}
+ /*}}}*/
+bool HashStringList::FileSize(unsigned long long const Size) /*{{{*/
+{
+ std::string size;
+ strprintf(size, "%llu", Size);
+ return push_back(HashString("Checksum-FileSize", size));
+}
+ /*}}}*/
+bool HashStringList::supported(char const * const type) /*{{{*/
+{
+ for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t)
+ if (strcasecmp(*t, type) == 0)
+ return true;
+ return false;
+}
+ /*}}}*/
+bool HashStringList::push_back(const HashString &hashString) /*{{{*/
+{
+ if (hashString.HashType().empty() == true ||
+ hashString.HashValue().empty() == true ||
+ supported(hashString.HashType().c_str()) == false)
+ return false;
+
+ // ensure that each type is added only once
+ HashString const * const hs = find(hashString.HashType().c_str());
+ if (hs != NULL)
+ return *hs == hashString;
+
+ list.push_back(hashString);
+ return true;
+}
+ /*}}}*/
+bool HashStringList::VerifyFile(std::string filename) const /*{{{*/
+{
+ if (usable() == false)
+ return false;