2022-07-28 20:36:28 +02:00
|
|
|
using System;
|
2025-11-29 14:06:03 +00:00
|
|
|
using System.Collections.Generic;
|
2015-12-30 11:19:42 +00:00
|
|
|
using System.IO;
|
2025-11-29 14:06:03 +00:00
|
|
|
using System.Linq;
|
2024-03-14 08:37:17 +00:00
|
|
|
using SharpCompress.Archives;
|
2015-12-30 11:19:42 +00:00
|
|
|
using SharpCompress.Common;
|
2018-05-08 14:10:49 +01:00
|
|
|
using SharpCompress.IO;
|
2016-09-26 11:49:49 +01:00
|
|
|
using SharpCompress.Readers;
|
|
|
|
|
using SharpCompress.Readers.Zip;
|
2018-07-10 10:15:21 -07:00
|
|
|
using SharpCompress.Test.Mocks;
|
2016-09-26 11:49:49 +01:00
|
|
|
using SharpCompress.Writers;
|
2015-12-30 11:19:42 +00:00
|
|
|
using Xunit;
|
|
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
namespace SharpCompress.Test.Zip;
|
|
|
|
|
|
|
|
|
|
public class ZipReaderTests : ReaderTests
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:20:49 +00:00
|
|
|
public ZipReaderTests() => UseExtensionInsteadOfNameToVerify = true;
|
2017-12-08 12:00:29 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Issue_269_Double_Skip()
|
|
|
|
|
{
|
|
|
|
|
var path = Path.Combine(TEST_ARCHIVES_PATH, "PrePostHeaders.zip");
|
|
|
|
|
using Stream stream = new ForwardOnlyStream(File.OpenRead(path));
|
|
|
|
|
using var reader = ReaderFactory.Open(stream);
|
|
|
|
|
var count = 0;
|
|
|
|
|
while (reader.MoveToNextEntry())
|
2017-07-17 11:05:21 -04:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
count++;
|
|
|
|
|
if (!reader.Entry.IsDirectory)
|
2017-07-17 11:05:21 -04:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
if (count % 2 != 0)
|
2017-07-17 11:05:21 -04:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
reader.WriteEntryTo(Stream.Null);
|
2017-07-17 11:05:21 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
}
|
2017-01-25 17:05:48 +10:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_Zip64_Streamed_Read() => Read("Zip.zip64.zip", CompressionType.Deflate);
|
2017-01-25 17:05:48 +10:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_ZipX_Streamed_Read() => Read("Zip.zipx", CompressionType.LZMA);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_BZip2_Streamed_Read() => Read("Zip.bzip2.dd.zip", CompressionType.BZip2);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_BZip2_Read() => Read("Zip.bzip2.zip", CompressionType.BZip2);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_Deflate_Streamed2_Read() =>
|
2022-12-20 15:06:44 +00:00
|
|
|
Read("Zip.deflate.dd-.zip", CompressionType.Deflate);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_Deflate_Streamed_Read() => Read("Zip.deflate.dd.zip", CompressionType.Deflate);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_Deflate_Streamed_Skip()
|
|
|
|
|
{
|
|
|
|
|
using Stream stream = new ForwardOnlyStream(
|
2022-12-20 15:14:22 +00:00
|
|
|
File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip"))
|
|
|
|
|
);
|
2022-12-20 15:06:44 +00:00
|
|
|
using var reader = ReaderFactory.Open(stream);
|
|
|
|
|
var x = 0;
|
|
|
|
|
while (reader.MoveToNextEntry())
|
2017-06-01 09:15:56 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
if (!reader.Entry.IsDirectory)
|
2017-06-01 09:15:56 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
x++;
|
|
|
|
|
if (x % 2 == 0)
|
2017-06-01 09:15:56 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
reader.WriteEntryToDirectory(
|
|
|
|
|
SCRATCH_FILES_PATH,
|
2024-03-14 08:37:17 +00:00
|
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
2022-12-20 15:06:44 +00:00
|
|
|
);
|
2017-06-01 09:15:56 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
}
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_Deflate_Read() => Read("Zip.deflate.zip", CompressionType.Deflate);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_Deflate64_Read() => Read("Zip.deflate64.zip", CompressionType.Deflate64);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_LZMA_Streamed_Read() => Read("Zip.lzma.dd.zip", CompressionType.LZMA);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_LZMA_Read() => Read("Zip.lzma.zip", CompressionType.LZMA);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_PPMd_Streamed_Read() => Read("Zip.ppmd.dd.zip", CompressionType.PPMd);
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_PPMd_Read() => Read("Zip.ppmd.zip", CompressionType.PPMd);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_None_Read() => Read("Zip.none.zip", CompressionType.None);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_Deflate_NoEmptyDirs_Read() =>
|
2022-12-20 15:06:44 +00:00
|
|
|
Read("Zip.deflate.noEmptyDirs.zip", CompressionType.Deflate);
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_BZip2_PkwareEncryption_Read()
|
|
|
|
|
{
|
|
|
|
|
using (
|
2022-12-20 15:14:22 +00:00
|
|
|
Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.bzip2.pkware.zip"))
|
2022-12-20 15:06:44 +00:00
|
|
|
)
|
2024-03-14 08:37:17 +00:00
|
|
|
using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" }))
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
while (reader.MoveToNextEntry())
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
if (!reader.Entry.IsDirectory)
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType);
|
|
|
|
|
reader.WriteEntryToDirectory(
|
|
|
|
|
SCRATCH_FILES_PATH,
|
2024-03-14 08:37:17 +00:00
|
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
2022-12-20 15:06:44 +00:00
|
|
|
);
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
VerifyFiles();
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_Reader_Disposal_Test()
|
|
|
|
|
{
|
|
|
|
|
using var stream = new TestStream(
|
2022-12-20 15:14:22 +00:00
|
|
|
File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip"))
|
|
|
|
|
);
|
2022-12-20 15:06:44 +00:00
|
|
|
using (var reader = ReaderFactory.Open(stream))
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
while (reader.MoveToNextEntry())
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
if (!reader.Entry.IsDirectory)
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
reader.WriteEntryToDirectory(
|
|
|
|
|
SCRATCH_FILES_PATH,
|
2024-03-14 08:37:17 +00:00
|
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
2022-12-20 15:06:44 +00:00
|
|
|
);
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.True(stream.IsDisposed);
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_Reader_Disposal_Test2()
|
|
|
|
|
{
|
|
|
|
|
using var stream = new TestStream(
|
2022-12-20 15:14:22 +00:00
|
|
|
File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip"))
|
|
|
|
|
);
|
2022-12-20 15:06:44 +00:00
|
|
|
var reader = ReaderFactory.Open(stream);
|
|
|
|
|
while (reader.MoveToNextEntry())
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
if (!reader.Entry.IsDirectory)
|
2022-12-20 13:45:47 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
reader.WriteEntryToDirectory(
|
|
|
|
|
SCRATCH_FILES_PATH,
|
2024-03-14 08:37:17 +00:00
|
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
2022-12-20 15:06:44 +00:00
|
|
|
);
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.False(stream.IsDisposed);
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2022-12-20 15:20:49 +00:00
|
|
|
public void Zip_LZMA_WinzipAES_Read() =>
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Throws<NotSupportedException>(() =>
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 13:45:47 +00:00
|
|
|
using (
|
|
|
|
|
Stream stream = File.OpenRead(
|
2022-12-20 15:06:44 +00:00
|
|
|
Path.Combine(TEST_ARCHIVES_PATH, "Zip.lzma.WinzipAES.zip")
|
2022-12-20 13:45:47 +00:00
|
|
|
)
|
|
|
|
|
)
|
2024-03-14 08:37:17 +00:00
|
|
|
using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" }))
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
if (!reader.Entry.IsDirectory)
|
|
|
|
|
{
|
2017-05-19 10:10:23 +01:00
|
|
|
Assert.Equal(CompressionType.Unknown, reader.Entry.CompressionType);
|
2022-12-20 13:45:47 +00:00
|
|
|
reader.WriteEntryToDirectory(
|
|
|
|
|
SCRATCH_FILES_PATH,
|
2024-03-14 08:37:17 +00:00
|
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
2022-12-20 13:45:47 +00:00
|
|
|
);
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
VerifyFiles();
|
2022-12-20 15:06:44 +00:00
|
|
|
});
|
2021-10-02 15:29:03 +01:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_Deflate_WinzipAES_Read()
|
|
|
|
|
{
|
|
|
|
|
using (
|
|
|
|
|
Stream stream = File.OpenRead(
|
|
|
|
|
Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES.zip")
|
|
|
|
|
)
|
|
|
|
|
)
|
2024-03-14 08:37:17 +00:00
|
|
|
using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" }))
|
2021-04-25 09:25:51 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
while (reader.MoveToNextEntry())
|
2021-04-25 09:25:51 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
if (!reader.Entry.IsDirectory)
|
2021-04-25 09:25:51 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Equal(CompressionType.Unknown, reader.Entry.CompressionType);
|
|
|
|
|
reader.WriteEntryToDirectory(
|
|
|
|
|
SCRATCH_FILES_PATH,
|
2024-03-14 08:37:17 +00:00
|
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
2022-12-20 15:06:44 +00:00
|
|
|
);
|
2021-04-25 09:25:51 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
VerifyFiles();
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_Deflate_ZipCrypto_Read()
|
|
|
|
|
{
|
|
|
|
|
var count = 0;
|
|
|
|
|
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "zipcrypto.zip")))
|
2024-03-14 08:37:17 +00:00
|
|
|
using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" }))
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
while (reader.MoveToNextEntry())
|
2018-07-11 18:52:33 -07:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
if (!reader.Entry.IsDirectory)
|
2015-12-30 11:19:42 +00:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Equal(CompressionType.None, reader.Entry.CompressionType);
|
|
|
|
|
reader.WriteEntryToDirectory(
|
|
|
|
|
SCRATCH_FILES_PATH,
|
2024-03-14 08:37:17 +00:00
|
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
2022-12-20 15:06:44 +00:00
|
|
|
);
|
|
|
|
|
count++;
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Equal(8, count);
|
|
|
|
|
}
|
2020-01-16 22:08:48 +01:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void TestSharpCompressWithEmptyStream()
|
|
|
|
|
{
|
2022-12-20 15:20:49 +00:00
|
|
|
var expected = new[]
|
2020-01-16 22:08:48 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
new Tuple<string, byte[]>("foo.txt", Array.Empty<byte>()),
|
2025-01-14 09:07:40 +00:00
|
|
|
new Tuple<string, byte[]>("foo2.txt", new byte[10]),
|
2022-12-20 15:06:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using var memory = new MemoryStream();
|
|
|
|
|
Stream stream = new TestStream(memory, read: true, write: true, seek: false);
|
|
|
|
|
|
2022-12-20 15:14:22 +00:00
|
|
|
using (var zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
|
2022-12-20 15:06:44 +00:00
|
|
|
{
|
|
|
|
|
zipWriter.Write(expected[0].Item1, new MemoryStream(expected[0].Item2));
|
|
|
|
|
zipWriter.Write(expected[1].Item1, new MemoryStream(expected[1].Item2));
|
|
|
|
|
}
|
2020-01-16 22:08:48 +01:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
stream = new MemoryStream(memory.ToArray());
|
|
|
|
|
File.WriteAllBytes(Path.Combine(SCRATCH_FILES_PATH, "foo.zip"), memory.ToArray());
|
2020-01-16 22:08:48 +01:00
|
|
|
|
2025-07-20 18:11:37 +01:00
|
|
|
using IReader zipReader = ZipReader.Open(
|
|
|
|
|
SharpCompressStream.Create(stream, leaveOpen: true, throwOnDispose: true)
|
|
|
|
|
);
|
2022-12-20 15:06:44 +00:00
|
|
|
var i = 0;
|
|
|
|
|
while (zipReader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
using (var entry = zipReader.OpenEntryStream())
|
|
|
|
|
{
|
|
|
|
|
var tempStream = new MemoryStream();
|
|
|
|
|
const int bufSize = 0x1000;
|
|
|
|
|
var buf = new byte[bufSize];
|
|
|
|
|
var bytesRead = 0;
|
|
|
|
|
while ((bytesRead = entry.Read(buf, 0, bufSize)) > 0)
|
|
|
|
|
{
|
|
|
|
|
tempStream.Write(buf, 0, bytesRead);
|
2020-01-16 22:08:48 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Equal(expected[i].Item1, zipReader.Entry.Key);
|
|
|
|
|
Assert.Equal(expected[i].Item2, tempStream.ToArray());
|
2020-01-16 22:08:48 +01:00
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
i++;
|
2020-01-16 22:08:48 +01:00
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
}
|
2020-01-16 22:08:48 +01:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_None_Issue86_Streamed_Read()
|
|
|
|
|
{
|
2022-12-20 15:20:49 +00:00
|
|
|
var keys = new[] { "Empty1", "Empty2", "Dir1/", "Dir2/", "Fake1", "Fake2", "Internal.zip" };
|
2022-12-20 15:06:44 +00:00
|
|
|
|
|
|
|
|
using Stream stream = File.OpenRead(
|
2022-12-20 15:14:22 +00:00
|
|
|
Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.issue86.zip")
|
|
|
|
|
);
|
2022-12-20 15:06:44 +00:00
|
|
|
using var reader = ZipReader.Open(stream);
|
|
|
|
|
foreach (var key in keys)
|
2022-07-28 20:36:28 +02:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
reader.MoveToNextEntry();
|
2022-07-28 20:36:28 +02:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Equal(reader.Entry.Key, key);
|
2022-07-28 20:36:28 +02:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
if (!reader.Entry.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
Assert.Equal(CompressionType.None, reader.Entry.CompressionType);
|
2022-07-28 20:36:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-20 13:45:47 +00:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.False(reader.MoveToNextEntry());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Zip_ReaderMoveToNextEntry()
|
|
|
|
|
{
|
2022-12-20 15:20:49 +00:00
|
|
|
var keys = new[] { "version", "sizehint", "data/0/metadata", "data/0/records" };
|
2022-12-20 15:06:44 +00:00
|
|
|
|
|
|
|
|
using var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "test_477.zip"));
|
|
|
|
|
using var reader = ZipReader.Open(fileStream);
|
|
|
|
|
foreach (var key in keys)
|
2022-07-29 09:47:35 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
reader.MoveToNextEntry();
|
|
|
|
|
|
|
|
|
|
Assert.Equal(reader.Entry.Key, key);
|
2022-07-29 09:47:35 +01:00
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
}
|
2022-07-29 09:47:35 +01:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Issue_685()
|
|
|
|
|
{
|
|
|
|
|
var count = 0;
|
|
|
|
|
using var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Issue_685.zip"));
|
|
|
|
|
using var reader = ZipReader.Open(fileStream);
|
|
|
|
|
while (reader.MoveToNextEntry())
|
2022-07-29 09:47:35 +01:00
|
|
|
{
|
2022-12-20 15:06:44 +00:00
|
|
|
count++;
|
|
|
|
|
reader.OpenEntryStream().Dispose(); // Uncomment for workaround
|
2022-07-29 09:47:35 +01:00
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
Assert.Equal(4, count);
|
|
|
|
|
}
|
2022-08-04 21:22:31 +02:00
|
|
|
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
2023-02-19 01:33:22 +01:00
|
|
|
public void Zip_ReaderFactory_Uncompressed_Read_All()
|
|
|
|
|
{
|
|
|
|
|
var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip");
|
2025-02-11 03:31:49 +01:00
|
|
|
using var stream = File.OpenRead(zipPath);
|
2023-02-19 01:33:22 +01:00
|
|
|
using var reader = ReaderFactory.Open(stream);
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
var target = new MemoryStream();
|
|
|
|
|
reader.OpenEntryStream().CopyTo(target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Zip_ReaderFactory_Uncompressed_Skip_All()
|
2022-12-20 15:06:44 +00:00
|
|
|
{
|
|
|
|
|
var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip");
|
2025-02-11 03:31:49 +01:00
|
|
|
using var stream = File.OpenRead(zipPath);
|
2022-12-20 15:06:44 +00:00
|
|
|
using var reader = ReaderFactory.Open(stream);
|
2022-12-20 15:14:22 +00:00
|
|
|
while (reader.MoveToNextEntry()) { }
|
2022-12-20 15:06:44 +00:00
|
|
|
}
|
2022-08-04 21:22:31 +02:00
|
|
|
|
2025-10-21 10:28:58 +01:00
|
|
|
//this test uses a large 7zip file containing a zip file inside it to test zip64 support
|
|
|
|
|
// we probably shouldn't be allowing ExtractAllEntries here but it works for now.
|
2022-12-20 15:06:44 +00:00
|
|
|
[Fact]
|
|
|
|
|
public void Zip_Uncompressed_64bit()
|
|
|
|
|
{
|
|
|
|
|
var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "64bitstream.zip.7z");
|
2025-02-11 03:31:49 +01:00
|
|
|
using var stream = File.OpenRead(zipPath);
|
2024-03-14 08:37:17 +00:00
|
|
|
var archive = ArchiveFactory.Open(stream);
|
2022-12-20 15:06:44 +00:00
|
|
|
var reader = archive.ExtractAllEntries();
|
|
|
|
|
reader.MoveToNextEntry();
|
|
|
|
|
var zipReader = ZipReader.Open(reader.OpenEntryStream());
|
|
|
|
|
var x = 0;
|
|
|
|
|
while (zipReader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
x++;
|
2022-08-04 21:22:31 +02:00
|
|
|
}
|
2022-12-20 15:06:44 +00:00
|
|
|
|
|
|
|
|
Assert.Equal(4, x);
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|
2025-08-21 19:51:09 +02:00
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Zip_Uncompressed_Encrypted_Read()
|
|
|
|
|
{
|
2025-10-21 09:56:29 +01:00
|
|
|
using var reader = ReaderFactory.Open(
|
2025-08-21 19:51:09 +02:00
|
|
|
Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.encrypted.zip"),
|
|
|
|
|
new ReaderOptions { Password = "test" }
|
|
|
|
|
);
|
|
|
|
|
reader.MoveToNextEntry();
|
|
|
|
|
Assert.Equal("first.txt", reader.Entry.Key);
|
|
|
|
|
Assert.Equal(199, reader.Entry.Size);
|
|
|
|
|
reader.OpenEntryStream().Dispose();
|
|
|
|
|
reader.MoveToNextEntry();
|
|
|
|
|
Assert.Equal("second.txt", reader.Entry.Key);
|
|
|
|
|
Assert.Equal(197, reader.Entry.Size);
|
|
|
|
|
}
|
2025-11-29 14:06:03 +00:00
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void ZipReader_Returns_Same_Entries_As_ZipArchive()
|
|
|
|
|
{
|
|
|
|
|
// Verifies that ZipReader and ZipArchive return the same entries
|
2025-11-29 15:36:46 +00:00
|
|
|
// for standard single-volume ZIP files. ZipReader processes LocalEntry
|
|
|
|
|
// headers sequentially, while ZipArchive uses DirectoryEntry headers
|
|
|
|
|
// from the central directory and seeks to LocalEntry headers for data.
|
2025-11-29 14:06:03 +00:00
|
|
|
var testFiles = new[] { "Zip.none.zip", "Zip.deflate.zip", "Zip.none.issue86.zip" };
|
|
|
|
|
|
|
|
|
|
foreach (var testFile in testFiles)
|
|
|
|
|
{
|
|
|
|
|
var path = Path.Combine(TEST_ARCHIVES_PATH, testFile);
|
|
|
|
|
|
|
|
|
|
var readerKeys = new List<string>();
|
|
|
|
|
using (var stream = File.OpenRead(path))
|
|
|
|
|
using (var reader = ZipReader.Open(stream))
|
|
|
|
|
{
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
readerKeys.Add(reader.Entry.Key!);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var archiveKeys = new List<string>();
|
|
|
|
|
using (var archive = Archives.Zip.ZipArchive.Open(path))
|
|
|
|
|
{
|
|
|
|
|
foreach (var entry in archive.Entries)
|
|
|
|
|
{
|
|
|
|
|
archiveKeys.Add(entry.Key!);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Assert.Equal(archiveKeys.Count, readerKeys.Count);
|
|
|
|
|
Assert.Equal(archiveKeys.OrderBy(k => k), readerKeys.OrderBy(k => k));
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-22 15:23:13 +00:00
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void EntryStream_Dispose_DoesNotThrow_OnNonSeekableStream_Deflate()
|
|
|
|
|
{
|
|
|
|
|
// Since version 0.41.0: EntryStream.Dispose() should not throw NotSupportedException
|
|
|
|
|
// when Flush() fails on non-seekable streams (Deflate compression)
|
|
|
|
|
var path = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip");
|
|
|
|
|
using Stream stream = new ForwardOnlyStream(File.OpenRead(path));
|
2026-01-23 09:04:55 +00:00
|
|
|
using var reader = ReaderFactory.Open(stream);
|
2026-01-22 15:23:13 +00:00
|
|
|
|
|
|
|
|
// This should not throw, even if internal Flush() fails
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
if (!reader.Entry.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
using var entryStream = reader.OpenEntryStream();
|
|
|
|
|
// Read some data
|
|
|
|
|
var buffer = new byte[1024];
|
|
|
|
|
entryStream.Read(buffer, 0, buffer.Length);
|
|
|
|
|
// Dispose should not throw NotSupportedException
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void EntryStream_Dispose_DoesNotThrow_OnNonSeekableStream_LZMA()
|
|
|
|
|
{
|
|
|
|
|
// Since version 0.41.0: EntryStream.Dispose() should not throw NotSupportedException
|
|
|
|
|
// when Flush() fails on non-seekable streams (LZMA compression)
|
|
|
|
|
var path = Path.Combine(TEST_ARCHIVES_PATH, "Zip.lzma.dd.zip");
|
|
|
|
|
using Stream stream = new ForwardOnlyStream(File.OpenRead(path));
|
2026-01-23 09:04:55 +00:00
|
|
|
using var reader = ReaderFactory.Open(stream);
|
2026-01-22 15:23:13 +00:00
|
|
|
|
|
|
|
|
// This should not throw, even if internal Flush() fails
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
if (!reader.Entry.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
using var entryStream = reader.OpenEntryStream();
|
|
|
|
|
// Read some data
|
|
|
|
|
var buffer = new byte[1024];
|
|
|
|
|
entryStream.Read(buffer, 0, buffer.Length);
|
|
|
|
|
// Dispose should not throw NotSupportedException
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-24 10:11:16 +00:00
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Archive_Iteration_DoesNotBreak_WhenFlushThrows_Deflate()
|
|
|
|
|
{
|
|
|
|
|
// Regression test: since 0.41.0, archive iteration would silently break
|
|
|
|
|
// when the input stream throws NotSupportedException in Flush().
|
|
|
|
|
// Only the first entry would be returned, then iteration would stop without exception.
|
|
|
|
|
var path = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.dd.zip");
|
|
|
|
|
using var fileStream = File.OpenRead(path);
|
|
|
|
|
using Stream stream = new ThrowOnFlushStream(fileStream);
|
2026-01-24 10:23:02 +00:00
|
|
|
using var reader = ReaderFactory.Open(stream);
|
2026-01-24 10:11:16 +00:00
|
|
|
|
|
|
|
|
var count = 0;
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
if (!reader.Entry.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Should iterate through all entries, not just the first one
|
|
|
|
|
Assert.True(count > 1, $"Expected more than 1 entry, but got {count}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Archive_Iteration_DoesNotBreak_WhenFlushThrows_LZMA()
|
|
|
|
|
{
|
|
|
|
|
// Regression test: since 0.41.0, archive iteration would silently break
|
|
|
|
|
// when the input stream throws NotSupportedException in Flush().
|
|
|
|
|
// Only the first entry would be returned, then iteration would stop without exception.
|
|
|
|
|
var path = Path.Combine(TEST_ARCHIVES_PATH, "Zip.lzma.dd.zip");
|
|
|
|
|
using var fileStream = File.OpenRead(path);
|
|
|
|
|
using Stream stream = new ThrowOnFlushStream(fileStream);
|
2026-01-24 10:23:02 +00:00
|
|
|
using var reader = ReaderFactory.Open(stream);
|
2026-01-24 10:11:16 +00:00
|
|
|
|
|
|
|
|
var count = 0;
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
if (!reader.Entry.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Should iterate through all entries, not just the first one
|
|
|
|
|
Assert.True(count > 1, $"Expected more than 1 entry, but got {count}");
|
|
|
|
|
}
|
2015-12-30 11:19:42 +00:00
|
|
|
}
|