Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip forced Deflate flush when using Stored compression #406

Merged
merged 2 commits into from
Jan 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ public override int Read(byte[] buffer, int offset, int count)
}

/// <summary>
/// Flushes the stream by calling <see cref="DeflaterOutputStream.Flush">Flush</see> on the deflater and then
/// Flushes the stream by calling <see cref="Flush">Flush</see> on the deflater and then
/// on the underlying stream. This ensures that all bytes are flushed.
/// </summary>
public override void Flush()
Expand Down
11 changes: 8 additions & 3 deletions src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,10 +1069,15 @@ private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
bool testHeader = (tests & HeaderTest.Header) != 0;
bool testData = (tests & HeaderTest.Extract) != 0;

baseStream_.Seek(offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin);
if ((int)ReadLEUint() != ZipConstants.LocalHeaderSignature)
var entryAbsOffset = offsetOfFirstEntry + entry.Offset;

baseStream_.Seek(entryAbsOffset, SeekOrigin.Begin);
var signature = (int)ReadLEUint();

if (signature != ZipConstants.LocalHeaderSignature)
{
throw new ZipException(string.Format("Wrong local header signature @{0:X}", offsetOfFirstEntry + entry.Offset));
throw new ZipException(string.Format("Wrong local header signature at 0x{0:x}, expected 0x{1:x8}, actual 0x{2:x8}",
entryAbsOffset, ZipConstants.LocalHeaderSignature, signature));
}

var extractVersion = (short)(ReadLEUshort() & 0x00ff);
Expand Down
16 changes: 16 additions & 0 deletions src/ICSharpCode.SharpZipLib/Zip/ZipOutputStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,22 @@ public override void Finish()
entries = null;
}

/// <summary>
/// Flushes the stream by calling <see cref="DeflaterOutputStream.Flush">Flush</see> on the deflater stream unless
/// the current compression method is <see cref="CompressionMethod.Stored"/>. Then it flushes the underlying output stream.
/// </summary>
public override void Flush()
{
if(curMethod == CompressionMethod.Stored)
{
baseOutputStream_.Flush();
}
else
{
base.Flush();
}
}

#region Instance Fields

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ public byte this[int index]
}

[TestFixture]
[Explicit("Meta tests (for ringbuffer)")]
public class ExerciseBuffer
{
[Test]
Expand Down
31 changes: 24 additions & 7 deletions test/ICSharpCode.SharpZipLib.Tests/TestSupport/Utils.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using NUnit.Framework;
using System;
using System.IO;
using System.Text;

namespace ICSharpCode.SharpZipLib.Tests.TestSupport
{
Expand All @@ -9,6 +10,8 @@ namespace ICSharpCode.SharpZipLib.Tests.TestSupport
/// </summary>
public static class Utils
{
public static int DummyContentLength = 16;

private static Random random = new Random();

private static void Compare(byte[] a, byte[] b)
Expand All @@ -32,16 +35,24 @@ private static void Compare(byte[] a, byte[] b)

public static void WriteDummyData(string fileName, int size = -1)
{
if (size < 0)
using(var fs = File.OpenWrite(fileName))
{
File.WriteAllText(fileName, DateTime.UtcNow.Ticks.ToString("x16"));
WriteDummyData(fs, size);
}
else if (size > 0)
}

public static void WriteDummyData(Stream stream, int size = -1)
{
var bytes = (size < 0)
? Encoding.ASCII.GetBytes(DateTime.UtcNow.Ticks.ToString("x16"))
: new byte[size];

if(size > 0)
{
var bytes = Array.CreateInstance(typeof(byte), size) as byte[];
random.NextBytes(bytes);
File.WriteAllBytes(fileName, bytes);
}

stream.Write(bytes, 0, bytes.Length);
}

public static TempFile GetDummyFile(int size = -1)
Expand Down Expand Up @@ -85,7 +96,10 @@ protected virtual void Dispose(bool disposing)
}

public void Dispose()
=> Dispose(true);
{
Dispose(true);
GC.SuppressFinalize(this);
}

#endregion IDisposable Support
}
Expand Down Expand Up @@ -122,7 +136,10 @@ protected virtual void Dispose(bool disposing)
}

public void Dispose()
=> Dispose(true);
{
Dispose(true);
GC.SuppressFinalize(this);
}

internal string CreateDummyFile(int size = -1)
=> CreateDummyFile(GetDummyFileName(), size);
Expand Down
26 changes: 26 additions & 0 deletions test/ICSharpCode.SharpZipLib.Tests/Zip/FastZipHandling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,32 @@ public void ExtractEmptyDirectories()
Assert.IsTrue(Directory.Exists(targetDir), "Empty directory should be created");
}

[Test]
[Category("Zip")]
[Category("CreatesTempFile")]
public void ContentEqualAfterAfterArchived([Values(0, 1, 64)]int contentSize)
{
using(var sourceDir = new Utils.TempDir())
using(var targetDir = new Utils.TempDir())
using(var zipFile = Utils.GetDummyFile(0))
{
var sourceFile = sourceDir.CreateDummyFile(contentSize);
var sourceContent = File.ReadAllBytes(sourceFile);
new FastZip().CreateZip(zipFile.Filename, sourceDir.Fullpath, true, null);

Assert.DoesNotThrow(() =>
{
new FastZip().ExtractZip(zipFile.Filename, targetDir.Fullpath, null);
}, "Exception during extraction of test archive");

var targetFile = Path.Combine(targetDir.Fullpath, Path.GetFileName(sourceFile));
var targetContent = File.ReadAllBytes(targetFile);

Assert.AreEqual(sourceContent.Length, targetContent.Length, "Extracted file size does not match source file size");
Assert.AreEqual(sourceContent, targetContent, "Extracted content does not match source content");
}
}

[Test]
[Category("Zip")]
public void Encryption()
Expand Down
50 changes: 49 additions & 1 deletion test/ICSharpCode.SharpZipLib.Tests/Zip/StreamHandling.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ICSharpCode.SharpZipLib.Tests.TestSupport;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Tests.TestSupport;
using ICSharpCode.SharpZipLib.Zip;
using NUnit.Framework;
using System.IO;
Expand Down Expand Up @@ -190,6 +191,53 @@ public void EmptyZipEntries()
Assert.AreEqual(extractCount, 0, "No data should be read from empty entries");
}

[Test]
[Category("Zip")]
public void WriteZipStreamWithNoCompression([Values(0, 1, 256)] int contentLength)
{
var buffer = new byte[255];

using (var dummyZip = Utils.GetDummyFile(0))
using (var inputFile = Utils.GetDummyFile(contentLength))
{
using (var zipFileStream = File.OpenWrite(dummyZip.Filename))
using (var zipOutputStream = new ZipOutputStream(zipFileStream))
using (var inputFileStream = File.OpenRead(inputFile.Filename))
{
zipOutputStream.PutNextEntry(new ZipEntry(inputFile.Filename)
{
CompressionMethod = CompressionMethod.Stored,
});

StreamUtils.Copy(inputFileStream, zipOutputStream, buffer);
}

using (var zf = new ZipFile(dummyZip.Filename))
{
var inputBytes = File.ReadAllBytes(inputFile.Filename);

var inputFileName = ZipEntry.CleanName(inputFile.Filename);
var entry = zf.GetEntry(inputFileName);
Assert.IsNotNull(entry, "No entry matching source file \"{0}\" found in archive, found \"{1}\"", inputFileName, zf[0].Name);

Assert.DoesNotThrow(() =>
{
using (var entryStream = zf.GetInputStream(entry))
{
var outputBytes = new byte[entryStream.Length];
entryStream.Read(outputBytes, 0, outputBytes.Length);

Assert.AreEqual(inputBytes, outputBytes, "Archive content does not match the source content");
}
}, "Failed to locate entry stream in archive");

Assert.IsTrue(zf.TestArchive(testData: true), "Archive did not pass TestArchive");
}


}
}

/// <summary>
/// Empty zips can be created and read?
/// </summary>
Expand Down
35 changes: 33 additions & 2 deletions test/ICSharpCode.SharpZipLib.Tests/Zip/ZipFileHandling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,37 @@ public void CreateEmptyArchive()
File.Delete(tempFile);
}

[Test]
[Category("Zip")]
[Category("CreatesTempFile")]
public void CreateArchiveWithNoCompression()
{

using (var sourceFile = Utils.GetDummyFile())
using (var zipFile = Utils.GetDummyFile(0))
{
var inputContent = File.ReadAllText(sourceFile.Filename);
using (ZipFile f = ZipFile.Create(zipFile.Filename))
{
f.BeginUpdate();
f.Add(sourceFile.Filename, CompressionMethod.Stored);
f.CommitUpdate();
Assert.IsTrue(f.TestArchive(true));
f.Close();
}

using (ZipFile f = new ZipFile(zipFile.Filename))
{
Assert.AreEqual(1, f.Count);
using (var sr = new StreamReader(f.GetInputStream(f[0])))
{
var outputContent = sr.ReadToEnd();
Assert.AreEqual(inputContent, outputContent, "extracted content does not match source content");
}
}
}
}

/// <summary>
/// Check that ZipFile finds entries when its got a long comment
/// </summary>
Expand Down Expand Up @@ -1089,8 +1120,8 @@ public void NameFactory()
var names = new string[]
{
"\u030A\u03B0", // Greek
"\u0680\u0685" // Arabic
};
"\u0680\u0685" // Arabic
};

foreach (string name in names)
{
Expand Down