summaryrefslogtreecommitdiff
path: root/apt-pkg/contrib
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2013-08-18 23:17:05 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2014-05-09 01:25:55 +0200
commitf4c3850ea335545e297504941dc8c7a8f1c83358 (patch)
tree935afa3ad29bc2770a3b72d8093885fdf0fefc35 /apt-pkg/contrib
parent0c8171d7c52a46a719382ee7ed67451213f608ec (diff)
add a simple container for HashStrings
APT supports more than just one HashString and even allows to enforce the usage of a specific hash. This class is intended to help with storage and passing around of the HashStrings. Git-Dch: Ignore
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r--apt-pkg/contrib/hashes.cc118
-rw-r--r--apt-pkg/contrib/hashes.h85
2 files changed, 187 insertions, 16 deletions
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc
index 15f83615d..bb11a3fca 100644
--- a/apt-pkg/contrib/hashes.cc
+++ b/apt-pkg/contrib/hashes.cc
@@ -27,7 +27,7 @@
#include <iostream>
/*}}}*/
-const char* HashString::_SupportedHashes[] =
+const char * HashString::_SupportedHashes[] =
{
"SHA512", "SHA256", "SHA1", "MD5Sum", NULL
};
@@ -42,11 +42,16 @@ HashString::HashString(std::string Type, std::string Hash) : Type(Type), Hash(Ha
HashString::HashString(std::string StringedHash) /*{{{*/
{
- // legacy: md5sum without "MD5Sum:" prefix
- if (StringedHash.find(":") == std::string::npos && StringedHash.size() == 32)
+ if (StringedHash.find(":") == std::string::npos)
{
- Type = "MD5Sum";
- Hash = StringedHash;
+ // legacy: md5sum without "MD5Sum:" prefix
+ if (StringedHash.size() == 32)
+ {
+ Type = "MD5Sum";
+ Hash = StringedHash;
+ }
+ if(_config->FindB("Debug::Hashes",false) == true)
+ std::clog << "HashString(string): invalid StringedHash " << StringedHash << std::endl;
return;
}
std::string::size_type pos = StringedHash.find(":");
@@ -82,25 +87,25 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/
std::string fileHash;
FileFd Fd(filename, FileFd::ReadOnly);
- if(Type == "MD5Sum")
+ if(strcasecmp(Type.c_str(), "MD5Sum") == 0)
{
MD5Summation MD5;
MD5.AddFD(Fd);
fileHash = (std::string)MD5.Result();
}
- else if (Type == "SHA1")
+ else if (strcasecmp(Type.c_str(), "SHA1") == 0)
{
SHA1Summation SHA1;
SHA1.AddFD(Fd);
fileHash = (std::string)SHA1.Result();
}
- else if (Type == "SHA256")
+ else if (strcasecmp(Type.c_str(), "SHA256") == 0)
{
SHA256Summation SHA256;
SHA256.AddFD(Fd);
fileHash = (std::string)SHA256.Result();
}
- else if (Type == "SHA512")
+ else if (strcasecmp(Type.c_str(), "SHA512") == 0)
{
SHA512Summation SHA512;
SHA512.AddFD(Fd);
@@ -111,20 +116,105 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/
return fileHash;
}
/*}}}*/
-const char** HashString::SupportedHashes()
+const char** HashString::SupportedHashes() /*{{{*/
{
return _SupportedHashes;
}
-
-APT_PURE bool HashString::empty() const
+ /*}}}*/
+APT_PURE bool HashString::empty() const /*{{{*/
{
return (Type.empty() || Hash.empty());
}
+ /*}}}*/
+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);
+}
+ /*}}}*/
+
+HashString const * HashStringList::find(char const * const type) const /*{{{*/
+{
+ if (type == NULL || type[0] == '\0')
+ {
+ std::string 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;
+}
+ /*}}}*/
+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;
-std::string HashString::toStr() const
+ list.push_back(hashString);
+ return true;
+}
+ /*}}}*/
+bool HashStringList::VerifyFile(std::string filename) const /*{{{*/
{
- return Type + std::string(":") + Hash;
+ if (list.empty() == true)
+ return false;
+ HashString const * const hs = find(NULL);
+ if (hs == NULL || hs->VerifyFile(filename) == false)
+ return false;
+ return true;
}
+ /*}}}*/
+bool HashStringList::operator==(HashStringList const &other) const /*{{{*/
+{
+ short matches = 0;
+ for (const_iterator hs = begin(); hs != end(); ++hs)
+ {
+ HashString const * const ohs = other.find(hs->HashType());
+ if (ohs == NULL)
+ continue;
+ if (*hs != *ohs)
+ return false;
+ ++matches;
+ }
+ if (matches == 0)
+ return false;
+ return true;
+}
+bool HashStringList::operator!=(HashStringList const &other) const
+{
+ return !(*this == other);
+}
+ /*}}}*/
// Hashes::AddFD - Add the contents of the FD /*{{{*/
// ---------------------------------------------------------------------
diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h
index 7a62f8a8f..490282209 100644
--- a/apt-pkg/contrib/hashes.h
+++ b/apt-pkg/contrib/hashes.h
@@ -17,6 +17,7 @@
#include <apt-pkg/md5.h>
#include <apt-pkg/sha1.h>
#include <apt-pkg/sha2.h>
+#include <apt-pkg/macros.h>
#include <cstring>
#include <string>
@@ -41,7 +42,7 @@ class HashString
protected:
std::string Type;
std::string Hash;
- static const char* _SupportedHashes[10];
+ static const char * _SupportedHashes[10];
// internal helper
std::string GetHashForFile(std::string filename) const;
@@ -52,7 +53,8 @@ class HashString
HashString();
// get hash type used
- std::string HashType() { return Type; };
+ std::string HashType() const { return Type; };
+ std::string HashValue() const { return Hash; };
// verify the given filename against the currently loaded hash
bool VerifyFile(std::string filename) const;
@@ -64,11 +66,90 @@ class HashString
// helper
std::string toStr() const; // convert to str as "type:hash"
bool empty() const;
+ bool operator==(HashString const &other) const;
+ bool operator!=(HashString const &other) const;
// return the list of hashes we support
static APT_CONST const char** SupportedHashes();
};
+class HashStringList
+{
+ public:
+ /** find best hash if no specific one is requested
+ *
+ * @param type of the checksum to return, can be \b NULL
+ * @return If type is \b NULL (or the empty string) it will
+ * return the 'best' hash; otherwise the hash which was
+ * specifically requested. If no hash is found \b NULL will be returned.
+ */
+ HashString const * find(char const * const type) const;
+ HashString const * find(std::string const &type) const { return find(type.c_str()); }
+ /** check if the given hash type is supported
+ *
+ * @param type to check
+ * @return true if supported, otherwise false
+ */
+ static APT_PURE bool supported(char const * const type);
+ /** add the given #HashString to the list
+ *
+ * @param hashString to add
+ * @return true if the hash is added because it is supported and
+ * not already a different hash of the same type included, otherwise false
+ */
+ bool push_back(const HashString &hashString);
+ /** @return size of the list of HashStrings */
+ size_t size() const { return list.size(); }
+
+ /** take the 'best' hash and verify file with it
+ *
+ * @param filename to verify
+ * @return true if the file matches the hashsum, otherwise false
+ */
+ bool VerifyFile(std::string filename) const;
+
+ /** is the list empty ?
+ *
+ * @return \b true if the list is empty, otherwise \b false
+ */
+ bool empty() const { return list.empty(); }
+
+ typedef std::vector<HashString>::const_iterator const_iterator;
+
+ /** iterator to the first element */
+ const_iterator begin() const { return list.begin(); }
+
+ /** iterator to the end element */
+ const_iterator end() const { return list.end(); }
+
+ /** start fresh with a clear list */
+ void clear() { list.clear(); }
+
+ /** compare two HashStringList for similarity.
+ *
+ * Two lists are similar if at least one hashtype is in both lists
+ * and the hashsum matches. All hashes are checked, if one doesn't
+ * match false is returned regardless of how many matched before.
+ */
+ bool operator==(HashStringList const &other) const;
+ bool operator!=(HashStringList const &other) const;
+
+ HashStringList() {}
+
+ // simplifying API-compatibility constructors
+ HashStringList(std::string const &hash) {
+ if (hash.empty() == false)
+ list.push_back(HashString(hash));
+ }
+ HashStringList(char const * const hash) {
+ if (hash != NULL && hash[0] != '\0')
+ list.push_back(HashString(hash));
+ }
+
+ private:
+ std::vector<HashString> list;
+};
+
class Hashes
{
public: