diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs
index cc2fd27d2..b0f33a764 100644
--- a/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs
+++ b/src/ICSharpCode.SharpZipLib/Zip/ZipConstants.cs
@@ -281,6 +281,11 @@ public static class ZipConstants
///
public const int VersionZip64 = 45;
+ ///
+ /// The version required for BZip2 compression (4.6 or higher)
+ ///
+ public const int VersionBZip2 = 46;
+
#endregion Versions
#region Header Sizes
diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs
index d6e4b98fa..3baf8415d 100644
--- a/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs
+++ b/src/ICSharpCode.SharpZipLib/Zip/ZipEntry.cs
@@ -585,6 +585,10 @@ public int Version
{
result = 20;
}
+ else if (CompressionMethod.BZip2 == method)
+ {
+ result = ZipConstants.VersionBZip2;
+ }
else if (IsDirectory == true)
{
result = 20;
@@ -616,6 +620,7 @@ public bool CanDecompress
(Version == 11) ||
(Version == 20) ||
(Version == 45) ||
+ (Version == 46) ||
(Version == 51)) &&
IsCompressionMethodSupported();
}
@@ -1290,7 +1295,8 @@ public static bool IsCompressionMethodSupported(CompressionMethod method)
{
return
(method == CompressionMethod.Deflated) ||
- (method == CompressionMethod.Stored);
+ (method == CompressionMethod.Stored) ||
+ (method == CompressionMethod.BZip2);
}
///
diff --git a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
index c5c05afad..e7fb41978 100644
--- a/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
+++ b/src/ICSharpCode.SharpZipLib/Zip/ZipFile.cs
@@ -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);
}
@@ -1899,7 +1903,7 @@ public void AddDirectory(string directoryName)
/// The compression method for the new entry.
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");
}
@@ -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);
}
diff --git a/test/ICSharpCode.SharpZipLib.Tests/Zip/GeneralHandling.cs b/test/ICSharpCode.SharpZipLib.Tests/Zip/GeneralHandling.cs
index b0d22c9bc..b74ed1ddc 100644
--- a/test/ICSharpCode.SharpZipLib.Tests/Zip/GeneralHandling.cs
+++ b/test/ICSharpCode.SharpZipLib.Tests/Zip/GeneralHandling.cs
@@ -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());
}
diff --git a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipFileHandling.cs b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipFileHandling.cs
index 996b09213..16dad656d 100644
--- a/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipFileHandling.cs
+++ b/test/ICSharpCode.SharpZipLib.Tests/Zip/ZipFileHandling.cs
@@ -1611,5 +1611,149 @@ public void AddFileWithAlternateName()
}
}
}
+
+ ///
+ /// Test a zip file using BZip2 compression.
+ ///
+ [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?
+ }
+ }
+
+ ///
+ /// We should be able to read a bzip2 compressed zip file created by 7-zip.
+ ///
+ [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");
+ }
+ }
+ }
+ }
+
+ ///
+ /// We should be able to read a bzip2 compressed / AES encrypted zip file created by 7-zip.
+ ///
+ [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");
+ }
+ }
+ }
+ }
}
}