After spending some time with this issue recently I discovered the root
of the problem. Unlike I assumed before it has nothing to do with
the way the http method is structured but solely stems from the way
hashing is done in apt, sequential and in the same thread as the
download.

Replacing the hashing methods with the ones provided by libnettle, which
apt is already indirectly linked against via libcurl-gnutls resulted in a
speedboost from 24MBps up to around 32MBps. Anything more than that will
require threading of the hash methods. For reference the maximum speed
without hashing would be 75MBps.

Old implementation:
% apt-get download 0ad-data
Get:1 http://.../ jessie/main 0ad-data all 0.0.17-1 [566 MB]
Fetched 566 MB in 23s (23.7 MB/s)

And with libnettle:
% apt-get download 0ad-data
Get:1 http://.../ jessie/main 0ad-data all 0.0.17-1 [566 MB]
Fetched 566 MB in 17s (31.9 MB/s)

In the process of finding the culprit I also replaced the http method
with a new version using libcurl. Similiar to the https method. This
change does not provide any measurable speed boost as of yet, as the
whole process is still waiting for the hashing to complete. I attached
the patch nonetheless as it removes a lot of redudant code.
diff --git a/apt-pkg/contrib/md5.cc b/apt-pkg/contrib/md5.cc
index b487a96..5c7780d 100644
--- a/apt-pkg/contrib/md5.cc
+++ b/apt-pkg/contrib/md5.cc
@@ -1,183 +1,25 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: md5.cc,v 1.12 2001/05/13 05:15:03 jgg Exp $
+// $Id: md5.cc,v 1.2 2015/01/16 09:42:12 lhw Exp $
 /* ######################################################################
-   
-   MD5Sum - MD5 Message Digest Algorithm.
-
-   This code implements the MD5 message-digest algorithm. The algorithm is 
-   due to Ron Rivest.  This code was written by Colin Plumb in 1993, no 
-   copyright is claimed. This code is in the public domain; do with it what 
-   you wish.
- 
-   Equivalent code is available from RSA Data Security, Inc. This code has 
-   been tested against that, and is equivalent, except that you don't need to 
-   include two pages of legalese with every copy.
 
-   To compute the message digest of a chunk of bytes, instantiate the class,
-   and repeatedly call one of the Add() members. When finished the Result 
-   method will return the Hash and finalize the value.
-   
-   Changed so as no longer to depend on Colin Plumb's `usual.h' header
-   definitions; now uses stuff from dpkg's config.h.
-    - Ian Jackson <[email protected]>.
-   
-   Changed into a C++ interface and made work with APT's config.h.
-    - Jason Gunthorpe <[email protected]>
-   
-   Still in the public domain.
+   MD5Sum - MD5 Message Digest Algorithm.
 
-   The classes use arrays of char that are a specific size. We cast those
-   arrays to uint8_t's and go from there. This allows us to advoid using
-   the uncommon inttypes.h in a public header or internally newing memory.
-   In theory if C9x becomes nicely accepted
-   
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
 #include <config.h>
 
 #include <apt-pkg/md5.h>
-
-#include <stdint.h>
-#include <string.h>
-									/*}}}*/
-
-// byteSwap - Swap bytes in a buffer					/*{{{*/
-// ---------------------------------------------------------------------
-/* Swap n 32 bit longs in given buffer */
-#ifdef WORDS_BIGENDIAN
-static void byteSwap(uint32_t *buf, unsigned words)
-{
-   uint8_t *p = (uint8_t *)buf;
-   
-   do 
-   {
-      *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
-	 ((unsigned)p[1] << 8 | p[0]);
-      p += 4;
-   } while (--words);
-}
-#else
-#define byteSwap(buf,words)
-#endif
 									/*}}}*/
-// MD5Transform - Alters an existing MD5 hash				/*{{{*/
-// ---------------------------------------------------------------------
-/* The core of the MD5 algorithm, this alters an existing MD5 hash to
-   reflect the addition of 16 longwords of new data. Add blocks
-   the data and converts bytes into longwords for this routine. */
-
-// The four core functions - F1 is optimized somewhat
-// #define F1(x, y, z) (x & y | ~x & z)
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
 
-// This is the central step in the MD5 algorithm.
-#define MD5STEP(f,w,x,y,z,in,s) \
-	 (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
 
-static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
-{
-   register uint32_t a, b, c, d;
-   
-   a = buf[0];
-   b = buf[1];
-   c = buf[2];
-   d = buf[3];
-   
-   MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
-   MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
-   MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
-   MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
-   MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
-   MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
-   MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
-   MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
-   MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
-   MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
-   MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
-   MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
-   MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
-   MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
-   MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
-   MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
-   MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
-   MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
-   MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
-   MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
-   MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
-   MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
-   MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
-   MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
-   MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
-   MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
-   MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
-   MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
-   MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
-   MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
-   MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
-   MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-   
-   MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
-   MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
-   MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
-   MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
-   MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
-   MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
-   MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
-   MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
-   MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
-   MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
-   MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
-   MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
-   MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
-   MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
-   MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
-   MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-   
-   MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
-   MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
-   MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
-   MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
-   MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
-   MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
-   MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
-   MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
-   MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
-   MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
-   MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
-   MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
-   MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
-   MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
-   MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
-   MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-   
-   buf[0] += a;
-   buf[1] += b;
-   buf[2] += c;
-   buf[3] += d;
-}
-									/*}}}*/
 // MD5Summation::MD5Summation - Initialize the summer			/*{{{*/
 // ---------------------------------------------------------------------
-/* This assigns the deep magic initial values */
+/* */
 MD5Summation::MD5Summation()
 {
-   uint32_t *buf = (uint32_t *)Buf;
-   uint32_t *bytes = (uint32_t *)Bytes;
-   
-   buf[0] = 0x67452301;
-   buf[1] = 0xefcdab89;
-   buf[2] = 0x98badcfe;
-   buf[3] = 0x10325476;
-   
-   bytes[0] = 0;
-   bytes[1] = 0;
-   Done = false;
+   md5_init(&context);
 }
 									/*}}}*/
 // MD5Summation::Add - 'Add' a data set to the hash			/*{{{*/
@@ -185,94 +27,20 @@ MD5Summation::MD5Summation()
 /* */
 bool MD5Summation::Add(const unsigned char *data,unsigned long long len)
 {
-   if (Done == true)
-      return false;
-
-   uint32_t *buf = (uint32_t *)Buf;
-   uint32_t *bytes = (uint32_t *)Bytes;
-   uint32_t *in = (uint32_t *)In;
-
-   // Update byte count and carry (this could be done with a long long?)
-   uint32_t t = bytes[0];
-   if ((bytes[0] = t + len) < t)
-      bytes[1]++;	
-
-   // Space available (at least 1)
-   t = 64 - (t & 0x3f);	
-   if (t > len) 
-   {
-      memcpy((unsigned char *)in + 64 - t,data,len);
-      return true;
-   }
-
-   // First chunk is an odd size
-   memcpy((unsigned char *)in + 64 - t,data,t);
-   byteSwap(in, 16);
-   MD5Transform(buf,in);
-   data += t;
-   len -= t;
-   
-   // Process data in 64-byte chunks
-   while (len >= 64)
-   {
-      memcpy(in,data,64);
-      byteSwap(in,16);
-      MD5Transform(buf,in);
-      data += 64;
-      len -= 64;
-   }
-
-   // Handle any remaining bytes of data.
-   memcpy(in,data,len);
-
-   return true;   
+   md5_update(&context, len, data);
+   return true;
 }
 									/*}}}*/
 // MD5Summation::Result - Returns the value of the sum			/*{{{*/
 // ---------------------------------------------------------------------
-/* Because this must add in the last bytes of the series it prevents anyone
-   from calling add after. */
+/* Add() may not be called after this */
 MD5SumValue MD5Summation::Result()
 {
-   uint32_t *buf = (uint32_t *)Buf;
-   uint32_t *bytes = (uint32_t *)Bytes;
-   uint32_t *in = (uint32_t *)In;
-   
-   if (Done == false)
-   {
-      // Number of bytes in In
-      int count = bytes[0] & 0x3f;	
-      unsigned char *p = (unsigned char *)in + count;
-      
-      // Set the first char of padding to 0x80.  There is always room.
-      *p++ = 0x80;
-      
-      // Bytes of padding needed to make 56 bytes (-8..55)
-      count = 56 - 1 - count;
-      
-      // Padding forces an extra block 
-      if (count < 0) 
-      {
-	 memset(p,0,count + 8);
-	 byteSwap(in, 16);
-	 MD5Transform(buf,in);
-	 p = (unsigned char *)in;
-	 count = 56;
-      }
-      
-      memset(p, 0, count);
-      byteSwap(in, 14);
-      
-      // Append length in bits and transform
-      in[14] = bytes[0] << 3;
-      in[15] = bytes[1] << 3 | bytes[0] >> 29;
-      MD5Transform(buf,in);   
-      byteSwap(buf,4);
-      Done = true;
-   }
-   
+   uint8_t digest[MD5_DIGEST_SIZE];
    MD5SumValue V;
-   V.Set((unsigned char *)buf);
+
+   md5_digest(&context, MD5_DIGEST_SIZE, digest);
+   V.Set((unsigned char *)digest);
    return V;
 }
 									/*}}}*/
diff --git a/apt-pkg/contrib/md5.h b/apt-pkg/contrib/md5.h
index f4992c2..73ad56e 100644
--- a/apt-pkg/contrib/md5.h
+++ b/apt-pkg/contrib/md5.h
@@ -1,29 +1,20 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: md5.h,v 1.6 2001/05/07 05:06:52 jgg Exp $
+// $Id: md5.h,v 1.7 2015/01/16 09:42:13 lhw Exp $
 /* ######################################################################
-   
+
    MD5SumValue - Storage for a MD5Sum
    MD5Summation - MD5 Message Digest Algorithm.
-   
+
    This is a C++ interface to a set of MD5Sum functions. The class can
    store a MD5Sum in 16 bytes of memory.
-   
-   A MD5Sum is used to generate a (hopefully) unique 16 byte number for a
-   block of data. This can be used to guard against corruption of a file.
-   MD5 should not be used for tamper protection, use SHA or something more
-   secure.
-   
-   There are two classes because computing a MD5 is not a continual 
-   operation unless 64 byte blocks are used. Also the summation requires an
-   extra 18*4 bytes to operate.
-   
+
    ##################################################################### */
 									/*}}}*/
 #ifndef APTPKG_MD5_H
 #define APTPKG_MD5_H
 
-#include <stdint.h>
+#include <nettle/md5.h>
 
 #include "hashsum_template.h"
 
@@ -41,13 +32,9 @@ typedef HashSumValue<128> MD5SumValue;
 
 class MD5Summation : public SummationImplementation
 {
-   uint32_t Buf[4];
-   unsigned char Bytes[2*4];
-   unsigned char In[16*4];
-   bool Done;
+   struct md5_ctx context;
 
    public:
-
    bool Add(const unsigned char *inbuf, unsigned long long inlen);
    using SummationImplementation::Add;
 
diff --git a/apt-pkg/contrib/sha1.cc b/apt-pkg/contrib/sha1.cc
index bf6bc6c..992ef57 100644
--- a/apt-pkg/contrib/sha1.cc
+++ b/apt-pkg/contrib/sha1.cc
@@ -1,272 +1,46 @@
 // -*- mode: cpp; mode: fold -*-
-// Description                                                          /*{{{*/
-// $Id: sha1.cc,v 1.3 2001/05/13 05:15:03 jgg Exp $
+// Description                 /*{{{*/
+// $Id: sha1.cc,v 1.4 2015/01/22 12:38:50 lhw Exp $
 /* ######################################################################
-   
+
    SHA1 - SHA-1 Secure Hash Algorithm.
-   
-   This file is a Public Domain wrapper for the Public Domain SHA1 
-   calculation code that is at it's end.
 
-   The algorithm was originally implemented by 
-   Steve Reid <[email protected]> and later modified by 
-   James H. Brown <[email protected]>.
-   
-   Modifications for APT were done by Alfredo K. Kojima and Jason 
-   Gunthorpe.
-   
-   Still in the public domain.
-   
-   Test Vectors (from FIPS PUB 180-1)
-   "abc"
-   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-   "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-   A million repetitions of "a"
-   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-   
-   ##################################################################### 
+   #####################################################################
  */
 									/*}}} */
-// Include Files                                                        /*{{{*/
+// Include Files              /*{{{*/
 #include <config.h>
 
 #include <apt-pkg/sha1.h>
-
-#include <stdint.h>
-#include <string.h>
-									/*}}}*/
-
-// SHA1Transform - Alters an existing SHA-1 hash			/*{{{*/
-// ---------------------------------------------------------------------
-/* The core of the SHA-1 algorithm. This alters an existing SHA-1 hash to
-   reflect the addition of 16 longwords of new data. Other routines convert
-   incoming stream data into 16 long word chunks for this routine */
-
-#define rol(value,bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#ifndef WORDS_BIGENDIAN
-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-    |(rol(block->l[i],8)&0x00FF00FF))
-#else
-#define blk0(i) block->l[i]
-#endif
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-    ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1),R2,R3,R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-static void SHA1Transform(uint32_t state[5],uint8_t const buffer[64])
-{
-   uint32_t a,b,c,d,e;
-   typedef union
-   {
-      uint8_t c[64];
-      uint32_t l[16];
-   }
-   CHAR64LONG16;
-   CHAR64LONG16 workspace, *block;
-
-   block = &workspace;
-   memcpy(block,buffer,sizeof(workspace));
-
-   /* Copy context->state[] to working vars */
-   a = state[0];
-   b = state[1];
-   c = state[2];
-   d = state[3];
-   e = state[4];
-   
-   /* 4 rounds of 20 operations each. Loop unrolled. */
-   R0(a,b,c,d,e,0);
-   R0(e,a,b,c,d,1);
-   R0(d,e,a,b,c,2);
-   R0(c,d,e,a,b,3);
-   R0(b,c,d,e,a,4);
-   R0(a,b,c,d,e,5);
-   R0(e,a,b,c,d,6);
-   R0(d,e,a,b,c,7);
-   R0(c,d,e,a,b,8);
-   R0(b,c,d,e,a,9);
-   R0(a,b,c,d,e,10);
-   R0(e,a,b,c,d,11);
-   R0(d,e,a,b,c,12);
-   R0(c,d,e,a,b,13);
-   R0(b,c,d,e,a,14);
-   R0(a,b,c,d,e,15);
-   R1(e,a,b,c,d,16);
-   R1(d,e,a,b,c,17);
-   R1(c,d,e,a,b,18);
-   R1(b,c,d,e,a,19);
-   R2(a,b,c,d,e,20);
-   R2(e,a,b,c,d,21);
-   R2(d,e,a,b,c,22);
-   R2(c,d,e,a,b,23);
-   R2(b,c,d,e,a,24);
-   R2(a,b,c,d,e,25);
-   R2(e,a,b,c,d,26);
-   R2(d,e,a,b,c,27);
-   R2(c,d,e,a,b,28);
-   R2(b,c,d,e,a,29);
-   R2(a,b,c,d,e,30);
-   R2(e,a,b,c,d,31);
-   R2(d,e,a,b,c,32);
-   R2(c,d,e,a,b,33);
-   R2(b,c,d,e,a,34);
-   R2(a,b,c,d,e,35);
-   R2(e,a,b,c,d,36);
-   R2(d,e,a,b,c,37);
-   R2(c,d,e,a,b,38);
-   R2(b,c,d,e,a,39);
-   R3(a,b,c,d,e,40);
-   R3(e,a,b,c,d,41);
-   R3(d,e,a,b,c,42);
-   R3(c,d,e,a,b,43);
-   R3(b,c,d,e,a,44);
-   R3(a,b,c,d,e,45);
-   R3(e,a,b,c,d,46);
-   R3(d,e,a,b,c,47);
-   R3(c,d,e,a,b,48);
-   R3(b,c,d,e,a,49);
-   R3(a,b,c,d,e,50);
-   R3(e,a,b,c,d,51);
-   R3(d,e,a,b,c,52);
-   R3(c,d,e,a,b,53);
-   R3(b,c,d,e,a,54);
-   R3(a,b,c,d,e,55);
-   R3(e,a,b,c,d,56);
-   R3(d,e,a,b,c,57);
-   R3(c,d,e,a,b,58);
-   R3(b,c,d,e,a,59);
-   R4(a,b,c,d,e,60);
-   R4(e,a,b,c,d,61);
-   R4(d,e,a,b,c,62);
-   R4(c,d,e,a,b,63);
-   R4(b,c,d,e,a,64);
-   R4(a,b,c,d,e,65);
-   R4(e,a,b,c,d,66);
-   R4(d,e,a,b,c,67);
-   R4(c,d,e,a,b,68);
-   R4(b,c,d,e,a,69);
-   R4(a,b,c,d,e,70);
-   R4(e,a,b,c,d,71);
-   R4(d,e,a,b,c,72);
-   R4(c,d,e,a,b,73);
-   R4(b,c,d,e,a,74);
-   R4(a,b,c,d,e,75);
-   R4(e,a,b,c,d,76);
-   R4(d,e,a,b,c,77);
-   R4(c,d,e,a,b,78);
-   R4(b,c,d,e,a,79);
-   
-   /* Add the working vars back into context.state[] */
-   state[0] += a;
-   state[1] += b;
-   state[2] += c;
-   state[3] += d;
-   state[4] += e;   
-}
 									/*}}}*/
 
-// SHA1Summation::SHA1Summation - Constructor                           /*{{{*/
+// SHA1Summation::SHA1Summation - Constructor               /*{{{*/
 // ---------------------------------------------------------------------
 /* */
 SHA1Summation::SHA1Summation()
 {
-   uint32_t *state = (uint32_t *)State;
-   uint32_t *count = (uint32_t *)Count;
-   
-   /* SHA1 initialization constants */
-   state[0] = 0x67452301;
-   state[1] = 0xEFCDAB89;
-   state[2] = 0x98BADCFE;
-   state[3] = 0x10325476;
-   state[4] = 0xC3D2E1F0;
-   count[0] = 0;
-   count[1] = 0;
-   Done = false;
+  sha1_init(&context);
 }
 									/*}}}*/
-// SHA1Summation::Result - Return checksum value                        /*{{{*/
+// SHA1Summation::Add - Adds content of buffer into the checksum  /*{{{*/
 // ---------------------------------------------------------------------
-/* Add() may not be called after this */
-SHA1SumValue SHA1Summation::Result()
+/* May not be called after Result() is called */
+bool SHA1Summation::Add(const unsigned char *data,unsigned long long len)
 {
-   uint32_t *state = (uint32_t *)State;
-   uint32_t *count = (uint32_t *)Count;
-   
-   // Apply the padding
-   if (Done == false)
-   {
-      unsigned char finalcount[8];
-
-      for (unsigned i = 0; i < 8; i++)
-      {
-	 // Endian independent
-	 finalcount[i] = (unsigned char) ((count[(i >= 4 ? 0 : 1)]
-					   >> ((3 - (i & 3)) * 8)) & 255);	
-      }
-      
-      Add((unsigned char *) "\200",1);
-      while ((count[0] & 504) != 448)
-	 Add((unsigned char *) "\0",1);
-      
-      Add(finalcount,8);	/* Should cause a SHA1Transform() */
-      
-   }
-
-   Done = true;
-
-   // Transfer over the result
-   SHA1SumValue Value;
-   unsigned char res[20];
-   for (unsigned i = 0; i < 20; i++)
-   {
-      res[i] = (unsigned char)
-	 ((state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
-   }
-   Value.Set(res);
-   return Value;
+  sha1_update(&context, len, data);
+  return true;
 }
 									/*}}}*/
-// SHA1Summation::Add - Adds content of buffer into the checksum        /*{{{*/
+// SHA1Summation::Result - Return checksum value            /*{{{*/
 // ---------------------------------------------------------------------
-/* May not be called after Result() is called */
-bool SHA1Summation::Add(const unsigned char *data,unsigned long long len)
+/* Add() may not be called after this */
+SHA1SumValue SHA1Summation::Result()
 {
-   if (Done)
-      return false;
-
-   uint32_t *state = (uint32_t *)State;
-   uint32_t *count = (uint32_t *)Count;
-   uint8_t *buffer = (uint8_t *)Buffer;
-   uint32_t i,j;
+  uint8_t digest[SHA1_DIGEST_SIZE];
+  SHA1SumValue V;
 
-   j = (count[0] >> 3) & 63;
-   if ((count[0] += len << 3) < (len << 3))
-      count[1]++;
-   count[1] += (len >> 29);
-   if ((j + len) > 63)
-   {
-      memcpy(&buffer[j],data,(i = 64 - j));
-      SHA1Transform(state,buffer);
-      for (; i + 63 < len; i += 64)
-      {
-	 SHA1Transform(state,&data[i]);
-      }
-      j = 0;
-   }
-   else
-      i = 0;
-   memcpy(&buffer[j],&data[i],len - i);
-   
-   return true;
+  sha1_digest(&context, SHA1_DIGEST_SIZE, digest);
+  V.Set((unsigned char *)digest);
+  return V;
 }
 									/*}}}*/
diff --git a/apt-pkg/contrib/sha1.h b/apt-pkg/contrib/sha1.h
index 5770c31..bd80d69 100644
--- a/apt-pkg/contrib/sha1.h
+++ b/apt-pkg/contrib/sha1.h
@@ -1,19 +1,21 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: sha1.h,v 1.3 2001/05/07 05:05:47 jgg Exp $
+// $Id: sha1.h,v 1.4 2015/01/30 10:38:33 lhw Exp $
 /* ######################################################################
 
    SHA1SumValue - Storage for a SHA-1 hash.
    SHA1Summation - SHA-1 Secure Hash Algorithm.
-   
+
    This is a C++ interface to a set of SHA1Sum functions, that mirrors
-   the equivalent MD5 classes. 
+   the equivalent MD5 classes.
 
    ##################################################################### */
 									/*}}}*/
 #ifndef APTPKG_SHA1_H
 #define APTPKG_SHA1_H
 
+#include <nettle/sha1.h>
+
 #include "hashsum_template.h"
 
 #ifndef APT_10_CLEANER_HEADERS
@@ -30,18 +32,14 @@ typedef  HashSumValue<160> SHA1SumValue;
 
 class SHA1Summation : public SummationImplementation
 {
-   /* assumes 64-bit alignment just in case */
-   unsigned char Buffer[64] __attribute__((aligned(8)));
-   unsigned char State[5*4] __attribute__((aligned(8)));
-   unsigned char Count[2*4] __attribute__((aligned(8)));
-   bool Done;
-   
+   struct sha1_ctx context;
+
    public:
    bool Add(const unsigned char *inbuf, unsigned long long inlen);
    using SummationImplementation::Add;
 
    SHA1SumValue Result();
-   
+
    SHA1Summation();
 };
 
diff --git a/apt-pkg/contrib/sha2.cc b/apt-pkg/contrib/sha2.cc
new file mode 100644
index 0000000..0af0123
--- /dev/null
+++ b/apt-pkg/contrib/sha2.cc
@@ -0,0 +1,76 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                 /*{{{*/
+// $Id: sha1.cc,v 1.4 2015/01/22 12:38:50 lhw Exp $
+/* ######################################################################
+
+   SHA2 - SHA-256 and SHA-512 Secure Hash Algorithm.
+
+   #####################################################################
+ */
+									/*}}} */
+// Include Files              /*{{{*/
+#include <config.h>
+
+#include <apt-pkg/sha2.h>
+									/*}}}*/
+
+// SHA256Summation::SHA256Summation - Constructor               /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+SHA256Summation::SHA256Summation()
+{
+  sha256_init(&context);
+}
+									/*}}}*/
+// SHA256Summation::Add - Adds content of buffer into the checksum  /*{{{*/
+// ---------------------------------------------------------------------
+/* May not be called after Result() is called */
+bool SHA256Summation::Add(const unsigned char *data,unsigned long long len)
+{
+  sha256_update(&context, len, data);
+  return true;
+}
+									/*}}}*/
+// SHA256Summation::Result - Return checksum value            /*{{{*/
+// ---------------------------------------------------------------------
+/* Add() may not be called after this */
+SHA256SumValue SHA256Summation::Result()
+{
+  uint8_t digest[SHA256_DIGEST_SIZE];
+  SHA256SumValue V;
+
+  sha256_digest(&context, SHA256_DIGEST_SIZE, digest);
+  V.Set((unsigned char *)digest);
+  return V;
+}
+									/*}}}*/
+// SHA512Summation::SHA512Summation - Constructor               /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+SHA512Summation::SHA512Summation()
+{
+  sha512_init(&context);
+}
+									/*}}}*/
+// SHA512Summation::Add - Adds content of buffer into the checksum  /*{{{*/
+// ---------------------------------------------------------------------
+/* May not be called after Result() is called */
+bool SHA512Summation::Add(const unsigned char *data,unsigned long long len)
+{
+  sha512_update(&context, len, data);
+  return true;
+}
+									/*}}}*/
+// SHA512Summation::Result - Return checksum value            /*{{{*/
+// ---------------------------------------------------------------------
+/* Add() may not be called after this */
+SHA512SumValue SHA512Summation::Result()
+{
+  uint8_t digest[SHA512_DIGEST_SIZE];
+  SHA512SumValue V;
+
+  sha512_digest(&context, SHA512_DIGEST_SIZE, digest);
+  V.Set((unsigned char *)digest);
+  return V;
+}
+									/*}}}*/
diff --git a/apt-pkg/contrib/sha2.h b/apt-pkg/contrib/sha2.h
index a25ad4d..f30710d 100644
--- a/apt-pkg/contrib/sha2.h
+++ b/apt-pkg/contrib/sha2.h
@@ -1,22 +1,21 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                          /*{{{*/
-// $Id: sha512.h,v 1.3 2001/05/07 05:05:47 jgg Exp $
+// $Id: sha512.h,v 1.4 2015/01/22 13:00:49 lhw Exp $
 /* ######################################################################
 
    SHA{512,256}SumValue - Storage for a SHA-{512,256} hash.
    SHA{512,256}Summation - SHA-{512,256} Secure Hash Algorithm.
-   
+
    This is a C++ interface to a set of SHA{512,256}Sum functions, that mirrors
-   the equivalent MD5 & SHA1 classes. 
+   the equivalent MD5 & SHA1 classes.
 
    ##################################################################### */
                                                                         /*}}}*/
 #ifndef APTPKG_SHA2_H
 #define APTPKG_SHA2_H
 
-#include <cstring>
+#include <nettle/sha2.h>
 
-#include "sha2_internal.h"
 #include "hashsum_template.h"
 
 #ifndef APT_10_CLEANER_HEADERS
@@ -24,6 +23,10 @@
 #include <algorithm>
 #include <stdint.h>
 #endif
+#ifndef APT_8_CLEANER_HEADERS
+using std::string;
+using std::min;
+#endif
 
 
 typedef HashSumValue<512> SHA512SumValue;
@@ -31,78 +34,30 @@ typedef HashSumValue<256> SHA256SumValue;
 
 class SHA2SummationBase : public SummationImplementation
 {
- protected:
-   bool Done;
  public:
    bool Add(const unsigned char *inbuf, unsigned long long len) = 0;
-
+   using SummationImplementation::Add;
    void Result();
 };
 
 class SHA256Summation : public SHA2SummationBase
 {
-   SHA256_CTX ctx;
-   unsigned char Sum[32];
-
-   public:
-   bool Add(const unsigned char *inbuf, unsigned long long len)
-   {
-      if (Done) 
-         return false;
-      SHA256_Update(&ctx, inbuf, len);
-      return true;
-   };
+   struct sha256_ctx context;
+ public:
+   bool Add(const unsigned char *inbuf, unsigned long long len);
    using SummationImplementation::Add;
-
-   SHA256SumValue Result()
-   {
-      if (!Done) {
-         SHA256_Final(Sum, &ctx);
-         Done = true;
-      }
-      SHA256SumValue res;
-      res.Set(Sum);
-      return res;
-   };
-   SHA256Summation()
-   {
-      SHA256_Init(&ctx);
-      Done = false;
-      memset(&Sum, 0, sizeof(Sum));
-   };
+   SHA256SumValue Result();
+   SHA256Summation();
 };
 
 class SHA512Summation : public SHA2SummationBase
 {
-   SHA512_CTX ctx;
-   unsigned char Sum[64];
-
-   public:
-   bool Add(const unsigned char *inbuf, unsigned long long len)
-   {
-      if (Done) 
-         return false;
-      SHA512_Update(&ctx, inbuf, len);
-      return true;
-   };
+   struct sha512_ctx context;
+ public:
+   bool Add(const unsigned char *inbuf, unsigned long long len);
    using SummationImplementation::Add;
-
-   SHA512SumValue Result()
-   {
-      if (!Done) {
-         SHA512_Final(Sum, &ctx);
-         Done = true;
-      }
-      SHA512SumValue res;
-      res.Set(Sum);
-      return res;
-   };
-   SHA512Summation()
-   {
-      SHA512_Init(&ctx);
-      Done = false;
-      memset(&Sum, 0, sizeof(Sum));
-   };
+   SHA512SumValue Result();
+   SHA512Summation();
 };
 
 
diff --git a/apt-pkg/contrib/sha256.h b/apt-pkg/contrib/sha256.h
deleted file mode 100644
index 15146c9..0000000
--- a/apt-pkg/contrib/sha256.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef APTPKG_SHA256_H
-#define APTPKG_SHA256_H
-
-#include "sha2.h"
-
-#warning "This header is deprecated, please include sha2.h instead"
-
-#endif
diff --git a/apt-pkg/contrib/sha2_internal.cc b/apt-pkg/contrib/sha2_internal.cc
deleted file mode 100644
index 131ff5b..0000000
--- a/apt-pkg/contrib/sha2_internal.cc
+++ /dev/null
@@ -1,1081 +0,0 @@
-/*
- * FILE:	sha2.c
- * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
- * 
- * Copyright (c) 2000-2001, Aaron D. Gifford
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
- */
-#include <config.h>
-
-#include <endian.h>
-#include <string.h>	/* memcpy()/memset() or bcopy()/bzero() */
-#include <assert.h>	/* assert() */
-#include "sha2_internal.h"
-
-/*
- * ASSERT NOTE:
- * Some sanity checking code is included using assert().  On my FreeBSD
- * system, this additional code can be removed by compiling with NDEBUG
- * defined.  Check your own systems manpage on assert() to see how to
- * compile WITHOUT the sanity checking code on your system.
- *
- * UNROLLED TRANSFORM LOOP NOTE:
- * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
- * loop version for the hash transform rounds (defined using macros
- * later in this file).  Either define on the command line, for example:
- *
- *   cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
- *
- * or define below:
- *
- *   #define SHA2_UNROLL_TRANSFORM
- *
- */
-
-
-/*** SHA-256/384/512 Machine Architecture Definitions *****************/
-/*
- * BYTE_ORDER NOTE:
- *
- * Please make sure that your system defines BYTE_ORDER.  If your
- * architecture is little-endian, make sure it also defines
- * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
- * equivalent.
- *
- * If your system does not define the above, then you can do so by
- * hand like this:
- *
- *   #define LITTLE_ENDIAN 1234
- *   #define BIG_ENDIAN    4321
- *
- * And for little-endian machines, add:
- *
- *   #define BYTE_ORDER LITTLE_ENDIAN 
- *
- * Or for big-endian machines:
- *
- *   #define BYTE_ORDER BIG_ENDIAN
- *
- * The FreeBSD machine this was written on defines BYTE_ORDER
- * appropriately by including <sys/types.h> (which in turn includes
- * <machine/endian.h> where the appropriate definitions are actually
- * made).
- */
-#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
-#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
-#endif
-
-/*
- * Define the followingsha2_* types to types of the correct length on
- * the native archtecture.   Most BSD systems and Linux define u_intXX_t
- * types.  Machines with very recent ANSI C headers, can use the
- * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
- * during compile or in the sha.h header file.
- *
- * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
- * will need to define these three typedefs below (and the appropriate
- * ones in sha.h too) by hand according to their system architecture.
- *
- * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
- * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
- */
-#ifdef SHA2_USE_INTTYPES_H
-
-typedef uint8_t  sha2_byte;	/* Exactly 1 byte */
-typedef uint32_t sha2_word32;	/* Exactly 4 bytes */
-typedef uint64_t sha2_word64;	/* Exactly 8 bytes */
-
-#else /* SHA2_USE_INTTYPES_H */
-
-typedef u_int8_t  sha2_byte;	/* Exactly 1 byte */
-typedef u_int32_t sha2_word32;	/* Exactly 4 bytes */
-typedef u_int64_t sha2_word64;	/* Exactly 8 bytes */
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-
-/*** SHA-256/384/512 Various Length Definitions ***********************/
-/* NOTE: Most of these are in sha2.h */
-#define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
-#define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
-#define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
-
-
-/*** ENDIAN REVERSAL MACROS *******************************************/
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define REVERSE32(w,x)	{ \
-	sha2_word32 tmp = (w); \
-	tmp = (tmp >> 16) | (tmp << 16); \
-	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
-}
-#define REVERSE64(w,x)	{ \
-	sha2_word64 tmp = (w); \
-	tmp = (tmp >> 32) | (tmp << 32); \
-	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
-	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
-	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
-	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
-}
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-/*
- * Macro for incrementally adding the unsigned 64-bit integer n to the
- * unsigned 128-bit integer (represented using a two-element array of
- * 64-bit words):
- */
-#define ADDINC128(w,n)	{ \
-	(w)[0] += (sha2_word64)(n); \
-	if ((w)[0] < (n)) { \
-		(w)[1]++; \
-	} \
-}
-
-/*
- * Macros for copying blocks of memory and for zeroing out ranges
- * of memory.  Using these macros makes it easy to switch from
- * using memset()/memcpy() and using bzero()/bcopy().
- *
- * Please define either SHA2_USE_MEMSET_MEMCPY or define
- * SHA2_USE_BZERO_BCOPY depending on which function set you
- * choose to use:
- */
-#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
-/* Default to memset()/memcpy() if no option is specified */
-#define	SHA2_USE_MEMSET_MEMCPY	1
-#endif
-#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
-/* Abort with an error if BOTH options are defined */
-#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
-#endif
-
-#ifdef SHA2_USE_MEMSET_MEMCPY
-#define MEMSET_BZERO(p,l)	memset((p), 0, (l))
-#define MEMCPY_BCOPY(d,s,l)	memcpy((d), (s), (l))
-#endif
-#ifdef SHA2_USE_BZERO_BCOPY
-#define MEMSET_BZERO(p,l)	bzero((p), (l))
-#define MEMCPY_BCOPY(d,s,l)	bcopy((s), (d), (l))
-#endif
-
-
-/*** THE SIX LOGICAL FUNCTIONS ****************************************/
-/*
- * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
- *
- *   NOTE:  The naming of R and S appears backwards here (R is a SHIFT and
- *   S is a ROTATION) because the SHA-256/384/512 description document
- *   (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
- *   same "backwards" definition.
- */
-/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
-#define R(b,x) 		((x) >> (b))
-/* 32-bit Rotate-right (used in SHA-256): */
-#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
-/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
-#define S64(b,x)	(((x) >> (b)) | ((x) << (64 - (b))))
-
-/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
-#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
-#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
-
-/* Four of six logical functions used in SHA-256: */
-#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
-#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
-#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
-#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
-
-/* Four of six logical functions used in SHA-384 and SHA-512: */
-#define Sigma0_512(x)	(S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
-#define Sigma1_512(x)	(S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
-#define sigma0_512(x)	(S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7,   (x)))
-#define sigma1_512(x)	(S64(19, (x)) ^ S64(61, (x)) ^ R( 6,   (x)))
-
-/*** INTERNAL FUNCTION PROTOTYPES *************************************/
-/* NOTE: These should not be accessed directly from outside this
- * library -- they are intended for private internal visibility/use
- * only.
- */
-static void SHA512_Last(SHA512_CTX*);
-static void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
-static void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
-
-
-/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
-/* Hash constant words K for SHA-256: */
-const static sha2_word32 K256[64] = {
-	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
-	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
-	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
-	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
-	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
-	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
-	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
-	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
-	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
-	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
-	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
-	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
-	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
-	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
-	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
-	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
-};
-
-/* Initial hash value H for SHA-256: */
-const static sha2_word32 sha256_initial_hash_value[8] = {
-	0x6a09e667UL,
-	0xbb67ae85UL,
-	0x3c6ef372UL,
-	0xa54ff53aUL,
-	0x510e527fUL,
-	0x9b05688cUL,
-	0x1f83d9abUL,
-	0x5be0cd19UL
-};
-
-/* Hash constant words K for SHA-384 and SHA-512: */
-const static sha2_word64 K512[80] = {
-	0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
-	0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
-	0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
-	0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
-	0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
-	0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
-	0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
-	0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
-	0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
-	0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
-	0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
-	0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
-	0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
-	0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
-	0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
-	0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
-	0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
-	0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
-	0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
-	0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
-	0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
-	0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
-	0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
-	0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
-	0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
-	0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
-	0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
-	0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
-	0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
-	0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
-	0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
-	0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
-	0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
-	0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
-	0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
-	0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
-	0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
-	0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
-	0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
-	0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
-};
-
-/* Initial hash value H for SHA-384 */
-const static sha2_word64 sha384_initial_hash_value[8] = {
-	0xcbbb9d5dc1059ed8ULL,
-	0x629a292a367cd507ULL,
-	0x9159015a3070dd17ULL,
-	0x152fecd8f70e5939ULL,
-	0x67332667ffc00b31ULL,
-	0x8eb44a8768581511ULL,
-	0xdb0c2e0d64f98fa7ULL,
-	0x47b5481dbefa4fa4ULL
-};
-
-/* Initial hash value H for SHA-512 */
-const static sha2_word64 sha512_initial_hash_value[8] = {
-	0x6a09e667f3bcc908ULL,
-	0xbb67ae8584caa73bULL,
-	0x3c6ef372fe94f82bULL,
-	0xa54ff53a5f1d36f1ULL,
-	0x510e527fade682d1ULL,
-	0x9b05688c2b3e6c1fULL,
-	0x1f83d9abfb41bd6bULL,
-	0x5be0cd19137e2179ULL
-};
-
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char *sha2_hex_digits = "0123456789abcdef";
-
-
-/*** SHA-256: *********************************************************/
-void SHA256_Init(SHA256_CTX* context) {
-	if (context == (SHA256_CTX*)0) {
-		return;
-	}
-	MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
-	MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH);
-	context->bitcount = 0;
-}
-
-#ifdef SHA2_UNROLL_TRANSFORM
-
-/* Unrolled SHA-256 round macros: */
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
-	REVERSE32(*data++, W256[j]); \
-	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
-             K256[j] + W256[j]; \
-	(d) += T1; \
-	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
-	j++
-
-
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h)	\
-	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
-	     K256[j] + (W256[j] = *data++); \
-	(d) += T1; \
-	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
-	j++
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND256(a,b,c,d,e,f,g,h)	\
-	s0 = W256[(j+1)&0x0f]; \
-	s0 = sigma0_256(s0); \
-	s1 = W256[(j+14)&0x0f]; \
-	s1 = sigma1_256(s1); \
-	T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
-	     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
-	(d) += T1; \
-	(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
-	j++
-
-static void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
-	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
-	sha2_word32	T1, *W256;
-	int		j;
-
-	W256 = (sha2_word32*)context->buffer;
-
-	/* Initialize registers with the prev. intermediate value */
-	a = context->state[0];
-	b = context->state[1];
-	c = context->state[2];
-	d = context->state[3];
-	e = context->state[4];
-	f = context->state[5];
-	g = context->state[6];
-	h = context->state[7];
-
-	j = 0;
-	do {
-		/* Rounds 0 to 15 (unrolled): */
-		ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
-		ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
-		ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
-		ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
-		ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
-		ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
-		ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
-		ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
-	} while (j < 16);
-
-	/* Now for the remaining rounds to 64: */
-	do {
-		ROUND256(a,b,c,d,e,f,g,h);
-		ROUND256(h,a,b,c,d,e,f,g);
-		ROUND256(g,h,a,b,c,d,e,f);
-		ROUND256(f,g,h,a,b,c,d,e);
-		ROUND256(e,f,g,h,a,b,c,d);
-		ROUND256(d,e,f,g,h,a,b,c);
-		ROUND256(c,d,e,f,g,h,a,b);
-		ROUND256(b,c,d,e,f,g,h,a);
-	} while (j < 64);
-
-	/* Compute the current intermediate hash value */
-	context->state[0] += a;
-	context->state[1] += b;
-	context->state[2] += c;
-	context->state[3] += d;
-	context->state[4] += e;
-	context->state[5] += f;
-	context->state[6] += g;
-	context->state[7] += h;
-
-	/* Clean up */
-	a = b = c = d = e = f = g = h = T1 = 0;
-}
-
-#else /* SHA2_UNROLL_TRANSFORM */
-
-static void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
-	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
-	sha2_word32	T1, T2, *W256;
-	int		j;
-
-	W256 = (sha2_word32*)context->buffer;
-
-	/* Initialize registers with the prev. intermediate value */
-	a = context->state[0];
-	b = context->state[1];
-	c = context->state[2];
-	d = context->state[3];
-	e = context->state[4];
-	f = context->state[5];
-	g = context->state[6];
-	h = context->state[7];
-
-	j = 0;
-	do {
-#if BYTE_ORDER == LITTLE_ENDIAN
-		/* Copy data while converting to host byte order */
-		REVERSE32(*data++,W256[j]);
-		/* Apply the SHA-256 compression function to update a..h */
-		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-		/* Apply the SHA-256 compression function to update a..h with copy */
-		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-		T2 = Sigma0_256(a) + Maj(a, b, c);
-		h = g;
-		g = f;
-		f = e;
-		e = d + T1;
-		d = c;
-		c = b;
-		b = a;
-		a = T1 + T2;
-
-		j++;
-	} while (j < 16);
-
-	do {
-		/* Part of the message block expansion: */
-		s0 = W256[(j+1)&0x0f];
-		s0 = sigma0_256(s0);
-		s1 = W256[(j+14)&0x0f];	
-		s1 = sigma1_256(s1);
-
-		/* Apply the SHA-256 compression function to update a..h */
-		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
-		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
-		T2 = Sigma0_256(a) + Maj(a, b, c);
-		h = g;
-		g = f;
-		f = e;
-		e = d + T1;
-		d = c;
-		c = b;
-		b = a;
-		a = T1 + T2;
-
-		j++;
-	} while (j < 64);
-
-	/* Compute the current intermediate hash value */
-	context->state[0] += a;
-	context->state[1] += b;
-	context->state[2] += c;
-	context->state[3] += d;
-	context->state[4] += e;
-	context->state[5] += f;
-	context->state[6] += g;
-	context->state[7] += h;
-
-	/* Clean up */
-	a = b = c = d = e = f = g = h = T1 = T2 = 0;
-}
-
-#endif /* SHA2_UNROLL_TRANSFORM */
-
-void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
-	unsigned int	freespace, usedspace;
-
-	if (len == 0) {
-		/* Calling with no data is valid - we do nothing */
-		return;
-	}
-
-	/* Sanity check: */
-	assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
-
-	usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
-	if (usedspace > 0) {
-		/* Calculate how much free space is available in the buffer */
-		freespace = SHA256_BLOCK_LENGTH - usedspace;
-
-		if (len >= freespace) {
-			/* Fill the buffer completely and process it */
-			MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
-			context->bitcount += freespace << 3;
-			len -= freespace;
-			data += freespace;
-			SHA256_Transform(context, (sha2_word32*)context->buffer);
-		} else {
-			/* The buffer is not yet full */
-			MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
-			context->bitcount += len << 3;
-			/* Clean up: */
-			usedspace = freespace = 0;
-			return;
-		}
-	}
-	while (len >= SHA256_BLOCK_LENGTH) {
-		/* Process as many complete blocks as we can */
-		sha2_byte buffer[SHA256_BLOCK_LENGTH];
-		MEMCPY_BCOPY(buffer, data, SHA256_BLOCK_LENGTH);
-		SHA256_Transform(context, (sha2_word32*)buffer);
-		context->bitcount += SHA256_BLOCK_LENGTH << 3;
-		len -= SHA256_BLOCK_LENGTH;
-		data += SHA256_BLOCK_LENGTH;
-	}
-	if (len > 0) {
-		/* There's left-overs, so save 'em */
-		MEMCPY_BCOPY(context->buffer, data, len);
-		context->bitcount += len << 3;
-	}
-	/* Clean up: */
-	usedspace = freespace = 0;
-}
-
-void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
-	sha2_word32	*d = (sha2_word32*)digest;
-	unsigned int	usedspace;
-
-	/* Sanity check: */
-	assert(context != (SHA256_CTX*)0);
-
-	/* If no digest buffer is passed, we don't bother doing this: */
-	if (digest != (sha2_byte*)0) {
-		usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
-#if BYTE_ORDER == LITTLE_ENDIAN
-		/* Convert FROM host byte order */
-		REVERSE64(context->bitcount,context->bitcount);
-#endif
-		if (usedspace > 0) {
-			/* Begin padding with a 1 bit: */
-			context->buffer[usedspace++] = 0x80;
-
-			if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
-				/* Set-up for the last transform: */
-				MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
-			} else {
-				if (usedspace < SHA256_BLOCK_LENGTH) {
-					MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
-				}
-				/* Do second-to-last transform: */
-				SHA256_Transform(context, (sha2_word32*)context->buffer);
-
-				/* And set-up for the last transform: */
-				MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
-			}
-		} else {
-			/* Set-up for the last transform: */
-			MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
-
-			/* Begin padding with a 1 bit: */
-			*context->buffer = 0x80;
-		}
-		/* Set the bit count: */
-		union {
-			sha2_byte* c;
-			sha2_word64* l;
-		} bitcount;
-		bitcount.c = &context->buffer[SHA256_SHORT_BLOCK_LENGTH];
-		*(bitcount.l) = context->bitcount;
-
-		/* Final transform: */
-		SHA256_Transform(context, (sha2_word32*)context->buffer);
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-		{
-			/* Convert TO host byte order */
-			int	j;
-			for (j = 0; j < 8; j++) {
-				REVERSE32(context->state[j],context->state[j]);
-				*d++ = context->state[j];
-			}
-		}
-#else
-		MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
-#endif
-	}
-
-	/* Clean up state data: */
-	MEMSET_BZERO(context, sizeof(*context));
-	usedspace = 0;
-}
-
-char *SHA256_End(SHA256_CTX* context, char buffer[]) {
-	sha2_byte	digest[SHA256_DIGEST_LENGTH], *d = digest;
-	int		i;
-
-	/* Sanity check: */
-	assert(context != (SHA256_CTX*)0);
-
-	if (buffer != (char*)0) {
-		SHA256_Final(digest, context);
-
-		for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
-			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-			*buffer++ = sha2_hex_digits[*d & 0x0f];
-			d++;
-		}
-		*buffer = (char)0;
-	} else {
-		MEMSET_BZERO(context, sizeof(*context));
-	}
-	MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
-	return buffer;
-}
-
-char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
-	SHA256_CTX	context;
-
-	SHA256_Init(&context);
-	SHA256_Update(&context, data, len);
-	return SHA256_End(&context, digest);
-}
-
-
-/*** SHA-512: *********************************************************/
-void SHA512_Init(SHA512_CTX* context) {
-	if (context == (SHA512_CTX*)0) {
-		return;
-	}
-	MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
-	MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH);
-	context->bitcount[0] = context->bitcount[1] =  0;
-}
-
-#ifdef SHA2_UNROLL_TRANSFORM
-
-/* Unrolled SHA-512 round macros: */
-#if BYTE_ORDER == LITTLE_ENDIAN
-
-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
-	REVERSE64(*data++, W512[j]); \
-	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
-             K512[j] + W512[j]; \
-	(d) += T1, \
-	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
-	j++
-
-
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h)	\
-	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
-             K512[j] + (W512[j] = *data++); \
-	(d) += T1; \
-	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
-	j++
-
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-
-#define ROUND512(a,b,c,d,e,f,g,h)	\
-	s0 = W512[(j+1)&0x0f]; \
-	s0 = sigma0_512(s0); \
-	s1 = W512[(j+14)&0x0f]; \
-	s1 = sigma1_512(s1); \
-	T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
-             (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
-	(d) += T1; \
-	(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
-	j++
-
-static void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
-	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
-	sha2_word64	T1, *W512 = (sha2_word64*)context->buffer;
-	int		j;
-
-	/* Initialize registers with the prev. intermediate value */
-	a = context->state[0];
-	b = context->state[1];
-	c = context->state[2];
-	d = context->state[3];
-	e = context->state[4];
-	f = context->state[5];
-	g = context->state[6];
-	h = context->state[7];
-
-	j = 0;
-	do {
-		ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
-		ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
-		ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
-		ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
-		ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
-		ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
-		ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
-		ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
-	} while (j < 16);
-
-	/* Now for the remaining rounds up to 79: */
-	do {
-		ROUND512(a,b,c,d,e,f,g,h);
-		ROUND512(h,a,b,c,d,e,f,g);
-		ROUND512(g,h,a,b,c,d,e,f);
-		ROUND512(f,g,h,a,b,c,d,e);
-		ROUND512(e,f,g,h,a,b,c,d);
-		ROUND512(d,e,f,g,h,a,b,c);
-		ROUND512(c,d,e,f,g,h,a,b);
-		ROUND512(b,c,d,e,f,g,h,a);
-	} while (j < 80);
-
-	/* Compute the current intermediate hash value */
-	context->state[0] += a;
-	context->state[1] += b;
-	context->state[2] += c;
-	context->state[3] += d;
-	context->state[4] += e;
-	context->state[5] += f;
-	context->state[6] += g;
-	context->state[7] += h;
-
-	/* Clean up */
-	a = b = c = d = e = f = g = h = T1 = 0;
-}
-
-#else /* SHA2_UNROLL_TRANSFORM */
-
-static void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
-	sha2_word64	a, b, c, d, e, f, g, h, s0, s1;
-	sha2_word64	T1, T2, *W512 = (sha2_word64*)context->buffer;
-	int		j;
-
-	/* Initialize registers with the prev. intermediate value */
-	a = context->state[0];
-	b = context->state[1];
-	c = context->state[2];
-	d = context->state[3];
-	e = context->state[4];
-	f = context->state[5];
-	g = context->state[6];
-	h = context->state[7];
-
-	j = 0;
-	do {
-#if BYTE_ORDER == LITTLE_ENDIAN
-		/* Convert TO host byte order */
-		REVERSE64(*data++, W512[j]);
-		/* Apply the SHA-512 compression function to update a..h */
-		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-		/* Apply the SHA-512 compression function to update a..h with copy */
-		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
-#endif /* BYTE_ORDER == LITTLE_ENDIAN */
-		T2 = Sigma0_512(a) + Maj(a, b, c);
-		h = g;
-		g = f;
-		f = e;
-		e = d + T1;
-		d = c;
-		c = b;
-		b = a;
-		a = T1 + T2;
-
-		j++;
-	} while (j < 16);
-
-	do {
-		/* Part of the message block expansion: */
-		s0 = W512[(j+1)&0x0f];
-		s0 = sigma0_512(s0);
-		s1 = W512[(j+14)&0x0f];
-		s1 =  sigma1_512(s1);
-
-		/* Apply the SHA-512 compression function to update a..h */
-		T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
-		     (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
-		T2 = Sigma0_512(a) + Maj(a, b, c);
-		h = g;
-		g = f;
-		f = e;
-		e = d + T1;
-		d = c;
-		c = b;
-		b = a;
-		a = T1 + T2;
-
-		j++;
-	} while (j < 80);
-
-	/* Compute the current intermediate hash value */
-	context->state[0] += a;
-	context->state[1] += b;
-	context->state[2] += c;
-	context->state[3] += d;
-	context->state[4] += e;
-	context->state[5] += f;
-	context->state[6] += g;
-	context->state[7] += h;
-
-	/* Clean up */
-	a = b = c = d = e = f = g = h = T1 = T2 = 0;
-}
-
-#endif /* SHA2_UNROLL_TRANSFORM */
-
-void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
-	unsigned int	freespace, usedspace;
-
-	if (len == 0) {
-		/* Calling with no data is valid - we do nothing */
-		return;
-	}
-
-	/* Sanity check: */
-	assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
-
-	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
-	if (usedspace > 0) {
-		/* Calculate how much free space is available in the buffer */
-		freespace = SHA512_BLOCK_LENGTH - usedspace;
-
-		if (len >= freespace) {
-			/* Fill the buffer completely and process it */
-			MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
-			ADDINC128(context->bitcount, freespace << 3);
-			len -= freespace;
-			data += freespace;
-			SHA512_Transform(context, (sha2_word64*)context->buffer);
-		} else {
-			/* The buffer is not yet full */
-			MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
-			ADDINC128(context->bitcount, len << 3);
-			/* Clean up: */
-			usedspace = freespace = 0;
-			return;
-		}
-	}
-	while (len >= SHA512_BLOCK_LENGTH) {
-		/* Process as many complete blocks as we can */
-		sha2_byte buffer[SHA512_BLOCK_LENGTH];
-		MEMCPY_BCOPY(buffer, data, SHA512_BLOCK_LENGTH);
-		SHA512_Transform(context, (sha2_word64*)buffer);
-		ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
-		len -= SHA512_BLOCK_LENGTH;
-		data += SHA512_BLOCK_LENGTH;
-	}
-	if (len > 0) {
-		/* There's left-overs, so save 'em */
-		MEMCPY_BCOPY(context->buffer, data, len);
-		ADDINC128(context->bitcount, len << 3);
-	}
-	/* Clean up: */
-	usedspace = freespace = 0;
-}
-
-static void SHA512_Last(SHA512_CTX* context) {
-	unsigned int	usedspace;
-
-	usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
-#if BYTE_ORDER == LITTLE_ENDIAN
-	/* Convert FROM host byte order */
-	REVERSE64(context->bitcount[0],context->bitcount[0]);
-	REVERSE64(context->bitcount[1],context->bitcount[1]);
-#endif
-	if (usedspace > 0) {
-		/* Begin padding with a 1 bit: */
-		context->buffer[usedspace++] = 0x80;
-
-		if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
-			/* Set-up for the last transform: */
-			MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
-		} else {
-			if (usedspace < SHA512_BLOCK_LENGTH) {
-				MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
-			}
-			/* Do second-to-last transform: */
-			SHA512_Transform(context, (sha2_word64*)context->buffer);
-
-			/* And set-up for the last transform: */
-			MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
-		}
-	} else {
-		/* Prepare for final transform: */
-		MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
-
-		/* Begin padding with a 1 bit: */
-		*context->buffer = 0x80;
-	}
-	/* Store the length of input data (in bits): */
-	union {
-		sha2_byte* c;
-		sha2_word64* l;
-	} bitcount;
-	bitcount.c = &context->buffer[SHA512_SHORT_BLOCK_LENGTH];
-	bitcount.l[0] = context->bitcount[1];
-	bitcount.l[1] = context->bitcount[0];
-
-	/* Final transform: */
-	SHA512_Transform(context, (sha2_word64*)context->buffer);
-}
-
-void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
-	sha2_word64	*d = (sha2_word64*)digest;
-
-	/* Sanity check: */
-	assert(context != (SHA512_CTX*)0);
-
-	/* If no digest buffer is passed, we don't bother doing this: */
-	if (digest != (sha2_byte*)0) {
-		SHA512_Last(context);
-
-		/* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
-		{
-			/* Convert TO host byte order */
-			int	j;
-			for (j = 0; j < 8; j++) {
-				REVERSE64(context->state[j],context->state[j]);
-				*d++ = context->state[j];
-			}
-		}
-#else
-		MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
-#endif
-	}
-
-	/* Zero out state data */
-	MEMSET_BZERO(context, sizeof(*context));
-}
-
-char *SHA512_End(SHA512_CTX* context, char buffer[]) {
-	sha2_byte	digest[SHA512_DIGEST_LENGTH], *d = digest;
-	int		i;
-
-	/* Sanity check: */
-	assert(context != (SHA512_CTX*)0);
-
-	if (buffer != (char*)0) {
-		SHA512_Final(digest, context);
-
-		for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
-			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-			*buffer++ = sha2_hex_digits[*d & 0x0f];
-			d++;
-		}
-		*buffer = (char)0;
-	} else {
-		MEMSET_BZERO(context, sizeof(*context));
-	}
-	MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
-	return buffer;
-}
-
-char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
-	SHA512_CTX	context;
-
-	SHA512_Init(&context);
-	SHA512_Update(&context, data, len);
-	return SHA512_End(&context, digest);
-}
-
-
-/*** SHA-384: *********************************************************/
-void SHA384_Init(SHA384_CTX* context) {
-	if (context == (SHA384_CTX*)0) {
-		return;
-	}
-	MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
-	MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH);
-	context->bitcount[0] = context->bitcount[1] = 0;
-}
-
-void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
-	SHA512_Update((SHA512_CTX*)context, data, len);
-}
-
-void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
-	sha2_word64	*d = (sha2_word64*)digest;
-
-	/* Sanity check: */
-	assert(context != (SHA384_CTX*)0);
-
-	/* If no digest buffer is passed, we don't bother doing this: */
-	if (digest != (sha2_byte*)0) {
-		SHA512_Last((SHA512_CTX*)context);
-
-		/* Save the hash data for output: */
-#if BYTE_ORDER == LITTLE_ENDIAN
-		{
-			/* Convert TO host byte order */
-			int	j;
-			for (j = 0; j < 6; j++) {
-				REVERSE64(context->state[j],context->state[j]);
-				*d++ = context->state[j];
-			}
-		}
-#else
-		MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH);
-#endif
-	}
-
-	/* Zero out state data */
-	MEMSET_BZERO(context, sizeof(*context));
-}
-
-char *SHA384_End(SHA384_CTX* context, char buffer[]) {
-	sha2_byte	digest[SHA384_DIGEST_LENGTH], *d = digest;
-	int		i;
-
-	/* Sanity check: */
-	assert(context != (SHA384_CTX*)0);
-
-	if (buffer != (char*)0) {
-		SHA384_Final(digest, context);
-
-		for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
-			*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-			*buffer++ = sha2_hex_digits[*d & 0x0f];
-			d++;
-		}
-		*buffer = (char)0;
-	} else {
-		MEMSET_BZERO(context, sizeof(*context));
-	}
-	MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
-	return buffer;
-}
-
-char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
-	SHA384_CTX	context;
-
-	SHA384_Init(&context);
-	SHA384_Update(&context, data, len);
-	return SHA384_End(&context, digest);
-}
-
diff --git a/apt-pkg/contrib/sha2_internal.h b/apt-pkg/contrib/sha2_internal.h
deleted file mode 100644
index 1b82d96..0000000
--- a/apt-pkg/contrib/sha2_internal.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * FILE:	sha2.h
- * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
- * 
- * Copyright (c) 2000-2001, Aaron D. Gifford
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the names of contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
- */
-
-#ifndef __SHA2_H__
-#define __SHA2_H__
-
-/*
- * Import u_intXX_t size_t type definitions from system headers.  You
- * may need to change this, or define these things yourself in this
- * file.
- */
-#include <sys/types.h>
-
-#ifdef SHA2_USE_INTTYPES_H
-
-#include <stddef.h>
-#include <inttypes.h>
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-
-/*** SHA-256/384/512 Various Length Definitions ***********************/
-#define SHA256_BLOCK_LENGTH		64
-#define SHA256_DIGEST_LENGTH		32
-#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
-#define SHA384_BLOCK_LENGTH		128
-#define SHA384_DIGEST_LENGTH		48
-#define SHA384_DIGEST_STRING_LENGTH	(SHA384_DIGEST_LENGTH * 2 + 1)
-#define SHA512_BLOCK_LENGTH		128
-#define SHA512_DIGEST_LENGTH		64
-#define SHA512_DIGEST_STRING_LENGTH	(SHA512_DIGEST_LENGTH * 2 + 1)
-
-
-/*** SHA-256/384/512 Context Structures *******************************/
-/* NOTE: If your architecture does not define either u_intXX_t types or
- * uintXX_t (from inttypes.h), you may need to define things by hand
- * for your system:
- */
-#if 0
-typedef unsigned char u_int8_t;		/* 1-byte  (8-bits)  */
-typedef unsigned int u_int32_t;		/* 4-bytes (32-bits) */
-typedef unsigned long long u_int64_t;	/* 8-bytes (64-bits) */
-#endif
-/*
- * Most BSD systems already define u_intXX_t types, as does Linux.
- * Some systems, however, like Compaq's Tru64 Unix instead can use
- * uintXX_t types defined by very recent ANSI C standards and included
- * in the file:
- *
- *   #include <inttypes.h>
- *
- * If you choose to use <inttypes.h> then please define: 
- *
- *   #define SHA2_USE_INTTYPES_H
- *
- * Or on the command line during compile:
- *
- *   cc -DSHA2_USE_INTTYPES_H ...
- */
-#ifdef SHA2_USE_INTTYPES_H
-
-typedef struct _SHA256_CTX {
-	uint32_t	state[8];
-	uint64_t	bitcount;
-	uint8_t	buffer[SHA256_BLOCK_LENGTH];
-} SHA256_CTX;
-typedef struct _SHA512_CTX {
-	uint64_t	state[8];
-	uint64_t	bitcount[2];
-	uint8_t	buffer[SHA512_BLOCK_LENGTH];
-} SHA512_CTX;
-
-#else /* SHA2_USE_INTTYPES_H */
-
-typedef struct _SHA256_CTX {
-	u_int32_t	state[8];
-	u_int64_t	bitcount;
-	u_int8_t	buffer[SHA256_BLOCK_LENGTH];
-} SHA256_CTX;
-typedef struct _SHA512_CTX {
-	u_int64_t	state[8];
-	u_int64_t	bitcount[2];
-	u_int8_t	buffer[SHA512_BLOCK_LENGTH];
-} SHA512_CTX;
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-typedef SHA512_CTX SHA384_CTX;
-
-
-/*** SHA-256/384/512 Function Prototypes ******************************/
-#ifndef NOPROTO
-#ifdef SHA2_USE_INTTYPES_H
-
-void SHA256_Init(SHA256_CTX *);
-void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t);
-void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
-char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
-char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
-
-void SHA384_Init(SHA384_CTX*);
-void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t);
-void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
-char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
-char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
-
-void SHA512_Init(SHA512_CTX*);
-void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t);
-void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
-char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
-char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
-
-#else /* SHA2_USE_INTTYPES_H */
-
-void SHA256_Init(SHA256_CTX *);
-void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t);
-void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
-char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
-char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
-
-void SHA384_Init(SHA384_CTX*);
-void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t);
-void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
-char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
-char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
-
-void SHA512_Init(SHA512_CTX*);
-void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t);
-void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
-char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
-char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
-
-#endif /* SHA2_USE_INTTYPES_H */
-
-#else /* NOPROTO */
-
-void SHA256_Init();
-void SHA256_Update();
-void SHA256_Final();
-char* SHA256_End();
-char* SHA256_Data();
-
-void SHA384_Init();
-void SHA384_Update();
-void SHA384_Final();
-char* SHA384_End();
-char* SHA384_Data();
-
-void SHA512_Init();
-void SHA512_Update();
-void SHA512_Final();
-char* SHA512_End();
-char* SHA512_Data();
-
-#endif /* NOPROTO */
-
-#endif /* __SHA2_H__ */
-
diff --git a/apt-pkg/makefile b/apt-pkg/makefile
index 5603b51..149937b 100644
--- a/apt-pkg/makefile
+++ b/apt-pkg/makefile
@@ -15,7 +15,7 @@ include ../buildlib/libversion.mak
 LIBRARY=apt-pkg
 MAJOR=$(LIBAPTPKG_MAJOR)
 MINOR=$(LIBAPTPKG_RELEASE)
-SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil -ldl
+SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil -ldl -lnettle
 ifeq ($(HAVE_ZLIB),yes)
 SLIBS+= -lz
 endif
diff --git a/configure.ac b/configure.ac
index d728e5e..7f02472 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,6 +89,13 @@ AC_CHECK_LIB(curl, curl_easy_init,
      AC_MSG_ERROR([failed: I need CURL due https support]),
 )
 
+AC_CHECK_LIB(nettle, nettle_md5_init,
+     [AC_CHECK_HEADER(nettle/md5.h,
+        nettle_ok=yes,
+        nettle_ok=no)],
+     AC_MSG_ERROR([failed: I need nettle for hashes]),
+)
+
 AC_LANG_PUSH([C++])
 AC_CHECK_HEADER(gtest/gtest.h,,
      AC_MSG_ERROR([failed: I need gtest to build tests]),
diff --git a/debian/control b/debian/control
index 0437aa7..aa67fb0 100644
--- a/debian/control
+++ b/debian/control
@@ -6,7 +6,7 @@ Uploaders: Michael Vogt <[email protected]>, Christian Perrier <[email protected]>
  Julian Andres Klode <[email protected]>
 Standards-Version: 3.9.5
 Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev,
- gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~),
+ gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~), nettle-dev,
  zlib1g-dev, libbz2-dev, liblzma-dev,
  xsltproc, docbook-xsl, docbook-xml, po4a (>= 0.34-2),
  autotools-dev, autoconf, automake, libgtest-dev
diff --git a/methods/http.cc b/methods/http.cc
index 1b996db..845395b 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -1,27 +1,12 @@
-// -*- mode: cpp; mode: fold -*-
+//-*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: http.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $
+// $Id: http.cc,v 1.6 2016/01/30 10:36:09 lhw Exp $
 /* ######################################################################
 
    HTTP Acquire Method - This is the HTTP acquire method for APT.
-   
-   It uses HTTP/1.1 and many of the fancy options there-in, such as
-   pipelining, range, if-range and so on. 
-
-   It is based on a doubly buffered select loop. A groupe of requests are 
-   fed into a single output buffer that is constantly fed out the 
-   socket. This provides ideal pipelining as in many cases all of the
-   requests will fit into a single packet. The input socket is buffered 
-   the same way and fed into the fd for the file (may be a pipe in future).
-   
-   This double buffering provides fairly substantial transfer rates,
-   compared to wget the http method is about 4% faster. Most importantly,
-   when HTTP is compared with FTP as a protocol the speed difference is
-   huge. In tests over the internet from two sites to llug (via ATM) this
-   program got 230k/s sustained http transfer rates. FTP on the other 
-   hand topped out at 170k/s. That combined with the time to setup the
-   FTP connection makes HTTP a vastly superior protocol.
-      
+
+   It uses libcurl
+
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
@@ -33,749 +18,348 @@
 #include <apt-pkg/error.h>
 #include <apt-pkg/hashes.h>
 #include <apt-pkg/netrc.h>
-#include <apt-pkg/strutl.h>
 #include <apt-pkg/proxy.h>
 
-#include <stddef.h>
-#include <stdlib.h>
-#include <sys/select.h>
-#include <cstring>
 #include <sys/stat.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <iostream>
 #include <sstream>
+#include <stdlib.h>
 
-#include "config.h"
-#include "connect.h"
 #include "http.h"
-
-#include <apti18n.h>
-									/*}}}*/
+							/*}}}*/
 using namespace std;
 
-unsigned long long CircleBuf::BwReadLimit=0;
-unsigned long long CircleBuf::BwTickReadData=0;
-struct timeval CircleBuf::BwReadTick={0,0};
-const unsigned int CircleBuf::BW_HZ=10;
-
-// CircleBuf::CircleBuf - Circular input buffer				/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-CircleBuf::CircleBuf(unsigned long long Size) : Size(Size), Hash(0)
+size_t
+HttpMethod::parse_header(void *buffer, size_t size, size_t nmemb, void *userp)
 {
-   Buf = new unsigned char[Size];
-   Reset();
-
-   CircleBuf::BwReadLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024;
-}
-									/*}}}*/
-// CircleBuf::Reset - Reset to the default state			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void CircleBuf::Reset()
-{
-   InP = 0;
-   OutP = 0;
-   StrPos = 0;
-   MaxGet = (unsigned long long)-1;
-   OutQueue = string();
-   if (Hash != 0)
-   {
-      delete Hash;
-      Hash = new Hashes;
-   }
-}
-									/*}}}*/
-// CircleBuf::Read - Read from a FD into the circular buffer		/*{{{*/
-// ---------------------------------------------------------------------
-/* This fills up the buffer with as much data as is in the FD, assuming it
-   is non-blocking.. */
-bool CircleBuf::Read(int Fd)
-{
-   while (1)
+  size_t len = size * nmemb;
+  HttpMethod *me = (HttpMethod *)userp;
+  std::string line((char*) buffer, len);
+  for (--len; len > 0; --len)
+   if (isspace(line[len]) == 0)
    {
-      // Woops, buffer is full
-      if (InP - OutP == Size)
-	 return true;
-
-      // what's left to read in this tick
-      unsigned long long const BwReadMax = CircleBuf::BwReadLimit/BW_HZ;
-
-      if(CircleBuf::BwReadLimit) {
-	 struct timeval now;
-	 gettimeofday(&now,0);
-
-	 unsigned long long d = (now.tv_sec-CircleBuf::BwReadTick.tv_sec)*1000000 +
-	    now.tv_usec-CircleBuf::BwReadTick.tv_usec;
-	 if(d > 1000000/BW_HZ) {
-	    CircleBuf::BwReadTick = now;
-	    CircleBuf::BwTickReadData = 0;
-	 } 
-	 
-	 if(CircleBuf::BwTickReadData >= BwReadMax) {
-	    usleep(1000000/BW_HZ);
-	    return true;
-	 }
-      }
-
-      // Write the buffer segment
-      ssize_t Res;
-      if(CircleBuf::BwReadLimit) {
-	 Res = read(Fd,Buf + (InP%Size), 
-		    BwReadMax > LeftRead() ? LeftRead() : BwReadMax);
-      } else
-	 Res = read(Fd,Buf + (InP%Size),LeftRead());
-      
-      if(Res > 0 && BwReadLimit > 0) 
-	 CircleBuf::BwTickReadData += Res;
-    
-      if (Res == 0)
-	 return false;
-      if (Res < 0)
-      {
-	 if (errno == EAGAIN)
-	    return true;
-	 return false;
-      }
-
-      if (InP == 0)
-	 gettimeofday(&Start,0);
-      InP += Res;
+     ++len;
+     break;
    }
+  line.erase(len);
+
+  if (line.empty() == true)
+  {
+    if (me->Server->Result != 416 && me->Server->StartPos != 0);
+    else if (me->Server->Result == 416 && me->Server->Size == me->File->FileSize())
+    {
+      me->Server->Result = 200;
+      me->Server->StartPos = me->Server->Size;
+    }
+    else
+     me->Server->StartPos = 0;
+
+    me->File->Truncate(me->Server->StartPos);
+    me->File->Seek(me->Server->StartPos);
+  }
+  else if (me->Server->HeaderLine(line) == false)
+   return 0;
+
+  return size*nmemb;
 }
-									/*}}}*/
-// CircleBuf::Read - Put the string into the buffer			/*{{{*/
-// ---------------------------------------------------------------------
-/* This will hold the string in and fill the buffer with it as it empties */
-bool CircleBuf::Read(string Data)
-{
-   OutQueue += Data;
-   FillOut();
-   return true;
-}
-									/*}}}*/
-// CircleBuf::FillOut - Fill the buffer from the output queue		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void CircleBuf::FillOut()
-{
-   if (OutQueue.empty() == true)
-      return;
-   while (1)
-   {
-      // Woops, buffer is full
-      if (InP - OutP == Size)
-	 return;
-      
-      // Write the buffer segment
-      unsigned long long Sz = LeftRead();
-      if (OutQueue.length() - StrPos < Sz)
-	 Sz = OutQueue.length() - StrPos;
-      memcpy(Buf + (InP%Size),OutQueue.c_str() + StrPos,Sz);
-      
-      // Advance
-      StrPos += Sz;
-      InP += Sz;
-      if (OutQueue.length() == StrPos)
-      {
-	 StrPos = 0;
-	 OutQueue = "";
-	 return;
-      }
-   }
-}
-									/*}}}*/
-// CircleBuf::Write - Write from the buffer into a FD			/*{{{*/
-// ---------------------------------------------------------------------
-/* This empties the buffer into the FD. */
-bool CircleBuf::Write(int Fd)
-{
-   while (1)
-   {
-      FillOut();
-      
-      // Woops, buffer is empty
-      if (OutP == InP)
-	 return true;
-      
-      if (OutP == MaxGet)
-	 return true;
-      
-      // Write the buffer segment
-      ssize_t Res;
-      Res = write(Fd,Buf + (OutP%Size),LeftWrite());
-
-      if (Res == 0)
-	 return false;
-      if (Res < 0)
-      {
-	 if (errno == EAGAIN)
-	    return true;
-	 
-	 return false;
-      }
-      
-      if (Hash != 0)
-	 Hash->Add(Buf + (OutP%Size),Res);
-      
-      OutP += Res;
-   }
-}
-									/*}}}*/
-// CircleBuf::WriteTillEl - Write from the buffer to a string		/*{{{*/
-// ---------------------------------------------------------------------
-/* This copies till the first empty line */
-bool CircleBuf::WriteTillEl(string &Data,bool Single)
+
+size_t
+HttpMethod::write_data(void *buffer, size_t size, size_t nmemb, void *userp)
 {
-   // We cheat and assume it is unneeded to have more than one buffer load
-   for (unsigned long long I = OutP; I < InP; I++)
-   {      
-      if (Buf[I%Size] != '\n')
-	 continue;
-      ++I;
-      
-      if (Single == false)
-      {
-         if (I < InP  && Buf[I%Size] == '\r')
-            ++I;
-         if (I >= InP || Buf[I%Size] != '\n')
-            continue;
-         ++I;
-      }
-      
-      Data = "";
-      while (OutP < I)
-      {
-	 unsigned long long Sz = LeftWrite();
-	 if (Sz == 0)
-	    return false;
-	 if (I - OutP < Sz)
-	    Sz = I - OutP;
-	 Data += string((char *)(Buf + (OutP%Size)),Sz);
-	 OutP += Sz;
-      }
-      return true;
-   }      
+  HttpMethod *me = (HttpMethod *)userp;
+
+  if (me->Res.Size == 0)
+   me->URIStart(me->Res);
+  if(me->File->Write(buffer, size*nmemb) != true)
    return false;
-}
-									/*}}}*/
-// CircleBuf::Stats - Print out stats information			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void CircleBuf::Stats()
-{
-   if (InP == 0)
-      return;
-   
-   struct timeval Stop;
-   gettimeofday(&Stop,0);
-/*   float Diff = Stop.tv_sec - Start.tv_sec + 
-             (float)(Stop.tv_usec - Start.tv_usec)/1000000;
-   clog << "Got " << InP << " in " << Diff << " at " << InP/Diff << endl;*/
-}
-									/*}}}*/
-CircleBuf::~CircleBuf()
-{
-   delete [] Buf;
-   delete Hash;
-}
 
-// HttpServerState::HttpServerState - Constructor			/*{{{*/
-HttpServerState::HttpServerState(URI Srv,HttpMethod *Owner) : ServerState(Srv, Owner), In(64*1024), Out(4*1024)
-{
-   TimeOut = _config->FindI("Acquire::http::Timeout",TimeOut);
-   Reset();
-}
-									/*}}}*/
-// HttpServerState::Open - Open a connection to the server		/*{{{*/
-// ---------------------------------------------------------------------
-/* This opens a connection to the server. */
-bool HttpServerState::Open()
-{
-   // Use the already open connection if possible.
-   if (ServerFd != -1)
-      return true;
-   
-   Close();
-   In.Reset();
-   Out.Reset();
-   Persistent = true;
-   
-   // Determine the proxy setting
-   AutoDetectProxy(ServerName);
-   string SpecificProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host);
-   if (!SpecificProxy.empty())
-   {
-	   if (SpecificProxy == "DIRECT")
-		   Proxy = "";
-	   else
-		   Proxy = SpecificProxy;
-   }
-   else
-   {
-	   string DefProxy = _config->Find("Acquire::http::Proxy");
-	   if (!DefProxy.empty())
-	   {
-		   Proxy = DefProxy;
-	   }
-	   else
-	   {
-		   char* result = getenv("http_proxy");
-		   Proxy = result ? result : "";
-	   }
-   }
-   
-   // Parse no_proxy, a , separated list of domains
-   if (getenv("no_proxy") != 0)
-   {
-      if (CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
-	 Proxy = "";
-   }
-   
-   // Determine what host and port to use based on the proxy settings
-   int Port = 0;
-   string Host;   
-   if (Proxy.empty() == true || Proxy.Host.empty() == true)
-   {
-      if (ServerName.Port != 0)
-	 Port = ServerName.Port;
-      Host = ServerName.Host;
-   }
-   else
-   {
-      if (Proxy.Port != 0)
-	 Port = Proxy.Port;
-      Host = Proxy.Host;
-   }
-   
-   // Connect to the remote server
-   if (Connect(Host,Port,"http",80,ServerFd,TimeOut,Owner) == false)
-      return false;
-   
-   return true;
-}
-									/*}}}*/
-// HttpServerState::Close - Close a connection to the server		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool HttpServerState::Close()
-{
-   close(ServerFd);
-   ServerFd = -1;
-   return true;
-}
-									/*}}}*/
-// HttpServerState::RunData - Transfer the data from the socket		/*{{{*/
-bool HttpServerState::RunData(FileFd * const File)
-{
-   State = Data;
-   
-   // Chunked transfer encoding is fun..
-   if (Encoding == Chunked)
-   {
-      while (1)
-      {
-	 // Grab the block size
-	 bool Last = true;
-	 string Data;
-	 In.Limit(-1);
-	 do
-	 {
-	    if (In.WriteTillEl(Data,true) == true)
-	       break;
-	 }
-	 while ((Last = Go(false, File)) == true);
-
-	 if (Last == false)
-	    return false;
-	 	 
-	 // See if we are done
-	 unsigned long long Len = strtoull(Data.c_str(),0,16);
-	 if (Len == 0)
-	 {
-	    In.Limit(-1);
-	    
-	    // We have to remove the entity trailer
-	    Last = true;
-	    do
-	    {
-	       if (In.WriteTillEl(Data,true) == true && Data.length() <= 2)
-		  break;
-	    }
-	    while ((Last = Go(false, File)) == true);
-	    if (Last == false)
-	       return false;
-	    return !_error->PendingError();
-	 }
-	 
-	 // Transfer the block
-	 In.Limit(Len);
-	 while (Go(true, File) == true)
-	    if (In.IsLimit() == true)
-	       break;
-	 
-	 // Error
-	 if (In.IsLimit() == false)
-	    return false;
-	 
-	 // The server sends an extra new line before the next block specifier..
-	 In.Limit(-1);
-	 Last = true;
-	 do
-	 {
-	    if (In.WriteTillEl(Data,true) == true)
-	       break;
-	 }
-	 while ((Last = Go(false, File)) == true);
-	 if (Last == false)
-	    return false;
-      }
-   }
-   else
-   {
-      /* Closes encoding is used when the server did not specify a size, the
-         loss of the connection means we are done */
-      if (Encoding == Closes)
-	 In.Limit(-1);
-      else if (JunkSize != 0)
-	 In.Limit(JunkSize);
-      else
-	 In.Limit(Size - StartPos);
-      
-      // Just transfer the whole block.
-      do
-      {
-	 if (In.IsLimit() == false)
-	    continue;
-	 
-	 In.Limit(-1);
-	 return !_error->PendingError();
-      }
-      while (Go(true, File) == true);
-   }
+  if (me->Server->Hash != 0)
+   me->Server->Hash->Add((const unsigned char *)buffer, nmemb);
 
-   return Owner->Flush() && !_error->PendingError();
+  return size*nmemb;
 }
-									/*}}}*/
-bool HttpServerState::ReadHeaderLines(std::string &Data)		/*{{{*/
-{
-   return In.WriteTillEl(Data);
-}
-									/*}}}*/
-bool HttpServerState::LoadNextResponse(bool const ToFile, FileFd * const File)/*{{{*/
-{
-   return Go(ToFile, File);
-}
-									/*}}}*/
-bool HttpServerState::WriteResponse(const std::string &Data)		/*{{{*/
-{
-   return Out.Read(Data);
-}
-									/*}}}*/
-APT_PURE bool HttpServerState::IsOpen()					/*{{{*/
-{
-   return (ServerFd != -1);
-}
-									/*}}}*/
-bool HttpServerState::InitHashes(FileFd &File)				/*{{{*/
-{
-   delete In.Hash;
-   In.Hash = new Hashes;
 
-   // Set the expected size and read file for the hashes
-   File.Truncate(StartPos);
-   return In.Hash->AddFD(File, StartPos);
-}
-									/*}}}*/
-APT_PURE Hashes * HttpServerState::GetHashes()				/*{{{*/
+int
+HttpMethod::progress_callback(void *clientp, double dltotal, double /*dlnow*/,
+ double /*ultotal*/, double /*ulnow*/)
 {
-   return In.Hash;
+  HttpMethod *me = (HttpMethod *)clientp;
+  if(dltotal > 0 && me->Res.Size == 0) {
+    me->Res.Size = (unsigned long long)dltotal;
+  }
+  return 0;
 }
-									/*}}}*/
-// HttpServerState::Die - The server has closed the connection.		/*{{{*/
-bool HttpServerState::Die(FileFd &File)
-{
-   unsigned int LErrno = errno;
 
-   // Dump the buffer to the file
-   if (State == ServerState::Data)
-   {
-      // on GNU/kFreeBSD, apt dies on /dev/null because non-blocking
-      // can't be set
-      if (File.Name() != "/dev/null")
-	 SetNonBlock(File.Fd(),false);
-      while (In.WriteSpace() == true)
-      {
-	 if (In.Write(File.Fd()) == false)
-	    return _error->Errno("write",_("Error writing to the file"));
-
-	 // Done
-	 if (In.IsLimit() == true)
-	    return true;
-      }
-   }
-
-   // See if this is because the server finished the data stream
-   if (In.IsLimit() == false && State != HttpServerState::Header &&
-       Encoding != HttpServerState::Closes)
-   {
-      Close();
-      if (LErrno == 0)
-	 return _error->Error(_("Error reading from server. Remote end closed connection"));
-      errno = LErrno;
-      return _error->Errno("read",_("Error reading from server"));
-   }
-   else
-   {
-      In.Limit(-1);
-
-      // Nothing left in the buffer
-      if (In.WriteSpace() == false)
-	 return false;
-
-      // We may have got multiple responses back in one packet..
-      Close();
-      return true;
-   }
-
-   return false;
-}
-									/*}}}*/
-// HttpServerState::Flush - Dump the buffer into the file		/*{{{*/
-// ---------------------------------------------------------------------
-/* This takes the current input buffer from the Server FD and writes it
-   into the file */
-bool HttpServerState::Flush(FileFd * const File)
+HttpServerState::HttpServerState(URI Srv, HttpMethod *) : ServerState(Srv, NULL)
 {
-   if (File != NULL)
-   {
-      // on GNU/kFreeBSD, apt dies on /dev/null because non-blocking
-      // can't be set
-      if (File->Name() != "/dev/null")
-	 SetNonBlock(File->Fd(),false);
-      if (In.WriteSpace() == false)
-	 return true;
-      
-      while (In.WriteSpace() == true)
-      {
-	 if (In.Write(File->Fd()) == false)
-	    return _error->Errno("write",_("Error writing to file"));
-	 if (In.IsLimit() == true)
-	    return true;
-      }
-
-      if (In.IsLimit() == true || Encoding == ServerState::Closes)
-	 return true;
-   }
-   return false;
+  TimeOut = _config->FindI("Acquire::http::Timeout",TimeOut);
+  Reset();
 }
-									/*}}}*/
-// HttpServerState::Go - Run a single loop				/*{{{*/
-// ---------------------------------------------------------------------
-/* This runs the select loop over the server FDs, Output file FDs and
-   stdin. */
-bool HttpServerState::Go(bool ToFile, FileFd * const File)
-{
-   // Server has closed the connection
-   if (ServerFd == -1 && (In.WriteSpace() == false || 
-			       ToFile == false))
-      return false;
-   
-   fd_set rfds,wfds;
-   FD_ZERO(&rfds);
-   FD_ZERO(&wfds);
-   
-   /* Add the server. We only send more requests if the connection will 
-      be persisting */
-   if (Out.WriteSpace() == true && ServerFd != -1 
-       && Persistent == true)
-      FD_SET(ServerFd,&wfds);
-   if (In.ReadSpace() == true && ServerFd != -1)
-      FD_SET(ServerFd,&rfds);
-   
-   // Add the file
-   int FileFD = -1;
-   if (File != NULL)
-      FileFD = File->Fd();
-   
-   if (In.WriteSpace() == true && ToFile == true && FileFD != -1)
-      FD_SET(FileFD,&wfds);
-
-   // Add stdin
-   if (_config->FindB("Acquire::http::DependOnSTDIN", true) == true)
-      FD_SET(STDIN_FILENO,&rfds);
-	  
-   // Figure out the max fd
-   int MaxFd = FileFD;
-   if (MaxFd < ServerFd)
-      MaxFd = ServerFd;
-
-   // Select
-   struct timeval tv;
-   tv.tv_sec = TimeOut;
-   tv.tv_usec = 0;
-   int Res = 0;
-   if ((Res = select(MaxFd+1,&rfds,&wfds,0,&tv)) < 0)
-   {
-      if (errno == EINTR)
-	 return true;
-      return _error->Errno("select",_("Select failed"));
-   }
-   
-   if (Res == 0)
-   {
-      _error->Error(_("Connection timed out"));
-      return Die(*File);
-   }
-   
-   // Handle server IO
-   if (ServerFd != -1 && FD_ISSET(ServerFd,&rfds))
-   {
-      errno = 0;
-      if (In.Read(ServerFd) == false)
-	 return Die(*File);
-   }
-	 
-   if (ServerFd != -1 && FD_ISSET(ServerFd,&wfds))
-   {
-      errno = 0;
-      if (Out.Write(ServerFd) == false)
-	 return Die(*File);
-   }
 
-   // Send data to the file
-   if (FileFD != -1 && FD_ISSET(FileFD,&wfds))
-   {
-      if (In.Write(FileFD) == false)
-	 return _error->Errno("write",_("Error writing to output file"));
-   }
+bool HttpServerState::InitHashes(FileFd &File)
+{
+  Hash = new Hashes;
 
-   // Handle commands from APT
-   if (FD_ISSET(STDIN_FILENO,&rfds))
-   {
-      if (Owner->Run(true) != -1)
-	 exit(100);
-   }   
-       
-   return true;
+  File.Truncate(StartPos);
+  return Hash->AddFD(File, StartPos);
 }
-									/*}}}*/
 
-// HttpMethod::SendReq - Send the HTTP request				/*{{{*/
-// ---------------------------------------------------------------------
-/* This places the http request in the outbound buffer */
-void HttpMethod::SendReq(FetchItem *Itm)
+APT_PURE Hashes * HttpServerState::GetHashes()
 {
-   URI Uri = Itm->Uri;
-
-   // The HTTP server expects a hostname with a trailing :port
-   std::stringstream Req;
-   string ProperHost;
-
-   if (Uri.Host.find(':') != string::npos)
-      ProperHost = '[' + Uri.Host + ']';
-   else
-      ProperHost = Uri.Host;
-
-   /* RFC 2616 ??5.1.2 requires absolute URIs for requests to proxies,
-      but while its a must for all servers to accept absolute URIs,
-      it is assumed clients will sent an absolute path for non-proxies */
-   std::string requesturi;
-   if (Server->Proxy.empty() == true || Server->Proxy.Host.empty())
-      requesturi = Uri.Path;
-   else
-      requesturi = Itm->Uri;
-
-   // The "+" is encoded as a workaround for a amazon S3 bug
-   // see LP bugs #1003633 and #1086997.
-   requesturi = QuoteString(requesturi, "+~ ");
-
-   /* Build the request. No keep-alive is included as it is the default
-      in 1.1, can cause problems with proxies, and we are an HTTP/1.1
-      client anyway.
-      C.f. https://tools.ietf.org/wg/httpbis/trac/ticket/158 */
-   Req << "GET " << requesturi << " HTTP/1.1\r\n";
-   if (Uri.Port != 0)
-      Req << "Host: " << ProperHost << ":" << Uri.Port << "\r\n";
-   else
-      Req << "Host: " << ProperHost << "\r\n";
-
-   // generate a cache control header (if needed)
-   if (_config->FindB("Acquire::http::No-Cache",false) == true)
-      Req << "Cache-Control: no-cache\r\n"
-	 << "Pragma: no-cache\r\n";
-   else if (Itm->IndexFile == true)
-      Req << "Cache-Control: max-age=" << _config->FindI("Acquire::http::Max-Age",0) << "\r\n";
-   else if (_config->FindB("Acquire::http::No-Store",false) == true)
-      Req << "Cache-Control: no-store\r\n";
-
-   // If we ask for uncompressed files servers might respond with content-
-   // negotiation which lets us end up with compressed files we do not support,
-   // see 657029, 657560 and co, so if we have no extension on the request
-   // ask for text only. As a sidenote: If there is nothing to negotate servers
-   // seem to be nice and ignore it.
-   if (_config->FindB("Acquire::http::SendAccept", true) == true)
-   {
-      size_t const filepos = Itm->Uri.find_last_of('/');
-      string const file = Itm->Uri.substr(filepos + 1);
-      if (flExtension(file) == file)
-	 Req << "Accept: text/*\r\n";
-   }
-
-   // Check for a partial file and send if-queries accordingly
-   struct stat SBuf;
-   if (stat(Itm->DestFile.c_str(),&SBuf) >= 0 && SBuf.st_size > 0)
-      Req << "Range: bytes=" << SBuf.st_size << "-\r\n"
-	 << "If-Range: " << TimeRFC1123(SBuf.st_mtime) << "\r\n";
-   else if (Itm->LastModified != 0)
-      Req << "If-Modified-Since: " << TimeRFC1123(Itm->LastModified).c_str() << "\r\n";
-
-   if (Server->Proxy.User.empty() == false || Server->Proxy.Password.empty() == false)
-      Req << "Proxy-Authorization: Basic "
-	 << Base64Encode(Server->Proxy.User + ":" + Server->Proxy.Password) << "\r\n";
-
-   maybe_add_auth (Uri, _config->FindFile("Dir::Etc::netrc"));
-   if (Uri.User.empty() == false || Uri.Password.empty() == false)
-      Req << "Authorization: Basic "
-	 << Base64Encode(Uri.User + ":" + Uri.Password) << "\r\n";
-
-   Req << "User-Agent: " << _config->Find("Acquire::http::User-Agent",
-		"Debian APT-HTTP/1.3 (" PACKAGE_VERSION ")") << "\r\n";
-
-   Req << "\r\n";
-
-   if (Debug == true)
-      cerr << Req.str() << endl;
-
-   Server->WriteResponse(Req.str());
+  return Hash;
 }
-									/*}}}*/
-// HttpMethod::Configuration - Handle a configuration message		/*{{{*/
-// ---------------------------------------------------------------------
-/* We stash the desired pipeline depth */
-bool HttpMethod::Configuration(string Message)
-{
-   if (ServerMethod::Configuration(Message) == false)
-      return false;
 
-   AllowRedirect = _config->FindB("Acquire::http::AllowRedirect",true);
-   PipelineDepth = _config->FindI("Acquire::http::Pipeline-Depth",
-				  PipelineDepth);
-   Debug = _config->FindB("Debug::Acquire::http",false);
-
-   return true;
-}
-									/*}}}*/
-ServerState * HttpMethod::CreateServerState(URI uri)			/*{{{*/
+void HttpMethod::SetupProxy()
 {
-   return new HttpServerState(uri, this);
+  URI ServerName = Queue->Uri;
+
+  // Determine the proxy setting
+  AutoDetectProxy(ServerName);
+
+  // Curl should never read proxy settings from the environment, as
+  // we determine which proxy to use.  Do this for consistency among
+  // methods and prevent an environment variable overriding a
+  // no-proxy ("DIRECT") setting in apt.conf.
+  curl_easy_setopt(curl, CURLOPT_PROXY, "");
+
+  // Determine the proxy setting
+  string UseProxy = _config->Find("Acquire::http::Proxy::" + ServerName.Host).c_str();
+
+  if (UseProxy.empty() == true)
+   UseProxy = _config->Find("Acquire::http::Proxy").c_str();
+
+  // User want to use NO proxy, so nothing to setup
+  if (UseProxy == "DIRECT")
+   return;
+
+  if (UseProxy.empty() == false)
+  {
+    // Parse no_proxy, a comma (,) separated list of domains we don't want to use
+    // a proxy for so we stop right here if it is in the list
+    if (getenv("no_proxy") != 0 && CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
+     return;
+  } else {
+    const char* result = getenv("http_proxy");
+    UseProxy = result == NULL ? "" : result;
+  }
+
+  // Determine what host and port to use based on the proxy settings
+  if (UseProxy.empty() == false)
+  {
+    Proxy = UseProxy;
+    if (Proxy.Port != 1)
+     curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port);
+    curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str());
+    if (Proxy.User.empty() == false || Proxy.Password.empty() == false)
+    {
+      curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, Proxy.User.c_str());
+      curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, Proxy.Password.c_str());
+    }
+  }
 }
-									/*}}}*/
-void HttpMethod::RotateDNS()						/*{{{*/
+
+bool HttpMethod::Fetch(FetchItem *Itm)
 {
-   ::RotateDNS();
+  struct stat SBuf;
+  struct curl_slist *headers=NULL;
+  char curl_errorstr[CURL_ERROR_SIZE];
+  URI Uri = Itm->Uri;
+  string remotehost = Uri.Host;
+
+  // TODO:
+  //       - http::Pipeline-Depth
+  //       - error checking/reporting
+  //       - more debug options? (CURLOPT_DEBUGFUNCTION?)
+
+  curl_easy_reset(curl);
+  SetupProxy();
+
+  maybe_add_auth (Uri, _config->FindFile("Dir::Etc::netrc"));
+
+  // callbacks
+  curl_easy_setopt(curl, CURLOPT_URL, static_cast<string>(Uri).c_str());
+  curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header);
+  curl_easy_setopt(curl, CURLOPT_WRITEHEADER, this);
+  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
+  curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
+  curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);
+  curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
+  // options
+  curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
+  curl_easy_setopt(curl, CURLOPT_FILETIME, true);
+  // only allow curl to handle http, not the other stuff it supports
+  curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP);
+  curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP);
+
+  // cache-control
+  if(_config->FindB("Acquire::http::No-Cache",false) == false)
+  {
+    // cache enabled
+    if (_config->FindB("Acquire::http::No-Store",false) == true)
+     headers = curl_slist_append(headers,"Cache-Control: no-store");
+    stringstream ss;
+    ioprintf(ss, "Cache-Control: max-age=%u", _config->FindI("Acquire::http::Max-Age",0));
+    headers = curl_slist_append(headers, ss.str().c_str());
+  } else {
+    // cache disabled by user
+    headers = curl_slist_append(headers, "Cache-Control: no-cache");
+    headers = curl_slist_append(headers, "Pragma: no-cache");
+  }
+  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+  // speed limit
+  int const dlLimit = _config->FindI("Acquire::http::Dl-Limit",0)*1024;
+  if (dlLimit > 0)
+   curl_easy_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, dlLimit);
+
+  // set header
+  curl_easy_setopt(curl, CURLOPT_USERAGENT, _config->Find("Acquire::http::User-Agent",
+    "Debian APT-CURL/1.0 (" PACKAGE_VERSION ")").c_str());
+
+  // set timeout
+  int const timeout = _config->FindI("Acquire::http::Timeout",120);
+  curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
+  //set really low lowspeed timeout (see #497983)
+  curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, DL_MIN_SPEED);
+  curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, timeout);
+
+  // set redirect options and default to 10 redirects
+  bool const AllowRedirect = _config->FindB("Acquire::http::AllowRedirect",true);
+  curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, AllowRedirect);
+  curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10);
+
+  // debug
+  if(_config->FindB("Debug::Acquire::http", false))
+   curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
+
+  // error handling
+  curl_errorstr[0] = '\0';
+  curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
+
+  // If we ask for uncompressed files servers might respond with content-
+  // negotiation which lets us end up with compressed files we do not support,
+  // see 657029, 657560 and co, so if we have no extension on the request
+  // ask for text only. As a sidenote: If there is nothing to negotate servers
+  // seem to be nice and ignore it.
+  if (_config->FindB("Acquire::http::SendAccept", true) == true)
+  {
+    size_t const filepos = Itm->Uri.find_last_of('/');
+    string const file = Itm->Uri.substr(filepos + 1);
+    if (flExtension(file) == file)
+     headers = curl_slist_append(headers, "Accept: text/*");
+  }
+
+  // if we have the file send an if-range query with a range header
+  if (stat(Itm->DestFile.c_str(),&SBuf) >= 0 && SBuf.st_size > 0)
+  {
+    std::string Buf;
+    strprintf(Buf, "Range: bytes=%lli-", (long long) SBuf.st_size);
+    headers = curl_slist_append(headers, Buf.c_str());
+    strprintf(Buf, "If-Range: %s", TimeRFC1123(SBuf.st_mtime).c_str());
+    headers = curl_slist_append(headers, Buf.c_str());
+  }
+  else if(Itm->LastModified > 0)
+  {
+    curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+    curl_easy_setopt(curl, CURLOPT_TIMEVALUE, Itm->LastModified);
+  }
+
+  // go for it - if the file exists, append on it
+  File = new FileFd(Itm->DestFile, FileFd::WriteAny);
+  Server = new HttpServerState(Itm->Uri, this);
+  Server->InitHashes(*File);
+
+  // keep apt updated
+  Res.Filename = Itm->DestFile;
+
+  // get it!
+  CURLcode success = curl_easy_perform(curl);
+
+  // If the server returns 200 OK but the If-Modified-Since condition is not
+  // met, CURLINFO_CONDITION_UNMET will be set to 1
+  long curl_condition_unmet = 0;
+  curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &curl_condition_unmet);
+
+  File->Close();
+  curl_slist_free_all(headers);
+
+  // cleanup
+  if (success != 0)
+  {
+    _error->Error("%s", curl_errorstr);
+    unlink(File->Name().c_str());
+    return false;
+  }
+
+  // server says file not modified
+  if (Server->Result == 304 || curl_condition_unmet == 1)
+  {
+    unlink(File->Name().c_str());
+    Res.IMSHit = true;
+    Res.LastModified = Itm->LastModified;
+    Res.Size = 0;
+    URIDone(Res);
+    return true;
+  }
+  Res.IMSHit = false;
+
+  if (Server->Result != 200 && // OK
+   Server->Result != 206 && // Partial
+   Server->Result != 416) // invalid Range
+  {
+    char err[255];
+    snprintf(err, sizeof(err) - 1, "HttpError%i", Server->Result);
+    SetFailReason(err);
+    _error->Error("%s", err);
+    // unlink, no need keep 401/404 page content in partial/
+    unlink(File->Name().c_str());
+    return false;
+  }
+
+  struct stat resultStat;
+  if (unlikely(stat(File->Name().c_str(), &resultStat) != 0))
+  {
+    _error->Errno("stat", "Unable to access file %s", File->Name().c_str());
+    return false;
+  }
+  Res.Size = resultStat.st_size;
+
+  // invalid range-request
+  if (Server->Result == 416)
+  {
+    unlink(File->Name().c_str());
+    Res.Size = 0;
+    delete File;
+    Redirect(Itm->Uri);
+    return true;
+  }
+
+  // Timestamp
+  curl_easy_getinfo(curl, CURLINFO_FILETIME, &Res.LastModified);
+  if (Res.LastModified != -1)
+  {
+    struct timeval times[2];
+    times[0].tv_sec = Res.LastModified;
+    times[1].tv_sec = Res.LastModified;
+    times[0].tv_usec = times[1].tv_usec = 0;
+    utimes(File->Name().c_str(), times);
+  }
+  else
+   Res.LastModified = resultStat.st_mtime;
+
+  // take hashes
+  /*
+  Hashes Hash;
+  FileFd Fd(Res.Filename, FileFd::ReadOnly);
+  Hash.AddFD(Fd);
+  */
+  Res.TakeHashes(*Server->Hash);
+
+  // keep apt updated
+  URIDone(Res);
+
+  // cleanup
+  Res.Size = 0;
+  delete File;
+
+  return true;
 }
-									/*}}}*/
diff --git a/methods/http.h b/methods/http.h
index 1df9fa0..03c0f31 100644
--- a/methods/http.h
+++ b/methods/http.h
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
-// Description								/*{{{*/// $Id: http.h,v 1.12 2002/04/18 05:09:38 jgg Exp $
-// $Id: http.h,v 1.12 2002/04/18 05:09:38 jgg Exp $
+// Description								/*{{{*/// $Id: http.h,v 1.13 2002/04/18 05:09:38 jgg Exp $
+// $Id: http.h,v 1.2 2015/01/30 10:34:50 lhw Exp $
 /* ######################################################################
 
    HTTP Acquire Method - This is the HTTP acquire method for APT.
@@ -11,135 +11,73 @@
 #ifndef APT_HTTP_H
 #define APT_HTTP_H
 
-#include <apt-pkg/strutl.h>
 #include <apt-pkg/acquire-method.h>
 
-#include <string>
-#include <sys/time.h>
-#include <iostream>
+#include <curl/curl.h>
 
 #include "server.h"
 
-using std::cout;
-using std::endl;
-
-class FileFd;
-class HttpMethod;
 class Hashes;
+class HttpMethod;
 
-class CircleBuf
-{
-   unsigned char *Buf;
-   unsigned long long Size;
-   unsigned long long InP;
-   unsigned long long OutP;
-   std::string OutQueue;
-   unsigned long long StrPos;
-   unsigned long long MaxGet;
-   struct timeval Start;
-
-   static unsigned long long BwReadLimit;
-   static unsigned long long BwTickReadData;
-   static struct timeval BwReadTick;
-   static const unsigned int BW_HZ;
-
-   unsigned long long LeftRead() const
-   {
-      unsigned long long Sz = Size - (InP - OutP);
-      if (Sz > Size - (InP%Size))
-	 Sz = Size - (InP%Size);
-      return Sz;
-   }
-   unsigned long long LeftWrite() const
-   {
-      unsigned long long Sz = InP - OutP;
-      if (InP > MaxGet)
-	 Sz = MaxGet - OutP;
-      if (Sz > Size - (OutP%Size))
-	 Sz = Size - (OutP%Size);
-      return Sz;
-   }
-   void FillOut();
-
-   public:
-   Hashes *Hash;
-
-   // Read data in
-   bool Read(int Fd);
-   bool Read(std::string Data);
-
-   // Write data out
-   bool Write(int Fd);
-   bool WriteTillEl(std::string &Data,bool Single = false);
-
-   // Control the write limit
-   void Limit(long long Max) {if (Max == -1) MaxGet = 0-1; else MaxGet = OutP + Max;}
-   bool IsLimit() const {return MaxGet == OutP;};
-   void Print() const {cout << MaxGet << ',' << OutP << endl;};
-
-   // Test for free space in the buffer
-   bool ReadSpace() const {return Size - (InP - OutP) > 0;};
-   bool WriteSpace() const {return InP - OutP > 0;};
-
-   // Dump everything
-   void Reset();
-   void Stats();
-
-   CircleBuf(unsigned long long Size);
-   ~CircleBuf();
-};
-
-struct HttpServerState: public ServerState
+class HttpServerState : public ServerState
 {
-   // This is the connection itself. Output is data FROM the server
-   CircleBuf In;
-   CircleBuf Out;
-   int ServerFd;
-
-   protected:
-   virtual bool ReadHeaderLines(std::string &Data);
-   virtual bool LoadNextResponse(bool const ToFile, FileFd * const File);
-   virtual bool WriteResponse(std::string const &Data);
-
-   public:
-   virtual void Reset() { ServerState::Reset(); ServerFd = -1; };
-
-   virtual bool RunData(FileFd * const File);
-
-   virtual bool Open();
-   virtual bool IsOpen();
-   virtual bool Close();
-   virtual bool InitHashes(FileFd &File);
+protected:
+   virtual bool ReadHeaderLines(std::string &/*Data*/) { return false; }
+   virtual bool LoadNextResponse(bool const /*ToFile*/, FileFd * const /*File*/) { return false; }
+public:
+   virtual bool WriteResponse(std::string const &/*Data*/) { return false; }
+
+   /** \brief Transfer the data from the socket */
+   virtual bool RunData(FileFd * const /*File*/) { return false; }
+
+   virtual bool Open() { return false; }
+   virtual bool IsOpen() { return false; }
+   virtual bool Close() { return false; }
+   virtual bool InitHashes(FileFd &/*File*/);
    virtual Hashes * GetHashes();
-   virtual bool Die(FileFd &File);
-   virtual bool Flush(FileFd * const File);
-   virtual bool Go(bool ToFile, FileFd * const File);
+   virtual bool Die(FileFd &/*File*/) { return false; }
+   virtual bool Flush(FileFd * const /*File*/) { return false; }
+   virtual bool Go(bool /*ToFile*/, FileFd * const /*File*/) { return false; }
 
    HttpServerState(URI Srv, HttpMethod *Owner);
    virtual ~HttpServerState() {Close();};
+   Hashes *Hash;
 };
 
-class HttpMethod : public ServerMethod
+class HttpMethod : public pkgAcqMethod
 {
-   public:
-   virtual void SendReq(FetchItem *Itm);
-
-   virtual bool Configuration(std::string Message);
-
-   virtual ServerState * CreateServerState(URI uri);
-   virtual void RotateDNS();
-
-   protected:
-   std::string AutoDetectProxyCmd;
+   // minimum speed in bytes/se that triggers download timeout handling
+   static const int DL_MIN_SPEED = 10;
+
+public:
+   virtual bool Fetch(FetchItem *);
+private:
+   static size_t parse_header(void *buffer, size_t size, size_t nmemb, void *userp);
+   static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
+   static int progress_callback(void *clientp, double dltotal, double dlnow,
+				double ultotal, double ulnow);
+   void SetupProxy();
+   CURL *curl;
+   URI Proxy;
+   FetchResult Res;
+   HttpServerState *Server;
 
    public:
-   friend struct HttpServerState;
+   FileFd *File;
 
-   HttpMethod() : ServerMethod("1.2",Pipeline | SendConfig)
+   HttpMethod() : pkgAcqMethod("1.2",Pipeline | SendConfig), File(NULL)
    {
       File = 0;
-      Server = 0;
+      curl = curl_easy_init();
+   };
+
+   ~HttpMethod()
+   {
+      curl_easy_cleanup(curl);
    };
 };
 
+#include <apt-pkg/strutl.h>
+
 #endif
diff --git a/methods/http_main.cc b/methods/http_main.cc
index 3b346a5..82c91d9 100644
--- a/methods/http_main.cc
+++ b/methods/http_main.cc
@@ -13,5 +13,5 @@ int main()
    signal(SIGPIPE, SIG_IGN);
 
    HttpMethod Mth;
-   return Mth.Loop();
+   return Mth.Run();
 }
diff --git a/methods/makefile b/methods/makefile
index 6b77812..7c40d52 100644
--- a/methods/makefile
+++ b/methods/makefile
@@ -46,9 +46,9 @@ include $(PROGRAM_H)
 
 # The http method
 PROGRAM=http
-SLIBS = -lapt-pkg $(SOCKETLIBS) $(INTLLIBS)
+SLIBS = -lapt-pkg -lcurl $(SOCKETLIBS) $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
-SOURCE = http.cc http_main.cc rfc2553emu.cc connect.cc server.cc
+SOURCE = http.cc http_main.cc rfc2553emu.cc server.cc
 include $(PROGRAM_H)
 
 # The https method
@@ -81,7 +81,7 @@ include $(PROGRAM_H)
 
 # The mirror method
 PROGRAM=mirror
-SLIBS = -lapt-pkg $(SOCKETLIBS)
+SLIBS = -lapt-pkg -lcurl $(SOCKETLIBS)
 LIB_MAKES = apt-pkg/makefile
 SOURCE = mirror.cc http.cc rfc2553emu.cc connect.cc server.cc
 include $(PROGRAM_H)
diff --git a/methods/mirror.cc b/methods/mirror.cc
index d3aef91..48c7530 100644
--- a/methods/mirror.cc
+++ b/methods/mirror.cc
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: mirror.cc,v 1.59 2004/05/08 19:42:35 mdz Exp $
+// $Id: mirror.cc,v 1.6 2015/01/30 10:37:12 lhw Exp $
 /* ######################################################################
 
    Mirror Acquire Method - This is the Mirror acquire method for APT.
@@ -468,7 +468,7 @@ int main()
 
    MirrorMethod Mth;
 
-   return Mth.Loop();
+   return Mth.Run();
 }
 
 

Reply via email to