in src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs [941:1082]
public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandler resultHandler)
{
if (isDisposed_)
{
throw new ObjectDisposedException("ZipFile");
}
var status = new TestStatus(this);
resultHandler?.Invoke(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 (ZipException ex)
{
status.AddError();
resultHandler?.Invoke(status, $"Exception during test - '{ex.Message}'");
testing &= strategy != TestStrategy.FindFirstError;
}
if (testing && testData && this[entryIndex].IsFile)
{
// Don't check CRC for AES encrypted archives
var checkCRC = this[entryIndex].AESKeySize == 0;
if (resultHandler != null)
{
status.SetOperation(TestOperation.EntryData);
resultHandler(status, null);
}
var 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)
{
if (checkCRC)
{
crc.Update(new ArraySegment<byte>(buffer, 0, bytesRead));
}
if (resultHandler != null)
{
totalBytes += bytesRead;
status.SetBytesTested(totalBytes);
resultHandler(status, null);
}
}
}
if (checkCRC && this[entryIndex].Crc != crc.Value)
{
status.AddError();
resultHandler?.Invoke(status, "CRC mismatch");
testing &= strategy != TestStrategy.FindFirstError;
}
if ((this[entryIndex].Flags & (int)GeneralBitFlags.Descriptor) != 0)
{
var data = new DescriptorData();
ZipFormat.ReadDataDescriptor(baseStream_, this[entryIndex].LocalHeaderRequiresZip64, data);
if (checkCRC && this[entryIndex].Crc != data.Crc)
{
status.AddError();
resultHandler?.Invoke(status, "Descriptor CRC mismatch");
}
if (this[entryIndex].CompressedSize != data.CompressedSize)
{
status.AddError();
resultHandler?.Invoke(status, "Descriptor compressed size mismatch");
}
if (this[entryIndex].Size != data.Size)
{
status.AddError();
resultHandler?.Invoke(status, "Descriptor size mismatch");
}
}
}
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();
resultHandler?.Invoke(status, $"Exception during test - '{ex.Message}'");
}
if (resultHandler != null)
{
status.SetOperation(TestOperation.Complete);
status.SetEntry(null);
resultHandler(status, null);
}
return (status.ErrorCount == 0);
}