// Crc32.cs // // Implements the CRC algorithm, which is used in zip files. The zip format calls for // the zipfile to contain a CRC for the unencrypted byte stream of each file. // // It is based on example source code published at // http://www.vbaccelerator.com/home/net/code/libraries/CRC32/Crc32_zip_CRC32_CRC32_cs.asp // // This implementation adds a tweak of that code for use within zip creation. While // computing the CRC we also compress the byte stream, in the same read loop. This // avoids the need to read through the uncompressed stream twice - once to computer CRC // and another time to compress. // // // Thu, 30 Mar 2006 13:58 // using System; namespace ionic.utils.zip { /// <summary> /// Calculates a 32bit Cyclic Redundancy Checksum (CRC) using the /// same polynomial used by Zip. /// </summary> public class CRC32 { private UInt32[] crc32Table; private const int BUFFER_SIZE = 8192; private Int32 _TotalBytesRead = 0; public Int32 TotalBytesRead { get { return _TotalBytesRead; } } /// <summary> /// Returns the CRC32 for the specified stream. /// </summary> /// <param name="input">The stream over which to calculate the CRC32</param> /// <returns>the CRC32 calculation</returns> public UInt32 GetCrc32(System.IO.Stream input) { return GetCrc32AndCopy(input, null); } /// <summary> /// Returns the CRC32 for the specified stream, and writes the input into the output stream. /// </summary> /// <param name="input">The stream over which to calculate the CRC32</param> /// <param name="output">The stream into which to deflate the input</param> /// <returns>the CRC32 calculation</returns> public UInt32 GetCrc32AndCopy(System.IO.Stream input, System.IO.Stream output) { unchecked { UInt32 crc32Result; crc32Result = 0xFFFFFFFF; byte[] buffer = new byte[BUFFER_SIZE]; int readSize = BUFFER_SIZE; _TotalBytesRead = 0; int count = input.Read(buffer, 0, readSize); if (output != null) output.Write(buffer, 0, count); _TotalBytesRead += count; while (count > 0) { for (int i = 0; i < count; i++) { crc32Result = ((crc32Result) >> 8) ^ crc32Table[(buffer[i]) ^ ((crc32Result) & 0x000000FF)]; } count = input.Read(buffer, 0, readSize); if (output != null) output.Write(buffer, 0, count); _TotalBytesRead += count; } return ~crc32Result; } } /// <summary> /// Construct an instance of the CRC32 class, pre-initialising the table /// for speed of lookup. /// </summary> public CRC32() { unchecked { // This is the official polynomial used by CRC32 in PKZip. // Often the polynomial is shown reversed as 0x04C11DB7. UInt32 dwPolynomial = 0xEDB88320; UInt32 i, j; crc32Table = new UInt32[256]; UInt32 dwCrc; for (i = 0; i < 256; i++) { dwCrc = i; for (j = 8; j > 0; j--) { if ((dwCrc & 1) == 1) { dwCrc = (dwCrc >> 1) ^ dwPolynomial; } else { dwCrc >>= 1; } } crc32Table[i] = dwCrc; } } } } }