mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 13:34:59 +00:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a28d686eb9 | ||
|
|
ac525a8ec2 | ||
|
|
52c44befa2 | ||
|
|
c64251c341 | ||
|
|
bdc57d3c33 | ||
|
|
7edc437df2 | ||
|
|
57e4395e7d | ||
|
|
ee17dca9e5 | ||
|
|
e9f3add5b9 | ||
|
|
faf1a9f7e4 | ||
|
|
5357bd07c7 | ||
|
|
8c0e2cbd25 | ||
|
|
674f3b4f28 | ||
|
|
6e42e00974 | ||
|
|
8598885258 | ||
|
|
669e40d53c | ||
|
|
1adcce6c62 | ||
|
|
147be6e6e1 | ||
|
|
5879999094 | ||
|
|
477a30cf5b | ||
|
|
2fec03e1ac | ||
|
|
9a17449a02 | ||
|
|
087a6aad8c | ||
|
|
e243a8e88f | ||
|
|
b57df8026a | ||
|
|
a1d45b44cd | ||
|
|
e47e1d220a | ||
|
|
0129a933df | ||
|
|
fa241bb0d7 | ||
|
|
d8804ae108 | ||
|
|
8090d269e7 | ||
|
|
b0101f20c5 | ||
|
|
dd48e4299a | ||
|
|
c61ee0c24f | ||
|
|
9576867c34 | ||
|
|
4426a24298 | ||
|
|
3b43c1e413 | ||
|
|
aa6575c8f9 | ||
|
|
0268713960 | ||
|
|
f36167d425 | ||
|
|
33ffcb9308 | ||
|
|
a649c25a91 | ||
|
|
fa1e773960 | ||
|
|
62f7238796 | ||
|
|
d4ccf73340 | ||
|
|
5ddb0f96bc | ||
|
|
75a6db8f4c | ||
|
|
ae5635319b | ||
|
|
98ed3080d0 | ||
|
|
c618eacad4 | ||
|
|
3b11e6ef97 | ||
|
|
40af9359db | ||
|
|
d6bf9dae42 | ||
|
|
13917941ff | ||
|
|
28f04329ae | ||
|
|
404a6b231d | ||
|
|
184596da3c | ||
|
|
f00f393687 | ||
|
|
cbbfb89619 | ||
|
|
6a5cf11dd0 | ||
|
|
fc1d0a0464 | ||
|
|
74af1759eb | ||
|
|
ee3162ad71 | ||
|
|
4357165163 | ||
|
|
6973436b94 | ||
|
|
7750ed7106 | ||
|
|
773158e9d8 | ||
|
|
4db615597d | ||
|
|
6bdf2365fc | ||
|
|
3b2e273832 | ||
|
|
43c839eb89 |
12
.config/dotnet-tools.json
Normal file
12
.config/dotnet-tools.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-format": {
|
||||
"version": "4.1.131201",
|
||||
"commands": [
|
||||
"dotnet-format"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
2
.github/workflows/dotnetcore.yml
vendored
2
.github/workflows/dotnetcore.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 3.1.302
|
||||
dotnet-version: 5.0.101
|
||||
- run: dotnet run -p build/build.csproj
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SharpCompress
|
||||
|
||||
SharpCompress is a compression library in pure C# for .NET Standard 2.0, 2.1 and NET 4.6 that can unrar, un7zip, unzip, untar unbzip2, ungzip, unlzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip/lzip are implemented.
|
||||
SharpCompress is a compression library in pure C# for .NET Standard 2.0, 2.1, .NET Core 3.1 and .NET 5.0 that can unrar, un7zip, unzip, untar unbzip2, ungzip, unlzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip/lzip are implemented.
|
||||
|
||||
The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream).
|
||||
|
||||
|
||||
@@ -9,10 +9,11 @@ using static SimpleExec.Command;
|
||||
class Program
|
||||
{
|
||||
private const string Clean = "clean";
|
||||
private const string Format = "format";
|
||||
private const string Build = "build";
|
||||
private const string Test = "test";
|
||||
private const string Publish = "publish";
|
||||
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Target(Clean,
|
||||
@@ -39,30 +40,36 @@ class Program
|
||||
}
|
||||
});
|
||||
|
||||
Target(Build, ForEach("net46", "netstandard2.0", "netstandard2.1"),
|
||||
Target(Format, () =>
|
||||
{
|
||||
Run("dotnet", "tool restore");
|
||||
Run("dotnet", "format --check");
|
||||
});
|
||||
|
||||
Target(Build, DependsOn(Format),
|
||||
framework =>
|
||||
{
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && framework == "net46")
|
||||
{
|
||||
return;
|
||||
}
|
||||
Run("dotnet", "build src/SharpCompress/SharpCompress.csproj -c Release");
|
||||
});
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && framework == "net46")
|
||||
{
|
||||
return;
|
||||
}
|
||||
Run("dotnet", "build src/SharpCompress/SharpCompress.csproj -c Release");
|
||||
});
|
||||
|
||||
Target(Test, DependsOn(Build), ForEach("netcoreapp3.1"),
|
||||
framework =>
|
||||
{
|
||||
IEnumerable<string> GetFiles(string d)
|
||||
{
|
||||
return Glob.Files(".", d);
|
||||
}
|
||||
Target(Test, DependsOn(Build), ForEach("net5.0"),
|
||||
framework =>
|
||||
{
|
||||
IEnumerable<string> GetFiles(string d)
|
||||
{
|
||||
return Glob.Files(".", d);
|
||||
}
|
||||
|
||||
foreach (var file in GetFiles("**/*.Test.csproj"))
|
||||
{
|
||||
Run("dotnet", $"test {file} -c Release -f {framework}");
|
||||
}
|
||||
});
|
||||
|
||||
foreach (var file in GetFiles("**/*.Test.csproj"))
|
||||
{
|
||||
Run("dotnet", $"test {file} -c Release -f {framework}");
|
||||
}
|
||||
});
|
||||
|
||||
Target(Publish, DependsOn(Test),
|
||||
() =>
|
||||
{
|
||||
@@ -70,7 +77,7 @@ class Program
|
||||
});
|
||||
|
||||
Target("default", DependsOn(Publish), () => Console.WriteLine("Done!"));
|
||||
|
||||
|
||||
RunTargetsAndExit(args);
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Bullseye" Version="3.3.0" />
|
||||
<PackageReference Include="Glob" Version="1.1.7" />
|
||||
<PackageReference Include="SimpleExec" Version="6.2.0" />
|
||||
<PackageReference Include="Bullseye" Version="3.6.0" />
|
||||
<PackageReference Include="Glob" Version="1.1.8" />
|
||||
<PackageReference Include="SimpleExec" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "3.1.302"
|
||||
"version": "5.0.101"
|
||||
}
|
||||
}
|
||||
285
src/SharpCompress/Algorithms/Alder32.cs
Normal file
285
src/SharpCompress/Algorithms/Alder32.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
// Copyright (c) Six Labors and contributors.
|
||||
// Licensed under the GNU Affero General Public License, Version 3.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
#endif
|
||||
|
||||
namespace SharpCompress.Algorithms
|
||||
{
|
||||
/// <summary>
|
||||
/// Calculates the 32 bit Adler checksum of a given buffer according to
|
||||
/// RFC 1950. ZLIB Compressed Data Format Specification version 3.3)
|
||||
/// </summary>
|
||||
internal static class Adler32
|
||||
{
|
||||
/// <summary>
|
||||
/// The default initial seed value of a Adler32 checksum calculation.
|
||||
/// </summary>
|
||||
public const uint SeedValue = 1U;
|
||||
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
private const int MinBufferSize = 64;
|
||||
#endif
|
||||
|
||||
// Largest prime smaller than 65536
|
||||
private const uint BASE = 65521;
|
||||
|
||||
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
||||
private const uint NMAX = 5552;
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Adler32 checksum with the bytes taken from the span.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The readonly span of bytes.</param>
|
||||
/// <returns>The <see cref="uint"/>.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static uint Calculate(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
return Calculate(SeedValue, buffer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Adler32 checksum with the bytes taken from the span and seed.
|
||||
/// </summary>
|
||||
/// <param name="adler">The input Adler32 value.</param>
|
||||
/// <param name="buffer">The readonly span of bytes.</param>
|
||||
/// <returns>The <see cref="uint"/>.</returns>
|
||||
public static uint Calculate(uint adler, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
if (buffer.IsEmpty)
|
||||
{
|
||||
return SeedValue;
|
||||
}
|
||||
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
if (Sse3.IsSupported && buffer.Length >= MinBufferSize)
|
||||
{
|
||||
return CalculateSse(adler, buffer);
|
||||
}
|
||||
|
||||
return CalculateScalar(adler, buffer);
|
||||
#else
|
||||
return CalculateScalar(adler, buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Based on https://github.com/chromium/chromium/blob/master/third_party/zlib/adler32_simd.c
|
||||
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
|
||||
private static unsafe uint CalculateSse(uint adler, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
uint s1 = adler & 0xFFFF;
|
||||
uint s2 = (adler >> 16) & 0xFFFF;
|
||||
|
||||
// Process the data in blocks.
|
||||
const int BLOCK_SIZE = 1 << 5;
|
||||
|
||||
uint length = (uint)buffer.Length;
|
||||
uint blocks = length / BLOCK_SIZE;
|
||||
length -= blocks * BLOCK_SIZE;
|
||||
|
||||
int index = 0;
|
||||
fixed (byte* bufferPtr = &buffer[0])
|
||||
{
|
||||
index += (int)blocks * BLOCK_SIZE;
|
||||
var localBufferPtr = bufferPtr;
|
||||
|
||||
// _mm_setr_epi8 on x86
|
||||
var tap1 = Vector128.Create(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17);
|
||||
var tap2 = Vector128.Create(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
|
||||
Vector128<byte> zero = Vector128<byte>.Zero;
|
||||
var ones = Vector128.Create((short)1);
|
||||
|
||||
while (blocks > 0)
|
||||
{
|
||||
uint n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */
|
||||
if (n > blocks)
|
||||
{
|
||||
n = blocks;
|
||||
}
|
||||
|
||||
blocks -= n;
|
||||
|
||||
// Process n blocks of data. At most NMAX data bytes can be
|
||||
// processed before s2 must be reduced modulo BASE.
|
||||
Vector128<int> v_ps = Vector128.CreateScalar(s1 * n).AsInt32();
|
||||
Vector128<int> v_s2 = Vector128.CreateScalar(s2).AsInt32();
|
||||
Vector128<int> v_s1 = Vector128<int>.Zero;
|
||||
|
||||
do
|
||||
{
|
||||
// Load 32 input bytes.
|
||||
Vector128<byte> bytes1 = Sse3.LoadDquVector128(localBufferPtr);
|
||||
Vector128<byte> bytes2 = Sse3.LoadDquVector128(localBufferPtr + 16);
|
||||
|
||||
// Add previous block byte sum to v_ps.
|
||||
v_ps = Sse2.Add(v_ps, v_s1);
|
||||
|
||||
// Horizontally add the bytes for s1, multiply-adds the
|
||||
// bytes by [ 32, 31, 30, ... ] for s2.
|
||||
v_s1 = Sse2.Add(v_s1, Sse2.SumAbsoluteDifferences(bytes1, zero).AsInt32());
|
||||
Vector128<short> mad1 = Ssse3.MultiplyAddAdjacent(bytes1, tap1);
|
||||
v_s2 = Sse2.Add(v_s2, Sse2.MultiplyAddAdjacent(mad1, ones));
|
||||
|
||||
v_s1 = Sse2.Add(v_s1, Sse2.SumAbsoluteDifferences(bytes2, zero).AsInt32());
|
||||
Vector128<short> mad2 = Ssse3.MultiplyAddAdjacent(bytes2, tap2);
|
||||
v_s2 = Sse2.Add(v_s2, Sse2.MultiplyAddAdjacent(mad2, ones));
|
||||
|
||||
localBufferPtr += BLOCK_SIZE;
|
||||
}
|
||||
while (--n > 0);
|
||||
|
||||
v_s2 = Sse2.Add(v_s2, Sse2.ShiftLeftLogical(v_ps, 5));
|
||||
|
||||
// Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
|
||||
const byte S2301 = 0b1011_0001; // A B C D -> B A D C
|
||||
const byte S1032 = 0b0100_1110; // A B C D -> C D A B
|
||||
|
||||
v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, S2301));
|
||||
v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, S1032));
|
||||
|
||||
s1 += (uint)v_s1.ToScalar();
|
||||
|
||||
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S2301));
|
||||
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S1032));
|
||||
|
||||
s2 = (uint)v_s2.ToScalar();
|
||||
|
||||
// Reduce.
|
||||
s1 %= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
}
|
||||
|
||||
ref byte bufferRef = ref MemoryMarshal.GetReference(buffer);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
if (length >= 16)
|
||||
{
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
length -= 16;
|
||||
}
|
||||
|
||||
while (length-- > 0)
|
||||
{
|
||||
s2 += s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
}
|
||||
|
||||
if (s1 >= BASE)
|
||||
{
|
||||
s1 -= BASE;
|
||||
}
|
||||
|
||||
s2 %= BASE;
|
||||
}
|
||||
|
||||
return s1 | (s2 << 16);
|
||||
}
|
||||
#endif
|
||||
|
||||
private static uint CalculateScalar(uint adler, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
uint s1 = adler & 0xFFFF;
|
||||
uint s2 = (adler >> 16) & 0xFFFF;
|
||||
uint k;
|
||||
|
||||
ref byte bufferRef = ref MemoryMarshal.GetReference<byte>(buffer);
|
||||
uint length = (uint)buffer.Length;
|
||||
int index = 0;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
k = length < NMAX ? length : NMAX;
|
||||
length -= k;
|
||||
|
||||
while (k >= 16)
|
||||
{
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
k -= 16;
|
||||
}
|
||||
|
||||
if (k != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
s1 += Unsafe.Add(ref bufferRef, index++);
|
||||
s2 += s1;
|
||||
}
|
||||
while (--k != 0);
|
||||
}
|
||||
|
||||
s1 %= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
|
||||
return (s2 << 16) | s1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,29 +81,29 @@ namespace SharpCompress.Archives
|
||||
/// <summary>
|
||||
/// Returns an ReadOnlyCollection of all the RarArchiveEntries across the one or many parts of the RarArchive.
|
||||
/// </summary>
|
||||
public virtual ICollection<TEntry> Entries { get { return lazyEntries; } }
|
||||
public virtual ICollection<TEntry> Entries => lazyEntries;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an ReadOnlyCollection of all the RarArchiveVolumes across the one or many parts of the RarArchive.
|
||||
/// </summary>
|
||||
public ICollection<TVolume> Volumes { get { return lazyVolumes; } }
|
||||
public ICollection<TVolume> Volumes => lazyVolumes;
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the files compressed in the archive.
|
||||
/// </summary>
|
||||
public virtual long TotalSize { get { return Entries.Aggregate(0L, (total, cf) => total + cf.CompressedSize); } }
|
||||
public virtual long TotalSize => Entries.Aggregate(0L, (total, cf) => total + cf.CompressedSize);
|
||||
|
||||
/// <summary>
|
||||
/// The total size of the files as uncompressed in the archive.
|
||||
/// </summary>
|
||||
public virtual long TotalUncompressSize { get { return Entries.Aggregate(0L, (total, cf) => total + cf.Size); } }
|
||||
public virtual long TotalUncompressSize => Entries.Aggregate(0L, (total, cf) => total + cf.Size);
|
||||
|
||||
protected abstract IEnumerable<TVolume> LoadVolumes(IEnumerable<Stream> streams);
|
||||
protected abstract IEnumerable<TEntry> LoadEntries(IEnumerable<TVolume> volumes);
|
||||
|
||||
IEnumerable<IArchiveEntry> IArchive.Entries { get { return Entries.Cast<IArchiveEntry>(); } }
|
||||
IEnumerable<IArchiveEntry> IArchive.Entries => Entries.Cast<IArchiveEntry>();
|
||||
|
||||
IEnumerable<IVolume> IArchive.Volumes { get { return lazyVolumes.Cast<IVolume>(); } }
|
||||
IEnumerable<IVolume> IArchive.Volumes => lazyVolumes.Cast<IVolume>();
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
@@ -132,9 +132,9 @@ namespace SharpCompress.Archives
|
||||
void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
|
||||
{
|
||||
FilePartExtractionBegin?.Invoke(this, new FilePartExtractionBeginEventArgs(
|
||||
compressedSize : compressedSize,
|
||||
size : size,
|
||||
name : name
|
||||
compressedSize: compressedSize,
|
||||
size: size,
|
||||
name: name
|
||||
));
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace SharpCompress.Archives
|
||||
/// <summary>
|
||||
/// Archive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files).
|
||||
/// </summary>
|
||||
public virtual bool IsSolid { get { return false; } }
|
||||
public virtual bool IsSolid => false;
|
||||
|
||||
/// <summary>
|
||||
/// The archive can find all the parts of the archive needed to fully extract the archive. This forces the parsing of the entire archive.
|
||||
|
||||
@@ -12,11 +12,28 @@ namespace SharpCompress.Archives
|
||||
where TEntry : IArchiveEntry
|
||||
where TVolume : IVolume
|
||||
{
|
||||
private class RebuildPauseDisposable : IDisposable
|
||||
{
|
||||
private readonly AbstractWritableArchive<TEntry, TVolume> archive;
|
||||
|
||||
public RebuildPauseDisposable(AbstractWritableArchive<TEntry, TVolume> archive)
|
||||
{
|
||||
this.archive = archive;
|
||||
archive.pauseRebuilding = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
archive.pauseRebuilding = false;
|
||||
archive.RebuildModifiedCollection();
|
||||
}
|
||||
}
|
||||
private readonly List<TEntry> newEntries = new List<TEntry>();
|
||||
private readonly List<TEntry> removedEntries = new List<TEntry>();
|
||||
|
||||
private readonly List<TEntry> modifiedEntries = new List<TEntry>();
|
||||
private bool hasModifications;
|
||||
private bool pauseRebuilding;
|
||||
|
||||
internal AbstractWritableArchive(ArchiveType type)
|
||||
: base(type)
|
||||
@@ -45,8 +62,17 @@ namespace SharpCompress.Archives
|
||||
}
|
||||
}
|
||||
|
||||
public IDisposable PauseEntryRebuilding()
|
||||
{
|
||||
return new RebuildPauseDisposable(this);
|
||||
}
|
||||
|
||||
private void RebuildModifiedCollection()
|
||||
{
|
||||
if (pauseRebuilding)
|
||||
{
|
||||
return;
|
||||
}
|
||||
hasModifications = true;
|
||||
newEntries.RemoveAll(v => removedEntries.Contains(v));
|
||||
modifiedEntries.Clear();
|
||||
@@ -83,8 +109,7 @@ namespace SharpCompress.Archives
|
||||
public TEntry AddEntry(string key, Stream source, bool closeStream,
|
||||
long size = 0, DateTime? modified = null)
|
||||
{
|
||||
if (key.StartsWith("/")
|
||||
|| key.StartsWith("\\"))
|
||||
if (key.Length > 0 && key[0] is '/' or '\\')
|
||||
{
|
||||
key = key.Substring(1);
|
||||
}
|
||||
@@ -103,7 +128,7 @@ namespace SharpCompress.Archives
|
||||
foreach (var path in Entries.Select(x => x.Key))
|
||||
{
|
||||
var p = path.Replace('/', '\\');
|
||||
if (p.StartsWith("\\"))
|
||||
if (p.Length > 0 && p[0] == '\\')
|
||||
{
|
||||
p = p.Substring(1);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives
|
||||
{
|
||||
public class ArchiveFactory
|
||||
public static class ArchiveFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens an Archive for random access
|
||||
@@ -25,7 +25,7 @@ namespace SharpCompress.Archives
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
readerOptions = readerOptions ?? new ReaderOptions();
|
||||
readerOptions ??= new ReaderOptions();
|
||||
if (ZipArchive.IsZipFile(stream, null))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
@@ -60,25 +60,13 @@ namespace SharpCompress.Archives
|
||||
|
||||
public static IWritableArchive Create(ArchiveType type)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case ArchiveType.Zip:
|
||||
{
|
||||
return ZipArchive.Create();
|
||||
}
|
||||
case ArchiveType.Tar:
|
||||
{
|
||||
return TarArchive.Create();
|
||||
}
|
||||
case ArchiveType.GZip:
|
||||
{
|
||||
return GZipArchive.Create();
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new NotSupportedException("Cannot create Archives of type: " + type);
|
||||
}
|
||||
}
|
||||
ArchiveType.Zip => ZipArchive.Create(),
|
||||
ArchiveType.Tar => TarArchive.Create(),
|
||||
ArchiveType.GZip => GZipArchive.Create(),
|
||||
_ => throw new NotSupportedException("Cannot create Archives of type: " + type)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -100,35 +88,34 @@ namespace SharpCompress.Archives
|
||||
public static IArchive Open(FileInfo fileInfo, ReaderOptions? options = null)
|
||||
{
|
||||
fileInfo.CheckNotNull(nameof(fileInfo));
|
||||
options = options ?? new ReaderOptions { LeaveStreamOpen = false };
|
||||
using (var stream = fileInfo.OpenRead())
|
||||
options ??= new ReaderOptions { LeaveStreamOpen = false };
|
||||
|
||||
using var stream = fileInfo.OpenRead();
|
||||
if (ZipArchive.IsZipFile(stream, null))
|
||||
{
|
||||
if (ZipArchive.IsZipFile(stream, null))
|
||||
{
|
||||
return ZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (SevenZipArchive.IsSevenZipFile(stream))
|
||||
{
|
||||
return SevenZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (GZipArchive.IsGZipFile(stream))
|
||||
{
|
||||
return GZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (RarArchive.IsRarFile(stream, options))
|
||||
{
|
||||
return RarArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (TarArchive.IsTarFile(stream))
|
||||
{
|
||||
return TarArchive.Open(fileInfo, options);
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
|
||||
return ZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (SevenZipArchive.IsSevenZipFile(stream))
|
||||
{
|
||||
return SevenZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (GZipArchive.IsGZipFile(stream))
|
||||
{
|
||||
return GZipArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (RarArchive.IsRarFile(stream, options))
|
||||
{
|
||||
return RarArchive.Open(fileInfo, options);
|
||||
}
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
if (TarArchive.IsTarFile(stream))
|
||||
{
|
||||
return TarArchive.Open(fileInfo, options);
|
||||
}
|
||||
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -137,12 +124,10 @@ namespace SharpCompress.Archives
|
||||
public static void WriteToDirectory(string sourceArchive, string destinationDirectory,
|
||||
ExtractionOptions? options = null)
|
||||
{
|
||||
using (IArchive archive = Open(sourceArchive))
|
||||
using IArchive archive = Open(sourceArchive);
|
||||
foreach (IArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
foreach (IArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
entry.WriteToDirectory(destinationDirectory, options);
|
||||
}
|
||||
entry.WriteToDirectory(destinationDirectory, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,10 +77,9 @@ namespace SharpCompress.Archives.GZip
|
||||
{
|
||||
return false;
|
||||
}
|
||||
using (Stream stream = fileInfo.OpenRead())
|
||||
{
|
||||
return IsGZipFile(stream);
|
||||
}
|
||||
|
||||
using Stream stream = fileInfo.OpenRead();
|
||||
return IsGZipFile(stream);
|
||||
}
|
||||
|
||||
public void SaveTo(string filePath)
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace SharpCompress.Archives
|
||||
}
|
||||
streamListener.FireEntryExtractionEnd(archiveEntry);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Extract to specific directory, retaining filename
|
||||
/// </summary>
|
||||
@@ -45,11 +45,11 @@ namespace SharpCompress.Archives
|
||||
/// <summary>
|
||||
/// Extract to specific file
|
||||
/// </summary>
|
||||
public static void WriteToFile(this IArchiveEntry entry,
|
||||
public static void WriteToFile(this IArchiveEntry entry,
|
||||
string destinationFileName,
|
||||
ExtractionOptions? options = null)
|
||||
{
|
||||
|
||||
|
||||
ExtractionMethods.WriteEntryToFile(entry, destinationFileName, options,
|
||||
(x, fm) =>
|
||||
{
|
||||
|
||||
@@ -11,5 +11,11 @@ namespace SharpCompress.Archives
|
||||
IArchiveEntry AddEntry(string key, Stream source, bool closeStream, long size = 0, DateTime? modified = null);
|
||||
|
||||
void SaveTo(Stream stream, WriterOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Use this to pause entry rebuilding when adding large collections of entries. Dispose when complete. A using statement is recommended.
|
||||
/// </summary>
|
||||
/// <returns>IDisposeable to resume entry rebuilding</returns>
|
||||
IDisposable PauseEntryRebuilding();
|
||||
}
|
||||
}
|
||||
@@ -35,11 +35,14 @@ namespace SharpCompress.Archives
|
||||
this IWritableArchive writableArchive,
|
||||
string filePath, string searchPattern = "*.*", SearchOption searchOption = SearchOption.AllDirectories)
|
||||
{
|
||||
foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption))
|
||||
using (writableArchive.PauseEntryRebuilding())
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length,
|
||||
fileInfo.LastWriteTime);
|
||||
foreach (var path in Directory.EnumerateFiles(filePath, searchPattern, searchOption))
|
||||
{
|
||||
var fileInfo = new FileInfo(path);
|
||||
writableArchive.AddEntry(path.Substring(filePath.Length), fileInfo.OpenRead(), true, fileInfo.Length,
|
||||
fileInfo.LastWriteTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static IArchiveEntry AddEntry(this IWritableArchive writableArchive, string key, FileInfo fileInfo)
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace SharpCompress.Archives.Rar
|
||||
return IsRarFile(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool IsRarFile(Stream stream, ReaderOptions? options = null)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -61,16 +61,16 @@ namespace SharpCompress.Archives.Rar
|
||||
{
|
||||
return new RarStream(archive.UnpackV1.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
|
||||
}
|
||||
|
||||
|
||||
return new RarStream(archive.UnpackV2017.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
|
||||
}
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
get
|
||||
{
|
||||
return parts.Select(fp => fp.FileHeader).Any(fh => !fh.IsSplitAfter);
|
||||
}
|
||||
public bool IsComplete
|
||||
{
|
||||
get
|
||||
{
|
||||
return parts.Select(fp => fp.FileHeader).Any(fh => !fh.IsSplitAfter);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckIncomplete()
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace SharpCompress.Archives.Rar
|
||||
yield return part;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal static IEnumerable<RarVolume> GetParts(FileInfo fileInfo, ReaderOptions options)
|
||||
{
|
||||
FileInfoRarArchiveVolume part = new FileInfoRarArchiveVolume(fileInfo, options);
|
||||
@@ -68,7 +68,7 @@ namespace SharpCompress.Archives.Rar
|
||||
// .rar, .r00, .r01, ...
|
||||
string extension = currentFileInfo.Extension;
|
||||
|
||||
StringBuilder buffer = new StringBuilder(currentFileInfo.FullName.Length);
|
||||
var buffer = new StringBuilder(currentFileInfo.FullName.Length);
|
||||
buffer.Append(currentFileInfo.FullName.Substring(0,
|
||||
currentFileInfo.FullName.Length - extension.Length));
|
||||
if (string.Compare(extension, ".rar", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
@@ -77,8 +77,7 @@ namespace SharpCompress.Archives.Rar
|
||||
}
|
||||
else
|
||||
{
|
||||
int num = 0;
|
||||
if (int.TryParse(extension.Substring(2, 2), out num))
|
||||
if (int.TryParse(extension.Substring(2, 2), out int num))
|
||||
{
|
||||
num++;
|
||||
buffer.Append(".r");
|
||||
@@ -111,12 +110,11 @@ namespace SharpCompress.Archives.Rar
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(currentFileInfo.FullName.Length);
|
||||
buffer.Append(currentFileInfo.FullName, 0, startIndex);
|
||||
int num = 0;
|
||||
string numString = currentFileInfo.FullName.Substring(startIndex + 5,
|
||||
currentFileInfo.FullName.IndexOf('.', startIndex + 5) -
|
||||
startIndex - 5);
|
||||
buffer.Append(".part");
|
||||
if (int.TryParse(numString, out num))
|
||||
if (int.TryParse(numString, out int num))
|
||||
{
|
||||
num++;
|
||||
for (int i = 0; i < numString.Length - num.ToString().Length; i++)
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace SharpCompress.Archives.SevenZip
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> SIGNATURE => new byte[] {(byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
private static ReadOnlySpan<byte> SIGNATURE => new byte[] { (byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C };
|
||||
|
||||
private static bool SignatureMatch(Stream stream)
|
||||
{
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace SharpCompress.Archives.Tar
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace SharpCompress.Archives.Zip
|
||||
/// if the compression method is set to deflate
|
||||
/// </summary>
|
||||
public CompressionLevel DeflateCompressionLevel { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor expects a filepath to an existing file.
|
||||
/// </summary>
|
||||
@@ -57,7 +57,7 @@ namespace SharpCompress.Archives.Zip
|
||||
stream.CheckNotNull(nameof(stream));
|
||||
return new ZipArchive(stream, readerOptions ?? new ReaderOptions());
|
||||
}
|
||||
|
||||
|
||||
public static bool IsZipFile(string filePath, string? password = null)
|
||||
{
|
||||
return IsZipFile(new FileInfo(filePath), password);
|
||||
@@ -80,8 +80,7 @@ namespace SharpCompress.Archives.Zip
|
||||
StreamingZipHeaderFactory headerFactory = new StreamingZipHeaderFactory(password, new ArchiveEncoding());
|
||||
try
|
||||
{
|
||||
ZipHeader header =
|
||||
headerFactory.ReadStreamHeader(stream).FirstOrDefault(x => x.ZipHeaderType != ZipHeaderType.Split);
|
||||
ZipHeader? header = headerFactory.ReadStreamHeader(stream).FirstOrDefault(x => x.ZipHeaderType != ZipHeaderType.Split);
|
||||
if (header is null)
|
||||
{
|
||||
return false;
|
||||
@@ -97,7 +96,7 @@ namespace SharpCompress.Archives.Zip
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with a FileInfo object to an existing file.
|
||||
/// </summary>
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace SharpCompress.Common
|
||||
Password = password;
|
||||
}
|
||||
|
||||
#if NETSTANDARD1_3 || NETSTANDARD2_0 || NETSTANDARD2_1
|
||||
#if !NET461
|
||||
static ArchiveEncoding()
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
|
||||
@@ -47,7 +47,8 @@ namespace SharpCompress.Common
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void Flush() {
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Length => _stream.Length;
|
||||
|
||||
@@ -8,9 +8,9 @@ namespace SharpCompress.Common
|
||||
/// <summary>
|
||||
/// Extract to specific directory, retaining filename
|
||||
/// </summary>
|
||||
public static void WriteEntryToDirectory(IEntry entry,
|
||||
public static void WriteEntryToDirectory(IEntry entry,
|
||||
string destinationDirectory,
|
||||
ExtractionOptions? options,
|
||||
ExtractionOptions? options,
|
||||
Action<string, ExtractionOptions?> write)
|
||||
{
|
||||
string destinationFileName;
|
||||
@@ -18,20 +18,18 @@ namespace SharpCompress.Common
|
||||
string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory);
|
||||
|
||||
options ??= new ExtractionOptions()
|
||||
{
|
||||
Overwrite = true
|
||||
};
|
||||
{
|
||||
Overwrite = true
|
||||
};
|
||||
|
||||
if (options.ExtractFullPath)
|
||||
{
|
||||
string folder = Path.GetDirectoryName(entry.Key);
|
||||
string destdir = Path.GetFullPath(
|
||||
Path.Combine(fullDestinationDirectoryPath, folder)
|
||||
);
|
||||
string folder = Path.GetDirectoryName(entry.Key)!;
|
||||
string destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder));
|
||||
|
||||
if (!Directory.Exists(destdir))
|
||||
{
|
||||
if (!destdir.StartsWith(fullDestinationDirectoryPath))
|
||||
if (!destdir.StartsWith(fullDestinationDirectoryPath, StringComparison.Ordinal))
|
||||
{
|
||||
throw new ExtractionException("Entry is trying to create a directory outside of the destination directory.");
|
||||
}
|
||||
@@ -41,7 +39,7 @@ namespace SharpCompress.Common
|
||||
destinationFileName = Path.Combine(destdir, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
destinationFileName = Path.Combine(fullDestinationDirectoryPath, file);
|
||||
|
||||
}
|
||||
@@ -50,7 +48,7 @@ namespace SharpCompress.Common
|
||||
{
|
||||
destinationFileName = Path.GetFullPath(destinationFileName);
|
||||
|
||||
if (!destinationFileName.StartsWith(fullDestinationDirectoryPath))
|
||||
if (!destinationFileName.StartsWith(fullDestinationDirectoryPath, StringComparison.Ordinal))
|
||||
{
|
||||
throw new ExtractionException("Entry is trying to write a file outside of the destination directory.");
|
||||
}
|
||||
@@ -61,7 +59,7 @@ namespace SharpCompress.Common
|
||||
Directory.CreateDirectory(destinationFileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void WriteEntryToFile(IEntry entry, string destinationFileName,
|
||||
ExtractionOptions? options,
|
||||
Action<string, FileMode> openAndWrite)
|
||||
@@ -78,9 +76,9 @@ namespace SharpCompress.Common
|
||||
{
|
||||
FileMode fm = FileMode.Create;
|
||||
options ??= new ExtractionOptions()
|
||||
{
|
||||
Overwrite = true
|
||||
};
|
||||
{
|
||||
Overwrite = true
|
||||
};
|
||||
|
||||
if (!options.Overwrite)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace SharpCompress.Common
|
||||
/// <summary>
|
||||
/// overwrite target if it exists
|
||||
/// </summary>
|
||||
public bool Overwrite {get; set; }
|
||||
public bool Overwrite { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// extract with internal directory structure
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace SharpCompress.Common.GZip
|
||||
|
||||
public override CompressionType CompressionType => CompressionType.GZip;
|
||||
|
||||
public override long Crc => 0;
|
||||
public override long Crc => _filePart.Crc ?? 0;
|
||||
|
||||
public override string Key => _filePart.FilePartName;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace SharpCompress.Common.GZip
|
||||
|
||||
public override long CompressedSize => 0;
|
||||
|
||||
public override long Size => 0;
|
||||
public override long Size => _filePart.UncompressedSize ?? 0;
|
||||
|
||||
public override DateTime? LastModifiedTime => _filePart.DateModified;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ using SharpCompress.Compressors.Deflate;
|
||||
|
||||
namespace SharpCompress.Common.GZip
|
||||
{
|
||||
internal class GZipFilePart : FilePart
|
||||
internal sealed class GZipFilePart : FilePart
|
||||
{
|
||||
private string? _name;
|
||||
private readonly Stream _stream;
|
||||
@@ -16,14 +16,23 @@ namespace SharpCompress.Common.GZip
|
||||
internal GZipFilePart(Stream stream, ArchiveEncoding archiveEncoding)
|
||||
: base(archiveEncoding)
|
||||
{
|
||||
ReadAndValidateGzipHeader(stream);
|
||||
EntryStartPosition = stream.Position;
|
||||
_stream = stream;
|
||||
ReadAndValidateGzipHeader();
|
||||
if (stream.CanSeek)
|
||||
{
|
||||
long position = stream.Position;
|
||||
stream.Position = stream.Length - 8;
|
||||
ReadTrailer();
|
||||
stream.Position = position;
|
||||
}
|
||||
EntryStartPosition = stream.Position;
|
||||
}
|
||||
|
||||
internal long EntryStartPosition { get; }
|
||||
|
||||
internal DateTime? DateModified { get; private set; }
|
||||
internal int? Crc { get; private set; }
|
||||
internal int? UncompressedSize { get; private set; }
|
||||
|
||||
internal override string FilePartName => _name!;
|
||||
|
||||
@@ -37,11 +46,21 @@ namespace SharpCompress.Common.GZip
|
||||
return _stream;
|
||||
}
|
||||
|
||||
private void ReadAndValidateGzipHeader(Stream stream)
|
||||
private void ReadTrailer()
|
||||
{
|
||||
// Read and potentially verify the GZIP trailer: CRC32 and size mod 2^32
|
||||
Span<byte> trailer = stackalloc byte[8];
|
||||
int n = _stream.Read(trailer);
|
||||
|
||||
Crc = BinaryPrimitives.ReadInt32LittleEndian(trailer);
|
||||
UncompressedSize = BinaryPrimitives.ReadInt32LittleEndian(trailer.Slice(4));
|
||||
}
|
||||
|
||||
private void ReadAndValidateGzipHeader()
|
||||
{
|
||||
// read the header on the first read
|
||||
byte[] header = new byte[10];
|
||||
int n = stream.Read(header, 0, header.Length);
|
||||
Span<byte> header = stackalloc byte[10];
|
||||
int n = _stream.Read(header);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
@@ -59,17 +78,17 @@ namespace SharpCompress.Common.GZip
|
||||
throw new ZlibException("Bad GZIP header.");
|
||||
}
|
||||
|
||||
int timet = BinaryPrimitives.ReadInt32LittleEndian(header.AsSpan(4));
|
||||
int timet = BinaryPrimitives.ReadInt32LittleEndian(header.Slice(4));
|
||||
DateModified = TarHeader.EPOCH.AddSeconds(timet);
|
||||
if ((header[3] & 0x04) == 0x04)
|
||||
{
|
||||
// read and discard extra field
|
||||
n = stream.Read(header, 0, 2); // 2-byte length field
|
||||
n = _stream.Read(header.Slice(0, 2)); // 2-byte length field
|
||||
|
||||
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
|
||||
short extraLength = (short)(header[0] + header[1] * 256);
|
||||
byte[] extra = new byte[extraLength];
|
||||
|
||||
if (!stream.ReadFully(extra))
|
||||
if (!_stream.ReadFully(extra))
|
||||
{
|
||||
throw new ZlibException("Unexpected end-of-file reading GZIP header.");
|
||||
}
|
||||
@@ -77,15 +96,15 @@ namespace SharpCompress.Common.GZip
|
||||
}
|
||||
if ((header[3] & 0x08) == 0x08)
|
||||
{
|
||||
_name = ReadZeroTerminatedString(stream);
|
||||
_name = ReadZeroTerminatedString(_stream);
|
||||
}
|
||||
if ((header[3] & 0x10) == 0x010)
|
||||
{
|
||||
ReadZeroTerminatedString(stream);
|
||||
ReadZeroTerminatedString(_stream);
|
||||
}
|
||||
if ((header[3] & 0x02) == 0x02)
|
||||
{
|
||||
stream.ReadByte(); // CRC16, ignore
|
||||
_stream.ReadByte(); // CRC16, ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
internal class AvHeader : RarHeader
|
||||
{
|
||||
public AvHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Av)
|
||||
public AvHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Av)
|
||||
{
|
||||
if (IsRar5)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ 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_SALT30 = 8;
|
||||
@@ -15,14 +15,14 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
private const int SIZE_PSWCHECK_CSUM = 4;
|
||||
private const int CRYPT5_KDF_LG2_COUNT = 15; // LOG2 of PDKDF2 iteration count.
|
||||
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)
|
||||
{
|
||||
@@ -35,12 +35,12 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
//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)
|
||||
{
|
||||
|
||||
@@ -4,14 +4,14 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
internal sealed class ArchiveHeader : RarHeader
|
||||
{
|
||||
public ArchiveHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Archive)
|
||||
public ArchiveHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Archive)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ReadFinish(MarkingBinaryReader reader)
|
||||
{
|
||||
if (IsRar5)
|
||||
if (IsRar5)
|
||||
{
|
||||
Flags = reader.ReadRarVIntUInt16();
|
||||
if (HasFlag(ArchiveFlagsV5.HAS_VOLUME_NUMBER))
|
||||
@@ -22,8 +22,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
//if (ExtraSize != 0) {
|
||||
// ReadLocator(reader);
|
||||
//}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
Flags = HeaderFlags;
|
||||
HighPosAv = reader.ReadInt16();
|
||||
@@ -35,7 +35,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadLocator(MarkingBinaryReader reader) {
|
||||
private void ReadLocator(MarkingBinaryReader reader)
|
||||
{
|
||||
var size = reader.ReadRarVIntUInt16();
|
||||
var type = reader.ReadRarVIntUInt16();
|
||||
if (type != 1)
|
||||
@@ -47,18 +48,20 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
const ushort hasQuickOpenOffset = 0x01;
|
||||
const ushort hasRecoveryOffset = 0x02;
|
||||
ulong quickOpenOffset = 0;
|
||||
if ((flags & hasQuickOpenOffset) == hasQuickOpenOffset) {
|
||||
if ((flags & hasQuickOpenOffset) == hasQuickOpenOffset)
|
||||
{
|
||||
quickOpenOffset = reader.ReadRarVInt();
|
||||
}
|
||||
ulong recoveryOffset = 0;
|
||||
if ((flags & hasRecoveryOffset) == hasRecoveryOffset) {
|
||||
if ((flags & hasRecoveryOffset) == hasRecoveryOffset)
|
||||
{
|
||||
recoveryOffset = reader.ReadRarVInt();
|
||||
}
|
||||
}
|
||||
|
||||
private ushort Flags { get; set; }
|
||||
private ushort Flags { get; set; }
|
||||
|
||||
private bool HasFlag(ushort flag)
|
||||
private bool HasFlag(ushort flag)
|
||||
{
|
||||
return (Flags & flag) == flag;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
internal class CommentHeader : RarHeader
|
||||
{
|
||||
protected CommentHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Comment)
|
||||
{
|
||||
: base(header, reader, HeaderType.Comment)
|
||||
{
|
||||
if (IsRar5)
|
||||
{
|
||||
throw new InvalidFormatException("unexpected rar5 record");
|
||||
|
||||
@@ -4,14 +4,14 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
internal class EndArchiveHeader : RarHeader
|
||||
{
|
||||
public EndArchiveHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.EndArchive)
|
||||
public EndArchiveHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.EndArchive)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ReadFinish(MarkingBinaryReader reader)
|
||||
{
|
||||
if (IsRar5)
|
||||
if (IsRar5)
|
||||
{
|
||||
Flags = reader.ReadRarVIntUInt16();
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
private ushort Flags { get; set; }
|
||||
|
||||
private bool HasFlag(ushort flag)
|
||||
private bool HasFlag(ushort flag)
|
||||
{
|
||||
return (Flags & flag) == flag;
|
||||
}
|
||||
|
||||
@@ -21,18 +21,18 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
private uint _fileCrc;
|
||||
|
||||
public FileHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType)
|
||||
: base(header, reader, headerType)
|
||||
public FileHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType)
|
||||
: base(header, reader, headerType)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ReadFinish(MarkingBinaryReader reader)
|
||||
protected override void ReadFinish(MarkingBinaryReader reader)
|
||||
{
|
||||
if (IsRar5)
|
||||
if (IsRar5)
|
||||
{
|
||||
ReadFromReaderV5(reader);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadFromReaderV4(reader);
|
||||
}
|
||||
@@ -49,11 +49,13 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
FileAttributes = reader.ReadRarVIntUInt32();
|
||||
|
||||
if (HasFlag(FileFlagsV5.HAS_MOD_TIME)) {
|
||||
if (HasFlag(FileFlagsV5.HAS_MOD_TIME))
|
||||
{
|
||||
FileLastModifiedTime = Utility.UnixTimeToDateTime(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
if (HasFlag(FileFlagsV5.HAS_CRC32)) {
|
||||
if (HasFlag(FileFlagsV5.HAS_CRC32))
|
||||
{
|
||||
FileCrc = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
@@ -65,7 +67,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
// but it was already used in RAR 1.5 and Unpack needs to distinguish
|
||||
// them.
|
||||
CompressionAlgorithm = (byte)((compressionInfo & 0x3f) + 50);
|
||||
|
||||
|
||||
// 7th bit (0x0040) defines the solid flag. If it is set, RAR continues to use the compression dictionary left after processing preceding files.
|
||||
// It can be set only for file headers and is never set for service headers.
|
||||
IsSolid = (compressionInfo & 0x40) == 0x40;
|
||||
@@ -74,7 +76,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
CompressionMethod = (byte)((compressionInfo >> 7) & 0x7);
|
||||
|
||||
// Bits 11 - 14 (0x3c00) define the minimum size of dictionary size required to extract data. Value 0 means 128 KB, 1 - 256 KB, ..., 14 - 2048 MB, 15 - 4096 MB.
|
||||
WindowSize = IsDirectory ? 0 : ((size_t)0x20000) << ((compressionInfo>>10) & 0xf);
|
||||
WindowSize = IsDirectory ? 0 : ((size_t)0x20000) << ((compressionInfo >> 10) & 0xf);
|
||||
|
||||
HostOs = reader.ReadRarVIntByte();
|
||||
|
||||
@@ -101,18 +103,20 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
FileName = ConvertPathV5(Encoding.UTF8.GetString(b, 0, b.Length));
|
||||
|
||||
// extra size seems to be redudant since we know the total header size
|
||||
if (ExtraSize != RemainingHeaderBytes(reader))
|
||||
if (ExtraSize != RemainingHeaderBytes(reader))
|
||||
{
|
||||
throw new InvalidFormatException("rar5 header size / extra size inconsistency");
|
||||
}
|
||||
|
||||
isEncryptedRar5 = false;
|
||||
|
||||
while (RemainingHeaderBytes(reader) > 0) {
|
||||
while (RemainingHeaderBytes(reader) > 0)
|
||||
{
|
||||
var size = reader.ReadRarVIntUInt16();
|
||||
int n = RemainingHeaderBytes(reader);
|
||||
var type = reader.ReadRarVIntUInt16();
|
||||
switch (type) {
|
||||
switch (type)
|
||||
{
|
||||
//TODO
|
||||
case 1: // file encryption
|
||||
{
|
||||
@@ -120,7 +124,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
//var version = reader.ReadRarVIntByte();
|
||||
//if (version != 0) throw new InvalidFormatException("unknown encryption algorithm " + version);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// case 2: // file hash
|
||||
// {
|
||||
@@ -131,38 +135,41 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
ushort flags = reader.ReadRarVIntUInt16();
|
||||
var isWindowsTime = (flags & 1) == 0;
|
||||
if ((flags & 0x2) == 0x2) {
|
||||
if ((flags & 0x2) == 0x2)
|
||||
{
|
||||
FileLastModifiedTime = ReadExtendedTimeV5(reader, isWindowsTime);
|
||||
}
|
||||
if ((flags & 0x4) == 0x4) {
|
||||
if ((flags & 0x4) == 0x4)
|
||||
{
|
||||
FileCreatedTime = ReadExtendedTimeV5(reader, isWindowsTime);
|
||||
}
|
||||
if ((flags & 0x8) == 0x8) {
|
||||
if ((flags & 0x8) == 0x8)
|
||||
{
|
||||
FileLastAccessedTime = ReadExtendedTimeV5(reader, isWindowsTime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
//TODO
|
||||
// case 4: // file version
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 5: // file system redirection
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 6: // unix owner
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 7: // service data
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
//TODO
|
||||
// case 4: // file version
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 5: // file system redirection
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 6: // unix owner
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
// case 7: // service data
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// break;
|
||||
|
||||
default:
|
||||
// skip unknown record types to allow new record types to be added in the future
|
||||
@@ -171,25 +178,26 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
// drain any trailing bytes of extra record
|
||||
int did = n - RemainingHeaderBytes(reader);
|
||||
int drain = size - did;
|
||||
if (drain > 0)
|
||||
if (drain > 0)
|
||||
{
|
||||
reader.ReadBytes(drain);
|
||||
}
|
||||
}
|
||||
|
||||
if (AdditionalDataSize != 0) {
|
||||
if (AdditionalDataSize != 0)
|
||||
{
|
||||
CompressedSize = AdditionalDataSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static DateTime ReadExtendedTimeV5(MarkingBinaryReader reader, bool isWindowsTime)
|
||||
private static DateTime ReadExtendedTimeV5(MarkingBinaryReader reader, bool isWindowsTime)
|
||||
{
|
||||
if (isWindowsTime)
|
||||
if (isWindowsTime)
|
||||
{
|
||||
return DateTime.FromFileTime(reader.ReadInt64());
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
return Utility.UnixTimeToDateTime(reader.ReadUInt32());
|
||||
}
|
||||
@@ -201,7 +209,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
// replace embedded \\ with valid filename char
|
||||
return path.Replace('\\', '-').Replace('/', '\\');
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -376,20 +384,22 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
private ushort Flags { get; set; }
|
||||
|
||||
private bool HasFlag(ushort flag)
|
||||
private bool HasFlag(ushort flag)
|
||||
{
|
||||
return (Flags & flag) == flag;
|
||||
}
|
||||
|
||||
internal uint FileCrc
|
||||
{
|
||||
get {
|
||||
if (IsRar5 && !HasFlag(FileFlagsV5.HAS_CRC32)) {
|
||||
//!!! rar5:
|
||||
internal uint FileCrc
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsRar5 && !HasFlag(FileFlagsV5.HAS_CRC32))
|
||||
{
|
||||
//!!! rar5:
|
||||
throw new InvalidOperationException("TODO rar5");
|
||||
}
|
||||
return _fileCrc;
|
||||
}
|
||||
return _fileCrc;
|
||||
}
|
||||
private set => _fileCrc = value;
|
||||
}
|
||||
|
||||
@@ -409,7 +419,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
//case 29: // rar 3.x compression
|
||||
//case 50: // RAR 5.0 compression algorithm.
|
||||
internal byte CompressionAlgorithm { get; private set; }
|
||||
|
||||
|
||||
public bool IsSolid { get; private set; }
|
||||
|
||||
// unused for UnpackV1 implementation (limitation)
|
||||
@@ -432,8 +442,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
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 ? isEncryptedRar5 : HasFlag(FileFlagsV4.PASSWORD);
|
||||
|
||||
internal DateTime? FileLastModifiedTime { get; private set; }
|
||||
|
||||
internal DateTime? FileCreatedTime { get; private set; }
|
||||
|
||||
@@ -42,10 +42,10 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
|
||||
internal static class EncryptionFlagsV5
|
||||
{
|
||||
{
|
||||
// RAR 5.0 archive encryption header specific flags.
|
||||
public const uint CHFL_CRYPT_PSWCHECK = 0x01; // Password check data is present.
|
||||
|
||||
|
||||
public const uint FHEXTRA_CRYPT_PSWCHECK = 0x01; // Password check data is present.
|
||||
public const uint FHEXTRA_CRYPT_HASHMAC = 0x02;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
internal interface IRarHeader
|
||||
internal interface IRarHeader
|
||||
{
|
||||
HeaderType HeaderType { get; }
|
||||
}
|
||||
|
||||
@@ -11,39 +11,39 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
public bool IsRar5 { get; }
|
||||
|
||||
private MarkHeader(bool isRar5)
|
||||
{
|
||||
private MarkHeader(bool isRar5)
|
||||
{
|
||||
IsRar5 = isRar5;
|
||||
}
|
||||
|
||||
public HeaderType HeaderType => HeaderType.Mark;
|
||||
|
||||
private static byte GetByte(Stream stream)
|
||||
private static byte GetByte(Stream stream)
|
||||
{
|
||||
var b = stream.ReadByte();
|
||||
if (b != -1)
|
||||
if (b != -1)
|
||||
{
|
||||
return (byte)b;
|
||||
}
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
public static MarkHeader Read(Stream stream, bool leaveStreamOpen, bool lookForHeader)
|
||||
public static MarkHeader Read(Stream stream, bool leaveStreamOpen, bool lookForHeader)
|
||||
{
|
||||
int maxScanIndex = lookForHeader ? MAX_SFX_SIZE : 0;
|
||||
try
|
||||
{
|
||||
int start = -1;
|
||||
var b = GetByte(stream); start++;
|
||||
while (start <= maxScanIndex)
|
||||
while (start <= maxScanIndex)
|
||||
{
|
||||
// Rar old signature: 52 45 7E 5E
|
||||
// Rar4 signature: 52 61 72 21 1A 07 00
|
||||
// Rar5 signature: 52 61 72 21 1A 07 01 00
|
||||
if (b == 0x52)
|
||||
if (b == 0x52)
|
||||
{
|
||||
b = GetByte(stream); start++;
|
||||
if (b == 0x61)
|
||||
if (b == 0x61)
|
||||
{
|
||||
b = GetByte(stream); start++;
|
||||
if (b != 0x72)
|
||||
@@ -70,7 +70,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
|
||||
b = GetByte(stream); start++;
|
||||
if (b == 1)
|
||||
if (b == 1)
|
||||
{
|
||||
b = GetByte(stream); start++;
|
||||
if (b != 0)
|
||||
@@ -79,13 +79,13 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
|
||||
return new MarkHeader(true); // Rar5
|
||||
}
|
||||
else if (b == 0)
|
||||
}
|
||||
else if (b == 0)
|
||||
{
|
||||
return new MarkHeader(false); // Rar4
|
||||
}
|
||||
}
|
||||
else if (b == 0x45)
|
||||
}
|
||||
}
|
||||
else if (b == 0x45)
|
||||
{
|
||||
b = GetByte(stream); start++;
|
||||
if (b != 0x7e)
|
||||
@@ -100,9 +100,9 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
|
||||
throw new InvalidFormatException("Rar format version pre-4 is unsupported.");
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b = GetByte(stream); start++;
|
||||
}
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
|
||||
namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
internal class NewSubHeaderType : IEquatable<NewSubHeaderType>
|
||||
internal sealed class NewSubHeaderType : IEquatable<NewSubHeaderType>
|
||||
{
|
||||
internal static readonly NewSubHeaderType SUBHEAD_TYPE_CMT = new NewSubHeaderType('C', 'M', 'T');
|
||||
internal static readonly NewSubHeaderType SUBHEAD_TYPE_CMT = new('C', 'M', 'T');
|
||||
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_ACL = new NewSubHeaderType(new byte[]{'A','C','L'});
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_ACL = new (new byte[]{'A','C','L'});
|
||||
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_STREAM = new NewSubHeaderType(new byte[]{'S','T','M'});
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_STREAM = new (new byte[]{'S','T','M'});
|
||||
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_UOWNER = new NewSubHeaderType(new byte[]{'U','O','W'});
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_UOWNER = new (new byte[]{'U','O','W'});
|
||||
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_AV = new NewSubHeaderType(new byte[]{'A','V'});
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_AV = new (new byte[]{'A','V'});
|
||||
|
||||
internal static readonly NewSubHeaderType SUBHEAD_TYPE_RR = new NewSubHeaderType('R', 'R');
|
||||
internal static readonly NewSubHeaderType SUBHEAD_TYPE_RR = new('R', 'R');
|
||||
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_OS2EA = new NewSubHeaderType(new byte[]{'E','A','2'});
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_OS2EA = new (new byte[]{'E','A','2'});
|
||||
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_BEOSEA = new NewSubHeaderType(new byte[]{'E','A','B','E'});
|
||||
//internal static final NewSubHeaderType SUBHEAD_TYPE_BEOSEA = new (new byte[]{'E','A','B','E'});
|
||||
|
||||
private readonly byte[] _bytes;
|
||||
|
||||
@@ -37,19 +37,13 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < bytes.Length; ++i)
|
||||
{
|
||||
if (_bytes[i] != bytes[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
return _bytes.AsSpan().SequenceEqual(bytes);
|
||||
}
|
||||
|
||||
public bool Equals(NewSubHeaderType other)
|
||||
public bool Equals(NewSubHeaderType? other)
|
||||
{
|
||||
return Equals(other._bytes);
|
||||
return other is not null && Equals(other._bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
// ProtectHeader is part of the Recovery Record feature
|
||||
internal sealed class ProtectHeader : RarHeader
|
||||
{
|
||||
public ProtectHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Protect)
|
||||
public ProtectHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Protect)
|
||||
{
|
||||
if (IsRar5)
|
||||
{
|
||||
|
||||
@@ -23,12 +23,12 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
}
|
||||
|
||||
private RarHeader(RarCrcBinaryReader reader, bool isRar5, ArchiveEncoding archiveEncoding)
|
||||
private RarHeader(RarCrcBinaryReader reader, bool isRar5, ArchiveEncoding archiveEncoding)
|
||||
{
|
||||
_headerType = HeaderType.Null;
|
||||
_isRar5 = isRar5;
|
||||
ArchiveEncoding = archiveEncoding;
|
||||
if (IsRar5)
|
||||
if (IsRar5)
|
||||
{
|
||||
HeaderCrc = reader.ReadUInt32();
|
||||
reader.ResetCrc();
|
||||
@@ -45,7 +45,9 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
{
|
||||
AdditionalDataSize = (long)reader.ReadRarVInt();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Mark();
|
||||
HeaderCrc = reader.ReadUInt16();
|
||||
reader.ResetCrc();
|
||||
@@ -59,7 +61,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
}
|
||||
|
||||
protected RarHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) {
|
||||
protected RarHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType)
|
||||
{
|
||||
_headerType = headerType;
|
||||
_isRar5 = header.IsRar5;
|
||||
HeaderCrc = header.HeaderCrc;
|
||||
@@ -80,7 +83,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
VerifyHeaderCrc(reader.GetCrc32());
|
||||
}
|
||||
|
||||
protected int RemainingHeaderBytes(MarkingBinaryReader reader) {
|
||||
protected int RemainingHeaderBytes(MarkingBinaryReader reader)
|
||||
{
|
||||
return checked(HeaderSize - (int)reader.CurrentReadByteCount);
|
||||
}
|
||||
|
||||
@@ -108,7 +112,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
|
||||
protected ushort HeaderFlags { get; }
|
||||
|
||||
protected bool HasHeaderFlag(ushort flag)
|
||||
protected bool HasHeaderFlag(ushort flag)
|
||||
{
|
||||
return (HeaderFlags & flag) == flag;
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
private RarHeader? TryReadNextHeader(Stream stream)
|
||||
{
|
||||
RarCrcBinaryReader reader;
|
||||
if (!IsEncrypted)
|
||||
if (!IsEncrypted)
|
||||
{
|
||||
reader = new RarCrcBinaryReader(stream);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Options.Password is null)
|
||||
{
|
||||
@@ -65,7 +65,7 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
case HeaderCodeV.RAR4_ARCHIVE_HEADER:
|
||||
{
|
||||
var ah = new ArchiveHeader(header, reader);
|
||||
if (ah.IsEncrypted == true)
|
||||
if (ah.IsEncrypted == true)
|
||||
{
|
||||
//!!! rar5 we don't know yet
|
||||
IsEncrypted = true;
|
||||
@@ -150,11 +150,11 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
return new EndArchiveHeader(header, reader);
|
||||
}
|
||||
case HeaderCodeV.RAR5_ARCHIVE_ENCRYPTION_HEADER:
|
||||
{
|
||||
var ch = new ArchiveCryptHeader(header, reader);
|
||||
IsEncrypted = true;
|
||||
return ch;
|
||||
}
|
||||
{
|
||||
var ch = new ArchiveCryptHeader(header, reader);
|
||||
IsEncrypted = true;
|
||||
return ch;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new InvalidFormatException("Unknown Rar Header: " + header.HeaderCode);
|
||||
@@ -162,21 +162,26 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
}
|
||||
}
|
||||
|
||||
private void SkipData(FileHeader fh, RarCrcBinaryReader reader) {
|
||||
switch (StreamingMode) {
|
||||
case StreamingMode.Seekable: {
|
||||
fh.DataStartPosition = reader.BaseStream.Position;
|
||||
reader.BaseStream.Position += fh.CompressedSize;
|
||||
}
|
||||
private void SkipData(FileHeader fh, RarCrcBinaryReader reader)
|
||||
{
|
||||
switch (StreamingMode)
|
||||
{
|
||||
case StreamingMode.Seekable:
|
||||
{
|
||||
fh.DataStartPosition = reader.BaseStream.Position;
|
||||
reader.BaseStream.Position += fh.CompressedSize;
|
||||
}
|
||||
break;
|
||||
case StreamingMode.Streaming: {
|
||||
//skip the data because it's useless?
|
||||
reader.BaseStream.Skip(fh.CompressedSize);
|
||||
}
|
||||
case StreamingMode.Streaming:
|
||||
{
|
||||
//skip the data because it's useless?
|
||||
reader.BaseStream.Skip(fh.CompressedSize);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
throw new InvalidFormatException("Invalid StreamingMode");
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new InvalidFormatException("Invalid StreamingMode");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace SharpCompress.Common.Rar.Headers
|
||||
internal class SignHeader : RarHeader
|
||||
{
|
||||
protected SignHeader(RarHeader header, RarCrcBinaryReader reader)
|
||||
: base(header, reader, HeaderType.Sign)
|
||||
{
|
||||
: base(header, reader, HeaderType.Sign)
|
||||
{
|
||||
if (IsRar5)
|
||||
{
|
||||
throw new InvalidFormatException("unexpected rar5 record");
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace SharpCompress.Common.Rar
|
||||
/// As the V2017 port isn't complete, add this check to use the legacy Rar code.
|
||||
/// </summary>
|
||||
internal bool IsRarV3 => FileHeader.CompressionAlgorithm == 29 || FileHeader.CompressionAlgorithm == 36;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The File's 32 bit CRC Hash
|
||||
/// </summary>
|
||||
|
||||
@@ -27,13 +27,13 @@ namespace SharpCompress.Common.Rar
|
||||
|
||||
_rijndael = new RijndaelEngine();
|
||||
_aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE];
|
||||
int rawLength = 2*_password.Length;
|
||||
int rawLength = 2 * _password.Length;
|
||||
byte[] rawPassword = new byte[rawLength + 8];
|
||||
byte[] passwordBytes = Encoding.UTF8.GetBytes(_password);
|
||||
for (int i = 0; i < _password.Length; i++)
|
||||
{
|
||||
rawPassword[i*2] = passwordBytes[i];
|
||||
rawPassword[i*2 + 1] = 0;
|
||||
rawPassword[i * 2] = passwordBytes[i];
|
||||
rawPassword[i * 2 + 1] = 0;
|
||||
}
|
||||
for (int i = 0; i < _salt.Length; i++)
|
||||
{
|
||||
@@ -68,11 +68,11 @@ namespace SharpCompress.Common.Rar
|
||||
{
|
||||
for (int 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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,11 +87,11 @@ namespace SharpCompress.Common.Rar
|
||||
return rijndael;
|
||||
}
|
||||
|
||||
public byte[] ProcessBlock(byte[] cipherText)
|
||||
public byte[] ProcessBlock(ReadOnlySpan<byte> cipherText)
|
||||
{
|
||||
var plainText = new byte[CRYPTO_BLOCK_SIZE];
|
||||
Span<byte> plainText = stackalloc byte[CRYPTO_BLOCK_SIZE]; // 16 bytes
|
||||
byte[] decryptedBytes = new byte[CRYPTO_BLOCK_SIZE];
|
||||
_rijndael.ProcessBlock(cipherText, 0, plainText, 0);
|
||||
_rijndael.ProcessBlock(cipherText, plainText);
|
||||
|
||||
for (int j = 0; j < CRYPTO_BLOCK_SIZE; j++)
|
||||
{
|
||||
|
||||
@@ -39,20 +39,20 @@ namespace SharpCompress.Common.Rar
|
||||
switch (header.HeaderType)
|
||||
{
|
||||
case HeaderType.Mark:
|
||||
{
|
||||
lastMarkHeader = (MarkHeader)header;
|
||||
}
|
||||
{
|
||||
lastMarkHeader = (MarkHeader)header;
|
||||
}
|
||||
break;
|
||||
case HeaderType.Archive:
|
||||
{
|
||||
ArchiveHeader = (ArchiveHeader)header;
|
||||
}
|
||||
{
|
||||
ArchiveHeader = (ArchiveHeader)header;
|
||||
}
|
||||
break;
|
||||
case HeaderType.File:
|
||||
{
|
||||
var fh = (FileHeader)header;
|
||||
yield return CreateFilePart(lastMarkHeader!, fh);
|
||||
}
|
||||
{
|
||||
var fh = (FileHeader)header;
|
||||
yield return CreateFilePart(lastMarkHeader!, fh);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
{
|
||||
// v3.13 incorrectly worked with empty folders
|
||||
// v4.07: Loop for skipping empty folders
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
if (folderIndex >= _folders.Count)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
|
||||
private void WaitAttribute(BlockType attribute)
|
||||
{
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
BlockType? type = ReadId();
|
||||
if (type == attribute)
|
||||
@@ -452,7 +452,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#endif
|
||||
|
||||
BlockType? type;
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
type = ReadId();
|
||||
if (type == BlockType.End)
|
||||
@@ -508,7 +508,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
int index = 0;
|
||||
for (int i = 0; i < numFolders; i++)
|
||||
{
|
||||
var f = new CFolder {_firstPackStreamId = index};
|
||||
var f = new CFolder { _firstPackStreamId = index };
|
||||
folders.Add(f);
|
||||
GetNextFolderItem(f);
|
||||
index += f._packStreams.Count;
|
||||
@@ -539,7 +539,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#endif
|
||||
}
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
BlockType? type = ReadId();
|
||||
if (type == BlockType.End)
|
||||
@@ -580,7 +580,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
numUnpackStreamsInFolders = null;
|
||||
|
||||
BlockType? type;
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
type = ReadId();
|
||||
if (type == BlockType.NumUnpackStream)
|
||||
@@ -602,7 +602,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if (type == BlockType.Crc || type == BlockType.Size)
|
||||
if (type is BlockType.Crc or BlockType.Size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -672,7 +672,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
|
||||
digests = null;
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
if (type == BlockType.Crc)
|
||||
{
|
||||
@@ -755,7 +755,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
unpackSizes = null;
|
||||
digests = null;
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
switch (ReadId())
|
||||
{
|
||||
@@ -791,22 +791,14 @@ namespace SharpCompress.Common.SevenZip
|
||||
#endif
|
||||
try
|
||||
{
|
||||
long dataStartPos;
|
||||
List<long> packSizes;
|
||||
List<uint?> packCrCs;
|
||||
List<CFolder> folders;
|
||||
List<int> numUnpackStreamsInFolders;
|
||||
List<long> unpackSizes;
|
||||
List<uint?> digests;
|
||||
|
||||
ReadStreamsInfo(null,
|
||||
out dataStartPos,
|
||||
out packSizes,
|
||||
out packCrCs,
|
||||
out folders,
|
||||
out numUnpackStreamsInFolders,
|
||||
out unpackSizes,
|
||||
out digests);
|
||||
out long dataStartPos,
|
||||
out List<long> packSizes,
|
||||
out List<uint?> packCrCs,
|
||||
out List<CFolder> folders,
|
||||
out List<int> numUnpackStreamsInFolders,
|
||||
out List<long> unpackSizes,
|
||||
out List<uint?> digests);
|
||||
|
||||
dataStartPos += baseOffset;
|
||||
|
||||
@@ -934,7 +926,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
BitVector antiFileVector = null;
|
||||
int numEmptyStreams = 0;
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
type = ReadId();
|
||||
if (type == BlockType.End)
|
||||
@@ -969,7 +961,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#if DEBUG
|
||||
Log.Write("WinAttributes:");
|
||||
#endif
|
||||
ReadAttributeVector(dataVector, numFiles, delegate(int i, uint? attr)
|
||||
ReadAttributeVector(dataVector, numFiles, delegate (int i, uint? attr)
|
||||
{
|
||||
// Some third party implementations established an unofficial extension
|
||||
// of the 7z archive format by placing posix file attributes in the high
|
||||
@@ -1057,7 +1049,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#if DEBUG
|
||||
Log.Write("StartPos:");
|
||||
#endif
|
||||
ReadNumberVector(dataVector, numFiles, delegate(int i, long? startPos)
|
||||
ReadNumberVector(dataVector, numFiles, delegate (int i, long? startPos)
|
||||
{
|
||||
db._files[i].StartPos = startPos;
|
||||
#if DEBUG
|
||||
@@ -1072,7 +1064,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#if DEBUG
|
||||
Log.Write("CTime:");
|
||||
#endif
|
||||
ReadDateTimeVector(dataVector, numFiles, delegate(int i, DateTime? time)
|
||||
ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time)
|
||||
{
|
||||
db._files[i].CTime = time;
|
||||
#if DEBUG
|
||||
@@ -1087,7 +1079,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#if DEBUG
|
||||
Log.Write("ATime:");
|
||||
#endif
|
||||
ReadDateTimeVector(dataVector, numFiles, delegate(int i, DateTime? time)
|
||||
ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time)
|
||||
{
|
||||
db._files[i].ATime = time;
|
||||
#if DEBUG
|
||||
@@ -1102,7 +1094,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
#if DEBUG
|
||||
Log.Write("MTime:");
|
||||
#endif
|
||||
ReadDateTimeVector(dataVector, numFiles, delegate(int i, DateTime? time)
|
||||
ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time)
|
||||
{
|
||||
db._files[i].MTime = time;
|
||||
#if DEBUG
|
||||
@@ -1445,8 +1437,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
|
||||
private Stream GetCachedDecoderStream(ArchiveDatabase db, int folderIndex)
|
||||
{
|
||||
Stream s;
|
||||
if (!_cachedStreams.TryGetValue(folderIndex, out s))
|
||||
if (!_cachedStreams.TryGetValue(folderIndex, out Stream s))
|
||||
{
|
||||
CFolder folderInfo = db._folders[folderIndex];
|
||||
int packStreamIndex = db._folders[folderIndex]._firstPackStreamId;
|
||||
@@ -1494,7 +1485,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
int numItems = allFilesMode
|
||||
? db._files.Count
|
||||
: indices.Length;
|
||||
|
||||
|
||||
if (numItems == 0)
|
||||
{
|
||||
return;
|
||||
@@ -1563,7 +1554,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
Stream s = DecoderStreamHelper.CreateDecoderStream(_stream, folderStartPackPos, packSizes,
|
||||
folderInfo, db.PasswordProvider);
|
||||
byte[] buffer = new byte[4 << 10];
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
int processed = s.Read(buffer, 0, buffer.Length);
|
||||
if (processed == 0)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace SharpCompress.Common.SevenZip
|
||||
{
|
||||
internal struct CMethodId
|
||||
internal readonly struct CMethodId
|
||||
{
|
||||
public const ulong K_COPY_ID = 0;
|
||||
public const ulong K_LZMA_ID = 0x030101;
|
||||
@@ -24,9 +24,9 @@
|
||||
return _id.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is CMethodId && (CMethodId)obj == this;
|
||||
return obj is CMethodId other && Equals(other);
|
||||
}
|
||||
|
||||
public bool Equals(CMethodId other)
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace SharpCompress.Common.SevenZip
|
||||
{
|
||||
int ending = Offset;
|
||||
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
if (ending + 2 > _ending)
|
||||
{
|
||||
|
||||
@@ -84,20 +84,20 @@ namespace SharpCompress.Common.SevenZip
|
||||
{
|
||||
var coder = Folder!._coders.First();
|
||||
switch (coder._methodId._id)
|
||||
{
|
||||
{
|
||||
case K_LZMA:
|
||||
case K_LZMA2:
|
||||
{
|
||||
return CompressionType.LZMA;
|
||||
}
|
||||
{
|
||||
return CompressionType.LZMA;
|
||||
}
|
||||
case K_PPMD:
|
||||
{
|
||||
return CompressionType.PPMd;
|
||||
}
|
||||
{
|
||||
return CompressionType.PPMd;
|
||||
}
|
||||
case K_B_ZIP2:
|
||||
{
|
||||
return CompressionType.BZip2;
|
||||
}
|
||||
{
|
||||
return CompressionType.BZip2;
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Text;
|
||||
|
||||
namespace SharpCompress.Common.Tar.Headers
|
||||
{
|
||||
internal class TarHeader
|
||||
internal sealed class TarHeader
|
||||
{
|
||||
internal static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
@@ -260,10 +260,16 @@ namespace SharpCompress.Common.Tar.Headers
|
||||
return Convert.ToInt64(s);
|
||||
}
|
||||
|
||||
|
||||
private static readonly byte[] eightSpaces = {
|
||||
(byte)' ', (byte)' ', (byte)' ', (byte)' ',
|
||||
(byte)' ', (byte)' ', (byte)' ', (byte)' '
|
||||
};
|
||||
|
||||
internal static int RecalculateChecksum(byte[] buf)
|
||||
{
|
||||
// Set default value for checksum. That is 8 spaces.
|
||||
Encoding.UTF8.GetBytes(" ").CopyTo(buf, 148);
|
||||
eightSpaces.CopyTo(buf, 148);
|
||||
|
||||
// Calculate checksum
|
||||
int headerChecksum = 0;
|
||||
@@ -276,7 +282,7 @@ namespace SharpCompress.Common.Tar.Headers
|
||||
|
||||
internal static int RecalculateAltChecksum(byte[] buf)
|
||||
{
|
||||
Encoding.UTF8.GetBytes(" ").CopyTo(buf, 148);
|
||||
eightSpaces.CopyTo(buf, 148);
|
||||
int headerChecksum = 0;
|
||||
foreach (byte b in buf)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
byte[] name = reader.ReadBytes(nameLength);
|
||||
byte[] extra = reader.ReadBytes(extraLength);
|
||||
byte[] comment = reader.ReadBytes(commentLength);
|
||||
|
||||
|
||||
// According to .ZIP File Format Specification
|
||||
//
|
||||
// For example: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
|
||||
@@ -40,7 +40,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
// Bit 11: Language encoding flag (EFS). If this bit is set,
|
||||
// the filename and comment fields for this file
|
||||
// MUST be encoded using UTF-8. (see APPENDIX D)
|
||||
|
||||
|
||||
if (Flags.HasFlag(HeaderFlags.Efs))
|
||||
{
|
||||
Name = ArchiveEncoding.DecodeUTF8(name);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
ushort extraLength = reader.ReadUInt16();
|
||||
byte[] name = reader.ReadBytes(nameLength);
|
||||
byte[] extra = reader.ReadBytes(extraLength);
|
||||
|
||||
|
||||
// According to .ZIP File Format Specification
|
||||
//
|
||||
// For example: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
|
||||
@@ -32,7 +32,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
// Bit 11: Language encoding flag (EFS). If this bit is set,
|
||||
// the filename and comment fields for this file
|
||||
// MUST be encoded using UTF-8. (see APPENDIX D)
|
||||
|
||||
|
||||
if (Flags.HasFlag(HeaderFlags.Efs))
|
||||
{
|
||||
Name = ArchiveEncoding.DecodeUTF8(name);
|
||||
@@ -41,7 +41,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
{
|
||||
Name = ArchiveEncoding.Decode(name);
|
||||
}
|
||||
|
||||
|
||||
LoadExtra(extra);
|
||||
|
||||
var unicodePathExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnicodePathExtraField);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Text;
|
||||
|
||||
@@ -20,13 +18,25 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
|
||||
internal class ExtraData
|
||||
{
|
||||
internal ExtraDataType Type { get; set; }
|
||||
internal ushort Length { get; set; }
|
||||
internal byte[] DataBytes { get; set; }
|
||||
public ExtraData(ExtraDataType type, ushort length, byte[] dataBytes)
|
||||
{
|
||||
Type = type;
|
||||
Length = length;
|
||||
DataBytes = dataBytes;
|
||||
}
|
||||
|
||||
internal ExtraDataType Type { get; }
|
||||
internal ushort Length { get; }
|
||||
internal byte[] DataBytes { get; }
|
||||
}
|
||||
|
||||
internal class ExtraUnicodePathExtraField : ExtraData
|
||||
internal sealed class ExtraUnicodePathExtraField : ExtraData
|
||||
{
|
||||
public ExtraUnicodePathExtraField(ExtraDataType type, ushort length, byte[] dataBytes)
|
||||
: base(type, length, dataBytes)
|
||||
{
|
||||
}
|
||||
|
||||
internal byte Version => DataBytes[0];
|
||||
|
||||
internal byte[] NameCrc32
|
||||
@@ -51,14 +61,11 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
}
|
||||
}
|
||||
|
||||
internal class Zip64ExtendedInformationExtraField : ExtraData
|
||||
internal sealed class Zip64ExtendedInformationExtraField : ExtraData
|
||||
{
|
||||
|
||||
public Zip64ExtendedInformationExtraField(ExtraDataType type, ushort length, byte[] dataBytes)
|
||||
: base(type, length, dataBytes)
|
||||
{
|
||||
Type = type;
|
||||
Length = length;
|
||||
DataBytes = dataBytes;
|
||||
Process();
|
||||
}
|
||||
|
||||
@@ -108,7 +115,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
VolumeNumber = BinaryPrimitives.ReadUInt32LittleEndian(DataBytes.AsSpan(24));
|
||||
return;
|
||||
default:
|
||||
throw new ArchiveException("Unexpected size of of Zip64 extended information extra field");
|
||||
throw new ArchiveException("Unexpected size of of Zip64 extended information extra field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,30 +129,12 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
{
|
||||
internal static ExtraData Create(ExtraDataType type, ushort length, byte[] extraData)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case ExtraDataType.UnicodePathExtraField:
|
||||
return new ExtraUnicodePathExtraField
|
||||
{
|
||||
Type = type,
|
||||
Length = length,
|
||||
DataBytes = extraData
|
||||
};
|
||||
case ExtraDataType.Zip64ExtendedInformationExtraField:
|
||||
return new Zip64ExtendedInformationExtraField
|
||||
(
|
||||
type,
|
||||
length,
|
||||
extraData
|
||||
);
|
||||
default:
|
||||
return new ExtraData
|
||||
{
|
||||
Type = type,
|
||||
Length = length,
|
||||
DataBytes = extraData
|
||||
};
|
||||
}
|
||||
ExtraDataType.UnicodePathExtraField => new ExtraUnicodePathExtraField(type, length, extraData),
|
||||
ExtraDataType.Zip64ExtendedInformationExtraField => new Zip64ExtendedInformationExtraField(type, length, extraData),
|
||||
_ => new ExtraData(type, length, extraData)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Name.EndsWith("/"))
|
||||
if (Name.EndsWith('/'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace SharpCompress.Common.Zip.Headers
|
||||
//.NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers
|
||||
return CompressedSize == 0
|
||||
&& UncompressedSize == 0
|
||||
&& Name.EndsWith("\\");
|
||||
&& Name.EndsWith('\\');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace SharpCompress.Common.Zip
|
||||
internal class PkwareTraditionalEncryptionData
|
||||
{
|
||||
private static readonly CRC32 CRC32 = new CRC32();
|
||||
private readonly UInt32[] _keys = {0x12345678, 0x23456789, 0x34567890};
|
||||
private readonly UInt32[] _keys = { 0x12345678, 0x23456789, 0x34567890 };
|
||||
private readonly ArchiveEncoding _archiveEncoding;
|
||||
|
||||
private PkwareTraditionalEncryptionData(string password, ArchiveEncoding archiveEncoding)
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace SharpCompress.Common.Zip
|
||||
if (Header.HasData && !Skipped)
|
||||
{
|
||||
_decompressionStream ??= GetCompressedStream();
|
||||
|
||||
|
||||
_decompressionStream.Skip();
|
||||
|
||||
if (_decompressionStream is DeflateStream deflateStream)
|
||||
|
||||
@@ -49,7 +49,10 @@ namespace SharpCompress.Common.Zip
|
||||
_lastEntryHeader = null;
|
||||
uint headerBytes = reader.ReadUInt32();
|
||||
header = ReadHeader(headerBytes, reader);
|
||||
if (header is null) { yield break; }
|
||||
if (header is null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
//entry could be zero bytes so we need to know that.
|
||||
if (header.ZipHeaderType == ZipHeaderType.LocalEntry)
|
||||
@@ -57,11 +60,11 @@ namespace SharpCompress.Common.Zip
|
||||
var local_header = ((LocalEntryHeader)header);
|
||||
|
||||
// If we have CompressedSize, there is data to be read
|
||||
if( local_header.CompressedSize > 0 )
|
||||
if (local_header.CompressedSize > 0)
|
||||
{
|
||||
header.HasData = true;
|
||||
} // Check if zip is streaming ( Length is 0 and is declared in PostDataDescriptor )
|
||||
else if( local_header.Flags.HasFlag(HeaderFlags.UsePostDataDescriptor) )
|
||||
else if (local_header.Flags.HasFlag(HeaderFlags.UsePostDataDescriptor))
|
||||
{
|
||||
bool isRecording = rewindableStream.IsRecording;
|
||||
if (!isRecording)
|
||||
|
||||
@@ -33,8 +33,10 @@ namespace SharpCompress.Common.Zip
|
||||
|
||||
private int KeySizeInBytes
|
||||
{
|
||||
get { return KeyLengthInBytes(_keySize);
|
||||
}
|
||||
get
|
||||
{
|
||||
return KeyLengthInBytes(_keySize);
|
||||
}
|
||||
}
|
||||
|
||||
internal static int KeyLengthInBytes(WinzipAesKeySize keySize)
|
||||
|
||||
@@ -27,33 +27,33 @@ namespace SharpCompress.Common.Zip
|
||||
switch (_filePart.Header.CompressionMethod)
|
||||
{
|
||||
case ZipCompressionMethod.BZip2:
|
||||
{
|
||||
return CompressionType.BZip2;
|
||||
}
|
||||
{
|
||||
return CompressionType.BZip2;
|
||||
}
|
||||
case ZipCompressionMethod.Deflate:
|
||||
{
|
||||
return CompressionType.Deflate;
|
||||
}
|
||||
{
|
||||
return CompressionType.Deflate;
|
||||
}
|
||||
case ZipCompressionMethod.Deflate64:
|
||||
{
|
||||
return CompressionType.Deflate64;
|
||||
}
|
||||
{
|
||||
return CompressionType.Deflate64;
|
||||
}
|
||||
case ZipCompressionMethod.LZMA:
|
||||
{
|
||||
return CompressionType.LZMA;
|
||||
}
|
||||
{
|
||||
return CompressionType.LZMA;
|
||||
}
|
||||
case ZipCompressionMethod.PPMd:
|
||||
{
|
||||
return CompressionType.PPMd;
|
||||
}
|
||||
{
|
||||
return CompressionType.PPMd;
|
||||
}
|
||||
case ZipCompressionMethod.None:
|
||||
{
|
||||
return CompressionType.None;
|
||||
}
|
||||
{
|
||||
return CompressionType.None;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return CompressionType.Unknown;
|
||||
}
|
||||
{
|
||||
return CompressionType.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,72 +60,72 @@ namespace SharpCompress.Common.Zip
|
||||
switch (method)
|
||||
{
|
||||
case ZipCompressionMethod.None:
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
case ZipCompressionMethod.Deflate:
|
||||
{
|
||||
return new DeflateStream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
{
|
||||
return new DeflateStream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
case ZipCompressionMethod.Deflate64:
|
||||
{
|
||||
return new Deflate64Stream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
{
|
||||
return new Deflate64Stream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
case ZipCompressionMethod.BZip2:
|
||||
{
|
||||
return new BZip2Stream(stream, CompressionMode.Decompress, false);
|
||||
}
|
||||
{
|
||||
return new BZip2Stream(stream, CompressionMode.Decompress, false);
|
||||
}
|
||||
case ZipCompressionMethod.LZMA:
|
||||
{
|
||||
if (FlagUtility.HasFlag(Header.Flags, HeaderFlags.Encrypted))
|
||||
{
|
||||
throw new NotSupportedException("LZMA with pkware encryption.");
|
||||
if (FlagUtility.HasFlag(Header.Flags, HeaderFlags.Encrypted))
|
||||
{
|
||||
throw new NotSupportedException("LZMA with pkware encryption.");
|
||||
}
|
||||
var reader = new BinaryReader(stream);
|
||||
reader.ReadUInt16(); //LZMA version
|
||||
var props = new byte[reader.ReadUInt16()];
|
||||
reader.Read(props, 0, props.Length);
|
||||
return new LzmaStream(props, stream,
|
||||
Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
|
||||
FlagUtility.HasFlag(Header.Flags, HeaderFlags.Bit1)
|
||||
? -1
|
||||
: (long)Header.UncompressedSize);
|
||||
}
|
||||
var reader = new BinaryReader(stream);
|
||||
reader.ReadUInt16(); //LZMA version
|
||||
var props = new byte[reader.ReadUInt16()];
|
||||
reader.Read(props, 0, props.Length);
|
||||
return new LzmaStream(props, stream,
|
||||
Header.CompressedSize > 0 ? Header.CompressedSize - 4 - props.Length : -1,
|
||||
FlagUtility.HasFlag(Header.Flags, HeaderFlags.Bit1)
|
||||
? -1
|
||||
: (long)Header.UncompressedSize);
|
||||
}
|
||||
case ZipCompressionMethod.PPMd:
|
||||
{
|
||||
var props = new byte[2];
|
||||
stream.ReadFully(props);
|
||||
return new PpmdStream(new PpmdProperties(props), stream, false);
|
||||
}
|
||||
{
|
||||
var props = new byte[2];
|
||||
stream.ReadFully(props);
|
||||
return new PpmdStream(new PpmdProperties(props), stream, false);
|
||||
}
|
||||
case ZipCompressionMethod.WinzipAes:
|
||||
{
|
||||
ExtraData data = Header.Extra.Where(x => x.Type == ExtraDataType.WinZipAes).SingleOrDefault();
|
||||
if (data is null)
|
||||
{
|
||||
throw new InvalidFormatException("No Winzip AES extra data found.");
|
||||
}
|
||||
if (data.Length != 7)
|
||||
{
|
||||
throw new InvalidFormatException("Winzip data length is not 7.");
|
||||
}
|
||||
ushort compressedMethod = BinaryPrimitives.ReadUInt16LittleEndian(data.DataBytes);
|
||||
ExtraData? data = Header.Extra.SingleOrDefault(x => x.Type == ExtraDataType.WinZipAes);
|
||||
if (data is null)
|
||||
{
|
||||
throw new InvalidFormatException("No Winzip AES extra data found.");
|
||||
}
|
||||
if (data.Length != 7)
|
||||
{
|
||||
throw new InvalidFormatException("Winzip data length is not 7.");
|
||||
}
|
||||
ushort compressedMethod = BinaryPrimitives.ReadUInt16LittleEndian(data.DataBytes);
|
||||
|
||||
if (compressedMethod != 0x01 && compressedMethod != 0x02)
|
||||
{
|
||||
throw new InvalidFormatException("Unexpected vendor version number for WinZip AES metadata");
|
||||
}
|
||||
if (compressedMethod != 0x01 && compressedMethod != 0x02)
|
||||
{
|
||||
throw new InvalidFormatException("Unexpected vendor version number for WinZip AES metadata");
|
||||
}
|
||||
|
||||
ushort vendorId = BinaryPrimitives.ReadUInt16LittleEndian(data.DataBytes.AsSpan(2));
|
||||
if (vendorId != 0x4541)
|
||||
{
|
||||
throw new InvalidFormatException("Unexpected vendor ID for WinZip AES metadata");
|
||||
ushort vendorId = BinaryPrimitives.ReadUInt16LittleEndian(data.DataBytes.AsSpan(2));
|
||||
if (vendorId != 0x4541)
|
||||
{
|
||||
throw new InvalidFormatException("Unexpected vendor ID for WinZip AES metadata");
|
||||
}
|
||||
return CreateDecompressionStream(stream, (ZipCompressionMethod)BinaryPrimitives.ReadUInt16LittleEndian(data.DataBytes.AsSpan(5)));
|
||||
}
|
||||
return CreateDecompressionStream(stream, (ZipCompressionMethod)BinaryPrimitives.ReadUInt16LittleEndian(data.DataBytes.AsSpan(5)));
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new NotSupportedException("CompressionMethod: " + Header.CompressionMethod);
|
||||
}
|
||||
{
|
||||
throw new NotSupportedException("CompressionMethod: " + Header.CompressionMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,23 +159,23 @@ namespace SharpCompress.Common.Zip
|
||||
case ZipCompressionMethod.BZip2:
|
||||
case ZipCompressionMethod.LZMA:
|
||||
case ZipCompressionMethod.PPMd:
|
||||
{
|
||||
return new PkwareTraditionalCryptoStream(plainStream, Header.ComposeEncryptionData(plainStream), CryptoMode.Decrypt);
|
||||
}
|
||||
{
|
||||
return new PkwareTraditionalCryptoStream(plainStream, Header.ComposeEncryptionData(plainStream), CryptoMode.Decrypt);
|
||||
}
|
||||
|
||||
case ZipCompressionMethod.WinzipAes:
|
||||
{
|
||||
if (Header.WinzipAesEncryptionData != null)
|
||||
{
|
||||
return new WinzipAesCryptoStream(plainStream, Header.WinzipAesEncryptionData, Header.CompressedSize - 10);
|
||||
if (Header.WinzipAesEncryptionData != null)
|
||||
{
|
||||
return new WinzipAesCryptoStream(plainStream, Header.WinzipAesEncryptionData, Header.CompressedSize - 10);
|
||||
}
|
||||
return plainStream;
|
||||
}
|
||||
return plainStream;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,20 +35,20 @@ namespace SharpCompress.Common.Zip
|
||||
switch (headerBytes)
|
||||
{
|
||||
case ENTRY_HEADER_BYTES:
|
||||
{
|
||||
var entryHeader = new LocalEntryHeader(_archiveEncoding);
|
||||
entryHeader.Read(reader);
|
||||
LoadHeader(entryHeader, reader.BaseStream);
|
||||
{
|
||||
var entryHeader = new LocalEntryHeader(_archiveEncoding);
|
||||
entryHeader.Read(reader);
|
||||
LoadHeader(entryHeader, reader.BaseStream);
|
||||
|
||||
_lastEntryHeader = entryHeader;
|
||||
return entryHeader;
|
||||
}
|
||||
_lastEntryHeader = entryHeader;
|
||||
return entryHeader;
|
||||
}
|
||||
case DIRECTORY_START_HEADER_BYTES:
|
||||
{
|
||||
var entry = new DirectoryEntryHeader(_archiveEncoding);
|
||||
entry.Read(reader);
|
||||
return entry;
|
||||
}
|
||||
{
|
||||
var entry = new DirectoryEntryHeader(_archiveEncoding);
|
||||
entry.Read(reader);
|
||||
return entry;
|
||||
}
|
||||
case POST_DATA_DESCRIPTOR:
|
||||
{
|
||||
if (FlagUtility.HasFlag(_lastEntryHeader!.Flags, HeaderFlags.UsePostDataDescriptor))
|
||||
@@ -129,7 +129,7 @@ namespace SharpCompress.Common.Zip
|
||||
|
||||
if (entryHeader.CompressionMethod == ZipCompressionMethod.WinzipAes)
|
||||
{
|
||||
ExtraData data = entryHeader.Extra.SingleOrDefault(x => x.Type == ExtraDataType.WinZipAes);
|
||||
ExtraData? data = entryHeader.Extra.SingleOrDefault(x => x.Type == ExtraDataType.WinZipAes);
|
||||
if (data != null)
|
||||
{
|
||||
var keySize = (WinzipAesKeySize)data.DataBytes[4];
|
||||
|
||||
@@ -52,32 +52,24 @@ namespace SharpCompress.Compressors.ADC
|
||||
|
||||
private static int GetChunkSize(byte byt)
|
||||
{
|
||||
switch (GetChunkType(byt))
|
||||
return GetChunkType(byt) switch
|
||||
{
|
||||
case PLAIN:
|
||||
return (byt & 0x7F) + 1;
|
||||
case TWO_BYTE:
|
||||
return ((byt & 0x3F) >> 2) + 3;
|
||||
case THREE_BYTE:
|
||||
return (byt & 0x3F) + 4;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
PLAIN => (byt & 0x7F) + 1,
|
||||
TWO_BYTE => ((byt & 0x3F) >> 2) + 3,
|
||||
THREE_BYTE => (byt & 0x3F) + 4,
|
||||
_ => -1,
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetOffset(ReadOnlySpan<byte> chunk)
|
||||
{
|
||||
switch (GetChunkType(chunk[0]))
|
||||
return GetChunkType(chunk[0]) switch
|
||||
{
|
||||
case PLAIN:
|
||||
return 0;
|
||||
case TWO_BYTE:
|
||||
return ((chunk[0] & 0x03) << 8) + chunk[1];
|
||||
case THREE_BYTE:
|
||||
return (chunk[1] << 8) + chunk[2];
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
PLAIN => 0,
|
||||
TWO_BYTE => ((chunk[0] & 0x03) << 8) + chunk[1],
|
||||
THREE_BYTE => (chunk[1] << 8) + chunk[2],
|
||||
_ => -1,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Compressors.BZip2
|
||||
{
|
||||
public class BZip2Stream : Stream
|
||||
public sealed class BZip2Stream : Stream
|
||||
{
|
||||
private readonly Stream stream;
|
||||
private bool isDisposed;
|
||||
@@ -82,6 +83,20 @@ namespace SharpCompress.Compressors.BZip2
|
||||
stream.SetLength(value);
|
||||
}
|
||||
|
||||
#if !NET461 && !NETSTANDARD2_0
|
||||
|
||||
public override int Read(Span<byte> buffer)
|
||||
{
|
||||
return stream.Read(buffer);
|
||||
}
|
||||
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
stream.Write(buffer);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
stream.Write(buffer, offset, count);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
/*
|
||||
@@ -835,7 +836,7 @@ namespace SharpCompress.Compressors.BZip2
|
||||
|
||||
private void SetupBlock()
|
||||
{
|
||||
int[] cftab = new int[257];
|
||||
Span<int> cftab = stackalloc int[257];
|
||||
char ch;
|
||||
|
||||
cftab[0] = 0;
|
||||
@@ -854,7 +855,6 @@ namespace SharpCompress.Compressors.BZip2
|
||||
tt[cftab[ch]] = i;
|
||||
cftab[ch]++;
|
||||
}
|
||||
cftab = null;
|
||||
|
||||
tPos = tt[origPtr];
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
/*
|
||||
* Copyright 2001,2004-2005 The Apache Software Foundation
|
||||
@@ -88,9 +89,9 @@ namespace SharpCompress.Compressors.BZip2
|
||||
int nNodes, nHeap, n1, n2, i, j, k;
|
||||
bool tooLong;
|
||||
|
||||
int[] heap = new int[BZip2Constants.MAX_ALPHA_SIZE + 2];
|
||||
int[] weight = new int[BZip2Constants.MAX_ALPHA_SIZE * 2];
|
||||
int[] parent = new int[BZip2Constants.MAX_ALPHA_SIZE * 2];
|
||||
Span<int> heap = stackalloc int[BZip2Constants.MAX_ALPHA_SIZE + 2]; // 1040 bytes
|
||||
Span<int> weight = stackalloc int[BZip2Constants.MAX_ALPHA_SIZE * 2]; // 1040 bytes
|
||||
Span<int> parent = stackalloc int[BZip2Constants.MAX_ALPHA_SIZE * 2]; // 1040 bytes
|
||||
|
||||
for (i = 0; i < alphaSize; i++)
|
||||
{
|
||||
@@ -603,14 +604,7 @@ namespace SharpCompress.Compressors.BZip2
|
||||
while (bsLive > 0)
|
||||
{
|
||||
int ch = (bsBuff >> 24);
|
||||
try
|
||||
{
|
||||
bsStream.WriteByte((byte)ch); // write 8-bit
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
bsStream.WriteByte((byte)ch); // write 8-bit
|
||||
bsBuff <<= 8;
|
||||
bsLive -= 8;
|
||||
bytesOut++;
|
||||
@@ -622,14 +616,7 @@ namespace SharpCompress.Compressors.BZip2
|
||||
while (bsLive >= 8)
|
||||
{
|
||||
int ch = (bsBuff >> 24);
|
||||
try
|
||||
{
|
||||
bsStream.WriteByte((byte)ch); // write 8-bit
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
bsStream.WriteByte((byte)ch); // write 8-bit
|
||||
bsBuff <<= 8;
|
||||
bsLive -= 8;
|
||||
bytesOut++;
|
||||
@@ -1328,8 +1315,8 @@ namespace SharpCompress.Compressors.BZip2
|
||||
private void MainSort()
|
||||
{
|
||||
int i, j, ss, sb;
|
||||
int[] runningOrder = new int[256];
|
||||
int[] copy = new int[256];
|
||||
Span<int> runningOrder = stackalloc int[256];
|
||||
Span<int> copy = stackalloc int[256];
|
||||
bool[] bigDone = new bool[256];
|
||||
int c1, c2;
|
||||
int numQSorted;
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
|
||||
// pre-initialize the crc table for speed of lookup.
|
||||
|
||||
private uint gf2_matrix_times(uint[] matrix, uint vec)
|
||||
private uint gf2_matrix_times(ReadOnlySpan<uint> matrix, uint vec)
|
||||
{
|
||||
uint sum = 0;
|
||||
int i = 0;
|
||||
@@ -205,7 +205,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
return sum;
|
||||
}
|
||||
|
||||
private void gf2_matrix_square(uint[] square, uint[] mat)
|
||||
private void gf2_matrix_square(Span<uint> square, Span<uint> mat)
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
@@ -225,8 +225,8 @@ namespace SharpCompress.Compressors.Deflate
|
||||
/// <param name="length">the length of data the CRC value was calculated on</param>
|
||||
public void Combine(int crc, int length)
|
||||
{
|
||||
var even = new uint[32]; // even-power-of-two zeros operator
|
||||
var odd = new uint[32]; // odd-power-of-two zeros operator
|
||||
Span<uint> even = stackalloc uint[32]; // even-power-of-two zeros operator
|
||||
Span<uint> odd = stackalloc uint[32]; // odd-power-of-two zeros operator
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
|
||||
using System;
|
||||
|
||||
using SharpCompress.Algorithms;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate
|
||||
{
|
||||
internal sealed partial class DeflateManager
|
||||
@@ -1685,7 +1687,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
Rfc1950BytesEmitted = false;
|
||||
|
||||
status = (WantRfc1950HeaderBytes) ? INIT_STATE : BUSY_STATE;
|
||||
_codec._Adler32 = Adler.Adler32(0, null, 0, 0);
|
||||
_codec._adler32 = 1;
|
||||
|
||||
last_flush = (int)FlushType.None;
|
||||
|
||||
@@ -1763,7 +1765,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
throw new ZlibException("Stream error.");
|
||||
}
|
||||
|
||||
_codec._Adler32 = Adler.Adler32(_codec._Adler32, dictionary, 0, dictionary.Length);
|
||||
_codec._adler32 = Adler32.Calculate(_codec._adler32, dictionary);
|
||||
|
||||
if (length < MIN_MATCH)
|
||||
{
|
||||
@@ -1850,12 +1852,12 @@ namespace SharpCompress.Compressors.Deflate
|
||||
////putShortMSB((int)(SharedUtils.URShift(_codec._Adler32, 16)));
|
||||
//putShortMSB((int)((UInt64)_codec._Adler32 >> 16));
|
||||
//putShortMSB((int)(_codec._Adler32 & 0xffff));
|
||||
pending[pendingCount++] = (byte)((_codec._Adler32 & 0xFF000000) >> 24);
|
||||
pending[pendingCount++] = (byte)((_codec._Adler32 & 0x00FF0000) >> 16);
|
||||
pending[pendingCount++] = (byte)((_codec._Adler32 & 0x0000FF00) >> 8);
|
||||
pending[pendingCount++] = (byte)(_codec._Adler32 & 0x000000FF);
|
||||
pending[pendingCount++] = (byte)((_codec._adler32 & 0xFF000000) >> 24);
|
||||
pending[pendingCount++] = (byte)((_codec._adler32 & 0x00FF0000) >> 16);
|
||||
pending[pendingCount++] = (byte)((_codec._adler32 & 0x0000FF00) >> 8);
|
||||
pending[pendingCount++] = (byte)(_codec._adler32 & 0x000000FF);
|
||||
}
|
||||
_codec._Adler32 = Adler.Adler32(0, null, 0, 0);
|
||||
_codec._adler32 = 1;
|
||||
}
|
||||
|
||||
// Flush as much pending output as possible
|
||||
@@ -1968,10 +1970,10 @@ namespace SharpCompress.Compressors.Deflate
|
||||
}
|
||||
|
||||
// Write the zlib trailer (adler32)
|
||||
pending[pendingCount++] = (byte)((_codec._Adler32 & 0xFF000000) >> 24);
|
||||
pending[pendingCount++] = (byte)((_codec._Adler32 & 0x00FF0000) >> 16);
|
||||
pending[pendingCount++] = (byte)((_codec._Adler32 & 0x0000FF00) >> 8);
|
||||
pending[pendingCount++] = (byte)(_codec._Adler32 & 0x000000FF);
|
||||
pending[pendingCount++] = (byte)((_codec._adler32 & 0xFF000000) >> 24);
|
||||
pending[pendingCount++] = (byte)((_codec._adler32 & 0x00FF0000) >> 16);
|
||||
pending[pendingCount++] = (byte)((_codec._adler32 & 0x0000FF00) >> 8);
|
||||
pending[pendingCount++] = (byte)(_codec._adler32 & 0x000000FF);
|
||||
|
||||
//putShortMSB((int)(SharedUtils.URShift(_codec._Adler32, 16)));
|
||||
//putShortMSB((int)(_codec._Adler32 & 0xffff));
|
||||
|
||||
@@ -37,10 +37,9 @@ namespace SharpCompress.Compressors.Deflate
|
||||
{
|
||||
internal static readonly DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
public DateTime? LastModified { get; set; }
|
||||
|
||||
private string? _comment;
|
||||
private string? _fileName;
|
||||
private DateTime? _lastModified;
|
||||
|
||||
internal ZlibBaseStream BaseStream;
|
||||
private bool _disposed;
|
||||
@@ -274,6 +273,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
_firstReadDone = true;
|
||||
FileName = BaseStream._GzipFileName;
|
||||
Comment = BaseStream._GzipComment;
|
||||
LastModified = BaseStream._GzipMtime;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -358,6 +358,20 @@ namespace SharpCompress.Compressors.Deflate
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public DateTime? LastModified
|
||||
{
|
||||
get => _lastModified;
|
||||
set
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(GZipStream));
|
||||
}
|
||||
_lastModified = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string? FileName
|
||||
{
|
||||
get => _fileName;
|
||||
@@ -372,28 +386,19 @@ namespace SharpCompress.Compressors.Deflate
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_fileName.Contains("/"))
|
||||
if (_fileName.Contains('/'))
|
||||
{
|
||||
_fileName = _fileName.Replace('/', '\\');
|
||||
}
|
||||
if (_fileName.EndsWith("\\"))
|
||||
if (_fileName.EndsWith('\\'))
|
||||
{
|
||||
throw new InvalidOperationException("Illegal filename");
|
||||
}
|
||||
|
||||
if (_fileName.Contains("\\"))
|
||||
if (_fileName.Contains('\\'))
|
||||
{
|
||||
// trim any leading path
|
||||
int length = _fileName.Length;
|
||||
int num = length;
|
||||
while (--num >= 0)
|
||||
{
|
||||
char c = _fileName[num];
|
||||
if (c == '\\')
|
||||
{
|
||||
_fileName = _fileName.Substring(num + 1, length - num - 1);
|
||||
}
|
||||
}
|
||||
_fileName = Path.GetFileName(_fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -407,8 +412,8 @@ namespace SharpCompress.Compressors.Deflate
|
||||
byte[]? filenameBytes = (FileName is null) ? null
|
||||
: _encoding.GetBytes(FileName);
|
||||
|
||||
int cbLength = (commentBytes is null) ? 0 : commentBytes.Length + 1;
|
||||
int fnLength = (filenameBytes is null) ? 0 : filenameBytes.Length + 1;
|
||||
int cbLength = commentBytes?.Length + 1 ?? 0;
|
||||
int fnLength = filenameBytes?.Length + 1 ?? 0;
|
||||
|
||||
int bufferLength = 10 + cbLength + fnLength;
|
||||
var header = new byte[bufferLength];
|
||||
@@ -434,7 +439,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
header[i++] = flag;
|
||||
|
||||
// mtime
|
||||
if (!LastModified.HasValue)
|
||||
if (LastModified is null)
|
||||
{
|
||||
LastModified = DateTime.Now;
|
||||
}
|
||||
@@ -456,7 +461,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
// filename
|
||||
if (fnLength != 0)
|
||||
{
|
||||
Array.Copy(filenameBytes, 0, header, i, fnLength - 1);
|
||||
Array.Copy(filenameBytes!, 0, header, i, fnLength - 1);
|
||||
i += fnLength - 1;
|
||||
header[i++] = 0; // terminate
|
||||
}
|
||||
@@ -464,7 +469,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
// comment
|
||||
if (cbLength != 0)
|
||||
{
|
||||
Array.Copy(commentBytes, 0, header, i, cbLength - 1);
|
||||
Array.Copy(commentBytes!, 0, header, i, cbLength - 1);
|
||||
i += cbLength - 1;
|
||||
header[i++] = 0; // terminate
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
|
||||
using System;
|
||||
|
||||
using SharpCompress.Algorithms;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate
|
||||
{
|
||||
internal sealed class InflateBlocks
|
||||
@@ -72,7 +74,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
private const int MANY = 1440;
|
||||
|
||||
// Table for deflate from PKZIP's appnote.txt.
|
||||
internal static readonly int[] border = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
internal static readonly int[] border = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
|
||||
|
||||
internal ZlibCodec _codec; // pointer back to this zlib stream
|
||||
internal int[] bb = new int[1]; // bit length tree depth
|
||||
@@ -118,7 +120,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
|
||||
if (checkfn != null)
|
||||
{
|
||||
_codec._Adler32 = check = Adler.Adler32(0, null, 0, 0);
|
||||
_codec._adler32 = check = 1;
|
||||
}
|
||||
return oldCheck;
|
||||
}
|
||||
@@ -559,35 +561,35 @@ namespace SharpCompress.Compressors.Deflate
|
||||
}
|
||||
|
||||
tb[0] = -1;
|
||||
{
|
||||
var bl = new[] {9}; // must be <= 9 for lookahead assumptions
|
||||
var bd = new[] {6}; // must be <= 9 for lookahead assumptions
|
||||
var tl = new int[1];
|
||||
var td = new int[1];
|
||||
|
||||
t = table;
|
||||
t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl,
|
||||
td, hufts, _codec);
|
||||
|
||||
if (t != ZlibConstants.Z_OK)
|
||||
{
|
||||
if (t == ZlibConstants.Z_DATA_ERROR)
|
||||
{
|
||||
blens = null;
|
||||
mode = InflateBlockMode.BAD;
|
||||
}
|
||||
r = t;
|
||||
var bl = new[] { 9 }; // must be <= 9 for lookahead assumptions
|
||||
var bd = new[] { 6 }; // must be <= 9 for lookahead assumptions
|
||||
var tl = new int[1];
|
||||
var td = new int[1];
|
||||
|
||||
bitb = b;
|
||||
bitk = k;
|
||||
_codec.AvailableBytesIn = n;
|
||||
_codec.TotalBytesIn += p - _codec.NextIn;
|
||||
_codec.NextIn = p;
|
||||
writeAt = q;
|
||||
return Flush(r);
|
||||
t = table;
|
||||
t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl,
|
||||
td, hufts, _codec);
|
||||
|
||||
if (t != ZlibConstants.Z_OK)
|
||||
{
|
||||
if (t == ZlibConstants.Z_DATA_ERROR)
|
||||
{
|
||||
blens = null;
|
||||
mode = InflateBlockMode.BAD;
|
||||
}
|
||||
r = t;
|
||||
|
||||
bitb = b;
|
||||
bitk = k;
|
||||
_codec.AvailableBytesIn = n;
|
||||
_codec.TotalBytesIn += p - _codec.NextIn;
|
||||
_codec.NextIn = p;
|
||||
writeAt = q;
|
||||
return Flush(r);
|
||||
}
|
||||
codes.Init(bl[0], bd[0], hufts, tl[0], hufts, td[0]);
|
||||
}
|
||||
codes.Init(bl[0], bd[0], hufts, tl[0], hufts, td[0]);
|
||||
}
|
||||
mode = InflateBlockMode.CODES;
|
||||
goto case InflateBlockMode.CODES;
|
||||
|
||||
@@ -739,7 +741,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
// update check information
|
||||
if (checkfn != null)
|
||||
{
|
||||
_codec._Adler32 = check = Adler.Adler32(check, window, readAt, nBytes);
|
||||
_codec._adler32 = check = Adler32.Calculate(check, window.AsSpan(readAt, nBytes));
|
||||
}
|
||||
|
||||
// copy as far as end of window
|
||||
@@ -1565,7 +1567,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
private const int PRESET_DICT = 0x20;
|
||||
|
||||
private const int Z_DEFLATED = 8;
|
||||
private static readonly byte[] mark = {0, 0, 0xff, 0xff};
|
||||
private static readonly byte[] mark = { 0, 0, 0xff, 0xff };
|
||||
|
||||
internal ZlibCodec _codec; // pointer back to this zlib stream
|
||||
internal InflateBlocks blocks; // current inflate_blocks state
|
||||
@@ -1764,7 +1766,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
_codec.AvailableBytesIn--;
|
||||
_codec.TotalBytesIn++;
|
||||
expectedCheck += (uint)(_codec.InputBuffer[_codec.NextIn++] & 0x000000ff);
|
||||
_codec._Adler32 = expectedCheck;
|
||||
_codec._adler32 = expectedCheck;
|
||||
mode = InflateManagerMode.DICT0;
|
||||
return ZlibConstants.Z_NEED_DICT;
|
||||
|
||||
@@ -1879,12 +1881,12 @@ namespace SharpCompress.Compressors.Deflate
|
||||
throw new ZlibException("Stream error.");
|
||||
}
|
||||
|
||||
if (Adler.Adler32(1, dictionary, 0, dictionary.Length) != _codec._Adler32)
|
||||
if (Adler32.Calculate(1, dictionary) != _codec._adler32)
|
||||
{
|
||||
return ZlibConstants.Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
_codec._Adler32 = Adler.Adler32(0, null, 0, 0);
|
||||
_codec._adler32 = 1;
|
||||
|
||||
if (length >= (1 << wbits))
|
||||
{
|
||||
|
||||
@@ -374,7 +374,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
};
|
||||
|
||||
// extra bits for each bit length code
|
||||
internal static readonly int[] extra_blbits = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
|
||||
internal static readonly int[] extra_blbits = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
|
||||
|
||||
internal static readonly StaticTree Literals;
|
||||
internal static readonly StaticTree Distances;
|
||||
@@ -405,88 +405,4 @@ namespace SharpCompress.Compressors.Deflate
|
||||
BitLengths = new StaticTree(null, extra_blbits, 0, InternalConstants.BL_CODES, InternalConstants.MAX_BL_BITS);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes an Adler-32 checksum.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Adler checksum is similar to a CRC checksum, but faster to compute, though less
|
||||
/// reliable. It is used in producing RFC1950 compressed streams. The Adler checksum
|
||||
/// is a required part of the "ZLIB" standard. Applications will almost never need to
|
||||
/// use this class directly.
|
||||
/// </remarks>
|
||||
internal sealed class Adler
|
||||
{
|
||||
// largest prime smaller than 65536
|
||||
private static readonly uint BASE = 65521U;
|
||||
|
||||
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
||||
private static readonly int NMAX = 5552;
|
||||
|
||||
internal static uint Adler32(uint adler, byte[]? buf, int index, int len)
|
||||
{
|
||||
if (buf is null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint s1 = adler & 0xffffU;
|
||||
uint s2 = (adler >> 16) & 0xffffU;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
int k = len < NMAX ? len : NMAX;
|
||||
len -= k;
|
||||
while (k >= 16)
|
||||
{
|
||||
//s1 += (buf[index++] & 0xff); s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
k -= 16;
|
||||
}
|
||||
if (k != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
s1 += buf[index++];
|
||||
s2 += s1;
|
||||
}
|
||||
while (--k != 0);
|
||||
}
|
||||
s1 %= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,12 +228,12 @@ namespace SharpCompress.Compressors.Deflate
|
||||
if (_wantCompress)
|
||||
{
|
||||
// Emit the GZIP trailer: CRC32 and size mod 2^32
|
||||
byte[] intBuf = new byte[4];
|
||||
Span<byte> intBuf = stackalloc byte[4];
|
||||
BinaryPrimitives.WriteInt32LittleEndian(intBuf, crc.Crc32Result);
|
||||
_stream.Write(intBuf, 0, 4);
|
||||
int c2 = (Int32)(crc.TotalBytesRead & 0x00000000FFFFFFFF);
|
||||
_stream.Write(intBuf);
|
||||
int c2 = (int)(crc.TotalBytesRead & 0x00000000FFFFFFFF);
|
||||
BinaryPrimitives.WriteInt32LittleEndian(intBuf, c2);
|
||||
_stream.Write(intBuf, 0, 4);
|
||||
_stream.Write(intBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -413,8 +413,8 @@ namespace SharpCompress.Compressors.Deflate
|
||||
int totalBytesRead = 0;
|
||||
|
||||
// read the header on the first read
|
||||
byte[] header = new byte[10];
|
||||
int n = _stream.Read(header, 0, header.Length);
|
||||
Span<byte> header = stackalloc byte[10];
|
||||
int n = _stream.Read(header);
|
||||
|
||||
// workitem 8501: handle edge case (decompress empty stream)
|
||||
if (n == 0)
|
||||
@@ -432,16 +432,16 @@ namespace SharpCompress.Compressors.Deflate
|
||||
throw new ZlibException("Bad GZIP header.");
|
||||
}
|
||||
|
||||
Int32 timet = BinaryPrimitives.ReadInt32LittleEndian(header.AsSpan(4));
|
||||
int timet = BinaryPrimitives.ReadInt32LittleEndian(header.Slice(4));
|
||||
_GzipMtime = TarHeader.EPOCH.AddSeconds(timet);
|
||||
totalBytesRead += n;
|
||||
if ((header[3] & 0x04) == 0x04)
|
||||
{
|
||||
// read and discard extra field
|
||||
n = _stream.Read(header, 0, 2); // 2-byte length field
|
||||
n = _stream.Read(header.Slice(0, 2)); // 2-byte length field
|
||||
totalBytesRead += n;
|
||||
|
||||
Int16 extraLength = (Int16)(header[0] + header[1] * 256);
|
||||
short extraLength = (short)(header[0] + header[1] * 256);
|
||||
byte[] extra = new byte[extraLength];
|
||||
n = _stream.Read(extra, 0, extra.Length);
|
||||
if (n != extraLength)
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
internal DeflateManager dstate;
|
||||
internal InflateManager istate;
|
||||
|
||||
internal uint _Adler32;
|
||||
internal uint _adler32;
|
||||
|
||||
/// <summary>
|
||||
/// The compression level to use in this codec. Useful only in compression mode.
|
||||
@@ -173,7 +173,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
/// <summary>
|
||||
/// The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this.
|
||||
/// </summary>
|
||||
public int Adler32 => (int)_Adler32;
|
||||
public int Adler32 => (int)_adler32;
|
||||
|
||||
/// <summary>
|
||||
/// Create a ZlibCodec.
|
||||
@@ -737,7 +737,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
|
||||
if (dstate.WantRfc1950HeaderBytes)
|
||||
{
|
||||
_Adler32 = Adler.Adler32(_Adler32, InputBuffer, NextIn, len);
|
||||
_adler32 = Algorithms.Adler32.Calculate(_adler32, InputBuffer.AsSpan(NextIn, len));
|
||||
}
|
||||
Array.Copy(InputBuffer, NextIn, buf, start, len);
|
||||
NextIn += len;
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace SharpCompress.Compressors.Deflate
|
||||
/// <summary>
|
||||
/// The size of the working buffer used in the ZlibCodec class. Defaults to 8192 bytes.
|
||||
/// </summary>
|
||||
#if NETCF
|
||||
#if NETCF
|
||||
public const int WorkingBufferSizeDefault = 8192;
|
||||
#else
|
||||
public const int WorkingBufferSizeDefault = 16384;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace SharpCompress.Compressors.Deflate64
|
||||
@@ -10,7 +11,7 @@ namespace SharpCompress.Compressors.Deflate64
|
||||
{
|
||||
// static information for encoding, DO NOT MODIFY
|
||||
|
||||
internal static readonly byte[] FAST_ENCODER_TREE_STRUCTURE_DATA =
|
||||
internal static ReadOnlySpan<byte> FAST_ENCODER_TREE_STRUCTURE_DATA => new byte[]
|
||||
{
|
||||
0xec,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d,0xca,
|
||||
0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60,
|
||||
@@ -23,7 +24,7 @@ namespace SharpCompress.Compressors.Deflate64
|
||||
0x1f,0x3f
|
||||
};
|
||||
|
||||
internal static readonly byte[] B_FINAL_FAST_ENCODER_TREE_STRUCTURE_DATA =
|
||||
internal static ReadOnlySpan<byte> B_FINAL_FAST_ENCODER_TREE_STRUCTURE_DATA => new byte[]
|
||||
{
|
||||
0xed,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d,0xca,
|
||||
0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
@@ -118,14 +119,14 @@ namespace SharpCompress.Compressors.Deflate64
|
||||
// This algorithm is described in standard RFC 1951
|
||||
private uint[] CalculateHuffmanCode()
|
||||
{
|
||||
uint[] bitLengthCount = new uint[17];
|
||||
Span<uint> bitLengthCount = stackalloc uint[17];
|
||||
foreach (int codeLength in _codeLengthArray)
|
||||
{
|
||||
bitLengthCount[codeLength]++;
|
||||
}
|
||||
bitLengthCount[0] = 0; // clear count for length 0
|
||||
|
||||
uint[] nextCode = new uint[17];
|
||||
Span<uint> nextCode = stackalloc uint[17];
|
||||
uint tempCode = 0;
|
||||
for (int bits = 1; bits <= 16; bits++)
|
||||
{
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace SharpCompress.Compressors.Deflate64
|
||||
private void Reset()
|
||||
{
|
||||
_state = //_hasFormatReader ?
|
||||
//InflaterState.ReadingHeader : // start by reading Header info
|
||||
//InflaterState.ReadingHeader : // start by reading Header info
|
||||
InflaterState.ReadingBFinal; // start by reading BFinal bit
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ namespace SharpCompress.Compressors.Deflate64
|
||||
//if (_hasFormatReader)
|
||||
// _state = InflaterState.StartReadingFooter;
|
||||
//else
|
||||
_state = InflaterState.Done;
|
||||
_state = InflaterState.Done;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -38,14 +38,14 @@ namespace SharpCompress.Compressors.Deflate64
|
||||
public void WriteLengthDistance(int length, int distance)
|
||||
{
|
||||
Debug.Assert((_bytesUsed + length) <= WINDOW_SIZE, "No Enough space");
|
||||
|
||||
|
||||
// move backwards distance bytes in the output stream,
|
||||
// and copy length bytes from this position to the output stream.
|
||||
_bytesUsed += length;
|
||||
int copyStart = (_end - distance) & WINDOW_MASK; // start position for coping.
|
||||
|
||||
int border = WINDOW_SIZE - length;
|
||||
if (copyStart <= border && _end < border)
|
||||
if (copyStart <= border && _end < border)
|
||||
{
|
||||
if (length <= distance)
|
||||
{
|
||||
|
||||
@@ -4,9 +4,9 @@ namespace SharpCompress.Compressors.Filters
|
||||
{
|
||||
internal class BCJFilter : Filter
|
||||
{
|
||||
private static readonly bool[] MASK_TO_ALLOWED_STATUS = {true, true, true, false, true, false, false, false};
|
||||
private static readonly bool[] MASK_TO_ALLOWED_STATUS = { true, true, true, false, true, false, false, false };
|
||||
|
||||
private static readonly int[] MASK_TO_BIT_NUMBER = {0, 1, 2, 2, 3, 3, 3, 3};
|
||||
private static readonly int[] MASK_TO_BIT_NUMBER = { 0, 1, 2, 2, 3, 3, 3, 3 };
|
||||
|
||||
private int _pos;
|
||||
private int _prevMask;
|
||||
|
||||
@@ -6,10 +6,8 @@ using SharpCompress.Compressors.LZMA.Utilites;
|
||||
|
||||
namespace SharpCompress.Compressors.LZMA
|
||||
{
|
||||
internal class AesDecoderStream : DecoderStream2
|
||||
internal sealed class AesDecoderStream : DecoderStream2
|
||||
{
|
||||
#region Variables
|
||||
|
||||
private readonly Stream mStream;
|
||||
private readonly ICryptoTransform mDecoder;
|
||||
private readonly byte[] mBuffer;
|
||||
@@ -20,26 +18,24 @@ namespace SharpCompress.Compressors.LZMA
|
||||
private int mUnderflow;
|
||||
private bool isDisposed;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Stream Methods
|
||||
|
||||
public AesDecoderStream(Stream input, byte[] info, IPasswordProvider pass, long limit)
|
||||
{
|
||||
mStream = input;
|
||||
mLimit = limit;
|
||||
|
||||
if (((uint) input.Length & 15) != 0)
|
||||
if (((uint)input.Length & 15) != 0)
|
||||
{
|
||||
throw new NotSupportedException("AES decoder does not support padding.");
|
||||
}
|
||||
|
||||
int numCyclesPower;
|
||||
byte[] salt, seed;
|
||||
Init(info, out numCyclesPower, out salt, out seed);
|
||||
Init(info, out int numCyclesPower, out byte[] salt, out byte[] seed);
|
||||
|
||||
byte[] password = Encoding.Unicode.GetBytes(pass.CryptoGetTextPassword());
|
||||
byte[] key = InitKey(numCyclesPower, salt, password);
|
||||
byte[]? key = InitKey(numCyclesPower, salt, password);
|
||||
if (key == null)
|
||||
{
|
||||
throw new InvalidOperationException("Initialized with null key");
|
||||
}
|
||||
|
||||
using (var aes = Aes.Create())
|
||||
{
|
||||
@@ -72,21 +68,9 @@ namespace SharpCompress.Compressors.LZMA
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return mWritten;
|
||||
}
|
||||
}
|
||||
public override long Position => mWritten;
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return mLimit;
|
||||
}
|
||||
}
|
||||
public override long Length => mLimit;
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
@@ -127,7 +111,7 @@ namespace SharpCompress.Compressors.LZMA
|
||||
// the stream length is not a multiple of the block size.
|
||||
if (count > mLimit - mWritten)
|
||||
{
|
||||
count = (int) (mLimit - mWritten);
|
||||
count = (int)(mLimit - mWritten);
|
||||
}
|
||||
|
||||
// We cannot transform less than 16 bytes into the target buffer,
|
||||
@@ -150,8 +134,6 @@ namespace SharpCompress.Compressors.LZMA
|
||||
return processed;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void Init(byte[] info, out int numCyclesPower, out byte[] salt, out byte[] iv)
|
||||
@@ -199,7 +181,7 @@ namespace SharpCompress.Compressors.LZMA
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] InitKey(int mNumCyclesPower, byte[] salt, byte[] pass)
|
||||
private byte[]? InitKey(int mNumCyclesPower, byte[] salt, byte[] pass)
|
||||
{
|
||||
if (mNumCyclesPower == 0x3F)
|
||||
{
|
||||
@@ -220,54 +202,50 @@ namespace SharpCompress.Compressors.LZMA
|
||||
}
|
||||
else
|
||||
{
|
||||
#if NETSTANDARD1_3 || NETSTANDARD2_0
|
||||
using (IncrementalHash sha = IncrementalHash.CreateHash(HashAlgorithmName.SHA256))
|
||||
#if NETSTANDARD2_0
|
||||
using IncrementalHash sha = IncrementalHash.CreateHash(HashAlgorithmName.SHA256);
|
||||
byte[] counter = new byte[8];
|
||||
long numRounds = 1L << mNumCyclesPower;
|
||||
for (long round = 0; round < numRounds; round++)
|
||||
{
|
||||
byte[] counter = new byte[8];
|
||||
long numRounds = 1L << mNumCyclesPower;
|
||||
for (long round = 0; round < numRounds; round++)
|
||||
{
|
||||
sha.AppendData(salt, 0, salt.Length);
|
||||
sha.AppendData(pass, 0, pass.Length);
|
||||
sha.AppendData(counter, 0, 8);
|
||||
sha.AppendData(salt, 0, salt.Length);
|
||||
sha.AppendData(pass, 0, pass.Length);
|
||||
sha.AppendData(counter, 0, 8);
|
||||
|
||||
// This mirrors the counter so we don't have to convert long to byte[] each round.
|
||||
// (It also ensures the counter is little endian, which BitConverter does not.)
|
||||
for (int i = 0; i < 8; i++)
|
||||
// This mirrors the counter so we don't have to convert long to byte[] each round.
|
||||
// (It also ensures the counter is little endian, which BitConverter does not.)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (++counter[i] != 0)
|
||||
{
|
||||
if (++counter[i] != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sha.GetHashAndReset();
|
||||
}
|
||||
return sha.GetHashAndReset();
|
||||
#else
|
||||
using (var sha = SHA256.Create())
|
||||
using var sha = SHA256.Create();
|
||||
byte[] counter = new byte[8];
|
||||
long numRounds = 1L << mNumCyclesPower;
|
||||
for (long round = 0; round < numRounds; round++)
|
||||
{
|
||||
byte[] counter = new byte[8];
|
||||
long numRounds = 1L << mNumCyclesPower;
|
||||
for (long round = 0; round < numRounds; round++)
|
||||
{
|
||||
sha.TransformBlock(salt, 0, salt.Length, null, 0);
|
||||
sha.TransformBlock(pass, 0, pass.Length, null, 0);
|
||||
sha.TransformBlock(counter, 0, 8, null, 0);
|
||||
sha.TransformBlock(salt, 0, salt.Length, null, 0);
|
||||
sha.TransformBlock(pass, 0, pass.Length, null, 0);
|
||||
sha.TransformBlock(counter, 0, 8, null, 0);
|
||||
|
||||
// This mirrors the counter so we don't have to convert long to byte[] each round.
|
||||
// (It also ensures the counter is little endian, which BitConverter does not.)
|
||||
for (int i = 0; i < 8; i++)
|
||||
// This mirrors the counter so we don't have to convert long to byte[] each round.
|
||||
// (It also ensures the counter is little endian, which BitConverter does not.)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (++counter[i] != 0)
|
||||
{
|
||||
if (++counter[i] != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sha.TransformFinalBlock(counter, 0, 0);
|
||||
return sha.Hash;
|
||||
}
|
||||
|
||||
sha.TransformFinalBlock(counter, 0, 0);
|
||||
return sha.Hash;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace SharpCompress.Compressors.LZMA
|
||||
|
||||
byte prevByte = 0;
|
||||
uint processedBytes = 0;
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
byte b = 0;
|
||||
uint i;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace SharpCompress.Compressors.LZMA
|
||||
/// <summary>
|
||||
/// Stream supporting the LZIP format, as documented at http://www.nongnu.org/lzip/manual/lzip_manual.html
|
||||
/// </summary>
|
||||
public class LZipStream : Stream
|
||||
public sealed class LZipStream : Stream
|
||||
{
|
||||
private readonly Stream _stream;
|
||||
private readonly CountingWritableSubStream? _countingWritableSubStream;
|
||||
@@ -117,6 +117,23 @@ namespace SharpCompress.Compressors.LZMA
|
||||
|
||||
public override void SetLength(long value) => throw new NotImplementedException();
|
||||
|
||||
|
||||
#if !NET461 && !NETSTANDARD2_0
|
||||
|
||||
public override int Read(Span<byte> buffer)
|
||||
{
|
||||
return _stream.Read(buffer);
|
||||
}
|
||||
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
_stream.Write(buffer);
|
||||
|
||||
_writeCount += buffer.Length;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
_stream.Write(buffer, offset, count);
|
||||
@@ -151,9 +168,10 @@ namespace SharpCompress.Compressors.LZMA
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
// Read the header
|
||||
byte[] header = new byte[6];
|
||||
int n = stream.Read(header, 0, header.Length);
|
||||
Span<byte> header = stackalloc byte[6];
|
||||
int n = stream.Read(header);
|
||||
|
||||
// TODO: Handle reading only part of the header?
|
||||
|
||||
|
||||
@@ -766,7 +766,7 @@ namespace SharpCompress.Compressors.LZMA
|
||||
{
|
||||
offs += 2;
|
||||
}
|
||||
for (;; len++)
|
||||
for (; ; len++)
|
||||
{
|
||||
UInt32 distance = _matchDistances[offs + 1];
|
||||
UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
|
||||
@@ -1107,7 +1107,7 @@ namespace SharpCompress.Compressors.LZMA
|
||||
offs += 2;
|
||||
}
|
||||
|
||||
for (UInt32 lenTest = startLen;; lenTest++)
|
||||
for (UInt32 lenTest = startLen; ; lenTest++)
|
||||
{
|
||||
UInt32 curBack = _matchDistances[offs + 1];
|
||||
UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
|
||||
@@ -1665,129 +1665,129 @@ namespace SharpCompress.Compressors.LZMA
|
||||
switch (propIDs[i])
|
||||
{
|
||||
case CoderPropId.NumFastBytes:
|
||||
{
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
Int32 numFastBytes = (Int32)prop;
|
||||
if (numFastBytes < 5 || numFastBytes > Base.K_MATCH_MAX_LEN)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_numFastBytes = (UInt32)numFastBytes;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.Algorithm:
|
||||
{
|
||||
/*
|
||||
if (!(prop is Int32))
|
||||
throw new InvalidParamException();
|
||||
Int32 maximize = (Int32)prop;
|
||||
_fastMode = (maximize == 0);
|
||||
_maxMode = (maximize >= 2);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case CoderPropId.MatchFinder:
|
||||
{
|
||||
if (!(prop is String))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
EMatchFinderType matchFinderIndexPrev = _matchFinderType;
|
||||
int m = FindMatchFinder(((string)prop).ToUpper());
|
||||
if (m < 0)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_matchFinderType = (EMatchFinderType)m;
|
||||
if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
|
||||
{
|
||||
_dictionarySizePrev = 0xFFFFFFFF;
|
||||
_matchFinder = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CoderPropId.DictionarySize:
|
||||
{
|
||||
const int kDicLogSizeMaxCompress = 30;
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
;
|
||||
Int32 dictionarySize = (Int32)prop;
|
||||
if (dictionarySize < (UInt32)(1 << Base.K_DIC_LOG_SIZE_MIN) ||
|
||||
dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_dictionarySize = (UInt32)dictionarySize;
|
||||
int dicLogSize;
|
||||
for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
|
||||
{
|
||||
if (dictionarySize <= ((UInt32)(1) << dicLogSize))
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
break;
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
Int32 numFastBytes = (Int32)prop;
|
||||
if (numFastBytes < 5 || numFastBytes > Base.K_MATCH_MAX_LEN)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_numFastBytes = (UInt32)numFastBytes;
|
||||
break;
|
||||
}
|
||||
_distTableSize = (UInt32)dicLogSize * 2;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.PosStateBits:
|
||||
{
|
||||
if (!(prop is Int32))
|
||||
case CoderPropId.Algorithm:
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
/*
|
||||
if (!(prop is Int32))
|
||||
throw new InvalidParamException();
|
||||
Int32 maximize = (Int32)prop;
|
||||
_fastMode = (maximize == 0);
|
||||
_maxMode = (maximize >= 2);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
Int32 v = (Int32)prop;
|
||||
if (v < 0 || v > (UInt32)Base.K_NUM_POS_STATES_BITS_ENCODING_MAX)
|
||||
case CoderPropId.MatchFinder:
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
if (!(prop is String))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
EMatchFinderType matchFinderIndexPrev = _matchFinderType;
|
||||
int m = FindMatchFinder(((string)prop).ToUpper());
|
||||
if (m < 0)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_matchFinderType = (EMatchFinderType)m;
|
||||
if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
|
||||
{
|
||||
_dictionarySizePrev = 0xFFFFFFFF;
|
||||
_matchFinder = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
_posStateBits = v;
|
||||
_posStateMask = (((UInt32)1) << _posStateBits) - 1;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.LitPosBits:
|
||||
{
|
||||
if (!(prop is Int32))
|
||||
case CoderPropId.DictionarySize:
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
Int32 v = (Int32)prop;
|
||||
if (v < 0 || v > Base.K_NUM_LIT_POS_STATES_BITS_ENCODING_MAX)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_numLiteralPosStateBits = v;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.LitContextBits:
|
||||
{
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
Int32 v = (Int32)prop;
|
||||
if (v < 0 || v > Base.K_NUM_LIT_CONTEXT_BITS_MAX)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
const int kDicLogSizeMaxCompress = 30;
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
;
|
||||
_numLiteralContextBits = v;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.EndMarker:
|
||||
{
|
||||
if (!(prop is Boolean))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
Int32 dictionarySize = (Int32)prop;
|
||||
if (dictionarySize < (UInt32)(1 << Base.K_DIC_LOG_SIZE_MIN) ||
|
||||
dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_dictionarySize = (UInt32)dictionarySize;
|
||||
int dicLogSize;
|
||||
for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
|
||||
{
|
||||
if (dictionarySize <= ((UInt32)(1) << dicLogSize))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
_distTableSize = (UInt32)dicLogSize * 2;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.PosStateBits:
|
||||
{
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
Int32 v = (Int32)prop;
|
||||
if (v < 0 || v > (UInt32)Base.K_NUM_POS_STATES_BITS_ENCODING_MAX)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_posStateBits = v;
|
||||
_posStateMask = (((UInt32)1) << _posStateBits) - 1;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.LitPosBits:
|
||||
{
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
Int32 v = (Int32)prop;
|
||||
if (v < 0 || v > Base.K_NUM_LIT_POS_STATES_BITS_ENCODING_MAX)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
_numLiteralPosStateBits = v;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.LitContextBits:
|
||||
{
|
||||
if (!(prop is Int32))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
Int32 v = (Int32)prop;
|
||||
if (v < 0 || v > Base.K_NUM_LIT_CONTEXT_BITS_MAX)
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
;
|
||||
_numLiteralContextBits = v;
|
||||
break;
|
||||
}
|
||||
case CoderPropId.EndMarker:
|
||||
{
|
||||
if (!(prop is Boolean))
|
||||
{
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
SetWriteEndMarkerMode((Boolean)prop);
|
||||
break;
|
||||
}
|
||||
SetWriteEndMarkerMode((Boolean)prop);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new InvalidParamException();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace SharpCompress.Compressors.PPMd.H
|
||||
|
||||
private readonly int[][] _binSumm = new int[128][]; // binary SEE-contexts
|
||||
|
||||
private static readonly int[] INIT_BIN_ESC = {0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};
|
||||
private static readonly int[] INIT_BIN_ESC = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051 };
|
||||
|
||||
// Temp fields
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
@@ -846,7 +846,7 @@ namespace SharpCompress.Compressors.PPMd.H
|
||||
_charMask[rs.Symbol] = 0;
|
||||
_prevSuccess = 0;
|
||||
}
|
||||
for (;;)
|
||||
for (; ; )
|
||||
{
|
||||
State s = _tempState1.Initialize(Heap);
|
||||
int i;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace SharpCompress.Compressors.PPMd.H
|
||||
private int _suffix; // pointer ppmcontext
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ExpEscape'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly int[] EXP_ESCAPE = {25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2};
|
||||
public static readonly int[] EXP_ESCAPE = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||
|
||||
// Temp fields
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'tempState1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
0x6051
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> EXPONENTIAL_ESCAPES => new byte[] {25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2};
|
||||
private static ReadOnlySpan<byte> EXPONENTIAL_ESCAPES => new byte[] { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
|
||||
|
||||
#region Public Methods
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
_coder.RangeEncoderNormalize(target);
|
||||
}
|
||||
|
||||
StopEncoding:
|
||||
StopEncoding:
|
||||
_coder.RangeEncoderFlush(target);
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
_coder.RangeDecoderNormalize(source);
|
||||
}
|
||||
|
||||
StopDecoding:
|
||||
StopDecoding:
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -573,7 +573,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
_maximumContext = foundStateSuccessor;
|
||||
return;
|
||||
|
||||
RestartModel:
|
||||
RestartModel:
|
||||
RestoreModel(currentContext, minimumContext, foundStateSuccessor);
|
||||
}
|
||||
|
||||
@@ -633,7 +633,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
(byte)(((context.Suffix.NumberStatistics == 0) ? 1 : 0) & ((state.Frequency < 24) ? 1 : 0));
|
||||
}
|
||||
|
||||
LoopEntry:
|
||||
LoopEntry:
|
||||
if (state.Successor != upBranch)
|
||||
{
|
||||
context = state.Successor;
|
||||
@@ -643,7 +643,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
}
|
||||
while (context.Suffix != PpmContext.ZERO);
|
||||
|
||||
NoLoop:
|
||||
NoLoop:
|
||||
if (stateIndex == 0)
|
||||
{
|
||||
return context;
|
||||
@@ -767,7 +767,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
state.Frequency += (byte)((state.Frequency < 32) ? 1 : 0);
|
||||
}
|
||||
|
||||
LoopEntry:
|
||||
LoopEntry:
|
||||
if (state.Successor != PpmContext.ZERO)
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace SharpCompress.Compressors.PPMd.I1
|
||||
_numberMasked = context.NumberStatistics;
|
||||
return;
|
||||
|
||||
SymbolFound:
|
||||
SymbolFound:
|
||||
_coder._lowCount = lowCount;
|
||||
lowCount += state.Frequency;
|
||||
_coder._highCount = lowCount;
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace SharpCompress.Compressors.PPMd
|
||||
if (Version == PpmdVersion.I1)
|
||||
{
|
||||
_allocator ??= new Allocator();
|
||||
|
||||
|
||||
_allocator.Start(_allocatorSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,9 @@ namespace SharpCompress.Compressors.Rar
|
||||
{
|
||||
private static readonly uint[] crcTab;
|
||||
|
||||
public static uint CheckCrc(uint startCrc, byte b) {
|
||||
return (crcTab[((int) ((int) startCrc ^ (int) b)) & 0xff] ^ (startCrc >> 8));
|
||||
public static uint CheckCrc(uint startCrc, byte b)
|
||||
{
|
||||
return (crcTab[((int)((int)startCrc ^ (int)b)) & 0xff] ^ (startCrc >> 8));
|
||||
}
|
||||
|
||||
public static uint CheckCrc(uint startCrc, byte[] data, int offset, int count)
|
||||
|
||||
@@ -36,7 +36,8 @@ namespace SharpCompress.Compressors.Rar
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!isDisposed) {
|
||||
if (!isDisposed)
|
||||
{
|
||||
isDisposed = true;
|
||||
base.Dispose(disposing);
|
||||
readStream.Dispose();
|
||||
|
||||
@@ -2,9 +2,9 @@ namespace SharpCompress.Compressors.Rar.UnpackV1.Decode
|
||||
{
|
||||
internal enum FilterType : byte
|
||||
{
|
||||
// These values must not be changed, because we use them directly
|
||||
// in RAR5 compression and decompression code.
|
||||
FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
|
||||
FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
|
||||
// These values must not be changed, because we use them directly
|
||||
// in RAR5 compression and decompression code.
|
||||
FILTER_DELTA = 0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
|
||||
FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
|
||||
}
|
||||
}
|
||||
@@ -15,27 +15,27 @@ namespace SharpCompress.Compressors.Rar.UnpackV1.Decode
|
||||
public const int DC = 60;
|
||||
public const int LDC = 17;
|
||||
public const int RC = 28;
|
||||
// 20171217: NOTE: these constants seem to have been updated in the unrar src code
|
||||
// at some unknown point. updating causes decompression failure, not sure why.
|
||||
// public const int NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
// public const int DC = 64;
|
||||
// public const int LDC = 16;
|
||||
// public const int RC = 44;
|
||||
// 20171217: NOTE: these constants seem to have been updated in the unrar src code
|
||||
// at some unknown point. updating causes decompression failure, not sure why.
|
||||
// public const int NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
// public const int DC = 64;
|
||||
// public const int LDC = 16;
|
||||
// public const int RC = 44;
|
||||
public const int HUFF_TABLE_SIZE = NC + DC + RC + LDC;
|
||||
public const int BC = 20;
|
||||
public const int BC = 20;
|
||||
|
||||
public const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC30 = 60;
|
||||
public const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC30 = 60;
|
||||
public const uint LDC30 = 17;
|
||||
public const uint RC30 = 28;
|
||||
public const uint BC30 = 20;
|
||||
public const uint RC30 = 28;
|
||||
public const uint BC30 = 20;
|
||||
public const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
|
||||
|
||||
public const int NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const int DC20 = 48;
|
||||
public const int RC20 = 28;
|
||||
public const int BC20 = 19;
|
||||
public const int MC20 = 257;
|
||||
public const int NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const int DC20 = 48;
|
||||
public const int RC20 = 28;
|
||||
public const int BC20 = 19;
|
||||
public const int MC20 = 257;
|
||||
|
||||
// Largest alphabet size among all values listed above.
|
||||
public const uint LARGEST_TABLE_SIZE = 306;
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
{
|
||||
private readonly BitInput Inp;
|
||||
|
||||
public Unpack() {
|
||||
public Unpack()
|
||||
{
|
||||
// to ease in porting Unpack50.cs
|
||||
Inp = this;
|
||||
}
|
||||
@@ -86,7 +87,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
|
||||
private int lowDistRepCount;
|
||||
|
||||
private static readonly int[] DBitLengthCounts = {4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 14, 0, 12};
|
||||
private static readonly int[] DBitLengthCounts = { 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 14, 0, 12 };
|
||||
|
||||
private FileHeader fileHeader;
|
||||
|
||||
@@ -677,7 +678,8 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
destUnpSize -= size;
|
||||
}
|
||||
|
||||
private void InsertOldDist(uint distance) {
|
||||
private void InsertOldDist(uint distance)
|
||||
{
|
||||
// TODO uint
|
||||
InsertOldDist((int)distance);
|
||||
}
|
||||
@@ -696,9 +698,10 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
lastLength = length;
|
||||
}
|
||||
|
||||
private void CopyString(uint length, uint distance) {
|
||||
private void CopyString(uint length, uint distance)
|
||||
{
|
||||
// TODO uint
|
||||
CopyString((int)length, (int)distance) ;
|
||||
CopyString((int)length, (int)distance);
|
||||
}
|
||||
|
||||
private void CopyString(int length, int distance)
|
||||
@@ -743,7 +746,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
unpPtr = 0;
|
||||
wrPtr = 0;
|
||||
PpmEscChar = 2;
|
||||
WriteBorder=Math.Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
|
||||
WriteBorder = Math.Min(MaxWinSize, UNPACK_MAX_WRITE) & MaxWinMask;
|
||||
|
||||
InitFilters();
|
||||
}
|
||||
@@ -755,35 +758,35 @@ WriteBorder=Math.Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
|
||||
unpInitData20(solid);
|
||||
}
|
||||
|
||||
//void Unpack::UnpInitData(bool Solid)
|
||||
//{
|
||||
// if (!Solid)
|
||||
// {
|
||||
// memset(OldDist,0,sizeof(OldDist));
|
||||
// OldDistPtr=0;
|
||||
// LastDist=LastLength=0;
|
||||
//// memset(Window,0,MaxWinSize);
|
||||
// memset(&BlockTables,0,sizeof(BlockTables));
|
||||
// UnpPtr=WrPtr=0;
|
||||
// WriteBorder=Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
|
||||
// }
|
||||
// // Filters never share several solid files, so we can safely reset them
|
||||
// // even in solid archive.
|
||||
// InitFilters();
|
||||
//
|
||||
// Inp.InitBitInput();
|
||||
// WrittenFileSize=0;
|
||||
// ReadTop=0;
|
||||
// ReadBorder=0;
|
||||
//
|
||||
// memset(&BlockHeader,0,sizeof(BlockHeader));
|
||||
// BlockHeader.BlockSize=-1; // '-1' means not defined yet.
|
||||
//#ifndef SFX_MODULE
|
||||
// UnpInitData20(Solid);
|
||||
//#endif
|
||||
// UnpInitData30(Solid);
|
||||
// UnpInitData50(Solid);
|
||||
//}
|
||||
//void Unpack::UnpInitData(bool Solid)
|
||||
//{
|
||||
// if (!Solid)
|
||||
// {
|
||||
// memset(OldDist,0,sizeof(OldDist));
|
||||
// OldDistPtr=0;
|
||||
// LastDist=LastLength=0;
|
||||
//// memset(Window,0,MaxWinSize);
|
||||
// memset(&BlockTables,0,sizeof(BlockTables));
|
||||
// UnpPtr=WrPtr=0;
|
||||
// WriteBorder=Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
|
||||
// }
|
||||
// // Filters never share several solid files, so we can safely reset them
|
||||
// // even in solid archive.
|
||||
// InitFilters();
|
||||
//
|
||||
// Inp.InitBitInput();
|
||||
// WrittenFileSize=0;
|
||||
// ReadTop=0;
|
||||
// ReadBorder=0;
|
||||
//
|
||||
// memset(&BlockHeader,0,sizeof(BlockHeader));
|
||||
// BlockHeader.BlockSize=-1; // '-1' means not defined yet.
|
||||
//#ifndef SFX_MODULE
|
||||
// UnpInitData20(Solid);
|
||||
//#endif
|
||||
// UnpInitData30(Solid);
|
||||
// UnpInitData50(Solid);
|
||||
//}
|
||||
|
||||
private void InitFilters()
|
||||
{
|
||||
@@ -1063,7 +1066,7 @@ WriteBorder=Math.Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
|
||||
UnpackFilter Filter;
|
||||
if (NewFilter)
|
||||
|
||||
// new filter code, never used before since VM reset
|
||||
// new filter code, never used before since VM reset
|
||||
{
|
||||
// too many different filters, corrupt archive
|
||||
if (FiltPos > 1024)
|
||||
@@ -1121,8 +1124,8 @@ WriteBorder=Math.Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
|
||||
|
||||
if ((firstByte & 0x10) != 0)
|
||||
|
||||
// set registers to optional parameters
|
||||
// if any
|
||||
// set registers to optional parameters
|
||||
// if any
|
||||
{
|
||||
int InitMask = Utility.URShift(Inp.GetBits(), 9);
|
||||
Inp.AddBits(7);
|
||||
@@ -1208,7 +1211,7 @@ WriteBorder=Math.Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
|
||||
}
|
||||
if ((firstByte & 8) != 0)
|
||||
|
||||
// put data block passed as parameter if any
|
||||
// put data block passed as parameter if any
|
||||
{
|
||||
if (Inp.Overflow(3))
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
, 0xffff
|
||||
};
|
||||
|
||||
private static readonly int[] PosL1 = {0, 0, 0, 2, 3, 5, 7, 11, 16, 20, 24, 32, 32};
|
||||
private static readonly int[] PosL1 = { 0, 0, 0, 2, 3, 5, 7, 11, 16, 20, 24, 32, 32 };
|
||||
|
||||
private const int STARTL2 = 3;
|
||||
|
||||
@@ -76,39 +76,39 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
0xa000, 0xc000, 0xd000, 0xe000, 0xea00, 0xee00, 0xf000, 0xf200, 0xf240, 0xffff
|
||||
};
|
||||
|
||||
private static readonly int[] PosL2 = {0, 0, 0, 0, 5, 7, 9, 13, 18, 22, 26, 34, 36};
|
||||
private static readonly int[] PosL2 = { 0, 0, 0, 0, 5, 7, 9, 13, 18, 22, 26, 34, 36 };
|
||||
|
||||
private const int STARTHF0 = 4;
|
||||
|
||||
private static readonly int[] DecHf0 = {0x8000, 0xc000, 0xe000, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xffff};
|
||||
private static readonly int[] DecHf0 = { 0x8000, 0xc000, 0xe000, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xffff };
|
||||
|
||||
private static readonly int[] PosHf0 = {0, 0, 0, 0, 0, 8, 16, 24, 33, 33, 33, 33, 33};
|
||||
private static readonly int[] PosHf0 = { 0, 0, 0, 0, 0, 8, 16, 24, 33, 33, 33, 33, 33 };
|
||||
|
||||
private const int STARTHF1 = 5;
|
||||
|
||||
private static readonly int[] DecHf1 = {0x2000, 0xc000, 0xe000, 0xf000, 0xf200, 0xf200, 0xf7e0, 0xffff};
|
||||
private static readonly int[] DecHf1 = { 0x2000, 0xc000, 0xe000, 0xf000, 0xf200, 0xf200, 0xf7e0, 0xffff };
|
||||
|
||||
private static readonly int[] PosHf1 = {0, 0, 0, 0, 0, 0, 4, 44, 60, 76, 80, 80, 127};
|
||||
private static readonly int[] PosHf1 = { 0, 0, 0, 0, 0, 0, 4, 44, 60, 76, 80, 80, 127 };
|
||||
|
||||
private const int STARTHF2 = 5;
|
||||
|
||||
private static readonly int[] DecHf2 = {0x1000, 0x2400, 0x8000, 0xc000, 0xfa00, 0xffff, 0xffff, 0xffff};
|
||||
private static readonly int[] DecHf2 = { 0x1000, 0x2400, 0x8000, 0xc000, 0xfa00, 0xffff, 0xffff, 0xffff };
|
||||
|
||||
private static readonly int[] PosHf2 = {0, 0, 0, 0, 0, 0, 2, 7, 53, 117, 233, 0, 0};
|
||||
private static readonly int[] PosHf2 = { 0, 0, 0, 0, 0, 0, 2, 7, 53, 117, 233, 0, 0 };
|
||||
|
||||
private const int STARTHF3 = 6;
|
||||
|
||||
private static readonly int[] DecHf3 = {0x800, 0x2400, 0xee00, 0xfe80, 0xffff, 0xffff, 0xffff};
|
||||
private static readonly int[] DecHf3 = { 0x800, 0x2400, 0xee00, 0xfe80, 0xffff, 0xffff, 0xffff };
|
||||
|
||||
private static readonly int[] PosHf3 = {0, 0, 0, 0, 0, 0, 0, 2, 16, 218, 251, 0, 0};
|
||||
private static readonly int[] PosHf3 = { 0, 0, 0, 0, 0, 0, 0, 2, 16, 218, 251, 0, 0 };
|
||||
|
||||
private const int STARTHF4 = 8;
|
||||
|
||||
private static readonly int[] DecHf4 = {0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
|
||||
private static readonly int[] DecHf4 = { 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
|
||||
private static readonly int[] PosHf4 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0};
|
||||
private static readonly int[] PosHf4 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0 };
|
||||
|
||||
private static readonly int[] ShortLen1 = {1, 3, 4, 4, 5, 6, 7, 8, 8, 4, 4, 5, 6, 6, 4, 0};
|
||||
private static readonly int[] ShortLen1 = { 1, 3, 4, 4, 5, 6, 7, 8, 8, 4, 4, 5, 6, 6, 4, 0 };
|
||||
|
||||
private static readonly int[] ShortXor1 =
|
||||
{
|
||||
@@ -116,7 +116,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
, 0x9c, 0xb0
|
||||
};
|
||||
|
||||
private static readonly int[] ShortLen2 = {2, 3, 3, 3, 4, 4, 5, 6, 6, 4, 4, 5, 6, 6, 4, 0};
|
||||
private static readonly int[] ShortLen2 = { 2, 3, 3, 3, 4, 4, 5, 6, 6, 4, 4, 5, 6, 6, 4, 0 };
|
||||
|
||||
private static readonly int[] ShortXor2 =
|
||||
{
|
||||
@@ -290,7 +290,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
BitField = Utility.URShift(BitField, 8);
|
||||
if (AvrLn1 < 37)
|
||||
{
|
||||
for (Length = 0;; Length++)
|
||||
for (Length = 0; ; Length++)
|
||||
{
|
||||
if (((BitField ^ ShortXor1[Length]) & (~(Utility.URShift(0xff, getShortLen1(Length))))) == 0)
|
||||
{
|
||||
@@ -301,7 +301,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Length = 0;; Length++)
|
||||
for (Length = 0; ; Length++)
|
||||
{
|
||||
if (((BitField ^ ShortXor2[Length]) & (~(0xff >> getShortLen2(Length)))) == 0)
|
||||
{
|
||||
|
||||
@@ -60,9 +60,9 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
, 16, 16, 16, 16, 16, 16, 16
|
||||
};
|
||||
|
||||
private static readonly int[] SDDecode = {0, 4, 8, 16, 32, 64, 128, 192};
|
||||
private static readonly int[] SDDecode = { 0, 4, 8, 16, 32, 64, 128, 192 };
|
||||
|
||||
private static readonly int[] SDBits = {2, 2, 3, 4, 5, 6, 6, 6};
|
||||
private static readonly int[] SDBits = { 2, 2, 3, 4, 5, 6, 6, 6 };
|
||||
|
||||
private void unpack20(bool solid)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,29 +3,29 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
{
|
||||
internal partial class Unpack
|
||||
{
|
||||
private uint SlotToLength(uint Slot)
|
||||
private uint SlotToLength(uint Slot)
|
||||
{
|
||||
//uint LBits,Length=2;
|
||||
int LBits;
|
||||
uint Length=2;
|
||||
if (Slot<8)
|
||||
{
|
||||
LBits=0;
|
||||
Length+=Slot;
|
||||
}
|
||||
else
|
||||
{
|
||||
//LBits=Slot/4-1;
|
||||
LBits=(int)(Slot/4-1);
|
||||
Length+=(4 | (Slot & 3)) << LBits;
|
||||
}
|
||||
//uint LBits,Length=2;
|
||||
int LBits;
|
||||
uint Length = 2;
|
||||
if (Slot < 8)
|
||||
{
|
||||
LBits = 0;
|
||||
Length += Slot;
|
||||
}
|
||||
else
|
||||
{
|
||||
//LBits=Slot/4-1;
|
||||
LBits = (int)(Slot / 4 - 1);
|
||||
Length += (4 | (Slot & 3)) << LBits;
|
||||
}
|
||||
|
||||
if (LBits>0)
|
||||
{
|
||||
Length+=getbits()>>(16-LBits);
|
||||
AddBits(LBits);
|
||||
}
|
||||
return Length;
|
||||
if (LBits > 0)
|
||||
{
|
||||
Length += getbits() >> (16 - LBits);
|
||||
AddBits(LBits);
|
||||
}
|
||||
return Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using System;
|
||||
|
||||
using SharpCompress.Compressors.Rar.VM;
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
{
|
||||
internal static class UnpackUtility
|
||||
{
|
||||
//!!! TODO rename methods
|
||||
internal static uint DecodeNumber(this BitInput input, Decode.Decode dec) {
|
||||
//!!! TODO rename methods
|
||||
internal static uint DecodeNumber(this BitInput input, Decode.Decode dec)
|
||||
{
|
||||
return (uint)input.decodeNumber(dec);
|
||||
}
|
||||
|
||||
@@ -182,8 +184,8 @@ namespace SharpCompress.Compressors.Rar.UnpackV1
|
||||
|
||||
internal static void makeDecodeTables(byte[] lenTab, int offset, Decode.Decode dec, int size)
|
||||
{
|
||||
int[] lenCount = new int[16];
|
||||
int[] tmpPos = new int[16];
|
||||
Span<int> lenCount = stackalloc int[16];
|
||||
Span<int> tmpPos = stackalloc int[16];
|
||||
int i;
|
||||
long M, N;
|
||||
|
||||
|
||||
@@ -15,57 +15,57 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017
|
||||
internal partial class BitInput
|
||||
{
|
||||
|
||||
public BitInput(bool AllocBuffer)
|
||||
{
|
||||
ExternalBuffer=false;
|
||||
if (AllocBuffer)
|
||||
{
|
||||
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
|
||||
// So let's allocate 3 additional bytes for situation, when we need to
|
||||
// read only 1 byte from the last position of buffer and avoid a crash
|
||||
// from access to next 3 bytes, which contents we do not need.
|
||||
size_t BufSize=MAX_SIZE+3;
|
||||
InBuf=new byte[BufSize];
|
||||
public BitInput(bool AllocBuffer)
|
||||
{
|
||||
ExternalBuffer = false;
|
||||
if (AllocBuffer)
|
||||
{
|
||||
// getbits32 attempts to read data from InAddr, ... InAddr+3 positions.
|
||||
// So let's allocate 3 additional bytes for situation, when we need to
|
||||
// read only 1 byte from the last position of buffer and avoid a crash
|
||||
// from access to next 3 bytes, which contents we do not need.
|
||||
size_t BufSize = MAX_SIZE + 3;
|
||||
InBuf = new byte[BufSize];
|
||||
|
||||
// Ensure that we get predictable results when accessing bytes in area
|
||||
// not filled with read data.
|
||||
//memset(InBuf,0,BufSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
InBuf=null;
|
||||
}
|
||||
}
|
||||
// Ensure that we get predictable results when accessing bytes in area
|
||||
// not filled with read data.
|
||||
//memset(InBuf,0,BufSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
InBuf = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//BitInput::~BitInput()
|
||||
//{
|
||||
// if (!ExternalBuffer)
|
||||
// delete[] InBuf;
|
||||
//}
|
||||
//
|
||||
//BitInput::~BitInput()
|
||||
//{
|
||||
// if (!ExternalBuffer)
|
||||
// delete[] InBuf;
|
||||
//}
|
||||
//
|
||||
|
||||
public
|
||||
void faddbits(uint Bits)
|
||||
{
|
||||
// Function wrapped version of inline addbits to save code size.
|
||||
addbits(Bits);
|
||||
}
|
||||
public
|
||||
void faddbits(uint Bits)
|
||||
{
|
||||
// Function wrapped version of inline addbits to save code size.
|
||||
addbits(Bits);
|
||||
}
|
||||
|
||||
public
|
||||
uint fgetbits()
|
||||
{
|
||||
// Function wrapped version of inline getbits to save code size.
|
||||
return getbits();
|
||||
}
|
||||
public
|
||||
uint fgetbits()
|
||||
{
|
||||
// Function wrapped version of inline getbits to save code size.
|
||||
return getbits();
|
||||
}
|
||||
|
||||
private void SetExternalBuffer(byte []Buf)
|
||||
{
|
||||
//if (InBuf!=NULL && !ExternalBuffer)
|
||||
// delete[] InBuf;
|
||||
InBuf=Buf;
|
||||
ExternalBuffer=true;
|
||||
}
|
||||
private void SetExternalBuffer(byte[] Buf)
|
||||
{
|
||||
//if (InBuf!=NULL && !ExternalBuffer)
|
||||
// delete[] InBuf;
|
||||
InBuf = Buf;
|
||||
ExternalBuffer = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017
|
||||
{
|
||||
|
||||
internal partial class BitInput
|
||||
{
|
||||
public const int MAX_SIZE=0x8000; // Size of input buffer.
|
||||
|
||||
public int InAddr; // Curent byte position in the buffer.
|
||||
public int InBit; // Current bit position in the current byte.
|
||||
|
||||
public bool ExternalBuffer;
|
||||
|
||||
//BitInput(bool AllocBuffer);
|
||||
//~BitInput();
|
||||
|
||||
public byte[] InBuf; // Dynamically allocated input buffer.
|
||||
|
||||
public
|
||||
void InitBitInput()
|
||||
internal partial class BitInput
|
||||
{
|
||||
InAddr=InBit=0;
|
||||
}
|
||||
|
||||
// Move forward by 'Bits' bits.
|
||||
public void addbits(uint _Bits)
|
||||
{
|
||||
var Bits = checked((int)_Bits);
|
||||
Bits+=InBit;
|
||||
InAddr+=Bits>>3;
|
||||
InBit=Bits&7;
|
||||
}
|
||||
|
||||
// Return 16 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
public uint getbits()
|
||||
{
|
||||
uint BitField=(uint)InBuf[InAddr] << 16;
|
||||
BitField|=(uint)InBuf[InAddr+1] << 8;
|
||||
BitField|=(uint)InBuf[InAddr+2];
|
||||
BitField >>= (8-InBit);
|
||||
return BitField & 0xffff;
|
||||
}
|
||||
public const int MAX_SIZE = 0x8000; // Size of input buffer.
|
||||
|
||||
// Return 32 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
public uint getbits32()
|
||||
{
|
||||
uint BitField=(uint)InBuf[InAddr] << 24;
|
||||
BitField|=(uint)InBuf[InAddr+1] << 16;
|
||||
BitField|=(uint)InBuf[InAddr+2] << 8;
|
||||
BitField|=(uint)InBuf[InAddr+3];
|
||||
BitField <<= InBit;
|
||||
BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
|
||||
return BitField & 0xffffffff;
|
||||
}
|
||||
|
||||
//void faddbits(uint Bits);
|
||||
//uint fgetbits();
|
||||
|
||||
// Check if buffer has enough space for IncPtr bytes. Returns 'true'
|
||||
// if buffer will be overflown.
|
||||
private bool Overflow(uint IncPtr)
|
||||
{
|
||||
return InAddr+IncPtr>=MAX_SIZE;
|
||||
}
|
||||
public int InAddr; // Curent byte position in the buffer.
|
||||
public int InBit; // Current bit position in the current byte.
|
||||
|
||||
//void SetExternalBuffer(byte *Buf);
|
||||
}
|
||||
public bool ExternalBuffer;
|
||||
|
||||
//BitInput(bool AllocBuffer);
|
||||
//~BitInput();
|
||||
|
||||
public byte[] InBuf; // Dynamically allocated input buffer.
|
||||
|
||||
public
|
||||
void InitBitInput()
|
||||
{
|
||||
InAddr = InBit = 0;
|
||||
}
|
||||
|
||||
// Move forward by 'Bits' bits.
|
||||
public void addbits(uint _Bits)
|
||||
{
|
||||
var Bits = checked((int)_Bits);
|
||||
Bits += InBit;
|
||||
InAddr += Bits >> 3;
|
||||
InBit = Bits & 7;
|
||||
}
|
||||
|
||||
// Return 16 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
public uint getbits()
|
||||
{
|
||||
uint BitField = (uint)InBuf[InAddr] << 16;
|
||||
BitField |= (uint)InBuf[InAddr + 1] << 8;
|
||||
BitField |= (uint)InBuf[InAddr + 2];
|
||||
BitField >>= (8 - InBit);
|
||||
return BitField & 0xffff;
|
||||
}
|
||||
|
||||
// Return 32 bits from current position in the buffer.
|
||||
// Bit at (InAddr,InBit) has the highest position in returning data.
|
||||
public uint getbits32()
|
||||
{
|
||||
uint BitField = (uint)InBuf[InAddr] << 24;
|
||||
BitField |= (uint)InBuf[InAddr + 1] << 16;
|
||||
BitField |= (uint)InBuf[InAddr + 2] << 8;
|
||||
BitField |= (uint)InBuf[InAddr + 3];
|
||||
BitField <<= InBit;
|
||||
BitField |= (uint)InBuf[InAddr + 4] >> (8 - InBit);
|
||||
return BitField & 0xffffffff;
|
||||
}
|
||||
|
||||
//void faddbits(uint Bits);
|
||||
//uint fgetbits();
|
||||
|
||||
// Check if buffer has enough space for IncPtr bytes. Returns 'true'
|
||||
// if buffer will be overflown.
|
||||
private bool Overflow(uint IncPtr)
|
||||
{
|
||||
return InAddr + IncPtr >= MAX_SIZE;
|
||||
}
|
||||
|
||||
//void SetExternalBuffer(byte *Buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,169 +15,178 @@ using System;
|
||||
|
||||
namespace SharpCompress.Compressors.Rar.UnpackV2017
|
||||
{
|
||||
internal partial class FragmentedWindow
|
||||
internal partial class FragmentedWindow
|
||||
{
|
||||
|
||||
public FragmentedWindow()
|
||||
{
|
||||
//memset(Mem,0,sizeof(Mem));
|
||||
//memset(MemSize,0,sizeof(MemSize));
|
||||
}
|
||||
public FragmentedWindow()
|
||||
{
|
||||
//memset(Mem,0,sizeof(Mem));
|
||||
//memset(MemSize,0,sizeof(MemSize));
|
||||
}
|
||||
|
||||
|
||||
//FragmentedWindow::~FragmentedWindow()
|
||||
//{
|
||||
// Reset();
|
||||
//}
|
||||
//FragmentedWindow::~FragmentedWindow()
|
||||
//{
|
||||
// Reset();
|
||||
//}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
for (uint I=0;I<Mem.Length;I++)
|
||||
{
|
||||
if (Mem[I]!=null)
|
||||
{
|
||||
//free(Mem[I]);
|
||||
Mem[I]=null;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Reset()
|
||||
{
|
||||
for (uint I = 0; I < Mem.Length; I++)
|
||||
{
|
||||
if (Mem[I] != null)
|
||||
{
|
||||
//free(Mem[I]);
|
||||
Mem[I] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Init(size_t WinSize)
|
||||
{
|
||||
Reset();
|
||||
public void Init(size_t WinSize)
|
||||
{
|
||||
Reset();
|
||||
|
||||
uint BlockNum=0;
|
||||
size_t TotalSize=0; // Already allocated.
|
||||
while (TotalSize<WinSize && BlockNum<Mem.Length)
|
||||
{
|
||||
size_t Size=WinSize-TotalSize; // Size needed to allocate.
|
||||
uint BlockNum = 0;
|
||||
size_t TotalSize = 0; // Already allocated.
|
||||
while (TotalSize < WinSize && BlockNum < Mem.Length)
|
||||
{
|
||||
size_t Size = WinSize - TotalSize; // Size needed to allocate.
|
||||
|
||||
// Minimum still acceptable block size. Next allocations cannot be larger
|
||||
// than current, so we do not need blocks if they are smaller than
|
||||
// "size left / attempts left". Also we do not waste time to blocks
|
||||
// smaller than some arbitrary constant.
|
||||
size_t MinSize=Math.Max(Size/(size_t)(Mem.Length-BlockNum), 0x400000);
|
||||
// Minimum still acceptable block size. Next allocations cannot be larger
|
||||
// than current, so we do not need blocks if they are smaller than
|
||||
// "size left / attempts left". Also we do not waste time to blocks
|
||||
// smaller than some arbitrary constant.
|
||||
size_t MinSize = Math.Max(Size / (size_t)(Mem.Length - BlockNum), 0x400000);
|
||||
|
||||
byte[] NewMem=null;
|
||||
while (Size>=MinSize)
|
||||
{
|
||||
NewMem=new byte[Size];
|
||||
if (NewMem!=null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
byte[] NewMem = null;
|
||||
while (Size >= MinSize)
|
||||
{
|
||||
NewMem = new byte[Size];
|
||||
if (NewMem != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Size-=Size/32;
|
||||
}
|
||||
if (NewMem==null)
|
||||
//throw std::bad_alloc();
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
Size -= Size / 32;
|
||||
}
|
||||
if (NewMem == null)
|
||||
//throw std::bad_alloc();
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access to unused areas of sliding dictionary.
|
||||
// sharpcompress: don't need this, freshly allocated above
|
||||
//Utility.Memset(NewMem,0,Size);
|
||||
// Clean the window to generate the same output when unpacking corrupt
|
||||
// RAR files, which may access to unused areas of sliding dictionary.
|
||||
// sharpcompress: don't need this, freshly allocated above
|
||||
//Utility.Memset(NewMem,0,Size);
|
||||
|
||||
Mem[BlockNum]=NewMem;
|
||||
TotalSize+=Size;
|
||||
MemSize[BlockNum]=TotalSize;
|
||||
BlockNum++;
|
||||
}
|
||||
if (TotalSize<WinSize) // Not found enough free blocks.
|
||||
//throw std::bad_alloc();
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
Mem[BlockNum] = NewMem;
|
||||
TotalSize += Size;
|
||||
MemSize[BlockNum] = TotalSize;
|
||||
BlockNum++;
|
||||
}
|
||||
if (TotalSize < WinSize) // Not found enough free blocks.
|
||||
//throw std::bad_alloc();
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte this[size_t Item] {
|
||||
get {
|
||||
if (Item<MemSize[0])
|
||||
{
|
||||
return Mem[0][Item];
|
||||
}
|
||||
public byte this[size_t Item]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Item < MemSize[0])
|
||||
{
|
||||
return Mem[0][Item];
|
||||
}
|
||||
|
||||
for (uint I=1;I<MemSize.Length;I++)
|
||||
{
|
||||
if (Item<MemSize[I])
|
||||
{
|
||||
return Mem[I][Item-MemSize[I-1]];
|
||||
}
|
||||
}
|
||||
for (uint I = 1; I < MemSize.Length; I++)
|
||||
{
|
||||
if (Item < MemSize[I])
|
||||
{
|
||||
return Mem[I][Item - MemSize[I - 1]];
|
||||
}
|
||||
}
|
||||
|
||||
return Mem[0][0]; // Must never happen;
|
||||
}
|
||||
set {
|
||||
if (Item<MemSize[0]) {
|
||||
Mem[0][Item] = value;
|
||||
return;
|
||||
}
|
||||
for (uint I=1;I<MemSize.Length;I++)
|
||||
{
|
||||
if (Item<MemSize[I]) {
|
||||
Mem[I][Item-MemSize[I-1]] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return Mem[0][0]; // Must never happen;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Item < MemSize[0])
|
||||
{
|
||||
Mem[0][Item] = value;
|
||||
return;
|
||||
}
|
||||
for (uint I = 1; I < MemSize.Length; I++)
|
||||
{
|
||||
if (Item < MemSize[I])
|
||||
{
|
||||
Mem[I][Item - MemSize[I - 1]] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Mem[0][0] = value; // Must never happen;
|
||||
}
|
||||
}
|
||||
Mem[0][0] = value; // Must never happen;
|
||||
}
|
||||
}
|
||||
|
||||
// sharpcompress: added the following code
|
||||
public void GetBuffer(size_t Item, out byte[] buf, out uint offset) {
|
||||
if (Item<MemSize[0]) {
|
||||
//return Mem[0][Item];
|
||||
buf = Mem[0]; offset = Item; return;
|
||||
}
|
||||
for (uint I=1;I<MemSize.Length;I++) {
|
||||
if (Item<MemSize[I]) {
|
||||
//return Mem[I][Item-MemSize[I-1]];
|
||||
buf = Mem[I]; offset = Item-MemSize[I-1]; return;
|
||||
}
|
||||
}
|
||||
//return Mem[0][0]; // Must never happen;
|
||||
buf = Mem[0]; offset = 0; return; // Must never happen;
|
||||
}
|
||||
// sharpcompress: added the following code
|
||||
public void GetBuffer(size_t Item, out byte[] buf, out uint offset)
|
||||
{
|
||||
if (Item < MemSize[0])
|
||||
{
|
||||
//return Mem[0][Item];
|
||||
buf = Mem[0]; offset = Item; return;
|
||||
}
|
||||
for (uint I = 1; I < MemSize.Length; I++)
|
||||
{
|
||||
if (Item < MemSize[I])
|
||||
{
|
||||
//return Mem[I][Item-MemSize[I-1]];
|
||||
buf = Mem[I]; offset = Item - MemSize[I - 1]; return;
|
||||
}
|
||||
}
|
||||
//return Mem[0][0]; // Must never happen;
|
||||
buf = Mem[0]; offset = 0; return; // Must never happen;
|
||||
}
|
||||
|
||||
public void CopyString(uint Length,uint Distance,ref size_t UnpPtr,size_t MaxWinMask)
|
||||
{
|
||||
size_t SrcPtr=UnpPtr-Distance;
|
||||
while (Length-- > 0)
|
||||
{
|
||||
this[UnpPtr]=this[SrcPtr++ & MaxWinMask];
|
||||
// We need to have masked UnpPtr after quit from loop, so it must not
|
||||
// be replaced with '(*this)[UnpPtr++ & MaxWinMask]'
|
||||
UnpPtr=(UnpPtr+1) & MaxWinMask;
|
||||
}
|
||||
}
|
||||
public void CopyString(uint Length, uint Distance, ref size_t UnpPtr, size_t MaxWinMask)
|
||||
{
|
||||
size_t SrcPtr = UnpPtr - Distance;
|
||||
while (Length-- > 0)
|
||||
{
|
||||
this[UnpPtr] = this[SrcPtr++ & MaxWinMask];
|
||||
// We need to have masked UnpPtr after quit from loop, so it must not
|
||||
// be replaced with '(*this)[UnpPtr++ & MaxWinMask]'
|
||||
UnpPtr = (UnpPtr + 1) & MaxWinMask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void CopyData(byte[] Dest, size_t destOffset, size_t WinPos,size_t Size)
|
||||
{
|
||||
for (size_t I=0;I<Size;I++)
|
||||
{
|
||||
Dest[destOffset+I]=this[WinPos+I];
|
||||
}
|
||||
}
|
||||
public void CopyData(byte[] Dest, size_t destOffset, size_t WinPos, size_t Size)
|
||||
{
|
||||
for (size_t I = 0; I < Size; I++)
|
||||
{
|
||||
Dest[destOffset + I] = this[WinPos + I];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public size_t GetBlockSize(size_t StartPos,size_t RequiredSize)
|
||||
{
|
||||
for (uint I=0;I<MemSize.Length;I++)
|
||||
{
|
||||
if (StartPos<MemSize[I])
|
||||
{
|
||||
return Math.Min(MemSize[I]-StartPos,RequiredSize);
|
||||
}
|
||||
}
|
||||
public size_t GetBlockSize(size_t StartPos, size_t RequiredSize)
|
||||
{
|
||||
for (uint I = 0; I < MemSize.Length; I++)
|
||||
{
|
||||
if (StartPos < MemSize[I])
|
||||
{
|
||||
return Math.Min(MemSize[I] - StartPos, RequiredSize);
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // Must never be here.
|
||||
}
|
||||
return 0; // Must never be here.
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,54 +3,54 @@
|
||||
internal static class PackDef
|
||||
{
|
||||
|
||||
// Combine pack and unpack constants to class to avoid polluting global
|
||||
// namespace with numerous short names.
|
||||
public const uint MAX_LZ_MATCH = 0x1001;
|
||||
public const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
|
||||
public const uint LOW_DIST_REP_COUNT = 16;
|
||||
// Combine pack and unpack constants to class to avoid polluting global
|
||||
// namespace with numerous short names.
|
||||
public const uint MAX_LZ_MATCH = 0x1001;
|
||||
public const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
|
||||
public const uint LOW_DIST_REP_COUNT = 16;
|
||||
|
||||
public const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC = 64;
|
||||
public const uint LDC = 16;
|
||||
public const uint RC = 44;
|
||||
public const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
|
||||
public const uint BC = 20;
|
||||
public const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC = 64;
|
||||
public const uint LDC = 16;
|
||||
public const uint RC = 44;
|
||||
public const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
|
||||
public const uint BC = 20;
|
||||
|
||||
public const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC30 = 60;
|
||||
public const uint LDC30 = 17;
|
||||
public const uint RC30 = 28;
|
||||
public const uint BC30 = 20;
|
||||
public const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
|
||||
public const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC30 = 60;
|
||||
public const uint LDC30 = 17;
|
||||
public const uint RC30 = 28;
|
||||
public const uint BC30 = 20;
|
||||
public const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
|
||||
|
||||
public const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC20 = 48;
|
||||
public const uint RC20 = 28;
|
||||
public const uint BC20 = 19;
|
||||
public const uint MC20 = 257;
|
||||
public const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
|
||||
public const uint DC20 = 48;
|
||||
public const uint RC20 = 28;
|
||||
public const uint BC20 = 19;
|
||||
public const uint MC20 = 257;
|
||||
|
||||
// Largest alphabet size among all values listed above.
|
||||
public const uint LARGEST_TABLE_SIZE = 306;
|
||||
// Largest alphabet size among all values listed above.
|
||||
public const uint LARGEST_TABLE_SIZE = 306;
|
||||
|
||||
// enum {
|
||||
// CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
|
||||
// CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
|
||||
// };
|
||||
// enum {
|
||||
// CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
|
||||
// CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
|
||||
// };
|
||||
|
||||
|
||||
//enum FilterType {
|
||||
// These values must not be changed, because we use them directly
|
||||
// in RAR5 compression and decompression code.
|
||||
public const int FILTER_DELTA = 0;
|
||||
public const int FILTER_E8 = 1;
|
||||
public const int FILTER_E8E9 = 2;
|
||||
public const int FILTER_ARM = 3;
|
||||
public const int FILTER_AUDIO = 4;
|
||||
public const int FILTER_RGB = 5;
|
||||
public const int FILTER_ITANIUM = 6;
|
||||
public const int FILTER_PPM = 7;
|
||||
public const int FILTER_NONE = 8;
|
||||
//}
|
||||
//enum FilterType {
|
||||
// These values must not be changed, because we use them directly
|
||||
// in RAR5 compression and decompression code.
|
||||
public const int FILTER_DELTA = 0;
|
||||
public const int FILTER_E8 = 1;
|
||||
public const int FILTER_E8E9 = 2;
|
||||
public const int FILTER_ARM = 3;
|
||||
public const int FILTER_AUDIO = 4;
|
||||
public const int FILTER_RGB = 5;
|
||||
public const int FILTER_ITANIUM = 6;
|
||||
public const int FILTER_PPM = 7;
|
||||
public const int FILTER_NONE = 8;
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user