Skip to content
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
5 changes: 5 additions & 0 deletions src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ public static class ZipConstants
/// </summary>
public const int VersionZip64 = 45;

/// <summary>
/// The version required for BZip2 compression (4.6 or higher)
/// </summary>
public const int VersionBZip2 = 46;

#endregion Versions

#region Header Sizes
Expand Down
8 changes: 7 additions & 1 deletion src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,10 @@ public int Version
{
result = 20;
}
else if (CompressionMethod.BZip2 == method)
{
result = ZipConstants.VersionBZip2;
}
else if (IsDirectory == true)
{
result = 20;
Expand Down Expand Up @@ -616,6 +620,7 @@ public bool CanDecompress
(Version == 11) ||
(Version == 20) ||
(Version == 45) ||
(Version == 46) ||
(Version == 51)) &&
IsCompressionMethodSupported();
}
Expand Down Expand Up @@ -1290,7 +1295,8 @@ public static bool IsCompressionMethodSupported(CompressionMethod method)
{
return
(method == CompressionMethod.Deflated) ||
(method == CompressionMethod.Stored);
(method == CompressionMethod.Stored) ||
(method == CompressionMethod.BZip2);
}

/// <summary>
Expand Down
16 changes: 15 additions & 1 deletion src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,10 @@ public Stream GetInputStream(long entryIndex)
result = new InflaterInputStream(result, new Inflater(true));
break;

case CompressionMethod.BZip2:
result = new BZip2.BZip2InputStream(result);
break;

default:
throw new ZipException("Unsupported compression method " + method);
}
Expand Down Expand Up @@ -1899,7 +1903,7 @@ public void AddDirectory(string directoryName)
/// <param name="compressionMethod">The compression method for the new entry.</param>
private void CheckSupportedCompressionMethod(CompressionMethod compressionMethod)
{
if (compressionMethod != CompressionMethod.Deflated && compressionMethod != CompressionMethod.Stored)
if (compressionMethod != CompressionMethod.Deflated && compressionMethod != CompressionMethod.Stored && compressionMethod != CompressionMethod.BZip2)
{
throw new NotImplementedException("Compression method not supported");
}
Expand Down Expand Up @@ -2629,6 +2633,16 @@ private Stream GetOutputStream(ZipEntry entry)
result = dos;
break;

case CompressionMethod.BZip2:
var bzos = new BZip2.BZip2OutputStream(result)
{
// If there is an encryption stream in use, then we want that to be disposed when the BZip2OutputStream stream is disposed
// If not, then we don't want it to dispose the base stream
IsStreamOwner = entry.IsCrypted
};
result = bzos;
break;

default:
throw new ZipException("Unknown compression method " + entry.CompressionMethod);
}
Expand Down
2 changes: 1 addition & 1 deletion test/ICSharpCode.SharpZipLib.Tests/Zip/GeneralHandling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public void UnsupportedCompressionMethod()
var ze = new ZipEntry("HumblePie");
//ze.CompressionMethod = CompressionMethod.BZip2;

Assert.That(() => ze.CompressionMethod = CompressionMethod.BZip2,
Assert.That(() => ze.CompressionMethod = CompressionMethod.Deflate64,
Throws.TypeOf<NotSupportedException>());
}

Expand Down
144 changes: 144 additions & 0 deletions test/ICSharpCode.SharpZipLib.Tests/Zip/ZipFileHandling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,5 +1611,149 @@ public void AddFileWithAlternateName()
}
}
}

/// <summary>
/// Test a zip file using BZip2 compression.
/// </summary>
[TestCase(true)]
[TestCase(false)]
[Category("Zip")]
public void ZipWithBZip2Compression(bool encryptEntries)
{
string password = "pwd";

using (var memStream = new MemoryStream())
{
using (ZipFile f = new ZipFile(memStream, leaveOpen: true))
{
if (encryptEntries)
f.Password = password;

f.BeginUpdate(new MemoryArchiveStorage());

var m = new StringMemoryDataSource("BZip2Compressed");
f.Add(m, "a.dat", CompressionMethod.BZip2);

var m2 = new StringMemoryDataSource("DeflateCompressed");
f.Add(m2, "b.dat", CompressionMethod.Deflated);
f.CommitUpdate();
Assert.IsTrue(f.TestArchive(true));
}

memStream.Seek(0, SeekOrigin.Begin);

using (ZipFile f = new ZipFile(memStream))
{
if (encryptEntries)
f.Password = password;

{
var entry = f.GetEntry("a.dat");
Assert.That(entry.CompressionMethod, Is.EqualTo(CompressionMethod.BZip2), "Compression method should be BZip2");
Assert.That(entry.Version, Is.EqualTo(ZipConstants.VersionBZip2), "Entry version should be 46");
Assert.That(entry.IsCrypted, Is.EqualTo(encryptEntries));

using (var reader = new StreamReader(f.GetInputStream(entry)))
{
string contents = reader.ReadToEnd();
Assert.That(contents, Is.EqualTo("BZip2Compressed"), "extract string must match original string");
}
}

{
var entry = f.GetEntry("b.dat");
Assert.That(entry.CompressionMethod, Is.EqualTo(CompressionMethod.Deflated), "Compression method should be Deflated");
Assert.That(entry.IsCrypted, Is.EqualTo(encryptEntries));

using (var reader = new StreamReader(f.GetInputStream(entry)))
{
string contents = reader.ReadToEnd();
Assert.That(contents, Is.EqualTo("DeflateCompressed"), "extract string must match original string");
}
}
}

// @@TODO@@ verify the archive with 7-zip?
}
}

/// <summary>
/// We should be able to read a bzip2 compressed zip file created by 7-zip.
/// </summary>
[Test]
[Category("Zip")]
public void ShouldReadBZip2ZipCreatedBy7Zip()
{
const string BZip2CompressedZipCreatedBy7Zip =
"UEsDBC4AAAAMAIa50U4/rHf5qwAAAK8AAAAJAAAASGVsbG8udHh0QlpoOTFBWSZTWTL8pwYAA" +
"BWfgEhlUAAiLUgQP+feMCAAiCKaeiaBobU9JiaAMGmoak9GmRNqPUDQ9T1PQsz/t9B6YvEdvF" +
"5dhwXzGE1ooO41A6TtATBEFxFUq6trGtUcSJDyWWWj/S2VwY15fy3IqHi3hHUS+K76zdoDzQa" +
"VGE/4YkYZe3JAtv1EsIqIsiTnnktIbBo1R4xY3JZEOm2BvwLuSKcKEgZflODAUEsBAj8ALgAA" +
"AAwAhrnRTj+sd/mrAAAArwAAAAkAJAAAAAAAAAAgAAAAAAAAAEhlbGxvLnR4dAoAIAAAAAAAA" +
"QAYAO97MLZZJdUB73swtlkl1QEK0UTFWCXVAVBLBQYAAAAAAQABAFsAAADSAAAAAAA=";

const string OriginalText =
"SharpZipLib (#ziplib, formerly NZipLib) is a compression library that supports Zip files using both stored and deflate compression methods, PKZIP 2.0 style and AES encryption.";

var fileBytes = System.Convert.FromBase64String(BZip2CompressedZipCreatedBy7Zip);

using (var input = new MemoryStream(fileBytes, false))
{
using (ZipFile f = new ZipFile(input))
{
var entry = f.GetEntry("Hello.txt");
Assert.That(entry.CompressionMethod, Is.EqualTo(CompressionMethod.BZip2), "Compression method should be BZip2");
Assert.That(entry.Version, Is.EqualTo(ZipConstants.VersionBZip2), "Entry version should be 46");

using (var reader = new StreamReader(f.GetInputStream(entry)))
{
string contents = reader.ReadToEnd();
Assert.That(contents, Is.EqualTo(OriginalText), "extract string must match original string");
}
}
}
}

/// <summary>
/// We should be able to read a bzip2 compressed / AES encrypted zip file created by 7-zip.
/// </summary>
[Test]
[Category("Zip")]
public void ShouldReadAESBZip2ZipCreatedBy7Zip()
{
const string BZip2CompressedZipCreatedBy7Zip =
"UEsDBDMAAQBjAIa50U4AAAAAxwAAAK8AAAAJAAsASGVsbG8udHh0AZkHAAIAQUUDDAAYg6jqf" +
"kvZClVMOtgmqKT0/8I9fMPgo96myxw9hLQUhKj1Qczi3fT7QIhAnAKU+u03nA8rCKGWmDI5Qz" +
"qPREy95boQVDPwmwEsWksv3GAWzMfzZUhmB/TgIJlA34a4yP0f2ucy3/QCQYo8QcHjBtjWX5b" +
"dZn0+fwY9Ci7q8JSI8zNSbgQ0Ert/lIJ9MxQ4lzBxMl4LySkd104cDPh/FslTAcPtHoy8Mf1c" +
"vnI1uICMgjWVeTqYrvSvt2uuHnqr4AiehArFiXTnUEsBAj8AMwABAGMAhrnRTgAAAADHAAAAr" +
"wAAAAkALwAAAAAAAAAgAAAAAAAAAEhlbGxvLnR4dAoAIAAAAAAAAQAYAO97MLZZJdUBYdnjul" +
"kl1QEK0UTFWCXVAQGZBwACAEFFAwwAUEsFBgAAAAABAAEAZgAAAPkAAAAAAA==";

const string OriginalText =
"SharpZipLib (#ziplib, formerly NZipLib) is a compression library that supports Zip files using both stored and deflate compression methods, PKZIP 2.0 style and AES encryption.";

var fileBytes = System.Convert.FromBase64String(BZip2CompressedZipCreatedBy7Zip);

using (var input = new MemoryStream(fileBytes, false))
{
using (ZipFile f = new ZipFile(input))
{
f.Password = "password";

var entry = f.GetEntry("Hello.txt");
Assert.That(entry.CompressionMethod, Is.EqualTo(CompressionMethod.BZip2), "Compression method should be BZip2");
Assert.That(entry.Version, Is.EqualTo(ZipConstants.VERSION_AES), "Entry version should be 51");
Assert.That(entry.IsCrypted, Is.True, "Entry should be encrypted");
Assert.That(entry.AESKeySize, Is.EqualTo(256), "AES Keysize should be 256");

using (var reader = new StreamReader(f.GetInputStream(entry)))
{
string contents = reader.ReadToEnd();
Assert.That(contents, Is.EqualTo(OriginalText), "extract string must match original string");
}
}
}
}
}
}