Click here to Skip to main content
15,895,142 members
Articles / Desktop Programming / Windows Forms

Deployer

Rate me:
Please Sign up or sign in to vote.
4.43/5 (17 votes)
30 Mar 2012Apache14 min read 82.3K   543   91  
Automate deployment of Windows Services, ClickOnce, and other .NET applications.
// 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 - Wrapping and enhancing the zlib
 * Copyright (C) 2005-06, Tyron Madlener <zlib@tyron.at>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * See COPYING for details
 */

using System;
using System.IO;

namespace UsefulHeap.Zip {
	/// <summary>Specifies how the the zip entry should be compressed.</summary>
	public enum CompressionMethod {
		/// <summary>No compression.</summary>
		Stored = 0,

		/// <summary>Default and only supported compression method.</summary>
		Deflated = 8
	}

	/// <summary>Specifies the amount of compression to apply to compressed zip entires.</summary>
	public enum CompressionLevel : int {
		/// <summary>Default compression level.  A good choice for speed and size.</summary>
		Default = -1,

		/// <summary>Do not perfrom compression.</summary>
		None = 0,

		/// <summary>Compress the entry as fast as possible size trading size for time.</summary>
		Fastest = 1,

		/// <summary>Compress the entry using a balance of size and time.</summary>
		Average = 5,

		/// <summary>Compress the entry to smallest possible size trading time for size.</summary>
		Smallest = 9
	}

	/// <summary>Represents a entry in a zip file.</summary>
	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;

		/// <summary>Initializes a instance of the <see cref="ZipEntry"/> class with the given name.</summary>
		/// <param name="name">The name of entry that will be stored in the directory of the zip file.</param>
		public ZipEntry(string name) {
			Name = name;
		}

		/// <summary>Creates a new Zip file entry reading values from a zip file.</summary>
		internal ZipEntry(IntPtr handle) {
			ZipEntryInfo entryInfo = new ZipEntryInfo();
			int result = 0;
			result = ZipLib.unzGetCurrentFileInfo(handle, out entryInfo, null, 0, null, 0, null, 0);

			if (result != 0) {		
				throw new ZipException("Could not read entries from zip file '"+Name+"'\nErrorcode "+result);
			}

			ExtraField = new byte[entryInfo.ExtraFieldLength];
			sbyte[] entryNameBuffer = new sbyte[entryInfo.FileNameLength];
			sbyte[] commentBuffer   = new sbyte[entryInfo.CommentLength];

			result = ZipLib.unzGetCurrentFileInfo(handle, out 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);
		}

		/// <summary>Gets and sets the local file comment for the entry.</summary>
		/// <remarks>
		///   <para>Currently only Ascii 8 bit characters are supported in comments.</para>
		///   <para>A comment cannot exceed 65535 bytes.</para>
		/// </remarks>
		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;
			}
		}

		/// <summary>Gets the compressed size of the entry data in bytes, or -1 if not known.</summary>
		public long CompressedLength {
			get { return _compressedLength; }
		}

		/// <summary>Gets the CRC-32 checksum of the uncompressed entry data.</summary>
		public uint Crc {
			get { return _crc; }
		}

		/// <summary>Gets and sets the optional extra field data for the entry.</summary>
		/// <remarks>ExtraField data cannot exceed 65535 bytes.</remarks>
		public byte[] ExtraField {
			get {
				return _extraField;
			}
			set {
				if (value.Length > 0xffff) {
					throw new ArgumentOutOfRangeException("ExtraField cannot not exceed 65535 bytes.");
				}
				_extraField = value;
			}
		}

		/// <summary>Gets and sets the default compresion method for zip file entries.  See <see cref="CompressionMethod"/> for a list of possible values.</summary>
		public CompressionMethod Method {
			get { return _method; }
			set { _method = value; }
		}

		/// <summary>Gets and sets the default compresion level for zip file entries.  See <see cref="CompressionMethod"/> for a partial list of values.</summary>
		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;
			}
		}

		/// <summary>Gets the size of the uncompressed entry data in in bytes.</summary>
		public long Length {
			get { return _uncompressedLength; }
		}

		/// <summary>Gets and sets the modification time of the entry.</summary>
		public DateTime ModifiedTime {
			get { return _modifiedTime; }
			set { _modifiedTime = value; }
		}

		/// <summary>Gets and sets the name of the entry.</summary>
		/// <remarks>
		///   <para>Currently only Ascii 8 bit characters are supported in comments.</para>
		///   <para>A comment cannot exceed 65535 bytes.</para>
		/// </remarks>
		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;
			}
		}

		/// <summary>Flag that indicates if this entry is a directory or a file.</summary>
		public bool IsDirectory {
			get {
				return (Length == 0 && CompressedLength == 0);
			}
		}

		/// <summary>Gets the compression ratio as a percentage.</summary>
		/// <remarks>Returns -1.0 if unknown.</remarks>
		public float Ratio {
			get {
				float ratio = -1.0f;
				if (Length > 0) {
					ratio = Convert.ToSingle(Length - CompressedLength) / Length;
				}
				return ratio;
			}
		}

		/// <summary>Returns a string representation of the Zip entry.</summary>
		public override string ToString() {
			return String.Format("{0} {1}", Name, base.ToString());
		}

		/// <summary>Check if <paramref name="str"/> only contains Ascii 8 bit characters.</summary>
		static bool IsAscii(string str) {
			foreach (char ch in str) {
				if (ch > 0xff) {
					return false;
				}
			}
			return true;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Apache License, Version 2.0


Written By
Chief Technology Officer
United States United States
If you liked this article, consider reading other articles by me. For republishing article on other websites, please contact me by leaving a comment.

Comments and Discussions