/// <summary>
        /// Add a new entry to the zip
        /// </summary>
        /// <param name="entry">
        /// The details about the header of the entry
        /// </param>
        public void Add(ZipEntry entry)
        {
            FileStream fs = null;

            fs = File.OpenRead(entry.Name);
            entry.Size = (Int32)fs.Length;
            entry.DateTime = File.GetLastWriteTime(entry.Name);
            PutNextHeader(entry);
            WriteCompressedFile(fs, entry);
        }
        /// <summary>
        /// Extracts the specified entry
        ///	</summary>
        /// <param name="entry">
        ///	The entry that is to be extracted.Cannot be null
        /// </param>
        /// <param name="jump">
        ///	The offset from the SeekOrigin.Begin at which the 
        /// comrpessed data is located
        /// </param>
        public void Extract(ZipEntry entry, long jump, string startPath)
        {
            DirectoryInfo dir = new DirectoryInfo(startPath + zipName);
            if (!dir.Exists)
                dir.Create();
            int index1 = entry.Name.IndexOf(ZipConstants.BackSlash);
            int index2 = entry.Name.LastIndexOf(ZipConstants.BackSlash);
            string relPath = entry.Name.Substring(index1 + 1,
                index2 - index1);
            if (index1 == 0)
                relPath = String.Empty;

            if (relPath.Length != 0)
                dir.CreateSubdirectory(relPath);
            baseStream.Seek(jump, SeekOrigin.Begin);
            jump = ZipConstants.FixedHeaderSize + entry.NameLength;
            baseStream.Seek(jump, SeekOrigin.Current);

            WriteUncompressedFile(entry, startPath + zipName +
                    ZipConstants.BackSlash + relPath);
        }
 private void WriteCompressedSizeCRC(Int32 value, byte[] crc,
     ZipEntry entry)
 {
     entry.CompressedSize = value;
     entry.SetCrc(crc);
     baseStream.Seek(offset, SeekOrigin.Begin);
     WriteLeInt32(entry.CompressedSize);
     WriteBytes(crc);
     //Remove the recorded offset
     offset = -1;
     baseStream.Seek(0, SeekOrigin.End);
 }
        /// <summary>
        /// Writes the compressed data into the basestream 
        /// It instantiates a memory stream which will serve 
        /// as a temp store and then compresses it using Gzip Stream or
        /// Deflate stream and writes it to the base stream
        /// </summary>
        private void WriteCompressedFile(FileStream fStream, ZipEntry entry)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                if (method == ZipConstants.DEFLATE)
                    zipStream = new DeflateStream(ms, CompressionMode.Compress,
                        true);
                else if (method == ZipConstants.GZIP)
                    zipStream = new GZipStream(ms, CompressionMode.Compress,
                        true);

                byte[] buffer = new byte[fStream.Length];
                fStream.Read(buffer, 0, buffer.Length);
                zipStream.Write(buffer, 0, buffer.Length);
                zipStream.Close();

                byte[] b = new byte[ms.Length];
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(b, 0, b.Length);
                baseStream.Write(b, 0, b.Length);
                //Go back and write the length and the CRC
                WriteCompressedSizeCRC((int)ms.Length, ComputeMD5(b), entry);
            }
        }
 /// <summary>
 /// Puts the next header in a predefined order
 /// </summary>
 /// <param name="entry">
 /// the ZipEntry which contains all the information
 /// </param>
 private void PutNextHeader(ZipEntry entry)
 {
     WriteLeInt32(entry.Size);
     //REcord the offset to write proper CRC and compressed size
     offset = baseStream.Position;
     WriteLeInt32(entry.CompressedSize);
     WriteBytes(entry.GetCrc());
     WriteLeInt32(entry.DosTime);
     WriteLeInt16(entry.NameLength);
     byte[] names = ConvertToArray(entry.Name);
     baseStream.Write(names, 0, names.Length);
 }
 /// <summary>
 /// Remove an entry from the archive
 /// </summary>
 /// <param name="jump">
 /// The offset of the file to be removed
 /// </param>
 public void Remove(long jump, ZipEntry entry)
 {
     long fileJump = ZipConstants.FixedHeaderSize +
             entry.NameLength +
             entry.CompressedSize;
     baseStream.Seek(jump + fileJump, SeekOrigin.Begin);
     long length = baseStream.Length - fileJump - jump;
     byte[] b = new byte[length];
     baseStream.Read(b, 0, (int)length);
     baseStream.Seek(jump, SeekOrigin.Begin);
     baseStream.Write(b, 0, (int)length);
     baseStream.SetLength(baseStream.Length - fileJump);
 }
        /// <summary>
        /// Writes the uncompressed data into the filename in the 
        /// entry. It instantiates a memory stream which will serve 
        /// as a temp store and decompresses it using Gzip Stream or
        /// Deflate stream
        /// </summary>
        private void WriteUncompressedFile(ZipEntry entry, string completePath)
        {
            MemoryStream ms = new MemoryStream();
            try
            {
                byte[] b = new byte[entry.CompressedSize];
                baseStream.Read(b, 0, (int)entry.CompressedSize);
                if (CheckCRC(entry.GetCrc(), b))
                    ms.Write(b, 0, b.Length);
                ms.Seek(0, SeekOrigin.Begin);
                if (method == ZipConstants.DEFLATE)
                    zipStream = new DeflateStream(ms,
                        CompressionMode.Decompress, false);
                else if (method == ZipConstants.GZIP)
                    zipStream = new GZipStream(ms, CompressionMode.Decompress,
                        false);

                int index = entry.Name.LastIndexOf(ZipConstants.BackSlash);
                string name = completePath + entry.Name.Substring(index + 1);
                FileStream rewrite = new FileStream(name, FileMode.Create);
                b = new byte[entry.Size];
                zipStream.Read(b, 0, (int)entry.Size);

                rewrite.Write(b, 0, (int)entry.Size);
                rewrite.Close();
            }
            finally
            {
                zipStream.Close();
                ms.Close();
            }
        }
        /// <summary>
        /// Open the next entry from the zip archive, and return its 
        /// description. The method expects the pointer to be intact.
        /// </summary>
        private ZipEntry GetNextEntry()
        {
            ZipEntry currentEntry = null;
            Int32 size = ReadLeInt32();
            if (size == -1)
                return new ZipEntry(String.Empty);

            Int32 csize = ReadLeInt32();
            byte[] crc = new byte[16];
            ReadBuf(crc, crc.Length);

            Int32 dostime = ReadLeInt32();
            Int16 nameLength = ReadLeInt16();

            byte[] buffer = new byte[nameLength];
            ReadBuf(buffer, nameLength);
            string name = ConvertToString(buffer);

            currentEntry = new ZipEntry(name);
            currentEntry.Size = size;
            currentEntry.CompressedSize = csize;
            currentEntry.SetCrc(crc);
            currentEntry.DosTime = dostime;

            return currentEntry;
        }
        public void Add(string fileName)
        {
            ZipEntry entry = new ZipEntry(fileName);
            thisWriter.Add(entry);

            zipEntries.Add(entry);
            thisWriter.CloseHeaders((Int16)zipEntries.Count);
        }