Пример #1
0
        public ZipFileHeader(ZipFileInfo fileInfo, bool zip64)
            : this()
        {
            this.flags = ZipFileFlags.None;
            this.compressionMethod = fileInfo.CompressionMethod;
            this.fileName = Path.Combine(fileInfo.Path, fileInfo.Name);
            CompressionEngine.DateTimeToDosDateAndTime(
                fileInfo.LastWriteTime, out this.lastModDate, out this.lastModTime);
            this.zip64 = zip64;

            if (this.zip64)
            {
                this.compressedSize = UInt32.MaxValue;
                this.uncompressedSize = UInt32.MaxValue;
                this.diskStart = UInt16.MaxValue;
                this.versionMadeBy = 45;
                this.versionNeeded = 45;
                ZipExtraFileField field = new ZipExtraFileField();
                field.fieldType = ZipExtraFileFieldType.ZIP64;
                field.SetZip64Data(
                    fileInfo.CompressedLength,
                    fileInfo.Length,
                    0,
                    fileInfo.ArchiveNumber);
                this.extraFields = new ZipExtraFileField[] { field };
            }
            else
            {
                this.compressedSize = (uint) fileInfo.CompressedLength;
                this.uncompressedSize = (uint) fileInfo.Length;
                this.diskStart = (ushort) fileInfo.ArchiveNumber;
            }
        }
Пример #2
0
        internal uint Write(Stream outputStream, ZipCompressionMethod compression)
        {
            byte[] bytes  = Encoding.UTF8.GetBytes(this.FileName);
            byte[] buffer = Encoding.UTF8.GetBytes(this.Comment);
            outputStream.Write(new byte[] { 80, 0x4b, 1, 2, 0x3f, 0, 10, 0 }, 0, 8);
            HeaderFlags flags = HeaderFlags.UTF8;

            if (!outputStream.CanSeek)
            {
                flags = (HeaderFlags)((ushort)(flags | HeaderFlags.UsePostDataDescriptor));
                if (compression == ZipCompressionMethod.LZMA)
                {
                    flags = (HeaderFlags)((ushort)(flags | HeaderFlags.Bit1));
                }
            }
            outputStream.Write(BitConverter.GetBytes((ushort)flags), 0, 2);
            outputStream.Write(BitConverter.GetBytes((ushort)compression), 0, 2);
            outputStream.Write(BitConverter.GetBytes(Utility.DateTimeToDosTime(this.ModificationTime)), 0, 4);
            outputStream.Write(BitConverter.GetBytes(this.Crc), 0, 4);
            outputStream.Write(BitConverter.GetBytes(this.Compressed), 0, 4);
            outputStream.Write(BitConverter.GetBytes(this.Decompressed), 0, 4);
            outputStream.Write(BitConverter.GetBytes((ushort)bytes.Length), 0, 2);
            outputStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            outputStream.Write(BitConverter.GetBytes((ushort)buffer.Length), 0, 2);
            outputStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            outputStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            outputStream.Write(BitConverter.GetBytes((ushort)0), 0, 2);
            outputStream.Write(BitConverter.GetBytes((ushort)0x8100), 0, 2);
            outputStream.Write(BitConverter.GetBytes(this.HeaderOffset), 0, 4);
            outputStream.Write(bytes, 0, bytes.Length);
            outputStream.Write(buffer, 0, buffer.Length);
            return((uint)((0x2e + bytes.Length) + buffer.Length));
        }
Пример #3
0
 public ZipCentralDirectoryEntry(ZipCompressionMethod compression, string fileName, ulong headerOffset, Encoding forceEncoding)
 {
     this.compression   = compression;
     this.fileName      = fileName;
     HeaderOffset       = headerOffset;
     this.forceEncoding = forceEncoding;
 }
Пример #4
0
        public ZipFileHeader(ZipFileInfo fileInfo, bool zip64)
            : this()
        {
            this.flags             = ZipFileFlags.None;
            this.compressionMethod = fileInfo.CompressionMethod;
            this.fileName          = Path.Combine(fileInfo.Path, fileInfo.Name);
            CompressionEngine.DateTimeToDosDateAndTime(
                fileInfo.LastWriteTime, out this.lastModDate, out this.lastModTime);
            this.zip64 = zip64;

            if (this.zip64)
            {
                this.compressedSize   = UInt32.MaxValue;
                this.uncompressedSize = UInt32.MaxValue;
                this.diskStart        = UInt16.MaxValue;
                this.versionMadeBy    = 45;
                this.versionNeeded    = 45;
                ZipExtraFileField field = new ZipExtraFileField();
                field.fieldType = ZipExtraFileFieldType.ZIP64;
                field.SetZip64Data(
                    fileInfo.CompressedLength,
                    fileInfo.Length,
                    0,
                    fileInfo.ArchiveNumber);
                this.extraFields = new ZipExtraFileField[] { field };
            }
            else
            {
                this.compressedSize   = (uint)fileInfo.CompressedLength;
                this.uncompressedSize = (uint)fileInfo.Length;
                this.diskStart        = (ushort)fileInfo.ArchiveNumber;
            }
        }
Пример #5
0
 public ZipCompressionInfo(CompressionInfo compressionInfo)
 {
     switch (compressionInfo.Type)
     {
         case CompressionType.None:
             {
                 this.Compression = ZipCompressionMethod.None;
             }
             break;
         case CompressionType.Deflate:
             {
                 this.DeflateCompressionLevel = compressionInfo.DeflateCompressionLevel;
                 this.Compression = ZipCompressionMethod.Deflate;
             }
             break;
         case CompressionType.BZip2:
             {
                 this.Compression = ZipCompressionMethod.BZip2;
             }
             break;
         case CompressionType.LZMA:
             {
                 this.Compression = ZipCompressionMethod.LZMA;
             }
             break;
         case CompressionType.PPMd:
             {
                 this.Compression = ZipCompressionMethod.PPMd;
             }
             break;
         default:
             throw new InvalidFormatException("Invalid compression method: " + compressionInfo.Type);
     }
 }
Пример #6
0
        virtual protected void ReadHeader(Stream source)
        {
            var reader = new BinaryReader(source);
            int fileNameLength;
            int extraFieldLength;
            var enc = encoding437;

            Version          = reader.ReadInt16();
            Flags            = reader.ReadInt16();
            Compression      = (ZipCompressionMethod)reader.ReadInt16();
            LastModifiedTime = reader.ReadInt16();
            LastModifiedDate = reader.ReadInt16();
            Crc32            = reader.ReadInt32();
            CompressedSize   = reader.ReadInt32();
            UncompressedSize = reader.ReadInt32();
            fileNameLength   = reader.ReadInt16();
            extraFieldLength = reader.ReadInt16();
            ExtraData        = new List <ZipExtraField>();

            if (UseUTF8)
            {
                enc = encodingUTF8;
            }

            if (fileNameLength > 0)
            {
                Filename = enc.GetString(reader.ReadBytes(fileNameLength));
            }
            else
            {
                Filename = "";
            }

            while (extraFieldLength > 0)
            {
                // load extra data
                int           id          = reader.ReadInt16();
                int           fieldLength = reader.ReadInt16();
                ZipExtraField zef         = new ZipExtraField(id, reader.ReadBytes(fieldLength));
                extraFieldLength -= fieldLength + 4;
                ExtraData.Add(zef);
            }

            foreach (var data in ExtraData)
            {
                using (MemoryStream dataMem = new MemoryStream(data.Data))
                {
                    BinaryReader dataReader = new BinaryReader(dataMem);
                    switch (data.Id)
                    {
                    case 1:     // ZIP64
                        UncompressedSize = dataReader.ReadInt64();
                        CompressedSize   = dataReader.ReadInt64();
                        break;
                    }
                }
            }

            Offset = source.Position;
        }
Пример #7
0
 internal ZipWritingStream(ZipWriter writer, Stream originalStream, ZipCentralDirectoryEntry entry,
                           ZipCompressionMethod zipCompressionMethod, CompressionLevel compressionLevel)
 {
     this.writer               = writer;
     this.originalStream       = originalStream;
     this.writer               = writer;
     this.entry                = entry;
     this.zipCompressionMethod = zipCompressionMethod;
     this.compressionLevel     = compressionLevel;
     writeStream               = GetWriteStream(originalStream);
 }
Пример #8
0
 /// <summary>
 /// Creates a new ZipFileInfo object with all parameters specified,
 /// used internally when reading the metadata out of a zip archive.
 /// </summary>
 /// <param name="filePath">The internal path and name of the file in the zip archive.</param>
 /// <param name="zipNumber">The zip archive number where the file starts.</param>
 /// <param name="attributes">The stored attributes of the file.</param>
 /// <param name="lastWriteTime">The stored last write time of the file.</param>
 /// <param name="length">The uncompressed size of the file.</param>
 /// <param name="compressedLength">The compressed size of the file.</param>
 /// <param name="compressionMethod">Compression algorithm used for this file.</param>
 internal ZipFileInfo(
     string filePath,
     int zipNumber,
     FileAttributes attributes,
     DateTime lastWriteTime,
     long length,
     long compressedLength,
     ZipCompressionMethod compressionMethod)
     : base(filePath, zipNumber, attributes, lastWriteTime, length)
 {
     this.compressedLength = compressedLength;
     this.compressionMethod = compressionMethod;
 }
Пример #9
0
 /// <summary>
 /// Creates a new ZipFileInfo object with all parameters specified,
 /// used internally when reading the metadata out of a zip archive.
 /// </summary>
 /// <param name="filePath">The internal path and name of the file in the zip archive.</param>
 /// <param name="zipNumber">The zip archive number where the file starts.</param>
 /// <param name="attributes">The stored attributes of the file.</param>
 /// <param name="lastWriteTime">The stored last write time of the file.</param>
 /// <param name="length">The uncompressed size of the file.</param>
 /// <param name="compressedLength">The compressed size of the file.</param>
 /// <param name="compressionMethod">Compression algorithm used for this file.</param>
 internal ZipFileInfo(
     string filePath,
     int zipNumber,
     FileAttributes attributes,
     DateTime lastWriteTime,
     long length,
     long compressedLength,
     ZipCompressionMethod compressionMethod)
     : base(filePath, zipNumber, attributes, lastWriteTime, length)
 {
     this.compressedLength  = compressedLength;
     this.compressionMethod = compressionMethod;
 }
Пример #10
0
 /// <summary>
 /// Registers a delegate that can create a warpper stream for
 /// compressing or uncompressing the data of a source stream.
 /// </summary>
 /// <param name="compressionMethod">Compression method being registered.</param>
 /// <param name="compressionMode">Indicates registration for ether
 /// compress or decompress mode.</param>
 /// <param name="creator">Delegate being registered.</param>
 /// <remarks>
 /// For compression, the delegate accepts a stream that writes to the archive
 /// and returns a wrapper stream that compresses bytes as they are written.
 /// For decompression, the delegate accepts a stream that reads from the archive
 /// and returns a wrapper stream that decompresses bytes as they are read.
 /// This wrapper stream model follows the design used by
 /// System.IO.Compression.DeflateStream, and indeed that class is used
 /// to implement the Deflate compression method by default.
 /// <para>To unregister a delegate, call this method again and pass
 /// null for the delegate parameter.</para>
 /// </remarks>
 /// <example>
 /// When the ZipEngine class is initialized, the Deflate compression method
 /// is automatically registered like this:
 /// <code>
 ///        ZipEngine.RegisterCompressionStreamCreator(
 ///            ZipCompressionMethod.Deflate,
 ///            CompressionMode.Compress,
 ///            delegate(Stream stream) {
 ///                return new DeflateStream(stream, CompressionMode.Compress, true);
 ///            });
 ///        ZipEngine.RegisterCompressionStreamCreator(
 ///            ZipCompressionMethod.Deflate,
 ///            CompressionMode.Decompress,
 ///            delegate(Stream stream) {
 ///                return new DeflateStream(stream, CompressionMode.Decompress, true);
 ///            });
 /// </code></example>
 public static void RegisterCompressionStreamCreator(
     ZipCompressionMethod compressionMethod,
     CompressionMode compressionMode,
     Converter <Stream, Stream> creator)
 {
     ZipEngine.InitCompressionStreamCreators();
     if (compressionMode == CompressionMode.Compress)
     {
         ZipEngine.compressionStreamCreators[compressionMethod] = creator;
     }
     else
     {
         ZipEngine.decompressionStreamCreators[compressionMethod] = creator;
     }
 }
Пример #11
0
        /// <summary>
        /// Sets up this DeflateManagedStream to be used for Inflation/Decompression
        /// </summary>
        private void InitializeInflater(Stream stream, ZipCompressionMethod method = ZipCompressionMethod.Deflate)
        {
            Debug.Assert(stream != null);
            Debug.Assert(method == ZipCompressionMethod.Deflate || method == ZipCompressionMethod.Deflate64);
            if (!stream.CanRead)
            {
                throw new ArgumentException("Deflate64: input stream is not readable", nameof(stream));
            }

            _inflater = new InflaterManaged(method == ZipCompressionMethod.Deflate64);

            _stream = stream;
            _mode   = CompressionMode.Decompress;
            _buffer = new byte[DEFAULT_BUFFER_SIZE];
        }
        /// <summary>
        /// Sets up this DeflateManagedStream to be used for Inflation/Decompression
        /// </summary>
        internal void InitializeInflater(Stream stream, bool leaveOpen, ZipCompressionMethod method = ZipCompressionMethod.Deflate)
        {
            Debug.Assert(stream != null);
            Debug.Assert(method == ZipCompressionMethod.Deflate || method == ZipCompressionMethod.Deflate64);
            if (!stream.CanRead)
            {
                throw new ArgumentException("Deflate64: input stream is not readable", nameof(stream));
            }

            _inflater = new InflaterManaged(method == ZipCompressionMethod.Deflate64);

            _stream    = stream;
            _mode      = CompressionMode.Decompress;
            _leaveOpen = leaveOpen;
            _buffer    = new byte[DefaultBufferSize];
        }
Пример #13
0
        private readonly PpmdProperties ppmdProperties; // Caching properties to speed up PPMd.
#endif

        public ZipWriter(Stream destination, CompressionInfo compressionInfo, string zipComment, Encoding encoding = null)
            : base(ArchiveType.Zip)
        {
            this.zipComment = zipComment ?? string.Empty;
            this.encoding   = encoding ?? ArchiveEncoding.Default;

            switch (compressionInfo.Type)
            {
            case CompressionType.None:
            {
                compression = ZipCompressionMethod.None;
            }
            break;

            case CompressionType.Deflate:
            {
                compression             = ZipCompressionMethod.Deflate;
                deflateCompressionLevel = compressionInfo.DeflateCompressionLevel;
            }
            break;

            case CompressionType.BZip2:
            {
                compression = ZipCompressionMethod.BZip2;
            }
            break;

#if LZMA
            case CompressionType.LZMA:
            {
                compression = ZipCompressionMethod.LZMA;
            }
            break;
#endif
#if PPMd
            case CompressionType.PPMd:
            {
                ppmdProperties = new PpmdProperties();
                compression    = ZipCompressionMethod.PPMd;
            }
            break;
#endif
            default:
                throw new InvalidFormatException("Invalid compression method: " + compressionInfo.Type);
            }
            InitalizeStream(destination, false);
        }
Пример #14
0
        // TODO: This method looks like ZipWriter.WriteHeader. Ideally the logic
        // has to be extracted into a common method and be called from both places
        // or better refactoring has to be done to keep the header info in a separate
        // class and use it in the reader and writer.
        public uint Write(Stream outputStream, ZipCompressionMethod compression)
        {
            byte[] encodedFilename = Encoding.UTF8.GetBytes(FileName);
            byte[] encodedComment  = Encoding.UTF8.GetBytes(Comment);

            //constant sig, then version made by, compabitility, then version to extract
            outputStream.Write(new byte[] { 80, 75, 1, 2, 0x14, 0, 0x0A, 0 }, 0, 8);
            HeaderFlags flags = HeaderFlags.UTF8;

            if (IsEncrypted)
            {
                flags |= HeaderFlags.Encrypted;
            }
            if (!outputStream.CanSeek)
            {
                flags |= HeaderFlags.UsePostDataDescriptor;
                if (compression == ZipCompressionMethod.LZMA)
                {
                    flags |= HeaderFlags.Bit1; // eos marker
                }
            }
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)flags), 0, 2);
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)compression), 0, 2);  // zipping method
            outputStream.Write(DataConverter.LittleEndian.GetBytes(ModificationTime.DateTimeToDosTime()), 0, 4);
            // zipping date and time
            outputStream.Write(DataConverter.LittleEndian.GetBytes(Crc), 0, 4);                            // file CRC
            outputStream.Write(DataConverter.LittleEndian.GetBytes(Compressed), 0, 4);                     // compressed file size
            outputStream.Write(DataConverter.LittleEndian.GetBytes(Decompressed), 0, 4);                   // uncompressed file size
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)encodedFilename.Length), 0, 2); // Filename in zip
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);                      // extra length
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)encodedComment.Length), 0, 2);

            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);  // disk=0
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);  // file type: binary
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);  // Internal file attributes
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0x8100), 0, 2);
            // External file attributes (normal/readable)
            outputStream.Write(DataConverter.LittleEndian.GetBytes(HeaderOffset), 0, 4); // Offset of header

            outputStream.Write(encodedFilename, 0, encodedFilename.Length);
            outputStream.Write(encodedComment, 0, encodedComment.Length);

            return((uint)(8 + 2 + 2 + 4 + 4 + 4 + 4 + 2 + 2 + 2
                          + 2 + 2 + 2 + 2 + 4 + encodedFilename.Length + encodedComment.Length));
        }
Пример #15
0
        private readonly PpmdProperties ppmdProperties; // Caching properties to speed up PPMd.
#endif

        public ZipWriter(Stream destination, CompressionInfo compressionInfo, string zipComment, Encoding encoding = null)
            : base(ArchiveType.Zip)
        {
            this.zipComment = zipComment ?? string.Empty;
            this.encoding = encoding ?? ArchiveEncoding.Default;

            switch (compressionInfo.Type)
            {
                case CompressionType.None:
                    {
                        compression = ZipCompressionMethod.None;
                    }
                    break;
                case CompressionType.Deflate:
                    {
                        compression = ZipCompressionMethod.Deflate;
                        deflateCompressionLevel = compressionInfo.DeflateCompressionLevel;
                    }
                    break;
                case CompressionType.BZip2:
                    {
                        compression = ZipCompressionMethod.BZip2;
                    }
                    break;
#if LZMA
                case CompressionType.LZMA:
                    {
                        compression = ZipCompressionMethod.LZMA;
                    }
                    break;
#endif
#if PPMd
                case CompressionType.PPMd:
                    {
                        ppmdProperties = new PpmdProperties();
                        compression = ZipCompressionMethod.PPMd;
                    }
                    break;
#endif
                default:
                    throw new InvalidFormatException("Invalid compression method: " + compressionInfo.Type);
            }
            InitalizeStream(destination, false);
        }
        /// <summary>
        /// Creates a central file header from the information in a local file header.
        /// </summary>
        /// <param name="localFileHeader">Local file header to </param>
        public ZipFileHeader(ZipFileHeader localFileHeader)
        {
            if (localFileHeader.central)
            {
                throw new ArgumentException();
            }

            this.central           = true;
            this.compressionMethod = localFileHeader.compressionMethod;
            this.fileName          = localFileHeader.fileName;
            this.fileComment       = localFileHeader.fileComment;
            this.flags             = localFileHeader.flags;
            this.externalFileAttrs = localFileHeader.externalFileAttrs;
            this.internalFileAttrs = localFileHeader.internalFileAttrs;
            this.lastModDate       = localFileHeader.lastModDate;
            this.lastModTime       = localFileHeader.lastModTime;
            this.crc32             = localFileHeader.crc32;

            if (this.zip64)
            {
                this.versionMadeBy = 45;
                this.versionNeeded = 45;

                this.compressedSize   = UInt32.MaxValue;
                this.uncompressedSize = UInt32.MaxValue;
                this.diskStart        = UInt16.MaxValue;

                ZipExtraFileField field = new ZipExtraFileField();
                field.fieldType = ZipExtraFileFieldType.ZIP64;
                field.SetZip64Data(localFileHeader.compressedSize, localFileHeader.uncompressedSize, localFileHeader.localHeaderOffset, localFileHeader.diskStart);
                this.extraFields = new ZipExtraFileField[] { field };
            }
            else
            {
                this.versionMadeBy = 20;
                this.versionNeeded = 20;

                this.localHeaderOffset = localFileHeader.localHeaderOffset;
                this.compressedSize    = localFileHeader.compressedSize;
                this.uncompressedSize  = localFileHeader.uncompressedSize;
            }
        }
        internal uint Write(Stream outputStream, ZipCompressionMethod compression)
        {
            byte[] encodedFilename = Encoding.UTF8.GetBytes(FileName);
            byte[] encodedComment = Encoding.UTF8.GetBytes(Comment);

            //constant sig, then version made by, compabitility, then version to extract
            outputStream.Write(new byte[] {80, 75, 1, 2, 0x14, 0, 0x0A, 0}, 0, 8);
            HeaderFlags flags = HeaderFlags.UTF8;
            if (!outputStream.CanSeek)
            {
                flags |= HeaderFlags.UsePostDataDescriptor;
                if (compression == ZipCompressionMethod.LZMA)
                {
                    flags |= HeaderFlags.Bit1; // eos marker
                }
            }
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) flags), 0, 2);
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) compression), 0, 2); // zipping method
            outputStream.Write(DataConverter.LittleEndian.GetBytes(ModificationTime.DateTimeToDosTime()), 0, 4);
                // zipping date and time
            outputStream.Write(DataConverter.LittleEndian.GetBytes(Crc), 0, 4); // file CRC
            outputStream.Write(DataConverter.LittleEndian.GetBytes(Compressed), 0, 4); // compressed file size
            outputStream.Write(DataConverter.LittleEndian.GetBytes(Decompressed), 0, 4); // uncompressed file size
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) encodedFilename.Length), 0, 2); // Filename in zip
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // extra length
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) encodedComment.Length), 0, 2);

            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // disk=0
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // file type: binary
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0), 0, 2); // Internal file attributes
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort) 0x8100), 0, 2);
                // External file attributes (normal/readable)
            outputStream.Write(DataConverter.LittleEndian.GetBytes(HeaderOffset), 0, 4); // Offset of header

            outputStream.Write(encodedFilename, 0, encodedFilename.Length);
            outputStream.Write(encodedComment, 0, encodedComment.Length);

            return (uint) (8 + 2 + 2 + 4 + 4 + 4 + 4 + 2 + 2 + 2
                           + 2 + 2 + 2 + 2 + 4 + encodedFilename.Length + encodedComment.Length);
        }
Пример #18
0
        public ZipCompressionInfo(CompressionInfo compressionInfo)
        {
            switch (compressionInfo.Type)
            {
            case CompressionType.None:
            {
                this.Compression = ZipCompressionMethod.None;
            }
            break;

            case CompressionType.Deflate:
            {
                this.DeflateCompressionLevel = compressionInfo.DeflateCompressionLevel;
                this.Compression             = ZipCompressionMethod.Deflate;
            }
            break;

            case CompressionType.BZip2:
            {
                this.Compression = ZipCompressionMethod.BZip2;
            }
            break;

            case CompressionType.LZMA:
            {
                this.Compression = ZipCompressionMethod.LZMA;
            }
            break;

            case CompressionType.PPMd:
            {
                this.Compression = ZipCompressionMethod.PPMd;
            }
            break;

            default:
                throw new InvalidFormatException("Invalid compression method: " + compressionInfo.Type);
            }
        }
Пример #19
0
        public bool Read(Stream stream, bool central)
        {
            long startPos = stream.Position;

            if (stream.Length - startPos <
                (central ? CFH_FIXEDSIZE : LFH_FIXEDSIZE))
            {
                return false;
            }

            BinaryReader reader = new BinaryReader(stream);
            uint sig = reader.ReadUInt32();

            if (sig == SPANSIG || sig == SPANSIG2)
            {
                // Spanned zip files may optionally begin with a special marker.
                // Just ignore it and move on.
                sig = reader.ReadUInt32();
            }

            if (sig != (central ? CFHSIG : LFHSIG))
            {
                return false;
            }

            this.versionMadeBy = (central ? reader.ReadUInt16() : (ushort) 0);
            this.versionNeeded = reader.ReadUInt16();
            this.flags = (ZipFileFlags) reader.ReadUInt16();
            this.compressionMethod = (ZipCompressionMethod) reader.ReadUInt16();
            this.lastModTime = reader.ReadInt16();
            this.lastModDate = reader.ReadInt16();
            this.crc32 = reader.ReadUInt32();
            this.compressedSize = reader.ReadUInt32();
            this.uncompressedSize = reader.ReadUInt32();

            this.zip64 = this.uncompressedSize == UInt32.MaxValue;

            int fileNameLength = reader.ReadUInt16();
            int extraFieldLength = reader.ReadUInt16();
            int fileCommentLength;

            if (central)
            {
                fileCommentLength = reader.ReadUInt16();

                this.diskStart = reader.ReadUInt16();
                this.internalFileAttrs = reader.ReadUInt16();
                this.externalFileAttrs = reader.ReadUInt32();
                this.localHeaderOffset = reader.ReadUInt32();
            }
            else
            {
                fileCommentLength = 0;
                this.diskStart = 0;
                this.internalFileAttrs = 0;
                this.externalFileAttrs = 0;
                this.localHeaderOffset = 0;
            }

            if (stream.Length - stream.Position <
                fileNameLength + extraFieldLength + fileCommentLength)
            {
                return false;
            }

            Encoding headerEncoding = ((this.flags | ZipFileFlags.UTF8) != 0 ?
                Encoding.UTF8 : Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage));

            byte[] fileNameBytes = reader.ReadBytes(fileNameLength);
            this.fileName = headerEncoding.GetString(fileNameBytes).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

            List<ZipExtraFileField> fields = new List<ZipExtraFileField>();
            while (extraFieldLength > 0)
            {
                ZipExtraFileField field = new ZipExtraFileField();
                if (!field.Read(stream, ref extraFieldLength))
                {
                    return false;
                }
                fields.Add(field);
                if (field.fieldType == ZipExtraFileFieldType.ZIP64)
                {
                    this.zip64 = true;
                }
            }
            this.extraFields = fields.ToArray();

            byte[] fileCommentBytes = reader.ReadBytes(fileCommentLength);
            this.fileComment = headerEncoding.GetString(fileCommentBytes);

            return true;
        }
Пример #20
0
        internal uint Write(Stream outputStream, ZipCompressionMethod compression)
        {
            byte[] encodedFilename = Encoding.UTF8.GetBytes(FileName);
            byte[] encodedComment  = Encoding.UTF8.GetBytes(Comment);

            var zip64_stream = Compressed >= uint.MaxValue || Decompressed >= uint.MaxValue;
            var zip64        = zip64_stream || HeaderOffset >= uint.MaxValue || Zip64HeaderOffset != 0;

            var compressedvalue   = zip64 ? uint.MaxValue : (uint)Compressed;
            var decompressedvalue = zip64 ? uint.MaxValue : (uint)Decompressed;
            var headeroffsetvalue = zip64 ? uint.MaxValue : (uint)HeaderOffset;
            var extralength       = zip64 ? (2 + 2 + 8 + 8 + 8 + 4) : 0;
            var version           = (byte)(zip64 ? 45 : 10);

            HeaderFlags flags = HeaderFlags.UTF8;

            if (!outputStream.CanSeek)
            {
                // Cannot use data descriptors with zip64:
                // https://blogs.oracle.com/xuemingshen/entry/is_zipinput_outputstream_handling_of

                // We check that streams are not written too large in the ZipWritingStream,
                // so this extra guard is not required, but kept to simplify changing the code
                // once the zip64 post-data issue is resolved
                if (!zip64_stream)
                {
                    flags |= HeaderFlags.UsePostDataDescriptor;
                }

                if (compression == ZipCompressionMethod.LZMA)
                {
                    flags |= HeaderFlags.Bit1; // eos marker
                }
            }

            //constant sig, then version made by, compabitility, then version to extract
            outputStream.Write(new byte[] { 80, 75, 1, 2, 0x14, 0, version, 0 }, 0, 8);

            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)flags), 0, 2);
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)compression), 0, 2); // zipping method
            outputStream.Write(DataConverter.LittleEndian.GetBytes(ModificationTime.DateTimeToDosTime()), 0, 4);

            // zipping date and time
            outputStream.Write(DataConverter.LittleEndian.GetBytes(Crc), 0, 4);                            // file CRC
            outputStream.Write(DataConverter.LittleEndian.GetBytes(compressedvalue), 0, 4);                // compressed file size
            outputStream.Write(DataConverter.LittleEndian.GetBytes(decompressedvalue), 0, 4);              // uncompressed file size
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)encodedFilename.Length), 0, 2); // Filename in zip
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)extralength), 0, 2);            // extra length
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)encodedComment.Length), 0, 2);

            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2); // disk=0
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2); // file type: binary
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2); // Internal file attributes
            outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0x8100), 0, 2);

            // External file attributes (normal/readable)
            outputStream.Write(DataConverter.LittleEndian.GetBytes(headeroffsetvalue), 0, 4); // Offset of header

            outputStream.Write(encodedFilename, 0, encodedFilename.Length);
            if (zip64)
            {
                outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0x0001), 0, 2);
                outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)(extralength - 4)), 0, 2);

                outputStream.Write(DataConverter.LittleEndian.GetBytes(Decompressed), 0, 8);
                outputStream.Write(DataConverter.LittleEndian.GetBytes(Compressed), 0, 8);
                outputStream.Write(DataConverter.LittleEndian.GetBytes(HeaderOffset), 0, 8);
                outputStream.Write(DataConverter.LittleEndian.GetBytes(0), 0, 4); // VolumeNumber = 0
            }

            outputStream.Write(encodedComment, 0, encodedComment.Length);

            return((uint)(8 + 2 + 2 + 4 + 4 + 4 + 4 + 2 + 2 + 2
                          + 2 + 2 + 2 + 2 + 4 + encodedFilename.Length + extralength + encodedComment.Length));
        }
Пример #21
0
        public bool Read(Stream stream, bool central)
        {
            long startPos = stream.Position;

            if (stream.Length - startPos <
                (central ? CFH_FIXEDSIZE : LFH_FIXEDSIZE))
            {
                return(false);
            }

            BinaryReader reader = new BinaryReader(stream);
            uint         sig    = reader.ReadUInt32();

            if (sig == SPANSIG || sig == SPANSIG2)
            {
                // Spanned zip files may optionally begin with a special marker.
                // Just ignore it and move on.
                sig = reader.ReadUInt32();
            }

            if (sig != (central ? CFHSIG : LFHSIG))
            {
                return(false);
            }

            this.versionMadeBy     = (central ? reader.ReadUInt16() : (ushort)0);
            this.versionNeeded     = reader.ReadUInt16();
            this.flags             = (ZipFileFlags)reader.ReadUInt16();
            this.compressionMethod = (ZipCompressionMethod)reader.ReadUInt16();
            this.lastModTime       = reader.ReadInt16();
            this.lastModDate       = reader.ReadInt16();
            this.crc32             = reader.ReadUInt32();
            this.compressedSize    = reader.ReadUInt32();
            this.uncompressedSize  = reader.ReadUInt32();

            this.zip64 = this.uncompressedSize == UInt32.MaxValue;

            int fileNameLength   = reader.ReadUInt16();
            int extraFieldLength = reader.ReadUInt16();
            int fileCommentLength;

            if (central)
            {
                fileCommentLength = reader.ReadUInt16();

                this.diskStart         = reader.ReadUInt16();
                this.internalFileAttrs = reader.ReadUInt16();
                this.externalFileAttrs = reader.ReadUInt32();
                this.localHeaderOffset = reader.ReadUInt32();
            }
            else
            {
                fileCommentLength      = 0;
                this.diskStart         = 0;
                this.internalFileAttrs = 0;
                this.externalFileAttrs = 0;
                this.localHeaderOffset = 0;
            }

            if (stream.Length - stream.Position <
                fileNameLength + extraFieldLength + fileCommentLength)
            {
                return(false);
            }

#if CORECLR
            Encoding headerEncoding = Encoding.UTF8;
#else
            Encoding headerEncoding = ((this.flags | ZipFileFlags.UTF8) != 0 ?
                                       Encoding.UTF8 : Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage));
#endif

            byte[] fileNameBytes = reader.ReadBytes(fileNameLength);
            this.fileName = headerEncoding.GetString(fileNameBytes).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

            List <ZipExtraFileField> fields = new List <ZipExtraFileField>();
            while (extraFieldLength > 0)
            {
                ZipExtraFileField field = new ZipExtraFileField();
                if (!field.Read(stream, ref extraFieldLength))
                {
                    return(false);
                }
                fields.Add(field);
                if (field.fieldType == ZipExtraFileFieldType.ZIP64)
                {
                    this.zip64 = true;
                }
            }
            this.extraFields = fields.ToArray();

            byte[] fileCommentBytes = reader.ReadBytes(fileCommentLength);
            this.fileComment = headerEncoding.GetString(fileCommentBytes);

            return(true);
        }
Пример #22
0
        /// <summary>
        /// Adds one file to a zip archive in the process of being created.
        /// </summary>
        private ZipFileHeader PackOneFile(
            IPackStreamContext streamContext,
            string file,
            long maxArchiveSize,
            bool forceZip64,
            ref Stream archiveStream)
        {
            Stream fileStream          = null;
            int    headerArchiveNumber = 0;

            try
            {
                // TODO: call GetOption to get compression method for the specific file
                ZipCompressionMethod compressionMethod = ZipCompressionMethod.Deflate;
                if (this.CompressionLevel == CompressionLevel.None)
                {
                    compressionMethod = ZipCompressionMethod.Store;
                }

                Func <Stream, Stream> compressionStreamCreator;
                if (!ZipEngine.compressionStreamCreators.TryGetValue(
                        compressionMethod, out compressionStreamCreator))
                {
                    return(null);
                }

                FileAttributes attributes;
                DateTime       lastWriteTime;
                fileStream = streamContext.OpenFileReadStream(
                    file, out attributes, out lastWriteTime);
                if (fileStream == null)
                {
                    return(null);
                }

                this.currentFileName = file;
                this.currentFileNumber++;

                this.currentFileTotalBytes     = fileStream.Length;
                this.currentFileBytesProcessed = 0;
                this.OnProgress(ArchiveProgressType.StartFile);

                ZipFileInfo fileInfo = new ZipFileInfo(
                    file,
                    this.currentArchiveNumber,
                    attributes,
                    lastWriteTime,
                    fileStream.Length,
                    0,
                    compressionMethod);

                bool          zip64      = forceZip64 || fileStream.Length >= (long)UInt32.MaxValue;
                ZipFileHeader fileHeader = new ZipFileHeader(fileInfo, zip64);

                this.CheckArchiveWriteStream(
                    streamContext,
                    maxArchiveSize,
                    fileHeader.GetSize(false),
                    ref archiveStream);

                long headerPosition = archiveStream.Position;
                fileHeader.Write(archiveStream, false);
                headerArchiveNumber = this.currentArchiveNumber;

                uint crc;
                long bytesWritten = this.PackFileBytes(
                    streamContext,
                    fileStream,
                    maxArchiveSize,
                    compressionStreamCreator,
                    ref archiveStream,
                    out crc);

                fileHeader.Update(
                    bytesWritten,
                    fileStream.Length,
                    crc,
                    headerPosition,
                    headerArchiveNumber);

                streamContext.CloseFileReadStream(file, fileStream);
                fileStream = null;

                // Go back and rewrite the updated file header.
                if (this.currentArchiveNumber == headerArchiveNumber)
                {
                    long fileEndPosition = archiveStream.Position;
                    archiveStream.Seek(headerPosition, SeekOrigin.Begin);
                    fileHeader.Write(archiveStream, false);
                    archiveStream.Seek(fileEndPosition, SeekOrigin.Begin);
                }
                else
                {
                    // The file spanned archives, so temporarily reopen
                    // the archive where it started.
                    string headerArchiveName = streamContext.GetArchiveName(
                        headerArchiveNumber + 1);
                    Stream headerStream = null;
                    try
                    {
                        headerStream = streamContext.OpenArchiveWriteStream(
                            headerArchiveNumber, headerArchiveName, false, this);
                        headerStream.Seek(headerPosition, SeekOrigin.Begin);
                        fileHeader.Write(headerStream, false);
                    }
                    finally
                    {
                        if (headerStream != null)
                        {
                            streamContext.CloseArchiveWriteStream(
                                headerArchiveNumber, headerArchiveName, headerStream);
                        }
                    }
                }

                this.OnProgress(ArchiveProgressType.FinishFile);

                return(fileHeader);
            }
            finally
            {
                if (fileStream != null)
                {
                    streamContext.CloseFileReadStream(
                        this.currentFileName, fileStream);
                }
            }
        }
Пример #23
0
        protected Stream CreateDecompressionStream(Stream stream, ZipCompressionMethod method)
        {
            switch (method)
            {
            case ZipCompressionMethod.None:
            {
                return(stream);
            }

            case ZipCompressionMethod.Deflate:
            {
                return(new DeflateStream(stream, CompressionMode.Decompress));
            }

            case ZipCompressionMethod.BZip2:
            {
                return(new BZip2Stream(stream, CompressionMode.Decompress));
            }

            case ZipCompressionMethod.LZMA:
            {
                if (FlagUtility.HasFlag(Header.Flags, HeaderFlags.Encrypted))
                {
                    throw new NotSupportedException("LZMA with pkware encryption.");
                }
                var reader = new BinaryReader(stream);
                reader.ReadUInt16();     //LZMA version
                var props = new byte[reader.ReadUInt16()];
                reader.Read(props, 0, props.Length);
                return(new LzmaStream(props, stream,
                                      Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
                                      FlagUtility.HasFlag(Header.Flags, HeaderFlags.Bit1)
                                              ? -1
                                              : (long)Header.UncompressedSize));
            }

            case ZipCompressionMethod.PPMd:
            {
                var props = new byte[2];
                stream.ReadFully(props);
                return(new PpmdStream(new PpmdProperties(props), stream, false));
            }

            case ZipCompressionMethod.WinzipAes:
            {
                ExtraData data = Header.Extra.Where(x => x.Type == ExtraDataType.WinZipAes).SingleOrDefault();
                if (data == null)
                {
                    throw new InvalidFormatException("No Winzip AES extra data found.");
                }
                if (data.Length != 7)
                {
                    throw new InvalidFormatException("Winzip data length is not 7.");
                }
                ushort compressedMethod = DataConverter.LittleEndian.GetUInt16(data.DataBytes, 0);

                if (compressedMethod != 0x01 && compressedMethod != 0x02)
                {
                    throw new InvalidFormatException("Unexpected vendor version number for WinZip AES metadata");
                }

                ushort vendorId = DataConverter.LittleEndian.GetUInt16(data.DataBytes, 2);
                if (vendorId != 0x4541)
                {
                    throw new InvalidFormatException("Unexpected vendor ID for WinZip AES metadata");
                }
                return(CreateDecompressionStream(stream, (ZipCompressionMethod)DataConverter.LittleEndian.GetUInt16(data.DataBytes, 5)));
            }

            default:
            {
                throw new NotSupportedException("CompressionMethod: " + Header.CompressionMethod);
            }
            }
        }
Пример #24
0
 /// <summary>
 /// Registers a delegate that can create a warpper stream for
 /// compressing or uncompressing the data of a source stream.
 /// </summary>
 /// <param name="compressionMethod">Compression method being registered.</param>
 /// <param name="compressionMode">Indicates registration for ether
 /// compress or decompress mode.</param>
 /// <param name="creator">Delegate being registered.</param>
 /// <remarks>
 /// For compression, the delegate accepts a stream that writes to the archive
 /// and returns a wrapper stream that compresses bytes as they are written.
 /// For decompression, the delegate accepts a stream that reads from the archive
 /// and returns a wrapper stream that decompresses bytes as they are read.
 /// This wrapper stream model follows the design used by
 /// System.IO.Compression.DeflateStream, and indeed that class is used
 /// to implement the Deflate compression method by default.
 /// <para>To unregister a delegate, call this method again and pass
 /// null for the delegate parameter.</para>
 /// </remarks>
 /// <example>
 /// When the ZipEngine class is initialized, the Deflate compression method
 /// is automatically registered like this:
 /// <code>
 ///        ZipEngine.RegisterCompressionStreamCreator(
 ///            ZipCompressionMethod.Deflate,
 ///            CompressionMode.Compress,
 ///            delegate(Stream stream) {
 ///                return new DeflateStream(stream, CompressionMode.Compress, true);
 ///            });
 ///        ZipEngine.RegisterCompressionStreamCreator(
 ///            ZipCompressionMethod.Deflate,
 ///            CompressionMode.Decompress,
 ///            delegate(Stream stream) {
 ///                return new DeflateStream(stream, CompressionMode.Decompress, true);
 ///            });
 /// </code></example>
 public static void RegisterCompressionStreamCreator(
     ZipCompressionMethod compressionMethod,
     CompressionMode compressionMode,
     Converter<Stream, Stream> creator)
 {
     ZipEngine.InitCompressionStreamCreators();
     if (compressionMode == CompressionMode.Compress)
     {
         ZipEngine.compressionStreamCreators[compressionMethod] = creator;
     }
     else
     {
         ZipEngine.decompressionStreamCreators[compressionMethod] = creator;
     }
 }
 internal uint Write(Stream outputStream, ZipCompressionMethod compression)
 {
     byte[] bytes = Encoding.UTF8.GetBytes(this.FileName);
     byte[] buffer = Encoding.UTF8.GetBytes(this.Comment);
     outputStream.Write(new byte[] { 80, 0x4b, 1, 2, 0x3f, 0, 10, 0 }, 0, 8);
     HeaderFlags flags = HeaderFlags.UTF8;
     if (!outputStream.CanSeek)
     {
         flags = (HeaderFlags) ((ushort) (flags | HeaderFlags.UsePostDataDescriptor));
         if (compression == ZipCompressionMethod.LZMA)
         {
             flags = (HeaderFlags) ((ushort) (flags | HeaderFlags.Bit1));
         }
     }
     outputStream.Write(BitConverter.GetBytes((ushort) flags), 0, 2);
     outputStream.Write(BitConverter.GetBytes((ushort) compression), 0, 2);
     outputStream.Write(BitConverter.GetBytes(Utility.DateTimeToDosTime(this.ModificationTime)), 0, 4);
     outputStream.Write(BitConverter.GetBytes(this.Crc), 0, 4);
     outputStream.Write(BitConverter.GetBytes(this.Compressed), 0, 4);
     outputStream.Write(BitConverter.GetBytes(this.Decompressed), 0, 4);
     outputStream.Write(BitConverter.GetBytes((ushort) bytes.Length), 0, 2);
     outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2);
     outputStream.Write(BitConverter.GetBytes((ushort) buffer.Length), 0, 2);
     outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2);
     outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2);
     outputStream.Write(BitConverter.GetBytes((ushort) 0), 0, 2);
     outputStream.Write(BitConverter.GetBytes((ushort) 0x8100), 0, 2);
     outputStream.Write(BitConverter.GetBytes(this.HeaderOffset), 0, 4);
     outputStream.Write(bytes, 0, bytes.Length);
     outputStream.Write(buffer, 0, buffer.Length);
     return (uint) ((0x2e + bytes.Length) + buffer.Length);
 }