| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 | 
							- using System;
 
- using System.IO;
 
- using System.Text;
 
- namespace ICSharpCode.SharpZipLib.Zip
 
- {
 
- 	/// <summary>
 
- 	/// Holds data pertinent to a data descriptor.
 
- 	/// </summary>
 
- 	public class DescriptorData
 
- 	{
 
- 		/// <summary>
 
- 		/// Get /set the compressed size of data.
 
- 		/// </summary>
 
- 		public long CompressedSize {
 
- 			get { return compressedSize; }
 
- 			set { compressedSize = value; }
 
- 		}
 
- 		/// <summary>
 
- 		/// Get / set the uncompressed size of data
 
- 		/// </summary>
 
- 		public long Size {
 
- 			get { return size; }
 
- 			set { size = value; }
 
- 		}
 
- 		/// <summary>
 
- 		/// Get /set the crc value.
 
- 		/// </summary>
 
- 		public long Crc {
 
- 			get { return crc; }
 
- 			set { crc = (value & 0xffffffff); }
 
- 		}
 
- 		#region Instance Fields
 
- 		long size;
 
- 		long compressedSize;
 
- 		long crc;
 
- 		#endregion
 
- 	}
 
- 	class EntryPatchData
 
- 	{
 
- 		public long SizePatchOffset {
 
- 			get { return sizePatchOffset_; }
 
- 			set { sizePatchOffset_ = value; }
 
- 		}
 
- 		public long CrcPatchOffset {
 
- 			get { return crcPatchOffset_; }
 
- 			set { crcPatchOffset_ = value; }
 
- 		}
 
- 		#region Instance Fields
 
- 		long sizePatchOffset_;
 
- 		long crcPatchOffset_;
 
- 		#endregion
 
- 	}
 
- 	/// <summary>
 
- 	/// This class assists with writing/reading from Zip files.
 
- 	/// </summary>
 
- 	internal class ZipHelperStream : Stream
 
- 	{
 
- 		#region Constructors
 
- 		/// <summary>
 
- 		/// Initialise an instance of this class.
 
- 		/// </summary>
 
- 		/// <param name="name">The name of the file to open.</param>
 
- 		public ZipHelperStream(string name)
 
- 		{
 
- 			stream_ = new FileStream(name, FileMode.Open, FileAccess.ReadWrite);
 
- 			isOwner_ = true;
 
- 		}
 
- 		/// <summary>
 
- 		/// Initialise a new instance of <see cref="ZipHelperStream"/>.
 
- 		/// </summary>
 
- 		/// <param name="stream">The stream to use.</param>
 
- 		public ZipHelperStream(Stream stream)
 
- 		{
 
- 			stream_ = stream;
 
- 		}
 
- 		#endregion
 
- 		/// <summary>
 
- 		/// Get / set a value indicating wether the the underlying stream is owned or not.
 
- 		/// </summary>
 
- 		/// <remarks>If the stream is owned it is closed when this instance is closed.</remarks>
 
- 		public bool IsStreamOwner {
 
- 			get { return isOwner_; }
 
- 			set { isOwner_ = value; }
 
- 		}
 
- 		#region Base Stream Methods
 
- 		public override bool CanRead {
 
- 			get { return stream_.CanRead; }
 
- 		}
 
- 		public override bool CanSeek {
 
- 			get { return stream_.CanSeek; }
 
- 		}
 
- 		public override bool CanTimeout {
 
- 			get { return stream_.CanTimeout; }
 
- 		}
 
- 		public override long Length {
 
- 			get { return stream_.Length; }
 
- 		}
 
- 		public override long Position {
 
- 			get { return stream_.Position; }
 
- 			set { stream_.Position = value; }
 
- 		}
 
- 		public override bool CanWrite {
 
- 			get { return stream_.CanWrite; }
 
- 		}
 
- 		public override void Flush()
 
- 		{
 
- 			stream_.Flush();
 
- 		}
 
- 		public override long Seek(long offset, SeekOrigin origin)
 
- 		{
 
- 			return stream_.Seek(offset, origin);
 
- 		}
 
- 		public override void SetLength(long value)
 
- 		{
 
- 			stream_.SetLength(value);
 
- 		}
 
- 		public override int Read(byte[] buffer, int offset, int count)
 
- 		{
 
- 			return stream_.Read(buffer, offset, count);
 
- 		}
 
- 		public override void Write(byte[] buffer, int offset, int count)
 
- 		{
 
- 			stream_.Write(buffer, offset, count);
 
- 		}
 
- 		/// <summary>
 
- 		/// Close the stream.
 
- 		/// </summary>
 
- 		/// <remarks>
 
- 		/// The underlying stream is closed only if <see cref="IsStreamOwner"/> is true.
 
- 		/// </remarks>
 
- 		protected override void Dispose(bool disposing)
 
- 		{
 
- 			Stream toClose = stream_;
 
- 			stream_ = null;
 
- 			if (isOwner_ && (toClose != null)) {
 
- 				isOwner_ = false;
 
- 				toClose.Dispose();
 
- 			}
 
- 		}
 
- 		#endregion
 
- 		// Write the local file header
 
- 		// TODO: ZipHelperStream.WriteLocalHeader is not yet used and needs checking for ZipFile and ZipOuptutStream usage
 
- 		void WriteLocalHeader(ZipEntry entry, EntryPatchData patchData)
 
- 		{
 
- 			CompressionMethod method = entry.CompressionMethod;
 
- 			bool headerInfoAvailable = true; // How to get this?
 
- 			bool patchEntryHeader = false;
 
- 			WriteLEInt(ZipConstants.LocalHeaderSignature);
 
- 			WriteLEShort(entry.Version);
 
- 			WriteLEShort(entry.Flags);
 
- 			WriteLEShort((byte)method);
 
- 			WriteLEInt((int)entry.DosTime);
 
- 			if (headerInfoAvailable == true) {
 
- 				WriteLEInt((int)entry.Crc);
 
- 				if (entry.LocalHeaderRequiresZip64) {
 
- 					WriteLEInt(-1);
 
- 					WriteLEInt(-1);
 
- 				} else {
 
- 					WriteLEInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize);
 
- 					WriteLEInt((int)entry.Size);
 
- 				}
 
- 			} else {
 
- 				if (patchData != null) {
 
- 					patchData.CrcPatchOffset = stream_.Position;
 
- 				}
 
- 				WriteLEInt(0);  // Crc
 
- 				if (patchData != null) {
 
- 					patchData.SizePatchOffset = stream_.Position;
 
- 				}
 
- 				// For local header both sizes appear in Zip64 Extended Information
 
- 				if (entry.LocalHeaderRequiresZip64 && patchEntryHeader) {
 
- 					WriteLEInt(-1);
 
- 					WriteLEInt(-1);
 
- 				} else {
 
- 					WriteLEInt(0);  // Compressed size
 
- 					WriteLEInt(0);  // Uncompressed size
 
- 				}
 
- 			}
 
- 			byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
 
- 			if (name.Length > 0xFFFF) {
 
- 				throw new ZipException("Entry name too long.");
 
- 			}
 
- 			var ed = new ZipExtraData(entry.ExtraData);
 
- 			if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) {
 
- 				ed.StartNewEntry();
 
- 				if (headerInfoAvailable) {
 
- 					ed.AddLeLong(entry.Size);
 
- 					ed.AddLeLong(entry.CompressedSize);
 
- 				} else {
 
- 					ed.AddLeLong(-1);
 
- 					ed.AddLeLong(-1);
 
- 				}
 
- 				ed.AddNewEntry(1);
 
- 				if (!ed.Find(1)) {
 
- 					throw new ZipException("Internal error cant find extra data");
 
- 				}
 
- 				if (patchData != null) {
 
- 					patchData.SizePatchOffset = ed.CurrentReadIndex;
 
- 				}
 
- 			} else {
 
- 				ed.Delete(1);
 
- 			}
 
- 			byte[] extra = ed.GetEntryData();
 
- 			WriteLEShort(name.Length);
 
- 			WriteLEShort(extra.Length);
 
- 			if (name.Length > 0) {
 
- 				stream_.Write(name, 0, name.Length);
 
- 			}
 
- 			if (entry.LocalHeaderRequiresZip64 && patchEntryHeader) {
 
- 				patchData.SizePatchOffset += stream_.Position;
 
- 			}
 
- 			if (extra.Length > 0) {
 
- 				stream_.Write(extra, 0, extra.Length);
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Locates a block with the desired <paramref name="signature"/>.
 
- 		/// </summary>
 
- 		/// <param name="signature">The signature to find.</param>
 
- 		/// <param name="endLocation">Location, marking the end of block.</param>
 
- 		/// <param name="minimumBlockSize">Minimum size of the block.</param>
 
- 		/// <param name="maximumVariableData">The maximum variable data.</param>
 
- 		/// <returns>Eeturns the offset of the first byte after the signature; -1 if not found</returns>
 
- 		public long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData)
 
- 		{
 
- 			long pos = endLocation - minimumBlockSize;
 
- 			if (pos < 0) {
 
- 				return -1;
 
- 			}
 
- 			long giveUpMarker = Math.Max(pos - maximumVariableData, 0);
 
- 			// TODO: This loop could be optimised for speed.
 
- 			do {
 
- 				if (pos < giveUpMarker) {
 
- 					return -1;
 
- 				}
 
- 				Seek(pos--, SeekOrigin.Begin);
 
- 			} while (ReadLEInt() != signature);
 
- 			return Position;
 
- 		}
 
- 		/// <summary>
 
- 		/// Write Zip64 end of central directory records (File header and locator).
 
- 		/// </summary>
 
- 		/// <param name="noOfEntries">The number of entries in the central directory.</param>
 
- 		/// <param name="sizeEntries">The size of entries in the central directory.</param>
 
- 		/// <param name="centralDirOffset">The offset of the dentral directory.</param>
 
- 		public void WriteZip64EndOfCentralDirectory(long noOfEntries, long sizeEntries, long centralDirOffset)
 
- 		{
 
- 			long centralSignatureOffset = stream_.Position;
 
- 			WriteLEInt(ZipConstants.Zip64CentralFileHeaderSignature);
 
- 			WriteLELong(44);    // Size of this record (total size of remaining fields in header or full size - 12)
 
- 			WriteLEShort(ZipConstants.VersionMadeBy);   // Version made by
 
- 			WriteLEShort(ZipConstants.VersionZip64);   // Version to extract
 
- 			WriteLEInt(0);      // Number of this disk
 
- 			WriteLEInt(0);      // number of the disk with the start of the central directory
 
- 			WriteLELong(noOfEntries);       // No of entries on this disk
 
- 			WriteLELong(noOfEntries);       // Total No of entries in central directory
 
- 			WriteLELong(sizeEntries);       // Size of the central directory
 
- 			WriteLELong(centralDirOffset);  // offset of start of central directory
 
- 											// zip64 extensible data sector not catered for here (variable size)
 
- 			// Write the Zip64 end of central directory locator
 
- 			WriteLEInt(ZipConstants.Zip64CentralDirLocatorSignature);
 
- 			// no of the disk with the start of the zip64 end of central directory
 
- 			WriteLEInt(0);
 
- 			// relative offset of the zip64 end of central directory record
 
- 			WriteLELong(centralSignatureOffset);
 
- 			// total number of disks
 
- 			WriteLEInt(1);
 
- 		}
 
- 		/// <summary>
 
- 		/// Write the required records to end the central directory.
 
- 		/// </summary>
 
- 		/// <param name="noOfEntries">The number of entries in the directory.</param>
 
- 		/// <param name="sizeEntries">The size of the entries in the directory.</param>
 
- 		/// <param name="startOfCentralDirectory">The start of the central directory.</param>
 
- 		/// <param name="comment">The archive comment.  (This can be null).</param>
 
- 		public void WriteEndOfCentralDirectory(long noOfEntries, long sizeEntries,
 
- 			long startOfCentralDirectory, byte[] comment)
 
- 		{
 
- 			if ((noOfEntries >= 0xffff) ||
 
- 				(startOfCentralDirectory >= 0xffffffff) ||
 
- 				(sizeEntries >= 0xffffffff)) {
 
- 				WriteZip64EndOfCentralDirectory(noOfEntries, sizeEntries, startOfCentralDirectory);
 
- 			}
 
- 			WriteLEInt(ZipConstants.EndOfCentralDirectorySignature);
 
- 			// TODO: ZipFile Multi disk handling not done
 
- 			WriteLEShort(0);                    // number of this disk
 
- 			WriteLEShort(0);                    // no of disk with start of central dir
 
- 			// Number of entries
 
- 			if (noOfEntries >= 0xffff) {
 
- 				WriteLEUshort(0xffff);  // Zip64 marker
 
- 				WriteLEUshort(0xffff);
 
- 			} else {
 
- 				WriteLEShort((short)noOfEntries);          // entries in central dir for this disk
 
- 				WriteLEShort((short)noOfEntries);          // total entries in central directory
 
- 			}
 
- 			// Size of the central directory
 
- 			if (sizeEntries >= 0xffffffff) {
 
- 				WriteLEUint(0xffffffff);    // Zip64 marker
 
- 			} else {
 
- 				WriteLEInt((int)sizeEntries);
 
- 			}
 
- 			// offset of start of central directory
 
- 			if (startOfCentralDirectory >= 0xffffffff) {
 
- 				WriteLEUint(0xffffffff);    // Zip64 marker
 
- 			} else {
 
- 				WriteLEInt((int)startOfCentralDirectory);
 
- 			}
 
- 			int commentLength = (comment != null) ? comment.Length : 0;
 
- 			if (commentLength > 0xffff) {
 
- 				throw new ZipException(string.Format("Comment length({0}) is too long can only be 64K", commentLength));
 
- 			}
 
- 			WriteLEShort(commentLength);
 
- 			if (commentLength > 0) {
 
- 				Write(comment, 0, comment.Length);
 
- 			}
 
- 		}
 
- 		#region LE value reading/writing
 
- 		/// <summary>
 
- 		/// Read an unsigned short in little endian byte order.
 
- 		/// </summary>
 
- 		/// <returns>Returns the value read.</returns>
 
- 		/// <exception cref="IOException">
 
- 		/// An i/o error occurs.
 
- 		/// </exception>
 
- 		/// <exception cref="EndOfStreamException">
 
- 		/// The file ends prematurely
 
- 		/// </exception>
 
- 		public int ReadLEShort()
 
- 		{
 
- 			int byteValue1 = stream_.ReadByte();
 
- 			if (byteValue1 < 0) {
 
- 				throw new EndOfStreamException();
 
- 			}
 
- 			int byteValue2 = stream_.ReadByte();
 
- 			if (byteValue2 < 0) {
 
- 				throw new EndOfStreamException();
 
- 			}
 
- 			return byteValue1 | (byteValue2 << 8);
 
- 		}
 
- 		/// <summary>
 
- 		/// Read an int in little endian byte order.
 
- 		/// </summary>
 
- 		/// <returns>Returns the value read.</returns>
 
- 		/// <exception cref="IOException">
 
- 		/// An i/o error occurs.
 
- 		/// </exception>
 
- 		/// <exception cref="System.IO.EndOfStreamException">
 
- 		/// The file ends prematurely
 
- 		/// </exception>
 
- 		public int ReadLEInt()
 
- 		{
 
- 			return ReadLEShort() | (ReadLEShort() << 16);
 
- 		}
 
- 		/// <summary>
 
- 		/// Read a long in little endian byte order.
 
- 		/// </summary>
 
- 		/// <returns>The value read.</returns>
 
- 		public long ReadLELong()
 
- 		{
 
- 			return (uint)ReadLEInt() | ((long)ReadLEInt() << 32);
 
- 		}
 
- 		/// <summary>
 
- 		/// Write an unsigned short in little endian byte order.
 
- 		/// </summary>
 
- 		/// <param name="value">The value to write.</param>
 
- 		public void WriteLEShort(int value)
 
- 		{
 
- 			stream_.WriteByte((byte)(value & 0xff));
 
- 			stream_.WriteByte((byte)((value >> 8) & 0xff));
 
- 		}
 
- 		/// <summary>
 
- 		/// Write a ushort in little endian byte order.
 
- 		/// </summary>
 
- 		/// <param name="value">The value to write.</param>
 
- 		public void WriteLEUshort(ushort value)
 
- 		{
 
- 			stream_.WriteByte((byte)(value & 0xff));
 
- 			stream_.WriteByte((byte)(value >> 8));
 
- 		}
 
- 		/// <summary>
 
- 		/// Write an int in little endian byte order.
 
- 		/// </summary>
 
- 		/// <param name="value">The value to write.</param>
 
- 		public void WriteLEInt(int value)
 
- 		{
 
- 			WriteLEShort(value);
 
- 			WriteLEShort(value >> 16);
 
- 		}
 
- 		/// <summary>
 
- 		/// Write a uint in little endian byte order.
 
- 		/// </summary>
 
- 		/// <param name="value">The value to write.</param>
 
- 		public void WriteLEUint(uint value)
 
- 		{
 
- 			WriteLEUshort((ushort)(value & 0xffff));
 
- 			WriteLEUshort((ushort)(value >> 16));
 
- 		}
 
- 		/// <summary>
 
- 		/// Write a long in little endian byte order.
 
- 		/// </summary>
 
- 		/// <param name="value">The value to write.</param>
 
- 		public void WriteLELong(long value)
 
- 		{
 
- 			WriteLEInt((int)value);
 
- 			WriteLEInt((int)(value >> 32));
 
- 		}
 
- 		/// <summary>
 
- 		/// Write a ulong in little endian byte order.
 
- 		/// </summary>
 
- 		/// <param name="value">The value to write.</param>
 
- 		public void WriteLEUlong(ulong value)
 
- 		{
 
- 			WriteLEUint((uint)(value & 0xffffffff));
 
- 			WriteLEUint((uint)(value >> 32));
 
- 		}
 
- 		#endregion
 
- 		/// <summary>
 
- 		/// Write a data descriptor.
 
- 		/// </summary>
 
- 		/// <param name="entry">The entry to write a descriptor for.</param>
 
- 		/// <returns>Returns the number of descriptor bytes written.</returns>
 
- 		public int WriteDataDescriptor(ZipEntry entry)
 
- 		{
 
- 			if (entry == null) {
 
- 				throw new ArgumentNullException("nameof(entry)");
 
- 			}
 
- 			int result = 0;
 
- 			// Add data descriptor if flagged as required
 
- 			if ((entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) {
 
- 				// The signature is not PKZIP originally but is now described as optional
 
- 				// in the PKZIP Appnote documenting trhe format.
 
- 				WriteLEInt(ZipConstants.DataDescriptorSignature);
 
- 				WriteLEInt(unchecked((int)(entry.Crc)));
 
- 				result += 8;
 
- 				if (entry.LocalHeaderRequiresZip64) {
 
- 					WriteLELong(entry.CompressedSize);
 
- 					WriteLELong(entry.Size);
 
- 					result += 16;
 
- 				} else {
 
- 					WriteLEInt((int)entry.CompressedSize);
 
- 					WriteLEInt((int)entry.Size);
 
- 					result += 8;
 
- 				}
 
- 			}
 
- 			return result;
 
- 		}
 
- 		/// <summary>
 
- 		/// Read data descriptor at the end of compressed data.
 
- 		/// </summary>
 
- 		/// <param name="zip64">if set to <c>true</c> [zip64].</param>
 
- 		/// <param name="data">The data to fill in.</param>
 
- 		/// <returns>Returns the number of bytes read in the descriptor.</returns>
 
- 		public void ReadDataDescriptor(bool zip64, DescriptorData data)
 
- 		{
 
- 			int intValue = ReadLEInt();
 
- 			// In theory this may not be a descriptor according to PKZIP appnote.
 
- 			// In practise its always there.
 
- 			if (intValue != ZipConstants.DataDescriptorSignature) {
 
- 				throw new ZipException("Data descriptor signature not found");
 
- 			}
 
- 			data.Crc = ReadLEInt();
 
- 			if (zip64) {
 
- 				data.CompressedSize = ReadLELong();
 
- 				data.Size = ReadLELong();
 
- 			} else {
 
- 				data.CompressedSize = ReadLEInt();
 
- 				data.Size = ReadLEInt();
 
- 			}
 
- 		}
 
- 		#region Instance Fields
 
- 		bool isOwner_;
 
- 		Stream stream_;
 
- 		#endregion
 
- 	}
 
- }
 
 
  |