Example #1
0
        private Stream OpenInReadMode(bool checkOpenable)
        {
            if (checkOpenable)
            {
                ThrowIfNotOpenable(needToUncompress: true, needToLoadIntoMemory: false);
            }

            Stream compressedStream = null;


            if (_archive.ArchiveStream is MemoryStream ms)
            {
                var buffer           = ms.GetBuffer();
                var readOnlySequence = new ReadOnlySequence <byte>(buffer, (int)OffsetOfCompressedData, (int)_compressedSize);
                compressedStream = new ReadOnlySequenceStream(readOnlySequence);
            }
            else
            {
                //old implementation, not thread safe in readmode
                compressedStream = new SubReadStream(_archive.ArchiveStream, OffsetOfCompressedData, _compressedSize);
            }
            //_archive.AddActiveReference();
            return(GetDataDecompressor(compressedStream));
        }
Example #2
0
        public static List <ZipGenericExtraField> GetExtraFields(BinaryReader reader)
        {
            // assumes that TrySkipBlock has already been called, so we don't have to validate twice

            List <ZipGenericExtraField> result;

            const int OffsetToFilenameLength = 26; // from the point before the signature

            reader.BaseStream.Seek(OffsetToFilenameLength, SeekOrigin.Current);

            ushort filenameLength   = reader.ReadUInt16();
            ushort extraFieldLength = reader.ReadUInt16();

            reader.BaseStream.Seek(filenameLength, SeekOrigin.Current);


            using (Stream str = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, extraFieldLength))
            {
                result = ZipGenericExtraField.ParseExtraField(str);
            }
            Zip64ExtraField.RemoveZip64Blocks(result);

            return(result);
        }
Example #3
0
        // if saveExtraFieldsAndComments is false, FileComment and ExtraFields will be null
        // in either case, the zip64 extra field info will be incorporated into other fields
        public static bool TryReadBlock(BinaryReader reader, bool saveExtraFieldsAndComments, out ZipCentralDirectoryFileHeader header)
        {
            header = new ZipCentralDirectoryFileHeader();

            if (reader.ReadUInt32() != SignatureConstant)
            {
                return(false);
            }
            header.VersionMadeBySpecification = reader.ReadByte();
            header.VersionMadeByCompatibility = reader.ReadByte();
            header.VersionNeededToExtract     = reader.ReadUInt16();
            header.GeneralPurposeBitFlag      = reader.ReadUInt16();
            header.CompressionMethod          = reader.ReadUInt16();
            header.LastModified = reader.ReadUInt32();
            header.Crc32        = reader.ReadUInt32();
            uint compressedSizeSmall   = reader.ReadUInt32();
            uint uncompressedSizeSmall = reader.ReadUInt32();

            header.FilenameLength    = reader.ReadUInt16();
            header.ExtraFieldLength  = reader.ReadUInt16();
            header.FileCommentLength = reader.ReadUInt16();
            ushort diskNumberStartSmall = reader.ReadUInt16();

            header.InternalFileAttributes = reader.ReadUInt16();
            header.ExternalFileAttributes = reader.ReadUInt32();
            uint relativeOffsetOfLocalHeaderSmall = reader.ReadUInt32();

            header.Filename = reader.ReadBytes(header.FilenameLength);

            bool uncompressedSizeInZip64 = uncompressedSizeSmall == ZipHelper.Mask32Bit;
            bool compressedSizeInZip64   = compressedSizeSmall == ZipHelper.Mask32Bit;
            bool relativeOffsetInZip64   = relativeOffsetOfLocalHeaderSmall == ZipHelper.Mask32Bit;
            bool diskNumberStartInZip64  = diskNumberStartSmall == ZipHelper.Mask16Bit;

            Zip64ExtraField zip64;

            long endExtraFields = reader.BaseStream.Position + header.ExtraFieldLength;

            using (Stream str = new SubReadStream(reader.BaseStream, reader.BaseStream.Position, header.ExtraFieldLength))
            {
                if (saveExtraFieldsAndComments)
                {
                    header.ExtraFields = ZipGenericExtraField.ParseExtraField(str);
                    zip64 = Zip64ExtraField.GetAndRemoveZip64Block(header.ExtraFields,
                                                                   uncompressedSizeInZip64, compressedSizeInZip64,
                                                                   relativeOffsetInZip64, diskNumberStartInZip64);
                }
                else
                {
                    header.ExtraFields = null;
                    zip64 = Zip64ExtraField.GetJustZip64Block(str,
                                                              uncompressedSizeInZip64, compressedSizeInZip64,
                                                              relativeOffsetInZip64, diskNumberStartInZip64);
                }
            }

            // There are zip files that have malformed ExtraField blocks in which GetJustZip64Block() silently bails out without reading all the way to the end
            // of the ExtraField block. Thus we must force the stream's position to the proper place.
            reader.BaseStream.AdvanceToPosition(endExtraFields);

            if (saveExtraFieldsAndComments)
            {
                header.FileComment = reader.ReadBytes(header.FileCommentLength);
            }
            else
            {
                reader.BaseStream.Position += header.FileCommentLength;
                header.FileComment          = null;
            }

            header.UncompressedSize = zip64.UncompressedSize == null
                                                    ? uncompressedSizeSmall
                                                    : zip64.UncompressedSize.Value;
            header.CompressedSize = zip64.CompressedSize == null
                                                    ? compressedSizeSmall
                                                    : zip64.CompressedSize.Value;
            header.RelativeOffsetOfLocalHeader = zip64.LocalHeaderOffset == null
                                                    ? relativeOffsetOfLocalHeaderSmall
                                                    : zip64.LocalHeaderOffset.Value;
            header.DiskNumberStart = zip64.StartDiskNumber == null
                                                    ? diskNumberStartSmall
                                                    : zip64.StartDiskNumber.Value;

            return(true);
        }