/// <summary> /// Read data descriptor at the end of compressed data. /// </summary> /// <param name="blubb64">if set to <c>true</c> [blubb64].</param> /// <param name="data">The data to fill in.</param> /// <returns>Returns the number of bytes read in the descriptor.</returns> public void ReadDataDescriptor(bool blubb64, DescriptorData data) { int intValue = ReadLEInt(); // In theory this may not be a descriptor according to PKZIP appnote. // In practise its always there. if (intValue != BlubbZipConstants.DataDescriptorSignature) { throw new BlubbZipException("Data descriptor signature not found"); } data.Crc = ReadLEInt(); if (blubb64) { data.CompressedSize = ReadLELong(); data.Size = ReadLELong(); } else { data.CompressedSize = ReadLEInt(); data.Size = ReadLEInt(); } }
/// <summary> /// Test an archive for integrity/validity /// </summary> /// <param name="testData">Perform low level data Crc check</param> /// <param name="strategy">The <see cref="TestStrategy"></see> to apply.</param> /// <param name="resultHandler">The <see cref="BlubbTestResultHandler"></see> handler to call during testing.</param> /// <returns>true if all tests pass, false otherwise</returns> /// <exception cref="ObjectDisposedException">The object has already been closed.</exception> public bool TestArchive( bool testData, TestStrategy strategy, BlubbTestResultHandler resultHandler ) { if( isDisposed_ ) { throw new ObjectDisposedException( "BlubbFile" ); } TestStatus status = new TestStatus( this ); if( resultHandler != null ) { resultHandler( status, null ); } HeaderTest test = testData ? ( HeaderTest.Header | HeaderTest.Extract ) : HeaderTest.Header; bool testing = true; try { int entryIndex = 0; while( testing && ( entryIndex < Count ) ) { if( resultHandler != null ) { status.SetEntry( this[ entryIndex ] ); status.SetOperation( TestOperation.EntryHeader ); resultHandler( status, null ); } try { TestLocalHeader( this[ entryIndex ], test ); } catch( BlubbZipException ex ) { status.AddError(); if( resultHandler != null ) { resultHandler( status, string.Format( "Exception during test - '{0}'", ex.Message ) ); } if( strategy == TestStrategy.FindFirstError ) { testing = false; } } if( testing && testData && this[ entryIndex ].IsFile ) { if( resultHandler != null ) { status.SetOperation( TestOperation.EntryData ); resultHandler( status, null ); } Crc32 crc = new Crc32(); using( Stream entryStream = this.GetInputStream( this[ entryIndex ] ) ) { byte[] buffer = new byte[ 4096 ]; long totalBytes = 0; int bytesRead; while( ( bytesRead = entryStream.Read( buffer, 0, buffer.Length ) ) > 0 ) { crc.Update( buffer, 0, bytesRead ); if( resultHandler != null ) { totalBytes += bytesRead; status.SetBytesTested( totalBytes ); resultHandler( status, null ); } } } if( this[ entryIndex ].Crc != crc.Value ) { status.AddError(); if( resultHandler != null ) { resultHandler( status, "CRC mismatch" ); } if( strategy == TestStrategy.FindFirstError ) { testing = false; } } if( ( this[ entryIndex ].Flags & (int)GeneralBitFlags.Descriptor ) != 0 ) { BlubbZipHelperStream helper = new BlubbZipHelperStream( baseStream_ ); DescriptorData data = new DescriptorData(); helper.ReadDataDescriptor( this[ entryIndex ].LocalHeaderRequiresBlubb64, data ); if( this[ entryIndex ].Crc != data.Crc ) { status.AddError(); } if( this[ entryIndex ].CompressedSize != data.CompressedSize ) { status.AddError(); } if( this[ entryIndex ].Size != data.Size ) { status.AddError(); } } } if( resultHandler != null ) { status.SetOperation( TestOperation.EntryComplete ); resultHandler( status, null ); } entryIndex += 1; } if( resultHandler != null ) { status.SetOperation( TestOperation.MiscellaneousTests ); resultHandler( status, null ); } // TODO: the 'Corrina Johns' test where local headers are missing from // the central directory. They are therefore invisible to many archivers. } catch( Exception ex ) { status.AddError(); if( resultHandler != null ) { resultHandler( status, string.Format( "Exception during test - '{0}'", ex.Message ) ); } } if( resultHandler != null ) { status.SetOperation( TestOperation.Complete ); status.SetEntry( null ); resultHandler( status, null ); } return ( status.ErrorCount == 0 ); }
/// <summary> /// Read data descriptor at the end of compressed data. /// </summary> /// <param name="blubb64">if set to <c>true</c> [blubb64].</param> /// <param name="data">The data to fill in.</param> /// <returns>Returns the number of bytes read in the descriptor.</returns> public void ReadDataDescriptor( bool blubb64, DescriptorData data ) { int intValue = ReadLEInt(); // In theory this may not be a descriptor according to PKZIP appnote. // In practise its always there. if( intValue != BlubbZipConstants.DataDescriptorSignature ) { throw new BlubbZipException( "Data descriptor signature not found" ); } data.Crc = ReadLEInt(); if( blubb64 ) { data.CompressedSize = ReadLELong(); data.Size = ReadLELong(); } else { data.CompressedSize = ReadLEInt(); data.Size = ReadLEInt(); } }