Merge pull request #916 from Morilli/rar-multipart-reader

Implement multipart rar handling for ExtractAllEntries
This commit is contained in:
Adam Hathcock
2025-05-14 11:33:12 +01:00
committed by GitHub
3 changed files with 45 additions and 36 deletions

View File

@@ -67,6 +67,16 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
protected override IReader CreateReaderForSolidExtraction()
{
if (this.IsMultipartVolume())
{
var streams = Volumes.Select(volume =>
{
volume.Stream.Position = 0;
return volume.Stream;
});
return RarReader.Open(streams, ReaderOptions);
}
var stream = Volumes.First().Stream;
stream.Position = 0;
return RarReader.Open(stream, ReaderOptions);

View File

@@ -131,7 +131,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti
{
var part = Entry.Parts.First();
if (!Entry.IsSolid && Entry.CompressedSize > 0)
if (!Entry.IsSplitAfter && !Entry.IsSolid && Entry.CompressedSize > 0)
{
//not solid and has a known compressed size then we can skip raw bytes.
var rawStream = part.GetRawStream();

View File

@@ -1,6 +1,8 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Readers.Rar;
@@ -328,43 +330,15 @@ public class RarReaderTests : ReaderTests
}
[Fact]
public void Rar_NullReference()
public void Rar_SkipEncryptedFilesWithoutPassword()
{
using var stream = File.OpenRead(
Path.Combine(TEST_ARCHIVES_PATH, "Rar.encrypted_filesOnly.rar")
);
using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true });
while (reader.MoveToNextEntry())
{
var archives = new[]
{
"Rar.EncryptedParts.part01.rar",
"Rar.EncryptedParts.part02.rar",
"Rar.EncryptedParts.part03.rar",
"Rar.EncryptedParts.part04.rar",
"Rar.EncryptedParts.part05.rar",
"Rar.EncryptedParts.part06.rar",
};
using var reader = RarReader.Open(
archives
.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s))
.Select(p => File.OpenRead(p)),
new ReaderOptions { Password = "test" }
);
while (reader.MoveToNextEntry())
{
//
}
}
{
using var stream = File.OpenRead(
Path.Combine(TEST_ARCHIVES_PATH, "Rar.encrypted_filesOnly.rar")
);
using var reader = ReaderFactory.Open(
stream,
new ReaderOptions { LookForHeader = true }
);
while (reader.MoveToNextEntry())
{
//
}
//
}
}
@@ -418,4 +392,29 @@ public class RarReaderTests : ReaderTests
CompressionType.Rar
)
);
[Fact]
public void Rar_Iterate_Multipart()
{
var expectedOrder = new Stack(
new[]
{
"Failure",
"jpg",
"exe",
"Empty",
"тест.txt",
Path.Combine("jpg", "test.jpg"),
Path.Combine("exe", "test.exe"),
}
);
using var archive = RarArchive.Open(
Path.Combine(TEST_ARCHIVES_PATH, "Rar.multi.part01.rar")
);
using var reader = archive.ExtractAllEntries();
while (reader.MoveToNextEntry())
{
Assert.Equal(expectedOrder.Pop(), reader.Entry.Key);
}
}
}