internal IEnumerable <ZipHeader> ReadSeekableHeader(Stream stream)
        {
            var reader = new BinaryReader(stream);

            SeekBackToHeader(stream, reader, DIRECTORY_END_HEADER_BYTES);
            var entry = new DirectoryEndHeader();

            entry.Read(reader);

            if (entry.IsZip64)
            {
                _zip64 = true;
                SeekBackToHeader(stream, reader, ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR);
                var zip64Locator = new Zip64DirectoryEndLocatorHeader();
                zip64Locator.Read(reader);

                stream.Seek(zip64Locator.RelativeOffsetOfTheEndOfDirectoryRecord, SeekOrigin.Begin);
                uint zip64Signature = reader.ReadUInt32();
                if (zip64Signature != ZIP64_END_OF_CENTRAL_DIRECTORY)
                {
                    throw new ArchiveException("Failed to locate the Zip64 Header");
                }

                var zip64Entry = new Zip64DirectoryEndHeader();
                zip64Entry.Read(reader);
                stream.Seek(zip64Entry.DirectoryStartOffsetRelativeToDisk, SeekOrigin.Begin);
            }
            else
            {
                stream.Seek(entry.DirectoryStartOffsetRelativeToDisk, SeekOrigin.Begin);
            }

            long position = stream.Position;

            while (true)
            {
                stream.Position = position;
                uint signature  = reader.ReadUInt32();
                var  nextHeader = ReadHeader(signature, reader, _zip64);
                position = stream.Position;

                if (nextHeader == null)
                {
                    yield break;
                }

                if (nextHeader is DirectoryEntryHeader entryHeader)
                {
                    //entry could be zero bytes so we need to know that.
                    entryHeader.HasData = entryHeader.CompressedSize != 0;
                    yield return(entryHeader);
                }
                else if (nextHeader is DirectoryEndHeader endHeader)
                {
                    yield return(endHeader);
                }
            }
        }
Esempio n. 2
0
        protected ZipHeader ReadHeader(uint headerBytes, BinaryReader reader, bool zip64 = false)
        {
            switch (headerBytes)
            {
            case ENTRY_HEADER_BYTES:
            {
                var entryHeader = new LocalEntryHeader(_archiveEncoding);
                entryHeader.Read(reader);
                LoadHeader(entryHeader, reader.BaseStream);

                _lastEntryHeader = entryHeader;
                return(entryHeader);
            }

            case DIRECTORY_START_HEADER_BYTES:
            {
                var entry = new DirectoryEntryHeader(_archiveEncoding);
                entry.Read(reader);
                return(entry);
            }

            case POST_DATA_DESCRIPTOR:
            {
                if (FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor))
                {
                    _lastEntryHeader.Crc              = reader.ReadUInt32();
                    _lastEntryHeader.CompressedSize   = zip64 ? (long)reader.ReadUInt64() : reader.ReadUInt32();
                    _lastEntryHeader.UncompressedSize = zip64 ? (long)reader.ReadUInt64() : reader.ReadUInt32();
                }
                else
                {
                    reader.ReadBytes(zip64 ? 20 : 12);
                }
                return(null);
            }

            case DIGITAL_SIGNATURE:
                return(null);

            case DIRECTORY_END_HEADER_BYTES:
            {
                var entry = new DirectoryEndHeader();
                entry.Read(reader);
                return(entry);
            }

            case SPLIT_ARCHIVE_HEADER_BYTES:
            {
                return(new SplitHeader());
            }

            case ZIP64_END_OF_CENTRAL_DIRECTORY:
            {
                var entry = new Zip64DirectoryEndHeader();
                entry.Read(reader);
                return(entry);
            }

            case ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR:
            {
                var entry = new Zip64DirectoryEndLocatorHeader();
                entry.Read(reader);
                return(entry);
            }

            default:
                return(null);
            }
        }