Compare commits

...

35 Commits

Author SHA1 Message Date
Adam Hathcock
7764684c68 Release for 0.34 2023-09-18 09:53:05 +01:00
Adam Hathcock
feb2c38572 fmt update 2023-09-18 09:48:31 +01:00
Adam Hathcock
6a97e82a2e Merge pull request #763 from btomblinson/master
#751 Add .tar.7z support
2023-09-18 09:47:01 +01:00
btomblinson
57c0d19cde #751 Add .tar.7z support 2023-09-17 17:46:56 -06:00
Adam Hathcock
e14ed89f3d Merge pull request #759 from Erior/feature/748
Feature/748
2023-09-14 09:05:48 +01:00
Adam Hathcock
6a14893a23 Merge branch 'master' into feature/748 2023-09-14 09:00:50 +01:00
Lars Vahlenberg
0f19735d33 Cleanup 2023-09-11 19:31:27 +02:00
Lars Vahlenberg
6a859ac65d Adding Filters to 7z 2023-09-11 19:24:54 +02:00
Adam Hathcock
4d9c24244c Merge pull request #758 from adamhathcock/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2023-09-11 10:47:54 +01:00
dependabot[bot]
cdeb288c4f Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-11 09:38:10 +00:00
Adam Hathcock
7f8016497b Merge pull request #750 from FlsZen/master
Add fast `ExtractToDirectoryAsync` extension method on `IArchive`
2023-09-07 15:05:15 +01:00
FlsZen
ec01225225 It looks like build format wants this on one line 2023-08-13 12:52:14 -04:00
James Hood
4e23b84999 Remove Task aspect 2023-07-21 13:17:42 -04:00
James Hood
c7c143fed9 Add ExtractToDirectoryAsync extension method on IArchive that is very fast compared to WriteToDirectory. 2023-07-19 08:22:15 -04:00
Adam Hathcock
4932171834 update csharpier 2023-06-12 09:53:00 +01:00
Adam Hathcock
00fc6c8e2f formatting 2023-06-12 09:52:35 +01:00
Adam Hathcock
1b73dab341 Merge remote-tracking branch 'Nanook/fixes-zstd' 2023-06-12 09:52:17 +01:00
Adam Hathcock
99e99c1ccd Merge branch 'master' into fixes-zstd 2023-06-12 09:45:35 +01:00
Adam Hathcock
14ce479ab7 Merge pull request #746 from rodesfl/patch-1
Added simple example
2023-06-12 09:31:17 +01:00
Rodrigo Lotrário
e7e873a1b2 Added simple example
Had some difficult figuring this one out, as this is so straight forward and is the simplest use case, maybe should be included at the top of the docs ?
2023-06-09 19:38:42 -03:00
Adam Hathcock
5a57428ec0 Merge pull request #745 from Erior/feature/Issue-743
Skip if we know the size, set blank password if not set for rar
2023-06-07 09:44:36 +01:00
Lars Vahlenberg
18e8e6ee98 Sharpier 2023-06-06 22:43:12 +02:00
Lars Vahlenberg
6bf6e51740 Skip if we know the size, set blank password if not set for rar 2023-06-06 22:27:53 +02:00
Adam Hathcock
b52a899a18 Merge pull request #740 from AlissaSabre/issue_739
Make ArchiveFactory.IsArchive(Stream, ...) public. Fix #739
2023-05-10 09:56:50 +01:00
Alissa Sabre
cf722a7120 Make ArchiveFactory.IsArchive(Stream, ...) public. Fix #739 2023-05-10 15:49:44 +09:00
Adam Hathcock
33cd1f3db8 Merge pull request #737 from Erior/feature/TarHeaderFactory-Infinite-loop
Check for broken file #736
2023-03-30 11:35:20 +01:00
Lars Vahlenberg
b7d2715ffd Remove whitespace 2023-03-29 19:39:03 +02:00
Lars Vahlenberg
fe63466d67 CSharpier 2023-03-29 18:18:17 +02:00
Lars Vahlenberg
0fb63eea99 Check for broken file 2023-03-28 23:07:21 +02:00
Adam Hathcock
59552804f6 fix badge 2023-03-21 14:11:18 +00:00
Adam Hathcock
579d6d73f8 build tests 2023-03-21 13:56:51 +00:00
Adam Hathcock
f83e3022ba add no restore to build 2023-03-21 13:54:45 +00:00
Adam Hathcock
bf93bbf5f8 fix restore 2023-03-21 13:44:02 +00:00
Adam Hathcock
fa2a52ff41 add caching and some cleanup 2023-03-21 13:41:36 +00:00
Nanook
92df1ecd5f ZStandard support added to zip/zipx (WinZip) and 7zip (mcmilk 7zip) 2023-02-02 01:06:18 +00:00
45 changed files with 663 additions and 91 deletions

View File

@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"csharpier": {
"version": "0.23.0",
"version": "0.25.0",
"commands": [
"dotnet-csharpier"
]

View File

@@ -14,10 +14,17 @@ jobs:
os: [windows-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
- name: NuGet Caching
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('packages.lock.json', '*/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- run: dotnet run --project build/build.csproj
- uses: actions/upload-artifact@v3
with:

View File

@@ -5,7 +5,8 @@ SharpCompress is a compression library in pure C# for .NET Standard 2.0, 2.1, .N
The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream).
GitHub Actions Build -
[![GitHubActions](https://github.com/adamhathcock/sharpcompress/workflows/SharpCompress/badge.svg)](https://circleci.com/gh/adamhathcock/sharpcompress)
[![SharpCompress](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml/badge.svg)](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml)
[![Static Badge](https://img.shields.io/badge/API%20Documentation-RobiniaDocs-43bc00?logo=readme&logoColor=white)](https://www.robiniadocs.com/d/sharpcompress/api/SharpCompress.html)
## Need Help?
@@ -42,6 +43,8 @@ I'm always looking for help or ideas. Please submit code or email with ideas. Un
## Version Log
* [Releases](https://github.com/adamhathcock/sharpcompress/releases)
### Version 0.18
* [Now on Github releases](https://github.com/adamhathcock/sharpcompress/releases/tag/0.18)

View File

@@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.6
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F18F1765-4A02-42FD-9BEF-F0E2FCBD9D17}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3C5BE746-03E5-4895-9988-0B57F162F86C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0F0901FF-E8D9-426A-B5A2-17C7F47C1529}"
@@ -15,6 +13,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpCompress.Test", "tests
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "build", "build\build.csproj", "{D4D613CB-5E94-47FB-85BE-B8423D20C545}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{CDB42573-7D22-4490-BA12-1B7FB99CE7FB}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
global.json = global.json
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

View File

@@ -33,6 +33,18 @@ If using Compression Stream classes directly and you don't want the wrapped stre
Also, look over the tests for more thorough [examples](https://github.com/adamhathcock/sharpcompress/tree/master/tests/SharpCompress.Test)
### Create Zip Archive from multiple files
```C#
using(var archive = ZipArchive.Create())
{
archive.AddEntry("file01.txt", "C:\\file01.txt");
archive.AddEntry("file02.txt", "C:\\file02.txt");
...
archive.SaveTo("C:\\temp.zip", CompressionType.Deflate);
}
```
### Create Zip Archive from all files in a directory to a file
```C#
@@ -143,4 +155,4 @@ foreach(var entry in tr.Entries)
{
Console.WriteLine($"{entry.Key}");
}
```
```

View File

@@ -7,8 +7,10 @@ using static Bullseye.Targets;
using static SimpleExec.Command;
const string Clean = "clean";
const string Restore = "restore";
const string Build = "build";
const string Test = "test";
const string Format = "format";
const string Publish = "publish";
Target(
@@ -38,10 +40,21 @@ Target(
);
Target(
Build,
Format,
() =>
{
Run("dotnet", "build src/SharpCompress/SharpCompress.csproj -c Release");
Run("dotnet", "tool restore");
Run("dotnet", "csharpier --check .");
}
);
Target(Restore, DependsOn(Format), () => Run("dotnet", "restore"));
Target(
Build,
DependsOn(Restore),
() =>
{
Run("dotnet", "build src/SharpCompress/SharpCompress.csproj -c Release --no-restore");
}
);
@@ -63,7 +76,7 @@ Target(
foreach (var file in GetFiles("**/*.Test.csproj"))
{
Run("dotnet", $"test {file} -c Release -f {framework}");
Run("dotnet", $"test {file} -c Release -f {framework} --no-restore --verbosity=normal");
}
}
);

View File

@@ -175,7 +175,7 @@ public static class ArchiveFactory
return IsArchive(s, out type);
}
private static bool IsArchive(Stream stream, out ArchiveType? type)
public static bool IsArchive(Stream stream, out ArchiveType? type)
{
type = null;
stream.CheckNotNull(nameof(stream));

View File

@@ -1,4 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
namespace SharpCompress.Archives;
@@ -19,4 +24,54 @@ public static class IArchiveExtensions
entry.WriteToDirectory(destinationDirectory, options);
}
}
/// <summary>
/// Extracts the archive to the destination directory. Directories will be created as needed.
/// </summary>
/// <param name="archive">The archive to extract.</param>
/// <param name="destination">The folder to extract into.</param>
/// <param name="progressReport">Optional progress report callback.</param>
/// <param name="cancellationToken">Optional cancellation token.</param>
public static void ExtractToDirectory(
this IArchive archive,
string destination,
Action<double>? progressReport = null,
CancellationToken cancellationToken = default
)
{
// Prepare for progress reporting
var totalBytes = archive.TotalUncompressSize;
var bytesRead = 0L;
// Tracking for created directories.
var seenDirectories = new HashSet<string>();
// Extract
var entries = archive.ExtractAllEntries();
while (entries.MoveToNextEntry())
{
cancellationToken.ThrowIfCancellationRequested();
var entry = entries.Entry;
if (entry.IsDirectory)
{
continue;
}
// Create each directory
var path = Path.Combine(destination, entry.Key);
if (Path.GetDirectoryName(path) is { } directory && seenDirectories.Add(path))
{
Directory.CreateDirectory(directory);
}
// Write file
using var fs = File.OpenWrite(path);
entries.WriteEntryTo(fs);
// Update progress
bytesRead += entry.Size;
progressReport?.Invoke(bytesRead / (double)totalBytes);
}
}
}

View File

@@ -15,7 +15,7 @@ internal sealed class RarCryptoWrapper : Stream
{
_actualStream = actualStream;
_salt = salt;
_rijndael = RarRijndael.InitializeFrom(password, salt);
_rijndael = RarRijndael.InitializeFrom(password ?? "", salt);
}
public override void Flush() => throw new NotSupportedException();

View File

@@ -72,6 +72,10 @@ public class TarEntry : Entry
yield return new TarEntry(new TarFilePart(h, null), compressionType);
}
}
else
{
throw new IncompleteArchiveException("Unexpected EOF reading tar file");
}
}
}
}

View File

@@ -7,6 +7,7 @@ internal enum ZipCompressionMethod
Deflate64 = 9,
BZip2 = 12,
LZMA = 14,
ZStd = 93,
Xz = 95,
PPMd = 98,
WinzipAes = 0x63 //http://www.winzip.com/aes_info.htm

View File

@@ -11,6 +11,7 @@ using SharpCompress.Compressors.LZMA;
using SharpCompress.Compressors.PPMd;
using SharpCompress.Compressors.Xz;
using SharpCompress.IO;
using ZstdSharp;
namespace SharpCompress.Common.Zip;
@@ -113,6 +114,10 @@ internal abstract class ZipFilePart : FilePart
{
return new XZStream(stream);
}
case ZipCompressionMethod.ZStd:
{
return new DecompressionStream(stream);
}
case ZipCompressionMethod.PPMd:
{
Span<byte> props = stackalloc byte[2];

View File

@@ -0,0 +1,49 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterARM : Filter
{
private int _pos;
public BCJFilterARM(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 8) => _pos = 8;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 4)
{
if ((buffer[i + 3] & 0xFF) == 0xEB)
{
int src =
((buffer[i + 2] & 0xFF) << 16)
| ((buffer[i + 1] & 0xFF) << 8)
| (buffer[i] & 0xFF);
src <<= 2;
int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}
dest >>>= 2;
buffer[i + 2] = (byte)(dest >>> 16);
buffer[i + 1] = (byte)(dest >>> 8);
buffer[i] = (byte)dest;
}
}
i -= offset;
_pos += i;
return i;
}
}

View File

@@ -0,0 +1,47 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterARMT : Filter
{
private int _pos;
public BCJFilterARMT(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 4;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 2)
{
if ((buffer[i + 1] & 0xF8) == 0xF0 && (buffer[i + 3] & 0xF8) == 0xF8)
{
int src =
((buffer[i + 1] & 0x07) << 19)
| ((buffer[i] & 0xFF) << 11)
| ((buffer[i + 3] & 0x07) << 8)
| (buffer[i + 2] & 0xFF);
src <<= 1;
int dest;
if (_isEncoder)
dest = src + (_pos + i - offset);
else
dest = src - (_pos + i - offset);
dest >>>= 1;
buffer[i + 1] = (byte)(0xF0 | ((dest >>> 19) & 0x07));
buffer[i] = (byte)(dest >>> 11);
buffer[i + 3] = (byte)(0xF8 | ((dest >>> 8) & 0x07));
buffer[i + 2] = (byte)dest;
i += 2;
}
}
i -= offset;
_pos += i;
return i;
}
}

View File

@@ -0,0 +1,107 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterIA64 : Filter
{
private int _pos;
private static readonly int[] BRANCH_TABLE =
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
4,
6,
6,
0,
0,
7,
7,
4,
4,
0,
0,
4,
4,
0,
0
};
public BCJFilterIA64(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 16) => _pos = 0;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 16;
int i;
for (i = offset; i <= end; i += 16)
{
int instrTemplate = buffer[i] & 0x1F;
int mask = BRANCH_TABLE[instrTemplate];
for (int slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41)
{
if (((mask >>> slot) & 1) == 0)
continue;
int bytePos = bitPos >>> 3;
int bitRes = bitPos & 7;
long instr = 0;
for (int j = 0; j < 6; ++j)
{
instr |= (buffer[i + bytePos + j] & 0xFFL) << (8 * j);
}
long instrNorm = instr >>> bitRes;
if (((instrNorm >>> 37) & 0x0F) != 0x05 || ((instrNorm >>> 9) & 0x07) != 0x00)
continue;
int src = (int)((instrNorm >>> 13) & 0x0FFFFF);
src |= ((int)(instrNorm >>> 36) & 1) << 20;
src <<= 4;
int dest;
if (_isEncoder)
dest = src + (_pos + i - offset);
else
dest = src - (_pos + i - offset);
dest >>>= 4;
instrNorm &= ~(0x8FFFFFL << 13);
instrNorm |= (dest & 0x0FFFFFL) << 13;
instrNorm |= (dest & 0x100000L) << (36 - 20);
instr &= (1 << bitRes) - 1;
instr |= instrNorm << bitRes;
for (int j = 0; j < 6; ++j)
{
buffer[i + bytePos + j] = (byte)(instr >>> (8 * j));
}
}
}
i -= offset;
_pos += i;
return i;
}
}

View File

@@ -0,0 +1,48 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterPPC : Filter
{
private int _pos;
public BCJFilterPPC(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 0;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 4)
{
if ((buffer[i] & 0xFC) == 0x48 && (buffer[i + 3] & 0x03) == 0x01)
{
int src =
((buffer[i] & 0x03) << 24)
| ((buffer[i + 1] & 0xFF) << 16)
| ((buffer[i + 2] & 0xFF) << 8)
| (buffer[i + 3] & 0xFC);
int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}
buffer[i] = (byte)(0x48 | ((dest >>> 24) & 0x03));
buffer[i + 1] = (byte)(dest >>> 16);
buffer[i + 2] = (byte)(dest >>> 8);
buffer[i + 3] = (byte)((buffer[i + 3] & 0x03) | dest);
}
}
i -= offset;
_pos += i;
return i;
}
}

View File

@@ -0,0 +1,58 @@
using System.IO;
namespace SharpCompress.Compressors.Filters;
internal class BCJFilterSPARC : Filter
{
private int _pos;
public BCJFilterSPARC(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 0;
protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;
for (i = offset; i <= end; i += 4)
{
if (
(buffer[i] == 0x40 && (buffer[i + 1] & 0xC0) == 0x00)
|| (buffer[i] == 0x7F && (buffer[i + 1] & 0xC0) == 0xC0)
)
{
int src =
((buffer[i] & 0xFF) << 24)
| ((buffer[i + 1] & 0xFF) << 16)
| ((buffer[i + 2] & 0xFF) << 8)
| (buffer[i + 3] & 0xFF);
src <<= 2;
int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}
dest >>>= 2;
dest =
(((0 - ((dest >>> 22) & 1)) << 22) & 0x3FFFFFFF)
| (dest & 0x3FFFFF)
| 0x40000000;
buffer[i] = (byte)(dest >>> 24);
buffer[i + 1] = (byte)(dest >>> 16);
buffer[i + 2] = (byte)(dest >>> 8);
buffer[i + 3] = (byte)dest;
}
}
i -= offset;
_pos += i;
return i;
}
}

View File

@@ -7,6 +7,7 @@ using SharpCompress.Compressors.Deflate;
using SharpCompress.Compressors.Filters;
using SharpCompress.Compressors.LZMA.Utilites;
using SharpCompress.Compressors.PPMd;
using ZstdSharp;
namespace SharpCompress.Compressors.LZMA;
@@ -19,8 +20,14 @@ internal static class DecoderRegistry
private const uint K_PPMD = 0x030401;
private const uint K_BCJ = 0x03030103;
private const uint K_BCJ2 = 0x0303011B;
private const uint K_PPC = 0x03030205;
private const uint K_IA64 = 0x03030401;
private const uint K_ARM = 0x03030501;
private const uint K_ARMT = 0x03030701;
private const uint K_SPARC = 0x03030805;
private const uint K_DEFLATE = 0x040108;
private const uint K_B_ZIP2 = 0x040202;
private const uint K_ZSTD = 0x4F71101;
internal static Stream CreateDecoderStream(
CMethodId id,
@@ -49,12 +56,24 @@ internal static class DecoderRegistry
return new BCJFilter(false, inStreams.Single());
case K_BCJ2:
return new Bcj2DecoderStream(inStreams, info, limit);
case K_PPC:
return new BCJFilterPPC(false, inStreams.Single());
case K_IA64:
return new BCJFilterIA64(false, inStreams.Single());
case K_ARM:
return new BCJFilterARM(false, inStreams.Single());
case K_ARMT:
return new BCJFilterARMT(false, inStreams.Single());
case K_SPARC:
return new BCJFilterSPARC(false, inStreams.Single());
case K_B_ZIP2:
return new BZip2Stream(inStreams.Single(), CompressionMode.Decompress, true);
case K_PPMD:
return new PpmdStream(new PpmdProperties(info), inStreams.Single(), false);
case K_DEFLATE:
return new DeflateStream(inStreams.Single(), CompressionMode.Decompress);
case K_ZSTD:
return new DecompressionStream(inStreams.Single());
default:
throw new NotSupportedException();
}

View File

@@ -6,32 +6,29 @@ namespace SharpCompress.Compressors.Xz.Filters;
public abstract class BlockFilter : ReadOnlyStream
{
[CLSCompliant(false)]
public enum FilterTypes : ulong
private enum FilterTypes : ulong
{
DELTA = 0x03,
ARCH_x86_FILTER = 0x04,
ARCH_PowerPC_FILTER = 0x05,
ARCH_IA64_FILTER = 0x06,
ARCH_ARM_FILTER = 0x07,
ARCH_ARMTHUMB_FILTER = 0x08,
ARCH_SPARC_FILTER = 0x09,
LZMA2 = 0x21
//Delta = 0x03,
ArchX86Filter = 0x04,
ArchPowerPcFilter = 0x05,
ArchIa64Filter = 0x06,
ArchArmFilter = 0x07,
ArchArmThumbFilter = 0x08,
ArchSparcFilter = 0x09,
Lzma2 = 0x21
}
private static readonly Dictionary<FilterTypes, Func<BlockFilter>> FilterMap = new Dictionary<
FilterTypes,
Func<BlockFilter>
>
{
{ FilterTypes.ARCH_x86_FILTER, () => new X86Filter() },
{ FilterTypes.ARCH_PowerPC_FILTER, () => new PowerPCFilter() },
{ FilterTypes.ARCH_IA64_FILTER, () => new IA64Filter() },
{ FilterTypes.ARCH_ARM_FILTER, () => new ArmFilter() },
{ FilterTypes.ARCH_ARMTHUMB_FILTER, () => new ArmThumbFilter() },
{ FilterTypes.ARCH_SPARC_FILTER, () => new SparcFilter() },
{ FilterTypes.LZMA2, () => new Lzma2Filter() }
};
private static readonly Dictionary<FilterTypes, Func<BlockFilter>> FILTER_MAP =
new()
{
{ FilterTypes.ArchX86Filter, () => new X86Filter() },
{ FilterTypes.ArchPowerPcFilter, () => new PowerPCFilter() },
{ FilterTypes.ArchIa64Filter, () => new IA64Filter() },
{ FilterTypes.ArchArmFilter, () => new ArmFilter() },
{ FilterTypes.ArchArmThumbFilter, () => new ArmThumbFilter() },
{ FilterTypes.ArchSparcFilter, () => new SparcFilter() },
{ FilterTypes.Lzma2, () => new Lzma2Filter() }
};
public abstract bool AllowAsLast { get; }
public abstract bool AllowAsNonLast { get; }
@@ -43,12 +40,12 @@ public abstract class BlockFilter : ReadOnlyStream
public static BlockFilter Read(BinaryReader reader)
{
var filterType = (FilterTypes)reader.ReadXZInteger();
if (!FilterMap.ContainsKey(filterType))
if (!FILTER_MAP.ContainsKey(filterType))
{
throw new NotImplementedException($"Filter {filterType} has not yet been implemented");
}
var filter = FilterMap[filterType]()!;
var filter = FILTER_MAP[filterType]();
var sizeOfProperties = reader.ReadXZInteger();
if (sizeOfProperties > int.MaxValue)

View File

@@ -9,10 +9,10 @@ namespace SharpCompress.IO;
public class SourceStream : Stream
{
private long _prevSize;
private List<FileInfo> _files;
private List<Stream> _streams;
private Func<int, FileInfo?> _getFilePart;
private Func<int, Stream?> _getStreamPart;
private readonly List<FileInfo> _files;
private readonly List<Stream> _streams;
private readonly Func<int, FileInfo?> _getFilePart;
private readonly Func<int, Stream?> _getStreamPart;
private int _stream;
public SourceStream(FileInfo file, Func<int, FileInfo?> getPart, ReaderOptions options)
@@ -39,10 +39,10 @@ public class SourceStream : Stream
{
_streams.Add(stream!);
_getStreamPart = getStreamPart!;
_getFilePart = new Func<int, FileInfo>(a => null!);
if (stream is FileStream)
_getFilePart = _ => null!;
if (stream is FileStream fileStream)
{
_files.Add(new FileInfo(((FileStream)stream!).Name));
_files.Add(new FileInfo(fileStream.Name));
}
}
else
@@ -50,7 +50,7 @@ public class SourceStream : Stream
_files.Add(file!);
_streams.Add(_files[0].OpenRead());
_getFilePart = getFilePart!;
_getStreamPart = new Func<int, Stream>(a => null!);
_getStreamPart = _ => null!;
}
_stream = 0;
_prevSize = 0;
@@ -98,9 +98,9 @@ public class SourceStream : Stream
}
//throw new Exception($"Stream part {idx} not available.");
_streams.Add(s);
if (s is FileStream)
if (s is FileStream stream)
{
_files.Add(new FileInfo(((FileStream)s).Name));
_files.Add(new FileInfo(stream.Name));
}
}
}
@@ -123,11 +123,11 @@ public class SourceStream : Stream
public override bool CanWrite => false;
public override long Length => (!IsVolumes ? _streams.Sum(a => a.Length) : Current.Length);
public override long Length => !IsVolumes ? _streams.Sum(a => a.Length) : Current.Length;
public override long Position
{
get => _prevSize + Current.Position; //_prevSize is 0 for multivolume
get => _prevSize + Current.Position; //_prevSize is 0 for multi-volume
set => Seek(value, SeekOrigin.Begin);
}
@@ -222,9 +222,12 @@ public class SourceStream : Stream
{
try
{
stream?.Dispose();
stream.Dispose();
}
catch
{
// ignored
}
catch { }
}
_streams.Clear();
_files.Clear();

View File

@@ -129,7 +129,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti
{
var part = Entry.Parts.First();
if (ArchiveType != ArchiveType.Rar && !Entry.IsSolid && Entry.CompressedSize > 0)
if (!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

@@ -11,5 +11,7 @@ internal class NonSeekableStreamFilePart : RarFilePart
internal override Stream GetCompressedStream() => FileHeader.PackedStream;
internal override Stream? GetRawStream() => FileHeader.PackedStream;
internal override string FilePartName => "Unknown Stream - File Entry: " + FileHeader.FileName;
}

View File

@@ -1,41 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyTitle>SharpCompress - Pure C# Decompression/Compression</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.33.0</VersionPrefix>
<AssemblyVersion>0.33.0</AssemblyVersion>
<FileVersion>0.33.0</FileVersion>
<Authors>Adam Hathcock</Authors>
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0;net7.0</TargetFrameworks>
<AssemblyName>SharpCompress</AssemblyName>
<AssemblyOriginatorKeyFile>../../SharpCompress.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<PackageId>SharpCompress</PackageId>
<PackageTags>rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz</PackageTags>
<PackageProjectUrl>https://github.com/adamhathcock/sharpcompress</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Copyright>Copyright (c) 2014 Adam Hathcock</Copyright>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Description>SharpCompress is a compression library for NET Standard 2.0/2.1/NET 6.0/NET 7.0 that can unrar, decompress 7zip, decompress xz, zip/unzip, tar/untar lzip/unlzip, bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.</Description>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyTitle>SharpCompress - Pure C# Decompression/Compression</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.34.0</VersionPrefix>
<AssemblyVersion>0.34.0</AssemblyVersion>
<FileVersion>0.34.0</FileVersion>
<Authors>Adam Hathcock</Authors>
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0;net7.0</TargetFrameworks>
<AssemblyName>SharpCompress</AssemblyName>
<AssemblyOriginatorKeyFile>../../SharpCompress.snk</AssemblyOriginatorKeyFile>
<SignAssembly>False</SignAssembly>
<PackageId>SharpCompress</PackageId>
<PackageTags>rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz</PackageTags>
<PackageProjectUrl>https://github.com/adamhathcock/sharpcompress</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Copyright>Copyright (c) 2014 Adam Hathcock</Copyright>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Description>SharpCompress is a compression library for NET Standard 2.0/2.1/NET 6.0/NET 7.0 that can unrar, decompress 7zip, decompress xz, zip/unzip, tar/untar lzip/unlzip, bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.</Description>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<IsTrimmable>true</IsTrimmable>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' == 'NETFRAMEWORK' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="ZstdSharp.Port" Version="0.6.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' == 'NETFRAMEWORK' ">
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
</Project>

View File

@@ -332,4 +332,49 @@ public class RarReaderTests : ReaderTests
}
}
}
[Fact]
public void Rar_NullReference()
{
{
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())
{
//
}
}
}
}

View File

@@ -1,5 +1,8 @@
using System;
using System.IO;
using System.Linq;
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
using SharpCompress.Readers;
using Xunit;
@@ -111,10 +114,78 @@ public class SevenZipArchiveTests : ArchiveTests
//"7Zip.BZip2.split.006",
//"7Zip.BZip2.split.007"
[Fact]
public void SevenZipArchive_ZSTD_StreamRead() => ArchiveStreamRead("7Zip.ZSTD.7z");
[Fact]
public void SevenZipArchive_ZSTD_PathRead() => ArchiveFileRead("7Zip.ZSTD.7z");
[Fact]
public void SevenZipArchive_ZSTD_Split() =>
Assert.Throws<InvalidOperationException>(
() =>
ArchiveStreamRead(
null,
"7Zip.ZSTD.Split.7z.001",
"7Zip.ZSTD.Split.7z.002",
"7Zip.ZSTD.Split.7z.003",
"7Zip.ZSTD.Split.7z.004",
"7Zip.ZSTD.Split.7z.005",
"7Zip.ZSTD.Split.7z.006"
)
);
[Fact]
public void SevenZipArchive_Delta_FileRead() => ArchiveFileRead("7Zip.delta.7z");
[Fact]
public void SevenZipArchive_ARM_FileRead() => ArchiveFileRead("7Zip.ARM.7z");
[Fact]
public void SevenZipArchive_ARMT_FileRead() => ArchiveFileRead("7Zip.ARMT.7z");
[Fact]
public void SevenZipArchive_BCJ_FileRead() => ArchiveFileRead("7Zip.BCJ.7z");
[Fact]
public void SevenZipArchive_BCJ2_FileRead() => ArchiveFileRead("7Zip.BCJ2.7z");
[Fact]
public void SevenZipArchive_IA64_FileRead() => ArchiveFileRead("7Zip.IA64.7z");
[Fact]
public void SevenZipArchive_PPC_FileRead() => ArchiveFileRead("7Zip.PPC.7z");
[Fact]
public void SevenZipArchive_SPARC_FileRead() => ArchiveFileRead("7Zip.SPARC.7z");
[Fact]
public void SevenZipArchive_Filters_FileRead() => ArchiveFileRead("7Zip.Filters.7z");
[Fact]
public void SevenZipArchive_Delta_Distance() =>
ArchiveDeltaDistanceRead("7Zip.delta.distance.7z");
[Fact]
public void SevenZipArchive_Tar_PathRead()
{
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "7Zip.Tar.tar.7z")))
using (var archive = SevenZipArchive.Open(stream))
{
var entry = archive.Entries.First();
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key));
var size = entry.Size;
var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "7Zip.Tar.tar"));
var test = new FileInfo(Path.Combine(TEST_ARCHIVES_PATH, "7Zip.Tar.tar"));
Assert.Equal(size, scratch.Length);
Assert.Equal(size, test.Length);
}
CompareArchivesByPath(
Path.Combine(SCRATCH_FILES_PATH, "7Zip.Tar.tar"),
Path.Combine(TEST_ARCHIVES_PATH, "7Zip.Tar.tar")
);
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Linq;
using SharpCompress.Archives;

View File

@@ -183,6 +183,25 @@ public class TarReaderTests : ReaderTests
}
}
[Fact]
public void Tar_Broken_Stream()
{
string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar");
using (Stream stream = File.OpenRead(archiveFullPath))
using (IReader reader = ReaderFactory.Open(stream))
{
var memoryStream = new MemoryStream();
Action action = () => reader.MoveToNextEntry();
var exception = Record.Exception(action);
Assert.Null(exception);
reader.MoveToNextEntry();
reader.WriteEntryTo(memoryStream);
stream.Close();
Assert.Throws<IncompleteArchiveException>(action);
}
}
#if !NETFRAMEWORK
[Fact]
public void Tar_GZip_With_Symlink_Entries()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.