public ZipEndOfCentralDirectory(Stream stream)
        {
            BinaryReader reader = new BinaryReader(stream);

            // Start searching for the Zip End of Central Directory signature from the end
            // of the file backwards (towards the beginning of the file). This allows us to
            // find Zip archives with extra data appended to the archive (for whatever reason
            // someone might want to do that).
            long offset = stream.Length - ZipEndOfCentralDirectory.EOCD_RECORD_FIXEDSIZE;

            for (; offset >= 0; --offset)
            {
                stream.Seek(offset, SeekOrigin.Begin);

                uint sig = reader.ReadUInt32();
                if (sig == ZipEndOfCentralDirectory.EOCDSIG)
                {
                    break;
                }
            }

            if (offset < 0)
            {
                throw new InvalidDataException("Failed to find end of central directory record.");
            }

            stream.Seek(offset, SeekOrigin.Begin);
            this.Read(stream);

            // If the offset to the central directory is DWORD_MAX then this must be a 64-bit
            // archive.
            if (this.dirOffset == (long)UInt32.MaxValue)
            {
                string saveComment = this.comment;

                stream.Seek(offset - Zip64EndOfCentralDirectoryLocator.EOCDL64_SIZE, SeekOrigin.Begin);

                Zip64EndOfCentralDirectoryLocator eocdl = new Zip64EndOfCentralDirectoryLocator(stream);
                if (eocdl.dirStartDiskNumber == eocdl.totalDisks - 1)
                {
                    // ZIP64 eocd is entirely in current stream.
                    stream.Seek(eocdl.dirOffset, SeekOrigin.Begin);
                    this.Read64(stream);
                }
                else
                {
                    // TODO: handle EOCD64 spanning archives!
                    throw new NotImplementedException("Zip implementation does not handle end of central directory record that spans archives.");
                }

                this.comment = saveComment;
            }

            // Read the central directory for the archive.
            stream.Seek(this.dirOffset, SeekOrigin.Begin);

            while (this.headers.Count < this.totalEntries)
            {
                ZipFileHeader header = new ZipFileHeader(true);
                if (!header.Read(stream))
                {
                    throw new InvalidDataException("Missing or invalid central directory file header");
                }

                this.headers.Add(header);

                if (this.headers.Count < this.totalEntries && stream.Position == stream.Length)
                {
                    //streamContext.CloseArchiveReadStream(this.currentArchiveNumber, String.Empty, archiveStream);
                    //this.currentArchiveNumber++;
                    //archiveStream = streamContext.OpenArchiveReadStream(this.currentArchiveNumber, String.Empty, this);
                    //if (archiveStream == null)
                    //{
                    //    this.currentArchiveNumber = 0;
                    //    archiveStream = streamContext.OpenArchiveReadStream(this.currentArchiveNumber, String.Empty, this);
                    //}
                }
            }
        }
Пример #2
0
        public IList <ZipFileHeader> GetCentralDirectory(Stream streamContext)
        {
            Stream archiveStream = null;

            //this.currentArchiveNumber = 0;
            try
            {
                List <ZipFileHeader> headers = new List <ZipFileHeader>();
                archiveStream = streamContext;
                //archiveStream = this.OpenArchive(streamContext, 0);

                ZipEndOfCentralDirectory eocd = this.GetEOCD(archiveStream);
                if (eocd == null)
                {
                    return(null);
                }
                else if (eocd.totalEntries == 0)
                {
                    return(headers);
                }

                headers.Capacity = (int)eocd.totalEntries;

                if (eocd.dirOffset > archiveStream.Length - ZipFileHeader.CFH_FIXEDSIZE)
                {
                    //streamContext.CloseArchiveReadStream(this.currentArchiveNumber, String.Empty, archiveStream);
                    archiveStream = null;
                }
                else
                {
                    archiveStream.Seek(eocd.dirOffset, SeekOrigin.Begin);
                    uint sig = new BinaryReader(archiveStream).ReadUInt32();
                    if (sig != ZipFileHeader.CFHSIG)
                    {
                        //streamContext.CloseArchiveReadStream(this.currentArchiveNumber, String.Empty, archiveStream);
                        archiveStream = null;
                    }
                }

                if (archiveStream == null)
                {
                    //this.currentArchiveNumber = (short)(eocd.dirStartDiskNumber + 1);
                    //archiveStream = streamContext.OpenArchiveReadStream(this.currentArchiveNumber, String.Empty, this);

                    if (archiveStream == null)
                    {
                        return(null);
                    }
                }

                archiveStream.Seek(eocd.dirOffset, SeekOrigin.Begin);

                while (headers.Count < eocd.totalEntries)
                {
                    ZipFileHeader header = new ZipFileHeader(true);
                    if (!header.Read(archiveStream))
                    {
                        throw new InvalidDataException("Missing or invalid central directory file header");
                    }

                    headers.Add(header);

                    if (headers.Count < eocd.totalEntries && archiveStream.Position == archiveStream.Length)
                    {
                        //streamContext.CloseArchiveReadStream(this.currentArchiveNumber, String.Empty, archiveStream);
                        //this.currentArchiveNumber++;
                        //archiveStream = streamContext.OpenArchiveReadStream(this.currentArchiveNumber, String.Empty, this);
                        //if (archiveStream == null)
                        //{
                        //    this.currentArchiveNumber = 0;
                        //    archiveStream = streamContext.OpenArchiveReadStream(this.currentArchiveNumber, String.Empty, this);
                        //}
                    }
                }

                return(headers);
            }
            finally
            {
                //if (archiveStream != null)
                //{
                //    streamContext.CloseArchiveReadStream(this.currentArchiveNumber, String.Empty, archiveStream);
                //}
            }
        }