Exemplo n.º 1
0
        void WriteHeader()
        {
            if (state_ == OutputState.Header)
            {
                state_ = OutputState.Footer;

                var    mod_time   = (int)((DateTime.Now.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000L); // Ticks give back 100ns intervals
                byte[] gzipHeader =
                {
                    // The two magic bytes
                    (byte)(GZipConstants.GZIP_MAGIC >> 8), (byte)(GZipConstants.GZIP_MAGIC & 0xff),

                    // The compression type
                    (byte)Deflater.DEFLATED,

                    // The flags (not set)
                    0,

                    // The modification time
                    (byte)mod_time,                        (byte)(mod_time >> 8),
                    (byte)(mod_time >> 16),                (byte)(mod_time >> 24),

                    // The extra flags
                    0,

                    // The OS type (unknown)
                    (byte)255
                };
                BaseOutputStream.Write(gzipHeader, 0, gzipHeader.Length);
            }
        }
Exemplo n.º 2
0
 /// <summary>
 /// Write an unsigned short in little endian byte order.
 /// </summary>
 private void WriteLeShort(int value)
 {
     unchecked {
         BaseOutputStream.WriteByte((byte)(value & 0xff));
         BaseOutputStream.WriteByte((byte)((value >> 8) & 0xff));
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Finish compression and write any footer information required to stream
        /// </summary>
        public override void Finish()
        {
            // If no data has been written a header should be added.
            if (state_ == OutputState.Header)
            {
                WriteHeader();
            }

            if (state_ == OutputState.Footer)
            {
                state_ = OutputState.Finished;
                base.Finish();

                var totalin = (uint)(Deflater.TotalIn & 0xffffffff);
                var crcval  = (uint)(crc.Value & 0xffffffff);

                byte[] gzipFooter;

                unchecked
                {
                    gzipFooter = new byte[] {
                        (byte)crcval, (byte)(crcval >> 8),
                        (byte)(crcval >> 16), (byte)(crcval >> 24),

                        (byte)totalin, (byte)(totalin >> 8),
                        (byte)(totalin >> 16), (byte)(totalin >> 24)
                    };
                }

                BaseOutputStream.Write(gzipFooter, 0, gzipFooter.Length);
            }
        }
Exemplo n.º 4
0
 private void WriteAesHeader(ZipEntry entry)
 {
     byte[] buffer;
     byte[] buffer2;
     InitializeAesPassword(entry, Password, out buffer, out buffer2);
     BaseOutputStream.Write(buffer, 0, buffer.Length);
     BaseOutputStream.Write(buffer2, 0, buffer2.Length);
 }
Exemplo n.º 5
0
 internal RecordStream(TlsProtocol handler, Stream input, Stream output)
 {
     this.mHandler              = handler;
     this.mInput                = input;
     this.mOutput               = output;
     this.mReadCompression      = new TlsNullCompression();
     this.mWriteCompression     = this.mReadCompression;
     this.mHandshakeHashUpdater = new HandshakeHashUpdateStream(this);
 }
Exemplo n.º 6
0
 private void WriteEncryptionHeader(long crcValue)
 {
     _offset += 12L;
     InitializePassword(Password);
     byte[] buffer = new byte[12];
     new Random().NextBytes(buffer);
     buffer[11] = (byte)(crcValue >> 0x18);
     EncryptBlock(buffer, 0, buffer.Length);
     BaseOutputStream.Write(buffer, 0, buffer.Length);
 }
Exemplo n.º 7
0
 private void CopyAndEncrypt(byte[] buffer, int off, int count)
 {
     byte[] destinationArray = new byte[0x1000];
     while (count > 0)
     {
         int length = (count < 0x1000) ? count : 0x1000;
         Array.Copy(buffer, off, destinationArray, 0, length);
         EncryptBlock(destinationArray, 0, length);
         BaseOutputStream.Write(destinationArray, 0, length);
         count -= length;
         off   += length;
     }
 }
Exemplo n.º 8
0
        void WriteEncryptionHeader(long crcValue)
        {
            offset += ZipConstants.CryptoHeaderSize;


            byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize];
            var    rnd         = new Random();

            rnd.NextBytes(cryptBuffer);
            cryptBuffer[11] = (byte)(crcValue >> 24);

            BaseOutputStream.Write(cryptBuffer, 0, cryptBuffer.Length);
        }
Exemplo n.º 9
0
        void CopyAndEncrypt(byte[] buffer, int offset, int count)
        {
            const int CopyBufferSize = 4096;

            byte[] localBuffer = new byte[CopyBufferSize];
            while (count > 0)
            {
                int bufferCount = (count < CopyBufferSize) ? count : CopyBufferSize;

                Array.Copy(buffer, offset, localBuffer, 0, bufferCount);
                BaseOutputStream.Write(localBuffer, 0, bufferCount);
                count  -= bufferCount;
                offset += bufferCount;
            }
        }
Exemplo n.º 10
0
 private void WriteHeader()
 {
     if (_state == OutputState.Header)
     {
         _state = OutputState.Footer;
         DateTime time2   = new DateTime(0x7b2, 1, 1);
         int      num     = (int)((DateTime.Now.Ticks - time2.Ticks) / 0x989680L);
         byte[]   buffer2 = { 0x1f, 0x8b, 8, 0, 0, 0, 0, 0, 0, 0xff };
         buffer2[4] = (byte)num;
         buffer2[5] = (byte)(num >> 8);
         buffer2[6] = (byte)(num >> 0x10);
         buffer2[7] = (byte)(num >> 0x18);
         byte[] buffer = buffer2;
         BaseOutputStream.Write(buffer, 0, buffer.Length);
     }
 }
Exemplo n.º 11
0
 public override void Finish()
 {
     if (_state == OutputState.Header)
     {
         WriteHeader();
     }
     if (_state == OutputState.Footer)
     {
         _state = OutputState.Finished;
         base.Finish();
         uint   num    = (uint)(((ulong)Deflater.TotalIn) & 0xffffffffL);
         uint   num2   = (uint)(((ulong)_crc.Value) & 0xffffffffL);
         byte[] buffer = { (byte)num2, (byte)(num2 >> 8), (byte)(num2 >> 0x10), (byte)(num2 >> 0x18),
                           (byte)num,  (byte)(num >> 8),  (byte)(num >> 0x10),  (byte)(num >> 0x18) };
         BaseOutputStream.Write(buffer, 0, buffer.Length);
     }
 }
Exemplo n.º 12
0
 /// <summary>
 /// Writes remaining compressed output data to the output stream
 /// and closes it.
 /// </summary>
 protected override void Dispose(bool disposing)
 {
     try
     {
         Finish();
     }
     finally
     {
         if (state_ != OutputState.Closed)
         {
             state_ = OutputState.Closed;
             if (IsStreamOwner)
             {
                 BaseOutputStream.Dispose();
             }
         }
     }
 }
Exemplo n.º 13
0
 public override void Close()
 {
     try
     {
         Finish();
     }
     finally
     {
         if (_state != OutputState.Closed)
         {
             _state = OutputState.Closed;
             if (IsStreamOwner)
             {
                 BaseOutputStream.Close();
             }
         }
     }
 }
Exemplo n.º 14
0
        /// <summary>
        /// Deflates everything in the input buffers.  This will call
        /// <code>def.deflate()</code> until all bytes from the input buffers
        /// are processed.
        /// </summary>
        protected void Deflate()
        {
            while (!Deflater.IsNeedingInput)
            {
                var deflate_count = Deflater.Deflate(_buffer, 0, _buffer.Length);

                if (deflate_count <= 0)
                {
                    break;
                }

                BaseOutputStream.Write(_buffer, 0, deflate_count);
            }

            if (!Deflater.IsNeedingInput)
            {
                throw new SharpZipBaseException("DeflaterOutputStream can't deflate all input?");
            }
        }
Exemplo n.º 15
0
        public override void Write(byte[] buffer, int off, int count)
        {
            if (_curEntry == null)
            {
                throw new InvalidOperationException("No open entry.");
            }
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (off < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(off), "Cannot be negative");
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "Cannot be negative");
            }
            if ((buffer.Length - off) < count)
            {
                throw new ArgumentException("Invalid offset/count combination");
            }
            _crc.Update(buffer, off, count);
            _size += count;
            switch (_curMethod)
            {
            case CompressionMethod.Stored:
                if (Password != null)
                {
                    CopyAndEncrypt(buffer, off, count);
                }
                else
                {
                    BaseOutputStream.Write(buffer, off, count);
                }
                break;

            case CompressionMethod.Deflated:
                Write(buffer, off, count);
                break;
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Calls <see cref="Finish"/> and closes the underlying
        /// stream when <see cref="IsStreamOwner"></see> is true.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (_is_closed)
            {
                return;
            }
            _is_closed = true;

            try
            {
                Finish();
            }
            finally
            {
                if (IsStreamOwner)
                {
                    BaseOutputStream.Dispose();
                }
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Writes the given buffer to the current entry.
        /// </summary>
        /// <param name="buffer">The buffer containing data to write.</param>
        /// <param name="offset">The offset of the first byte to write.</param>
        /// <param name="count">The number of bytes to write.</param>
        /// <exception cref="ZipException">Archive size is invalid</exception>
        /// <exception cref="System.InvalidOperationException">No entry is active.</exception>
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (curEntry == null)
            {
                throw new InvalidOperationException("No open entry.");
            }

            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset), "Cannot be negative");
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "Cannot be negative");
            }

            if ((buffer.Length - offset) < count)
            {
                throw new ArgumentException("Invalid offset/count combination");
            }

            crc.Update(new ArraySegment <byte>(buffer, offset, count));
            size += count;

            switch (curMethod)
            {
            case CompressionMethod.Deflated:
                base.Write(buffer, offset, count);
                break;

            case CompressionMethod.Stored:
                BaseOutputStream.Write(buffer, offset, count);
                break;
            }
        }
Exemplo n.º 18
0
        /// <summary>
        /// Finishes the stream by calling finish() on the deflater.
        /// </summary>
        /// <exception cref="SharpZipBaseException">
        /// Not all input is deflated
        /// </exception>
        public virtual void Finish()
        {
            Deflater.Finish();
            while (!Deflater.IsFinished)
            {
                int len = Deflater.Deflate(_buffer, 0, _buffer.Length);
                if (len <= 0)
                {
                    break;
                }

                BaseOutputStream.Write(_buffer, 0, len);
            }

            if (!Deflater.IsFinished)
            {
                throw new SharpZipBaseException("Can't deflate all input?");
            }

            BaseOutputStream.Flush();
        }
Exemplo n.º 19
0
        /// <summary>
        /// Calls <see cref="Finish"/> and closes the underlying
        /// stream when <see cref="IsStreamOwner"></see> is true.
        /// </summary>
        /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (!isClosed)
            {
                isClosed = true;

                try
                {
                    Finish();
                    if (CryptoTransform != null)
                    {
                        CryptoTransform.Dispose();
                        CryptoTransform = null;
                    }
                }
                finally
                {
                    if (IsStreamOwner)
                    {
                        BaseOutputStream.Dispose();
                    }
                }
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// Deflates everything in the input buffers.  This will call.
        /// <code>def.deflate()</code> until all bytes from the input buffers
        /// are processed.
        /// </summary>
        protected void Deflate()
        {
            while (!Deflater.IsNeedingInput)
            {
                var deflateCount = Deflater.Deflate(buffer, 0, buffer.Length);

                if (deflateCount <= 0)
                {
                    break;
                }

                if (CryptoTransform != null)
                {
                    EncryptBlock(buffer, 0, deflateCount);
                }

                BaseOutputStream.Write(buffer, 0, deflateCount);
            }

            if (!Deflater.IsNeedingInput)
            {
                throw new InvalidDataException("DeflaterOutputStream can't deflate all input?");
            }
        }
Exemplo n.º 21
0
        public void CloseEntry()
        {
            if (_curEntry == null)
            {
                throw new InvalidOperationException("No open entry");
            }
            long compressedSize = _size;

            if (_curMethod == CompressionMethod.Deflated)
            {
                if (_size >= 0L)
                {
                    Finish();
                    compressedSize = Deflater.TotalOut;
                }
                else
                {
                    Deflater.Reset();
                }
            }
            if (_curEntry.AesKeySize > 0)
            {
                BaseOutputStream.Write(AesAuthCode, 0, 10);
            }
            if (_curEntry.Size < 0L)
            {
                _curEntry.Size = _size;
            }
            else if (_curEntry.Size != _size)
            {
                throw new ZipException(string.Concat("size was ", _size, ", but I expected ", _curEntry.Size));
            }
            if (_curEntry.CompressedSize < 0L)
            {
                _curEntry.CompressedSize = compressedSize;
            }
            else if (_curEntry.CompressedSize != compressedSize)
            {
                throw new ZipException(string.Concat("compressed size was ", compressedSize, ", but I expected ", _curEntry.CompressedSize));
            }
            if (_curEntry.Crc < 0L)
            {
                _curEntry.Crc = _crc.Value;
            }
            else if (_curEntry.Crc != _crc.Value)
            {
                throw new ZipException(string.Concat("crc was ", _crc.Value, ", but I expected ", _curEntry.Crc));
            }
            _offset += compressedSize;
            if (_curEntry.IsCrypted)
            {
                if (_curEntry.AesKeySize > 0)
                {
                    _curEntry.CompressedSize += _curEntry.AesOverheadSize;
                }
                else
                {
                    _curEntry.CompressedSize += 12L;
                }
            }
            if (_patchEntryHeader)
            {
                _patchEntryHeader = false;
                long position = BaseOutputStream.Position;
                BaseOutputStream.Seek(_crcPatchPos, SeekOrigin.Begin);
                WriteLeInt((int)_curEntry.Crc);
                if (_curEntry.LocalHeaderRequiresZip64)
                {
                    if (_sizePatchPos == -1L)
                    {
                        throw new ZipException("Entry requires zip64 but this has been turned off");
                    }
                    BaseOutputStream.Seek(_sizePatchPos, SeekOrigin.Begin);
                    WriteLeLong(_curEntry.Size);
                    WriteLeLong(_curEntry.CompressedSize);
                }
                else
                {
                    WriteLeInt((int)_curEntry.CompressedSize);
                    WriteLeInt((int)_curEntry.Size);
                }
                BaseOutputStream.Seek(position, SeekOrigin.Begin);
            }
            if ((_curEntry.Flags & 8) != 0)
            {
                WriteLeInt(ZipConstants.DataDescriptorSignature);
                WriteLeInt((int)_curEntry.Crc);
                if (_curEntry.LocalHeaderRequiresZip64)
                {
                    WriteLeLong(_curEntry.CompressedSize);
                    WriteLeLong(_curEntry.Size);
                    _offset += 0x18L;
                }
                else
                {
                    WriteLeInt((int)_curEntry.CompressedSize);
                    WriteLeInt((int)_curEntry.Size);
                    _offset += 0x10L;
                }
            }
            _entries.Add(_curEntry);
            _curEntry = null;
        }
Exemplo n.º 22
0
 /// <summary>
 /// Flushes the stream by calling <see cref="Flush">Flush</see> on the deflater and then
 /// on the underlying stream.  This ensures that all bytes are flushed.
 /// </summary>
 public override void Flush()
 {
     Deflater.Flush();
     Deflate();
     BaseOutputStream.Flush();
 }
Exemplo n.º 23
0
        /// <summary>
        /// Closes the current entry, updating header and footer information as required
        /// </summary>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurs.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// No entry is active.
        /// </exception>
        public void CloseEntry()
        {
            if (curEntry == null)
            {
                throw new InvalidOperationException("No open entry");
            }

            long csize = size;

            // First finish the deflater, if appropriate
            if (curMethod == CompressionMethod.Deflated)
            {
                if (size >= 0)
                {
                    base.Finish();
                    csize = Deflater.TotalOut;
                }
                else
                {
                    Deflater.Reset();
                }
            }


            if (curEntry.Size < 0)
            {
                curEntry.Size = size;
            }
            else if (curEntry.Size != size)
            {
                throw new ZipException("size was " + size + ", but I expected " + curEntry.Size);
            }

            if (curEntry.CompressedSize < 0)
            {
                curEntry.CompressedSize = csize;
            }
            else if (curEntry.CompressedSize != csize)
            {
                throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize);
            }

            if (curEntry.Crc < 0)
            {
                curEntry.Crc = crc.Value;
            }
            else if (curEntry.Crc != crc.Value)
            {
                throw new ZipException("crc was " + crc.Value + ", but I expected " + curEntry.Crc);
            }

            offset += csize;

            if (curEntry.IsCrypted)
            {
                if (curEntry.AESKeySize > 0)
                {
                    curEntry.CompressedSize += curEntry.AESOverheadSize;
                }
                else
                {
                    curEntry.CompressedSize += ZipConstants.CryptoHeaderSize;
                }
            }

            // Patch the header if possible
            if (patchEntryHeader)
            {
                patchEntryHeader = false;

                long curPos = BaseOutputStream.Position;
                BaseOutputStream.Seek(crcPatchPos, SeekOrigin.Begin);
                WriteLeInt((int)curEntry.Crc);

                if (curEntry.LocalHeaderRequiresZip64)
                {
                    if (sizePatchPos == -1)
                    {
                        throw new ZipException("Entry requires zip64 but this has been turned off");
                    }

                    BaseOutputStream.Seek(sizePatchPos, SeekOrigin.Begin);
                    WriteLeLong(curEntry.Size);
                    WriteLeLong(curEntry.CompressedSize);
                }
                else
                {
                    WriteLeInt((int)curEntry.CompressedSize);
                    WriteLeInt((int)curEntry.Size);
                }
                BaseOutputStream.Seek(curPos, SeekOrigin.Begin);
            }

            // Add data descriptor if flagged as required
            if ((curEntry.Flags & 8) != 0)
            {
                WriteLeInt(ZipConstants.DataDescriptorSignature);
                WriteLeInt(unchecked ((int)curEntry.Crc));

                if (curEntry.LocalHeaderRequiresZip64)
                {
                    WriteLeLong(curEntry.CompressedSize);
                    WriteLeLong(curEntry.Size);
                    offset += ZipConstants.Zip64DataDescriptorSize;
                }
                else
                {
                    WriteLeInt((int)curEntry.CompressedSize);
                    WriteLeInt((int)curEntry.Size);
                    offset += ZipConstants.DataDescriptorSize;
                }
            }

            entries.Add(curEntry);
            curEntry = null;
        }
Exemplo n.º 24
0
        /// <summary>
        /// Finishes the stream.  This will write the central directory at the
        /// end of the zip file and flush the stream.
        /// </summary>
        /// <remarks>
        /// This is automatically called when the stream is closed.
        /// </remarks>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurs.
        /// </exception>
        /// <exception cref="ZipException">
        /// Comment exceeds the maximum length<br/>
        /// Entry name exceeds the maximum length
        /// </exception>
        public override void Finish()
        {
            if (entries == null)
            {
                return;
            }

            if (curEntry != null)
            {
                CloseEntry();
            }

            long numEntries  = entries.Count;
            long sizeEntries = 0;

            foreach (ZipEntry entry in entries)
            {
                WriteLeInt(ZipConstants.CentralHeaderSignature);
                WriteLeShort(ZipConstants.VersionMadeBy);
                WriteLeShort(entry.Version);
                WriteLeShort(entry.Flags);
                WriteLeShort((short)entry.CompressionMethodForHeader);
                WriteLeInt((int)entry.DosTime);
                WriteLeInt((int)entry.Crc);

                if (entry.IsZip64Forced() ||
                    (entry.CompressedSize >= uint.MaxValue))
                {
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt((int)entry.CompressedSize);
                }

                if (entry.IsZip64Forced() ||
                    (entry.Size >= uint.MaxValue))
                {
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt((int)entry.Size);
                }

                byte[] name = ZipStrings.ConvertToArray(entry.Flags, entry.Name);

                if (name.Length > 0xffff)
                {
                    throw new ZipException("Name too long.");
                }

                var ed = new ZipExtraData(entry.ExtraData);

                if (entry.CentralHeaderRequiresZip64)
                {
                    ed.StartNewEntry();
                    if (entry.IsZip64Forced() ||
                        (entry.Size >= 0xffffffff))
                    {
                        ed.AddLeLong(entry.Size);
                    }

                    if (entry.IsZip64Forced() ||
                        (entry.CompressedSize >= 0xffffffff))
                    {
                        ed.AddLeLong(entry.CompressedSize);
                    }

                    if (entry.Offset >= 0xffffffff)
                    {
                        ed.AddLeLong(entry.Offset);
                    }

                    ed.AddNewEntry(1);
                }
                else
                {
                    ed.Delete(1);
                }

                if (entry.AESKeySize > 0)
                {
                    AddExtraDataAES(entry, ed);
                }
                byte[] extra = ed.GetEntryData();

                byte[] entryComment =
                    (entry.Comment != null) ?
                    ZipStrings.ConvertToArray(entry.Flags, entry.Comment) :
                    new byte[0];

                if (entryComment.Length > 0xffff)
                {
                    throw new ZipException("Comment too long.");
                }

                WriteLeShort(name.Length);
                WriteLeShort(extra.Length);
                WriteLeShort(entryComment.Length);
                WriteLeShort(0);                    // disk number
                WriteLeShort(0);                    // internal file attributes
                // external file attributes

                if (entry.ExternalFileAttributes != -1)
                {
                    WriteLeInt(entry.ExternalFileAttributes);
                }
                else
                {
                    if (entry.IsDirectory)                                               // mark entry as directory (from nikolam.AT.perfectinfo.com)
                    {
                        WriteLeInt(16);
                    }
                    else
                    {
                        WriteLeInt(0);
                    }
                }

                if (entry.Offset >= uint.MaxValue)
                {
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt((int)entry.Offset);
                }

                if (name.Length > 0)
                {
                    BaseOutputStream.Write(name, 0, name.Length);
                }

                if (extra.Length > 0)
                {
                    BaseOutputStream.Write(extra, 0, extra.Length);
                }

                if (entryComment.Length > 0)
                {
                    BaseOutputStream.Write(entryComment, 0, entryComment.Length);
                }

                sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length;
            }

            using (ZipHelperStream zhs = new ZipHelperStream(BaseOutputStream)) {
                zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment);
            }

            entries = null;
        }
Exemplo n.º 25
0
 public override void Finish()
 {
     if (_entries != null)
     {
         if (_curEntry != null)
         {
             CloseEntry();
         }
         long count       = _entries.Count;
         long sizeEntries = 0L;
         foreach (ZipEntry entry in _entries)
         {
             WriteLeInt(ZipConstants.CentralHeaderSignature);
             WriteLeShort(0x33);
             WriteLeShort(entry.Version);
             WriteLeShort(entry.Flags);
             WriteLeShort((short)entry.CompressionMethodForHeader);
             WriteLeInt((int)entry.DosTime);
             WriteLeInt((int)entry.Crc);
             if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.CompressedSize);
             }
             if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.Size);
             }
             byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
             if (buffer.Length > 0xffff)
             {
                 throw new ZipException("Name too long.");
             }
             ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
             if (entry.CentralHeaderRequiresZip64)
             {
                 extraData.StartNewEntry();
                 if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
                 {
                     extraData.AddLeLong(entry.Size);
                 }
                 if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
                 {
                     extraData.AddLeLong(entry.CompressedSize);
                 }
                 if (entry.Offset >= 0xffffffffL)
                 {
                     extraData.AddLeLong(entry.Offset);
                 }
                 extraData.AddNewEntry(1);
             }
             else
             {
                 extraData.Delete(1);
             }
             if (entry.AesKeySize > 0)
             {
                 AddExtraDataAes(entry, extraData);
             }
             byte[] entryData = extraData.GetEntryData();
             byte[] buffer3   = (entry.Comment != null) ? ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : new byte[0];
             if (buffer3.Length > 0xffff)
             {
                 throw new ZipException("Comment too long.");
             }
             WriteLeShort(buffer.Length);
             WriteLeShort(entryData.Length);
             WriteLeShort(buffer3.Length);
             WriteLeShort(0);
             WriteLeShort(0);
             if (entry.ExternalFileAttributes != -1)
             {
                 WriteLeInt(entry.ExternalFileAttributes);
             }
             else if (entry.IsDirectory)
             {
                 WriteLeInt(0x10);
             }
             else
             {
                 WriteLeInt(0);
             }
             if (entry.Offset >= 0xffffffffL)
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.Offset);
             }
             if (buffer.Length > 0)
             {
                 BaseOutputStream.Write(buffer, 0, buffer.Length);
             }
             if (entryData.Length > 0)
             {
                 BaseOutputStream.Write(entryData, 0, entryData.Length);
             }
             if (buffer3.Length > 0)
             {
                 BaseOutputStream.Write(buffer3, 0, buffer3.Length);
             }
             sizeEntries += ((ZipConstants.CentralHeaderBaseSize + buffer.Length) + entryData.Length) + buffer3.Length;
         }
         using (ZipHelperStream stream = new ZipHelperStream(BaseOutputStream))
         {
             stream.WriteEndOfCentralDirectory(count, sizeEntries, _offset, _zipComment);
         }
         _entries = null;
     }
 }
Exemplo n.º 26
0
        public void PutNextEntry(ZipEntry entry)
        {
            bool hasCrc;

            if (entry == null)
            {
                throw new ArgumentNullException(nameof(entry));
            }
            if (_entries == null)
            {
                throw new InvalidOperationException("ZipOutputStream was finished");
            }
            if (_curEntry != null)
            {
                CloseEntry();
            }
            if (_entries.Count == 0x7fffffff)
            {
                throw new ZipException("Too many entries for Zip file");
            }
            CompressionMethod compressionMethod = entry.CompressionMethod;
            int compressionLevel = _defaultCompressionLevel;

            entry.Flags      &= 0x800;
            _patchEntryHeader = false;
            if (entry.Size == 0L)
            {
                entry.CompressedSize = entry.Size;
                entry.Crc            = 0L;
                compressionMethod    = CompressionMethod.Stored;
                hasCrc = true;
            }
            else
            {
                hasCrc = (entry.Size >= 0L) && entry.HasCrc;
                if (compressionMethod == CompressionMethod.Stored)
                {
                    if (!hasCrc)
                    {
                        if (!CanPatchEntries)
                        {
                            compressionMethod = CompressionMethod.Deflated;
                            compressionLevel  = 0;
                        }
                    }
                    else
                    {
                        entry.CompressedSize = entry.Size;
                        hasCrc = entry.HasCrc;
                    }
                }
            }
            if (!hasCrc)
            {
                if (!CanPatchEntries)
                {
                    entry.Flags |= 8;
                }
                else
                {
                    _patchEntryHeader = true;
                }
            }
            if (Password != null)
            {
                entry.IsCrypted = true;
                if (entry.Crc < 0L)
                {
                    entry.Flags |= 8;
                }
            }
            entry.Offset            = _offset;
            entry.CompressionMethod = compressionMethod;
            _curMethod    = compressionMethod;
            _sizePatchPos = -1L;
            if ((_useZip64 == UseZip64.On) || ((entry.Size < 0L) && (_useZip64 == UseZip64.Dynamic)))
            {
                entry.ForceZip64();
            }
            WriteLeInt(ZipConstants.LocalHeaderSignature);
            WriteLeShort(entry.Version);
            WriteLeShort(entry.Flags);
            WriteLeShort((byte)entry.CompressionMethodForHeader);
            WriteLeInt((int)entry.DosTime);
            if (hasCrc)
            {
                WriteLeInt((int)entry.Crc);
                if (entry.LocalHeaderRequiresZip64)
                {
                    WriteLeInt(-1);
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt(entry.IsCrypted ? (((int)entry.CompressedSize) + 12) : ((int)entry.CompressedSize));
                    WriteLeInt((int)entry.Size);
                }
            }
            else
            {
                if (_patchEntryHeader)
                {
                    _crcPatchPos = BaseOutputStream.Position;
                }
                WriteLeInt(0);
                if (_patchEntryHeader)
                {
                    _sizePatchPos = BaseOutputStream.Position;
                }
                if (entry.LocalHeaderRequiresZip64 || _patchEntryHeader)
                {
                    WriteLeInt(-1);
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt(0);
                    WriteLeInt(0);
                }
            }
            byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
            if (buffer.Length > 0xffff)
            {
                throw new ZipException("Entry name too long.");
            }
            ZipExtraData extraData = new ZipExtraData(entry.ExtraData);

            if (entry.LocalHeaderRequiresZip64)
            {
                extraData.StartNewEntry();
                if (hasCrc)
                {
                    extraData.AddLeLong(entry.Size);
                    extraData.AddLeLong(entry.CompressedSize);
                }
                else
                {
                    extraData.AddLeLong(-1L);
                    extraData.AddLeLong(-1L);
                }
                extraData.AddNewEntry(1);
                if (!extraData.Find(1))
                {
                    throw new ZipException("Internal error cant find extra data");
                }
                if (_patchEntryHeader)
                {
                    _sizePatchPos = extraData.CurrentReadIndex;
                }
            }
            else
            {
                extraData.Delete(1);
            }
            if (entry.AesKeySize > 0)
            {
                AddExtraDataAes(entry, extraData);
            }
            byte[] entryData = extraData.GetEntryData();
            WriteLeShort(buffer.Length);
            WriteLeShort(entryData.Length);
            if (buffer.Length > 0)
            {
                BaseOutputStream.Write(buffer, 0, buffer.Length);
            }
            if (entry.LocalHeaderRequiresZip64 && _patchEntryHeader)
            {
                _sizePatchPos += BaseOutputStream.Position;
            }
            if (entryData.Length > 0)
            {
                BaseOutputStream.Write(entryData, 0, entryData.Length);
            }
            _offset += (30 + buffer.Length) + entryData.Length;
            if (entry.AesKeySize > 0)
            {
                _offset += entry.AesOverheadSize;
            }
            _curEntry = entry;
            _crc.Reset();
            if (compressionMethod == CompressionMethod.Deflated)
            {
                Deflater.Reset();
                Deflater.SetLevel(compressionLevel);
            }
            _size = 0L;
            if (entry.IsCrypted)
            {
                if (entry.AesKeySize > 0)
                {
                    WriteAesHeader(entry);
                }
                else if (entry.Crc < 0L)
                {
                    WriteEncryptionHeader(entry.DosTime << 0x10);
                }
                else
                {
                    WriteEncryptionHeader(entry.Crc);
                }
            }
        }
Exemplo n.º 27
0
        /// <summary>
        /// Starts a new Zip entry. It automatically closes the previous
        /// entry if present.
        /// All entry elements bar name are optional, but must be correct if present.
        /// If the compression method is stored and the output is not patchable
        /// the compression for that entry is automatically changed to deflate level 0
        /// </summary>
        /// <param name="entry">
        /// the entry.
        /// </param>
        /// <exception cref="System.ArgumentNullException">
        /// if entry passed is null.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// if an I/O error occured.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// if stream was finished
        /// </exception>
        /// <exception cref="ZipException">
        /// Too many entries in the Zip file<br/>
        /// Entry name is too long<br/>
        /// Finish has already been called<br/>
        /// </exception>
        public void PutNextEntry(ZipEntry entry)
        {
            if (entry == null)
            {
                throw new ArgumentNullException(nameof(entry));
            }

            if (entries == null)
            {
                throw new InvalidOperationException("ZipOutputStream was finished");
            }

            if (curEntry != null)
            {
                CloseEntry();
            }

            if (entries.Count == int.MaxValue)
            {
                throw new ZipException("Too many entries for Zip file");
            }

            CompressionMethod method = entry.CompressionMethod;
            int compressionLevel     = defaultCompressionLevel;

            // Clear flags that the library manages internally
            entry.Flags     &= (int)GeneralBitFlags.UnicodeText;
            patchEntryHeader = false;

            bool headerInfoAvailable;

            // No need to compress - definitely no data.
            if (entry.Size == 0)
            {
                entry.CompressedSize = entry.Size;
                entry.Crc            = 0;
                method = CompressionMethod.Stored;
                headerInfoAvailable = true;
            }
            else
            {
                headerInfoAvailable = (entry.Size >= 0) && entry.HasCrc && entry.CompressedSize >= 0;

                // Switch to deflation if storing isnt possible.
                if (method == CompressionMethod.Stored)
                {
                    if (!headerInfoAvailable)
                    {
                        if (!CanPatchEntries)
                        {
                            // Can't patch entries so storing is not possible.
                            method           = CompressionMethod.Deflated;
                            compressionLevel = 0;
                        }
                    }
                    else                       // entry.size must be > 0
                    {
                        entry.CompressedSize = entry.Size;
                        headerInfoAvailable  = entry.HasCrc;
                    }
                }
            }

            if (headerInfoAvailable == false)
            {
                if (CanPatchEntries == false)
                {
                    // Only way to record size and compressed size is to append a data descriptor
                    // after compressed data.

                    // Stored entries of this form have already been converted to deflating.
                    entry.Flags |= 8;
                }
                else
                {
                    patchEntryHeader = true;
                }
            }


            entry.Offset            = offset;
            entry.CompressionMethod = (CompressionMethod)method;

            curMethod    = method;
            sizePatchPos = -1;

            if ((useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)))
            {
                entry.ForceZip64();
            }

            // Write the local file header
            WriteLeInt(ZipConstants.LocalHeaderSignature);

            WriteLeShort(entry.Version);
            WriteLeShort(entry.Flags);
            WriteLeShort((byte)entry.CompressionMethodForHeader);
            WriteLeInt((int)entry.DosTime);

            // TODO: Refactor header writing.  Its done in several places.
            if (headerInfoAvailable)
            {
                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 (patchEntryHeader)
                {
                    crcPatchPos = BaseOutputStream.Position;
                }
                WriteLeInt(0);                  // Crc

                if (patchEntryHeader)
                {
                    sizePatchPos = BaseOutputStream.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 = ZipStrings.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)
            {
                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 (patchEntryHeader)
                {
                    sizePatchPos = ed.CurrentReadIndex;
                }
            }
            else
            {
                ed.Delete(1);
            }

            if (entry.AESKeySize > 0)
            {
                AddExtraDataAES(entry, ed);
            }
            byte[] extra = ed.GetEntryData();

            WriteLeShort(name.Length);
            WriteLeShort(extra.Length);

            if (name.Length > 0)
            {
                BaseOutputStream.Write(name, 0, name.Length);
            }

            if (entry.LocalHeaderRequiresZip64 && patchEntryHeader)
            {
                sizePatchPos += BaseOutputStream.Position;
            }

            if (extra.Length > 0)
            {
                BaseOutputStream.Write(extra, 0, extra.Length);
            }

            offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length;
            // Fix offsetOfCentraldir for AES
            if (entry.AESKeySize > 0)
            {
                offset += entry.AESOverheadSize;
            }

            // Activate the entry.
            curEntry = entry;
            crc.Reset();
            if (method == CompressionMethod.Deflated)
            {
                Deflater.Reset();
                Deflater.SetLevel(compressionLevel);
            }
            size = 0;
        }