Explorar el Código

Support Adler32 checksum

Adler32 checksum is available for --checksum option and hash element
in Metalink files.  Currently, we use Adler32 implementation in Zlib.
Tatsuhiro Tsujikawa hace 11 años
padre
commit
e18e8aeeaa

+ 76 - 0
src/Adler32MessageDigestImpl.cc

@@ -0,0 +1,76 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2014 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "Adler32MessageDigestImpl.h"
+
+#include <cstring>
+
+#include <zlib.h>
+
+#include "a2netcompat.h"
+
+namespace aria2 {
+
+Adler32MessageDigestImpl::Adler32MessageDigestImpl()
+  : adler_(adler32(0, Z_NULL, 0))
+{}
+
+size_t Adler32MessageDigestImpl::getDigestLength() const
+{
+  return length();
+}
+
+void Adler32MessageDigestImpl::reset()
+{
+  adler_ = adler32(0, Z_NULL, 0);
+}
+
+void Adler32MessageDigestImpl::update(const void* data, size_t length)
+{
+  adler_ = adler32(adler_, reinterpret_cast<const unsigned char*>(data),
+                   length);
+}
+
+void Adler32MessageDigestImpl::digest(unsigned char* md)
+{
+  auto adler = htonl(adler_);
+  memcpy(md, &adler, getDigestLength());
+}
+
+size_t Adler32MessageDigestImpl::length()
+{
+  return 4;
+}
+
+} // namespace aria2

+ 67 - 0
src/Adler32MessageDigestImpl.h

@@ -0,0 +1,67 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2014 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef D_ADLER32_MESSAGE_DIGEST_H
+#define D_ADLER32_MESSAGE_DIGEST_H
+
+#include "MessageDigestImpl.h"
+
+namespace aria2 {
+
+#ifdef HAVE_ZLIB
+
+#define ADLER32_MESSAGE_DIGEST                          \
+  { "adler32", make_hi<Adler32MessageDigestImpl>() },
+
+class Adler32MessageDigestImpl : public MessageDigestImpl {
+public:
+  Adler32MessageDigestImpl();
+  virtual size_t getDigestLength() const CXX11_OVERRIDE;
+  virtual void reset() CXX11_OVERRIDE;
+  virtual void update(const void* data, size_t length) CXX11_OVERRIDE;
+  virtual void digest(unsigned char* md) CXX11_OVERRIDE;
+  static size_t length();
+private:
+  unsigned long adler_;
+};
+
+#else // !HAVE_ZLIB
+
+#define ADLER32_MESSAGE_DIGEST
+
+#endif // !HAVE_ZLIB
+
+} // namespace aria2
+
+#endif // D_ADLER32_MESSAGE_DIGEST_H

+ 3 - 0
src/AppleMessageDigestImpl.cc

@@ -37,6 +37,8 @@
 
 #include <CommonCrypto/CommonDigest.h>
 
+#include "Adler32MessageDigestImpl.h"
+
 namespace aria2 {
 namespace {
 
@@ -126,6 +128,7 @@ MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
   { "sha-384", make_hi<MessageDigestSHA384>() },
   { "sha-512", make_hi<MessageDigestSHA512>() },
   { "md5", make_hi<MessageDigestMD5>() },
+  ADLER32_MESSAGE_DIGEST
 };
 
 } // namespace aria2

+ 3 - 0
src/InternalMessageDigestImpl.cc

@@ -37,6 +37,8 @@
 
 #include "crypto_hash.h"
 
+#include "Adler32MessageDigestImpl.h"
+
 namespace {
 using namespace aria2;
 using namespace crypto;
@@ -101,6 +103,7 @@ MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
   { "sha-384", make_hi<MessageDigestSHA384>() },
   { "sha-512", make_hi<MessageDigestSHA512>() },
   { "md5", make_hi<MessageDigestMD5>() },
+  ADLER32_MESSAGE_DIGEST
 };
 
 } // namespace aria2

+ 3 - 0
src/LibgcryptMessageDigestImpl.cc

@@ -37,6 +37,8 @@
 
 #include <gcrypt.h>
 
+#include "Adler32MessageDigestImpl.h"
+
 namespace aria2 {
 
 namespace {
@@ -116,6 +118,7 @@ MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
   { "sha-384", make_hi<MessageDigestSHA384>() },
   { "sha-512", make_hi<MessageDigestSHA512>() },
   { "md5", make_hi<MessageDigestMD5>() },
+  ADLER32_MESSAGE_DIGEST
 };
 
 } // namespace aria2

+ 3 - 0
src/LibnettleMessageDigestImpl.cc

@@ -37,6 +37,8 @@
 
 #include <nettle/nettle-meta.h>
 
+#include "Adler32MessageDigestImpl.h"
+
 namespace aria2 {
 
 namespace {
@@ -95,6 +97,7 @@ MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
   { "sha-384", make_hi<MessageDigestSHA384>() },
   { "sha-512", make_hi<MessageDigestSHA512>() },
   { "md5", make_hi<MessageDigestMD5>() },
+  ADLER32_MESSAGE_DIGEST
 };
 
 } // namespace aria2

+ 3 - 0
src/LibsslMessageDigestImpl.cc

@@ -37,6 +37,8 @@
 
 #include <openssl/evp.h>
 
+#include "Adler32MessageDigestImpl.h"
+
 namespace aria2 {
 
 template<const EVP_MD* (*init_fn)()>
@@ -102,6 +104,7 @@ MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
   { "sha-512", make_hi<MessageDigestBase<EVP_sha512> >() },
 #endif
   { "md5", make_hi<MessageDigestMD5>() },
+  ADLER32_MESSAGE_DIGEST
 };
 
 } // namespace aria2

+ 2 - 1
src/Makefile.am

@@ -417,7 +417,8 @@ if HAVE_ZLIB
 SRCS += \
 	GZipDecodingStreamFilter.cc GZipDecodingStreamFilter.h\
 	GZipEncoder.cc GZipEncoder.h\
-	GZipFile.cc GZipFile.h
+	GZipFile.cc GZipFile.h \
+	Adler32MessageDigestImpl.cc Adler32MessageDigestImpl.h
 endif # HAVE_ZLIB
 
 if HAVE_SQLITE3

+ 2 - 1
src/MessageDigest.cc

@@ -59,7 +59,8 @@ HashTypeEntry hashTypes[] = {
   HashTypeEntry("sha-256", 3),
   HashTypeEntry("sha-384", 4),
   HashTypeEntry("sha-512", 5),
-  HashTypeEntry("md5", 0)
+  HashTypeEntry("md5", 0),
+  HashTypeEntry("adler32", 0),
 };
 } // namespace aria2
 

+ 16 - 0
test/MessageDigestTest.cc

@@ -19,11 +19,15 @@ class MessageDigestTest:public CppUnit::TestFixture {
 
   std::unique_ptr<MessageDigest> sha1_;
   std::unique_ptr<MessageDigest> md5_;
+  std::unique_ptr<MessageDigest> adler32_;
 public:
   void setUp()
   {
     md5_ = MessageDigest::create("md5");
     sha1_ = MessageDigest::sha1();
+#ifdef HAVE_ZLIB
+    adler32_ = MessageDigest::create("adler32");
+#endif // HAVE_ZLIB
   }
 
   void testDigest();
@@ -54,6 +58,18 @@ void MessageDigestTest::testDigest()
   sha1_->update("abc", 3);
   CPPUNIT_ASSERT_EQUAL(std::string("a9993e364706816aba3e25717850c26c9cd0d89d"),
                        util::toHex(sha1_->digest()));
+
+#ifdef HAVE_ZLIB
+  adler32_->reset();
+  adler32_->update("aria2", 5);
+  CPPUNIT_ASSERT_EQUAL(std::string("05e101d0"),
+                       util::toHex(adler32_->digest()));
+
+  adler32_->reset();
+  adler32_->update("abc", 3);
+  CPPUNIT_ASSERT_EQUAL(std::string("024d0127"),
+                       util::toHex(adler32_->digest()));
+#endif // HAVE_ZLIB
 }
 
 void MessageDigestTest::testSupports()