mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-09 05:24:55 +00:00
Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
372a2c8375 | ||
|
|
8f27121f21 | ||
|
|
b986bf675f | ||
|
|
80718a461b | ||
|
|
2d14ecf58b | ||
|
|
32aa9877c0 | ||
|
|
cee3a9c11d | ||
|
|
b78643f2d8 | ||
|
|
30a31de45b | ||
|
|
e4c4db534c | ||
|
|
4f7a0d3ad0 | ||
|
|
ea3a96eead | ||
|
|
c0e01ac132 | ||
|
|
28ea50bca4 | ||
|
|
619e44b30f | ||
|
|
d678275dee | ||
|
|
08eed53595 | ||
|
|
ff40f7d262 | ||
|
|
3c1ae51dae | ||
|
|
8a59fc9aaf | ||
|
|
b7ea9dd841 | ||
|
|
0320db6b4a | ||
|
|
18c7f58093 | ||
|
|
7f6f7b1436 | ||
|
|
ca49176b97 | ||
|
|
67be0cd9d7 | ||
|
|
902fadef83 | ||
|
|
2777b6411f | ||
|
|
e3235d7f04 | ||
|
|
dc89c8858e | ||
|
|
d28a278d63 | ||
|
|
7080c2abd0 | ||
|
|
43f86bcab8 | ||
|
|
7d9c875c4d | ||
|
|
ed4099eb12 | ||
|
|
632b83f75d | ||
|
|
66c92637f9 | ||
|
|
6bcaebc471 | ||
|
|
7feee1027c | ||
|
|
4fd8c77fa9 | ||
|
|
bc3bb2d323 | ||
|
|
7764684c68 | ||
|
|
feb2c38572 | ||
|
|
6a97e82a2e | ||
|
|
57c0d19cde | ||
|
|
e14ed89f3d | ||
|
|
6a14893a23 | ||
|
|
0f19735d33 | ||
|
|
6a859ac65d | ||
|
|
4d9c24244c | ||
|
|
cdeb288c4f | ||
|
|
7f8016497b | ||
|
|
ec01225225 | ||
|
|
4e23b84999 | ||
|
|
c7c143fed9 | ||
|
|
4932171834 | ||
|
|
00fc6c8e2f | ||
|
|
1b73dab341 | ||
|
|
99e99c1ccd | ||
|
|
14ce479ab7 | ||
|
|
e7e873a1b2 | ||
|
|
5a57428ec0 | ||
|
|
18e8e6ee98 | ||
|
|
6bf6e51740 | ||
|
|
b52a899a18 | ||
|
|
cf722a7120 | ||
|
|
33cd1f3db8 | ||
|
|
b7d2715ffd | ||
|
|
fe63466d67 | ||
|
|
0fb63eea99 | ||
|
|
59552804f6 | ||
|
|
579d6d73f8 | ||
|
|
f83e3022ba | ||
|
|
bf93bbf5f8 | ||
|
|
fa2a52ff41 | ||
|
|
92df1ecd5f |
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"csharpier": {
|
||||
"version": "0.23.0",
|
||||
"version": "0.26.7",
|
||||
"commands": [
|
||||
"dotnet-csharpier"
|
||||
]
|
||||
|
||||
8
.github/workflows/dotnetcore.yml
vendored
8
.github/workflows/dotnetcore.yml
vendored
@@ -14,12 +14,12 @@ jobs:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-dotnet@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
dotnet-version: 8.0.x
|
||||
- run: dotnet run --project build/build.csproj
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.os }}-sharpcompress.nupkg
|
||||
path: artifacts/*
|
||||
|
||||
@@ -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 -
|
||||
[](https://circleci.com/gh/adamhathcock/sharpcompress)
|
||||
[](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml)
|
||||
[](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)
|
||||
|
||||
@@ -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
|
||||
|
||||
14
USAGE.md
14
USAGE.md
@@ -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}");
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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,17 +40,28 @@ 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");
|
||||
}
|
||||
);
|
||||
|
||||
Target(
|
||||
Test,
|
||||
DependsOn(Build),
|
||||
ForEach("net7.0", "net462"),
|
||||
ForEach("net8.0", "net462"),
|
||||
framework =>
|
||||
{
|
||||
IEnumerable<string> GetFiles(string d)
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "7.0.101",
|
||||
"version": "8.0.100",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ public static class ArchiveFactory
|
||||
|
||||
public static IWritableArchive Create(ArchiveType type)
|
||||
{
|
||||
var factory = Factory.Factories
|
||||
.OfType<IWriteableArchiveFactory>()
|
||||
var factory = Factory
|
||||
.Factories.OfType<IWriteableArchiveFactory>()
|
||||
.FirstOrDefault(item => item.KnownArchiveType == type);
|
||||
|
||||
if (factory != null)
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,19 @@ internal class SeekableFilePart : RarFilePart
|
||||
internal override Stream GetCompressedStream()
|
||||
{
|
||||
stream.Position = FileHeader.DataStartPosition;
|
||||
|
||||
if (FileHeader.R4Salt != null)
|
||||
{
|
||||
return new RarCryptoWrapper(stream, password!, FileHeader.R4Salt);
|
||||
var cryptKey = new CryptKey3(password!);
|
||||
return new RarCryptoWrapper(stream, FileHeader.R4Salt, cryptKey);
|
||||
}
|
||||
|
||||
if (FileHeader.Rar5CryptoInfo != null)
|
||||
{
|
||||
var cryptKey = new CryptKey5(password!, FileHeader.Rar5CryptoInfo);
|
||||
return new RarCryptoWrapper(stream, FileHeader.Rar5CryptoInfo.Salt, cryptKey);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
87
src/SharpCompress/Common/Rar/CryptKey3.cs
Normal file
87
src/SharpCompress/Common/Rar/CryptKey3.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
#nullable disable
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
|
||||
namespace SharpCompress.Common.Rar;
|
||||
|
||||
internal class CryptKey3 : ICryptKey
|
||||
{
|
||||
const int AES_128 = 128;
|
||||
|
||||
private string _password;
|
||||
|
||||
public CryptKey3(string password)
|
||||
{
|
||||
_password = password ?? "";
|
||||
}
|
||||
|
||||
public ICryptoTransform Transformer(byte[] salt)
|
||||
{
|
||||
var aesIV = new byte[EncryptionConstV5.SIZE_INITV];
|
||||
|
||||
var rawLength = 2 * _password.Length;
|
||||
var rawPassword = new byte[rawLength + EncryptionConstV5.SIZE_SALT30];
|
||||
var passwordBytes = Encoding.UTF8.GetBytes(_password);
|
||||
for (var i = 0; i < _password.Length; i++)
|
||||
{
|
||||
rawPassword[i * 2] = passwordBytes[i];
|
||||
rawPassword[(i * 2) + 1] = 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < salt.Length; i++)
|
||||
{
|
||||
rawPassword[i + rawLength] = salt[i];
|
||||
}
|
||||
|
||||
var msgDigest = SHA1.Create();
|
||||
const int noOfRounds = (1 << 18);
|
||||
const int iblock = 3;
|
||||
|
||||
byte[] digest;
|
||||
var data = new byte[(rawPassword.Length + iblock) * noOfRounds];
|
||||
|
||||
//TODO slow code below, find ways to optimize
|
||||
for (var i = 0; i < noOfRounds; i++)
|
||||
{
|
||||
rawPassword.CopyTo(data, i * (rawPassword.Length + iblock));
|
||||
|
||||
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i;
|
||||
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8);
|
||||
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)(i >> 16);
|
||||
|
||||
if (i % (noOfRounds / EncryptionConstV5.SIZE_INITV) == 0)
|
||||
{
|
||||
digest = msgDigest.ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock));
|
||||
aesIV[i / (noOfRounds / EncryptionConstV5.SIZE_INITV)] = digest[19];
|
||||
}
|
||||
}
|
||||
digest = msgDigest.ComputeHash(data);
|
||||
//slow code ends
|
||||
|
||||
var aesKey = new byte[EncryptionConstV5.SIZE_INITV];
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
for (var j = 0; j < 4; j++)
|
||||
{
|
||||
aesKey[(i * 4) + j] = (byte)(
|
||||
(
|
||||
((digest[i * 4] * 0x1000000) & 0xff000000)
|
||||
| (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000)
|
||||
| (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00)
|
||||
| (uint)(digest[(i * 4) + 3] & 0xff)
|
||||
) >> (j * 8)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var aes = Aes.Create();
|
||||
aes.KeySize = AES_128;
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Padding = PaddingMode.None;
|
||||
aes.Key = aesKey;
|
||||
aes.IV = aesIV;
|
||||
return aes.CreateDecryptor();
|
||||
}
|
||||
}
|
||||
97
src/SharpCompress/Common/Rar/CryptKey5.cs
Normal file
97
src/SharpCompress/Common/Rar/CryptKey5.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
|
||||
namespace SharpCompress.Common.Rar;
|
||||
|
||||
internal class CryptKey5 : ICryptKey
|
||||
{
|
||||
const int AES_256 = 256;
|
||||
const int DERIVED_KEY_LENGTH = 0x10;
|
||||
const int SHA256_DIGEST_SIZE = 32;
|
||||
|
||||
private string _password;
|
||||
private Rar5CryptoInfo _cryptoInfo;
|
||||
private byte[] _pswCheck = { };
|
||||
private byte[] _hashKey = { };
|
||||
|
||||
public CryptKey5(string password, Rar5CryptoInfo rar5CryptoInfo)
|
||||
{
|
||||
_password = password;
|
||||
_cryptoInfo = rar5CryptoInfo;
|
||||
}
|
||||
|
||||
public byte[] PswCheck => _pswCheck;
|
||||
|
||||
public byte[] HashKey => _hashKey;
|
||||
|
||||
private static List<byte[]> GenerateRarPBKDF2Key(
|
||||
string password,
|
||||
byte[] salt,
|
||||
int iterations,
|
||||
int keyLength
|
||||
)
|
||||
{
|
||||
using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)))
|
||||
{
|
||||
byte[] block = hmac.ComputeHash(salt);
|
||||
byte[] finalHash = (byte[])block.Clone();
|
||||
|
||||
var loop = new int[] { iterations, 17, 17 };
|
||||
var res = new List<byte[]> { };
|
||||
|
||||
for (int x = 0; x < 3; x++)
|
||||
{
|
||||
for (int i = 1; i < loop[x]; i++)
|
||||
{
|
||||
block = hmac.ComputeHash(block);
|
||||
for (int j = 0; j < finalHash.Length; j++)
|
||||
{
|
||||
finalHash[j] ^= block[j];
|
||||
}
|
||||
}
|
||||
|
||||
res.Add((byte[])finalHash.Clone());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public ICryptoTransform Transformer(byte[] salt)
|
||||
{
|
||||
int iterations = (1 << _cryptoInfo.LG2Count); // Adjust the number of iterations as needed
|
||||
|
||||
var salt_rar5 = salt.Concat(new byte[] { 0, 0, 0, 1 });
|
||||
var derivedKey = GenerateRarPBKDF2Key(
|
||||
_password,
|
||||
salt_rar5.ToArray(),
|
||||
iterations,
|
||||
DERIVED_KEY_LENGTH
|
||||
);
|
||||
|
||||
_hashKey = derivedKey[1];
|
||||
|
||||
_pswCheck = new byte[EncryptionConstV5.SIZE_PSWCHECK];
|
||||
|
||||
for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
|
||||
{
|
||||
_pswCheck[i % EncryptionConstV5.SIZE_PSWCHECK] ^= derivedKey[2][i];
|
||||
}
|
||||
|
||||
if (_cryptoInfo.UsePswCheck && !_cryptoInfo.PswCheck.SequenceEqual(_pswCheck))
|
||||
{
|
||||
throw new CryptographicException("The password did not match.");
|
||||
}
|
||||
|
||||
var aes = Aes.Create();
|
||||
aes.KeySize = AES_256;
|
||||
aes.Mode = CipherMode.CBC;
|
||||
aes.Padding = PaddingMode.None;
|
||||
aes.Key = derivedKey[0];
|
||||
aes.IV = _cryptoInfo.InitV;
|
||||
return aes.CreateDecryptor();
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,21 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Rar.Headers;
|
||||
|
||||
internal class ArchiveCryptHeader : RarHeader
|
||||
{
|
||||
private const int CRYPT_VERSION = 0; // Supported encryption version.
|
||||
private const int SIZE_SALT50 = 16;
|
||||
private const int SIZE_PSWCHECK = 8;
|
||||
private const int SIZE_PSWCHECK_CSUM = 4;
|
||||
private const int CRYPT5_KDF_LG2_COUNT_MAX = 24; // LOG2 of maximum accepted iteration count.
|
||||
|
||||
private bool _usePswCheck;
|
||||
private uint _lg2Count; // Log2 of PBKDF2 repetition count.
|
||||
private byte[] _salt;
|
||||
private byte[] _pswCheck;
|
||||
private byte[] _pswCheckCsm;
|
||||
|
||||
public ArchiveCryptHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Crypt) { }
|
||||
|
||||
public Rar5CryptoInfo CryptInfo = new Rar5CryptoInfo();
|
||||
|
||||
protected override void ReadFinish(MarkingBinaryReader reader)
|
||||
{
|
||||
var cryptVersion = reader.ReadRarVIntUInt32();
|
||||
if (cryptVersion > CRYPT_VERSION)
|
||||
{
|
||||
//error?
|
||||
return;
|
||||
}
|
||||
var encryptionFlags = reader.ReadRarVIntUInt32();
|
||||
_usePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
|
||||
_lg2Count = reader.ReadRarVIntByte(1);
|
||||
|
||||
//UsePswCheck = HasHeaderFlag(EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
|
||||
if (_lg2Count > CRYPT5_KDF_LG2_COUNT_MAX)
|
||||
{
|
||||
//error?
|
||||
return;
|
||||
}
|
||||
|
||||
_salt = reader.ReadBytes(SIZE_SALT50);
|
||||
if (_usePswCheck)
|
||||
{
|
||||
_pswCheck = reader.ReadBytes(SIZE_PSWCHECK);
|
||||
_pswCheckCsm = reader.ReadBytes(SIZE_PSWCHECK_CSUM);
|
||||
}
|
||||
CryptInfo = new Rar5CryptoInfo(reader, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using SharpCompress.IO;
|
||||
#if !Rar2017_64bit
|
||||
using size_t = System.UInt32;
|
||||
#else
|
||||
@@ -8,11 +14,6 @@ using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
|
||||
using SharpCompress.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpCompress.Common.Rar.Headers;
|
||||
|
||||
internal class FileHeader : RarHeader
|
||||
@@ -104,7 +105,13 @@ internal class FileHeader : RarHeader
|
||||
throw new InvalidFormatException("rar5 header size / extra size inconsistency");
|
||||
}
|
||||
|
||||
isEncryptedRar5 = false;
|
||||
const ushort FHEXTRA_CRYPT = 0x01;
|
||||
const ushort FHEXTRA_HASH = 0x02;
|
||||
const ushort FHEXTRA_HTIME = 0x03;
|
||||
// const ushort FHEXTRA_VERSION = 0x04;
|
||||
// const ushort FHEXTRA_REDIR = 0x05;
|
||||
// const ushort FHEXTRA_UOWNER = 0x06;
|
||||
// const ushort FHEXTRA_SUBDATA = 0x07;
|
||||
|
||||
while (RemainingHeaderBytes(reader) > 0)
|
||||
{
|
||||
@@ -114,21 +121,34 @@ internal class FileHeader : RarHeader
|
||||
switch (type)
|
||||
{
|
||||
//TODO
|
||||
case 1: // file encryption
|
||||
case FHEXTRA_CRYPT: // file encryption
|
||||
|
||||
{
|
||||
isEncryptedRar5 = true;
|
||||
Rar5CryptoInfo = new Rar5CryptoInfo(reader, true);
|
||||
|
||||
//var version = reader.ReadRarVIntByte();
|
||||
//if (version != 0) throw new InvalidFormatException("unknown encryption algorithm " + version);
|
||||
if (Rar5CryptoInfo.PswCheck.All(singleByte => singleByte == 0))
|
||||
{
|
||||
Rar5CryptoInfo = null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// case 2: // file hash
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
case 3: // file time
|
||||
case FHEXTRA_HASH:
|
||||
|
||||
{
|
||||
const uint FHEXTRA_HASH_BLAKE2 = 0x0;
|
||||
const uint HASH_BLAKE2 = 0x03;
|
||||
const int BLAKE2_DIGEST_SIZE = 0x20;
|
||||
if ((uint)reader.ReadRarVInt() == FHEXTRA_HASH_BLAKE2)
|
||||
{
|
||||
var hash = HASH_BLAKE2;
|
||||
var digest = reader.ReadBytes(BLAKE2_DIGEST_SIZE);
|
||||
|
||||
throw new InvalidFormatException("Not yet implemented " + hash);
|
||||
}
|
||||
// enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
|
||||
}
|
||||
break;
|
||||
case FHEXTRA_HTIME: // file time
|
||||
|
||||
{
|
||||
var flags = reader.ReadRarVIntUInt16();
|
||||
@@ -148,22 +168,22 @@ internal class FileHeader : RarHeader
|
||||
}
|
||||
break;
|
||||
//TODO
|
||||
// case 4: // file version
|
||||
// case FHEXTRA_VERSION: // file version
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 5: // file system redirection
|
||||
// case FHEXTRA_REDIR: // file system redirection
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 6: // unix owner
|
||||
// case FHEXTRA_UOWNER: // unix owner
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 7: // service data
|
||||
// case FHEXTRA_SUBDATA: // service data
|
||||
// {
|
||||
//
|
||||
// }
|
||||
@@ -255,7 +275,6 @@ internal class FileHeader : RarHeader
|
||||
|
||||
var fileNameBytes = reader.ReadBytes(nameSize);
|
||||
|
||||
const int saltSize = 8;
|
||||
const int newLhdSize = 32;
|
||||
|
||||
switch (HeaderCode)
|
||||
@@ -293,7 +312,7 @@ internal class FileHeader : RarHeader
|
||||
var datasize = HeaderSize - newLhdSize - nameSize;
|
||||
if (HasFlag(FileFlagsV4.SALT))
|
||||
{
|
||||
datasize -= saltSize;
|
||||
datasize -= EncryptionConstV5.SIZE_SALT30;
|
||||
}
|
||||
if (datasize > 0)
|
||||
{
|
||||
@@ -314,7 +333,7 @@ internal class FileHeader : RarHeader
|
||||
|
||||
if (HasFlag(FileFlagsV4.SALT))
|
||||
{
|
||||
R4Salt = reader.ReadBytes(saltSize);
|
||||
R4Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT30);
|
||||
}
|
||||
if (HasFlag(FileFlagsV4.EXT_TIME))
|
||||
{
|
||||
@@ -432,7 +451,7 @@ internal class FileHeader : RarHeader
|
||||
internal size_t WindowSize { get; private set; }
|
||||
|
||||
internal byte[] R4Salt { get; private set; }
|
||||
|
||||
internal Rar5CryptoInfo Rar5CryptoInfo { get; private set; }
|
||||
private byte HostOs { get; set; }
|
||||
internal uint FileAttributes { get; private set; }
|
||||
internal long CompressedSize { get; private set; }
|
||||
@@ -450,8 +469,7 @@ internal class FileHeader : RarHeader
|
||||
|
||||
public bool IsDirectory => HasFlag(IsRar5 ? FileFlagsV5.DIRECTORY : FileFlagsV4.DIRECTORY);
|
||||
|
||||
private bool isEncryptedRar5 = false;
|
||||
public bool IsEncrypted => IsRar5 ? isEncryptedRar5 : HasFlag(FileFlagsV4.PASSWORD);
|
||||
public bool IsEncrypted => IsRar5 ? Rar5CryptoInfo != null : HasFlag(FileFlagsV4.PASSWORD);
|
||||
|
||||
internal DateTime? FileLastModifiedTime { get; private set; }
|
||||
|
||||
|
||||
@@ -50,6 +50,17 @@ internal static class EncryptionFlagsV5
|
||||
public const uint FHEXTRA_CRYPT_HASHMAC = 0x02;
|
||||
}
|
||||
|
||||
internal static class EncryptionConstV5
|
||||
{
|
||||
public const int VERSION = 0;
|
||||
public const uint CRYPT5_KDF_LG2_COUNT_MAX = 0x24;
|
||||
public const int SIZE_SALT30 = 0x08;
|
||||
public const int SIZE_SALT50 = 0x10;
|
||||
public const int SIZE_INITV = 0x10;
|
||||
public const int SIZE_PSWCHECK = 0x08;
|
||||
public const int SIZE_PSWCHECK_CSUM = 0x04;
|
||||
}
|
||||
|
||||
internal static class HeaderFlagsV5
|
||||
{
|
||||
public const ushort HAS_EXTRA = 0x0001;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.IO;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common.Rar;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
@@ -9,6 +11,8 @@ public class RarHeaderFactory
|
||||
{
|
||||
private bool _isRar5;
|
||||
|
||||
private Rar5CryptoInfo? _cryptInfo;
|
||||
|
||||
public RarHeaderFactory(StreamingMode mode, ReaderOptions options)
|
||||
{
|
||||
StreamingMode = mode;
|
||||
@@ -53,7 +57,19 @@ public class RarHeaderFactory
|
||||
"Encrypted Rar archive has no password specified."
|
||||
);
|
||||
}
|
||||
reader = new RarCryptoBinaryReader(stream, Options.Password);
|
||||
|
||||
if (_isRar5 && _cryptInfo != null)
|
||||
{
|
||||
_cryptInfo.ReadInitV(new MarkingBinaryReader(stream));
|
||||
var _headerKey = new CryptKey5(Options.Password!, _cryptInfo);
|
||||
|
||||
reader = new RarCryptoBinaryReader(stream, _headerKey, _cryptInfo.Salt);
|
||||
}
|
||||
else
|
||||
{
|
||||
var key = new CryptKey3(Options.Password);
|
||||
reader = new RarCryptoBinaryReader(stream, key);
|
||||
}
|
||||
}
|
||||
|
||||
var header = RarHeader.TryReadBase(reader, _isRar5, Options.ArchiveEncoding);
|
||||
@@ -105,7 +121,14 @@ public class RarHeaderFactory
|
||||
case HeaderCodeV.RAR5_SERVICE_HEADER:
|
||||
{
|
||||
var fh = new FileHeader(header, reader, HeaderType.Service);
|
||||
SkipData(fh, reader);
|
||||
if (fh.FileName == "CMT")
|
||||
{
|
||||
fh.PackedStream = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
SkipData(fh, reader);
|
||||
}
|
||||
return fh;
|
||||
}
|
||||
|
||||
@@ -133,7 +156,7 @@ public class RarHeaderFactory
|
||||
|
||||
{
|
||||
var ms = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize);
|
||||
if (fh.R4Salt is null)
|
||||
if (fh.R4Salt is null && fh.Rar5CryptoInfo is null)
|
||||
{
|
||||
fh.PackedStream = ms;
|
||||
}
|
||||
@@ -141,8 +164,10 @@ public class RarHeaderFactory
|
||||
{
|
||||
fh.PackedStream = new RarCryptoWrapper(
|
||||
ms,
|
||||
Options.Password!,
|
||||
fh.R4Salt
|
||||
fh.R4Salt is null ? fh.Rar5CryptoInfo.Salt : fh.R4Salt,
|
||||
fh.R4Salt is null
|
||||
? new CryptKey5(Options.Password!, fh.Rar5CryptoInfo)
|
||||
: new CryptKey3(Options.Password!)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -161,9 +186,11 @@ public class RarHeaderFactory
|
||||
}
|
||||
case HeaderCodeV.RAR5_ARCHIVE_ENCRYPTION_HEADER:
|
||||
{
|
||||
var ch = new ArchiveCryptHeader(header, reader);
|
||||
var cryptoHeader = new ArchiveCryptHeader(header, reader);
|
||||
IsEncrypted = true;
|
||||
return ch;
|
||||
_cryptInfo = cryptoHeader.CryptInfo;
|
||||
|
||||
return cryptoHeader;
|
||||
}
|
||||
default:
|
||||
{
|
||||
|
||||
8
src/SharpCompress/Common/Rar/ICryptKey.cs
Normal file
8
src/SharpCompress/Common/Rar/ICryptKey.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace SharpCompress.Common.Rar;
|
||||
|
||||
internal interface ICryptKey
|
||||
{
|
||||
ICryptoTransform Transformer(byte[] salt);
|
||||
}
|
||||
59
src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs
Normal file
59
src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Rar;
|
||||
|
||||
internal class Rar5CryptoInfo
|
||||
{
|
||||
public Rar5CryptoInfo() { }
|
||||
|
||||
public Rar5CryptoInfo(MarkingBinaryReader reader, bool readInitV)
|
||||
{
|
||||
var cryptVersion = reader.ReadRarVIntUInt32();
|
||||
if (cryptVersion > EncryptionConstV5.VERSION)
|
||||
{
|
||||
throw new CryptographicException($"Unsupported crypto version of {cryptVersion}");
|
||||
}
|
||||
var encryptionFlags = reader.ReadRarVIntUInt32();
|
||||
UsePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK);
|
||||
LG2Count = reader.ReadRarVIntByte(1);
|
||||
|
||||
if (LG2Count > EncryptionConstV5.CRYPT5_KDF_LG2_COUNT_MAX)
|
||||
{
|
||||
throw new CryptographicException($"Unsupported LG2 count of {LG2Count}.");
|
||||
}
|
||||
|
||||
Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT50);
|
||||
|
||||
if (readInitV) // File header needs to read IV here
|
||||
{
|
||||
ReadInitV(reader);
|
||||
}
|
||||
|
||||
if (UsePswCheck)
|
||||
{
|
||||
PswCheck = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK);
|
||||
var _pswCheckCsm = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK_CSUM);
|
||||
|
||||
var sha = SHA256.Create();
|
||||
UsePswCheck = sha.ComputeHash(PswCheck).AsSpan().StartsWith(_pswCheckCsm.AsSpan());
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadInitV(MarkingBinaryReader reader)
|
||||
{
|
||||
InitV = reader.ReadBytes(EncryptionConstV5.SIZE_INITV);
|
||||
}
|
||||
|
||||
public bool UsePswCheck = false;
|
||||
|
||||
public int LG2Count = 0;
|
||||
|
||||
public byte[] InitV = { };
|
||||
|
||||
public byte[] Salt = { };
|
||||
|
||||
public byte[] PswCheck = { };
|
||||
}
|
||||
@@ -1,27 +1,30 @@
|
||||
using System.Collections.Generic;
|
||||
#nullable disable
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.Crypto;
|
||||
|
||||
namespace SharpCompress.Common.Rar;
|
||||
|
||||
internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader
|
||||
{
|
||||
private RarRijndael _rijndael;
|
||||
private byte[] _salt;
|
||||
private readonly string _password;
|
||||
private BlockTransformer _rijndael;
|
||||
private readonly Queue<byte> _data = new Queue<byte>();
|
||||
private long _readCount;
|
||||
|
||||
public RarCryptoBinaryReader(Stream stream, string password)
|
||||
public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey)
|
||||
: base(stream)
|
||||
{
|
||||
_password = password;
|
||||
var salt = base.ReadBytes(EncryptionConstV5.SIZE_SALT30);
|
||||
_readCount += EncryptionConstV5.SIZE_SALT30;
|
||||
_rijndael = new BlockTransformer(cryptKey.Transformer(salt));
|
||||
}
|
||||
|
||||
// coderb: not sure why this was being done at this logical point
|
||||
//SkipQueue();
|
||||
var salt = ReadBytes(8);
|
||||
|
||||
_salt = salt;
|
||||
_rijndael = RarRijndael.InitializeFrom(_password, salt);
|
||||
public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey, byte[] salt)
|
||||
: base(stream)
|
||||
{
|
||||
_rijndael = new BlockTransformer(cryptKey.Transformer(salt));
|
||||
}
|
||||
|
||||
// track read count ourselves rather than using the underlying stream since we buffer
|
||||
@@ -36,28 +39,14 @@ internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader
|
||||
|
||||
public override void Mark() => _readCount = 0;
|
||||
|
||||
private bool UseEncryption => _salt != null;
|
||||
|
||||
public override byte ReadByte()
|
||||
{
|
||||
if (UseEncryption)
|
||||
{
|
||||
return ReadAndDecryptBytes(1)[0];
|
||||
}
|
||||
|
||||
_readCount++;
|
||||
return base.ReadByte();
|
||||
return ReadAndDecryptBytes(1)[0];
|
||||
}
|
||||
|
||||
public override byte[] ReadBytes(int count)
|
||||
{
|
||||
if (UseEncryption)
|
||||
{
|
||||
return ReadAndDecryptBytes(count);
|
||||
}
|
||||
|
||||
_readCount += count;
|
||||
return base.ReadBytes(count);
|
||||
return ReadAndDecryptBytes(count);
|
||||
}
|
||||
|
||||
private byte[] ReadAndDecryptBytes(int count)
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Crypto;
|
||||
|
||||
namespace SharpCompress.Common.Rar;
|
||||
|
||||
internal sealed class RarCryptoWrapper : Stream
|
||||
{
|
||||
private readonly Stream _actualStream;
|
||||
private readonly byte[] _salt;
|
||||
private RarRijndael _rijndael;
|
||||
private BlockTransformer _rijndael;
|
||||
private readonly Queue<byte> _data = new Queue<byte>();
|
||||
|
||||
public RarCryptoWrapper(Stream actualStream, string password, byte[] salt)
|
||||
public RarCryptoWrapper(Stream actualStream, byte[] salt, ICryptKey key)
|
||||
{
|
||||
_actualStream = actualStream;
|
||||
_salt = salt;
|
||||
_rijndael = RarRijndael.InitializeFrom(password, salt);
|
||||
_rijndael = new BlockTransformer(key.Transformer(salt));
|
||||
}
|
||||
|
||||
public override void Flush() => throw new NotSupportedException();
|
||||
@@ -26,10 +25,6 @@ internal sealed class RarCryptoWrapper : Stream
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (_salt is null)
|
||||
{
|
||||
return _actualStream.Read(buffer, offset, count);
|
||||
}
|
||||
return ReadAndDecrypt(buffer, offset, count);
|
||||
}
|
||||
|
||||
@@ -41,7 +36,7 @@ internal sealed class RarCryptoWrapper : Stream
|
||||
if (sizeToRead > 0)
|
||||
{
|
||||
var alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf);
|
||||
Span<byte> cipherText = stackalloc byte[RarRijndael.CRYPTO_BLOCK_SIZE];
|
||||
Span<byte> cipherText = stackalloc byte[16];
|
||||
for (var i = 0; i < alignedSize / 16; i++)
|
||||
{
|
||||
//long ax = System.currentTimeMillis();
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using SharpCompress.Crypto;
|
||||
|
||||
namespace SharpCompress.Common.Rar;
|
||||
|
||||
internal class RarRijndael : IDisposable
|
||||
{
|
||||
internal const int CRYPTO_BLOCK_SIZE = 16;
|
||||
|
||||
private readonly string _password;
|
||||
private readonly byte[] _salt;
|
||||
private byte[] _aesInitializationVector;
|
||||
private RijndaelEngine _rijndael;
|
||||
|
||||
private RarRijndael(string password, byte[] salt)
|
||||
{
|
||||
_password = password;
|
||||
_salt = salt;
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
_rijndael = new RijndaelEngine();
|
||||
_aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE];
|
||||
var rawLength = 2 * _password.Length;
|
||||
var rawPassword = new byte[rawLength + 8];
|
||||
var passwordBytes = Encoding.UTF8.GetBytes(_password);
|
||||
for (var i = 0; i < _password.Length; i++)
|
||||
{
|
||||
rawPassword[i * 2] = passwordBytes[i];
|
||||
rawPassword[(i * 2) + 1] = 0;
|
||||
}
|
||||
for (var i = 0; i < _salt.Length; i++)
|
||||
{
|
||||
rawPassword[i + rawLength] = _salt[i];
|
||||
}
|
||||
|
||||
const int noOfRounds = (1 << 18);
|
||||
const int iblock = 3;
|
||||
byte[] digest;
|
||||
var data = new byte[(rawPassword.Length + iblock) * noOfRounds];
|
||||
|
||||
//TODO slow code below, find ways to optimize
|
||||
for (var i = 0; i < noOfRounds; i++)
|
||||
{
|
||||
rawPassword.CopyTo(data, i * (rawPassword.Length + iblock));
|
||||
|
||||
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i;
|
||||
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8);
|
||||
data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)(
|
||||
i >> CRYPTO_BLOCK_SIZE
|
||||
);
|
||||
|
||||
if (i % (noOfRounds / CRYPTO_BLOCK_SIZE) == 0)
|
||||
{
|
||||
digest = SHA1.Create()
|
||||
.ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock));
|
||||
_aesInitializationVector[i / (noOfRounds / CRYPTO_BLOCK_SIZE)] = digest[19];
|
||||
}
|
||||
}
|
||||
digest = SHA1.Create().ComputeHash(data);
|
||||
//slow code ends
|
||||
|
||||
var aesKey = new byte[CRYPTO_BLOCK_SIZE];
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
for (var j = 0; j < 4; j++)
|
||||
{
|
||||
aesKey[(i * 4) + j] = (byte)(
|
||||
(
|
||||
((digest[i * 4] * 0x1000000) & 0xff000000)
|
||||
| (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000)
|
||||
| (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00)
|
||||
| (uint)(digest[(i * 4) + 3] & 0xff)
|
||||
) >> (j * 8)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_rijndael.Init(false, new KeyParameter(aesKey));
|
||||
}
|
||||
|
||||
public static RarRijndael InitializeFrom(string password, byte[] salt)
|
||||
{
|
||||
var rijndael = new RarRijndael(password, salt);
|
||||
rijndael.Initialize();
|
||||
return rijndael;
|
||||
}
|
||||
|
||||
public byte[] ProcessBlock(ReadOnlySpan<byte> cipherText)
|
||||
{
|
||||
Span<byte> plainText = stackalloc byte[CRYPTO_BLOCK_SIZE]; // 16 bytes
|
||||
var decryptedBytes = new byte[CRYPTO_BLOCK_SIZE];
|
||||
_rijndael.ProcessBlock(cipherText, plainText);
|
||||
|
||||
for (var j = 0; j < CRYPTO_BLOCK_SIZE; j++)
|
||||
{
|
||||
decryptedBytes[j] = (byte)(plainText[j] ^ _aesInitializationVector[j % 16]); //32:114, 33:101
|
||||
}
|
||||
|
||||
for (var j = 0; j < _aesInitializationVector.Length; j++)
|
||||
{
|
||||
_aesInitializationVector[j] = cipherText[j];
|
||||
}
|
||||
|
||||
return decryptedBytes;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
@@ -70,11 +71,7 @@ public abstract class RarVolume : Volume
|
||||
var part = CreateFilePart(lastMarkHeader!, fh);
|
||||
var buffer = new byte[fh.CompressedSize];
|
||||
part.GetCompressedStream().Read(buffer, 0, buffer.Length);
|
||||
Comment = System.Text.Encoding.UTF8.GetString(
|
||||
buffer,
|
||||
0,
|
||||
buffer.Length - 1
|
||||
);
|
||||
Comment = Encoding.UTF8.GetString(buffer, 0, buffer.Length - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
12
src/SharpCompress/Common/ReaderCancelledException.cs
Normal file
12
src/SharpCompress/Common/ReaderCancelledException.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Common;
|
||||
|
||||
public class ReaderCancelledException : Exception
|
||||
{
|
||||
public ReaderCancelledException(string message)
|
||||
: base(message) { }
|
||||
|
||||
public ReaderCancelledException(string message, Exception inner)
|
||||
: base(message, inner) { }
|
||||
}
|
||||
@@ -75,6 +75,9 @@ internal class SevenZipFilePart : FilePart
|
||||
|
||||
internal CompressionType GetCompression()
|
||||
{
|
||||
if (Header.IsDir)
|
||||
return CompressionType.None;
|
||||
|
||||
var coder = Folder!._coders.First();
|
||||
switch (coder._methodId._id)
|
||||
{
|
||||
@@ -97,5 +100,7 @@ internal class SevenZipFilePart : FilePart
|
||||
}
|
||||
|
||||
internal bool IsEncrypted =>
|
||||
Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1;
|
||||
Header.IsDir
|
||||
? false
|
||||
: Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#nullable disable
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
@@ -132,8 +132,8 @@ internal sealed class TarHeader
|
||||
Mode |= 0b1_000_000_000;
|
||||
}
|
||||
|
||||
UserId = ReadAsciiInt64Base8(buffer, 108, 7);
|
||||
GroupId = ReadAsciiInt64Base8(buffer, 116, 7);
|
||||
UserId = ReadAsciiInt64Base8oldGnu(buffer, 108, 7);
|
||||
GroupId = ReadAsciiInt64Base8oldGnu(buffer, 116, 7);
|
||||
var unixTimeStamp = ReadAsciiInt64Base8(buffer, 136, 11);
|
||||
LastModifiedTime = EPOCH.AddSeconds(unixTimeStamp).ToLocalTime();
|
||||
|
||||
@@ -249,6 +249,24 @@ internal sealed class TarHeader
|
||||
return Convert.ToInt64(s, 8);
|
||||
}
|
||||
|
||||
private static long ReadAsciiInt64Base8oldGnu(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (buffer[offset] == 0x80 && buffer[offset + 1] == 0x00)
|
||||
{
|
||||
return buffer[offset + 4] << 24
|
||||
| buffer[offset + 5] << 16
|
||||
| buffer[offset + 6] << 8
|
||||
| buffer[offset + 7];
|
||||
}
|
||||
var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls();
|
||||
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return Convert.ToInt64(s, 8);
|
||||
}
|
||||
|
||||
private static long ReadAsciiInt64(byte[] buffer, int offset, int count)
|
||||
{
|
||||
var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls();
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using SharpCompress.IO;
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Common.Tar;
|
||||
|
||||
|
||||
@@ -48,15 +48,15 @@ internal class WinzipAesEncryptionData
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
#if NET7_0
|
||||
#if NETFRAMEWORK || NETSTANDARD2_0
|
||||
var rfc2898 = new Rfc2898DeriveBytes(_password, _salt, RFC2898_ITERATIONS);
|
||||
#else
|
||||
var rfc2898 = new Rfc2898DeriveBytes(
|
||||
_password,
|
||||
_salt,
|
||||
RFC2898_ITERATIONS,
|
||||
HashAlgorithmName.SHA1
|
||||
);
|
||||
#else
|
||||
var rfc2898 = new Rfc2898DeriveBytes(_password, _salt, RFC2898_ITERATIONS);
|
||||
#endif
|
||||
|
||||
KeyBytes = rfc2898.GetBytes(KeySizeInBytes); // 16 or 24 or 32 ???
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -69,7 +69,6 @@
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
|
||||
using SharpCompress.Algorithms;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate;
|
||||
@@ -1959,7 +1958,9 @@ internal sealed partial class DeflateManager
|
||||
// returning Z_STREAM_END instead of Z_BUFF_ERROR.
|
||||
}
|
||||
else if (
|
||||
_codec.AvailableBytesIn == 0 && (int)flush <= old_flush && flush != FlushType.Finish
|
||||
_codec.AvailableBytesIn == 0
|
||||
&& (int)flush <= old_flush
|
||||
&& flush != FlushType.Finish
|
||||
)
|
||||
{
|
||||
// workitem 8557
|
||||
|
||||
@@ -64,7 +64,6 @@
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
|
||||
using SharpCompress.Algorithms;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate;
|
||||
|
||||
@@ -30,8 +30,8 @@ using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common.Tar.Headers;
|
||||
using System.Text;
|
||||
using SharpCompress.Common.Tar.Headers;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate;
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using SharpCompress.Common.Zip;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using SharpCompress.Common.Zip;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate64;
|
||||
|
||||
|
||||
49
src/SharpCompress/Compressors/Filters/BCJFilterARM.cs
Normal file
49
src/SharpCompress/Compressors/Filters/BCJFilterARM.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
47
src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs
Normal file
47
src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
107
src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs
Normal file
107
src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
48
src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs
Normal file
48
src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
58
src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs
Normal file
58
src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -207,14 +207,23 @@ public class LzmaStream : Stream
|
||||
|
||||
if (_availableBytes == 0 && !_uncompressedChunk)
|
||||
{
|
||||
_rangeDecoder.ReleaseStream();
|
||||
// Check range corruption scenario
|
||||
if (
|
||||
!_rangeDecoder.IsFinished
|
||||
|| (_rangeDecoderLimit >= 0 && _rangeDecoder._total != _rangeDecoderLimit)
|
||||
)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
// Stream might have End Of Stream marker
|
||||
_outWindow.SetLimit(toProcess + 1);
|
||||
if (!_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder))
|
||||
{
|
||||
_rangeDecoder.ReleaseStream();
|
||||
throw new DataErrorException();
|
||||
}
|
||||
}
|
||||
|
||||
_rangeDecoder.ReleaseStream();
|
||||
|
||||
_inputPosition += _rangeDecoder._total;
|
||||
if (_outWindow.HasPending)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -866,7 +866,8 @@ internal partial class Model
|
||||
);
|
||||
}
|
||||
else if (
|
||||
(currentContext.SummaryFrequency += 4) > 128 + (4 * currentContext.NumberStatistics)
|
||||
(currentContext.SummaryFrequency += 4)
|
||||
> 128 + (4 * currentContext.NumberStatistics)
|
||||
)
|
||||
{
|
||||
Refresh((uint)((currentContext.NumberStatistics + 2) >> 1), true, currentContext);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
|
||||
using SharpCompress.Compressors.Rar.VM;
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV1;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
#if !Rar2017_64bit
|
||||
using size_t = System.UInt32;
|
||||
#else
|
||||
@@ -7,7 +8,6 @@ using nint = System.Int64;
|
||||
using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
using System;
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#if !Rar2017_64bit
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
#if !Rar2017_64bit
|
||||
using size_t = System.UInt32;
|
||||
#else
|
||||
using nint = System.Int64;
|
||||
using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
using System;
|
||||
using System.IO;
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#if !Rar2017_64bit
|
||||
using uint32 = System.UInt32;
|
||||
|
||||
/*#if !Rar2017_64bit
|
||||
#else
|
||||
using nint = System.Int64;
|
||||
using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
using uint32 = System.UInt32;
|
||||
#endif*/
|
||||
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#if !Rar2017_64bit
|
||||
using System;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local;
|
||||
|
||||
/*#if !Rar2017_64bit
|
||||
#else
|
||||
using nint = System.Int64;
|
||||
using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
using System;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local;
|
||||
#endif*/
|
||||
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
|
||||
using int64 = System.Int64;
|
||||
#if !Rar2017_64bit
|
||||
using size_t = System.UInt32;
|
||||
#else
|
||||
@@ -7,11 +11,6 @@ using nint = System.Int64;
|
||||
using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
using int64 = System.Int64;
|
||||
|
||||
using System;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using SharpCompress.Common;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
|
||||
#if !Rar2017_64bit
|
||||
using size_t = System.UInt32;
|
||||
#else
|
||||
@@ -8,11 +12,6 @@ using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using SharpCompress.Common;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
internal sealed partial class Unpack : BitInput
|
||||
@@ -30,12 +29,12 @@ internal sealed partial class Unpack : BitInput
|
||||
Suspended = false;
|
||||
UnpAllBuf = false;
|
||||
UnpSomeRead = false;
|
||||
#if RarV2017_RAR_SMP
|
||||
MaxUserThreads = 1;
|
||||
UnpThreadPool = CreateThreadPool();
|
||||
ReadBufMT = null;
|
||||
UnpThreadData = null;
|
||||
#endif
|
||||
/*#if RarV2017_RAR_SMP
|
||||
MaxUserThreads = 1;
|
||||
UnpThreadPool = CreateThreadPool();
|
||||
ReadBufMT = null;
|
||||
UnpThreadData = null;
|
||||
#endif*/
|
||||
MaxWinSize = 0;
|
||||
MaxWinMask = 0;
|
||||
|
||||
@@ -199,21 +198,21 @@ internal sealed partial class Unpack : BitInput
|
||||
break;
|
||||
#endif
|
||||
case 50: // RAR 5.0 compression algorithm.
|
||||
#if RarV2017_RAR_SMP
|
||||
if (MaxUserThreads > 1)
|
||||
{
|
||||
// We do not use the multithreaded unpack routine to repack RAR archives
|
||||
// in 'suspended' mode, because unlike the single threaded code it can
|
||||
// write more than one dictionary for same loop pass. So we would need
|
||||
// larger buffers of unknown size. Also we do not support multithreading
|
||||
// in fragmented window mode.
|
||||
if (!Fragmented)
|
||||
{
|
||||
Unpack5MT(Solid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*#if RarV2017_RAR_SMP
|
||||
if (MaxUserThreads > 1)
|
||||
{
|
||||
// We do not use the multithreaded unpack routine to repack RAR archives
|
||||
// in 'suspended' mode, because unlike the single threaded code it can
|
||||
// write more than one dictionary for same loop pass. So we would need
|
||||
// larger buffers of unknown size. Also we do not support multithreading
|
||||
// in fragmented window mode.
|
||||
if (!Fragmented)
|
||||
{
|
||||
Unpack5MT(Solid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif*/
|
||||
Unpack5(Solid);
|
||||
break;
|
||||
#if !Rar2017_NOSTRICT
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#if !Rar2017_64bit
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
|
||||
/*#if !Rar2017_64bit
|
||||
#else
|
||||
using nint = System.Int64;
|
||||
using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
#endif*/
|
||||
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
|
||||
using int64 = System.Int64;
|
||||
#if !Rar2017_64bit
|
||||
using size_t = System.UInt32;
|
||||
#else
|
||||
@@ -5,12 +10,6 @@ using nint = System.Int64;
|
||||
using nuint = System.UInt64;
|
||||
using size_t = System.UInt64;
|
||||
#endif
|
||||
using int64 = System.Int64;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef;
|
||||
using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal;
|
||||
using System;
|
||||
|
||||
// TODO: REMOVE THIS... WIP
|
||||
#pragma warning disable 169
|
||||
@@ -20,8 +19,6 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017;
|
||||
|
||||
internal static class UnpackGlobal
|
||||
{
|
||||
|
||||
|
||||
// Maximum allowed number of compressed bits processed in quick mode.
|
||||
public const int MAX_QUICK_DECODE_BITS = 10;
|
||||
|
||||
@@ -97,11 +94,11 @@ internal struct UnpackBlockHeader
|
||||
|
||||
internal struct UnpackBlockTables
|
||||
{
|
||||
public DecodeTable LD; // Decode literals.
|
||||
public DecodeTable DD; // Decode distances.
|
||||
public DecodeTable LD; // Decode literals.
|
||||
public DecodeTable DD; // Decode distances.
|
||||
public DecodeTable LDD; // Decode lower bits of distances.
|
||||
public DecodeTable RD; // Decode repeating distances.
|
||||
public DecodeTable BD; // Decode bit lengths in Huffman table.
|
||||
public DecodeTable RD; // Decode repeating distances.
|
||||
public DecodeTable BD; // Decode bit lengths in Huffman table.
|
||||
|
||||
public void Init()
|
||||
{
|
||||
@@ -113,8 +110,7 @@ internal struct UnpackBlockTables
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if RarV2017_RAR_SMP
|
||||
/*#if RarV2017_RAR_SMP
|
||||
enum UNP_DEC_TYPE {
|
||||
UNPDT_LITERAL,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER
|
||||
};
|
||||
@@ -161,7 +157,7 @@ if (Decoded!=NULL)
|
||||
free(Decoded);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
|
||||
//struct UnpackFilter
|
||||
@@ -171,12 +167,12 @@ internal class UnpackFilter
|
||||
public uint BlockStart;
|
||||
public uint BlockLength;
|
||||
public byte Channels;
|
||||
|
||||
// uint Width;
|
||||
// byte PosR;
|
||||
public bool NextWindow;
|
||||
};
|
||||
|
||||
|
||||
//struct UnpackFilter30
|
||||
internal class UnpackFilter30
|
||||
{
|
||||
@@ -195,15 +191,21 @@ internal class UnpackFilter30
|
||||
|
||||
internal class AudioVariables // For RAR 2.0 archives only.
|
||||
{
|
||||
public int K1, K2, K3, K4, K5;
|
||||
public int D1, D2, D3, D4;
|
||||
public int K1,
|
||||
K2,
|
||||
K3,
|
||||
K4,
|
||||
K5;
|
||||
public int D1,
|
||||
D2,
|
||||
D3,
|
||||
D4;
|
||||
public int LastDelta;
|
||||
public readonly uint[] Dif = new uint[11];
|
||||
public uint ByteCount;
|
||||
public int LastChar;
|
||||
};
|
||||
|
||||
|
||||
// We can use the fragmented dictionary in case heap does not have the single
|
||||
// large enough memory block. It is slower than normal dictionary.
|
||||
internal partial class FragmentedWindow
|
||||
@@ -223,10 +225,8 @@ internal partial class FragmentedWindow
|
||||
//size_t GetBlockSize(size_t StartPos,size_t RequiredSize);
|
||||
};
|
||||
|
||||
|
||||
internal partial class Unpack
|
||||
{
|
||||
|
||||
//void Unpack5(bool Solid);
|
||||
//void Unpack5MT(bool Solid);
|
||||
//bool UnpReadBuf();
|
||||
@@ -254,16 +254,16 @@ internal partial class Unpack
|
||||
//BitInput Inp;
|
||||
private BitInput Inp => this; // hopefully this gets inlined
|
||||
|
||||
#if RarV2017_RAR_SMP
|
||||
void InitMT();
|
||||
bool UnpackLargeBlock(UnpackThreadData &D);
|
||||
bool ProcessDecoded(UnpackThreadData &D);
|
||||
|
||||
ThreadPool *UnpThreadPool;
|
||||
UnpackThreadData *UnpThreadData;
|
||||
uint MaxUserThreads;
|
||||
byte *ReadBufMT;
|
||||
#endif
|
||||
/*#if RarV2017_RAR_SMP
|
||||
void InitMT();
|
||||
bool UnpackLargeBlock(UnpackThreadData &D);
|
||||
bool ProcessDecoded(UnpackThreadData &D);
|
||||
|
||||
ThreadPool *UnpThreadPool;
|
||||
UnpackThreadData *UnpThreadData;
|
||||
uint MaxUserThreads;
|
||||
byte *ReadBufMT;
|
||||
#endif*/
|
||||
|
||||
private byte[] FilterSrcMemory = Array.Empty<byte>();
|
||||
private byte[] FilterDstMemory = Array.Empty<byte>();
|
||||
@@ -279,7 +279,8 @@ byte *ReadBufMT;
|
||||
// array. In RAR3 last distance is always stored in OldDist[0].
|
||||
private uint LastDist;
|
||||
|
||||
private size_t UnpPtr, WrPtr;
|
||||
private size_t UnpPtr,
|
||||
WrPtr;
|
||||
|
||||
// Top border of read packed data.
|
||||
private int ReadTop;
|
||||
@@ -307,7 +308,6 @@ byte *ReadBufMT;
|
||||
private int64 WrittenFileSize;
|
||||
private bool FileExtracted;
|
||||
|
||||
|
||||
/***************************** Unpack v 1.5 *********************************/
|
||||
//void Unpack15(bool Solid);
|
||||
//void ShortLZ();
|
||||
@@ -320,12 +320,29 @@ byte *ReadBufMT;
|
||||
//void CopyString15(uint Distance,uint Length);
|
||||
//uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab);
|
||||
|
||||
private readonly ushort[] ChSet = new ushort[256], ChSetA = new ushort[256], ChSetB = new ushort[256], ChSetC = new ushort[256];
|
||||
private readonly byte[] NToPl = new byte[256], NToPlB = new byte[256], NToPlC = new byte[256];
|
||||
private uint FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3;
|
||||
private int Buf60, NumHuf, StMode, LCount, FlagsCnt;
|
||||
private readonly ushort[] ChSet = new ushort[256],
|
||||
ChSetA = new ushort[256],
|
||||
ChSetB = new ushort[256],
|
||||
ChSetC = new ushort[256];
|
||||
private readonly byte[] NToPl = new byte[256],
|
||||
NToPlB = new byte[256],
|
||||
NToPlC = new byte[256];
|
||||
private uint FlagBuf,
|
||||
AvrPlc,
|
||||
AvrPlcB,
|
||||
AvrLn1,
|
||||
AvrLn2,
|
||||
AvrLn3;
|
||||
private int Buf60,
|
||||
NumHuf,
|
||||
StMode,
|
||||
LCount,
|
||||
FlagsCnt;
|
||||
|
||||
private uint Nhfb,
|
||||
Nlzb,
|
||||
MaxDist3;
|
||||
|
||||
private uint Nhfb, Nlzb, MaxDist3;
|
||||
/***************************** Unpack v 1.5 *********************************/
|
||||
|
||||
/***************************** Unpack v 2.0 *********************************/
|
||||
@@ -335,9 +352,11 @@ byte *ReadBufMT;
|
||||
|
||||
private readonly byte[] UnpOldTable20 = new byte[MC20 * 4];
|
||||
private bool UnpAudioBlock;
|
||||
private uint UnpChannels, UnpCurChannel;
|
||||
private uint UnpChannels,
|
||||
UnpCurChannel;
|
||||
|
||||
private int UnpChannelDelta;
|
||||
|
||||
//void CopyString20(uint Length,uint Distance);
|
||||
//bool ReadTables20();
|
||||
//void UnpWriteBuf20();
|
||||
@@ -345,6 +364,7 @@ byte *ReadBufMT;
|
||||
//void ReadLastTables();
|
||||
//byte DecodeAudio(int Delta);
|
||||
private AudioVariables[] AudV = new AudioVariables[4];
|
||||
|
||||
/***************************** Unpack v 2.0 *********************************/
|
||||
|
||||
/***************************** Unpack v 3.0 *********************************/
|
||||
@@ -363,7 +383,8 @@ byte *ReadBufMT;
|
||||
// because we can have a corrupt archive with one algorithm file
|
||||
// followed by another algorithm file with "solid" flag and we do not
|
||||
// want to reuse tables from one algorithm in another.
|
||||
private bool TablesRead2, TablesRead5;
|
||||
private bool TablesRead2,
|
||||
TablesRead5;
|
||||
|
||||
// Virtual machine to execute filters code.
|
||||
/*#if !RarV2017_RAR5ONLY
|
||||
@@ -385,13 +406,13 @@ byte *ReadBufMT;
|
||||
// the data block length if lengths are repeating.
|
||||
private readonly List<int> OldFilterLengths = new List<int>();
|
||||
|
||||
#if RarV2017_RAR_SMP
|
||||
// More than 8 threads are unlikely to provide a noticeable gain
|
||||
// for unpacking, but would use the additional memory.
|
||||
void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);}
|
||||
|
||||
void UnpackDecode(UnpackThreadData &D);
|
||||
#endif
|
||||
/*#if RarV2017_RAR_SMP
|
||||
// More than 8 threads are unlikely to provide a noticeable gain
|
||||
// for unpacking, but would use the additional memory.
|
||||
void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);}
|
||||
|
||||
void UnpackDecode(UnpackThreadData &D);
|
||||
#endif*/
|
||||
|
||||
private size_t MaxWinSize;
|
||||
private size_t MaxWinMask;
|
||||
|
||||
@@ -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)
|
||||
|
||||
32
src/SharpCompress/Crypto/BlockTransformer.cs
Normal file
32
src/SharpCompress/Crypto/BlockTransformer.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace SharpCompress.Crypto;
|
||||
|
||||
internal class BlockTransformer : IDisposable
|
||||
{
|
||||
private ICryptoTransform _transform;
|
||||
|
||||
public BlockTransformer(ICryptoTransform transformer)
|
||||
{
|
||||
_transform = transformer;
|
||||
}
|
||||
|
||||
public byte[] ProcessBlock(ReadOnlySpan<byte> cipherText)
|
||||
{
|
||||
var decryptedBytes = new byte[cipherText.Length];
|
||||
var bytes = _transform.TransformBlock(
|
||||
cipherText.ToArray(),
|
||||
0,
|
||||
cipherText.Length,
|
||||
decryptedBytes,
|
||||
0
|
||||
);
|
||||
|
||||
return decryptedBytes;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
using SharpCompress.Archives.Tar;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -75,7 +75,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti
|
||||
}
|
||||
if (Cancelled)
|
||||
{
|
||||
throw new InvalidOperationException("Reader has been cancelled.");
|
||||
throw new ReaderCancelledException("Reader has been cancelled.");
|
||||
}
|
||||
if (entriesForCurrentReadStream is null)
|
||||
{
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ using SharpCompress.Common.Tar;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Compressors.LZMA;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Readers.Tar;
|
||||
|
||||
|
||||
@@ -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.35.0</VersionPrefix>
|
||||
<AssemblyVersion>0.35.0</AssemblyVersion>
|
||||
<FileVersion>0.35.0</FileVersion>
|
||||
<Authors>Adam Hathcock</Authors>
|
||||
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.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>
|
||||
<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="8.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="ZstdSharp.Port" Version="0.7.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' == 'NETFRAMEWORK' ">
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
|
||||
using SharpCompress.Factories;
|
||||
|
||||
namespace SharpCompress.Writers;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Writers;
|
||||
@@ -10,8 +9,8 @@ public static class WriterFactory
|
||||
{
|
||||
public static IWriter Open(Stream stream, ArchiveType archiveType, WriterOptions writerOptions)
|
||||
{
|
||||
var factory = Factories.Factory.Factories
|
||||
.OfType<IWriterFactory>()
|
||||
var factory = Factories
|
||||
.Factory.Factories.OfType<IWriterFactory>()
|
||||
.FirstOrDefault(item => item.KnownArchiveType == archiveType);
|
||||
|
||||
if (factory != null)
|
||||
|
||||
@@ -298,10 +298,10 @@ public class ArchiveTests : ReaderTests
|
||||
memory.Position = 0;
|
||||
|
||||
for (int y = 0; y < 9; y++)
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
Assert.Equal(x, memory.ReadByte());
|
||||
}
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
Assert.Equal(x, memory.ReadByte());
|
||||
}
|
||||
|
||||
Assert.Equal((int)-1, memory.ReadByte());
|
||||
}
|
||||
|
||||
@@ -22,11 +22,16 @@ public class RarArchiveTests : ArchiveTests
|
||||
() => ReadRarPassword("Rar.encrypted_filesAndHeader.rar", null)
|
||||
);
|
||||
|
||||
/*[Fact]
|
||||
public void Rar5_EncryptedFileAndHeader_Archive()
|
||||
{
|
||||
[Fact]
|
||||
public void Rar5_EncryptedFileAndHeader_Archive() =>
|
||||
ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test");
|
||||
}*/
|
||||
|
||||
[Fact]
|
||||
public void Rar5_EncryptedFileAndHeader_Archive_Err() =>
|
||||
Assert.Throws(
|
||||
typeof(CryptographicException),
|
||||
() => ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "failed")
|
||||
);
|
||||
|
||||
[Fact]
|
||||
public void Rar5_EncryptedFileAndHeader_NoPasswordExceptionTest() =>
|
||||
@@ -39,20 +44,23 @@ public class RarArchiveTests : ArchiveTests
|
||||
public void Rar_EncryptedFileOnly_Archive() =>
|
||||
ReadRarPassword("Rar.encrypted_filesOnly.rar", "test");
|
||||
|
||||
/*[Fact]
|
||||
public void Rar5_EncryptedFileOnly_Archive()
|
||||
{
|
||||
[Fact]
|
||||
public void Rar_EncryptedFileOnly_Archive_Err() =>
|
||||
Assert.Throws(
|
||||
typeof(CryptographicException),
|
||||
() => ReadRarPassword("Rar5.encrypted_filesOnly.rar", "failed")
|
||||
);
|
||||
|
||||
[Fact]
|
||||
public void Rar5_EncryptedFileOnly_Archive() =>
|
||||
ReadRarPassword("Rar5.encrypted_filesOnly.rar", "test");
|
||||
}*/
|
||||
|
||||
[Fact]
|
||||
public void Rar_Encrypted_Archive() => ReadRarPassword("Rar.Encrypted.rar", "test");
|
||||
|
||||
/*[Fact]
|
||||
public void Rar5_Encrypted_Archive()
|
||||
{
|
||||
[Fact]
|
||||
public void Rar5_Encrypted_Archive() =>
|
||||
ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test");
|
||||
}*/
|
||||
|
||||
private void ReadRarPassword(string testArchive, string? password)
|
||||
{
|
||||
|
||||
@@ -284,6 +284,12 @@ public class RarReaderTests : ReaderTests
|
||||
[Fact]
|
||||
public void Rar_Solid_Reader() => Read("Rar.solid.rar", CompressionType.Rar);
|
||||
|
||||
[Fact]
|
||||
public void Rar_Comment_Reader() => Read("Rar.comment.rar", CompressionType.Rar);
|
||||
|
||||
[Fact]
|
||||
public void Rar5_Comment_Reader() => Read("Rar5.comment.rar", CompressionType.Rar);
|
||||
|
||||
[Fact]
|
||||
public void Rar5_Solid_Reader() => Read("Rar5.solid.rar", CompressionType.Rar);
|
||||
|
||||
@@ -332,4 +338,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())
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,81 @@ 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_EOS_FileRead() => ArchiveFileRead("7Zip.eos.7z");
|
||||
|
||||
[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")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net7.0;net462</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
||||
<AssemblyName>SharpCompress.Test</AssemblyName>
|
||||
<PackageId>SharpCompress.Test</PackageId>
|
||||
</PropertyGroup>
|
||||
@@ -8,13 +8,13 @@
|
||||
<ProjectReference Include="..\..\src\SharpCompress\SharpCompress.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="6.10.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit" Version="2.6.3" />
|
||||
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' != 'NETFRAMEWORK' ">
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Writers;
|
||||
using Xunit;
|
||||
using System.Text;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Writers.Tar;
|
||||
using SharpCompress.Readers.Tar;
|
||||
using SharpCompress.Writers;
|
||||
using SharpCompress.Writers.Tar;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Tar;
|
||||
|
||||
|
||||
@@ -56,6 +56,9 @@ public class TarReaderTests : ReaderTests
|
||||
[Fact]
|
||||
public void Tar_Xz_Reader() => Read("Tar.tar.xz", CompressionType.Xz);
|
||||
|
||||
[Fact]
|
||||
public void Tar_GZip_OldGnu_Reader() => Read("Tar.oldgnu.tar.gz", CompressionType.GZip);
|
||||
|
||||
[Fact]
|
||||
public void Tar_BZip2_Entry_Stream()
|
||||
{
|
||||
@@ -183,6 +186,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()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz.Filters;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Xz.Filters;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Xz;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Xz;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Xz;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Text;
|
||||
|
||||
using SharpCompress.Common;
|
||||
using Xunit;
|
||||
|
||||
|
||||
BIN
tests/TestArchives/Archives/7Zip.ARM.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.ARM.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ARMT.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.ARMT.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.BCJ.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.BCJ.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.BCJ2.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.BCJ2.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.Filters.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.Filters.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.IA64.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.IA64.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.PPC.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.PPC.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.SPARC.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.SPARC.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.Tar.tar
Normal file
BIN
tests/TestArchives/Archives/7Zip.Tar.tar
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.Tar.tar.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.Tar.tar.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ZSTD.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.ZSTD.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.001
Normal file
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.001
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.002
Normal file
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.002
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.003
Normal file
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.003
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.004
Normal file
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.004
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.005
Normal file
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.005
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.006
Normal file
BIN
tests/TestArchives/Archives/7Zip.ZSTD.Split.7z.006
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/7Zip.eos.7z
Normal file
BIN
tests/TestArchives/Archives/7Zip.eos.7z
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/Rar.comment.rar
Normal file
BIN
tests/TestArchives/Archives/Rar.comment.rar
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/Rar5.comment.rar
Normal file
BIN
tests/TestArchives/Archives/Rar5.comment.rar
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/Tar.oldgnu.tar.gz
Normal file
BIN
tests/TestArchives/Archives/Tar.oldgnu.tar.gz
Normal file
Binary file not shown.
BIN
tests/TestArchives/Archives/WinZip27_ZSTD.zipx
Normal file
BIN
tests/TestArchives/Archives/WinZip27_ZSTD.zipx
Normal file
Binary file not shown.
Reference in New Issue
Block a user