Skip to content

Commit

Permalink
added support for 7zip SFX archives by handling ReaderOptions.LookFor…
Browse files Browse the repository at this point in the history
…Header
  • Loading branch information
lostmsu committed Aug 3, 2024
1 parent 06a983e commit 9a9bcd8
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/SharpCompress/Archives/ArchiveFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,4 +239,6 @@ public static IEnumerable<FileInfo> GetFileParts(FileInfo part1)
}
}
}

public static IArchiveFactory AutoFactory { get; } = new AutoArchiveFactory();
}
29 changes: 29 additions & 0 deletions src/SharpCompress/Archives/AutoArchiveFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
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);
}
2 changes: 1 addition & 1 deletion src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private void LoadFactory(Stream stream)
{
stream.Position = 0;
var reader = new ArchiveReader();
reader.Open(stream);
reader.Open(stream, lookForHeader: ReaderOptions.LookForHeader);
_database = reader.ReadDatabase(new PasswordProvider(ReaderOptions.Password));
}
}
Expand Down
34 changes: 26 additions & 8 deletions src/SharpCompress/Common/SevenZip/ArchiveReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,23 +1220,41 @@ out digests

#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;
}

if (!lookForHeader || _header.AsSpan(0, length: 6).SequenceEqual<byte>([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]))
{
break;
}
offset += delta;

if (canScan == 0)
{
throw new InvalidFormatException("Unable to find 7z signature");
}

canScan--;
stream.Position = ++_streamOrigin;
}

_stream = stream;
Expand Down
25 changes: 19 additions & 6 deletions tests/SharpCompress.Test/ArchiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,37 @@ CompressionType compression
}
}

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
{
Expand Down Expand Up @@ -218,10 +228,10 @@ IEnumerable<string> testArchives
}
}

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))
{
Expand All @@ -234,6 +244,9 @@ protected void ArchiveFileRead(string testArchive, ReaderOptions? readerOptions
VerifyFiles();
}

protected void ArchiveFileRead(string testArchive, ReaderOptions? readerOptions = null) =>
ArchiveFileRead(ArchiveFactory.AutoFactory, testArchive, readerOptions);

protected void ArchiveFileSkip(
string testArchive,
string fileOrder,
Expand Down
9 changes: 9 additions & 0 deletions tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
using SharpCompress.Factories;
using SharpCompress.Readers;
using Xunit;

Expand Down Expand Up @@ -54,6 +55,14 @@ public void SevenZipArchive_PPMd_StreamRead_Extract_All() =>
[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" });
Expand Down
Binary file added tests/TestArchives/Archives/7Zip.LZMA2.exe
Binary file not shown.

0 comments on commit 9a9bcd8

Please sign in to comment.