diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..4dba023
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,49 @@
+Zip License
+-----------
+
+Copyright (C) 2001 Gerry Shaw
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Gerry Shaw (gerry_shaw@yahoo.com)
+
+
+zlib License
+------------
+
+Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Jean-loup Gailly Mark Adler
+jloup@gzip.org madler@alumni.caltech.edu
+
+http://www.gzip.org/zlib/
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fbd73ca
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# Zip
+
+Zip is a free .NET Zip library based on the java.util.zip package. It uses the
+freely available zlib library for the compression engine and a contribution
+to the zlib library for zip file manipulation.
+
+Note: This is a very old library and I no longer support it. I'm putting it
+up on GitHub for historical and keep safe reasons more than anything. That said
+it has been used in may products and continues to be of some value.
+
+## Authors
+
+* Gerry Shaw
+
+### Special Thanks
+
+* The [zlib](http://www.gzip.org/zlib) developers
+* Philip Craig for [NUnit](http://nunit.sourceforge.net)
+
+## License
+
+BSD
diff --git a/Zip.build b/Zip.build
new file mode 100644
index 0000000..0a1770e
--- /dev/null
+++ b/Zip.build
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bin/Zip.Tests.dll b/bin/Zip.Tests.dll
new file mode 100644
index 0000000..20ec8a2
Binary files /dev/null and b/bin/Zip.Tests.dll differ
diff --git a/bin/Zip.chm b/bin/Zip.chm
new file mode 100644
index 0000000..153b507
Binary files /dev/null and b/bin/Zip.chm differ
diff --git a/bin/Zip.dll b/bin/Zip.dll
new file mode 100644
index 0000000..00b7aa6
Binary files /dev/null and b/bin/Zip.dll differ
diff --git a/bin/Zip.xml b/bin/Zip.xml
new file mode 100644
index 0000000..3990879
--- /dev/null
+++ b/bin/Zip.xml
@@ -0,0 +1,684 @@
+
+
+
+ Zip
+
+
+
+ Thrown whenever an error occurs during the build.
+
+
+ Constructs an exception with no descriptive information.
+
+
+ Constructs an exception with a descriptive message.
+ The error message that explains the reason for the exception.
+
+
+ Constructs an exception with a descriptive message and a reference to the instance of the Exception that is the root cause of the this exception.
+ The error message that explains the reason for the exception.
+ An instance of Exception that is the cause of the current Exception. If is non-null, then the current Exception is raised in a catch block handling innerException.
+
+
+ Initializes a new instance of the BuildException class with serialized data.
+ The object that holds the serialized object data.
+ The contextual information about the source or destination.
+
+
+ Specifies how the the zip entry should be compressed.
+
+
+ No compression.
+
+
+ Default and only supported compression method.
+
+
+ Specifies the amount of compression to apply to compressed zip entires.
+
+
+ Default compression level. A good choice for speed and size.
+
+
+ Do not perfrom compression.
+
+
+ Compress the entry as fast as possible size trading size for time.
+
+
+ Compress the entry using a balance of size and time.
+
+
+ Compress the entry to smallest possible size trading time for size.
+
+
+ Represents a entry in a zip file.
+
+
+ Initializes a instance of the class with the given name.
+ The name of entry that will be stored in the directory of the zip file.
+
+
+ Creates a new Zip file entry reading values from a zip file.
+
+
+ Returns a string representation of the Zip entry.
+
+
+ Check if only contains Ascii 8 bit characters.
+
+
+ Gets and sets the local file comment for the entry.
+
+ Currently only Ascii 8 bit characters are supported in comments.
+ A comment cannot exceed 65535 bytes.
+
+
+
+ Gets the compressed size of the entry data in bytes, or -1 if not known.
+
+
+ Gets the CRC-32 checksum of the uncompressed entry data.
+
+
+ Gets and sets the optional extra field data for the entry.
+ ExtraField data cannot exceed 65535 bytes.
+
+
+ Gets and sets the default compresion method for zip file entries. See for a list of possible values.
+
+
+ Gets and sets the default compresion level for zip file entries. See for a partial list of values.
+
+
+ Gets the size of the uncompressed entry data in in bytes.
+
+
+ Gets and sets the modification time of the entry.
+
+
+ Gets and sets the name of the entry.
+
+ Currently only Ascii 8 bit characters are supported in comments.
+ A comment cannot exceed 65535 bytes.
+
+
+
+ Flag that indicates if this entry is a directory or a file.
+
+
+ Gets the compression ratio as a percentage.
+ Returns -1.0 if unknown.
+
+
+ Support methods for uncompressing zip files.
+
+ This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible.
+ Encryption and multi volume ZipFile (span) are not supported. Old compressions used by old PKZip 1.x are not supported.
+ Copyright (C) 1998 Gilles Vollant. http://www.winimage.com/zLibDll/unzip.htm
+ C# wrapper by Gerry Shaw (gerry_shaw@yahoo.com). http://www.organicbit.com/zip/
+
+
+
+ Create a zip file.
+
+
+ Open a new zip entry for writing.
+
+
+ Write data to the zip file.
+
+
+ Close the current entry in the zip file.
+
+
+ Close the zip file.
+
+
+ Opens a zip file for reading.
+ The name of the zip to open. At this time only file names with ANSI (8 bit) characters are supported.
+
+ A handle usable with other functions of the ZipLib class.
+ Otherwise IntPtr.Zero if the zip file could not e opened (file doen not exist or is not valid).
+
+
+
+ Closes a zip file opened with unzipOpen.
+ The zip file handle opened by .
+ If there are files inside the zip file opened with these files must be closed with before call unzClose.
+
+ Zero if there was no error.
+ Otherwise a value less than zero. See for the specific reason.
+
+
+
+ Get global information about the zip file.
+ The zip file handle opened by .
+ An address of a struct to hold the information. No preparation of the structure is needed.
+
+ Zero if there was no error.
+ Otherwise a value less than zero. See for the specific reason.
+
+
+
+ Get the comment associated with the entire zip file.
+ The zip file handle opened by
+ The buffer to hold the comment.
+ The length of the buffer in bytes (8 bit characters).
+
+ The number of characters in the comment if there was no error.
+ Otherwise a value less than zero. See for the specific reason.
+
+
+
+ Set the current file of the zip file to the first file.
+ The zip file handle opened by .
+
+ Zero if there was no error.
+ Otherwise a value less than zero. See for the specific reason.
+
+
+
+ Set the current file of the zip file to the next file.
+ The zip file handle opened by .
+
+ Zero if there was no error.
+ Otherwise if there are no more entries.
+
+
+
+ Try locate the entry in the zip file.
+ The zip file handle opened by .
+ The name of the entry to look for.
+ If 0 use the OS default. If 1 use case sensitivity like strcmp, Unix style. If 2 do not use case sensitivity like strcmpi, Windows style.
+
+ Zero if there was no error.
+ Otherwise if there are no more entries.
+
+
+
+ Get information about the current entry in the zip file.
+ The zip file handle opened by .
+ A ZipEntryInfo struct to hold information about the entry or null.
+ An array of sbyte characters to hold the entry name or null.
+ The length of the entryNameBuffer in bytes.
+ An array to hold the extra field data for the entry or null.
+ The length of the extraField array in bytes.
+ An array of sbyte characters to hold the entry name or null.
+ The length of theh commentBuffer in bytes.
+
+ If entryInfoPtr is not null the structure will contain information about the current file.
+ If entryNameBuffer is not null the name of the entry will be copied into it.
+ If extraField is not null the extra field data of the entry will be copied into it.
+ If commentBuffer is not null the comment of the entry will be copied into it.
+
+
+ Zero if there was no error.
+ Otherwise a value less than zero. See for the specific reason.
+
+
+
+ Open the zip file entry for reading.
+ The zip file handle opened by .
+
+ Zero if there was no error.
+ Otherwise a value from .
+
+
+
+ Close the file entry opened by .
+ The zip file handle opened by .
+
+ Zero if there was no error.
+ CrcError if the file was read but the Crc does not match.
+ Otherwise a value from .
+
+
+
+ Read bytes from the current zip file entry.
+ The zip file handle opened by .
+ Buffer to store the uncompressed data into.
+ Number of bytes to write from .
+
+ The number of byte copied if somes bytes are copied.
+ Zero if the end of file was reached.
+ Less than zero with error code if there is an error. See for a list of possible error codes.
+
+
+
+ Give the current position in uncompressed data of the zip file entry currently opened.
+ The zip file handle opened by .
+ The number of bytes into the uncompressed data read so far.
+
+
+ Determine if the end of the zip file entry has been reached.
+ The zip file handle opened by .
+
+ One if the end of file was reached.
+ Zero if elsewhere.
+
+
+
+ Converts a CLR string to a 8 bit ANSI array of characters.
+ The string to convert.
+ A 8 bit ANSI array of characters.
+
+
+ Converst an 8 bit ANSI C style string to a CLR string.
+ The array of a characters that holds the string.
+ The CLR string representing the characters passed in.
+
+
+ List of possible error codes.
+
+
+ No error.
+
+
+ Unknown error.
+
+
+ Last entry in directory reached.
+
+
+ Parameter error.
+
+
+ Zip file is invalid.
+
+
+ Internal program error.
+
+
+ Crc values do not match.
+
+
+ Global information about the zip file.
+
+
+ The number of entries in the directory.
+
+
+ Length of zip file comment in bytes (8 bit characters).
+
+
+ Custom ZipLib date time structure.
+
+
+ Seconds after the minute - [0,59]
+
+
+ Minutes after the hour - [0,59]
+
+
+ Hours since midnight - [0,23]
+
+
+ Day of the month - [1,31]
+
+
+ Months since January - [0,11]
+
+
+ Years - [1980..2044]
+
+
+ Information stored in zip file directory about an entry.
+
+
+ Version needed to extract (2 bytes).
+
+
+ General purpose bit flag (2 bytes).
+
+
+ Compression method (2 bytes).
+
+
+ Last mod file date in Dos fmt (4 bytes).
+
+
+ Crc-32 (4 bytes).
+
+
+ Compressed size (4 bytes).
+
+
+ Uncompressed size (4 bytes).
+
+
+ Filename length (2 bytes).
+
+
+ Extra field length (2 bytes).
+
+
+ File comment length (2 bytes).
+
+
+ Disk number start (2 bytes).
+
+
+ Internal file attributes (2 bytes).
+
+
+ External file attributes (4 bytes).
+
+
+ File modification date of entry.
+
+
+ A collection that stores objects.
+
+
+
+ Initializes a new instance of .
+
+
+ Initializes a new instance of based on another .
+ A from which the contents are copied.
+
+
+ Initializes a new instance of containing any array of objects.
+ A array of objects with which to intialize the collection.
+
+
+ Adds a with the specified value to the .
+ The to add.
+ The index at which the new element was inserted.
+
+
+
+ Copies the elements of an array to the end of the .
+ An array of type containing the objects to add to the collection.
+ None.
+
+
+
+ Adds the contents of another to the end of the collection.
+ A containing the objects to add to the collection.
+ None.
+
+
+
+ Gets a value indicating whether the contains the specified .
+ The to locate.
+
+ if the is contained in the collection;
+ otherwise, .
+
+
+
+
+ Copies the values to a one-dimensional instance at the specified index.
+ The one-dimensional that is the destination of the values copied from .
+ The index in where copying begins.
+ None.
+ is multidimensional. -or- The number of elements in the is greater than the available space between and the end of .
+ is .
+ is less than 's lowbound.
+
+
+
+ Returns the index of a in the .
+ The to locate.
+
+ The index of the of in the
+ , if found; otherwise, -1.
+
+
+
+
+ Inserts a into the at the specified index.
+ The zero-based index where should be inserted.
+ The to insert.
+ None.
+
+
+
+ Returns an enumerator that can iterate through the .
+ None.
+
+
+
+ Removes a specific from the .
+ The to remove from the .
+ None.
+ is not found in the Collection.
+
+
+ Represents the entry at the specified index of the .
+ The zero-based index of the entry to locate in the collection.
+
+ The entry at the specified index of the collection.
+
+ is outside the valid range of indexes for the collection.
+
+
+ Enumerator for .
+
+
+ Initializes a new instance of the class.
+
+
+ Advance the enumerator to the next entry in the collection.
+ true if there are more entries; false if there are no more entires in the collection.
+
+
+ Set the enumerator to just before the start of the collection. Call to advance to the first entry in the collection.
+
+
+ Gets the current entry.
+
+
+ Provides support for reading files in the ZIP file format. Includes support for both compressed and uncompressed entries.
+ This example shows how to view the entries in a ZIP file.
+
+ public static void View(string zipFileName) {
+ ZipReader reader = new ZipReader(zipFileName);
+
+ Console.WriteLine("Archive: {0} ({1} files)", zipFileName, reader.Entries.Count);
+ Console.WriteLine(reader.Comment);
+
+ string format = "{0,8} {1,8} {2,5} {3,10} {4,5} {5}";
+ Console.WriteLine(format, " Length ", " Size ", "Ratio", " Date ", "Time ", "Name");
+ Console.WriteLine(format, "--------", "--------", "-----", "----------", "-----", "----");
+
+ foreach (ZipEntry entry in reader.Entries) {
+ if (!entry.IsDirectory) {
+ Console.WriteLine(format,
+ entry.Length,
+ entry.CompressedLength,
+ entry.Ratio.ToString("P0"),
+ entry.ModifiedTime.ToString("yyyy-MM-dd"),
+ entry.ModifiedTime.ToString("hh:mm"),
+ entry.Name);
+ }
+ }
+ reader.Close();
+ }
+
+
+ This example shows how to extract files from a ZIP file.
+
+ public static void Extract(string zipFileName) {
+ ZipReader reader = new ZipReader(zipFileName);
+ Console.WriteLine("Archive: {0}", zipFileName);
+ Console.WriteLine(reader.Comment);
+
+ // buffer to hold temp bytes
+ byte[] buffer = new byte[4096];
+ int byteCount;
+
+ // Get the zipped entries
+ while (reader.MoveNext()) {
+ ZipEntry entry = reader.Current;
+
+ if (entry.IsDirectory) {
+ Directory.CreateDirectory(entry.Name);
+ } else {
+ Console.Write(" {0}", entry.Name);
+
+ // create output stream
+ FileStream writer = File.Open(entry.Name, FileMode.Create);
+
+ // write uncompressed data
+ while ((byteCount = reader.Read(buffer, 0, buffer.Length)) > 0) {
+ Console.Write(".");
+ writer.Write(buffer, 0, byteCount);
+ }
+ writer.Close();
+ Console.WriteLine();
+ }
+ }
+ reader.Close();
+ }
+
+
+
+
+ ZipFile handle to read data from.
+
+
+ Name of zip file.
+
+
+ Contents of zip file directory.
+
+
+ Global zip file comment.
+
+
+ True if an entry is open for reading.
+
+
+ Current zip entry open for reading.
+
+
+ Initializes a instance of the class for reading the zip file with the given name.
+ The name of zip file that will be read.
+
+
+ Cleans up the resources used by this zip file.
+
+
+ Dispose is synonym for Close.
+
+
+ Closes the zip file and releases any resources.
+
+
+ Advances the enumerator to the next element of the collection.
+ Sets to the next zip entry.
+ true if the next entry is not null; otherwise false.
+
+
+ Move to just before the first entry in the zip directory.
+
+
+ Seek to the specified entry.
+ The name of the entry to seek to.
+
+
+ Uncompress a block of bytes from the current zip entry and writes the data in a given buffer.
+ The array to write data into.
+ The byte offset in at which to begin writing.
+ The maximum number of bytes to read.
+
+
+ Gets the name of the zip file that was passed to the constructor.
+
+
+ Gets the global comment for the zip file.
+
+
+ Gets a object that contains all the entries in the zip file directory.
+
+
+ Gets the current entry in the zip file..
+
+
+ Provides support for writing files in the ZIP file format. Includes support for both compressed and uncompressed entries.
+ This example shows how to create a ZIP file.
+
+ public static void Add(string zipFileName, string[] entryPatterns) {
+ string currentDirectory = Directory.GetCurrentDirectory();
+ Console.WriteLine("Creating {0}", zipFileName);
+
+ ZipWriter writer = new ZipWriter(zipFileName);
+
+ // buffer to hold temp bytes
+ byte[] buffer = new byte[4096];
+ int byteCount;
+
+ // add files to archive
+ foreach (string pattern in entryPatterns) {
+ foreach (string path in Directory.GetFiles(currentDirectory, pattern)) {
+ string fileName = Path.GetFileName(path);
+ Console.Write("Adding {0}", fileName);
+
+ ZipEntry entry = new ZipEntry(fileName);
+ entry.ModifiedTime = File.GetLastWriteTime(fileName);
+ entry.Comment = "local file comment";
+
+ writer.AddEntry(entry);
+
+ FileStream reader = File.OpenRead(entry.Name);
+ while ((byteCount = reader.Read(buffer, 0, buffer.Length)) > 0) {
+ Console.Write(".");
+ writer.Write(buffer, 0, byteCount);
+ }
+ reader.Close();
+ Console.WriteLine();
+ }
+ }
+
+ writer.Close();
+ }
+
+
+
+
+ Name of the zip file.
+
+
+ Zip file global comment.
+
+
+ True if currently writing a new zip file entry.
+
+
+ Zip file handle.
+
+
+ Initializes a new instance fo the class with a specified file name. Any Existing file will be overwritten.
+ The name of the zip file to create.
+
+
+ Cleans up the resources used by this zip file.
+
+
+ Dispose is synonym for Close.
+
+
+ Closes the zip file and releases any resources.
+
+
+ Creates a new zip entry in the directory and positions the stream to the start of the entry data.
+ The zip entry to be written.
+ Closes the current entry if still active.
+
+
+ Compress a block of bytes from the given buffer and writes them into the current zip entry.
+ The array to read data from.
+ The byte offset in at which to begin reading.
+ The maximum number of bytes to write.
+
+
+ Gets the name of the zip file.
+
+
+ Gets and sets the zip file comment.
+
+
+
diff --git a/bin/zlib.dll b/bin/zlib.dll
new file mode 100644
index 0000000..d106ac6
Binary files /dev/null and b/bin/zlib.dll differ
diff --git a/examples/MiniZip/MiniZip.cs b/examples/MiniZip/MiniZip.cs
new file mode 100644
index 0000000..218b5c5
--- /dev/null
+++ b/examples/MiniZip/MiniZip.cs
@@ -0,0 +1,196 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.IO;
+using OrganicBit.Zip;
+
+namespace OrganicBit.Zip.Examples {
+
+ public class MiniZip {
+
+ public static void ShowHelp() {
+ Console.WriteLine(
+@"MiniZip - A simple zip file manipulator
+http://www.organicbit.com/zip/
+
+Usage: minizip [-v|-e|-a] [files to add]
+
+Examples:
+ minizip # displays this message
+ minizip -v # view contents
+ minizip -e # extract files
+ minizip -a [*.txt] # add files
+");
+ }
+
+ public static void View(string zipFileName) {
+ ZipReader reader = new ZipReader(zipFileName);
+
+ Console.WriteLine("Archive: {0} ({1} files)", zipFileName, reader.Entries.Count);
+ Console.WriteLine(reader.Comment);
+
+ string format = "{0,8} {1,8} {2,5} {3,10} {4,5} {5}";
+ Console.WriteLine(format, " Length ", " Size ", "Ratio", " Date ", "Time ", "Name");
+ Console.WriteLine(format, "--------", "--------", "-----", "----------", "-----", "----");
+
+ foreach (ZipEntry entry in reader.Entries) {
+ if (!entry.IsDirectory) {
+ Console.WriteLine(format,
+ entry.Length,
+ entry.CompressedLength,
+ entry.Ratio.ToString("P0"),
+ entry.ModifiedTime.ToString("yyyy-MM-dd"),
+ entry.ModifiedTime.ToString("hh:mm"),
+ entry.Name);
+ }
+ }
+ reader.Close();
+ }
+
+ public static void Extract(string zipFileName) {
+ ZipReader reader = new ZipReader(zipFileName);
+ Console.WriteLine("Archive: {0}", zipFileName);
+ Console.WriteLine(reader.Comment);
+
+ // buffer to hold temp bytes
+ byte[] buffer = new byte[4096];
+ int byteCount;
+
+ // Get the zipped entries
+ while (reader.MoveNext()) {
+ ZipEntry entry = reader.Current;
+
+ if (entry.IsDirectory) {
+ Directory.CreateDirectory(entry.Name);
+ } else {
+ Console.Write(" {0}", entry.Name);
+
+ // create output stream
+ FileStream writer = File.Open(entry.Name, FileMode.Create);
+
+ // write uncompressed data
+ while ((byteCount = reader.Read(buffer, 0, buffer.Length)) > 0) {
+ Console.Write(".");
+ writer.Write(buffer, 0, byteCount);
+ }
+ writer.Close();
+ Console.WriteLine();
+ }
+ }
+ reader.Close();
+ }
+
+ public static void Add(string zipFileName, string[] entryPatterns) {
+ string currentDirectory = Directory.GetCurrentDirectory();
+ Console.WriteLine("Creating {0}", zipFileName);
+
+ ZipWriter writer = new ZipWriter(zipFileName);
+
+ // buffer to hold temp bytes
+ byte[] buffer = new byte[4096];
+ int byteCount;
+
+ // add files to archive
+ foreach (string pattern in entryPatterns) {
+ foreach (string path in Directory.GetFiles(currentDirectory, pattern)) {
+ string fileName = Path.GetFileName(path);
+ Console.Write("Adding {0}", fileName);
+
+ ZipEntry entry = new ZipEntry(fileName);
+ entry.ModifiedTime = File.GetLastWriteTime(fileName);
+ entry.Comment = "local file comment";
+
+ writer.AddEntry(entry);
+
+ FileStream reader = File.OpenRead(entry.Name);
+ while ((byteCount = reader.Read(buffer, 0, buffer.Length)) > 0) {
+ Console.Write(".");
+ writer.Write(buffer, 0, byteCount);
+ }
+ reader.Close();
+ Console.WriteLine();
+ }
+ }
+
+ writer.Close();
+ }
+
+ enum Action {
+ Nothing,
+ ShowHelp,
+ View,
+ Extract,
+ Add
+ }
+
+ static Action ParseCommandLine(string[] args) {
+ Action action = Action.ShowHelp;
+ if (args.Length >= 2) {
+ if (args[0][0] == '-') {
+ switch (args[0][1]) {
+ case 'v':
+ action = Action.View;
+ break;
+
+ case 'e':
+ action = Action.Extract;
+ break;
+
+ case 'a':
+ action = Action.Add;
+ break;
+ }
+ }
+ }
+ return action;
+ }
+
+ public static int Main(string[] args) {
+ try {
+ Action action = ParseCommandLine(args);
+ switch (action) {
+ case Action.ShowHelp:
+ ShowHelp();
+ break;
+
+ case Action.View:
+ View(args[1]);
+ break;
+
+ case Action.Extract:
+ Extract(args[1]);
+ break;
+
+ case Action.Add:
+ string[] patterns = new string[args.Length - 2];
+ Array.Copy(args, 2, patterns, 0, args.Length - 2);
+ Add(args[1], patterns);
+ break;
+ }
+ } catch (Exception e) {
+ Console.WriteLine(e.Message);
+ Environment.Exit(1);
+ }
+
+ return 0;
+ }
+ }
+}
diff --git a/src/Zip.Tests/AllTests.cs b/src/Zip.Tests/AllTests.cs
new file mode 100644
index 0000000..06a4a1f
--- /dev/null
+++ b/src/Zip.Tests/AllTests.cs
@@ -0,0 +1,53 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.Reflection;
+using NUnit.Framework;
+
+namespace OrganicBit.Zip.Tests {
+
+ // This class bundles all our tests into a single suite. If you wanted
+ // you could create other suites with a sub set of the tests. All that is
+ // required is a property called Suite that returns a ITest object. The
+ // ITest object most commonly returned is a TestSuite. For single class
+ // tests this member can be included within the TestCase.
+ public class AllTests {
+ public static ITest Suite {
+ get {
+ // Use reflection to automagically scan all the classes that
+ // inherit from TestCase and add them to the suite.
+ TestSuite suite = new TestSuite("Zip Tests");
+ /*
+ Assembly assembly = Assembly.GetExecutingAssembly();
+ foreach(Type type in assembly.GetTypes()) {
+ if (type.IsSubclassOf(typeof(TestCase)) && !type.IsAbstract) {
+ suite.AddTestSuite(type);
+ }
+ }
+ */
+ suite.AddTestSuite(typeof(ZipExceptionTest));
+ suite.AddTestSuite(typeof(ZipFileTest));
+ suite.AddTestSuite(typeof(ZLibTest));
+ return suite;
+ }
+ }
+ }
+}
diff --git a/src/Zip.Tests/ExceptionTest.cs b/src/Zip.Tests/ExceptionTest.cs
new file mode 100644
index 0000000..d9dc805
--- /dev/null
+++ b/src/Zip.Tests/ExceptionTest.cs
@@ -0,0 +1,48 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
+using NUnit.Framework;
+
+namespace OrganicBit.Zip.Tests {
+
+ // By Eric Gunnerson (Microsoft Corporation)
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp08162001.asp
+ internal class ExceptionTest {
+ public static void TestSerialization(Exception e) {
+ string tempFileName = Path.GetTempFileName();
+
+ Stream streamRead = null;
+ Stream streamWrite = File.Create(tempFileName);
+ BinaryFormatter binaryWrite = new BinaryFormatter();
+ binaryWrite.Serialize(streamWrite, e);
+ streamWrite.Close();
+
+ streamRead = File.OpenRead(tempFileName);
+ BinaryFormatter binaryRead = new BinaryFormatter();
+ object oout = binaryRead.Deserialize(streamRead);
+ streamRead.Close();
+
+ File.Delete(tempFileName);
+ }
+ }
+}
diff --git a/src/Zip.Tests/ZLibTest.cs b/src/Zip.Tests/ZLibTest.cs
new file mode 100644
index 0000000..a76e47e
--- /dev/null
+++ b/src/Zip.Tests/ZLibTest.cs
@@ -0,0 +1,45 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using OrganicBit.Zip;
+using NUnit.Framework;
+
+namespace OrganicBit.Zip.Tests {
+
+ public class ZLibTest : TestCase {
+
+ public ZLibTest(String name) : base(name) {
+ }
+
+ protected override void SetUp() {
+ }
+
+ protected override void TearDown() {
+ }
+
+ public void Test_Version() {
+ try {
+ //Assert(ZLib.Version == "1.1.3");
+ } catch (Exception) {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Zip.Tests/ZipExceptionTest.cs b/src/Zip.Tests/ZipExceptionTest.cs
new file mode 100644
index 0000000..a12be72
--- /dev/null
+++ b/src/Zip.Tests/ZipExceptionTest.cs
@@ -0,0 +1,48 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using OrganicBit.Zip;
+using NUnit.Framework;
+
+namespace OrganicBit.Zip.Tests {
+
+ public class ZipExceptionTest : TestCase {
+
+ public ZipExceptionTest(String name) : base(name) {
+ }
+
+ protected override void SetUp() {
+ }
+
+ protected override void TearDown() {
+ }
+
+ public void Test_Serialization() {
+ try {
+ // getting a BadFormatException when accessing anything in Zip.dll
+ // new ZipException();
+ } catch (Exception e) {
+ Console.WriteLine(e.ToString());
+ }
+ //ExceptionTest.TestSerialization(new ZipException());
+ }
+ }
+}
diff --git a/src/Zip.Tests/ZipFileTest.cs b/src/Zip.Tests/ZipFileTest.cs
new file mode 100644
index 0000000..01c0c92
--- /dev/null
+++ b/src/Zip.Tests/ZipFileTest.cs
@@ -0,0 +1,49 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using OrganicBit.Zip;
+using NUnit.Framework;
+
+namespace OrganicBit.Zip.Tests {
+
+ public class ZipFileTest : TestCase {
+
+ public ZipFileTest(String name) : base(name) {
+ }
+
+ protected override void SetUp() {
+ }
+
+ protected override void TearDown() {
+ }
+
+ public void Test_Loading() {
+ /*
+ ZipFile zip = new ZipFile("test.zip");
+ Console.WriteLine(zip.ToString());
+
+ foreach (ZipEntry entry in zip.Entries) {
+ Console.WriteLine(entry.ToString());
+ }
+ */
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Zip.Tests/data/test.zip b/src/Zip.Tests/data/test.zip
new file mode 100644
index 0000000..95d53c6
Binary files /dev/null and b/src/Zip.Tests/data/test.zip differ
diff --git a/src/Zip/AssemblyInfo.cs b/src/Zip/AssemblyInfo.cs
new file mode 100644
index 0000000..f6d7ea7
--- /dev/null
+++ b/src/Zip/AssemblyInfo.cs
@@ -0,0 +1,39 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Zip")]
+[assembly: AssemblyDescription("A .NET Zip library")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("http://www.organicbit.com/zip/")]
+[assembly: AssemblyProduct("NAnt")]
+[assembly: AssemblyCopyright("Copyright (C) 2001 Gerry Shaw")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.9.0.*")]
+
+// This will not compile with Visual Studio. If you want to build a signed
+// executable use the NAnt build file. To build under Visual Studio just
+// exclude this file from the build.
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile(@"..\Zip.key")]
+//[assembly: AssemblyKeyName("")]
diff --git a/src/Zip/ZipEntry.cs b/src/Zip/ZipEntry.cs
new file mode 100644
index 0000000..0a73544
--- /dev/null
+++ b/src/Zip/ZipEntry.cs
@@ -0,0 +1,245 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.IO;
+
+namespace OrganicBit.Zip {
+
+ /// Specifies how the the zip entry should be compressed.
+ public enum CompressionMethod {
+ /// No compression.
+ Stored = 0,
+
+ /// Default and only supported compression method.
+ Deflated = 8
+ }
+
+ /// Specifies the amount of compression to apply to compressed zip entires.
+ public enum CompressionLevel : int {
+ /// Default compression level. A good choice for speed and size.
+ Default = -1,
+
+ /// Do not perfrom compression.
+ None = 0,
+
+ /// Compress the entry as fast as possible size trading size for time.
+ Fastest = 1,
+
+ /// Compress the entry using a balance of size and time.
+ Average = 5,
+
+ /// Compress the entry to smallest possible size trading time for size.
+ Smallest = 9
+ }
+
+ /// Represents a entry in a zip file.
+ public class ZipEntry {
+
+ string _name = String.Empty;
+ uint _crc = 0;
+ long _compressedLength = -1;
+ long _uncompressedLength = -1;
+ byte[] _extraField = null;
+ string _comment = String.Empty;
+ DateTime _modifiedTime = DateTime.Now;
+
+ CompressionMethod _method = CompressionMethod.Deflated;
+ int _level = (int) CompressionLevel.Default;
+
+ /// Initializes a instance of the class with the given name.
+ /// The name of entry that will be stored in the directory of the zip file.
+ public ZipEntry(string name) {
+ Name = name;
+ }
+
+ /// Creates a new Zip file entry reading values from a zip file.
+ internal ZipEntry(IntPtr handle) {
+ ZipEntryInfo entryInfo;
+ int result = 0;
+ unsafe {
+ result = ZipLib.unzGetCurrentFileInfo(handle, &entryInfo, null, 0, null, 0, null, 0);
+ }
+ if (result != 0) {
+ throw new ZipException("Could not read entries from zip file " + Name);
+ }
+
+ ExtraField = new byte[entryInfo.ExtraFieldLength];
+ sbyte[] entryNameBuffer = new sbyte[entryInfo.FileNameLength];
+ sbyte[] commentBuffer = new sbyte[entryInfo.CommentLength];
+
+ unsafe {
+ result = ZipLib.unzGetCurrentFileInfo(handle, &entryInfo,
+ entryNameBuffer, (uint) entryNameBuffer.Length,
+ ExtraField, (uint) ExtraField.Length,
+ commentBuffer, (uint) commentBuffer.Length);
+ }
+ if (result != 0) {
+ throw new ZipException("Could not read entries from zip file " + Name);
+ }
+
+ _name = ZipLib.AnsiToString(entryNameBuffer);
+ _comment = ZipLib.AnsiToString(commentBuffer);
+
+ _crc = entryInfo.Crc;
+ _compressedLength = entryInfo.CompressedSize;
+ _uncompressedLength = entryInfo.UncompressedSize;
+ _method = (CompressionMethod) entryInfo.CompressionMethod;
+ _modifiedTime = new DateTime(
+ (int) entryInfo.DateTime.Year,
+ (int) entryInfo.DateTime.Month + 1,
+ (int) entryInfo.DateTime.Day,
+ (int) entryInfo.DateTime.Hours,
+ (int) entryInfo.DateTime.Minutes,
+ (int) entryInfo.DateTime.Seconds);
+ }
+
+ /// Gets and sets the local file comment for the entry.
+ ///
+ /// Currently only Ascii 8 bit characters are supported in comments.
+ /// A comment cannot exceed 65535 bytes.
+ ///
+ public string Comment {
+ get { return _comment; }
+ set {
+ // null comments are valid
+ if (value != null) {
+ if (value.Length > 0xffff) {
+ throw new ArgumentOutOfRangeException("Comment cannot not exceed 65535 characters.");
+ }
+ if (!IsAscii(value)) {
+ throw new ArgumentException("Name can only contain Ascii 8 bit characters.");
+ }
+ }
+
+ // TODO: check for ASCII only characters
+ _comment = value;
+ }
+ }
+
+ /// Gets the compressed size of the entry data in bytes, or -1 if not known.
+ public long CompressedLength {
+ get { return _compressedLength; }
+ }
+
+ /// Gets the CRC-32 checksum of the uncompressed entry data.
+ public uint Crc {
+ get { return _crc; }
+ }
+
+ /// Gets and sets the optional extra field data for the entry.
+ /// ExtraField data cannot exceed 65535 bytes.
+ public byte[] ExtraField {
+ get {
+ return _extraField;
+ }
+ set {
+ if (value.Length > 0xffff) {
+ throw new ArgumentOutOfRangeException("ExtraField cannot not exceed 65535 bytes.");
+ }
+ _extraField = value;
+ }
+ }
+
+ /// Gets and sets the default compresion method for zip file entries. See for a list of possible values.
+ public CompressionMethod Method {
+ get { return _method; }
+ set { _method = value; }
+ }
+
+ /// Gets and sets the default compresion level for zip file entries. See for a partial list of values.
+ public int Level {
+ get { return _level; }
+ set {
+ if (value < -1 || value > 9) {
+ throw new ArgumentOutOfRangeException("Level", value, "Level value must be between -1 and 9.");
+ }
+ _level = value;
+ }
+ }
+
+ /// Gets the size of the uncompressed entry data in in bytes.
+ public long Length {
+ get { return _uncompressedLength; }
+ }
+
+ /// Gets and sets the modification time of the entry.
+ public DateTime ModifiedTime {
+ get { return _modifiedTime; }
+ set { _modifiedTime = value; }
+ }
+
+ /// Gets and sets the name of the entry.
+ ///
+ /// Currently only Ascii 8 bit characters are supported in comments.
+ /// A comment cannot exceed 65535 bytes.
+ ///
+ public string Name {
+ get { return _name; }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("Name cannot be null.");
+ }
+ if (value.Length > 0xffff) {
+ throw new ArgumentOutOfRangeException("Name cannot not exceed 65535 characters.");
+ }
+ if (!IsAscii(value)) {
+ throw new ArgumentException("Name can only contain Ascii 8 bit characters.");
+ }
+ // TODO: check for ASCII only characters
+ _name = value;
+ }
+ }
+
+ /// Flag that indicates if this entry is a directory or a file.
+ public bool IsDirectory {
+ get {
+ return (Length == 0 && CompressedLength == 0);
+ }
+ }
+
+ /// Gets the compression ratio as a percentage.
+ /// Returns -1.0 if unknown.
+ public float Ratio {
+ get {
+ float ratio = -1.0f;
+ if (Length > 0) {
+ ratio = Convert.ToSingle(Length - CompressedLength) / Length;
+ }
+ return ratio;
+ }
+ }
+
+ /// Returns a string representation of the Zip entry.
+ public override string ToString() {
+ return String.Format("{0} {1}", Name, base.ToString());
+ }
+
+ /// Check if only contains Ascii 8 bit characters.
+ static bool IsAscii(string str) {
+ foreach (char ch in str) {
+ if (ch > 0xff) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/src/Zip/ZipEntryCollection.cs b/src/Zip/ZipEntryCollection.cs
new file mode 100644
index 0000000..78102de
--- /dev/null
+++ b/src/Zip/ZipEntryCollection.cs
@@ -0,0 +1,195 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.Collections;
+
+namespace OrganicBit.Zip {
+
+ /// A collection that stores objects.
+ ///
+ [Serializable()]
+ public class ZipEntryCollection : CollectionBase {
+
+ /// Initializes a new instance of .
+ public ZipEntryCollection() {
+ }
+
+ /// Initializes a new instance of based on another .
+ /// A from which the contents are copied.
+ public ZipEntryCollection(ZipEntryCollection value) {
+ this.AddRange(value);
+ }
+
+ /// Initializes a new instance of containing any array of objects.
+ /// A array of objects with which to intialize the collection.
+ public ZipEntryCollection(ZipEntry[] value) {
+ this.AddRange(value);
+ }
+
+ /// Represents the entry at the specified index of the .
+ /// The zero-based index of the entry to locate in the collection.
+ ///
+ /// The entry at the specified index of the collection.
+ ///
+ /// is outside the valid range of indexes for the collection.
+ public ZipEntry this[int index] {
+ get {
+ return ((ZipEntry)(List[index]));
+ }
+ set {
+ List[index] = value;
+ }
+ }
+
+ /// Adds a with the specified value to the .
+ /// The to add.
+ /// The index at which the new element was inserted.
+ ///
+ public int Add(ZipEntry value) {
+ return List.Add(value);
+ }
+
+ /// Copies the elements of an array to the end of the .
+ /// An array of type containing the objects to add to the collection.
+ /// None.
+ ///
+ public void AddRange(ZipEntry[] value) {
+ for (int i = 0; (i < value.Length); i = (i + 1)) {
+ this.Add(value[i]);
+ }
+ }
+
+ /// Adds the contents of another to the end of the collection.
+ /// A containing the objects to add to the collection.
+ /// None.
+ ///
+ public void AddRange(ZipEntryCollection value) {
+ for (int i = 0; (i < value.Count); i = (i + 1)) {
+ this.Add(value[i]);
+ }
+ }
+
+ /// Gets a value indicating whether the contains the specified .
+ /// The to locate.
+ ///
+ /// if the is contained in the collection;
+ /// otherwise, .
+ ///
+ ///
+ public bool Contains(ZipEntry value) {
+ return List.Contains(value);
+ }
+
+ /// Copies the values to a one-dimensional instance at the specified index.
+ /// The one-dimensional that is the destination of the values copied from .
+ /// The index in where copying begins.
+ /// None.
+ /// is multidimensional. -or- The number of elements in the is greater than the available space between and the end of .
+ /// is .
+ /// is less than 's lowbound.
+ ///
+ public void CopyTo(ZipEntry[] array, int index) {
+ List.CopyTo(array, index);
+ }
+
+ /// Returns the index of a in the .
+ /// The to locate.
+ ///
+ /// The index of the of in the
+ /// , if found; otherwise, -1.
+ ///
+ ///
+ public int IndexOf(ZipEntry value) {
+ return List.IndexOf(value);
+ }
+
+ /// Inserts a into the at the specified index.
+ /// The zero-based index where should be inserted.
+ /// The to insert.
+ /// None.
+ ///
+ public void Insert(int index, ZipEntry value) {
+ List.Insert(index, value);
+ }
+
+ /// Returns an enumerator that can iterate through the .
+ /// None.
+ ///
+ public new ZipEntryEnumerator GetEnumerator() {
+ return new ZipEntryEnumerator(this);
+ }
+
+ /// Removes a specific from the .
+ /// The to remove from the .
+ /// None.
+ /// is not found in the Collection.
+ public void Remove(ZipEntry value) {
+ List.Remove(value);
+ }
+
+ /// Enumerator for .
+ public class ZipEntryEnumerator : object, IEnumerator {
+
+ private IEnumerator baseEnumerator;
+
+ private IEnumerable temp;
+
+ /// Initializes a new instance of the class.
+ public ZipEntryEnumerator(ZipEntryCollection mappings) {
+ this.temp = ((IEnumerable)(mappings));
+ this.baseEnumerator = temp.GetEnumerator();
+ }
+
+ /// Gets the current entry.
+ public ZipEntry Current {
+ get {
+ return ((ZipEntry)(baseEnumerator.Current));
+ }
+ }
+
+ object IEnumerator.Current {
+ get {
+ return baseEnumerator.Current;
+ }
+ }
+
+
+ /// Advance the enumerator to the next entry in the collection.
+ /// true if there are more entries; false if there are no more entires in the collection.
+ public bool MoveNext() {
+ return baseEnumerator.MoveNext();
+ }
+
+ bool IEnumerator.MoveNext() {
+ return baseEnumerator.MoveNext();
+ }
+
+ /// Set the enumerator to just before the start of the collection. Call to advance to the first entry in the collection.
+ public void Reset() {
+ baseEnumerator.Reset();
+ }
+
+ void IEnumerator.Reset() {
+ baseEnumerator.Reset();
+ }
+ }
+ }
+}
diff --git a/src/Zip/ZipException.cs b/src/Zip/ZipException.cs
new file mode 100644
index 0000000..eac22f1
--- /dev/null
+++ b/src/Zip/ZipException.cs
@@ -0,0 +1,51 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.Runtime.Serialization;
+
+namespace OrganicBit.Zip {
+
+ /// Thrown whenever an error occurs during the build.
+ [Serializable]
+ public class ZipException : ApplicationException {
+
+ /// Constructs an exception with no descriptive information.
+ public ZipException() : base() {
+ }
+
+ /// Constructs an exception with a descriptive message.
+ /// The error message that explains the reason for the exception.
+ public ZipException(String message) : base(message) {
+ }
+
+ /// Constructs an exception with a descriptive message and a reference to the instance of the Exception that is the root cause of the this exception.
+ /// The error message that explains the reason for the exception.
+ /// An instance of Exception that is the cause of the current Exception. If is non-null, then the current Exception is raised in a catch block handling innerException.
+ public ZipException(String message, Exception innerException) : base(message, innerException) {
+ }
+
+ /// Initializes a new instance of the BuildException class with serialized data.
+ /// The object that holds the serialized object data.
+ /// The contextual information about the source or destination.
+ public ZipException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/Zip/ZipLib.cs b/src/Zip/ZipLib.cs
new file mode 100644
index 0000000..310c956
--- /dev/null
+++ b/src/Zip/ZipLib.cs
@@ -0,0 +1,378 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace OrganicBit.Zip {
+
+ /// Support methods for uncompressing zip files.
+ ///
+ /// This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g WinZip, InfoZip tools and compatible.
+ /// Encryption and multi volume ZipFile (span) are not supported. Old compressions used by old PKZip 1.x are not supported.
+ /// Copyright (C) 1998 Gilles Vollant. http://www.winimage.com/zLibDll/unzip.htm
+ /// C# wrapper by Gerry Shaw (gerry_shaw@yahoo.com). http://www.organicbit.com/zip/
+ ///
+ internal sealed class ZipLib {
+
+ // prevent instances of this class from being constructed
+ private ZipLib() {}
+
+ /*
+ Create a zipfile.
+ pathname contain on Windows NT a filename like "c:\\zlib\\zlib111.zip" or on an Unix computer "zlib/zlib111.zip".
+ if the file pathname exist and append=1, the zip will be created at the end of the file. (useful if the file contain a self extractor code)
+ If the zipfile cannot be opened, the return value is NULL.
+ Else, the return value is a zipFile Handle, usable with other function of this zip package.
+ */
+ /// Create a zip file.
+ [DllImport("zlib.dll", ExactSpelling=true, CharSet=CharSet.Ansi)]
+ public static extern IntPtr zipOpen(string fileName, int append);
+
+ /*
+ Open a file in the ZIP for writing.
+ filename : the filename in zip (if NULL, '-' without quote will be used
+ *zipfi contain supplemental information
+ if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local contains the extrafield data the the local header
+ if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global contains the extrafield data the the local header
+ if comment != NULL, comment contain the comment string
+ method contain the compression method (0 for store, Z_DEFLATED for deflate)
+ level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
+ */
+ /// Open a new zip entry for writing.
+ [DllImport("zlib.dll", ExactSpelling=true, CharSet=CharSet.Ansi)]
+ unsafe public static extern int zipOpenNewFileInZip(IntPtr handle,
+ string entryName,
+ ZipFileEntryInfo* entryInfoPtr,
+ byte[] extraField,
+ uint extraFieldLength,
+ byte[] extraFieldGlobal,
+ uint extraFieldGlobalLength,
+ string comment,
+ int method,
+ int level);
+
+
+ /// Write data to the zip file.
+ [DllImport("zlib.dll")]
+ public static extern int zipWriteInFileInZip(IntPtr handle, byte[] buffer, uint count);
+
+ /// Close the current entry in the zip file.
+ [DllImport("zlib.dll")]
+ public static extern int zipCloseFileInZip(IntPtr handle);
+
+ /// Close the zip file.
+ [DllImport("zlib.dll", ExactSpelling=true, CharSet=CharSet.Ansi)]
+ public static extern int zipClose(IntPtr handle, string comment);
+
+
+ /// Opens a zip file for reading.
+ /// The name of the zip to open. At this time only file names with ANSI (8 bit) characters are supported.
+ ///
+ /// A handle usable with other functions of the ZipLib class.
+ /// Otherwise IntPtr.Zero if the zip file could not e opened (file doen not exist or is not valid).
+ ///
+ [DllImport("zlib.dll", ExactSpelling=true, CharSet=CharSet.Ansi)]
+ public static extern IntPtr unzOpen(string fileName);
+
+ /// Closes a zip file opened with unzipOpen.
+ /// The zip file handle opened by .
+ /// If there are files inside the zip file opened with these files must be closed with before call unzClose.
+ ///
+ /// Zero if there was no error.
+ /// Otherwise a value less than zero. See for the specific reason.
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzClose(IntPtr handle);
+
+ /// Get global information about the zip file.
+ /// The zip file handle opened by .
+ /// An address of a struct to hold the information. No preparation of the structure is needed.
+ ///
+ /// Zero if there was no error.
+ /// Otherwise a value less than zero. See for the specific reason.
+ ///
+ [DllImport("zlib.dll")]
+ public unsafe static extern int unzGetGlobalInfo(IntPtr handle, ZipFileInfo* globalInfoPtr);
+
+ /// Get the comment associated with the entire zip file.
+ /// The zip file handle opened by
+ /// The buffer to hold the comment.
+ /// The length of the buffer in bytes (8 bit characters).
+ ///
+ /// The number of characters in the comment if there was no error.
+ /// Otherwise a value less than zero. See for the specific reason.
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzGetGlobalComment(IntPtr handle, sbyte[] commentBuffer, uint commentBufferLength);
+
+ /// Set the current file of the zip file to the first file.
+ /// The zip file handle opened by .
+ ///
+ /// Zero if there was no error.
+ /// Otherwise a value less than zero. See for the specific reason.
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzGoToFirstFile(IntPtr handle);
+
+ /// Set the current file of the zip file to the next file.
+ /// The zip file handle opened by .
+ ///
+ /// Zero if there was no error.
+ /// Otherwise if there are no more entries.
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzGoToNextFile(IntPtr handle);
+
+ /// Try locate the entry in the zip file.
+ /// The zip file handle opened by .
+ /// The name of the entry to look for.
+ /// If 0 use the OS default. If 1 use case sensitivity like strcmp, Unix style. If 2 do not use case sensitivity like strcmpi, Windows style.
+ ///
+ /// Zero if there was no error.
+ /// Otherwise if there are no more entries.
+ ///
+ [DllImport("zlib.dll", ExactSpelling=true, CharSet=CharSet.Ansi)]
+ public static extern int unzLocateFile(IntPtr handle, string entryName, int caseSensitivity);
+
+ /// Get information about the current entry in the zip file.
+ /// The zip file handle opened by .
+ /// A ZipEntryInfo struct to hold information about the entry or null.
+ /// An array of sbyte characters to hold the entry name or null.
+ /// The length of the entryNameBuffer in bytes.
+ /// An array to hold the extra field data for the entry or null.
+ /// The length of the extraField array in bytes.
+ /// An array of sbyte characters to hold the entry name or null.
+ /// The length of theh commentBuffer in bytes.
+ ///
+ /// If entryInfoPtr is not null the structure will contain information about the current file.
+ /// If entryNameBuffer is not null the name of the entry will be copied into it.
+ /// If extraField is not null the extra field data of the entry will be copied into it.
+ /// If commentBuffer is not null the comment of the entry will be copied into it.
+ ///
+ ///
+ /// Zero if there was no error.
+ /// Otherwise a value less than zero. See for the specific reason.
+ ///
+ [DllImport("zlib.dll", ExactSpelling=true, CharSet=CharSet.Ansi)]
+ public unsafe static extern int unzGetCurrentFileInfo(IntPtr handle, ZipEntryInfo* entryInfoPtr,
+ sbyte[] entryNameBuffer, uint entryNameBufferLength,
+ byte[] extraField, uint extraFieldLength,
+ sbyte[] commentBuffer, uint commentBufferLength);
+
+ /// Open the zip file entry for reading.
+ /// The zip file handle opened by .
+ ///
+ /// Zero if there was no error.
+ /// Otherwise a value from .
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzOpenCurrentFile(IntPtr handle);
+
+ /// Close the file entry opened by .
+ /// The zip file handle opened by .
+ ///
+ /// Zero if there was no error.
+ /// CrcError if the file was read but the Crc does not match.
+ /// Otherwise a value from .
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzCloseCurrentFile(IntPtr handle);
+
+ /// Read bytes from the current zip file entry.
+ /// The zip file handle opened by .
+ /// Buffer to store the uncompressed data into.
+ /// Number of bytes to write from .
+ ///
+ /// The number of byte copied if somes bytes are copied.
+ /// Zero if the end of file was reached.
+ /// Less than zero with error code if there is an error. See for a list of possible error codes.
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzReadCurrentFile(IntPtr handle, byte[] buffer, uint count);
+
+ /// Give the current position in uncompressed data of the zip file entry currently opened.
+ /// The zip file handle opened by .
+ /// The number of bytes into the uncompressed data read so far.
+ [DllImport("zlib.dll")]
+ public static extern long unztell(IntPtr handle);
+
+ /// Determine if the end of the zip file entry has been reached.
+ /// The zip file handle opened by .
+ ///
+ /// One if the end of file was reached.
+ /// Zero if elsewhere.
+ ///
+ [DllImport("zlib.dll")]
+ public static extern int unzeof(IntPtr handle);
+
+ /// Converts a CLR string to a 8 bit ANSI array of characters.
+ /// The string to convert.
+ /// A 8 bit ANSI array of characters.
+ public static sbyte[] StringToAnsi(string str) {
+ int length = str.Length;
+ sbyte[] chars = new sbyte[length + 1];
+ for (int i = 0; i < length; i++) {
+ chars[i] = (sbyte) str[i];
+ }
+
+ return chars;
+ }
+
+ /// Converst an 8 bit ANSI C style string to a CLR string.
+ /// The array of a characters that holds the string.
+ /// The CLR string representing the characters passed in.
+ public static string AnsiToString(sbyte[] chars) {
+ int length = chars.Length;
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ builder.Append((char) chars[i]);
+ }
+ return builder.ToString();
+ }
+ }
+
+ /// List of possible error codes.
+ internal enum ErrorCode : int {
+ /// No error.
+ Ok = 0,
+
+ /// Unknown error.
+ Error = -1,
+
+ /// Last entry in directory reached.
+ EndOfListOfFile = -100,
+
+ /// Parameter error.
+ ParameterError = -102,
+
+ /// Zip file is invalid.
+ BadZipFile = -103,
+
+ /// Internal program error.
+ InternalError = -104,
+
+ /// Crc values do not match.
+ CrcError = -105
+ }
+
+ /// Global information about the zip file.
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct ZipFileInfo {
+ /// The number of entries in the directory.
+ public UInt32 EntryCount;
+
+ /// Length of zip file comment in bytes (8 bit characters).
+ public UInt32 CommentLength;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct ZipFileEntryInfo {
+ public ZipDateTimeInfo DateTime;
+ public UInt32 DosDate;
+ public UInt32 InternalFileAttributes; // 2 bytes
+ public UInt32 ExternalFileAttributes; // 4 bytes
+ }
+
+ /// Custom ZipLib date time structure.
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct ZipDateTimeInfo {
+ /// Seconds after the minute - [0,59]
+ public UInt32 Seconds;
+
+ /// Minutes after the hour - [0,59]
+ public UInt32 Minutes;
+
+ /// Hours since midnight - [0,23]
+ public UInt32 Hours;
+
+ /// Day of the month - [1,31]
+ public UInt32 Day;
+
+ /// Months since January - [0,11]
+ public UInt32 Month;
+
+ /// Years - [1980..2044]
+ public UInt32 Year;
+
+ // implicit conversion from DateTime to ZipDateTimeInfo
+ public static implicit operator ZipDateTimeInfo(DateTime date) {
+ ZipDateTimeInfo d;
+ d.Seconds = (uint) date.Second;
+ d.Minutes = (uint) date.Minute;
+ d.Hours = (uint) date.Hour;
+ d.Day = (uint) date.Day;
+ d.Month = (uint) date.Month - 1;
+ d.Year = (uint) date.Year;
+ return d;
+ }
+ }
+
+ /// Information stored in zip file directory about an entry.
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct ZipEntryInfo {
+ // Version made by (2 bytes).
+ public UInt32 Version;
+
+ /// Version needed to extract (2 bytes).
+ public UInt32 VersionNeeded;
+
+ /// General purpose bit flag (2 bytes).
+ public UInt32 Flag;
+
+ /// Compression method (2 bytes).
+ public UInt32 CompressionMethod;
+
+ /// Last mod file date in Dos fmt (4 bytes).
+ public UInt32 DosDate;
+
+ /// Crc-32 (4 bytes).
+ public UInt32 Crc;
+
+ /// Compressed size (4 bytes).
+ public UInt32 CompressedSize;
+
+ /// Uncompressed size (4 bytes).
+ public UInt32 UncompressedSize;
+
+ /// Filename length (2 bytes).
+ public UInt32 FileNameLength;
+
+ /// Extra field length (2 bytes).
+ public UInt32 ExtraFieldLength;
+
+ /// File comment length (2 bytes).
+ public UInt32 CommentLength;
+
+ /// Disk number start (2 bytes).
+ public UInt32 DiskStartNumber;
+
+ /// Internal file attributes (2 bytes).
+ public UInt32 InternalFileAttributes;
+
+ /// External file attributes (4 bytes).
+ public UInt32 ExternalFileAttributes;
+
+ /// File modification date of entry.
+ public ZipDateTimeInfo DateTime;
+ }
+}
diff --git a/src/Zip/ZipReader.cs b/src/Zip/ZipReader.cs
new file mode 100644
index 0000000..54bba75
--- /dev/null
+++ b/src/Zip/ZipReader.cs
@@ -0,0 +1,298 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.Collections;
+using System.Runtime.Serialization;
+
+namespace OrganicBit.Zip {
+
+ /// Provides support for reading files in the ZIP file format. Includes support for both compressed and uncompressed entries.
+ /// This example shows how to view the entries in a ZIP file.
+ ///
+ /// public static void View(string zipFileName) {
+ /// ZipReader reader = new ZipReader(zipFileName);
+ ///
+ /// Console.WriteLine("Archive: {0} ({1} files)", zipFileName, reader.Entries.Count);
+ /// Console.WriteLine(reader.Comment);
+ ///
+ /// string format = "{0,8} {1,8} {2,5} {3,10} {4,5} {5}";
+ /// Console.WriteLine(format, " Length ", " Size ", "Ratio", " Date ", "Time ", "Name");
+ /// Console.WriteLine(format, "--------", "--------", "-----", "----------", "-----", "----");
+ ///
+ /// foreach (ZipEntry entry in reader.Entries) {
+ /// if (!entry.IsDirectory) {
+ /// Console.WriteLine(format,
+ /// entry.Length,
+ /// entry.CompressedLength,
+ /// entry.Ratio.ToString("P0"),
+ /// entry.ModifiedTime.ToString("yyyy-MM-dd"),
+ /// entry.ModifiedTime.ToString("hh:mm"),
+ /// entry.Name);
+ /// }
+ /// }
+ /// reader.Close();
+ /// }
+ ///
+ ///
+ /// This example shows how to extract files from a ZIP file.
+ ///
+ /// public static void Extract(string zipFileName) {
+ /// ZipReader reader = new ZipReader(zipFileName);
+ /// Console.WriteLine("Archive: {0}", zipFileName);
+ /// Console.WriteLine(reader.Comment);
+ ///
+ /// // buffer to hold temp bytes
+ /// byte[] buffer = new byte[4096];
+ /// int byteCount;
+ ///
+ /// // Get the zipped entries
+ /// while (reader.MoveNext()) {
+ /// ZipEntry entry = reader.Current;
+ ///
+ /// if (entry.IsDirectory) {
+ /// Directory.CreateDirectory(entry.Name);
+ /// } else {
+ /// Console.Write(" {0}", entry.Name);
+ ///
+ /// // create output stream
+ /// FileStream writer = File.Open(entry.Name, FileMode.Create);
+ ///
+ /// // write uncompressed data
+ /// while ((byteCount = reader.Read(buffer, 0, buffer.Length)) > 0) {
+ /// Console.Write(".");
+ /// writer.Write(buffer, 0, byteCount);
+ /// }
+ /// writer.Close();
+ /// Console.WriteLine();
+ /// }
+ /// }
+ /// reader.Close();
+ /// }
+ ///
+ ///
+ public class ZipReader : IEnumerator, IDisposable {
+
+ /// ZipFile handle to read data from.
+ IntPtr _handle = IntPtr.Zero;
+
+ /// Name of zip file.
+ string _fileName = null;
+
+ /// Contents of zip file directory.
+ ZipEntryCollection _entries = null;
+
+ /// Global zip file comment.
+ string _comment = null;
+
+ /// True if an entry is open for reading.
+ bool _entryOpen = false;
+
+ /// Current zip entry open for reading.
+ ZipEntry _current = null;
+
+ /// Initializes a instance of the class for reading the zip file with the given name.
+ /// The name of zip file that will be read.
+ public ZipReader(string fileName) {
+ _fileName = fileName;
+ _handle = ZipLib.unzOpen(fileName);
+ if (_handle == IntPtr.Zero) {
+ string msg = String.Format("Could not open zip file '{0}'.", fileName);
+ throw new ZipException(msg);
+ }
+ }
+
+ /// Cleans up the resources used by this zip file.
+ ~ZipReader() {
+ CloseFile();
+ }
+
+ /// Dispose is synonym for Close.
+ void IDisposable.Dispose() {
+ Close();
+ }
+
+ /// Closes the zip file and releases any resources.
+ public void Close() {
+ // Free unmanaged resources.
+ CloseFile();
+
+ // If base type implements IDisposable we would call it here.
+
+ // Request the system not call the finalizer method for this object.
+ GC.SuppressFinalize(this);
+ }
+
+ /// Gets the name of the zip file that was passed to the constructor.
+ public string Name {
+ get { return _fileName; }
+ }
+
+ /// Gets the global comment for the zip file.
+ public string Comment {
+ get {
+ if (_comment == null) {
+ ZipFileInfo info;
+ int result = 0;
+ unsafe {
+ result = ZipLib.unzGetGlobalInfo(_handle, &info);
+ }
+ if (result < 0) {
+ string msg = String.Format("Could not read comment from zip file '{0}'.", Name);
+ throw new ZipException(msg);
+ }
+
+ sbyte[] buffer = new sbyte[info.CommentLength];
+ result = ZipLib.unzGetGlobalComment(_handle, buffer, (uint) buffer.Length);
+ if (result < 0) {
+ string msg = String.Format("Could not read comment from zip file '{0}'.", Name);
+ throw new ZipException(msg);
+ }
+ _comment = ZipLib.AnsiToString(buffer);
+ }
+ return _comment;
+ }
+ }
+
+ /// Gets a object that contains all the entries in the zip file directory.
+ public ZipEntryCollection Entries {
+ get {
+ if (_entries == null) {
+ _entries = new ZipEntryCollection();
+
+ int result = ZipLib.unzGoToFirstFile(_handle);
+ while (result == 0) {
+ ZipEntry entry = new ZipEntry(_handle);
+ _entries.Add(entry);
+ result = ZipLib.unzGoToNextFile(_handle);
+ }
+ }
+ return _entries;
+ }
+ }
+
+ object IEnumerator.Current {
+ get {
+ return _current;
+ }
+ }
+
+ /// Gets the current entry in the zip file..
+ public ZipEntry Current {
+ get {
+ return _current;
+ }
+ }
+
+ /// Advances the enumerator to the next element of the collection.
+ /// Sets to the next zip entry.
+ /// true if the next entry is not null; otherwise false.
+ public bool MoveNext() {
+ // close any open entry
+ CloseEntry();
+
+ int result;
+ if (_current == null) {
+ result = ZipLib.unzGoToFirstFile(_handle);
+ } else {
+ result = ZipLib.unzGoToNextFile(_handle);
+ }
+ if (result < 0) {
+ // last entry found - not an exceptional case
+ _current = null;
+ } else {
+ // entry found
+ OpenEntry();
+ }
+
+ return (_current != null);
+ }
+
+ /// Move to just before the first entry in the zip directory.
+ public void Reset() {
+ CloseEntry();
+ _current = null;
+ }
+
+ /// Seek to the specified entry.
+ /// The name of the entry to seek to.
+ public void Seek(string entryName) {
+ CloseEntry();
+ int result = ZipLib.unzLocateFile(_handle, entryName, 0);
+ if (result < 0) {
+ string msg = String.Format("Could not locate entry named '{0}'.", entryName);
+ throw new ZipException(msg);
+ }
+ OpenEntry();
+ }
+
+ private void OpenEntry() {
+ _current = new ZipEntry(_handle);
+ int result = ZipLib.unzOpenCurrentFile(_handle);
+ if (result < 0) {
+ _current = null;
+ throw new ZipException("Could not open entry for reading.");
+ }
+ _entryOpen = true;
+ }
+
+ /// Uncompress a block of bytes from the current zip entry and writes the data in a given buffer.
+ /// The array to write data into.
+ /// The byte offset in at which to begin writing.
+ /// The maximum number of bytes to read.
+ public int Read(byte[] buffer, int index, int count) {
+ if (index != 0) {
+ throw new ArgumentException("index", "Only index values of zero currently supported.");
+ }
+ int bytesRead = ZipLib.unzReadCurrentFile(_handle, buffer, (uint) count);
+ if (bytesRead < 0) {
+ throw new ZipException("Error reading zip entry.");
+ }
+ return bytesRead;
+ }
+
+ private void CloseEntry() {
+ if (_entryOpen) {
+ int result = ZipLib.unzCloseCurrentFile(_handle);
+ if (result < 0) {
+ switch ((ErrorCode) result) {
+ case ErrorCode.CrcError:
+ throw new ZipException("All the file was read but the CRC did not match.");
+
+ default:
+ throw new ZipException("Could not close zip entry.");
+ }
+ }
+ _entryOpen = false;
+ }
+ }
+
+ private void CloseFile() {
+ if (_handle != IntPtr.Zero) {
+ CloseEntry();
+ int result = ZipLib.unzClose(_handle);
+ if (result < 0) {
+ throw new ZipException("Could not close zip file.");
+ }
+ _handle = IntPtr.Zero;
+ }
+ }
+ }
+}
diff --git a/src/Zip/ZipWriter.cs b/src/Zip/ZipWriter.cs
new file mode 100644
index 0000000..0c3e4d5
--- /dev/null
+++ b/src/Zip/ZipWriter.cs
@@ -0,0 +1,181 @@
+// Copyright (C) 2001 Gerry Shaw
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would be
+// appreciated but is not required.
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+// 3. This notice may not be removed or altered from any source distribution.
+//
+// Gerry Shaw (gerry_shaw@yahoo.com)
+
+using System;
+using System.Runtime.Serialization;
+
+namespace OrganicBit.Zip {
+
+ /// Provides support for writing files in the ZIP file format. Includes support for both compressed and uncompressed entries.
+ /// This example shows how to create a ZIP file.
+ ///
+ /// public static void Add(string zipFileName, string[] entryPatterns) {
+ /// string currentDirectory = Directory.GetCurrentDirectory();
+ /// Console.WriteLine("Creating {0}", zipFileName);
+ ///
+ /// ZipWriter writer = new ZipWriter(zipFileName);
+ ///
+ /// // buffer to hold temp bytes
+ /// byte[] buffer = new byte[4096];
+ /// int byteCount;
+ ///
+ /// // add files to archive
+ /// foreach (string pattern in entryPatterns) {
+ /// foreach (string path in Directory.GetFiles(currentDirectory, pattern)) {
+ /// string fileName = Path.GetFileName(path);
+ /// Console.Write("Adding {0}", fileName);
+ ///
+ /// ZipEntry entry = new ZipEntry(fileName);
+ /// entry.ModifiedTime = File.GetLastWriteTime(fileName);
+ /// entry.Comment = "local file comment";
+ ///
+ /// writer.AddEntry(entry);
+ ///
+ /// FileStream reader = File.OpenRead(entry.Name);
+ /// while ((byteCount = reader.Read(buffer, 0, buffer.Length)) > 0) {
+ /// Console.Write(".");
+ /// writer.Write(buffer, 0, byteCount);
+ /// }
+ /// reader.Close();
+ /// Console.WriteLine();
+ /// }
+ /// }
+ ///
+ /// writer.Close();
+ /// }
+ ///
+ ///
+ public class ZipWriter : IDisposable {
+
+ /// Name of the zip file.
+ string _fileName;
+
+ /// Zip file global comment.
+ string _comment = "";
+
+ /// True if currently writing a new zip file entry.
+ bool _entryOpen = false;
+
+ /// Zip file handle.
+ IntPtr _handle = IntPtr.Zero;
+
+ /// Initializes a new instance fo the class with a specified file name. Any Existing file will be overwritten.
+ /// The name of the zip file to create.
+ public ZipWriter(string fileName) {
+ _fileName = fileName;
+
+ _handle = ZipLib.zipOpen(fileName, 0);
+ if (_handle == IntPtr.Zero) {
+ string msg = String.Format("Could not open zip file '{0}' for writing.", fileName);
+ throw new ZipException(msg);
+ }
+ }
+
+ /// Cleans up the resources used by this zip file.
+ ~ZipWriter() {
+ CloseFile();
+ }
+
+ /// Dispose is synonym for Close.
+ void IDisposable.Dispose() {
+ Close();
+ }
+
+ /// Closes the zip file and releases any resources.
+ public void Close() {
+ // Free unmanaged resources.
+ CloseFile();
+
+ // If base type implements IDisposable we would call it here.
+
+ // Request the system not call the finalizer method for this object.
+ GC.SuppressFinalize(this);
+ }
+
+ /// Gets the name of the zip file.
+ public string Name {
+ get {
+ return _fileName;
+ }
+ }
+
+ /// Gets and sets the zip file comment.
+ public string Comment {
+ get { return _comment; }
+ set { _comment = value; }
+ }
+
+ /// Creates a new zip entry in the directory and positions the stream to the start of the entry data.
+ /// The zip entry to be written.
+ /// Closes the current entry if still active.
+ public void AddEntry(ZipEntry entry) {
+ ZipFileEntryInfo info;
+ info.DateTime = entry.ModifiedTime;
+
+ int result;
+ unsafe {
+ byte[] extra = null;
+ uint extraLength = 0;
+ if (entry.ExtraField != null) {
+ extra = entry.ExtraField;
+ extraLength = (uint) entry.ExtraField.Length;
+ }
+
+ result = ZipLib.zipOpenNewFileInZip(
+ _handle,
+ entry.Name,
+ &info,
+ extra,
+ extraLength,
+ null, 0,
+ entry.Comment,
+ (int) entry.Method,
+ entry.Level);
+ }
+ _entryOpen = true;
+ }
+
+ /// Compress a block of bytes from the given buffer and writes them into the current zip entry.
+ /// The array to read data from.
+ /// The byte offset in at which to begin reading.
+ /// The maximum number of bytes to write.
+ public void Write(byte[] buffer, int index, int count) {
+ int result = ZipLib.zipWriteInFileInZip(_handle, buffer, (uint) count);
+ }
+
+ private void CloseEntry() {
+ if (_entryOpen) {
+ int result = ZipLib.zipCloseFileInZip(_handle);
+ _entryOpen = false;
+ }
+ }
+
+ void CloseFile() {
+ if (_handle != IntPtr.Zero) {
+ CloseEntry();
+ int result = ZipLib.zipClose(_handle, _comment);
+ if (result < 0) {
+ throw new ZipException("Could not close zip file.");
+ }
+ _handle = IntPtr.Zero;
+ }
+ }
+ }
+}