Zip.cs
上传用户:huiyue
上传日期:2022-04-08
资源大小:1429k
文件大小:51k
源码类别:

搜索引擎

开发平台:

ASP/ASPX

  1. // Zip.cs
  2. //
  3. // Copyright (c) 2006, 2007 Microsoft Corporation.  All rights reserved.
  4. //
  5. // 
  6. // This class library reads and writes zip files, according to the format
  7. // described by pkware, at:
  8. // http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
  9. //
  10. // This implementation is based on the
  11. // System.IO.Compression.DeflateStream base class in the .NET Framework
  12. // v2.0 base class library.
  13. //
  14. // There are other Zip class libraries available.  For example, it is
  15. // possible to read and write zip files within .NET via the J# runtime.
  16. // But some people don't like to install the extra DLL.  Also, there is
  17. // a 3rd party LGPL-based (or is it GPL?) library called SharpZipLib,
  18. // which works, in both .NET 1.1 and .NET 2.0.  But some people don't
  19. // like the GPL. Finally, there are commercial tools (From ComponentOne,
  20. // XCeed, etc).  But some people don't want to incur the cost.
  21. //
  22. // This alternative implementation is not GPL licensed, is free of cost,
  23. // and does not require J#. It does require .NET 2.0 (for the DeflateStream 
  24. // class).  
  25. // 
  26. // This code is released under the Microsoft Permissive License of OCtober 2006. 
  27. // See the License.txt for details.  
  28. //
  29. // Notes:
  30. // This is at best a cripppled and naive implementation. 
  31. //
  32. // Bugs:
  33. // 1. does not do 0..9 compression levels (not supported by DeflateStream)
  34. // 2. does not do encryption
  35. // 3. no support for reading or writing multi-disk zip archives
  36. // 4. no support for file comments or archive comments
  37. // 5. does not stream as it compresses; all compressed data is kept in memory.
  38. // 6. no support for double-byte chars in filenames
  39. // 7. no support for asynchronous operation
  40. // 
  41. // But it does read and write basic zip files, and it gets reasonable compression. 
  42. //
  43. // NB: PKWare's zip specification states: 
  44. //
  45. // ----------------------
  46. //   PKWARE is committed to the interoperability and advancement of the
  47. //   .ZIP format.  PKWARE offers a free license for certain technological
  48. //   aspects described above under certain restrictions and conditions.
  49. //   However, the use or implementation in a product of certain technological
  50. //   aspects set forth in the current APPNOTE, including those with regard to
  51. //   strong encryption or patching, requires a license from PKWARE.  Please 
  52. //   contact PKWARE with regard to acquiring a license.
  53. // ----------------------
  54. //    
  55. // Fri, 31 Mar 2006  14:43
  56. //
  57. // update Thu, 22 Feb 2007  19:03
  58. //  Fixed a problem with archives that had bit-3 (0x0008) set, 
  59. //  where the CRC, Compressed Size, and Uncompressed size 
  60. //  actually followed the compressed file data. 
  61. //
  62. using System;
  63. namespace ionic.utils.zip
  64. {
  65.     class Shared
  66.     {
  67.         protected internal static string StringFromBuffer(byte[] buf, int start, int maxlength)
  68.         {
  69.             int i;
  70.             char[] c = new char[maxlength];
  71.             for (i = 0; (i < maxlength) && (i < buf.Length) && (buf[i] != 0); i++)
  72.             {
  73.                 c[i] = (char)buf[i]; // System.BitConverter.ToChar(buf, start+i*2);
  74.             }
  75.             string s = new System.String(c, 0, i);
  76.             return s;
  77.         }
  78.         protected internal static int ReadSignature(System.IO.Stream s)
  79.         {
  80.             int n = 0;
  81.             byte[] sig = new byte[4];
  82.             n = s.Read(sig, 0, sig.Length);
  83.             if (n != sig.Length) throw new Exception("Could not read signature - no data!");
  84.             int signature = (((sig[3] * 256 + sig[2]) * 256) + sig[1]) * 256 + sig[0];
  85.             return signature;
  86.         }
  87.         protected internal static long FindSignature(System.IO.Stream s, int SignatureToFind)
  88.         {
  89.             long startingPosition = s.Position;
  90.             int BATCH_SIZE = 1024;
  91.             byte[] targetBytes = new byte[4];
  92.             targetBytes[0] = (byte) (SignatureToFind >> 24);
  93.             targetBytes[1] = (byte) ((SignatureToFind & 0x00FF0000) >> 16);
  94.             targetBytes[2] = (byte) ((SignatureToFind & 0x0000FF00) >> 8);
  95.             targetBytes[3] = (byte) (SignatureToFind & 0x000000FF);
  96.             byte[] batch = new byte[BATCH_SIZE];
  97.             int n = 0;
  98.             bool success = false;
  99.             do
  100.             {
  101.                 n = s.Read(batch, 0, batch.Length);
  102.                 if (n != 0)
  103.                 {
  104.                     for (int i = 0; i < n; i++)
  105.                     {
  106.                         if (batch[i] == targetBytes[3])
  107.                         {
  108.                             s.Seek(i - n, System.IO.SeekOrigin.Current);
  109.                             int sig = ReadSignature(s);
  110.                             success = (sig == SignatureToFind);
  111.                             if (!success) s.Seek(-3, System.IO.SeekOrigin.Current);
  112.                             break; // out of for loop
  113.                         }
  114.                     }
  115.                 }
  116.                 else break;
  117.                 if (success) break;
  118.             } while (true);
  119.             if (!success)
  120.             {
  121.                 s.Seek(startingPosition, System.IO.SeekOrigin.Begin);
  122.                 return -1;  // or throw?
  123.             }
  124.             // subtract 4 for the signature.
  125.             long bytesRead = (s.Position - startingPosition) - 4 ;
  126.             // number of bytes read, should be the same as compressed size of file            
  127.             return bytesRead;   
  128.         }
  129.         protected internal static DateTime PackedToDateTime(Int32 packedDateTime)
  130.         {
  131.             Int16 packedTime = (Int16)(packedDateTime & 0x0000ffff);
  132.             Int16 packedDate = (Int16)((packedDateTime & 0xffff0000) >> 16);
  133.             int year = 1980 + ((packedDate & 0xFE00) >> 9);
  134.             int month = (packedDate & 0x01E0) >> 5;
  135.             int day = packedDate & 0x001F;
  136.             int hour = (packedTime & 0xF800) >> 11;
  137.             int minute = (packedTime & 0x07E0) >> 5;
  138.             int second = packedTime & 0x001F;
  139.             DateTime d = System.DateTime.Now;
  140.             try { d = new System.DateTime(year, month, day, hour, minute, second, 0); }
  141.             catch
  142.             {
  143.                 Console.Write("nInvalid date/time?:nyear: {0} ", year);
  144.                 Console.Write("month: {0} ", month);
  145.                 Console.WriteLine("day: {0} ", day);
  146.                 Console.WriteLine("HH:MM:SS= {0}:{1}:{2}", hour, minute, second);
  147.             }
  148.             return d;
  149.         }
  150.         protected internal static Int32 DateTimeToPacked(DateTime time)
  151.         {
  152.             UInt16 packedDate = (UInt16)((time.Day & 0x0000001F) | ((time.Month << 5) & 0x000001E0) | (((time.Year - 1980) << 9) & 0x0000FE00));
  153.             UInt16 packedTime = (UInt16)((time.Second & 0x0000001F) | ((time.Minute << 5) & 0x000007E0) | ((time.Hour << 11) & 0x0000F800));
  154.             return (Int32)(((UInt32)(packedDate << 16)) | packedTime);
  155.         }
  156.     }
  157.     public class ZipDirEntry
  158.     {
  159.         internal const int ZipDirEntrySignature = 0x02014b50;
  160.         private bool _Debug = false;
  161.         private ZipDirEntry() { }
  162.         private DateTime _LastModified;
  163.         public DateTime LastModified
  164.         {
  165.             get { return _LastModified; }
  166.         }
  167.         private string _FileName;
  168.         public string FileName
  169.         {
  170.             get { return _FileName; }
  171.         }
  172.         private string _Comment;
  173.         public string Comment
  174.         {
  175.             get { return _Comment; }
  176.         }
  177.         private Int16 _VersionMadeBy;
  178.         public Int16 VersionMadeBy
  179.         {
  180.             get { return _VersionMadeBy; }
  181.         }
  182.         private Int16 _VersionNeeded;
  183.         public Int16 VersionNeeded
  184.         {
  185.             get { return _VersionNeeded; }
  186.         }
  187.         private Int16 _CompressionMethod;
  188.         public Int16 CompressionMethod
  189.         {
  190.             get { return _CompressionMethod; }
  191.         }
  192.         private Int32 _CompressedSize;
  193.         public Int32 CompressedSize
  194.         {
  195.             get { return _CompressedSize; }
  196.         }
  197.         private Int32 _UncompressedSize;
  198.         public Int32 UncompressedSize
  199.         {
  200.             get { return _UncompressedSize; }
  201.         }
  202.         public Double CompressionRatio
  203.         {
  204.             get
  205.             {
  206.                 return 100 * (1.0 - (1.0 * CompressedSize) / (1.0 * UncompressedSize));
  207.             }
  208.         }
  209.         private Int16 _BitField;
  210.         private Int32 _LastModDateTime;
  211.         private Int32 _Crc32;
  212.         private byte[] _Extra;
  213.         internal ZipDirEntry(ZipEntry ze) { }
  214.         public static ZipDirEntry Read(System.IO.Stream s)
  215.         {
  216.             return Read(s, false);
  217.         }
  218.         public static ZipDirEntry Read(System.IO.Stream s, bool TurnOnDebug)
  219.         {
  220.             int signature = ionic.utils.zip.Shared.ReadSignature(s);
  221.             // return null if this is not a local file header signature
  222.             if (SignatureIsNotValid(signature))
  223.             {
  224.                 s.Seek(-4, System.IO.SeekOrigin.Current);
  225.                 if (TurnOnDebug) System.Console.WriteLine("  ZipDirEntry::Read(): Bad signature ({0:X8}) at position {1}", signature, s.Position);
  226.                 return null;
  227.             }
  228.             byte[] block = new byte[42];
  229.             int n = s.Read(block, 0, block.Length);
  230.             if (n != block.Length) return null;
  231.             int i = 0;
  232.             ZipDirEntry zde = new ZipDirEntry();
  233.             zde._Debug = TurnOnDebug;
  234.             zde._VersionMadeBy = (short)(block[i++] + block[i++] * 256);
  235.             zde._VersionNeeded = (short)(block[i++] + block[i++] * 256);
  236.             zde._BitField = (short)(block[i++] + block[i++] * 256);
  237.             zde._CompressionMethod = (short)(block[i++] + block[i++] * 256);
  238.             zde._LastModDateTime = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  239.             zde._Crc32 = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  240.             zde._CompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  241.             zde._UncompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  242.             zde._LastModified = ionic.utils.zip.Shared.PackedToDateTime(zde._LastModDateTime);
  243.             Int16 filenameLength = (short)(block[i++] + block[i++] * 256);
  244.             Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256);
  245.             Int16 commentLength = (short)(block[i++] + block[i++] * 256);
  246.             Int16 diskNumber = (short)(block[i++] + block[i++] * 256);
  247.             Int16 internalFileAttrs = (short)(block[i++] + block[i++] * 256);
  248.             Int32 externalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  249.             Int32 Offset = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  250.             block = new byte[filenameLength];
  251.             n = s.Read(block, 0, block.Length);
  252.             zde._FileName = ionic.utils.zip.Shared.StringFromBuffer(block, 0, block.Length);
  253.             zde._Extra = new byte[extraFieldLength];
  254.             n = s.Read(zde._Extra, 0, zde._Extra.Length);
  255.             block = new byte[commentLength];
  256.             n = s.Read(block, 0, block.Length);
  257.             zde._Comment = ionic.utils.zip.Shared.StringFromBuffer(block, 0, block.Length);
  258.             return zde;
  259.         }
  260.         private static bool SignatureIsNotValid(int signature)
  261.         {
  262.             return (signature != ZipDirEntrySignature);
  263.         }
  264.     }
  265.     public class ZipEntry
  266.     {
  267.         private const int ZipEntrySignature = 0x04034b50;
  268.         private const int ZipEntryDataDescriptorSignature= 0x08074b50;
  269.  
  270.         private bool _Debug = false;
  271.         private DateTime _LastModified;
  272.         public DateTime LastModified
  273.         {
  274.             get { return _LastModified; }
  275.         }
  276.         private string _FileName;
  277.         public string FileName
  278.         {
  279.             get { return _FileName; }
  280.         }
  281.         private Int16 _VersionNeeded;
  282.         public Int16 VersionNeeded
  283.         {
  284.             get { return _VersionNeeded; }
  285.         }
  286.         private Int16 _BitField;
  287.         public Int16 BitField
  288.         {
  289.             get { return _BitField; }
  290.         }
  291.         private Int16 _CompressionMethod;
  292.         public Int16 CompressionMethod
  293.         {
  294.             get { return _CompressionMethod; }
  295.         }
  296.         private Int32 _CompressedSize;
  297.         public Int32 CompressedSize
  298.         {
  299.             get { return _CompressedSize; }
  300.         }
  301.         private Int32 _UncompressedSize;
  302.         public Int32 UncompressedSize
  303.         {
  304.             get { return _UncompressedSize; }
  305.         }
  306.         public Double CompressionRatio
  307.         {
  308.             get
  309.             {
  310.                 return 100 * (1.0 - (1.0 * CompressedSize) / (1.0 * UncompressedSize));
  311.             }
  312.         }
  313.         private Int32 _LastModDateTime;
  314.         private Int32 _Crc32;
  315.         private byte[] _Extra;
  316.         private byte[] __filedata;
  317.         private byte[] _FileData
  318.         {
  319.             get
  320.             {
  321.                 if (__filedata == null)
  322.                 {
  323.                 }
  324.                 return __filedata;
  325.             }
  326.         }
  327.         private System.IO.MemoryStream _UnderlyingMemoryStream;
  328.         private System.IO.Compression.DeflateStream _CompressedStream;
  329.         private System.IO.Compression.DeflateStream CompressedStream
  330.         {
  331.             get
  332.             {
  333.                 if (_CompressedStream == null)
  334.                 {
  335.                     _UnderlyingMemoryStream = new System.IO.MemoryStream();
  336.                     bool LeaveUnderlyingStreamOpen = true;
  337.                     _CompressedStream = new System.IO.Compression.DeflateStream(_UnderlyingMemoryStream,
  338.                                                     System.IO.Compression.CompressionMode.Compress,
  339.                                                     LeaveUnderlyingStreamOpen);
  340.                 }
  341.                 return _CompressedStream;
  342.             }
  343.         }
  344.         private byte[] _header;
  345.         internal byte[] Header
  346.         {
  347.             get
  348.             {
  349.                 return _header;
  350.             }
  351.         }
  352.         private int _RelativeOffsetOfHeader;
  353.         private static bool ReadHeader(System.IO.Stream s, ZipEntry ze)
  354.         {
  355.             int signature = ionic.utils.zip.Shared.ReadSignature(s);
  356.             // return null if this is not a local file header signature
  357.             if (SignatureIsNotValid(signature))
  358.             {
  359.                 s.Seek(-4, System.IO.SeekOrigin.Current);
  360.                 if (ze._Debug) System.Console.WriteLine("  ZipEntry::Read(): Bad signature ({0:X8}) at position {1}", signature, s.Position);
  361.                 return false;
  362.             }
  363.             byte[] block = new byte[26];
  364.             int n = s.Read(block, 0, block.Length);
  365.             if (n != block.Length) return false;
  366.             int i = 0;
  367.             ze._VersionNeeded = (short)(block[i++] + block[i++] * 256);
  368.             ze._BitField = (short)(block[i++] + block[i++] * 256);
  369.             ze._CompressionMethod = (short)(block[i++] + block[i++] * 256);
  370.             ze._LastModDateTime = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  371.             // the PKZIP spec says that if bit 3 is set (0x0008), then the CRC, Compressed size, and uncompressed size
  372.             // come directly after the file data.  The only way to find it is to scan the zip archive for the signature of 
  373.             // the Data Descriptor, and presume that that signature does not appear in the (compressed) data of the compressed file.  
  374.             if ((ze._BitField & 0x0008) != 0x0008)
  375.             {
  376.                 ze._Crc32 = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  377.                 ze._CompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  378.                 ze._UncompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  379.             }
  380.             else
  381.             {
  382.                 // the CRC, compressed size, and uncompressed size are stored later in the stream.
  383.                 // here, we advance the pointer.
  384.                 i += 12;
  385.             }
  386.             Int16 filenameLength = (short)(block[i++] + block[i++] * 256);
  387.             Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256);
  388.             block = new byte[filenameLength];
  389.             n = s.Read(block, 0, block.Length);
  390.             ze._FileName = ionic.utils.zip.Shared.StringFromBuffer(block, 0, block.Length);
  391.             ze._Extra = new byte[extraFieldLength];
  392.             n = s.Read(ze._Extra, 0, ze._Extra.Length);
  393.             // transform the time data into something usable
  394.             ze._LastModified = ionic.utils.zip.Shared.PackedToDateTime(ze._LastModDateTime);
  395.             // actually get the compressed size and CRC if necessary
  396.             if ((ze._BitField & 0x0008) == 0x0008)
  397.             {
  398.                 long posn = s.Position;
  399.                 long SizeOfDataRead = ionic.utils.zip.Shared.FindSignature(s, ZipEntryDataDescriptorSignature);
  400.                 if (SizeOfDataRead == -1) return false; 
  401.                 // read 3x 4-byte fields (CRC, Compressed Size, Uncompressed Size)
  402.                 block = new byte[12];
  403.                 n = s.Read(block, 0, block.Length);
  404.                 if (n != 12) return false;
  405.                 i = 0;
  406.                 ze._Crc32 = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  407.                 ze._CompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  408.                 ze._UncompressedSize = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
  409.                 if (SizeOfDataRead != ze._CompressedSize)
  410.                     throw new Exception("Data format error (bit 3 is set)"); 
  411.                 
  412.                 // seek back to previous position, to read file data
  413.                 s.Seek(posn, System.IO.SeekOrigin.Begin);
  414.             }
  415.             return true;
  416.         }
  417.         private static bool SignatureIsNotValid(int signature)
  418.         {
  419.             return (signature != ZipEntrySignature);
  420.         }
  421.         public static ZipEntry Read(System.IO.Stream s)
  422.         {
  423.             return Read(s, false);
  424.         }
  425.         public static ZipEntry Read(System.IO.Stream s, bool TurnOnDebug)
  426.         {
  427.             ZipEntry entry = new ZipEntry();
  428.             entry._Debug = TurnOnDebug;
  429.             if (!ReadHeader(s, entry)) return null;
  430.             entry.__filedata = new byte[entry.CompressedSize];
  431.             int n = s.Read(entry._FileData, 0, entry._FileData.Length);
  432.             if (n != entry._FileData.Length)
  433.             {
  434.                 throw new Exception("badly formatted zip file.");
  435.             }
  436.             // finally, seek past the (already read) Data descriptor if necessary
  437.             if ((entry._BitField & 0x0008) == 0x0008)
  438.             {
  439.                 s.Seek(16, System.IO.SeekOrigin.Current);
  440.             }
  441.             return entry;
  442.         }
  443.         internal static ZipEntry Create(String filename)
  444.         {
  445.             ZipEntry entry = new ZipEntry();
  446.             entry._FileName = filename;
  447.             entry._LastModified = System.IO.File.GetLastWriteTime(filename);
  448.             if (entry._LastModified.IsDaylightSavingTime())
  449.             {
  450.                 System.DateTime AdjustedTime = entry._LastModified - new System.TimeSpan(1, 0, 0);
  451.                 entry._LastModDateTime = ionic.utils.zip.Shared.DateTimeToPacked(AdjustedTime);
  452.             }
  453.             else
  454.                 entry._LastModDateTime = ionic.utils.zip.Shared.DateTimeToPacked(entry._LastModified);
  455.             // we don't actually slurp in the file until the caller invokes Write on this entry.
  456.             return entry;
  457.         }
  458.         public void Extract()
  459.         {
  460.             Extract(".");
  461.         }
  462.         public void Extract(System.IO.Stream s)
  463.         {
  464.             Extract(null, s);
  465.         }
  466.         public void Extract(string basedir)
  467.         {
  468.             Extract(basedir, null);
  469.         }
  470.         // pass in either basdir or s, but not both. 
  471.         private void Extract(string basedir, System.IO.Stream s)
  472.         {
  473.             string TargetFile = null;
  474.             if (basedir != null)
  475.             {
  476.                 TargetFile = System.IO.Path.Combine(basedir, FileName);
  477.                 // check if a directory
  478.                 if (FileName.EndsWith("/"))
  479.                 {
  480.                     if (!System.IO.Directory.Exists(TargetFile))
  481.                         System.IO.Directory.CreateDirectory(TargetFile);
  482.                     return;
  483.                 }
  484.             }
  485.             else if (s != null)
  486.             {
  487.                 if (FileName.EndsWith("/"))
  488.                     // extract a directory to streamwriter?  nothing to do!
  489.                     return;
  490.             }
  491.             else throw new Exception("Invalid input.");
  492.             using (System.IO.MemoryStream memstream = new System.IO.MemoryStream(_FileData))
  493.             {
  494.                 System.IO.Stream input = null;
  495.                 try
  496.                 {
  497.                     if (CompressedSize == UncompressedSize)
  498.                     {
  499.                         // the System.IO.Compression.DeflateStream class does not handle uncompressed data.
  500.                         // so if an entry is not compressed, then we just translate the bytes directly.
  501.                         input = memstream;
  502.                     }
  503.                     else
  504.                     {
  505.                         input = new System.IO.Compression.DeflateStream(memstream, System.IO.Compression.CompressionMode.Decompress);
  506.                     }
  507.                     if (TargetFile != null)
  508.                     {
  509.                         // ensure the target path exists
  510.                         if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(TargetFile)))
  511.                         {
  512.                             System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(TargetFile));
  513.                         }
  514.                     }
  515.                     System.IO.Stream output = null;
  516.                     try
  517.                     {
  518.                         if (TargetFile != null)
  519.                             output = new System.IO.FileStream(TargetFile, System.IO.FileMode.CreateNew);
  520.                         else
  521.                             output = s;
  522.                         byte[] bytes = new byte[4096];
  523.                         int n;
  524.                         if (_Debug)
  525.                         {
  526.                             Console.WriteLine("{0}: _FileData.Length= {1}", TargetFile, _FileData.Length);
  527.                             Console.WriteLine("{0}: memstream.Position: {1}", TargetFile, memstream.Position);
  528.                             n = _FileData.Length;
  529.                             if (n > 1000)
  530.                             {
  531.                                 n = 500;
  532.                                 Console.WriteLine("{0}: truncating dump from {1} to {2} bytes...", TargetFile, _FileData.Length, n);
  533.                             }
  534.                             for (int j = 0; j < n; j += 2)
  535.                             {
  536.                                 if ((j > 0) && (j % 40 == 0))
  537.                                     System.Console.WriteLine();
  538.                                 System.Console.Write(" {0:X2}", _FileData[j]);
  539.                                 if (j + 1 < n)
  540.                                     System.Console.Write("{0:X2}", _FileData[j + 1]);
  541.                             }
  542.                             System.Console.WriteLine("n");
  543.                         }
  544.                         n = 1; // anything non-zero
  545.                         while (n != 0)
  546.                         {
  547.                             if (_Debug) Console.WriteLine("{0}: about to read...", TargetFile);
  548.                             n = input.Read(bytes, 0, bytes.Length);
  549.                             if (_Debug) Console.WriteLine("{0}: got {1} bytes", TargetFile, n);
  550.                             if (n > 0)
  551.                             {
  552.                                 if (_Debug) Console.WriteLine("{0}: about to write...", TargetFile);
  553.                                 output.Write(bytes, 0, n);
  554.                             }
  555.                         }
  556.                     }
  557.                     finally
  558.                     {
  559.                         // we only close the output stream if we opened it. 
  560.                         if ((output != null) && (TargetFile != null))
  561.                         {
  562.                             output.Close();
  563.                             output.Dispose();
  564.                         }
  565.                     }
  566.                     if (TargetFile != null)
  567.                     {
  568.                         // We may have to adjust the last modified time to compensate
  569.                         // for differences in how the .NET Base Class Library deals
  570.                         // with daylight saving time (DST) versus how the Windows
  571.                         // filesystem deals with daylight saving time.
  572.                         if (LastModified.IsDaylightSavingTime())
  573.                         {
  574.                             DateTime AdjustedLastModified = LastModified + new System.TimeSpan(1, 0, 0);
  575.                             System.IO.File.SetLastWriteTime(TargetFile, AdjustedLastModified);
  576.                         }
  577.                         else
  578.                             System.IO.File.SetLastWriteTime(TargetFile, LastModified);
  579.                     }
  580.                 }
  581.                 finally
  582.                 {
  583.                     // we cannot use using() here because in some cases we do not want to Dispose the stream
  584.                     if ((input != null) && (input != memstream))
  585.                     {
  586.                         input.Close();
  587.                         input.Dispose();
  588.                     }
  589.                 }
  590.             }
  591.         }
  592.         internal void WriteCentralDirectoryEntry(System.IO.Stream s)
  593.         {
  594.             byte[] bytes = new byte[4096];
  595.             int i = 0;
  596.             // signature
  597.             bytes[i++] = (byte)(ZipDirEntry.ZipDirEntrySignature & 0x000000FF);
  598.             bytes[i++] = (byte)((ZipDirEntry.ZipDirEntrySignature & 0x0000FF00) >> 8);
  599.             bytes[i++] = (byte)((ZipDirEntry.ZipDirEntrySignature & 0x00FF0000) >> 16);
  600.             bytes[i++] = (byte)((ZipDirEntry.ZipDirEntrySignature & 0xFF000000) >> 24);
  601.             // Version Made By
  602.             bytes[i++] = Header[4];
  603.             bytes[i++] = Header[5];
  604.             // Version Needed, Bitfield, compression method, lastmod,
  605.             // crc, sizes, filename length and extra field length -
  606.             // are all the same as the local file header. So just copy them
  607.             int j = 0;
  608.             for (j = 0; j < 26; j++)
  609.                 bytes[i + j] = Header[4 + j];
  610.             i += j;  // positioned at next available byte
  611.             // File Comment Length
  612.             bytes[i++] = 0;
  613.             bytes[i++] = 0;
  614.             // Disk number start
  615.             bytes[i++] = 0;
  616.             bytes[i++] = 0;
  617.             // internal file attrs
  618.             // TODO: figure out what is required here. 
  619.             bytes[i++] = 1;
  620.             bytes[i++] = 0;
  621.             // external file attrs
  622.             // TODO: figure out what is required here. 
  623.             bytes[i++] = 0x20;
  624.             bytes[i++] = 0;
  625.             bytes[i++] = 0xb6;
  626.             bytes[i++] = 0x81;
  627.             // relative offset of local header (I think this can be zero)
  628.             bytes[i++] = (byte)(_RelativeOffsetOfHeader & 0x000000FF);
  629.             bytes[i++] = (byte)((_RelativeOffsetOfHeader & 0x0000FF00) >> 8);
  630.             bytes[i++] = (byte)((_RelativeOffsetOfHeader & 0x00FF0000) >> 16);
  631.             bytes[i++] = (byte)((_RelativeOffsetOfHeader & 0xFF000000) >> 24);
  632.             if (_Debug) System.Console.WriteLine("ninserting filename into CDS: (length= {0})", Header.Length - 30);
  633.             // actual filename (starts at offset 34 in header) 
  634.             for (j = 0; j < Header.Length - 30; j++)
  635.             {
  636.                 bytes[i + j] = Header[30 + j];
  637.                 if (_Debug) System.Console.Write(" {0:X2}", bytes[i + j]);
  638.             }
  639.             if (_Debug) System.Console.WriteLine();
  640.             i += j;
  641.             s.Write(bytes, 0, i);
  642.         }
  643.         private void WriteHeader(System.IO.Stream s, byte[] bytes)
  644.         {
  645.             // write the header info
  646.             int i = 0;
  647.             // signature
  648.             bytes[i++] = (byte)(ZipEntrySignature & 0x000000FF);
  649.             bytes[i++] = (byte)((ZipEntrySignature & 0x0000FF00) >> 8);
  650.             bytes[i++] = (byte)((ZipEntrySignature & 0x00FF0000) >> 16);
  651.             bytes[i++] = (byte)((ZipEntrySignature & 0xFF000000) >> 24);
  652.             // version needed
  653.             Int16 FixedVersionNeeded = 0x14; // from examining existing zip files
  654.             bytes[i++] = (byte)(FixedVersionNeeded & 0x00FF);
  655.             bytes[i++] = (byte)((FixedVersionNeeded & 0xFF00) >> 8);
  656.             // bitfield
  657.             Int16 BitField = 0x00; // from examining existing zip files
  658.             bytes[i++] = (byte)(BitField & 0x00FF);
  659.             bytes[i++] = (byte)((BitField & 0xFF00) >> 8);
  660.             // compression method
  661.             Int16 CompressionMethod = 0x08; // 0x08 = Deflate
  662.             bytes[i++] = (byte)(CompressionMethod & 0x00FF);
  663.             bytes[i++] = (byte)((CompressionMethod & 0xFF00) >> 8);
  664.             // LastMod
  665.             bytes[i++] = (byte)(_LastModDateTime & 0x000000FF);
  666.             bytes[i++] = (byte)((_LastModDateTime & 0x0000FF00) >> 8);
  667.             bytes[i++] = (byte)((_LastModDateTime & 0x00FF0000) >> 16);
  668.             bytes[i++] = (byte)((_LastModDateTime & 0xFF000000) >> 24);
  669.             // CRC32 (Int32)
  670.             CRC32 crc32 = new CRC32();
  671.             UInt32 crc = 0;
  672.             using (System.IO.Stream input = System.IO.File.OpenRead(FileName))
  673.             {
  674.                 crc = crc32.GetCrc32AndCopy(input, CompressedStream);
  675.             }
  676.             CompressedStream.Close();  // to get the footer bytes written to the underlying stream
  677.             bytes[i++] = (byte)(crc & 0x000000FF);
  678.             bytes[i++] = (byte)((crc & 0x0000FF00) >> 8);
  679.             bytes[i++] = (byte)((crc & 0x00FF0000) >> 16);
  680.             bytes[i++] = (byte)((crc & 0xFF000000) >> 24);
  681.             // CompressedSize (Int32)
  682.             Int32 isz = (Int32)_UnderlyingMemoryStream.Length;
  683.             UInt32 sz = (UInt32)isz;
  684.             bytes[i++] = (byte)(sz & 0x000000FF);
  685.             bytes[i++] = (byte)((sz & 0x0000FF00) >> 8);
  686.             bytes[i++] = (byte)((sz & 0x00FF0000) >> 16);
  687.             bytes[i++] = (byte)((sz & 0xFF000000) >> 24);
  688.             // UncompressedSize (Int32)
  689.             if (_Debug) System.Console.WriteLine("Uncompressed Size: {0}", crc32.TotalBytesRead);
  690.             bytes[i++] = (byte)(crc32.TotalBytesRead & 0x000000FF);
  691.             bytes[i++] = (byte)((crc32.TotalBytesRead & 0x0000FF00) >> 8);
  692.             bytes[i++] = (byte)((crc32.TotalBytesRead & 0x00FF0000) >> 16);
  693.             bytes[i++] = (byte)((crc32.TotalBytesRead & 0xFF000000) >> 24);
  694.             // filename length (Int16)
  695.             Int16 length = (Int16)FileName.Length;
  696.             bytes[i++] = (byte)(length & 0x00FF);
  697.             bytes[i++] = (byte)((length & 0xFF00) >> 8);
  698.             // extra field length (short)
  699.             Int16 ExtraFieldLength = 0x00;
  700.             bytes[i++] = (byte)(ExtraFieldLength & 0x00FF);
  701.             bytes[i++] = (byte)((ExtraFieldLength & 0xFF00) >> 8);
  702.             // actual filename
  703.             char[] c = FileName.ToCharArray();
  704.             int j = 0;
  705.             if (_Debug)
  706.             {
  707.                 System.Console.WriteLine("local header: writing filename, {0} chars", c.Length);
  708.                 System.Console.WriteLine("starting offset={0}", i);
  709.             }
  710.             for (j = 0; (j < c.Length) && (i + j < bytes.Length); j++)
  711.             {
  712.                 bytes[i + j] = System.BitConverter.GetBytes(c[j])[0];
  713.                 if (_Debug) System.Console.Write(" {0:X2}", bytes[i + j]);
  714.             }
  715.             if (_Debug) System.Console.WriteLine();
  716.             i += j;
  717.             // extra field (we always write null in this implementation)
  718.             // ;;
  719.             // remember the file offset of this header
  720.             _RelativeOffsetOfHeader = (int)s.Length;
  721.             if (_Debug)
  722.             {
  723.                 System.Console.WriteLine("nAll header data:");
  724.                 for (j = 0; j < i; j++)
  725.                     System.Console.Write(" {0:X2}", bytes[j]);
  726.                 System.Console.WriteLine();
  727.             }
  728.             // finally, write the header to the stream
  729.             s.Write(bytes, 0, i);
  730.             // preserve this header data for use with the central directory structure.
  731.             _header = new byte[i];
  732.             if (_Debug) System.Console.WriteLine("preserving header of {0} bytes", _header.Length);
  733.             for (j = 0; j < i; j++)
  734.                 _header[j] = bytes[j];
  735.         }
  736.         internal void Write(System.IO.Stream s)
  737.         {
  738.             byte[] bytes = new byte[4096];
  739.             int n;
  740.             // write the header:
  741.             WriteHeader(s, bytes);
  742.             // write the actual file data: 
  743.             _UnderlyingMemoryStream.Position = 0;
  744.             if (_Debug)
  745.             {
  746.                 Console.WriteLine("{0}: writing compressed data to zipfile...", FileName);
  747.                 Console.WriteLine("{0}: total data length: {1}", FileName, _UnderlyingMemoryStream.Length);
  748.             }
  749.             while ((n = _UnderlyingMemoryStream.Read(bytes, 0, bytes.Length)) != 0)
  750.             {
  751.                 if (_Debug)
  752.                 {
  753.                     Console.WriteLine("{0}: transferring {1} bytes...", FileName, n);
  754.                     for (int j = 0; j < n; j += 2)
  755.                     {
  756.                         if ((j > 0) && (j % 40 == 0))
  757.                             System.Console.WriteLine();
  758.                         System.Console.Write(" {0:X2}", bytes[j]);
  759.                         if (j + 1 < n)
  760.                             System.Console.Write("{0:X2}", bytes[j + 1]);
  761.                     }
  762.                     System.Console.WriteLine("n");
  763.                 }
  764.                 s.Write(bytes, 0, n);
  765.             }
  766.             //_CompressedStream.Close();
  767.             //_CompressedStream= null;
  768.             _UnderlyingMemoryStream.Close();
  769.             _UnderlyingMemoryStream = null;
  770.         }
  771.     }
  772.     public class ZipFile : System.Collections.Generic.IEnumerable<ZipEntry>,
  773.       IDisposable
  774.     {
  775.         private string _name;
  776.         public string Name
  777.         {
  778.             get { return _name; }
  779.         }
  780.         private System.IO.Stream ReadStream
  781.         {
  782.             get
  783.             {
  784.                 if (_readstream == null)
  785.                 {
  786.                     _readstream = System.IO.File.OpenRead(_name);
  787.                 }
  788.                 return _readstream;
  789.             }
  790.         }
  791.         private System.IO.FileStream WriteStream
  792.         {
  793.             get
  794.             {
  795.                 if (_writestream == null)
  796.                 {
  797.                     _writestream = new System.IO.FileStream(_name, System.IO.FileMode.CreateNew);
  798.                 }
  799.                 return _writestream;
  800.             }
  801.         }
  802.         private ZipFile() { }
  803.         #region For Writing Zip Files
  804.         public ZipFile(string NewZipFileName)
  805.         {
  806.             // create a new zipfile
  807.             _name = NewZipFileName;
  808.             if (System.IO.File.Exists(_name))
  809.                 throw new System.Exception(String.Format("That file ({0}) already exists.", NewZipFileName));
  810.             _entries = new System.Collections.Generic.List<ZipEntry>();
  811.         }
  812.         public void AddItem(string FileOrDirectoryName)
  813.         {
  814.             AddItem(FileOrDirectoryName, false);
  815.         }
  816.         public void AddItem(string FileOrDirectoryName, bool WantVerbose)
  817.         {
  818.             if (System.IO.File.Exists(FileOrDirectoryName))
  819.                 AddFile(FileOrDirectoryName, WantVerbose);
  820.             else if (System.IO.Directory.Exists(FileOrDirectoryName))
  821.                 AddDirectory(FileOrDirectoryName, WantVerbose);
  822.             else
  823.                 throw new Exception(String.Format("That file or directory ({0}) does not exist!", FileOrDirectoryName));
  824.         }
  825.         public void AddFile(string FileName)
  826.         {
  827.             AddFile(FileName, false);
  828.         }
  829.         public void AddFile(string FileName, bool WantVerbose)
  830.         {
  831.             ZipEntry ze = ZipEntry.Create(FileName);
  832.             if (WantVerbose) Console.WriteLine("adding {0}...", FileName);
  833.             _entries.Add(ze);
  834.         }
  835.         public void AddDirectory(string DirectoryName)
  836.         {
  837.             AddDirectory(DirectoryName, false);
  838.         }
  839.         public void AddDirectory(string DirectoryName, bool WantVerbose)
  840.         {
  841.             String[] filenames = System.IO.Directory.GetFiles(DirectoryName);
  842.             foreach (String filename in filenames)
  843.             {
  844.                 if (WantVerbose) Console.WriteLine("adding {0}...", filename);
  845.                 AddFile(filename);
  846.             }
  847.             String[] dirnames = System.IO.Directory.GetDirectories(DirectoryName);
  848.             foreach (String dir in dirnames)
  849.             {
  850.                 AddDirectory(dir, WantVerbose);
  851.             }
  852.         }
  853.         public void Save()
  854.         {
  855.             // an entry for each file
  856.             foreach (ZipEntry e in _entries)
  857.             {
  858.                 e.Write(WriteStream);
  859.             }
  860.             WriteCentralDirectoryStructure();
  861.             WriteStream.Close();
  862.             _writestream = null;
  863.         }
  864.         private void WriteCentralDirectoryStructure()
  865.         {
  866.             // the central directory structure
  867.             long Start = WriteStream.Length;
  868.             foreach (ZipEntry e in _entries)
  869.             {
  870.                 e.WriteCentralDirectoryEntry(WriteStream);
  871.             }
  872.             long Finish = WriteStream.Length;
  873.             // now, the footer
  874.             WriteCentralDirectoryFooter(Start, Finish);
  875.         }
  876.         private void WriteCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory)
  877.         {
  878.             byte[] bytes = new byte[1024];
  879.             int i = 0;
  880.             // signature
  881.             UInt32 EndOfCentralDirectorySignature = 0x06054b50;
  882.             bytes[i++] = (byte)(EndOfCentralDirectorySignature & 0x000000FF);
  883.             bytes[i++] = (byte)((EndOfCentralDirectorySignature & 0x0000FF00) >> 8);
  884.             bytes[i++] = (byte)((EndOfCentralDirectorySignature & 0x00FF0000) >> 16);
  885.             bytes[i++] = (byte)((EndOfCentralDirectorySignature & 0xFF000000) >> 24);
  886.             // number of this disk
  887.             bytes[i++] = 0;
  888.             bytes[i++] = 0;
  889.             // number of the disk with the start of the central directory
  890.             bytes[i++] = 0;
  891.             bytes[i++] = 0;
  892.             // total number of entries in the central dir on this disk
  893.             bytes[i++] = (byte)(_entries.Count & 0x00FF);
  894.             bytes[i++] = (byte)((_entries.Count & 0xFF00) >> 8);
  895.             // total number of entries in the central directory
  896.             bytes[i++] = (byte)(_entries.Count & 0x00FF);
  897.             bytes[i++] = (byte)((_entries.Count & 0xFF00) >> 8);
  898.             // size of the central directory
  899.             Int32 SizeOfCentralDirectory = (Int32)(EndOfCentralDirectory - StartOfCentralDirectory);
  900.             bytes[i++] = (byte)(SizeOfCentralDirectory & 0x000000FF);
  901.             bytes[i++] = (byte)((SizeOfCentralDirectory & 0x0000FF00) >> 8);
  902.             bytes[i++] = (byte)((SizeOfCentralDirectory & 0x00FF0000) >> 16);
  903.             bytes[i++] = (byte)((SizeOfCentralDirectory & 0xFF000000) >> 24);
  904.             // offset of the start of the central directory 
  905.             Int32 StartOffset = (Int32)StartOfCentralDirectory;  // cast down from Long
  906.             bytes[i++] = (byte)(StartOffset & 0x000000FF);
  907.             bytes[i++] = (byte)((StartOffset & 0x0000FF00) >> 8);
  908.             bytes[i++] = (byte)((StartOffset & 0x00FF0000) >> 16);
  909.             bytes[i++] = (byte)((StartOffset & 0xFF000000) >> 24);
  910.             // zip comment length
  911.             bytes[i++] = 0;
  912.             bytes[i++] = 0;
  913.             WriteStream.Write(bytes, 0, i);
  914.         }
  915.         #endregion
  916.         #region For Reading Zip Files
  917.         /// <summary>
  918.         /// This will throw if the zipfile does not exist. 
  919.         /// </summary>
  920.         public static ZipFile Read(string zipfilename)
  921.         {
  922.             return Read(zipfilename, false);
  923.         }
  924.         /// <summary>
  925.         /// This will throw if the zipfile does not exist. 
  926.         /// </summary>
  927.         public static ZipFile Read(string zipfilename, bool TurnOnDebug)
  928.         {
  929.             ZipFile zf = new ZipFile();
  930.             zf._Debug = TurnOnDebug;
  931.             zf._name = zipfilename;
  932.             zf._entries = new System.Collections.Generic.List<ZipEntry>();
  933.             ZipEntry e;
  934.             while ((e = ZipEntry.Read(zf.ReadStream, zf._Debug)) != null)
  935.             {
  936.                 if (zf._Debug) System.Console.WriteLine("  ZipFile::Read(): ZipEntry: {0}", e.FileName);
  937.                 zf._entries.Add(e);
  938.             }
  939.             // read the zipfile's central directory structure here.
  940.             zf._direntries = new System.Collections.Generic.List<ZipDirEntry>();
  941.             ZipDirEntry de;
  942.             while ((de = ZipDirEntry.Read(zf.ReadStream, zf._Debug)) != null)
  943.             {
  944.                 if (zf._Debug) System.Console.WriteLine("  ZipFile::Read(): ZipDirEntry: {0}", de.FileName);
  945.                 zf._direntries.Add(de);
  946.             }
  947.             return zf;
  948.         }
  949.         public System.Collections.Generic.IEnumerator<ZipEntry> GetEnumerator()
  950.         {
  951.             foreach (ZipEntry e in _entries)
  952.                 yield return e;
  953.         }
  954.         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  955.         {
  956.             return GetEnumerator();
  957.         }
  958.         public void ExtractAll(string path)
  959.         {
  960.             ExtractAll(path, false);
  961.         }
  962.         public void ExtractAll(string path, bool WantVerbose)
  963.         {
  964.             bool header = WantVerbose;
  965.             foreach (ZipEntry e in _entries)
  966.             {
  967.                 if (header)
  968.                 {
  969.                     System.Console.WriteLine("n{1,-22} {2,-6} {3,4}   {4,-8}  {0}",
  970.                                  "Name", "Modified", "Size", "Ratio", "Packed");
  971.                     System.Console.WriteLine(new System.String('-', 72));
  972.                     header = false;
  973.                 }
  974.                 if (WantVerbose)
  975.                     System.Console.WriteLine("{1,-22} {2,-6} {3,4:F0}%   {4,-8} {0}",
  976.                                  e.FileName,
  977.                                  e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
  978.                                  e.UncompressedSize,
  979.                                  e.CompressionRatio,
  980.                                  e.CompressedSize);
  981.                 e.Extract(path);
  982.             }
  983.         }
  984.         public void Extract(string filename)
  985.         {
  986.             this[filename].Extract();
  987.         }
  988.         public void Extract(string filename, System.IO.Stream s)
  989.         {
  990.             this[filename].Extract(s);
  991.         }
  992.         public ZipEntry this[String filename]
  993.         {
  994.             get
  995.             {
  996.                 foreach (ZipEntry e in _entries)
  997.                 {
  998.                     if (e.FileName == filename) return e;
  999.                 }
  1000.                 return null;
  1001.             }
  1002.         }
  1003.         #endregion
  1004.         // the destructor
  1005.         ~ZipFile()
  1006.         {
  1007.             // call Dispose with false.  Since we're in the
  1008.             // destructor call, the managed resources will be
  1009.             // disposed of anyways.
  1010.             Dispose(false);
  1011.         }
  1012.         public void Dispose()
  1013.         {
  1014.             // dispose of the managed and unmanaged resources
  1015.             Dispose(true);
  1016.             // tell the GC that the Finalize process no longer needs
  1017.             // to be run for this object.
  1018.             GC.SuppressFinalize(this);
  1019.         }
  1020.         protected virtual void Dispose(bool disposeManagedResources)
  1021.         {
  1022.             if (!this._disposed)
  1023.             {
  1024.                 if (disposeManagedResources)
  1025.                 {
  1026.                     // dispose managed resources
  1027.                     if (_readstream != null)
  1028.                     {
  1029.                         _readstream.Dispose();
  1030.                         _readstream = null;
  1031.                     }
  1032.                     if (_writestream != null)
  1033.                     {
  1034.                         _writestream.Dispose();
  1035.                         _writestream = null;
  1036.                     }
  1037.                 }
  1038.                 this._disposed = true;
  1039.             }
  1040.         }
  1041.         private System.IO.Stream _readstream;
  1042.         private System.IO.FileStream _writestream;
  1043.         private bool _Debug = false;
  1044.         private bool _disposed = false;
  1045.         private System.Collections.Generic.List<ZipEntry> _entries = null;
  1046.         private System.Collections.Generic.List<ZipDirEntry> _direntries = null;
  1047.     }
  1048. }
  1049. // Example usage: 
  1050. // 1. Extracting all files from a Zip file: 
  1051. //
  1052. //     try 
  1053. //     {
  1054. //       using(ZipFile zip= ZipFile.Read(ZipFile))
  1055. //       {
  1056. //         zip.ExtractAll(TargetDirectory, true);
  1057. //       }
  1058. //     }
  1059. //     catch (System.Exception ex1)
  1060. //     {
  1061. //       System.Console.Error.WriteLine("exception: " + ex1);
  1062. //     }
  1063. //
  1064. // 2. Extracting files from a zip individually:
  1065. //
  1066. //     try 
  1067. //     {
  1068. //       using(ZipFile zip= ZipFile.Read(ZipFile)) 
  1069. //       {
  1070. //         foreach (ZipEntry e in zip) 
  1071. //         {
  1072. //           e.Extract(TargetDirectory);
  1073. //         }
  1074. //       }
  1075. //     }
  1076. //     catch (System.Exception ex1)
  1077. //     {
  1078. //       System.Console.Error.WriteLine("exception: " + ex1);
  1079. //     }
  1080. //
  1081. // 3. Creating a zip archive: 
  1082. //
  1083. //     try 
  1084. //     {
  1085. //       using(ZipFile zip= new ZipFile(NewZipFile)) 
  1086. //       {
  1087. //
  1088. //         String[] filenames= System.IO.Directory.GetFiles(Directory); 
  1089. //         foreach (String filename in filenames) 
  1090. //         {
  1091. //           zip.Add(filename);
  1092. //         }
  1093. //
  1094. //         zip.Save(); 
  1095. //       }
  1096. //
  1097. //     }
  1098. //     catch (System.Exception ex1)
  1099. //     {
  1100. //       System.Console.Error.WriteLine("exception: " + ex1);
  1101. //     }
  1102. //
  1103. //
  1104. // ==================================================================
  1105. //
  1106. //
  1107. //
  1108. // Information on the ZIP format:
  1109. //
  1110. // From
  1111. // http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
  1112. //
  1113. //  Overall .ZIP file format:
  1114. //
  1115. //     [local file header 1]
  1116. //     [file data 1]
  1117. //     [data descriptor 1]  ** sometimes
  1118. //     . 
  1119. //     .
  1120. //     .
  1121. //     [local file header n]
  1122. //     [file data n]
  1123. //     [data descriptor n]   ** sometimes
  1124. //     [archive decryption header] 
  1125. //     [archive extra data record] 
  1126. //     [central directory]
  1127. //     [zip64 end of central directory record]
  1128. //     [zip64 end of central directory locator] 
  1129. //     [end of central directory record]
  1130. //
  1131. // Local File Header format:
  1132. //         local file header signature     4 bytes  (0x04034b50)
  1133. //         version needed to extract       2 bytes
  1134. //         general purpose bit flag        2 bytes
  1135. //         compression method              2 bytes
  1136. //         last mod file time              2 bytes
  1137. //         last mod file date              2 bytes
  1138. //         crc-32                          4 bytes
  1139. //         compressed size                 4 bytes
  1140. //         uncompressed size               4 bytes
  1141. //         file name length                2 bytes
  1142. //         extra field length              2 bytes
  1143. //         file name                       varies
  1144. //         extra field                     varies
  1145. //
  1146. //
  1147. // Data descriptor:  (used only when bit 3 of the general purpose bitfield is set)
  1148. //         local file header signature     4 bytes  (0x08074b50)
  1149. //         crc-32                          4 bytes
  1150. //         compressed size                 4 bytes
  1151. //         uncompressed size               4 bytes
  1152. //
  1153. //
  1154. //   Central directory structure:
  1155. //
  1156. //       [file header 1]
  1157. //       .
  1158. //       .
  1159. //       . 
  1160. //       [file header n]
  1161. //       [digital signature] 
  1162. //
  1163. //
  1164. //       File header:  (This is ZipDirEntry in the code above)
  1165. //         central file header signature   4 bytes  (0x02014b50)
  1166. //         version made by                 2 bytes
  1167. //         version needed to extract       2 bytes
  1168. //         general purpose bit flag        2 bytes
  1169. //         compression method              2 bytes
  1170. //         last mod file time              2 bytes
  1171. //         last mod file date              2 bytes
  1172. //         crc-32                          4 bytes
  1173. //         compressed size                 4 bytes
  1174. //         uncompressed size               4 bytes
  1175. //         file name length                2 bytes
  1176. //         extra field length              2 bytes
  1177. //         file comment length             2 bytes
  1178. //         disk number start               2 bytes
  1179. //         internal file attributes        2 bytes
  1180. //         external file attributes        4 bytes
  1181. //         relative offset of local header 4 bytes
  1182. //         file name (variable size)
  1183. //         extra field (variable size)
  1184. //         file comment (variable size)
  1185. //
  1186. // End of central directory record:
  1187. //
  1188. //         end of central dir signature    4 bytes  (0x06054b50)
  1189. //         number of this disk             2 bytes
  1190. //         number of the disk with the
  1191. //         start of the central directory  2 bytes
  1192. //         total number of entries in the
  1193. //         central directory on this disk  2 bytes
  1194. //         total number of entries in
  1195. //         the central directory           2 bytes
  1196. //         size of the central directory   4 bytes
  1197. //         offset of start of central
  1198. //         directory with respect to
  1199. //         the starting disk number        4 bytes
  1200. //         .ZIP file comment length        2 bytes
  1201. //         .ZIP file comment       (variable size)
  1202. //
  1203. // date and time are packed values, as MSDOS did them
  1204. // time: bits 0-4 : second
  1205. //            5-10: minute
  1206. //            11-15: hour
  1207. // date  bits 0-4 : day
  1208. //            5-8: month
  1209. //            9-15 year (since 1980)
  1210. //
  1211. // see http://www.vsft.com/hal/dostime.htm