mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 07:25:11 +00:00
added support for 7zip SFX archives by handling ReaderOptions.LookForHeader
This commit is contained in:
@@ -239,4 +239,6 @@ public static class ArchiveFactory
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IArchiveFactory AutoFactory { get; } = new AutoArchiveFactory();
|
||||
}
|
||||
|
||||
27
src/SharpCompress/Archives/AutoArchiveFactory.cs
Normal file
27
src/SharpCompress/Archives/AutoArchiveFactory.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives;
|
||||
|
||||
class AutoArchiveFactory : IArchiveFactory
|
||||
{
|
||||
public string Name => nameof(AutoArchiveFactory);
|
||||
|
||||
public ArchiveType? KnownArchiveType => null;
|
||||
|
||||
public IEnumerable<string> GetSupportedExtensions() => throw new NotSupportedException();
|
||||
|
||||
public bool IsArchive(Stream stream, string? password = null) =>
|
||||
throw new NotSupportedException();
|
||||
|
||||
public FileInfo? GetFilePart(int index, FileInfo part1) => throw new NotSupportedException();
|
||||
|
||||
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
|
||||
ArchiveFactory.Open(stream, readerOptions);
|
||||
|
||||
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
|
||||
ArchiveFactory.Open(fileInfo, readerOptions);
|
||||
}
|
||||
@@ -163,7 +163,7 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
|
||||
{
|
||||
stream.Position = 0;
|
||||
var reader = new ArchiveReader();
|
||||
reader.Open(stream);
|
||||
reader.Open(stream, lookForHeader: ReaderOptions.LookForHeader);
|
||||
_database = reader.ReadDatabase(new PasswordProvider(ReaderOptions.Password));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1220,23 +1220,46 @@ internal class ArchiveReader
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Open(Stream stream)
|
||||
public void Open(Stream stream, bool lookForHeader)
|
||||
{
|
||||
Close();
|
||||
|
||||
_streamOrigin = stream.Position;
|
||||
_streamEnding = stream.Length;
|
||||
|
||||
// TODO: Check Signature!
|
||||
_header = new byte[0x20];
|
||||
for (var offset = 0; offset < 0x20; )
|
||||
var canScan = lookForHeader ? 0x80000 - 20 : 0;
|
||||
while (true)
|
||||
{
|
||||
var delta = stream.Read(_header, offset, 0x20 - offset);
|
||||
if (delta == 0)
|
||||
// TODO: Check Signature!
|
||||
_header = new byte[0x20];
|
||||
for (var offset = 0; offset < 0x20; )
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
var delta = stream.Read(_header, offset, 0x20 - offset);
|
||||
if (delta == 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
offset += delta;
|
||||
}
|
||||
offset += delta;
|
||||
|
||||
if (
|
||||
!lookForHeader
|
||||
|| _header
|
||||
.AsSpan(0, length: 6)
|
||||
.SequenceEqual<byte>([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C])
|
||||
)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (canScan == 0)
|
||||
{
|
||||
throw new InvalidFormatException("Unable to find 7z signature");
|
||||
}
|
||||
|
||||
canScan--;
|
||||
stream.Position = ++_streamOrigin;
|
||||
}
|
||||
|
||||
_stream = stream;
|
||||
|
||||
@@ -73,27 +73,45 @@ public class ArchiveTests : ReaderTests
|
||||
}
|
||||
}
|
||||
|
||||
protected void ArchiveStreamRead(string testArchive, ReaderOptions? readerOptions = null)
|
||||
protected void ArchiveStreamRead(string testArchive, ReaderOptions? readerOptions = null) =>
|
||||
ArchiveStreamRead(ArchiveFactory.AutoFactory, testArchive, readerOptions);
|
||||
|
||||
protected void ArchiveStreamRead(
|
||||
IArchiveFactory archiveFactory,
|
||||
string testArchive,
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
ArchiveStreamRead(readerOptions, testArchive);
|
||||
ArchiveStreamRead(archiveFactory, readerOptions, testArchive);
|
||||
}
|
||||
|
||||
protected void ArchiveStreamRead(
|
||||
ReaderOptions? readerOptions = null,
|
||||
params string[] testArchives
|
||||
) => ArchiveStreamRead(ArchiveFactory.AutoFactory, readerOptions, testArchives);
|
||||
|
||||
protected void ArchiveStreamRead(
|
||||
IArchiveFactory archiveFactory,
|
||||
ReaderOptions? readerOptions = null,
|
||||
params string[] testArchives
|
||||
) =>
|
||||
ArchiveStreamRead(
|
||||
archiveFactory,
|
||||
readerOptions,
|
||||
testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x))
|
||||
);
|
||||
|
||||
protected void ArchiveStreamRead(ReaderOptions? readerOptions, IEnumerable<string> testArchives)
|
||||
protected void ArchiveStreamRead(
|
||||
IArchiveFactory archiveFactory,
|
||||
ReaderOptions? readerOptions,
|
||||
IEnumerable<string> testArchives
|
||||
)
|
||||
{
|
||||
foreach (var path in testArchives)
|
||||
{
|
||||
using (var stream = NonDisposingStream.Create(File.OpenRead(path), true))
|
||||
using (var archive = ArchiveFactory.Open(stream, readerOptions))
|
||||
using (var archive = archiveFactory.Open(stream, readerOptions))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -218,10 +236,14 @@ public class ArchiveTests : ReaderTests
|
||||
}
|
||||
}
|
||||
|
||||
protected void ArchiveFileRead(string testArchive, ReaderOptions? readerOptions = null)
|
||||
protected void ArchiveFileRead(
|
||||
IArchiveFactory archiveFactory,
|
||||
string testArchive,
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
using (var archive = ArchiveFactory.Open(testArchive, readerOptions))
|
||||
using (var archive = archiveFactory.Open(new FileInfo(testArchive), readerOptions))
|
||||
{
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
@@ -234,6 +256,9 @@ public class ArchiveTests : ReaderTests
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
protected void ArchiveFileRead(string testArchive, ReaderOptions? readerOptions = null) =>
|
||||
ArchiveFileRead(ArchiveFactory.AutoFactory, testArchive, readerOptions);
|
||||
|
||||
protected void ArchiveFileSkip(
|
||||
string testArchive,
|
||||
string fileOrder,
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Factories;
|
||||
using SharpCompress.Readers;
|
||||
using Xunit;
|
||||
|
||||
@@ -54,6 +55,14 @@ public class SevenZipArchiveTests : ArchiveTests
|
||||
[Fact]
|
||||
public void SevenZipArchive_LZMA2_PathRead() => ArchiveFileRead("7Zip.LZMA2.7z");
|
||||
|
||||
[Fact]
|
||||
public void SevenZipArchive_LZMA2_EXE_StreamRead() =>
|
||||
ArchiveStreamRead(new SevenZipFactory(), "7Zip.LZMA2.exe", new() { LookForHeader = true });
|
||||
|
||||
[Fact]
|
||||
public void SevenZipArchive_LZMA2_EXE_PathRead() =>
|
||||
ArchiveFileRead(new SevenZipFactory(), "7Zip.LZMA2.exe", new() { LookForHeader = true });
|
||||
|
||||
[Fact]
|
||||
public void SevenZipArchive_LZMA2AES_StreamRead() =>
|
||||
ArchiveStreamRead("7Zip.LZMA2.Aes.7z", new ReaderOptions { Password = "testpassword" });
|
||||
|
||||
BIN
tests/TestArchives/Archives/7Zip.LZMA2.exe
Normal file
BIN
tests/TestArchives/Archives/7Zip.LZMA2.exe
Normal file
Binary file not shown.
Reference in New Issue
Block a user