private ZipIOZip64EndOfCentralDirectoryLocatorBlock(ZipIOBlockManager blockManager) { Debug.Assert(blockManager != null); _blockManager = blockManager; }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ private ZipIOCentralDirectoryBlock(ZipIOBlockManager blockManager) { _blockManager = blockManager; }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ private ZipIORawDataFileBlock(ZipIOBlockManager blockManager) { _blockManager = blockManager; }
// !!! ATTENTION !!!! This function is only supposed to be called by // Block Manager.Save which has proper protection to ensure no stack overflow will happen // as a result of Stream.Flush calls which in turn result in BlockManager.Save calls public void UpdateReferences(bool closingFlag) { Invariant.Assert(!_blockManager.Streaming); long uncompressedSize; long compressedSize; CheckDisposed(); if (closingFlag) { CloseExposedStreams(); } else { FlushExposedStreams(); } // At this point we can update Local Headers with the proper CRC Value // We can also update other Local File Header Values (compressed/uncompressed size) // we rely on our DirtyFlag property to properly account for all possbile modifications within streams if (GetDirtyFlag(closingFlag)) { // Remember the size of the header before update long headerSizeBeforeUpdate = _localFileHeader.Size; // now prior to possibly closing streams we need to preserve uncompressed Size // otherwise Length function will fail to give it to us later after closing uncompressedSize = _crcCalculatingStream.Length; // calculate CRC prior to closing _localFileHeader.Crc32 = _crcCalculatingStream.CalculateCrc(); // If we are closing we can do extra things , calculate CRC , close deflate stream // it is particularly important to close the deflate stream as it might hold some extra bytes // even after Flush() if (closingFlag) { // we have got the CRC so we can close the stream _crcCalculatingStream.Close(); // in order to get proper compressed size we have to close the deflate stream if (_deflateStream != null) { _deflateStream.Close(); } } if (_fileItemStream.DataChanged) { _localFileHeader.LastModFileDateTime = ZipIOBlockManager.ToMsDosDateTime(DateTime.Now); } // get compressed size after possible closing Deflated stream // as a result of some ineffeciencies in CRC calculation it might result in Seek in compressed stream // and there fore switching mode and flushing extra compressed bytes compressedSize = _fileItemStream.Length; // this will properly (taking into account ZIP64 scenario) update local file header // Offset is passed in to determine whether ZIP 64 is required for small files that // happened to be located required 32 bit offset in the archive _localFileHeader.UpdateZip64Structures(compressedSize, uncompressedSize, Offset); // Add/remove padding to compensate the header size change // NOTE: Padding needs to be updated only after updating all the header fields // that can affect the header size _localFileHeader.UpdatePadding(_localFileHeader.Size - headerSizeBeforeUpdate); // We always save File Items in Non-streaming mode unless it wasn't touched //in which case we leave them alone _localFileHeader.StreamingCreationFlag = false; _localFileDataDescriptor = null; // in some cases UpdateZip64Structures call might result in creation/removal // of extra field if such thing happened we need to move FileItemStream appropriatel _fileItemStream.Move(checked (Offset + _localFileHeader.Size - _fileItemStream.Offset)); _dirtyFlag = true; } #if FALSE // we would like to take this oppportunity and validate basic asumption // that our GetDirtyFlag method is a reliable way to finding changes // there is no scenario in which change will happened, affecting sizes // and will not be registered by the GetDirtyFlag // ??????????????????????? else { // we even willing to recalculate CRC just in case for verification purposes UInt32 calculatedCRC32 = CalculateCrc32(); if (!_localFileHeader.StreamingCreationFlag) { Debug.Assert(_localFileHeader.Crc32 == calculatedCRC32); Debug.Assert(_localFileHeader.CompressedSize == CompressedSize); Debug.Assert(_localFileHeader.UncompressedSize == UncompressedSize); } else { Debug.Assert(_localFileDataDescriptor.Crc32 == calculatedCRC32); Debug.Assert(_localFileDataDescriptor.CompressedSize == CompressedSize); Debug.Assert(_localFileDataDescriptor.UncompressedSize == UncompressedSize); } /////////////////////////////////////////////////////////////////////// // we do not have an initialized value for the compressed size in this case compressedSize = _fileItemStream.Length; Debug.Assert(CompressedSize == compressedSize); Debug.Assert(UncompressedSize == uncompressedSize); } #endif }
///////////////////////////// // Internal Constructor ///////////////////////////// internal ProgressiveCrcCalculatingStream(ZipIOBlockManager blockManager, Stream underlyingStream) : this(blockManager, underlyingStream, 0) { _validateCrcWithExpectedCrc = false; }
internal static ZipIOLocalFileDataDescriptor ParseRecord(BinaryReader reader, long compressedSizeFromCentralDir, long uncompressedSizeFromCentralDir, UInt32 crc32FromCentralDir, UInt16 versionNeededToExtract) { ZipIOLocalFileDataDescriptor descriptor = new ZipIOLocalFileDataDescriptor(); // There are 4 distinct scenario we would like to support // 1.based on the appnote it seems that the structure of this record is following: // crc-32 4 bytes // compressed size 4 bytes (scenario 1.a has 8 bytes) // uncompressed size 4 bytes (scenario 1.a has 8 bytes) // // 2.based on files that we have been able to examine // data descriptor signature 4 bytes (0x08074b50) // crc-32 4 bytes // compressed size 4 bytes (scenario 2.a has 8 bytes) // uncompressed size 4 bytes (scenario 2.a has 8 bytes) // // we can safely assume that this record is not the last one in the file, so let's just // read the max Bytes required to store the largest structure , and compare results // at most we are looking at 6 * 4 = 24 bytes UInt32[] buffer = new UInt32[6]; // let's try to match the smallest possible structure (3 x 4) 32 bit without signature buffer[0] = reader.ReadUInt32(); buffer[1] = reader.ReadUInt32(); buffer[2] = reader.ReadUInt32(); if (descriptor.TestMatch(_signatureConstant, crc32FromCentralDir, compressedSizeFromCentralDir, uncompressedSizeFromCentralDir, _signatureConstant, buffer[0], buffer[1], buffer[2])) { descriptor._size = _fixedMinimalRecordSizeWithoutSignature; return(descriptor); } // let's try to match the next record size (4 x 4) 32 bit with signature buffer[3] = reader.ReadUInt32(); if (descriptor.TestMatch(_signatureConstant, crc32FromCentralDir, compressedSizeFromCentralDir, uncompressedSizeFromCentralDir, buffer[0], buffer[1], buffer[2], buffer[3])) { descriptor._size = _fixedMinimalRecordSizeWithSignature; return(descriptor); } // At this point prior to trying to match 64 bit structures we need to make sure that version is high enough if (versionNeededToExtract < (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } //let's try to match the 64 bit structures 64 bit without signature buffer[4] = reader.ReadUInt32(); if (descriptor.TestMatch(_signatureConstant, crc32FromCentralDir, compressedSizeFromCentralDir, uncompressedSizeFromCentralDir, _signatureConstant, buffer[0], ZipIOBlockManager.ConvertToUInt64(buffer[1], buffer[2]), ZipIOBlockManager.ConvertToUInt64(buffer[3], buffer[4]))) { descriptor._size = _fixedMinimalRecordSizeWithoutSignatureZip64; return(descriptor); } //let's try to match the 64 bit structures 64 bit with signature buffer[5] = reader.ReadUInt32(); if (descriptor.TestMatch(_signatureConstant, crc32FromCentralDir, compressedSizeFromCentralDir, uncompressedSizeFromCentralDir, buffer[0], buffer[1], ZipIOBlockManager.ConvertToUInt64(buffer[2], buffer[3]), ZipIOBlockManager.ConvertToUInt64(buffer[4], buffer[5]))) { descriptor._size = _fixedMinimalRecordSizeWithSignatureZip64; return(descriptor); } // we couldn't match anything at this point we need to fail throw new FileFormatException(SR.Get(SRID.CorruptedData)); }