Exemple #1
0
        //This function reads all the EOCD stuff it needs to find the offset to the start of the central directory
        //This offset gets put in _centralDirectoryStart and the number of this disk gets put in _numberOfThisDisk
        //Also does some verification that this isn't a split/spanned archive
        //Also checks that offset to CD isn't out of bounds
        private void ReadEndOfCentralDirectory()
        {
            try
            {
                //this seeks to the start of the end of central directory record
                _archiveStream.Seek(-ZipEndOfCentralDirectoryBlock.SizeOfBlockWithoutSignature, SeekOrigin.End);
                if (!ZipHelper.SeekBackwardsToSignature(_archiveStream, ZipEndOfCentralDirectoryBlock.SignatureConstant))
                {
                    throw new InvalidDataException(SR.EOCDNotFound);
                }

                Int64 eocdStart = _archiveStream.Position;

                //read the EOCD
                ZipEndOfCentralDirectoryBlock eocd;
                Boolean eocdProper = ZipEndOfCentralDirectoryBlock.TryReadBlock(_archiveReader, out eocd);
                Debug.Assert(eocdProper); //we just found this using the signature finder, so it should be okay

                if (eocd.NumberOfThisDisk != eocd.NumberOfTheDiskWithTheStartOfTheCentralDirectory)
                {
                    throw new InvalidDataException(SR.SplitSpanned);
                }

                _numberOfThisDisk      = eocd.NumberOfThisDisk;
                _centralDirectoryStart = eocd.OffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber;
                if (eocd.NumberOfEntriesInTheCentralDirectory != eocd.NumberOfEntriesInTheCentralDirectoryOnThisDisk)
                {
                    throw new InvalidDataException(SR.SplitSpanned);
                }
                _expectedNumberOfEntries = eocd.NumberOfEntriesInTheCentralDirectory;

                //only bother saving the comment if we are in update mode
                if (_mode == ZipArchiveMode.Update)
                {
                    _archiveComment = eocd.ArchiveComment;
                }

                //only bother looking for zip64 EOCD stuff if we suspect it is needed because some value is FFFFFFFFF
                //because these are the only two values we need, we only worry about these
                //if we don't find the zip64 EOCD, we just give up and try to use the original values
                if (eocd.NumberOfThisDisk == ZipHelper.Mask16Bit ||
                    eocd.OffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber == ZipHelper.Mask32Bit ||
                    eocd.NumberOfEntriesInTheCentralDirectory == ZipHelper.Mask16Bit)
                {
                    //we need to look for zip 64 EOCD stuff
                    //seek to the zip 64 EOCD locator
                    _archiveStream.Seek(eocdStart - Zip64EndOfCentralDirectoryLocator.SizeOfBlockWithoutSignature, SeekOrigin.Begin);
                    //if we don't find it, assume it doesn't exist and use data from normal eocd
                    if (ZipHelper.SeekBackwardsToSignature(_archiveStream, Zip64EndOfCentralDirectoryLocator.SignatureConstant))
                    {
                        //use locator to get to Zip64EOCD
                        Zip64EndOfCentralDirectoryLocator locator;
                        Boolean zip64eocdLocatorProper = Zip64EndOfCentralDirectoryLocator.TryReadBlock(_archiveReader, out locator);
                        Debug.Assert(zip64eocdLocatorProper); //we just found this using the signature finder, so it should be okay

                        if (locator.OffsetOfZip64EOCD > (UInt64)Int64.MaxValue)
                        {
                            throw new InvalidDataException(SR.FieldTooBigOffsetToZip64EOCD);
                        }
                        Int64 zip64EOCDOffset = (Int64)locator.OffsetOfZip64EOCD;

                        _archiveStream.Seek(zip64EOCDOffset, SeekOrigin.Begin);

                        //read Zip64EOCD
                        Zip64EndOfCentralDirectoryRecord record;
                        if (!Zip64EndOfCentralDirectoryRecord.TryReadBlock(_archiveReader, out record))
                        {
                            throw new InvalidDataException(SR.Zip64EOCDNotWhereExpected);
                        }

                        _numberOfThisDisk = record.NumberOfThisDisk;

                        if (record.NumberOfEntriesTotal > (UInt64)Int64.MaxValue)
                        {
                            throw new InvalidDataException(SR.FieldTooBigNumEntries);
                        }
                        if (record.OffsetOfCentralDirectory > (UInt64)Int64.MaxValue)
                        {
                            throw new InvalidDataException(SR.FieldTooBigOffsetToCD);
                        }
                        if (record.NumberOfEntriesTotal != record.NumberOfEntriesOnThisDisk)
                        {
                            throw new InvalidDataException(SR.SplitSpanned);
                        }

                        _expectedNumberOfEntries = (Int64)record.NumberOfEntriesTotal;
                        _centralDirectoryStart   = (Int64)record.OffsetOfCentralDirectory;
                    }
                }

                if (_centralDirectoryStart > _archiveStream.Length)
                {
                    throw new InvalidDataException(SR.FieldTooBigOffsetToCD);
                }
            }
            catch (EndOfStreamException ex)
            {
                throw new InvalidDataException(SR.CDCorrupt, ex);
            }
            catch (IOException ex)
            {
                throw new InvalidDataException(SR.CDCorrupt, ex);
            }
        }
Exemple #2
0
        // Tries to find the Zip64 End of Central Directory Locator, then the Zip64 End of Central Directory, assuming the
        // End of Central Directory block has already been found, as well as the location in the stream where the EOCD starts.
        private void TryReadZip64EndOfCentralDirectory(ZipEndOfCentralDirectoryBlock eocd, long eocdStart)
        {
            // Only bother looking for the Zip64-EOCD stuff if we suspect it is needed because some value is FFFFFFFFF
            // because these are the only two values we need, we only worry about these
            // if we don't find the Zip64-EOCD, we just give up and try to use the original values
            if (eocd.NumberOfThisDisk == ZipHelper.Mask16Bit ||
                eocd.OffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber == ZipHelper.Mask32Bit ||
                eocd.NumberOfEntriesInTheCentralDirectory == ZipHelper.Mask16Bit)
            {
                // Read Zip64 End of Central Directory Locator

                // This seeks forwards almost to the beginning of the Zip64-EOCDL, one byte after where the signature would be located
                _archiveStream.Seek(eocdStart - Zip64EndOfCentralDirectoryLocator.SizeOfBlockWithoutSignature, SeekOrigin.Begin);

                // Exactly the previous 4 bytes should contain the Zip64-EOCDL signature
                // if we don't find it, assume it doesn't exist and use data from normal EOCD
                if (ZipHelper.SeekBackwardsToSignature(_archiveStream,
                                                       Zip64EndOfCentralDirectoryLocator.SignatureConstant,
                                                       Zip64EndOfCentralDirectoryLocator.SignatureSize))
                {
                    Debug.Assert(_archiveReader != null);

                    // use locator to get to Zip64-EOCD
                    Zip64EndOfCentralDirectoryLocator locator;
                    bool zip64eocdLocatorProper = Zip64EndOfCentralDirectoryLocator.TryReadBlock(_archiveReader, out locator);
                    Debug.Assert(zip64eocdLocatorProper); // we just found this using the signature finder, so it should be okay

                    if (locator.OffsetOfZip64EOCD > long.MaxValue)
                    {
                        throw new InvalidDataException(SR.FieldTooBigOffsetToZip64EOCD);
                    }

                    long zip64EOCDOffset = (long)locator.OffsetOfZip64EOCD;

                    _archiveStream.Seek(zip64EOCDOffset, SeekOrigin.Begin);

                    // Read Zip64 End of Central Directory Record

                    Zip64EndOfCentralDirectoryRecord record;
                    if (!Zip64EndOfCentralDirectoryRecord.TryReadBlock(_archiveReader, out record))
                    {
                        throw new InvalidDataException(SR.Zip64EOCDNotWhereExpected);
                    }

                    _numberOfThisDisk = record.NumberOfThisDisk;

                    if (record.NumberOfEntriesTotal > long.MaxValue)
                    {
                        throw new InvalidDataException(SR.FieldTooBigNumEntries);
                    }

                    if (record.OffsetOfCentralDirectory > long.MaxValue)
                    {
                        throw new InvalidDataException(SR.FieldTooBigOffsetToCD);
                    }

                    if (record.NumberOfEntriesTotal != record.NumberOfEntriesOnThisDisk)
                    {
                        throw new InvalidDataException(SR.SplitSpanned);
                    }

                    _expectedNumberOfEntries = (long)record.NumberOfEntriesTotal;
                    _centralDirectoryStart   = (long)record.OffsetOfCentralDirectory;
                }
            }
        }
Exemple #3
0
        // This function reads all the EOCD stuff it needs to find the offset to the start of the central directory
        // This offset gets put in _centralDirectoryStart and the number of this disk gets put in _numberOfThisDisk
        // Also does some verification that this isn't a split/spanned archive
        // Also checks that offset to CD isn't out of bounds
        private void ReadEndOfCentralDirectory()
        {
            try
            {
                // This seeks backwards almost to the beginning of the EOCD, one byte after where the signature would be
                // located if the EOCD had the minimum possible size (no file zip comment)
                _archiveStream.Seek(-ZipEndOfCentralDirectoryBlock.SizeOfBlockWithoutSignature, SeekOrigin.End);

                // If the EOCD has the minimum possible size (no zip file comment), then exactly the previous 4 bytes will contain the signature
                // But if the EOCD has max possible size, the signature should be found somewhere in the previous 64K + 4 bytes
                if (!ZipHelper.SeekBackwardsToSignature(_archiveStream,
                                                        ZipEndOfCentralDirectoryBlock.SignatureConstant,
                                                        ZipEndOfCentralDirectoryBlock.ZipFileCommentMaxLength + ZipEndOfCentralDirectoryBlock.SignatureSize))
                {
                    throw new InvalidDataException(SR.EOCDNotFound);
                }

                long eocdStart = _archiveStream.Position;

                // read the EOCD
                ZipEndOfCentralDirectoryBlock eocd;
                bool eocdProper = ZipEndOfCentralDirectoryBlock.TryReadBlock(_archiveReader, out eocd);
                Debug.Assert(eocdProper); // we just found this using the signature finder, so it should be okay

                if (eocd.NumberOfThisDisk != eocd.NumberOfTheDiskWithTheStartOfTheCentralDirectory)
                {
                    throw new InvalidDataException(SR.SplitSpanned);
                }

                _numberOfThisDisk      = eocd.NumberOfThisDisk;
                _centralDirectoryStart = eocd.OffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber;

                if (eocd.NumberOfEntriesInTheCentralDirectory != eocd.NumberOfEntriesInTheCentralDirectoryOnThisDisk)
                {
                    throw new InvalidDataException(SR.SplitSpanned);
                }

                _expectedNumberOfEntries = eocd.NumberOfEntriesInTheCentralDirectory;

                // only bother saving the comment if we are in update mode
                if (_mode == ZipArchiveMode.Update)
                {
                    _archiveComment = eocd.ArchiveComment;
                }

                TryReadZip64EndOfCentralDirectory(eocd, eocdStart);

                if (_centralDirectoryStart > _archiveStream.Length)
                {
                    throw new InvalidDataException(SR.FieldTooBigOffsetToCD);
                }
            }
            catch (EndOfStreamException ex)
            {
                throw new InvalidDataException(SR.CDCorrupt, ex);
            }
            catch (IOException ex)
            {
                throw new InvalidDataException(SR.CDCorrupt, ex);
            }
        }
Exemple #4
0
        // return value is true if we allocated an extra field for 64 bit headers, un/compressed size
        private bool WriteLocalFileHeader(bool isEmptyFile)
        {
            BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream);

            // _entryname only gets set when we read in or call moveTo. MoveTo does a check, and
            // reading in should not be able to produce an entryname longer than ushort.MaxValue
            Debug.Assert(_storedEntryNameBytes.Length <= ushort.MaxValue);

            // decide if we need the Zip64 extra field:
            Zip64ExtraField zip64ExtraField = new Zip64ExtraField();
            bool            zip64Used = false;
            uint            compressedSizeTruncated, uncompressedSizeTruncated;

            // if we already know that we have an empty file don't worry about anything, just do a straight shot of the header
            if (isEmptyFile)
            {
                CompressionMethod         = CompressionMethodValues.Stored;
                compressedSizeTruncated   = 0;
                uncompressedSizeTruncated = 0;
                Debug.Assert(_compressedSize == 0);
                Debug.Assert(_uncompressedSize == 0);
                Debug.Assert(_crc32 == 0);
            }
            else
            {
                // if we have a non-seekable stream, don't worry about sizes at all, and just set the right bit
                // if we are using the data descriptor, then sizes and crc should be set to 0 in the header
                if (_archive.Mode == ZipArchiveMode.Create && _archive.ArchiveStream.CanSeek == false && !isEmptyFile)
                {
                    _generalPurposeBitFlag |= BitFlagValues.DataDescriptor;
                    zip64Used = false;
                    compressedSizeTruncated   = 0;
                    uncompressedSizeTruncated = 0;
                    // the crc should not have been set if we are in create mode, but clear it just to be sure
                    Debug.Assert(_crc32 == 0);
                }
                else // if we are not in streaming mode, we have to decide if we want to write zip64 headers
                {
                    if (SizesTooLarge()
#if DEBUG_FORCE_ZIP64
                        || (_archive._forceZip64 && _archive.Mode == ZipArchiveMode.Update)
#endif
                        )
                    {
                        zip64Used = true;
                        compressedSizeTruncated   = ZipHelper.Mask32Bit;
                        uncompressedSizeTruncated = ZipHelper.Mask32Bit;

                        // prepare Zip64 extra field object. If we have one of the sizes, the other must go in there
                        zip64ExtraField.CompressedSize   = _compressedSize;
                        zip64ExtraField.UncompressedSize = _uncompressedSize;

                        VersionToExtractAtLeast(ZipVersionNeededValues.Zip64);
                    }
                    else
                    {
                        zip64Used = false;
                        compressedSizeTruncated   = (uint)_compressedSize;
                        uncompressedSizeTruncated = (uint)_uncompressedSize;
                    }
                }
            }

            // save offset
            _offsetOfLocalHeader = writer.BaseStream.Position;

            // calculate extra field. if zip64 stuff + original extraField aren't going to fit, dump the original extraField, because this is more important
            int bigExtraFieldLength = (zip64Used ? zip64ExtraField.TotalSize : 0)
                                      + (_lhUnknownExtraFields != null ? ZipGenericExtraField.TotalSize(_lhUnknownExtraFields) : 0);
            ushort extraFieldLength;
            if (bigExtraFieldLength > ushort.MaxValue)
            {
                extraFieldLength      = (ushort)(zip64Used ? zip64ExtraField.TotalSize : 0);
                _lhUnknownExtraFields = null;
            }
            else
            {
                extraFieldLength = (ushort)bigExtraFieldLength;
            }

            // write header
            writer.Write(ZipLocalFileHeader.SignatureConstant);
            writer.Write((ushort)_versionToExtract);
            writer.Write((ushort)_generalPurposeBitFlag);
            writer.Write((ushort)CompressionMethod);
            writer.Write(ZipHelper.DateTimeToDosTime(_lastModified.DateTime)); // uint
            writer.Write(_crc32);                                              // uint
            writer.Write(compressedSizeTruncated);                             // uint
            writer.Write(uncompressedSizeTruncated);                           // uint
            writer.Write((ushort)_storedEntryNameBytes.Length);
            writer.Write(extraFieldLength);                                    // ushort

            writer.Write(_storedEntryNameBytes);

            if (zip64Used)
            {
                zip64ExtraField.WriteBlock(_archive.ArchiveStream);
            }
            if (_lhUnknownExtraFields != null)
            {
                ZipGenericExtraField.WriteAllBlocks(_lhUnknownExtraFields, _archive.ArchiveStream);
            }

            return(zip64Used);
        }
Exemple #5
0
        // should only throw an exception in extremely exceptional cases because it is called from dispose
        internal void WriteCentralDirectoryFileHeader()
        {
            // This part is simple, because we should definitely know the sizes by this time
            BinaryWriter writer = new BinaryWriter(_archive.ArchiveStream);

            // _entryname only gets set when we read in or call moveTo. MoveTo does a check, and
            // reading in should not be able to produce an entryname longer than ushort.MaxValue
            Debug.Assert(_storedEntryNameBytes.Length <= ushort.MaxValue);

            // decide if we need the Zip64 extra field:
            Zip64ExtraField zip64ExtraField = new Zip64ExtraField();
            uint            compressedSizeTruncated, uncompressedSizeTruncated, offsetOfLocalHeaderTruncated;

            bool zip64Needed = false;

            if (SizesTooLarge()
#if DEBUG_FORCE_ZIP64
                || _archive._forceZip64
#endif
                )
            {
                zip64Needed               = true;
                compressedSizeTruncated   = ZipHelper.Mask32Bit;
                uncompressedSizeTruncated = ZipHelper.Mask32Bit;

                // If we have one of the sizes, the other must go in there as speced for LH, but not necessarily for CH, but we do it anyways
                zip64ExtraField.CompressedSize   = _compressedSize;
                zip64ExtraField.UncompressedSize = _uncompressedSize;
            }
            else
            {
                compressedSizeTruncated   = (uint)_compressedSize;
                uncompressedSizeTruncated = (uint)_uncompressedSize;
            }


            if (_offsetOfLocalHeader > uint.MaxValue
#if DEBUG_FORCE_ZIP64
                || _archive._forceZip64
#endif
                )
            {
                zip64Needed = true;
                offsetOfLocalHeaderTruncated = ZipHelper.Mask32Bit;

                // If we have one of the sizes, the other must go in there as speced for LH, but not necessarily for CH, but we do it anyways
                zip64ExtraField.LocalHeaderOffset = _offsetOfLocalHeader;
            }
            else
            {
                offsetOfLocalHeaderTruncated = (uint)_offsetOfLocalHeader;
            }

            if (zip64Needed)
            {
                VersionToExtractAtLeast(ZipVersionNeededValues.Zip64);
            }

            // determine if we can fit zip64 extra field and original extra fields all in
            int bigExtraFieldLength = (zip64Needed ? zip64ExtraField.TotalSize : 0)
                                      + (_cdUnknownExtraFields != null ? ZipGenericExtraField.TotalSize(_cdUnknownExtraFields) : 0);
            ushort extraFieldLength;
            if (bigExtraFieldLength > ushort.MaxValue)
            {
                extraFieldLength      = (ushort)(zip64Needed ? zip64ExtraField.TotalSize : 0);
                _cdUnknownExtraFields = null;
            }
            else
            {
                extraFieldLength = (ushort)bigExtraFieldLength;
            }

            writer.Write(ZipCentralDirectoryFileHeader.SignatureConstant);      // Central directory file header signature  (4 bytes)
            writer.Write((byte)_versionMadeBySpecification);                    // Version made by Specification (version)  (1 byte)
            writer.Write((byte)CurrentZipPlatform);                             // Version made by Compatibility (type)     (1 byte)
            writer.Write((ushort)_versionToExtract);                            // Minimum version needed to extract        (2 bytes)
            writer.Write((ushort)_generalPurposeBitFlag);                       // General Purpose bit flag                 (2 bytes)
            writer.Write((ushort)CompressionMethod);                            // The Compression method                   (2 bytes)
            writer.Write(ZipHelper.DateTimeToDosTime(_lastModified.DateTime));  // File last modification time and date     (4 bytes)
            writer.Write(_crc32);                                               // CRC-32                                   (4 bytes)
            writer.Write(compressedSizeTruncated);                              // Compressed Size                          (4 bytes)
            writer.Write(uncompressedSizeTruncated);                            // Uncompressed Size                        (4 bytes)
            writer.Write((ushort)_storedEntryNameBytes.Length);                 // File Name Length                         (2 bytes)
            writer.Write(extraFieldLength);                                     // Extra Field Length                       (2 bytes)

            // This should hold because of how we read it originally in ZipCentralDirectoryFileHeader:
            Debug.Assert((_fileComment == null) || (_fileComment.Length <= ushort.MaxValue));

            writer.Write(_fileComment != null ? (ushort)_fileComment.Length : (ushort)0); // file comment length
            writer.Write((ushort)0);                                                      // disk number start
            writer.Write((ushort)0);                                                      // internal file attributes
            writer.Write(_externalFileAttr);                                              // external file attributes
            writer.Write(offsetOfLocalHeaderTruncated);                                   // offset of local header

            writer.Write(_storedEntryNameBytes);

            // write extra fields
            if (zip64Needed)
            {
                zip64ExtraField.WriteBlock(_archive.ArchiveStream);
            }
            if (_cdUnknownExtraFields != null)
            {
                ZipGenericExtraField.WriteAllBlocks(_cdUnknownExtraFields, _archive.ArchiveStream);
            }

            if (_fileComment != null)
            {
                writer.Write(_fileComment);
            }
        }
Exemple #6
0
        private void ReadEndOfCentralDirectory()
        {
            ZipEndOfCentralDirectoryBlock     zipEndOfCentralDirectoryBlock;
            Zip64EndOfCentralDirectoryLocator zip64EndOfCentralDirectoryLocator;
            Zip64EndOfCentralDirectoryRecord  zip64EndOfCentralDirectoryRecord;

            try
            {
                this._archiveStream.Seek((long)-18, SeekOrigin.End);
                if (!ZipHelper.SeekBackwardsToSignature(this._archiveStream, 101010256))
                {
                    throw new InvalidDataException(Messages.EOCDNotFound);
                }
                long position = this._archiveStream.Position;
                ZipEndOfCentralDirectoryBlock.TryReadBlock(this._archiveReader, out zipEndOfCentralDirectoryBlock);
                if (zipEndOfCentralDirectoryBlock.NumberOfThisDisk != zipEndOfCentralDirectoryBlock.NumberOfTheDiskWithTheStartOfTheCentralDirectory)
                {
                    throw new InvalidDataException(Messages.SplitSpanned);
                }
                this._numberOfThisDisk      = zipEndOfCentralDirectoryBlock.NumberOfThisDisk;
                this._centralDirectoryStart = (long)zipEndOfCentralDirectoryBlock.OffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber;
                if (zipEndOfCentralDirectoryBlock.NumberOfEntriesInTheCentralDirectory != zipEndOfCentralDirectoryBlock.NumberOfEntriesInTheCentralDirectoryOnThisDisk)
                {
                    throw new InvalidDataException(Messages.SplitSpanned);
                }
                this._expectedNumberOfEntries = (long)zipEndOfCentralDirectoryBlock.NumberOfEntriesInTheCentralDirectory;
                if (this._mode == ZipArchiveMode.Update)
                {
                    this._archiveComment = zipEndOfCentralDirectoryBlock.ArchiveComment;
                }
                if (zipEndOfCentralDirectoryBlock.NumberOfThisDisk == 65535 || zipEndOfCentralDirectoryBlock.OffsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber == -1 || zipEndOfCentralDirectoryBlock.NumberOfEntriesInTheCentralDirectory == 65535)
                {
                    this._archiveStream.Seek(position - (long)16, SeekOrigin.Begin);
                    if (ZipHelper.SeekBackwardsToSignature(this._archiveStream, 117853008))
                    {
                        Zip64EndOfCentralDirectoryLocator.TryReadBlock(this._archiveReader, out zip64EndOfCentralDirectoryLocator);
                        if (zip64EndOfCentralDirectoryLocator.OffsetOfZip64EOCD > 9223372036854775807L)
                        {
                            throw new InvalidDataException(Messages.FieldTooBigOffsetToZip64EOCD);
                        }
                        long offsetOfZip64EOCD = (long)zip64EndOfCentralDirectoryLocator.OffsetOfZip64EOCD;
                        this._archiveStream.Seek(offsetOfZip64EOCD, SeekOrigin.Begin);
                        if (!Zip64EndOfCentralDirectoryRecord.TryReadBlock(this._archiveReader, out zip64EndOfCentralDirectoryRecord))
                        {
                            throw new InvalidDataException(Messages.Zip64EOCDNotWhereExpected);
                        }
                        this._numberOfThisDisk = zip64EndOfCentralDirectoryRecord.NumberOfThisDisk;
                        if (zip64EndOfCentralDirectoryRecord.NumberOfEntriesTotal > 9223372036854775807L)
                        {
                            throw new InvalidDataException(Messages.FieldTooBigNumEntries);
                        }
                        if (zip64EndOfCentralDirectoryRecord.OffsetOfCentralDirectory > 9223372036854775807L)
                        {
                            throw new InvalidDataException(Messages.FieldTooBigOffsetToCD);
                        }
                        if (zip64EndOfCentralDirectoryRecord.NumberOfEntriesTotal != zip64EndOfCentralDirectoryRecord.NumberOfEntriesOnThisDisk)
                        {
                            throw new InvalidDataException(Messages.SplitSpanned);
                        }
                        this._expectedNumberOfEntries = (long)zip64EndOfCentralDirectoryRecord.NumberOfEntriesTotal;
                        this._centralDirectoryStart   = (long)zip64EndOfCentralDirectoryRecord.OffsetOfCentralDirectory;
                    }
                }
                if (this._centralDirectoryStart > this._archiveStream.Length)
                {
                    throw new InvalidDataException(Messages.FieldTooBigOffsetToCD);
                }
            }
            catch (EndOfStreamException endOfStreamException)
            {
                throw new InvalidDataException(Messages.CDCorrupt, endOfStreamException);
            }
            catch (IOException oException)
            {
                throw new InvalidDataException(Messages.CDCorrupt, oException);
            }
        }