/// <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();
            }
        }
Beispiel #2
0
		/// <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();
			}
		}