diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 00b1a064..ef84a272 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "csharpier": { - "version": "0.28.1", + "version": "0.25.0", "commands": [ "dotnet-csharpier" ] diff --git a/.editorconfig b/.editorconfig index eab3d428..1903a97c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -70,7 +70,7 @@ indent_style = tab [*.{cs,csx,cake,vb,vbx}] # Default Severity for all .NET Code Style rules below -dotnet_analyzer_diagnostic.severity = silent +dotnet_analyzer_diagnostic.severity = warning ########################################## # File Header (Uncomment to support file headers) @@ -269,8 +269,6 @@ dotnet_diagnostic.CA1305.severity = suggestion dotnet_diagnostic.CA1307.severity = suggestion dotnet_diagnostic.CA1309.severity = suggestion dotnet_diagnostic.CA1310.severity = error -dotnet_diagnostic.CA1507.severity = suggestion -dotnet_diagnostic.CA1513.severity = suggestion dotnet_diagnostic.CA1707.severity = suggestion dotnet_diagnostic.CA1708.severity = suggestion dotnet_diagnostic.CA1711.severity = suggestion @@ -288,7 +286,6 @@ dotnet_diagnostic.CA1834.severity = error dotnet_diagnostic.CA1845.severity = suggestion dotnet_diagnostic.CA1848.severity = suggestion dotnet_diagnostic.CA1852.severity = suggestion -dotnet_diagnostic.CA1860.severity = silent dotnet_diagnostic.CA2016.severity = suggestion dotnet_diagnostic.CA2201.severity = error dotnet_diagnostic.CA2206.severity = error @@ -306,12 +303,13 @@ dotnet_diagnostic.CS1998.severity = error dotnet_diagnostic.CS8602.severity = error dotnet_diagnostic.CS8604.severity = error dotnet_diagnostic.CS8618.severity = error -dotnet_diagnostic.CS0618.severity = suggestion +dotnet_diagnostic.CS0618.severity = error dotnet_diagnostic.CS1998.severity = error dotnet_diagnostic.CS4014.severity = error dotnet_diagnostic.CS8600.severity = error dotnet_diagnostic.CS8603.severity = error dotnet_diagnostic.CS8625.severity = error +dotnet_diagnostic.CS8981.severity = suggestion dotnet_diagnostic.BL0005.severity = suggestion @@ -320,7 +318,7 @@ dotnet_diagnostic.MVC1000.severity = suggestion dotnet_diagnostic.RZ10012.severity = error dotnet_diagnostic.IDE0004.severity = error # redundant cast -dotnet_diagnostic.IDE0005.severity = suggestion +dotnet_diagnostic.IDE0005.severity = error dotnet_diagnostic.IDE0007.severity = error # Use var dotnet_diagnostic.IDE0011.severity = error # Use braces on if statements dotnet_diagnostic.IDE0010.severity = silent # populate switch @@ -331,7 +329,7 @@ dotnet_diagnostic.IDE0023.severity = suggestion # use expression body for operat dotnet_diagnostic.IDE0024.severity = silent # expression body for operators dotnet_diagnostic.IDE0025.severity = suggestion # use expression body for properties dotnet_diagnostic.IDE0027.severity = suggestion # Use expression body for accessors -dotnet_diagnostic.IDE0028.severity = silent # expression body for accessors +dotnet_diagnostic.IDE0028.severity = silent dotnet_diagnostic.IDE0032.severity = suggestion # Use auto property dotnet_diagnostic.IDE0033.severity = error # prefer tuple name dotnet_diagnostic.IDE0037.severity = suggestion # simplify anonymous type @@ -339,7 +337,7 @@ dotnet_diagnostic.IDE0040.severity = error # modifiers required dotnet_diagnostic.IDE0041.severity = error # simplify null dotnet_diagnostic.IDE0042.severity = error # deconstruct variable dotnet_diagnostic.IDE0044.severity = suggestion # make field only when possible -dotnet_diagnostic.IDE0047.severity = suggestion # parameter name +dotnet_diagnostic.IDE0047.severity = suggestion # paratemeter name dotnet_diagnostic.IDE0051.severity = error # unused field dotnet_diagnostic.IDE0052.severity = error # unused member dotnet_diagnostic.IDE0053.severity = suggestion # lambda not needed @@ -353,20 +351,11 @@ dotnet_diagnostic.IDE0066.severity = suggestion # switch expression dotnet_diagnostic.IDE0072.severity = suggestion # Populate switch - forces population of all cases even when default specified dotnet_diagnostic.IDE0078.severity = suggestion # use pattern matching dotnet_diagnostic.IDE0090.severity = suggestion # new can be simplified -dotnet_diagnostic.IDE0130.severity = suggestion # namespace folder structure +dotnet_diagnostic.IDE0130.severity = error # namespace folder structure dotnet_diagnostic.IDE0160.severity = silent # Use block namespaces ARE NOT required dotnet_diagnostic.IDE0161.severity = error # Please use file namespaces dotnet_diagnostic.IDE0200.severity = suggestion # lambda not needed dotnet_diagnostic.IDE1006.severity = suggestion # Naming rule violation: These words cannot contain lower case characters -dotnet_diagnostic.IDE0260.severity = suggestion # Use pattern matching -dotnet_diagnostic.IDE0270.severity = suggestion # Null check simplifcation -dotnet_diagnostic.IDE0290.severity = error # Primary Constructor -dotnet_diagnostic.IDE0300.severity = suggestion # Collection -dotnet_diagnostic.IDE0305.severity = suggestion # Collection ToList - -dotnet_diagnostic.NX0001.severity = error -dotnet_diagnostic.NX0002.severity = silent -dotnet_diagnostic.NX0003.severity = silent ########################################## # Styles diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 27d73e23..4486b23f 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -15,11 +15,18 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-dotnet@v4 + - uses: actions/setup-dotnet@v3 with: - dotnet-version: 8.0.x + dotnet-version: 7.0.x + - name: NuGet Caching + uses: actions/cache@v3 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('packages.lock.json', '*/packages.lock.json') }} + restore-keys: | + ${{ runner.os }}-nuget- - run: dotnet run --project build/build.csproj - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v3 with: name: ${{ matrix.os }}-sharpcompress.nupkg path: artifacts/* diff --git a/Directory.Build.props b/Directory.Build.props index b3d0b595..4b343bf8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -10,7 +10,5 @@ true False False - true - true diff --git a/Directory.Packages.props b/Directory.Packages.props deleted file mode 100644 index e128f52f..00000000 --- a/Directory.Packages.props +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index 48259210..00000000 --- a/NuGet.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/README.md b/README.md index 2ab41c09..20681105 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # SharpCompress -SharpCompress is a compression library in pure C# for .NET Framework 4.62, .NET Standard 2.1, .NET 6.0 and NET 8.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. +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). GitHub Actions Build - [![SharpCompress](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml/badge.svg)](https://github.com/adamhathcock/sharpcompress/actions/workflows/dotnetcore.yml) -[![Static Badge](https://img.shields.io/badge/API%20Docs-DNDocs-190088?logo=readme&logoColor=white)](https://dndocs.com/d/sharpcompress/api/index.html) +[![Static Badge](https://img.shields.io/badge/API%20Documentation-RobiniaDocs-43bc00?logo=readme&logoColor=white)](https://www.robiniadocs.com/d/sharpcompress/api/SharpCompress.html) ## Need Help? @@ -36,7 +36,7 @@ I'm always looking for help or ideas. Please submit code or email with ideas. Un ## TODOs (always lots) -* RAR 5 decryption crc check support +* RAR 5 decryption support * 7Zip writing * Zip64 (Need writing and extend Reading) * Multi-volume Zip support. diff --git a/SharpCompress.sln b/SharpCompress.sln index ab4995b1..71ec294e 100644 --- a/SharpCompress.sln +++ b/SharpCompress.sln @@ -17,9 +17,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{CDB425 ProjectSection(SolutionItems) = preProject Directory.Build.props = Directory.Build.props global.json = global.json - .editorconfig = .editorconfig - Directory.Packages.props = Directory.Packages.props - NuGet.config = NuGet.config EndProjectSection EndProject Global diff --git a/SharpCompress.sln.DotSettings b/SharpCompress.sln.DotSettings index 4ff50910..248b4c35 100644 --- a/SharpCompress.sln.DotSettings +++ b/SharpCompress.sln.DotSettings @@ -79,10 +79,6 @@ <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> - <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> - <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /></Policy> - <Policy><Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"><ElementKinds><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> - <Policy><Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"><ElementKinds><Kind Name="FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /></Policy> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> @@ -131,7 +127,6 @@ True True True - True <SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="All tests from Solution" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Solution /> </SessionState> diff --git a/build/Program.cs b/build/Program.cs index acafec41..9475a66b 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -61,7 +61,7 @@ Target( Target( Test, DependsOn(Build), - ForEach("net8.0", "net462"), + ForEach("net7.0", "net462"), framework => { IEnumerable GetFiles(string d) diff --git a/build/build.csproj b/build/build.csproj index e0dffc7f..7b478cf3 100644 --- a/build/build.csproj +++ b/build/build.csproj @@ -2,13 +2,13 @@ Exe - net8.0 + net7.0 - - - + + + diff --git a/build/packages.lock.json b/build/packages.lock.json deleted file mode 100644 index 8a8fa2c0..00000000 --- a/build/packages.lock.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": 2, - "dependencies": { - "net8.0": { - "Bullseye": { - "type": "Direct", - "requested": "[5.0.0, )", - "resolved": "5.0.0", - "contentHash": "bqyt+m17ym+5aN45C5oZRAjuLDt8jKiCm/ys1XfymIXSkrTFwvI/QsbY3ucPSHDz7SF7uON7B57kXFv5H2k1ew==" - }, - "Glob": { - "type": "Direct", - "requested": "[1.1.9, )", - "resolved": "1.1.9", - "contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw==" - }, - "SimpleExec": { - "type": "Direct", - "requested": "[12.0.0, )", - "resolved": "12.0.0", - "contentHash": "ptxlWtxC8vM6Y6e3h9ZTxBBkOWnWrm/Sa1HT+2i1xcXY3Hx2hmKDZP5RShPf8Xr9D+ivlrXNy57ktzyH8kyt+Q==" - } - } - } -} \ No newline at end of file diff --git a/global.json b/global.json index 391ba3c2..e6e67e4e 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", + "version": "7.0.101", "rollForward": "latestFeature" } } diff --git a/src/SharpCompress/Algorithms/Adler32.cs b/src/SharpCompress/Algorithms/Adler32.cs index 10dbfc4d..1f094c13 100644 --- a/src/SharpCompress/Algorithms/Adler32.cs +++ b/src/SharpCompress/Algorithms/Adler32.cs @@ -62,7 +62,7 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl public static int ReduceSum(Vector256 accumulator) { // Add upper lane to lower lane. - var vsum = Sse2.Add(accumulator.GetLower(), accumulator.GetUpper()); + Vector128 vsum = Sse2.Add(accumulator.GetLower(), accumulator.GetUpper()); // Add odd to even. vsum = Sse2.Add(vsum, Sse2.Shuffle(vsum, 0b_11_11_01_01)); @@ -81,7 +81,7 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int EvenReduceSum(Vector256 accumulator) { - var vsum = Sse2.Add(accumulator.GetLower(), accumulator.GetUpper()); // add upper lane to lower lane + Vector128 vsum = Sse2.Add(accumulator.GetLower(), accumulator.GetUpper()); // add upper lane to lower lane vsum = Sse2.Add(vsum, Sse2.Shuffle(vsum, 0b_11_10_11_10)); // add high to low // Vector128.ToScalar() isn't optimized pre-net5.0 https://github.com/dotnet/runtime/pull/37882 @@ -189,29 +189,29 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateSse(uint adler, ReadOnlySpan buffer) { - var s1 = adler & 0xFFFF; - var s2 = (adler >> 16) & 0xFFFF; + uint s1 = adler & 0xFFFF; + uint s2 = (adler >> 16) & 0xFFFF; // Process the data in blocks. - var length = (uint)buffer.Length; - var blocks = length / BlockSize; + uint length = (uint)buffer.Length; + uint blocks = length / BlockSize; length -= blocks * BlockSize; fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { fixed (byte* tapPtr = &MemoryMarshal.GetReference(Tap1Tap2)) { - var localBufferPtr = bufferPtr; + byte* localBufferPtr = bufferPtr; // _mm_setr_epi8 on x86 - var tap1 = Sse2.LoadVector128((sbyte*)tapPtr); - var tap2 = Sse2.LoadVector128((sbyte*)(tapPtr + 0x10)); - var zero = Vector128.Zero; + Vector128 tap1 = Sse2.LoadVector128((sbyte*)tapPtr); + Vector128 tap2 = Sse2.LoadVector128((sbyte*)(tapPtr + 0x10)); + Vector128 zero = Vector128.Zero; var ones = Vector128.Create((short)1); while (blocks > 0) { - var n = NMAX / BlockSize; /* The NMAX constraint. */ + uint n = NMAX / BlockSize; /* The NMAX constraint. */ if (n > blocks) { n = blocks; @@ -221,15 +221,15 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl // Process n blocks of data. At most NMAX data bytes can be // processed before s2 must be reduced modulo BASE. - var v_ps = Vector128.CreateScalar(s1 * n); - var v_s2 = Vector128.CreateScalar(s2); - var v_s1 = Vector128.Zero; + Vector128 v_ps = Vector128.CreateScalar(s1 * n); + Vector128 v_s2 = Vector128.CreateScalar(s2); + Vector128 v_s1 = Vector128.Zero; do { // Load 32 input bytes. - var bytes1 = Sse3.LoadDquVector128(localBufferPtr); - var bytes2 = Sse3.LoadDquVector128(localBufferPtr + 0x10); + Vector128 bytes1 = Sse3.LoadDquVector128(localBufferPtr); + Vector128 bytes2 = Sse3.LoadDquVector128(localBufferPtr + 0x10); // Add previous block byte sum to v_ps. v_ps = Sse2.Add(v_ps, v_s1); @@ -237,11 +237,11 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl // 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).AsUInt32()); - var mad1 = Ssse3.MultiplyAddAdjacent(bytes1, tap1); + Vector128 mad1 = Ssse3.MultiplyAddAdjacent(bytes1, tap1); v_s2 = Sse2.Add(v_s2, Sse2.MultiplyAddAdjacent(mad1, ones).AsUInt32()); v_s1 = Sse2.Add(v_s1, Sse2.SumAbsoluteDifferences(bytes2, zero).AsUInt32()); - var mad2 = Ssse3.MultiplyAddAdjacent(bytes2, tap2); + Vector128 mad2 = Ssse3.MultiplyAddAdjacent(bytes2, tap2); v_s2 = Sse2.Add(v_s2, Sse2.MultiplyAddAdjacent(mad2, ones).AsUInt32()); localBufferPtr += BlockSize; @@ -281,15 +281,15 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] public static unsafe uint CalculateAvx2(uint adler, ReadOnlySpan buffer) { - var s1 = adler & 0xFFFF; - var s2 = (adler >> 16) & 0xFFFF; - var length = (uint)buffer.Length; + uint s1 = adler & 0xFFFF; + uint s2 = (adler >> 16) & 0xFFFF; + uint length = (uint)buffer.Length; fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { - var localBufferPtr = bufferPtr; + byte* localBufferPtr = bufferPtr; - var zero = Vector256.Zero; + Vector256 zero = Vector256.Zero; var dot3v = Vector256.Create((short)1); var dot2v = Vector256.Create( 32, @@ -333,29 +333,29 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl while (length >= 32) { - var k = length < NMAX ? (int)length : (int)NMAX; + int k = length < NMAX ? (int)length : (int)NMAX; k -= k % 32; length -= (uint)k; - var vs10 = vs1; - var vs3 = Vector256.Zero; + Vector256 vs10 = vs1; + Vector256 vs3 = Vector256.Zero; while (k >= 32) { // Load 32 input bytes. - var block = Avx.LoadVector256(localBufferPtr); + Vector256 block = Avx.LoadVector256(localBufferPtr); // Sum of abs diff, resulting in 2 x int32's - var vs1sad = Avx2.SumAbsoluteDifferences(block, zero); + Vector256 vs1sad = Avx2.SumAbsoluteDifferences(block, zero); vs1 = Avx2.Add(vs1, vs1sad.AsUInt32()); vs3 = Avx2.Add(vs3, vs10); // sum 32 uint8s to 16 shorts. - var vshortsum2 = Avx2.MultiplyAddAdjacent(block, dot2v); + Vector256 vshortsum2 = Avx2.MultiplyAddAdjacent(block, dot2v); // sum 16 shorts to 8 uint32s. - var vsum2 = Avx2.MultiplyAddAdjacent(vshortsum2, dot3v); + Vector256 vsum2 = Avx2.MultiplyAddAdjacent(vshortsum2, dot3v); vs2 = Avx2.Add(vsum2.AsUInt32(), vs2); vs10 = vs1; @@ -434,14 +434,14 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl [MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)] private static unsafe uint CalculateScalar(uint adler, ReadOnlySpan buffer) { - var s1 = adler & 0xFFFF; - var s2 = (adler >> 16) & 0xFFFF; + uint s1 = adler & 0xFFFF; + uint s2 = (adler >> 16) & 0xFFFF; uint k; fixed (byte* bufferPtr = buffer) { var localBufferPtr = bufferPtr; - var length = (uint)buffer.Length; + uint length = (uint)buffer.Length; while (length > 0) { diff --git a/src/SharpCompress/Archives/AbstractArchive.cs b/src/SharpCompress/Archives/AbstractArchive.cs index df54d781..cfac55f2 100644 --- a/src/SharpCompress/Archives/AbstractArchive.cs +++ b/src/SharpCompress/Archives/AbstractArchive.cs @@ -12,35 +12,39 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra where TEntry : IArchiveEntry where TVolume : IVolume { - private readonly LazyReadOnlyCollection _lazyVolumes; - private readonly LazyReadOnlyCollection _lazyEntries; - private bool _disposed; - private readonly SourceStream? _sourceStream; + private readonly LazyReadOnlyCollection lazyVolumes; + private readonly LazyReadOnlyCollection lazyEntries; public event EventHandler>? EntryExtractionBegin; public event EventHandler>? EntryExtractionEnd; public event EventHandler? CompressedBytesRead; public event EventHandler? FilePartExtractionBegin; + protected ReaderOptions ReaderOptions { get; } - internal AbstractArchive(ArchiveType type, SourceStream sourceStream) + private bool disposed; + protected SourceStream SrcStream; + + internal AbstractArchive(ArchiveType type, SourceStream srcStream) { Type = type; - ReaderOptions = sourceStream.ReaderOptions; - _sourceStream = sourceStream; - _lazyVolumes = new LazyReadOnlyCollection(LoadVolumes(_sourceStream)); - _lazyEntries = new LazyReadOnlyCollection(LoadEntries(Volumes)); + ReaderOptions = srcStream.ReaderOptions; + SrcStream = srcStream; + lazyVolumes = new LazyReadOnlyCollection(LoadVolumes(SrcStream)); + lazyEntries = new LazyReadOnlyCollection(LoadEntries(Volumes)); } +#nullable disable internal AbstractArchive(ArchiveType type) { Type = type; - ReaderOptions = new(); - _lazyVolumes = new LazyReadOnlyCollection(Enumerable.Empty()); - _lazyEntries = new LazyReadOnlyCollection(Enumerable.Empty()); + lazyVolumes = new LazyReadOnlyCollection(Enumerable.Empty()); + lazyEntries = new LazyReadOnlyCollection(Enumerable.Empty()); } +#nullable enable + public ArchiveType Type { get; } void IArchiveExtractionListener.FireEntryExtractionBegin(IArchiveEntry entry) => @@ -61,12 +65,12 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra /// /// Returns an ReadOnlyCollection of all the RarArchiveEntries across the one or many parts of the RarArchive. /// - public virtual ICollection Entries => _lazyEntries; + public virtual ICollection Entries => lazyEntries; /// /// Returns an ReadOnlyCollection of all the RarArchiveVolumes across the one or many parts of the RarArchive. /// - public ICollection Volumes => _lazyVolumes; + public ICollection Volumes => lazyVolumes; /// /// The total size of the files compressed in the archive. @@ -80,29 +84,29 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra public virtual long TotalUncompressSize => Entries.Aggregate(0L, (total, cf) => total + cf.Size); - protected abstract IEnumerable LoadVolumes(SourceStream sourceStream); + protected abstract IEnumerable LoadVolumes(SourceStream srcStream); protected abstract IEnumerable LoadEntries(IEnumerable volumes); IEnumerable IArchive.Entries => Entries.Cast(); - IEnumerable IArchive.Volumes => _lazyVolumes.Cast(); + IEnumerable IArchive.Volumes => lazyVolumes.Cast(); public virtual void Dispose() { - if (!_disposed) + if (!disposed) { - _lazyVolumes.ForEach(v => v.Dispose()); - _lazyEntries.GetLoaded().Cast().ForEach(x => x.Close()); - _sourceStream?.Dispose(); + lazyVolumes.ForEach(v => v.Dispose()); + lazyEntries.GetLoaded().Cast().ForEach(x => x.Close()); + SrcStream?.Dispose(); - _disposed = true; + disposed = true; } } void IArchiveExtractionListener.EnsureEntriesLoaded() { - _lazyEntries.EnsureFullyLoaded(); - _lazyVolumes.EnsureFullyLoaded(); + lazyEntries.EnsureFullyLoaded(); + lazyVolumes.EnsureFullyLoaded(); } void IExtractionListener.FireCompressedBytesRead( diff --git a/src/SharpCompress/Archives/AbstractWritableArchive.cs b/src/SharpCompress/Archives/AbstractWritableArchive.cs index 614489fe..30083ec7 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -31,18 +31,18 @@ public abstract class AbstractWritableArchive } } - private readonly List newEntries = new(); - private readonly List removedEntries = new(); + private readonly List newEntries = new List(); + private readonly List removedEntries = new List(); - private readonly List modifiedEntries = new(); + private readonly List modifiedEntries = new List(); private bool hasModifications; private bool pauseRebuilding; internal AbstractWritableArchive(ArchiveType type) : base(type) { } - internal AbstractWritableArchive(ArchiveType type, SourceStream sourceStream) - : base(type, sourceStream) { } + internal AbstractWritableArchive(ArchiveType type, SourceStream srcStream) + : base(type, srcStream) { } public override ICollection Entries { @@ -120,10 +120,6 @@ public abstract class AbstractWritableArchive { foreach (var path in Entries.Select(x => x.Key)) { - if (path is null) - { - continue; - } var p = path.Replace('/', '\\'); if (p.Length > 0 && p[0] == '\\') { diff --git a/src/SharpCompress/Archives/ArchiveFactory.cs b/src/SharpCompress/Archives/ArchiveFactory.cs index 3f479327..cd0952f1 100644 --- a/src/SharpCompress/Archives/ArchiveFactory.cs +++ b/src/SharpCompress/Archives/ArchiveFactory.cs @@ -25,8 +25,8 @@ public static class ArchiveFactory public static IWritableArchive Create(ArchiveType type) { - var factory = Factory - .Factories.OfType() + var factory = Factory.Factories + .OfType() .FirstOrDefault(item => item.KnownArchiveType == type); if (factory != null) diff --git a/src/SharpCompress/Archives/ArchiveVolumeFactory.cs b/src/SharpCompress/Archives/ArchiveVolumeFactory.cs index 81a5d4fd..d8f5535f 100644 --- a/src/SharpCompress/Archives/ArchiveVolumeFactory.cs +++ b/src/SharpCompress/Archives/ArchiveVolumeFactory.cs @@ -11,7 +11,7 @@ internal abstract class ArchiveVolumeFactory FileInfo? item = null; //split 001, 002 ... - var m = Regex.Match(part1.Name, @"^(.*\.)([0-9]+)$", RegexOptions.IgnoreCase); + Match m = Regex.Match(part1.Name, @"^(.*\.)([0-9]+)$", RegexOptions.IgnoreCase); if (m.Success) item = new FileInfo( Path.Combine( diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index ea46e8d0..fb2f7691 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -90,23 +90,25 @@ public class GZipArchive : AbstractWritableArchive { stream.CheckNotNull(nameof(stream)); return new GZipArchive( - new SourceStream(stream, _ => null, readerOptions ?? new ReaderOptions()) + new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions()) ); } - public static GZipArchive Create() => new(); + public static GZipArchive Create() => new GZipArchive(); /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - private GZipArchive(SourceStream sourceStream) - : base(ArchiveType.GZip, sourceStream) { } + /// + /// + internal GZipArchive(SourceStream srcStream) + : base(ArchiveType.Tar, srcStream) { } - protected override IEnumerable LoadVolumes(SourceStream sourceStream) + protected override IEnumerable LoadVolumes(SourceStream srcStream) { - sourceStream.LoadAllParts(); - return sourceStream.Streams.Select(a => new GZipVolume(a, ReaderOptions, 0)); + srcStream.LoadAllParts(); + var idx = 0; + return srcStream.Streams.Select(a => new GZipVolume(a, ReaderOptions, idx++)); } public static bool IsGZipFile(string filePath) => IsGZipFile(new FileInfo(filePath)); @@ -182,11 +184,7 @@ public class GZipArchive : AbstractWritableArchive foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory)) { using var entryStream = entry.OpenEntryStream(); - writer.Write( - entry.Key.NotNull("Entry Key is null"), - entryStream, - entry.LastModifiedTime - ); + writer.Write(entry.Key, entryStream, entry.LastModifiedTime); } } diff --git a/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs b/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs index 459d042d..be872e80 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs @@ -6,7 +6,7 @@ namespace SharpCompress.Archives.GZip; public class GZipArchiveEntry : GZipEntry, IArchiveEntry { - internal GZipArchiveEntry(GZipArchive archive, GZipFilePart? part) + internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part) : base(part) => Archive = archive; public virtual Stream OpenEntryStream() diff --git a/src/SharpCompress/Archives/GZip/GZipWritableArchiveEntry.cs b/src/SharpCompress/Archives/GZip/GZipWritableArchiveEntry.cs index 90f6f16f..27dfc2bf 100644 --- a/src/SharpCompress/Archives/GZip/GZipWritableArchiveEntry.cs +++ b/src/SharpCompress/Archives/GZip/GZipWritableArchiveEntry.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -30,7 +32,7 @@ internal sealed class GZipWritableArchiveEntry : GZipArchiveEntry, IWritableArch public override long Crc => 0; - public override string? Key { get; } + public override string Key { get; } public override long CompressedSize => 0; diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index 3d1daa1a..0992f152 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -17,11 +17,15 @@ public static class IArchiveEntryExtensions streamListener.EnsureEntriesLoaded(); streamListener.FireEntryExtractionBegin(archiveEntry); streamListener.FireFilePartExtractionBegin( - archiveEntry.Key ?? "Key", + archiveEntry.Key, archiveEntry.Size, archiveEntry.CompressedSize ); var entryStream = archiveEntry.OpenEntryStream(); + if (entryStream is null) + { + return; + } using (entryStream) { using Stream s = new ListeningStream(streamListener, entryStream); diff --git a/src/SharpCompress/Archives/IArchiveExtensions.cs b/src/SharpCompress/Archives/IArchiveExtensions.cs index 382c3ddf..56ea0d9f 100644 --- a/src/SharpCompress/Archives/IArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; +using System.Threading.Tasks; using SharpCompress.Common; namespace SharpCompress.Archives; @@ -58,7 +59,7 @@ public static class IArchiveExtensions } // Create each directory - var path = Path.Combine(destination, entry.Key.NotNull("Entry Key is null")); + var path = Path.Combine(destination, entry.Key); if (Path.GetDirectoryName(path) is { } directory && seenDirectories.Add(path)) { Directory.CreateDirectory(directory); diff --git a/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs b/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs index 6d9b44fd..3e576db3 100644 --- a/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs +++ b/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs @@ -13,7 +13,7 @@ namespace SharpCompress.Archives.Rar; /// internal class FileInfoRarArchiveVolume : RarVolume { - internal FileInfoRarArchiveVolume(FileInfo fileInfo, ReaderOptions options, int index) + internal FileInfoRarArchiveVolume(FileInfo fileInfo, ReaderOptions options, int index = 0) : base(StreamingMode.Seekable, fileInfo.OpenRead(), FixOptions(options), index) { FileInfo = fileInfo; diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index a05ad417..29d733f6 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -15,39 +14,40 @@ namespace SharpCompress.Archives.Rar; public class RarArchive : AbstractArchive { internal Lazy UnpackV2017 { get; } = - new(() => new Compressors.Rar.UnpackV2017.Unpack()); - internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); + new Lazy(() => new Compressors.Rar.UnpackV2017.Unpack()); + internal Lazy UnpackV1 { get; } = + new Lazy(() => new Compressors.Rar.UnpackV1.Unpack()); /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - private RarArchive(SourceStream sourceStream) - : base(ArchiveType.Rar, sourceStream) { } + /// + /// + internal RarArchive(SourceStream srcStream) + : base(ArchiveType.Rar, srcStream) { } protected override IEnumerable LoadEntries(IEnumerable volumes) => RarArchiveEntryFactory.GetEntries(this, volumes, ReaderOptions); - protected override IEnumerable LoadVolumes(SourceStream sourceStream) + protected override IEnumerable LoadVolumes(SourceStream srcStream) { - sourceStream.LoadAllParts(); //request all streams - var streams = sourceStream.Streams.ToArray(); - var i = 0; + SrcStream.LoadAllParts(); //request all streams + var streams = SrcStream.Streams.ToArray(); + var idx = 0; if (streams.Length > 1 && IsRarFile(streams[1], ReaderOptions)) //test part 2 - true = multipart not split { - sourceStream.IsVolumes = true; + SrcStream.IsVolumes = true; streams[1].Position = 0; - sourceStream.Position = 0; + SrcStream.Position = 0; - return sourceStream.Streams.Select(a => new StreamRarArchiveVolume( - a, - ReaderOptions, - i++ - )); + return srcStream.Streams.Select( + a => new StreamRarArchiveVolume(a, ReaderOptions, idx++) + ); + } + else //split mode or single file + { + return new StreamRarArchiveVolume(SrcStream, ReaderOptions, idx++).AsEnumerable(); } - - //split mode or single file - return new StreamRarArchiveVolume(sourceStream, ReaderOptions, i++).AsEnumerable(); } protected override IReader CreateReaderForSolidExtraction() @@ -106,7 +106,7 @@ public class RarArchive : AbstractArchive public static RarArchive Open(Stream stream, ReaderOptions? options = null) { stream.CheckNotNull(nameof(stream)); - return new RarArchive(new SourceStream(stream, _ => null, options ?? new ReaderOptions())); + return new RarArchive(new SourceStream(stream, i => null, options ?? new ReaderOptions())); } /// diff --git a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs index fa59b295..5885210a 100644 --- a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs +++ b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -41,10 +40,7 @@ public class RarArchiveEntry : RarEntry, IArchiveEntry get { CheckIncomplete(); - return BitConverter.ToUInt32( - parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc, - 0 - ); + return parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc; } } diff --git a/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs b/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs index f5ce89b8..72ccf60f 100644 --- a/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs +++ b/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs @@ -11,7 +11,7 @@ internal static class RarArchiveVolumeFactory FileInfo? item = null; //new style rar - ..part1 | /part01 | part001 .... - var m = Regex.Match(part1.Name, @"^(.*\.part)([0-9]+)(\.rar)$", RegexOptions.IgnoreCase); + Match m = Regex.Match(part1.Name, @"^(.*\.part)([0-9]+)(\.rar)$", RegexOptions.IgnoreCase); if (m.Success) item = new FileInfo( Path.Combine( diff --git a/src/SharpCompress/Archives/Rar/SeekableFilePart.cs b/src/SharpCompress/Archives/Rar/SeekableFilePart.cs index 97822d90..08aceb13 100644 --- a/src/SharpCompress/Archives/Rar/SeekableFilePart.cs +++ b/src/SharpCompress/Archives/Rar/SeekableFilePart.cs @@ -6,8 +6,8 @@ namespace SharpCompress.Archives.Rar; internal class SeekableFilePart : RarFilePart { - private readonly Stream _stream; - private readonly string? _password; + private readonly Stream stream; + private readonly string? password; internal SeekableFilePart( MarkHeader mh, @@ -18,27 +18,18 @@ internal class SeekableFilePart : RarFilePart ) : base(mh, fh, index) { - _stream = stream; - _password = password; + this.stream = stream; + this.password = password; } internal override Stream GetCompressedStream() { - _stream.Position = FileHeader.DataStartPosition; - + stream.Position = FileHeader.DataStartPosition; if (FileHeader.R4Salt != null) { - var cryptKey = new CryptKey3(_password!); - return new RarCryptoWrapper(_stream, FileHeader.R4Salt, cryptKey); + return new RarCryptoWrapper(stream, password!, FileHeader.R4Salt); } - - if (FileHeader.Rar5CryptoInfo != null) - { - var cryptKey = new CryptKey5(_password!, FileHeader.Rar5CryptoInfo); - return new RarCryptoWrapper(_stream, FileHeader.Rar5CryptoInfo.Salt, cryptKey); - } - - return _stream; + return stream; } internal override string FilePartName => "Unknown Stream - File Entry: " + FileHeader.FileName; diff --git a/src/SharpCompress/Archives/Rar/StreamRarArchiveVolume.cs b/src/SharpCompress/Archives/Rar/StreamRarArchiveVolume.cs index 60cbab9a..3eb5095c 100644 --- a/src/SharpCompress/Archives/Rar/StreamRarArchiveVolume.cs +++ b/src/SharpCompress/Archives/Rar/StreamRarArchiveVolume.cs @@ -9,7 +9,7 @@ namespace SharpCompress.Archives.Rar; internal class StreamRarArchiveVolume : RarVolume { - internal StreamRarArchiveVolume(Stream stream, ReaderOptions options, int index) + internal StreamRarArchiveVolume(Stream stream, ReaderOptions options, int index = 0) : base(StreamingMode.Seekable, stream, options, index) { } internal override IEnumerable ReadFileParts() => GetVolumeFileParts(); diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index ee165982..7577b43d 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -12,14 +14,14 @@ namespace SharpCompress.Archives.SevenZip; public class SevenZipArchive : AbstractArchive { - private ArchiveDatabase? _database; + private ArchiveDatabase database; /// /// Constructor expects a filepath to an existing file. /// /// /// - public static SevenZipArchive Open(string filePath, ReaderOptions? readerOptions = null) + public static SevenZipArchive Open(string filePath, ReaderOptions readerOptions = null) { filePath.CheckNotNullOrEmpty("filePath"); return Open(new FileInfo(filePath), readerOptions ?? new ReaderOptions()); @@ -30,7 +32,7 @@ public class SevenZipArchive : AbstractArchive /// /// - public static SevenZipArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) + public static SevenZipArchive Open(FileInfo fileInfo, ReaderOptions readerOptions = null) { fileInfo.CheckNotNull("fileInfo"); return new SevenZipArchive( @@ -49,7 +51,7 @@ public class SevenZipArchive : AbstractArchive public static SevenZipArchive Open( IEnumerable fileInfos, - ReaderOptions? readerOptions = null + ReaderOptions readerOptions = null ) { fileInfos.CheckNotNull(nameof(fileInfos)); @@ -70,7 +72,7 @@ public class SevenZipArchive : AbstractArchive public static SevenZipArchive Open( IEnumerable streams, - ReaderOptions? readerOptions = null + ReaderOptions readerOptions = null ) { streams.CheckNotNull(nameof(streams)); @@ -89,25 +91,27 @@ public class SevenZipArchive : AbstractArchive /// /// - public static SevenZipArchive Open(Stream stream, ReaderOptions? readerOptions = null) + public static SevenZipArchive Open(Stream stream, ReaderOptions readerOptions = null) { stream.CheckNotNull("stream"); return new SevenZipArchive( - new SourceStream(stream, _ => null, readerOptions ?? new ReaderOptions()) + new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions()) ); } /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - private SevenZipArchive(SourceStream sourceStream) - : base(ArchiveType.SevenZip, sourceStream) { } + /// + /// + internal SevenZipArchive(SourceStream srcStream) + : base(ArchiveType.SevenZip, srcStream) { } - protected override IEnumerable LoadVolumes(SourceStream sourceStream) + protected override IEnumerable LoadVolumes(SourceStream srcStream) { - sourceStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams - return new SevenZipVolume(sourceStream, ReaderOptions, 0).AsEnumerable(); //simple single volume or split, multivolume not supported + SrcStream.LoadAllParts(); //request all streams + var idx = 0; + return new SevenZipVolume(srcStream, ReaderOptions, idx++).AsEnumerable(); //simple single volume or split, multivolume not supported } public static bool IsSevenZipFile(string filePath) => IsSevenZipFile(new FileInfo(filePath)); @@ -131,17 +135,13 @@ public class SevenZipArchive : AbstractArchive(); - } - var entries = new SevenZipArchiveEntry[_database._files.Count]; - for (var i = 0; i < _database._files.Count; i++) - { - var file = _database._files[i]; + var file = database._files[i]; entries[i] = new SevenZipArchiveEntry( this, - new SevenZipFilePart(stream, _database, i, file, ReaderOptions.ArchiveEncoding) + new SevenZipFilePart(stream, database, i, file, ReaderOptions.ArchiveEncoding) ); } foreach (var group in entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder)) @@ -159,12 +159,12 @@ public class SevenZipArchive : AbstractArchive Signature => + private static ReadOnlySpan SIGNATURE => new byte[] { (byte)'7', (byte)'z', 0xBC, 0xAF, 0x27, 0x1C }; private static bool SignatureMatch(Stream stream) { var reader = new BinaryReader(stream); ReadOnlySpan signatureBytes = reader.ReadBytes(6); - return signatureBytes.SequenceEqual(Signature); + return signatureBytes.SequenceEqual(SIGNATURE); } protected override IReader CreateReaderForSolidExtraction() => @@ -196,24 +196,30 @@ public class SevenZipArchive : AbstractArchive Entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder).Count() > 1; - public override long TotalSize => - _database?._packSizes.Aggregate(0L, (total, packSize) => total + packSize) ?? 0; + public override long TotalSize + { + get + { + var i = Entries.Count; + return database._packSizes.Aggregate(0L, (total, packSize) => total + packSize); + } + } private sealed class SevenZipReader : AbstractReader { - private readonly SevenZipArchive _archive; - private CFolder? _currentFolder; - private Stream? _currentStream; - private CFileItem? _currentItem; + private readonly SevenZipArchive archive; + private CFolder currentFolder; + private Stream currentStream; + private CFileItem currentItem; internal SevenZipReader(ReaderOptions readerOptions, SevenZipArchive archive) - : base(readerOptions, ArchiveType.SevenZip) => this._archive = archive; + : base(readerOptions, ArchiveType.SevenZip) => this.archive = archive; - public override SevenZipVolume Volume => _archive.Volumes.Single(); + public override SevenZipVolume Volume => archive.Volumes.Single(); protected override IEnumerable GetEntries(Stream stream) { - var entries = _archive.Entries.ToList(); + var entries = archive.Entries.ToList(); stream.Position = 0; foreach (var dir in entries.Where(x => x.IsDirectory)) { @@ -223,42 +229,37 @@ public class SevenZipArchive : AbstractArchive !x.IsDirectory).GroupBy(x => x.FilePart.Folder) ) { - _currentFolder = group.Key; + currentFolder = group.Key; if (group.Key is null) { - _currentStream = Stream.Null; + currentStream = Stream.Null; } else { - _currentStream = _archive._database?.GetFolderStream( + currentStream = archive.database.GetFolderStream( stream, - _currentFolder, + currentFolder, new PasswordProvider(Options.Password) ); } foreach (var entry in group) { - _currentItem = entry.FilePart.Header; + currentItem = entry.FilePart.Header; yield return entry; } } } protected override EntryStream GetEntryStream() => - CreateEntryStream( - new ReadOnlySubStream( - _currentStream.NotNull("currentStream is not null"), - _currentItem?.Size ?? 0 - ) - ); + CreateEntryStream(new ReadOnlySubStream(currentStream, currentItem.Size)); } private class PasswordProvider : IPasswordProvider { - private readonly string? _password; + private readonly string _password; - public PasswordProvider(string? password) => _password = password; + public PasswordProvider(string password) => _password = password; - public string? CryptoGetTextPassword() => _password; + public string CryptoGetTextPassword() => _password; } } diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index fdf8cd42..43184b66 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -114,7 +114,7 @@ public class TarArchive : AbstractWritableArchive var tarHeader = new TarHeader(new ArchiveEncoding()); var readSucceeded = tarHeader.Read(new BinaryReader(stream)); var isEmptyArchive = - tarHeader.Name?.Length == 0 + tarHeader.Name.Length == 0 && tarHeader.Size == 0 && Enum.IsDefined(typeof(EntryType), tarHeader.EntryType); return readSucceeded || isEmptyArchive; @@ -123,20 +123,22 @@ public class TarArchive : AbstractWritableArchive return false; } - protected override IEnumerable LoadVolumes(SourceStream sourceStream) + protected override IEnumerable LoadVolumes(SourceStream srcStream) { - sourceStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams - return new TarVolume(sourceStream, ReaderOptions, 1).AsEnumerable(); //simple single volume or split, multivolume not supported + SrcStream.LoadAllParts(); //request all streams + var idx = 0; + return new TarVolume(srcStream, ReaderOptions, idx++).AsEnumerable(); //simple single volume or split, multivolume not supported } /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - private TarArchive(SourceStream sourceStream) - : base(ArchiveType.Tar, sourceStream) { } + /// + /// + internal TarArchive(SourceStream srcStream) + : base(ArchiveType.Tar, srcStream) { } - private TarArchive() + internal TarArchive() : base(ArchiveType.Tar) { } protected override IEnumerable LoadEntries(IEnumerable volumes) @@ -190,14 +192,10 @@ public class TarArchive : AbstractWritableArchive ); } } - else - { - throw new IncompleteArchiveException("Failed to read TAR header"); - } } } - public static TarArchive Create() => new(); + public static TarArchive Create() => new TarArchive(); protected override TarArchiveEntry CreateEntryInternal( string filePath, @@ -227,12 +225,7 @@ public class TarArchive : AbstractWritableArchive foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory)) { using var entryStream = entry.OpenEntryStream(); - writer.Write( - entry.Key.NotNull("Entry Key is null"), - entryStream, - entry.LastModifiedTime, - entry.Size - ); + writer.Write(entry.Key, entryStream, entry.LastModifiedTime, entry.Size); } } diff --git a/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs b/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs index d04c4ef8..2da84d71 100644 --- a/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs +++ b/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs @@ -7,7 +7,7 @@ namespace SharpCompress.Archives.Tar; public class TarArchiveEntry : TarEntry, IArchiveEntry { - internal TarArchiveEntry(TarArchive archive, TarFilePart? part, CompressionType compressionType) + internal TarArchiveEntry(TarArchive archive, TarFilePart part, CompressionType compressionType) : base(part, compressionType) => Archive = archive; public virtual Stream OpenEntryStream() => Parts.Single().GetCompressedStream(); diff --git a/src/SharpCompress/Archives/Tar/TarWritableArchiveEntry.cs b/src/SharpCompress/Archives/Tar/TarWritableArchiveEntry.cs index 32be7d9b..0bbea709 100644 --- a/src/SharpCompress/Archives/Tar/TarWritableArchiveEntry.cs +++ b/src/SharpCompress/Archives/Tar/TarWritableArchiveEntry.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index 85130f70..14e4a93e 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -16,7 +16,10 @@ namespace SharpCompress.Archives.Zip; public class ZipArchive : AbstractWritableArchive { - private readonly SeekableZipHeaderFactory? headerFactory; +#nullable disable + private readonly SeekableZipHeaderFactory headerFactory; + +#nullable enable /// /// Gets or sets the compression level applied to files added to the archive, @@ -27,13 +30,13 @@ public class ZipArchive : AbstractWritableArchive /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// + /// /// - internal ZipArchive(SourceStream sourceStream) - : base(ArchiveType.Zip, sourceStream) => + internal ZipArchive(SourceStream srcStream) + : base(ArchiveType.Zip, srcStream) => headerFactory = new SeekableZipHeaderFactory( - sourceStream.ReaderOptions.Password, - sourceStream.ReaderOptions.ArchiveEncoding + srcStream.ReaderOptions.Password, + srcStream.ReaderOptions.ArchiveEncoding ); /// @@ -186,21 +189,21 @@ public class ZipArchive : AbstractWritableArchive } } - protected override IEnumerable LoadVolumes(SourceStream stream) + protected override IEnumerable LoadVolumes(SourceStream srcStream) { - stream.LoadAllParts(); //request all streams - stream.Position = 0; + SrcStream.LoadAllParts(); //request all streams + SrcStream.Position = 0; - var streams = stream.Streams.ToList(); + var streams = SrcStream.Streams.ToList(); var idx = 0; - if (streams.Count() > 1) //test part 2 - true = multipart not split + if (streams.Count > 1) //test part 2 - true = multipart not split { streams[1].Position += 4; //skip the POST_DATA_DESCRIPTOR to prevent an exception var isZip = IsZipFile(streams[1], ReaderOptions.Password); streams[1].Position -= 4; if (isZip) { - stream.IsVolumes = true; + SrcStream.IsVolumes = true; var tmp = streams[0]; //arcs as zip, z01 ... swap the zip the end streams.RemoveAt(0); @@ -212,7 +215,7 @@ public class ZipArchive : AbstractWritableArchive } //split mode or single file - return new ZipVolume(stream, ReaderOptions, idx++).AsEnumerable(); + return new ZipVolume(SrcStream, ReaderOptions, idx++).AsEnumerable(); } internal ZipArchive() @@ -221,13 +224,14 @@ public class ZipArchive : AbstractWritableArchive protected override IEnumerable LoadEntries(IEnumerable volumes) { var vols = volumes.ToArray(); - foreach (var h in headerFactory.NotNull().ReadSeekableHeader(vols.Last().Stream)) + foreach (var h in headerFactory.ReadSeekableHeader(vols.Last().Stream)) { if (h != null) { switch (h.ZipHeaderType) { case ZipHeaderType.DirectoryEntry: + { var deh = (DirectoryEntryHeader)h; Stream s; @@ -250,14 +254,14 @@ public class ZipArchive : AbstractWritableArchive yield return new ZipArchiveEntry( this, - new SeekableZipFilePart(headerFactory.NotNull(), deh, s) + new SeekableZipFilePart(headerFactory, deh, s) ); } break; case ZipHeaderType.DirectoryEnd: { var bytes = ((DirectoryEndHeader)h).Comment ?? Array.Empty(); - vols.Last().Comment = ReaderOptions.ArchiveEncoding.Decode(bytes); + volumes.Last().Comment = ReaderOptions.ArchiveEncoding.Decode(bytes); yield break; } } @@ -278,11 +282,7 @@ public class ZipArchive : AbstractWritableArchive foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory)) { using var entryStream = entry.OpenEntryStream(); - writer.Write( - entry.Key.NotNull("Entry Key is null"), - entryStream, - entry.LastModifiedTime - ); + writer.Write(entry.Key, entryStream, entry.LastModifiedTime); } } @@ -294,7 +294,7 @@ public class ZipArchive : AbstractWritableArchive bool closeStream ) => new ZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream); - public static ZipArchive Create() => new(); + public static ZipArchive Create() => new ZipArchive(); protected override IReader CreateReaderForSolidExtraction() { diff --git a/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs b/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs index 1b2f093d..fdaa85b9 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs @@ -12,7 +12,7 @@ internal static class ZipArchiveVolumeFactory //load files with zip/zipx first. Swapped to end once loaded in ZipArchive //new style .zip, z01.. | .zipx, zx01 - if the numbers go beyond 99 then they use 100 ...1000 etc - var m = Regex.Match(part1.Name, @"^(.*\.)(zipx?|zx?[0-9]+)$", RegexOptions.IgnoreCase); + Match m = Regex.Match(part1.Name, @"^(.*\.)(zipx?|zx?[0-9]+)$", RegexOptions.IgnoreCase); if (m.Success) item = new FileInfo( Path.Combine( diff --git a/src/SharpCompress/BufferPool.cs b/src/SharpCompress/BufferPool.cs deleted file mode 100644 index b11dbe6f..00000000 --- a/src/SharpCompress/BufferPool.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Buffers; - -namespace SharpCompress; - -internal static class BufferPool -{ - /// - /// gets a buffer from the pool - /// - /// size of the buffer - /// the buffer - public static byte[] Rent(int bufferSize) - { -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER - return ArrayPool.Shared.Rent(bufferSize); -#else - return new byte[bufferSize]; -#endif - } - - /// - /// returns a buffer to the pool - /// - /// the buffer to return - public static void Return(byte[] buffer) - { -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER - ArrayPool.Shared.Return(buffer); -#else - // no-op -#endif - } -} diff --git a/src/SharpCompress/Common/ArchiveEncoding.cs b/src/SharpCompress/Common/ArchiveEncoding.cs index 3701a93b..f66044d3 100644 --- a/src/SharpCompress/Common/ArchiveEncoding.cs +++ b/src/SharpCompress/Common/ArchiveEncoding.cs @@ -8,12 +8,12 @@ public class ArchiveEncoding /// /// Default encoding to use when archive format doesn't specify one. /// - public Encoding? Default { get; set; } + public Encoding Default { get; set; } /// /// ArchiveEncoding used by encryption schemes which don't comply with RFC 2898. /// - public Encoding? Password { get; set; } + public Encoding Password { get; set; } /// /// Set this encoding when you want to force it for all encoding operations. @@ -50,8 +50,6 @@ public class ArchiveEncoding public Encoding GetEncoding() => Forced ?? Default ?? Encoding.UTF8; - public Encoding GetPasswordEncoding() => Password ?? Encoding.UTF8; - public Func GetDecoder() => CustomDecoder ?? ((bytes, index, count) => GetEncoding().GetString(bytes, index, count)); } diff --git a/src/SharpCompress/Common/CompressionType.cs b/src/SharpCompress/Common/CompressionType.cs index 20f166c4..11263245 100644 --- a/src/SharpCompress/Common/CompressionType.cs +++ b/src/SharpCompress/Common/CompressionType.cs @@ -14,7 +14,5 @@ public enum CompressionType LZip, Xz, Unknown, - Deflate64, - Shrink, - Lzw + Deflate64 } diff --git a/src/SharpCompress/Common/Entry.cs b/src/SharpCompress/Common/Entry.cs index 6209b3de..85219a43 100644 --- a/src/SharpCompress/Common/Entry.cs +++ b/src/SharpCompress/Common/Entry.cs @@ -14,7 +14,7 @@ public abstract class Entry : IEntry /// /// The string key of the file internal to the Archive. /// - public abstract string? Key { get; } + public abstract string Key { get; } /// /// The target of a symlink entry internal to the Archive. Will be null if not a symlink. @@ -71,11 +71,11 @@ public abstract class Entry : IEntry /// public abstract bool IsSplitAfter { get; } - public int VolumeIndexFirst => Parts.FirstOrDefault()?.Index ?? 0; - public int VolumeIndexLast => Parts.LastOrDefault()?.Index ?? 0; + public int VolumeIndexFirst => Parts?.FirstOrDefault()?.Index ?? 0; + public int VolumeIndexLast => Parts?.LastOrDefault()?.Index ?? 0; /// - public override string ToString() => Key ?? "Entry"; + public override string ToString() => Key; internal abstract IEnumerable Parts { get; } diff --git a/src/SharpCompress/Common/ExtractionMethods.cs b/src/SharpCompress/Common/ExtractionMethods.cs index 27d41648..c8e5896e 100644 --- a/src/SharpCompress/Common/ExtractionMethods.cs +++ b/src/SharpCompress/Common/ExtractionMethods.cs @@ -16,7 +16,7 @@ internal static class ExtractionMethods ) { string destinationFileName; - var fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory); + string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory); //check for trailing slash. if ( @@ -36,12 +36,11 @@ internal static class ExtractionMethods options ??= new ExtractionOptions() { Overwrite = true }; - var file = Path.GetFileName(entry.Key.NotNull("Entry Key is null")).NotNull("File is null"); + string file = Path.GetFileName(entry.Key); if (options.ExtractFullPath) { - var folder = Path.GetDirectoryName(entry.Key.NotNull("Entry Key is null")) - .NotNull("Directory is null"); - var 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)) { @@ -103,7 +102,7 @@ internal static class ExtractionMethods } else { - var fm = FileMode.Create; + FileMode fm = FileMode.Create; options ??= new ExtractionOptions() { Overwrite = true }; if (!options.Overwrite) diff --git a/src/SharpCompress/Common/FilePart.cs b/src/SharpCompress/Common/FilePart.cs index 23b8b400..3c286d54 100644 --- a/src/SharpCompress/Common/FilePart.cs +++ b/src/SharpCompress/Common/FilePart.cs @@ -8,7 +8,7 @@ public abstract class FilePart internal ArchiveEncoding ArchiveEncoding { get; } - internal abstract string? FilePartName { get; } + internal abstract string FilePartName { get; } public int Index { get; set; } internal abstract Stream GetCompressedStream(); diff --git a/src/SharpCompress/Common/GZip/GZipEntry.cs b/src/SharpCompress/Common/GZip/GZipEntry.cs index 9a551d07..bb9a22da 100644 --- a/src/SharpCompress/Common/GZip/GZipEntry.cs +++ b/src/SharpCompress/Common/GZip/GZipEntry.cs @@ -6,23 +6,23 @@ namespace SharpCompress.Common.GZip; public class GZipEntry : Entry { - private readonly GZipFilePart? _filePart; + private readonly GZipFilePart _filePart; - internal GZipEntry(GZipFilePart? filePart) => _filePart = filePart; + internal GZipEntry(GZipFilePart filePart) => _filePart = filePart; public override CompressionType CompressionType => CompressionType.GZip; - public override long Crc => _filePart?.Crc ?? 0; + public override long Crc => _filePart.Crc ?? 0; - public override string? Key => _filePart?.FilePartName; + public override string Key => _filePart.FilePartName; public override string? LinkTarget => null; public override long CompressedSize => 0; - public override long Size => _filePart?.UncompressedSize ?? 0; + public override long Size => _filePart.UncompressedSize ?? 0; - public override DateTime? LastModifiedTime => _filePart?.DateModified; + public override DateTime? LastModifiedTime => _filePart.DateModified; public override DateTime? CreatedTime => null; @@ -36,7 +36,7 @@ public class GZipEntry : Entry public override bool IsSplitAfter => false; - internal override IEnumerable Parts => _filePart.Empty(); + internal override IEnumerable Parts => _filePart.AsEnumerable(); internal static IEnumerable GetEntries(Stream stream, OptionsBase options) { diff --git a/src/SharpCompress/Common/GZip/GZipFilePart.cs b/src/SharpCompress/Common/GZip/GZipFilePart.cs index 4a1c9515..fbf4ee45 100644 --- a/src/SharpCompress/Common/GZip/GZipFilePart.cs +++ b/src/SharpCompress/Common/GZip/GZipFilePart.cs @@ -34,7 +34,7 @@ internal sealed class GZipFilePart : FilePart internal uint? Crc { get; private set; } internal uint? UncompressedSize { get; private set; } - internal override string? FilePartName => _name; + internal override string FilePartName => _name!; internal override Stream GetCompressedStream() => new DeflateStream(_stream, CompressionMode.Decompress, CompressionLevel.Default); diff --git a/src/SharpCompress/Common/GZip/GZipVolume.cs b/src/SharpCompress/Common/GZip/GZipVolume.cs index 600ba8e3..0dd9b8d9 100644 --- a/src/SharpCompress/Common/GZip/GZipVolume.cs +++ b/src/SharpCompress/Common/GZip/GZipVolume.cs @@ -5,7 +5,7 @@ namespace SharpCompress.Common.GZip; public class GZipVolume : Volume { - public GZipVolume(Stream stream, ReaderOptions? options, int index) + public GZipVolume(Stream stream, ReaderOptions options, int index = 0) : base(stream, options, index) { } public GZipVolume(FileInfo fileInfo, ReaderOptions options) diff --git a/src/SharpCompress/Common/IEntry.cs b/src/SharpCompress/Common/IEntry.cs index 56e1db81..df1fa603 100644 --- a/src/SharpCompress/Common/IEntry.cs +++ b/src/SharpCompress/Common/IEntry.cs @@ -9,7 +9,7 @@ public interface IEntry long CompressedSize { get; } long Crc { get; } DateTime? CreatedTime { get; } - string? Key { get; } + string Key { get; } string? LinkTarget { get; } bool IsDirectory { get; } bool IsEncrypted { get; } diff --git a/src/SharpCompress/Common/IVolume.cs b/src/SharpCompress/Common/IVolume.cs index aed35fd0..abbc0406 100644 --- a/src/SharpCompress/Common/IVolume.cs +++ b/src/SharpCompress/Common/IVolume.cs @@ -6,5 +6,5 @@ public interface IVolume : IDisposable { int Index { get; } - string? FileName { get; } + string FileName { get; } } diff --git a/src/SharpCompress/Common/OptionsBase.cs b/src/SharpCompress/Common/OptionsBase.cs index 8d1cbd1c..61a6cb55 100644 --- a/src/SharpCompress/Common/OptionsBase.cs +++ b/src/SharpCompress/Common/OptionsBase.cs @@ -7,5 +7,5 @@ public class OptionsBase /// public bool LeaveStreamOpen { get; set; } = true; - public ArchiveEncoding ArchiveEncoding { get; set; } = new(); + public ArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding(); } diff --git a/src/SharpCompress/Common/PasswordProtectedException.cs b/src/SharpCompress/Common/PasswordProtectedException.cs new file mode 100644 index 00000000..9ebe3d65 --- /dev/null +++ b/src/SharpCompress/Common/PasswordProtectedException.cs @@ -0,0 +1,12 @@ +using System; + +namespace SharpCompress.Common; + +public class PasswordProtectedException : ExtractionException +{ + public PasswordProtectedException(string message) + : base(message) { } + + public PasswordProtectedException(string message, Exception inner) + : base(message, inner) { } +} diff --git a/src/SharpCompress/Common/Rar/CryptKey3.cs b/src/SharpCompress/Common/Rar/CryptKey3.cs deleted file mode 100644 index 93e451b1..00000000 --- a/src/SharpCompress/Common/Rar/CryptKey3.cs +++ /dev/null @@ -1,84 +0,0 @@ -#nullable disable - -using System.Security.Cryptography; -using System.Text; -using SharpCompress.Common.Rar.Headers; - -namespace SharpCompress.Common.Rar; - -internal class CryptKey3 : ICryptKey -{ - const int AES_128 = 128; - - private string _password; - - public CryptKey3(string password) => _password = password ?? ""; - - public ICryptoTransform Transformer(byte[] salt) - { - var aesIV = new byte[EncryptionConstV5.SIZE_INITV]; - - var rawLength = 2 * _password.Length; - var rawPassword = new byte[rawLength + EncryptionConstV5.SIZE_SALT30]; - var passwordBytes = Encoding.UTF8.GetBytes(_password); - for (var i = 0; i < _password.Length; i++) - { - rawPassword[i * 2] = passwordBytes[i]; - rawPassword[(i * 2) + 1] = 0; - } - - for (var i = 0; i < salt.Length; i++) - { - rawPassword[i + rawLength] = salt[i]; - } - - var msgDigest = SHA1.Create(); - const int noOfRounds = (1 << 18); - const int iblock = 3; - - byte[] digest; - var data = new byte[(rawPassword.Length + iblock) * noOfRounds]; - - //TODO slow code below, find ways to optimize - for (var i = 0; i < noOfRounds; i++) - { - rawPassword.CopyTo(data, i * (rawPassword.Length + iblock)); - - data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i; - data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8); - data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)(i >> 16); - - if (i % (noOfRounds / EncryptionConstV5.SIZE_INITV) == 0) - { - digest = msgDigest.ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock)); - aesIV[i / (noOfRounds / EncryptionConstV5.SIZE_INITV)] = digest[19]; - } - } - digest = msgDigest.ComputeHash(data); - //slow code ends - - var aesKey = new byte[EncryptionConstV5.SIZE_INITV]; - for (var i = 0; i < 4; i++) - { - for (var j = 0; j < 4; j++) - { - aesKey[(i * 4) + j] = (byte)( - ( - ((digest[i * 4] * 0x1000000) & 0xff000000) - | (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000) - | (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00) - | (uint)(digest[(i * 4) + 3] & 0xff) - ) >> (j * 8) - ); - } - } - - var aes = Aes.Create(); - aes.KeySize = AES_128; - aes.Mode = CipherMode.CBC; - aes.Padding = PaddingMode.None; - aes.Key = aesKey; - aes.IV = aesIV; - return aes.CreateDecryptor(); - } -} diff --git a/src/SharpCompress/Common/Rar/CryptKey5.cs b/src/SharpCompress/Common/Rar/CryptKey5.cs deleted file mode 100644 index 0b802691..00000000 --- a/src/SharpCompress/Common/Rar/CryptKey5.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using SharpCompress.Common.Rar.Headers; - -namespace SharpCompress.Common.Rar; - -internal class CryptKey5 : ICryptKey -{ - const int AES_256 = 256; - const int DERIVED_KEY_LENGTH = 0x10; - const int SHA256_DIGEST_SIZE = 32; - - private string _password; - private Rar5CryptoInfo _cryptoInfo; - private byte[] _pswCheck = { }; - private byte[] _hashKey = { }; - - public CryptKey5(string password, Rar5CryptoInfo rar5CryptoInfo) - { - _password = password ?? ""; - _cryptoInfo = rar5CryptoInfo; - } - - public byte[] PswCheck => _pswCheck; - - public byte[] HashKey => _hashKey; - - private static List GenerateRarPBKDF2Key( - string password, - byte[] salt, - int iterations, - int keyLength - ) - { - using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)); - var block = hmac.ComputeHash(salt); - var finalHash = (byte[])block.Clone(); - - var loop = new int[] { iterations, 17, 17 }; - var res = new List { }; - - for (var x = 0; x < 3; x++) - { - for (var i = 1; i < loop[x]; i++) - { - block = hmac.ComputeHash(block); - for (var j = 0; j < finalHash.Length; j++) - { - finalHash[j] ^= block[j]; - } - } - - res.Add((byte[])finalHash.Clone()); - } - - return res; - } - - public ICryptoTransform Transformer(byte[] salt) - { - var iterations = (1 << _cryptoInfo.LG2Count); // Adjust the number of iterations as needed - - var salt_rar5 = salt.Concat(new byte[] { 0, 0, 0, 1 }); - var derivedKey = GenerateRarPBKDF2Key( - _password, - salt_rar5.ToArray(), - iterations, - DERIVED_KEY_LENGTH - ); - - _hashKey = derivedKey[1]; - - _pswCheck = new byte[EncryptionConstV5.SIZE_PSWCHECK]; - - for (var i = 0; i < SHA256_DIGEST_SIZE; i++) - { - _pswCheck[i % EncryptionConstV5.SIZE_PSWCHECK] ^= derivedKey[2][i]; - } - - if (_cryptoInfo.UsePswCheck && !_cryptoInfo.PswCheck.SequenceEqual(_pswCheck)) - { - throw new CryptographicException("The password did not match."); - } - - var aes = Aes.Create(); - aes.KeySize = AES_256; - aes.Mode = CipherMode.CBC; - aes.Padding = PaddingMode.None; - aes.Key = derivedKey[0]; - aes.IV = _cryptoInfo.InitV; - return aes.CreateDecryptor(); - } -} diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs index 5aa29d49..619e8fc9 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs @@ -1,19 +1,50 @@ #nullable disable -using System; -using System.Security.Cryptography; -using SharpCompress.Common.Rar.Headers; using SharpCompress.IO; namespace SharpCompress.Common.Rar.Headers; internal class ArchiveCryptHeader : RarHeader { + private const int CRYPT_VERSION = 0; // Supported encryption version. + private const int SIZE_SALT50 = 16; + private const int SIZE_PSWCHECK = 8; + private const int SIZE_PSWCHECK_CSUM = 4; + private const int CRYPT5_KDF_LG2_COUNT_MAX = 24; // LOG2 of maximum accepted iteration count. + + private bool _usePswCheck; + private uint _lg2Count; // Log2 of PBKDF2 repetition count. + private byte[] _salt; + private byte[] _pswCheck; + private byte[] _pswCheckCsm; + public ArchiveCryptHeader(RarHeader header, RarCrcBinaryReader reader) : base(header, reader, HeaderType.Crypt) { } - public Rar5CryptoInfo CryptInfo = new(); + protected override void ReadFinish(MarkingBinaryReader reader) + { + var cryptVersion = reader.ReadRarVIntUInt32(); + if (cryptVersion > CRYPT_VERSION) + { + //error? + return; + } + var encryptionFlags = reader.ReadRarVIntUInt32(); + _usePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK); + _lg2Count = reader.ReadRarVIntByte(1); - protected override void ReadFinish(MarkingBinaryReader reader) => - CryptInfo = new Rar5CryptoInfo(reader, false); + //UsePswCheck = HasHeaderFlag(EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK); + if (_lg2Count > CRYPT5_KDF_LG2_COUNT_MAX) + { + //error? + return; + } + + _salt = reader.ReadBytes(SIZE_SALT50); + if (_usePswCheck) + { + _pswCheck = reader.ReadBytes(SIZE_PSWCHECK); + _pswCheckCsm = reader.ReadBytes(SIZE_PSWCHECK_CSUM); + } + } } diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index eea8293d..e95052ef 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -1,11 +1,5 @@ #nullable disable -using System; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using SharpCompress.IO; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -14,11 +8,16 @@ using nuint = System.UInt64; using size_t = System.UInt64; #endif +using SharpCompress.IO; +using System; +using System.IO; +using System.Text; + namespace SharpCompress.Common.Rar.Headers; internal class FileHeader : RarHeader { - private byte[] _hash; + private uint _fileCrc; public FileHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) : base(header, reader, headerType) { } @@ -53,7 +52,7 @@ internal class FileHeader : RarHeader if (HasFlag(FileFlagsV5.HAS_CRC32)) { - FileCrc = reader.ReadBytes(4); + FileCrc = reader.ReadUInt32(); } var compressionInfo = reader.ReadRarVIntUInt16(); @@ -105,13 +104,7 @@ internal class FileHeader : RarHeader throw new InvalidFormatException("rar5 header size / extra size inconsistency"); } - const ushort FHEXTRA_CRYPT = 0x01; - const ushort FHEXTRA_HASH = 0x02; - const ushort FHEXTRA_HTIME = 0x03; - // const ushort FHEXTRA_VERSION = 0x04; - const ushort FHEXTRA_REDIR = 0x05; - // const ushort FHEXTRA_UOWNER = 0x06; - // const ushort FHEXTRA_SUBDATA = 0x07; + isEncryptedRar5 = false; while (RemainingHeaderBytes(reader) > 0) { @@ -120,30 +113,23 @@ internal class FileHeader : RarHeader var type = reader.ReadRarVIntUInt16(); switch (type) { - case FHEXTRA_CRYPT: // file encryption - { - Rar5CryptoInfo = new Rar5CryptoInfo(reader, true); + //TODO + case 1: // file encryption - if (Rar5CryptoInfo.PswCheck.All(singleByte => singleByte == 0)) - { - Rar5CryptoInfo = null; - } - } - break; - case FHEXTRA_HASH: { - const uint FHEXTRA_HASH_BLAKE2 = 0x0; - // const uint HASH_BLAKE2 = 0x03; - const int BLAKE2_DIGEST_SIZE = 0x20; - if ((uint)reader.ReadRarVInt() == FHEXTRA_HASH_BLAKE2) - { - // var hash = HASH_BLAKE2; - _hash = reader.ReadBytes(BLAKE2_DIGEST_SIZE); - } - // enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2}; + isEncryptedRar5 = true; + + //var version = reader.ReadRarVIntByte(); + //if (version != 0) throw new InvalidFormatException("unknown encryption algorithm " + version); } break; - case FHEXTRA_HTIME: // file time + // case 2: // file hash + // { + // + // } + // break; + case 3: // file time + { var flags = reader.ReadRarVIntUInt16(); var isWindowsTime = (flags & 1) == 0; @@ -162,27 +148,22 @@ internal class FileHeader : RarHeader } break; //TODO - // case FHEXTRA_VERSION: // file version + // case 4: // file version // { // // } // break; - case FHEXTRA_REDIR: // file system redirection - { - RedirType = reader.ReadRarVIntByte(); - RedirFlags = reader.ReadRarVIntByte(); - var nn = reader.ReadRarVIntUInt16(); - var bb = reader.ReadBytes(nn); - RedirTargetName = ConvertPathV5(Encoding.UTF8.GetString(bb, 0, bb.Length)); - } - break; - //TODO - // case FHEXTRA_UOWNER: // unix owner + // case 5: // file system redirection // { // // } // break; - // case FHEXTRA_SUBDATA: // service data + // case 6: // unix owner + // { + // + // } + // break; + // case 7: // service data // { // // } @@ -190,7 +171,6 @@ internal class FileHeader : RarHeader default: // skip unknown record types to allow new record types to be added in the future - //Console.WriteLine($"unhandled rar header field type {type}"); break; } // drain any trailing bytes of extra record @@ -242,7 +222,7 @@ internal class FileHeader : RarHeader HostOs = reader.ReadByte(); - FileCrc = reader.ReadBytes(4); + FileCrc = reader.ReadUInt32(); FileLastModifiedTime = Utility.DosDateToDateTime(reader.ReadUInt32()); @@ -275,11 +255,13 @@ internal class FileHeader : RarHeader var fileNameBytes = reader.ReadBytes(nameSize); + const int saltSize = 8; const int newLhdSize = 32; switch (HeaderCode) { case HeaderCodeV.RAR4_FILE_HEADER: + { if (HasFlag(FileFlagsV4.UNICODE)) { @@ -306,11 +288,12 @@ internal class FileHeader : RarHeader } break; case HeaderCodeV.RAR4_NEW_SUB_HEADER: + { var datasize = HeaderSize - newLhdSize - nameSize; if (HasFlag(FileFlagsV4.SALT)) { - datasize -= EncryptionConstV5.SIZE_SALT30; + datasize -= saltSize; } if (datasize > 0) { @@ -331,7 +314,7 @@ internal class FileHeader : RarHeader if (HasFlag(FileFlagsV4.SALT)) { - R4Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT30); + R4Salt = reader.ReadBytes(saltSize); } if (HasFlag(FileFlagsV4.EXT_TIME)) { @@ -412,10 +395,18 @@ internal class FileHeader : RarHeader private bool HasFlag(ushort flag) => (Flags & flag) == flag; - internal byte[] FileCrc + internal uint FileCrc { - get => _hash; - private set => _hash = value; + get + { + if (IsRar5 && !HasFlag(FileFlagsV5.HAS_CRC32)) + { + //!!! rar5: + throw new InvalidOperationException("TODO rar5"); + } + return _fileCrc; + } + private set => _fileCrc = value; } // 0 - storing @@ -437,17 +428,11 @@ internal class FileHeader : RarHeader public bool IsSolid { get; private set; } - public byte RedirType { get; private set; } - public bool IsRedir => RedirType != 0; - public byte RedirFlags { get; private set; } - public bool IsRedirDirectory => (RedirFlags & RedirFlagV5.DIRECTORY) != 0; - public string RedirTargetName { get; private set; } - // unused for UnpackV1 implementation (limitation) internal size_t WindowSize { get; private set; } internal byte[] R4Salt { get; private set; } - internal Rar5CryptoInfo Rar5CryptoInfo { get; private set; } + private byte HostOs { get; set; } internal uint FileAttributes { get; private set; } internal long CompressedSize { get; private set; } @@ -465,7 +450,8 @@ internal class FileHeader : RarHeader public bool IsDirectory => HasFlag(IsRar5 ? FileFlagsV5.DIRECTORY : FileFlagsV4.DIRECTORY); - public bool IsEncrypted => IsRar5 ? Rar5CryptoInfo != null : HasFlag(FileFlagsV4.PASSWORD); + private bool isEncryptedRar5 = false; + public bool IsEncrypted => IsRar5 ? isEncryptedRar5 : HasFlag(FileFlagsV4.PASSWORD); internal DateTime? FileLastModifiedTime { get; private set; } diff --git a/src/SharpCompress/Common/Rar/Headers/Flags.cs b/src/SharpCompress/Common/Rar/Headers/Flags.cs index 990dbc99..5a52f001 100644 --- a/src/SharpCompress/Common/Rar/Headers/Flags.cs +++ b/src/SharpCompress/Common/Rar/Headers/Flags.cs @@ -50,17 +50,6 @@ internal static class EncryptionFlagsV5 public const uint FHEXTRA_CRYPT_HASHMAC = 0x02; } -internal static class EncryptionConstV5 -{ - public const int VERSION = 0; - public const uint CRYPT5_KDF_LG2_COUNT_MAX = 0x24; - public const int SIZE_SALT30 = 0x08; - public const int SIZE_SALT50 = 0x10; - public const int SIZE_INITV = 0x10; - public const int SIZE_PSWCHECK = 0x08; - public const int SIZE_PSWCHECK_CSUM = 0x04; -} - internal static class HeaderFlagsV5 { public const ushort HAS_EXTRA = 0x0001; @@ -157,17 +146,3 @@ internal static class EndArchiveFlagsV5 { public const ushort HAS_NEXT_VOLUME = 0x0001; } - -internal static class RedirTypeV5 -{ - public const byte UNIX_SYMLINK = 0x0001; - public const byte WIN_SYMLINK = 0x0002; - public const byte WIN_JUNCTION = 0x0003; - public const byte HARD_LINK = 0x0004; - public const byte FILE_COPY = 0x0005; -} - -internal static class RedirFlagV5 -{ - public const byte DIRECTORY = 0x0001; -} diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs index 0d8648e8..81002fc4 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using SharpCompress.IO; diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index 74d68fc7..d371166d 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.IO; -using System.Linq; -using SharpCompress.Common.Rar; using SharpCompress.IO; using SharpCompress.Readers; @@ -11,8 +9,6 @@ public class RarHeaderFactory { private bool _isRar5; - private Rar5CryptoInfo? _cryptInfo; - public RarHeaderFactory(StreamingMode mode, ReaderOptions options) { StreamingMode = mode; @@ -57,19 +53,7 @@ public class RarHeaderFactory "Encrypted Rar archive has no password specified." ); } - - if (_isRar5 && _cryptInfo != null) - { - _cryptInfo.ReadInitV(new MarkingBinaryReader(stream)); - var _headerKey = new CryptKey5(Options.Password!, _cryptInfo); - - reader = new RarCryptoBinaryReader(stream, _headerKey, _cryptInfo.Salt); - } - else - { - var key = new CryptKey3(Options.Password); - reader = new RarCryptoBinaryReader(stream, key); - } + reader = new RarCryptoBinaryReader(stream, Options.Password); } var header = RarHeader.TryReadBase(reader, _isRar5, Options.ArchiveEncoding); @@ -98,11 +82,13 @@ public class RarHeaderFactory switch (StreamingMode) { case StreamingMode.Seekable: + { reader.BaseStream.Position += ph.DataSize; } break; case StreamingMode.Streaming: + { reader.BaseStream.Skip(ph.DataSize); } @@ -119,14 +105,7 @@ public class RarHeaderFactory case HeaderCodeV.RAR5_SERVICE_HEADER: { var fh = new FileHeader(header, reader, HeaderType.Service); - if (fh.FileName == "CMT") - { - fh.PackedStream = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize); - } - else - { - SkipData(fh, reader); - } + SkipData(fh, reader); return fh; } @@ -144,15 +123,17 @@ public class RarHeaderFactory switch (StreamingMode) { case StreamingMode.Seekable: + { fh.DataStartPosition = reader.BaseStream.Position; reader.BaseStream.Position += fh.CompressedSize; } break; case StreamingMode.Streaming: + { var ms = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize); - if (fh.R4Salt is null && fh.Rar5CryptoInfo is null) + if (fh.R4Salt is null) { fh.PackedStream = ms; } @@ -160,10 +141,8 @@ public class RarHeaderFactory { fh.PackedStream = new RarCryptoWrapper( ms, - fh.R4Salt is null ? fh.Rar5CryptoInfo.Salt : fh.R4Salt, - fh.R4Salt is null - ? new CryptKey5(Options.Password!, fh.Rar5CryptoInfo) - : new CryptKey3(Options.Password!) + Options.Password!, + fh.R4Salt ); } } @@ -182,11 +161,9 @@ public class RarHeaderFactory } case HeaderCodeV.RAR5_ARCHIVE_ENCRYPTION_HEADER: { - var cryptoHeader = new ArchiveCryptHeader(header, reader); + var ch = new ArchiveCryptHeader(header, reader); IsEncrypted = true; - _cryptInfo = cryptoHeader.CryptInfo; - - return cryptoHeader; + return ch; } default: { @@ -200,12 +177,14 @@ public class RarHeaderFactory 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); diff --git a/src/SharpCompress/Common/Rar/ICryptKey.cs b/src/SharpCompress/Common/Rar/ICryptKey.cs deleted file mode 100644 index 94f068f5..00000000 --- a/src/SharpCompress/Common/Rar/ICryptKey.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Security.Cryptography; - -namespace SharpCompress.Common.Rar; - -internal interface ICryptKey -{ - ICryptoTransform Transformer(byte[] salt); -} diff --git a/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs b/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs deleted file mode 100644 index 7b8edff9..00000000 --- a/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Security.Cryptography; -using SharpCompress.Common.Rar.Headers; -using SharpCompress.IO; - -namespace SharpCompress.Common.Rar; - -internal class Rar5CryptoInfo -{ - public Rar5CryptoInfo() { } - - public Rar5CryptoInfo(MarkingBinaryReader reader, bool readInitV) - { - var cryptVersion = reader.ReadRarVIntUInt32(); - if (cryptVersion > EncryptionConstV5.VERSION) - { - throw new CryptographicException($"Unsupported crypto version of {cryptVersion}"); - } - var encryptionFlags = reader.ReadRarVIntUInt32(); - UsePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK); - LG2Count = reader.ReadRarVIntByte(1); - - if (LG2Count > EncryptionConstV5.CRYPT5_KDF_LG2_COUNT_MAX) - { - throw new CryptographicException($"Unsupported LG2 count of {LG2Count}."); - } - - Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT50); - - if (readInitV) // File header needs to read IV here - { - ReadInitV(reader); - } - - if (UsePswCheck) - { - PswCheck = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK); - var _pswCheckCsm = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK_CSUM); - - var sha = SHA256.Create(); - UsePswCheck = sha.ComputeHash(PswCheck).AsSpan().StartsWith(_pswCheckCsm.AsSpan()); - } - } - - public void ReadInitV(MarkingBinaryReader reader) => - InitV = reader.ReadBytes(EncryptionConstV5.SIZE_INITV); - - public bool UsePswCheck = false; - - public int LG2Count = 0; - - public byte[] InitV = { }; - - public byte[] Salt = { }; - - public byte[] PswCheck = { }; -} diff --git a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs index 6e44286b..0be6e74e 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs @@ -1,28 +1,28 @@ -#nullable disable - -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; -using SharpCompress.Common.Rar.Headers; -using SharpCompress.Crypto; namespace SharpCompress.Common.Rar; internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader { - private BlockTransformer _rijndael; - private readonly Queue _data = new(); + private RarRijndael _rijndael; + private byte[] _salt; + private readonly string _password; + private readonly Queue _data = new Queue(); private long _readCount; - public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey) + public RarCryptoBinaryReader(Stream stream, string password) : base(stream) { - var salt = base.ReadBytes(EncryptionConstV5.SIZE_SALT30); - _readCount += EncryptionConstV5.SIZE_SALT30; - _rijndael = new BlockTransformer(cryptKey.Transformer(salt)); - } + _password = password; - public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey, byte[] salt) - : base(stream) => _rijndael = new BlockTransformer(cryptKey.Transformer(salt)); + // coderb: not sure why this was being done at this logical point + //SkipQueue(); + var salt = ReadBytes(8); + + _salt = salt; + _rijndael = RarRijndael.InitializeFrom(_password, salt); + } // track read count ourselves rather than using the underlying stream since we buffer public override long CurrentReadByteCount @@ -36,9 +36,29 @@ internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader public override void Mark() => _readCount = 0; - public override byte ReadByte() => ReadAndDecryptBytes(1)[0]; + private bool UseEncryption => _salt != null; - public override byte[] ReadBytes(int count) => ReadAndDecryptBytes(count); + public override byte ReadByte() + { + if (UseEncryption) + { + return ReadAndDecryptBytes(1)[0]; + } + + _readCount++; + return base.ReadByte(); + } + + public override byte[] ReadBytes(int count) + { + if (UseEncryption) + { + return ReadAndDecryptBytes(count); + } + + _readCount += count; + return base.ReadBytes(count); + } private byte[] ReadAndDecryptBytes(int count) { diff --git a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index 5500af8d..a1cee046 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -1,30 +1,37 @@ using System; using System.Collections.Generic; using System.IO; -using SharpCompress.Crypto; namespace SharpCompress.Common.Rar; internal sealed class RarCryptoWrapper : Stream { private readonly Stream _actualStream; - private BlockTransformer _rijndael; - private readonly Queue _data = new(); + private readonly byte[] _salt; + private RarRijndael _rijndael; + private readonly Queue _data = new Queue(); - public RarCryptoWrapper(Stream actualStream, byte[] salt, ICryptKey key) + public RarCryptoWrapper(Stream actualStream, string password, byte[] salt) { _actualStream = actualStream; - _rijndael = new BlockTransformer(key.Transformer(salt)); + _salt = salt; + _rijndael = RarRijndael.InitializeFrom(password ?? "", salt); } - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); public override void SetLength(long value) => throw new NotSupportedException(); - public override int Read(byte[] buffer, int offset, int count) => - ReadAndDecrypt(buffer, offset, count); + public override int Read(byte[] buffer, int offset, int count) + { + if (_salt is null) + { + return _actualStream.Read(buffer, offset, count); + } + return ReadAndDecrypt(buffer, offset, count); + } public int ReadAndDecrypt(byte[] buffer, int offset, int count) { @@ -34,7 +41,7 @@ internal sealed class RarCryptoWrapper : Stream if (sizeToRead > 0) { var alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf); - Span cipherText = stackalloc byte[16]; + Span cipherText = stackalloc byte[RarRijndael.CRYPTO_BLOCK_SIZE]; for (var i = 0; i < alignedSize / 16; i++) { //long ax = System.currentTimeMillis(); @@ -70,11 +77,11 @@ internal sealed class RarCryptoWrapper : Stream protected override void Dispose(bool disposing) { - if (disposing) + if (_rijndael != null) { _rijndael.Dispose(); + _rijndael = null!; } - base.Dispose(disposing); } } diff --git a/src/SharpCompress/Common/Rar/RarEntry.cs b/src/SharpCompress/Common/Rar/RarEntry.cs index a064c2f8..7f280e4a 100644 --- a/src/SharpCompress/Common/Rar/RarEntry.cs +++ b/src/SharpCompress/Common/Rar/RarEntry.cs @@ -20,12 +20,12 @@ public abstract class RarEntry : Entry /// /// The File's 32 bit CRC Hash /// - public override long Crc => BitConverter.ToUInt32(FileHeader.FileCrc, 0); + public override long Crc => FileHeader.FileCrc; /// /// The path of the file internal to the Rar Archive. /// - public override string? Key => FileHeader.FileName; + public override string Key => FileHeader.FileName; public override string? LinkTarget => null; @@ -55,21 +55,12 @@ public abstract class RarEntry : Entry public override bool IsEncrypted => FileHeader.IsEncrypted; /// - /// Entry Windows file attributes - /// - public override int? Attrib => (int)FileHeader.FileAttributes; - - /// - /// Entry is a directory + /// Entry is password protected and encrypted and cannot be extracted. /// public override bool IsDirectory => FileHeader.IsDirectory; public override bool IsSplitAfter => FileHeader.IsSplitAfter; - public bool IsRedir => FileHeader.IsRedir; - - public string RedirTargetName => FileHeader.RedirTargetName; - public override string ToString() => string.Format( "Entry Path: {0} Compressed Size: {1} Uncompressed Size: {2} CRC: {3}", diff --git a/src/SharpCompress/Common/Rar/RarRijndael.cs b/src/SharpCompress/Common/Rar/RarRijndael.cs new file mode 100644 index 00000000..94592639 --- /dev/null +++ b/src/SharpCompress/Common/Rar/RarRijndael.cs @@ -0,0 +1,114 @@ +#nullable disable + +using System; +using System.Security.Cryptography; +using System.Text; +using SharpCompress.Crypto; + +namespace SharpCompress.Common.Rar; + +internal class RarRijndael : IDisposable +{ + internal const int CRYPTO_BLOCK_SIZE = 16; + + private readonly string _password; + private readonly byte[] _salt; + private byte[] _aesInitializationVector; + private RijndaelEngine _rijndael; + + private RarRijndael(string password, byte[] salt) + { + _password = password; + _salt = salt; + } + + private void Initialize() + { + _rijndael = new RijndaelEngine(); + _aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE]; + var rawLength = 2 * _password.Length; + var rawPassword = new byte[rawLength + 8]; + var passwordBytes = Encoding.UTF8.GetBytes(_password); + for (var i = 0; i < _password.Length; i++) + { + rawPassword[i * 2] = passwordBytes[i]; + rawPassword[(i * 2) + 1] = 0; + } + for (var i = 0; i < _salt.Length; i++) + { + rawPassword[i + rawLength] = _salt[i]; + } + + const int noOfRounds = (1 << 18); + const int iblock = 3; + byte[] digest; + var data = new byte[(rawPassword.Length + iblock) * noOfRounds]; + + //TODO slow code below, find ways to optimize + for (var i = 0; i < noOfRounds; i++) + { + rawPassword.CopyTo(data, i * (rawPassword.Length + iblock)); + + data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i; + data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8); + data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)( + i >> CRYPTO_BLOCK_SIZE + ); + + if (i % (noOfRounds / CRYPTO_BLOCK_SIZE) == 0) + { + digest = SHA1.Create() + .ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock)); + _aesInitializationVector[i / (noOfRounds / CRYPTO_BLOCK_SIZE)] = digest[19]; + } + } + digest = SHA1.Create().ComputeHash(data); + //slow code ends + + var aesKey = new byte[CRYPTO_BLOCK_SIZE]; + for (var i = 0; i < 4; i++) + { + for (var j = 0; j < 4; j++) + { + aesKey[(i * 4) + j] = (byte)( + ( + ((digest[i * 4] * 0x1000000) & 0xff000000) + | (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000) + | (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00) + | (uint)(digest[(i * 4) + 3] & 0xff) + ) >> (j * 8) + ); + } + } + + _rijndael.Init(false, new KeyParameter(aesKey)); + } + + public static RarRijndael InitializeFrom(string password, byte[] salt) + { + var rijndael = new RarRijndael(password, salt); + rijndael.Initialize(); + return rijndael; + } + + public byte[] ProcessBlock(ReadOnlySpan cipherText) + { + Span plainText = stackalloc byte[CRYPTO_BLOCK_SIZE]; // 16 bytes + var decryptedBytes = new byte[CRYPTO_BLOCK_SIZE]; + _rijndael.ProcessBlock(cipherText, plainText); + + for (var j = 0; j < CRYPTO_BLOCK_SIZE; j++) + { + decryptedBytes[j] = (byte)(plainText[j] ^ _aesInitializationVector[j % 16]); //32:114, 33:101 + } + + for (var j = 0; j < _aesInitializationVector.Length; j++) + { + _aesInitializationVector[j] = cipherText[j]; + } + + return decryptedBytes; + } + + public void Dispose() { } +} diff --git a/src/SharpCompress/Common/Rar/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index d05e16c2..7be719ec 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using SharpCompress.Common.Rar.Headers; using SharpCompress.IO; using SharpCompress.Readers; @@ -15,14 +14,17 @@ namespace SharpCompress.Common.Rar; public abstract class RarVolume : Volume { private readonly RarHeaderFactory _headerFactory; - private int _maxCompressionAlgorithm; + internal int _maxCompressionAlgorithm; - internal RarVolume(StreamingMode mode, Stream stream, ReaderOptions options, int index) + internal RarVolume(StreamingMode mode, Stream stream, ReaderOptions options, int index = 0) : base(stream, options, index) => _headerFactory = new RarHeaderFactory(mode, options); - private ArchiveHeader? ArchiveHeader { get; set; } +#nullable disable + internal ArchiveHeader ArchiveHeader { get; private set; } - private StreamingMode Mode => _headerFactory.StreamingMode; +#nullable enable + + internal StreamingMode Mode => _headerFactory.StreamingMode; internal abstract IEnumerable ReadFileParts(); @@ -36,16 +38,19 @@ public abstract class RarVolume : Volume switch (header.HeaderType) { case HeaderType.Mark: + { lastMarkHeader = (MarkHeader)header; } break; case HeaderType.Archive: + { ArchiveHeader = (ArchiveHeader)header; } break; case HeaderType.File: + { var fh = (FileHeader)header; if (_maxCompressionAlgorithm < fh.CompressionAlgorithm) @@ -57,13 +62,19 @@ public abstract class RarVolume : Volume } break; case HeaderType.Service: + { var fh = (FileHeader)header; if (fh.FileName == "CMT") { + var part = CreateFilePart(lastMarkHeader!, fh); var buffer = new byte[fh.CompressedSize]; - fh.PackedStream.Read(buffer, 0, buffer.Length); - Comment = Encoding.UTF8.GetString(buffer, 0, buffer.Length - 1); + part.GetCompressedStream().Read(buffer, 0, buffer.Length); + Comment = System.Text.Encoding.UTF8.GetString( + buffer, + 0, + buffer.Length - 1 + ); } } break; @@ -97,7 +108,7 @@ public abstract class RarVolume : Volume get { EnsureArchiveHeaderLoaded(); - return ArchiveHeader?.IsFirstVolume ?? false; + return ArchiveHeader.IsFirstVolume; } } @@ -109,7 +120,7 @@ public abstract class RarVolume : Volume get { EnsureArchiveHeaderLoaded(); - return ArchiveHeader?.IsVolume ?? false; + return ArchiveHeader.IsVolume; } } @@ -122,7 +133,7 @@ public abstract class RarVolume : Volume get { EnsureArchiveHeaderLoaded(); - return ArchiveHeader?.IsSolid ?? false; + return ArchiveHeader.IsSolid; } } diff --git a/src/SharpCompress/Common/ReaderCancelledException.cs b/src/SharpCompress/Common/ReaderCancelledException.cs deleted file mode 100644 index 918e5abb..00000000 --- a/src/SharpCompress/Common/ReaderCancelledException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace SharpCompress.Common; - -public class ReaderCancelledException : Exception -{ - public ReaderCancelledException(string message) - : base(message) { } - - public ReaderCancelledException(string message, Exception inner) - : base(message, inner) { } -} diff --git a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs index 4bac08ad..5e42494a 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs @@ -15,15 +15,15 @@ internal class ArchiveDatabase internal long _startPositionAfterHeader; internal long _dataStartPosition; - internal List _packSizes = new(); - internal List _packCrCs = new(); - internal List _folders = new(); + internal List _packSizes = new List(); + internal List _packCrCs = new List(); + internal List _folders = new List(); internal List _numUnpackStreamsVector; - internal List _files = new(); + internal List _files = new List(); - internal List _packStreamStartPositions = new(); - internal List _folderStartFileIndex = new(); - internal List _fileIndexToFolderIndexMap = new(); + internal List _packStreamStartPositions = new List(); + internal List _folderStartFileIndex = new List(); + internal List _fileIndexToFolderIndexMap = new List(); internal IPasswordProvider PasswordProvider { get; } @@ -35,7 +35,7 @@ internal class ArchiveDatabase _packSizes.Clear(); _packCrCs.Clear(); _folders.Clear(); - _numUnpackStreamsVector = null; + _numUnpackStreamsVector = null!; _files.Clear(); _packStreamStartPositions.Clear(); diff --git a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs index 3e506e0e..42b5b6b2 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs @@ -14,13 +14,13 @@ namespace SharpCompress.Common.SevenZip; internal class ArchiveReader { internal Stream _stream; - internal Stack _readerStack = new(); + internal Stack _readerStack = new Stack(); internal DataReader _currentReader; internal long _streamOrigin; internal long _streamEnding; internal byte[] _header; - private readonly Dictionary _cachedStreams = new(); + private readonly Dictionary _cachedStreams = new Dictionary(); internal void AddByteStream(byte[] buffer, int offset, int length) { @@ -1359,7 +1359,7 @@ internal class ArchiveReader { internal int _fileIndex; internal int _folderIndex; - internal List _extractStatuses = new(); + internal List _extractStatuses = new List(); internal CExtractFolderInfo(int fileIndex, int folderIndex) { @@ -1393,7 +1393,7 @@ internal class ArchiveReader public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/Common/SevenZip/CFolder.cs b/src/SharpCompress/Common/SevenZip/CFolder.cs index 8b0123da..9d3516b1 100644 --- a/src/SharpCompress/Common/SevenZip/CFolder.cs +++ b/src/SharpCompress/Common/SevenZip/CFolder.cs @@ -6,11 +6,11 @@ namespace SharpCompress.Common.SevenZip; internal class CFolder { - internal List _coders = new(); - internal List _bindPairs = new(); - internal List _packStreams = new(); + internal List _coders = new List(); + internal List _bindPairs = new List(); + internal List _packStreams = new List(); internal int _firstPackStreamId; - internal List _unpackSizes = new(); + internal List _unpackSizes = new List(); internal uint? _unpackCrc; internal bool UnpackCrcDefined => _unpackCrc != null; diff --git a/src/SharpCompress/Common/SevenZip/CMethodId.cs b/src/SharpCompress/Common/SevenZip/CMethodId.cs index 8494aad5..6dce5773 100644 --- a/src/SharpCompress/Common/SevenZip/CMethodId.cs +++ b/src/SharpCompress/Common/SevenZip/CMethodId.cs @@ -7,10 +7,10 @@ internal readonly struct CMethodId public const ulong K_LZMA2_ID = 0x21; public const ulong K_AES_ID = 0x06F10701; - public static readonly CMethodId K_COPY = new(K_COPY_ID); - public static readonly CMethodId K_LZMA = new(K_LZMA_ID); - public static readonly CMethodId K_LZMA2 = new(K_LZMA2_ID); - public static readonly CMethodId K_AES = new(K_AES_ID); + public static readonly CMethodId K_COPY = new CMethodId(K_COPY_ID); + public static readonly CMethodId K_LZMA = new CMethodId(K_LZMA_ID); + public static readonly CMethodId K_LZMA2 = new CMethodId(K_LZMA2_ID); + public static readonly CMethodId K_AES = new CMethodId(K_AES_ID); public readonly ulong _id; diff --git a/src/SharpCompress/Common/SevenZip/SevenZipEntry.cs b/src/SharpCompress/Common/SevenZip/SevenZipEntry.cs index fbcb3d00..66170ba8 100644 --- a/src/SharpCompress/Common/SevenZip/SevenZipEntry.cs +++ b/src/SharpCompress/Common/SevenZip/SevenZipEntry.cs @@ -13,7 +13,7 @@ public class SevenZipEntry : Entry public override long Crc => FilePart.Header.Crc ?? 0; - public override string? Key => FilePart.Header.Name; + public override string Key => FilePart.Header.Name; public override string? LinkTarget => null; diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index fe221b53..aad191c9 100644 --- a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs +++ b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs @@ -41,7 +41,7 @@ internal class SevenZipFilePart : FilePart { if (!Header.HasStream) { - throw new InvalidOperationException("File does not have a stream."); + return null!; } var folderStream = _database.GetFolderStream(_stream, Folder!, _database.PasswordProvider); @@ -73,24 +73,34 @@ internal class SevenZipFilePart : FilePart private const uint K_PPMD = 0x030401; private const uint K_B_ZIP2 = 0x040202; - private CompressionType GetCompression() + internal CompressionType GetCompression() { if (Header.IsDir) - { return CompressionType.None; - } - var coder = Folder.NotNull()._coders.First(); - return coder._methodId._id switch + var coder = Folder!._coders.First(); + switch (coder._methodId._id) { - K_LZMA or K_LZMA2 => CompressionType.LZMA, - K_PPMD => CompressionType.PPMd, - K_B_ZIP2 => CompressionType.BZip2, - _ => throw new NotImplementedException() - }; + case K_LZMA: + case K_LZMA2: + { + return CompressionType.LZMA; + } + case K_PPMD: + { + return CompressionType.PPMd; + } + case K_B_ZIP2: + { + return CompressionType.BZip2; + } + default: + throw new NotImplementedException(); + } } internal bool IsEncrypted => - !Header.IsDir - && Folder?._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1; + Header.IsDir + ? false + : Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1; } diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index e9aa343c..ef86ab00 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Buffers.Binary; using System.IO; @@ -7,12 +9,12 @@ namespace SharpCompress.Common.Tar.Headers; internal sealed class TarHeader { - internal static readonly DateTime EPOCH = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + internal static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public TarHeader(ArchiveEncoding archiveEncoding) => ArchiveEncoding = archiveEncoding; - internal string? Name { get; set; } - internal string? LinkName { get; set; } + internal string Name { get; set; } + internal string LinkName { get; set; } internal long Mode { get; set; } internal long UserId { get; set; } @@ -20,7 +22,7 @@ internal sealed class TarHeader internal long Size { get; set; } internal DateTime LastModifiedTime { get; set; } internal EntryType EntryType { get; set; } - internal Stream? PackedStream { get; set; } + internal Stream PackedStream { get; set; } internal ArchiveEncoding ArchiveEncoding { get; } internal const int BLOCK_SIZE = 512; @@ -34,9 +36,7 @@ internal sealed class TarHeader WriteOctalBytes(0, buffer, 116, 8); // group ID //ArchiveEncoding.UTF8.GetBytes("magic").CopyTo(buffer, 257); - var nameByteCount = ArchiveEncoding - .GetEncoding() - .GetByteCount(Name.NotNull("Name is null")); + var nameByteCount = ArchiveEncoding.GetEncoding().GetByteCount(Name); if (nameByteCount > 100) { // Set mock filename and filetype to indicate the next block is the actual name of the file @@ -46,7 +46,7 @@ internal sealed class TarHeader } else { - WriteStringBytes(ArchiveEncoding.Encode(Name.NotNull("Name is null")), buffer, 100); + WriteStringBytes(ArchiveEncoding.Encode(Name), buffer, 100); WriteOctalBytes(Size, buffer, 124, 12); var time = (long)(LastModifiedTime.ToUniversalTime() - EPOCH).TotalSeconds; WriteOctalBytes(time, buffer, 136, 12); @@ -77,7 +77,7 @@ internal sealed class TarHeader // // and then infinite recursion is occured in WriteLongFilenameHeader because truncated.Length is 102. Name = ArchiveEncoding.Decode( - ArchiveEncoding.Encode(Name.NotNull("Name is null")), + ArchiveEncoding.Encode(Name), 0, 100 - ArchiveEncoding.GetEncoding().GetMaxByteCount(1) ); @@ -87,7 +87,7 @@ internal sealed class TarHeader private void WriteLongFilenameHeader(Stream output) { - var nameBytes = ArchiveEncoding.Encode(Name.NotNull("Name is null")); + var nameBytes = ArchiveEncoding.Encode(Name); output.Write(nameBytes, 0, nameBytes.Length); // pad to multiple of BlockSize bytes, and make sure a terminating null is added @@ -101,79 +101,57 @@ internal sealed class TarHeader internal bool Read(BinaryReader reader) { - string? longName = null; - string? longLinkName = null; - var hasLongValue = true; - byte[] buffer; - EntryType entryType; - - do + var buffer = ReadBlock(reader); + if (buffer.Length == 0) { - buffer = ReadBlock(reader); - - if (buffer.Length == 0) - { - return false; - } - - entryType = ReadEntryType(buffer); - - // LongName and LongLink headers can follow each other and need - // to apply to the header that follows them. - if (entryType == EntryType.LongName) - { - longName = ReadLongName(reader, buffer); - continue; - } - else if (entryType == EntryType.LongLink) - { - longLinkName = ReadLongName(reader, buffer); - continue; - } - - hasLongValue = false; - } while (hasLongValue); - - Name = longName ?? ArchiveEncoding.Decode(buffer, 0, 100).TrimNulls(); - EntryType = entryType; - Size = ReadSize(buffer); - - // for symlinks, additionally read the linkname - if (entryType == EntryType.SymLink || entryType == EntryType.HardLink) - { - LinkName = longLinkName ?? ArchiveEncoding.Decode(buffer, 157, 100).TrimNulls(); + return false; } - Mode = ReadAsciiInt64Base8(buffer, 100, 7); + // for symlinks, additionally read the linkname + if (ReadEntryType(buffer) == EntryType.SymLink) + { + LinkName = ArchiveEncoding.Decode(buffer, 157, 100).TrimNulls(); + } - if (entryType == EntryType.Directory) + if (ReadEntryType(buffer) == EntryType.LongName) + { + Name = ReadLongName(reader, buffer); + buffer = ReadBlock(reader); + } + else + { + Name = ArchiveEncoding.Decode(buffer, 0, 100).TrimNulls(); + } + + EntryType = ReadEntryType(buffer); + Size = ReadSize(buffer); + + Mode = ReadAsciiInt64Base8(buffer, 100, 7); + if (EntryType == EntryType.Directory) { Mode |= 0b1_000_000_000; } - UserId = ReadAsciiInt64Base8oldGnu(buffer, 108, 7); - GroupId = ReadAsciiInt64Base8oldGnu(buffer, 116, 7); - + UserId = ReadAsciiInt64Base8(buffer, 108, 7); + GroupId = ReadAsciiInt64Base8(buffer, 116, 7); var unixTimeStamp = ReadAsciiInt64Base8(buffer, 136, 11); - LastModifiedTime = EPOCH.AddSeconds(unixTimeStamp).ToLocalTime(); + Magic = ArchiveEncoding.Decode(buffer, 257, 6).TrimNulls(); if (!string.IsNullOrEmpty(Magic) && "ustar".Equals(Magic)) { - var namePrefix = ArchiveEncoding.Decode(buffer, 345, 157).TrimNulls(); - + var namePrefix = ArchiveEncoding.Decode(buffer, 345, 157); + namePrefix = namePrefix.TrimNulls(); if (!string.IsNullOrEmpty(namePrefix)) { Name = namePrefix + "/" + Name; } } - - if (entryType != EntryType.LongName && Name.Length == 0) + if (EntryType != EntryType.LongName && Name.Length == 0) { return false; } - return true; } @@ -271,24 +249,6 @@ internal sealed class TarHeader return Convert.ToInt64(s, 8); } - private static long ReadAsciiInt64Base8oldGnu(byte[] buffer, int offset, int count) - { - if (buffer[offset] == 0x80 && buffer[offset + 1] == 0x00) - { - return buffer[offset + 4] << 24 - | buffer[offset + 5] << 16 - | buffer[offset + 6] << 8 - | buffer[offset + 7]; - } - var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls(); - - if (string.IsNullOrEmpty(s)) - { - return 0; - } - return Convert.ToInt64(s, 8); - } - private static long ReadAsciiInt64(byte[] buffer, int offset, int count) { var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls(); @@ -345,5 +305,5 @@ internal sealed class TarHeader public long? DataStartPosition { get; set; } - public string? Magic { get; set; } + public string Magic { get; set; } } diff --git a/src/SharpCompress/Common/Tar/TarEntry.cs b/src/SharpCompress/Common/Tar/TarEntry.cs index 2597b837..59743070 100644 --- a/src/SharpCompress/Common/Tar/TarEntry.cs +++ b/src/SharpCompress/Common/Tar/TarEntry.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; @@ -8,9 +10,9 @@ namespace SharpCompress.Common.Tar; public class TarEntry : Entry { - private readonly TarFilePart? _filePart; + private readonly TarFilePart _filePart; - internal TarEntry(TarFilePart? filePart, CompressionType type) + internal TarEntry(TarFilePart filePart, CompressionType type) { _filePart = filePart; CompressionType = type; @@ -20,15 +22,15 @@ public class TarEntry : Entry public override long Crc => 0; - public override string? Key => _filePart?.Header.Name; + public override string Key => _filePart.Header.Name; - public override string? LinkTarget => _filePart?.Header.LinkName; + public override string LinkTarget => _filePart.Header.LinkName; - public override long CompressedSize => _filePart?.Header.Size ?? 0; + public override long CompressedSize => _filePart.Header.Size; - public override long Size => _filePart?.Header.Size ?? 0; + public override long Size => _filePart.Header.Size; - public override DateTime? LastModifiedTime => _filePart?.Header.LastModifiedTime; + public override DateTime? LastModifiedTime => _filePart.Header.LastModifiedTime; public override DateTime? CreatedTime => null; @@ -38,17 +40,17 @@ public class TarEntry : Entry public override bool IsEncrypted => false; - public override bool IsDirectory => _filePart?.Header.EntryType == EntryType.Directory; + public override bool IsDirectory => _filePart.Header.EntryType == EntryType.Directory; public override bool IsSplitAfter => false; - public long Mode => _filePart?.Header.Mode ?? 0; + public long Mode => _filePart.Header.Mode; - public long UserID => _filePart?.Header.UserId ?? 0; + public long UserID => _filePart.Header.UserId; - public long GroupId => _filePart?.Header.GroupId ?? 0; + public long GroupId => _filePart.Header.GroupId; - internal override IEnumerable Parts => _filePart.Empty(); + internal override IEnumerable Parts => _filePart.AsEnumerable(); internal static IEnumerable GetEntries( StreamingMode mode, @@ -57,17 +59,17 @@ public class TarEntry : Entry ArchiveEncoding archiveEncoding ) { - foreach (var header in TarHeaderFactory.ReadHeader(mode, stream, archiveEncoding)) + foreach (var h in TarHeaderFactory.ReadHeader(mode, stream, archiveEncoding)) { - if (header != null) + if (h != null) { if (mode == StreamingMode.Seekable) { - yield return new TarEntry(new TarFilePart(header, stream), compressionType); + yield return new TarEntry(new TarFilePart(h, stream), compressionType); } else { - yield return new TarEntry(new TarFilePart(header, null), compressionType); + yield return new TarEntry(new TarFilePart(h, null), compressionType); } } else diff --git a/src/SharpCompress/Common/Tar/TarFilePart.cs b/src/SharpCompress/Common/Tar/TarFilePart.cs index 06516114..bfd2fe29 100644 --- a/src/SharpCompress/Common/Tar/TarFilePart.cs +++ b/src/SharpCompress/Common/Tar/TarFilePart.cs @@ -5,9 +5,9 @@ namespace SharpCompress.Common.Tar; internal sealed class TarFilePart : FilePart { - private readonly Stream? _seekableStream; + private readonly Stream _seekableStream; - internal TarFilePart(TarHeader header, Stream? seekableStream) + internal TarFilePart(TarHeader header, Stream seekableStream) : base(header.ArchiveEncoding) { _seekableStream = seekableStream; @@ -16,16 +16,16 @@ internal sealed class TarFilePart : FilePart internal TarHeader Header { get; } - internal override string? FilePartName => Header?.Name; + internal override string FilePartName => Header.Name; internal override Stream GetCompressedStream() { if (_seekableStream != null) { - _seekableStream.Position = Header.DataStartPosition ?? 0; + _seekableStream.Position = Header.DataStartPosition!.Value; return new TarReadOnlySubStream(_seekableStream, Header.Size); } - return Header.PackedStream.NotNull(); + return Header.PackedStream; } internal override Stream? GetRawStream() => null; diff --git a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs index 13813353..85eec5b4 100644 --- a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs +++ b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs @@ -28,6 +28,7 @@ internal static class TarHeaderFactory switch (mode) { case StreamingMode.Seekable: + { header.DataStartPosition = reader.BaseStream.Position; @@ -36,6 +37,7 @@ internal static class TarHeaderFactory } break; case StreamingMode.Streaming: + { header.PackedStream = new TarReadOnlySubStream(stream, header.Size); } diff --git a/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs b/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs index 09a2fdb8..7ccfd238 100644 --- a/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs +++ b/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs @@ -1,6 +1,6 @@ +using SharpCompress.IO; using System; using System.IO; -using SharpCompress.IO; namespace SharpCompress.Common.Tar; @@ -47,7 +47,7 @@ internal class TarReadOnlySubStream : NonDisposingStream public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => throw new NotSupportedException(); @@ -63,7 +63,7 @@ internal class TarReadOnlySubStream : NonDisposingStream { count = (int)BytesLeftToRead; } - var read = Stream.Read(buffer, offset, count); + int read = Stream.Read(buffer, offset, count); if (read > 0) { BytesLeftToRead -= read; @@ -78,7 +78,7 @@ internal class TarReadOnlySubStream : NonDisposingStream { return -1; } - var value = Stream.ReadByte(); + int value = Stream.ReadByte(); if (value != -1) { --BytesLeftToRead; diff --git a/src/SharpCompress/Common/Volume.cs b/src/SharpCompress/Common/Volume.cs index 7be161ec..1f259257 100644 --- a/src/SharpCompress/Common/Volume.cs +++ b/src/SharpCompress/Common/Volume.cs @@ -9,11 +9,11 @@ public abstract class Volume : IVolume { private readonly Stream _actualStream; - internal Volume(Stream stream, ReaderOptions? readerOptions, int index = 0) + internal Volume(Stream stream, ReaderOptions readerOptions, int index = 0) { Index = index; - ReaderOptions = readerOptions ?? new ReaderOptions(); - if (ReaderOptions.LeaveStreamOpen) + ReaderOptions = readerOptions; + if (readerOptions.LeaveStreamOpen) { stream = NonDisposingStream.Create(stream); } @@ -32,7 +32,7 @@ public abstract class Volume : IVolume public virtual int Index { get; internal set; } - public string? FileName => (_actualStream as FileStream)?.Name; + public string FileName => (_actualStream as FileStream)?.Name!; /// /// RarArchive is part of a multi-part archive. diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index 2b26d298..fc2cb262 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs @@ -14,8 +14,8 @@ internal class DirectoryEntryHeader : ZipFileEntry VersionNeededToExtract = reader.ReadUInt16(); Flags = (HeaderFlags)reader.ReadUInt16(); CompressionMethod = (ZipCompressionMethod)reader.ReadUInt16(); - OriginalLastModifiedTime = LastModifiedTime = reader.ReadUInt16(); - OriginalLastModifiedDate = LastModifiedDate = reader.ReadUInt16(); + LastModifiedTime = reader.ReadUInt16(); + LastModifiedDate = reader.ReadUInt16(); Crc = reader.ReadUInt32(); CompressedSize = reader.ReadUInt32(); UncompressedSize = reader.ReadUInt32(); @@ -52,8 +52,8 @@ internal class DirectoryEntryHeader : ZipFileEntry LoadExtra(extra); - var unicodePathExtra = Extra.FirstOrDefault(u => - u.Type == ExtraDataType.UnicodePathExtraField + var unicodePathExtra = Extra.FirstOrDefault( + u => u.Type == ExtraDataType.UnicodePathExtraField ); if (unicodePathExtra != null && ArchiveEncoding.Forced == null) { @@ -85,36 +85,6 @@ internal class DirectoryEntryHeader : ZipFileEntry RelativeOffsetOfEntryHeader = zip64ExtraData.RelativeOffsetOfEntryHeader; } } - - var unixTimeExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnixTimeExtraField); - - if (unixTimeExtra is not null) - { - // Tuple order is last modified time, last access time, and creation time. - var unixTimeTuple = ((UnixTimeExtraField)unixTimeExtra).UnicodeTimes; - - if (unixTimeTuple.Item1.HasValue) - { - var dosTime = Utility.DateTimeToDosTime(unixTimeTuple.Item1.Value); - - LastModifiedDate = (ushort)(dosTime >> 16); - LastModifiedTime = (ushort)(dosTime & 0x0FFFF); - } - else if (unixTimeTuple.Item2.HasValue) - { - var dosTime = Utility.DateTimeToDosTime(unixTimeTuple.Item2.Value); - - LastModifiedDate = (ushort)(dosTime >> 16); - LastModifiedTime = (ushort)(dosTime & 0x0FFFF); - } - else if (unixTimeTuple.Item3.HasValue) - { - var dosTime = Utility.DateTimeToDosTime(unixTimeTuple.Item3.Value); - - LastModifiedDate = (ushort)(dosTime >> 16); - LastModifiedTime = (ushort)(dosTime & 0x0FFFF); - } - } } internal ushort Version { get; private set; } diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs index 1e3dc62d..93cc55ac 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs @@ -13,8 +13,8 @@ internal class LocalEntryHeader : ZipFileEntry Version = reader.ReadUInt16(); Flags = (HeaderFlags)reader.ReadUInt16(); CompressionMethod = (ZipCompressionMethod)reader.ReadUInt16(); - OriginalLastModifiedTime = LastModifiedTime = reader.ReadUInt16(); - OriginalLastModifiedDate = LastModifiedDate = reader.ReadUInt16(); + LastModifiedTime = reader.ReadUInt16(); + LastModifiedDate = reader.ReadUInt16(); Crc = reader.ReadUInt32(); CompressedSize = reader.ReadUInt32(); UncompressedSize = reader.ReadUInt32(); @@ -42,8 +42,8 @@ internal class LocalEntryHeader : ZipFileEntry LoadExtra(extra); - var unicodePathExtra = Extra.FirstOrDefault(u => - u.Type == ExtraDataType.UnicodePathExtraField + var unicodePathExtra = Extra.FirstOrDefault( + u => u.Type == ExtraDataType.UnicodePathExtraField ); if (unicodePathExtra != null && ArchiveEncoding.Forced == null) { @@ -64,36 +64,6 @@ internal class LocalEntryHeader : ZipFileEntry UncompressedSize = zip64ExtraData.UncompressedSize; } } - - var unixTimeExtra = Extra.FirstOrDefault(u => u.Type == ExtraDataType.UnixTimeExtraField); - - if (unixTimeExtra is not null) - { - // Tuple order is last modified time, last access time, and creation time. - var unixTimeTuple = ((UnixTimeExtraField)unixTimeExtra).UnicodeTimes; - - if (unixTimeTuple.Item1.HasValue) - { - var dosTime = Utility.DateTimeToDosTime(unixTimeTuple.Item1.Value); - - LastModifiedDate = (ushort)(dosTime >> 16); - LastModifiedTime = (ushort)(dosTime & 0x0FFFF); - } - else if (unixTimeTuple.Item2.HasValue) - { - var dosTime = Utility.DateTimeToDosTime(unixTimeTuple.Item2.Value); - - LastModifiedDate = (ushort)(dosTime >> 16); - LastModifiedTime = (ushort)(dosTime & 0x0FFFF); - } - else if (unixTimeTuple.Item3.HasValue) - { - var dosTime = Utility.DateTimeToDosTime(unixTimeTuple.Item3.Value); - - LastModifiedDate = (ushort)(dosTime >> 16); - LastModifiedTime = (ushort)(dosTime & 0x0FFFF); - } - } } internal ushort Version { get; private set; } diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeaderExtraFactory.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeaderExtraFactory.cs index 88e4a187..80ec9b8f 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeaderExtraFactory.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeaderExtraFactory.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Buffers.Binary; using System.Text; @@ -13,8 +13,7 @@ internal enum ExtraDataType : ushort // Third Party Mappings // -Info-ZIP Unicode Path Extra Field UnicodePathExtraField = 0x7075, - Zip64ExtendedInformationExtraField = 0x0001, - UnixTimeExtraField = 0x5455 + Zip64ExtendedInformationExtraField = 0x0001 } internal class ExtraData @@ -146,84 +145,6 @@ internal sealed class Zip64ExtendedInformationExtraField : ExtraData public uint VolumeNumber { get; private set; } } -internal sealed class UnixTimeExtraField : ExtraData -{ - public UnixTimeExtraField(ExtraDataType type, ushort length, byte[] dataBytes) - : base(type, length, dataBytes) { } - - /// - /// The unix modified time, last access time, and creation time, if set. - /// - /// Must return Tuple explicitly due to net462 support. - internal Tuple UnicodeTimes - { - get - { - // There has to be at least 5 byte for there to be a timestamp. - // 1 byte for flags and 4 bytes for a timestamp. - if (DataBytes is null || DataBytes.Length < 5) - { - return Tuple.Create(null, null, null); - } - - var flags = DataBytes[0]; - var isModifiedTimeSpecified = (flags & 0x01) == 1; - var isLastAccessTimeSpecified = (flags & 0x02) == 1; - var isCreationTimeSpecified = (flags & 0x04) == 1; - var currentIndex = 1; - DateTime? modifiedTime = null; - DateTime? lastAccessTime = null; - DateTime? creationTime = null; - - if (isModifiedTimeSpecified) - { - var modifiedEpochTime = BinaryPrimitives.ReadInt32LittleEndian( - DataBytes.AsSpan(currentIndex, 4) - ); - - currentIndex += 4; - modifiedTime = DateTimeOffset.FromUnixTimeSeconds(modifiedEpochTime).UtcDateTime; - } - - if (isLastAccessTimeSpecified) - { - if (currentIndex + 4 > DataBytes.Length) - { - throw new ArchiveException("Invalid UnicodeExtraTime field"); - } - - var lastAccessEpochTime = BinaryPrimitives.ReadInt32LittleEndian( - DataBytes.AsSpan(currentIndex, 4) - ); - - currentIndex += 4; - lastAccessTime = DateTimeOffset - .FromUnixTimeSeconds(lastAccessEpochTime) - .UtcDateTime; - } - - if (isCreationTimeSpecified) - { - if (currentIndex + 4 > DataBytes.Length) - { - throw new ArchiveException("Invalid UnicodeExtraTime field"); - } - - var creationTimeEpochTime = BinaryPrimitives.ReadInt32LittleEndian( - DataBytes.AsSpan(currentIndex, 4) - ); - - currentIndex += 4; - creationTime = DateTimeOffset - .FromUnixTimeSeconds(creationTimeEpochTime) - .UtcDateTime; - } - - return Tuple.Create(modifiedTime, lastAccessTime, creationTime); - } - } -} - internal static class LocalEntryHeaderExtraFactory { internal static ExtraData Create(ExtraDataType type, ushort length, byte[] extraData) => @@ -233,7 +154,6 @@ internal static class LocalEntryHeaderExtraFactory => new ExtraUnicodePathExtraField(type, length, extraData), ExtraDataType.Zip64ExtendedInformationExtraField => new Zip64ExtendedInformationExtraField(type, length, extraData), - ExtraDataType.UnixTimeExtraField => new UnixTimeExtraField(type, length, extraData), _ => new ExtraData(type, length, extraData) }; } diff --git a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs index 0570bf6d..98d230f5 100644 --- a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs +++ b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Buffers.Binary; using System.Collections.Generic; @@ -18,21 +20,21 @@ internal abstract class ZipFileEntry : ZipHeader { get { - if (Name?.EndsWith('/') ?? false) + if (Name.EndsWith('/')) { return true; } //.NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers - return CompressedSize == 0 && UncompressedSize == 0 && (Name?.EndsWith('\\') ?? false); + return CompressedSize == 0 && UncompressedSize == 0 && Name.EndsWith('\\'); } } - internal Stream? PackedStream { get; set; } + internal Stream PackedStream { get; set; } internal ArchiveEncoding ArchiveEncoding { get; } - internal string? Name { get; set; } + internal string Name { get; set; } internal HeaderFlags Flags { get; set; } @@ -46,7 +48,7 @@ internal abstract class ZipFileEntry : ZipHeader internal List Extra { get; set; } - public string? Password { get; set; } + public string Password { get; set; } internal PkwareTraditionalEncryptionData ComposeEncryptionData(Stream archiveStream) { @@ -63,28 +65,10 @@ internal abstract class ZipFileEntry : ZipHeader return encryptionData; } - internal WinzipAesEncryptionData? WinzipAesEncryptionData { get; set; } + internal WinzipAesEncryptionData WinzipAesEncryptionData { get; set; } - /// - /// The last modified date as read from the Local or Central Directory header. - /// - internal ushort OriginalLastModifiedDate { get; set; } - - /// - /// The last modified date from the UnixTimeExtraField, if present, or the - /// Local or Cental Directory header, if not. - /// internal ushort LastModifiedDate { get; set; } - /// - /// The last modified time as read from the Local or Central Directory header. - /// - internal ushort OriginalLastModifiedTime { get; set; } - - /// - /// The last modified time from the UnixTimeExtraField, if present, or the - /// Local or Cental Directory header, if not. - /// internal ushort LastModifiedTime { get; set; } internal uint Crc { get; set; } @@ -117,7 +101,7 @@ internal abstract class ZipFileEntry : ZipHeader } } - internal ZipFilePart? Part { get; set; } + internal ZipFilePart Part { get; set; } internal bool IsZip64 => CompressedSize >= uint.MaxValue; } diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs index 6ac48c6f..273a7a3c 100644 --- a/src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs +++ b/src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace SharpCompress.Common.Zip; @@ -87,7 +87,10 @@ internal class PkwareTraditionalCryptoStream : Stream _stream.Write(encrypted, 0, encrypted.Length); } - public override void Flush() { } + public override void Flush() + { + //throw new NotSupportedException(); + } public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs index 7b517857..353000d8 100644 --- a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs @@ -6,7 +6,7 @@ namespace SharpCompress.Common.Zip; internal class PkwareTraditionalEncryptionData { - private static readonly CRC32 CRC32 = new(); + private static readonly CRC32 CRC32 = new CRC32(); private readonly uint[] _keys = { 0x12345678, 0x23456789, 0x34567890 }; private readonly ArchiveEncoding _archiveEncoding; @@ -39,7 +39,7 @@ internal class PkwareTraditionalEncryptionData { throw new CryptographicException("The password did not match."); } - if (plainTextHeader[11] != (byte)((header.OriginalLastModifiedTime >> 8) & 0xff)) + if (plainTextHeader[11] != (byte)((header.LastModifiedTime >> 8) & 0xff)) { throw new CryptographicException("The password did not match."); } @@ -103,7 +103,7 @@ internal class PkwareTraditionalEncryptionData internal byte[] StringToByteArray(string value) { - var a = _archiveEncoding.GetPasswordEncoding().GetBytes(value); + var a = _archiveEncoding.Password.GetBytes(value); return a; } diff --git a/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs b/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs index e37008e5..63fdc933 100644 --- a/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs @@ -42,16 +42,16 @@ internal class SeekableZipFilePart : ZipFilePart protected override Stream CreateBaseStream() { - BaseStream.Position = Header.DataStartPosition.NotNull(); + BaseStream.Position = Header.DataStartPosition!.Value; if ( (Header.CompressedSize == 0) && FlagUtility.HasFlag(Header.Flags, HeaderFlags.UsePostDataDescriptor) - && _directoryEntryHeader.HasData - && (_directoryEntryHeader.CompressedSize != 0) + && (_directoryEntryHeader?.HasData == true) + && (_directoryEntryHeader?.CompressedSize != 0) ) { - return new ReadOnlySubStream(BaseStream, _directoryEntryHeader.CompressedSize); + return new ReadOnlySubStream(BaseStream, _directoryEntryHeader!.CompressedSize); } return BaseStream; diff --git a/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs b/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs index 97e44b6b..1cd1f61f 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs @@ -13,7 +13,7 @@ internal sealed class StreamingZipFilePart : ZipFilePart internal StreamingZipFilePart(ZipFileEntry header, Stream stream) : base(header, stream) { } - protected override Stream CreateBaseStream() => Header.PackedStream.NotNull(); + protected override Stream CreateBaseStream() => Header.PackedStream; internal override Stream GetCompressedStream() { diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 508dfd1a..e76a2856 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -15,7 +15,10 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory ArchiveEncoding archiveEncoding, IEnumerable? entries ) - : base(StreamingMode.Streaming, password, archiveEncoding) => _entries = entries; + : base(StreamingMode.Streaming, password, archiveEncoding) + { + _entries = entries; + } internal IEnumerable ReadStreamHeader(Stream stream) { @@ -36,19 +39,16 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory uint headerBytes = 0; if ( _lastEntryHeader != null - && FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) + && ( + FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) + || _lastEntryHeader.IsZip64 + ) ) { - if (_lastEntryHeader.Part is null) - { - continue; - } reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation( ref rewindableStream ); - var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null; - var crc = reader.ReadUInt32(); if (crc == POST_DATA_DESCRIPTOR) { @@ -81,60 +81,6 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory _lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize; } } - else if (_lastEntryHeader != null && _lastEntryHeader.IsZip64) - { - if (_lastEntryHeader.Part is null) - continue; - - reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation( - ref rewindableStream - ); - - var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null; - - headerBytes = reader.ReadUInt32(); - - var version = reader.ReadUInt16(); - var flags = (HeaderFlags)reader.ReadUInt16(); - var compressionMethod = (ZipCompressionMethod)reader.ReadUInt16(); - var lastModifiedDate = reader.ReadUInt16(); - var lastModifiedTime = reader.ReadUInt16(); - - var crc = reader.ReadUInt32(); - - if (crc == POST_DATA_DESCRIPTOR) - { - crc = reader.ReadUInt32(); - } - _lastEntryHeader.Crc = crc; - - // The DataDescriptor can be either 64bit or 32bit - var compressed_size = reader.ReadUInt32(); - var uncompressed_size = reader.ReadUInt32(); - - // Check if we have header or 64bit DataDescriptor - var test_header = !(headerBytes == 0x04034b50 || headerBytes == 0x02014b50); - - var test_64bit = ((long)uncompressed_size << 32) | compressed_size; - if (test_64bit == _lastEntryHeader.CompressedSize && test_header) - { - _lastEntryHeader.UncompressedSize = - ((long)reader.ReadUInt32() << 32) | headerBytes; - headerBytes = reader.ReadUInt32(); - } - else - { - _lastEntryHeader.UncompressedSize = uncompressed_size; - } - - if (pos.HasValue) - { - _lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize; - - // 4 = First 4 bytes of the entry header (i.e. 50 4B 03 04) - rewindableStream.Position = pos.Value + 4; - } - } else { headerBytes = reader.ReadUInt32(); @@ -151,12 +97,13 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory if (header.ZipHeaderType == ZipHeaderType.LocalEntry) { var local_header = ((LocalEntryHeader)header); - var dir_header = _entries?.FirstOrDefault(entry => - entry.Key == local_header.Name - && local_header.CompressedSize == 0 - && local_header.UncompressedSize == 0 - && local_header.Crc == 0 - && local_header.IsDirectory == false + var dir_header = _entries?.FirstOrDefault( + entry => + entry.Key == local_header.Name + && local_header.CompressedSize == 0 + && local_header.UncompressedSize == 0 + && local_header.Crc == 0 + && local_header.IsDirectory == false ); if (dir_header != null) diff --git a/src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs b/src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs index 5742458a..093ac034 100644 --- a/src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs +++ b/src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs @@ -73,7 +73,7 @@ internal class WinzipAesCryptoStream : Stream } } - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override int Read(byte[] buffer, int offset, int count) { diff --git a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs index 31322019..251b919e 100644 --- a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Buffers.Binary; using System.Security.Cryptography; @@ -8,7 +10,12 @@ internal class WinzipAesEncryptionData { private const int RFC2898_ITERATIONS = 1000; + private readonly byte[] _salt; private readonly WinzipAesKeySize _keySize; + private readonly byte[] _passwordVerifyValue; + private readonly string _password; + + private byte[] _generatedVerifyValue; internal WinzipAesEncryptionData( WinzipAesKeySize keySize, @@ -18,28 +25,10 @@ internal class WinzipAesEncryptionData ) { _keySize = keySize; - -#if NETFRAMEWORK || NETSTANDARD2_0 - var rfc2898 = new Rfc2898DeriveBytes(password, salt, RFC2898_ITERATIONS); -#else - var rfc2898 = new Rfc2898DeriveBytes( - password, - salt, - RFC2898_ITERATIONS, - HashAlgorithmName.SHA1 - ); -#endif - - KeyBytes = rfc2898.GetBytes(KeySizeInBytes); // 16 or 24 or 32 ??? - IvBytes = rfc2898.GetBytes(KeySizeInBytes); - var generatedVerifyValue = rfc2898.GetBytes(2); - - var verify = BinaryPrimitives.ReadInt16LittleEndian(passwordVerifyValue); - var generated = BinaryPrimitives.ReadInt16LittleEndian(generatedVerifyValue); - if (verify != generated) - { - throw new InvalidFormatException("bad password"); - } + _salt = salt; + _passwordVerifyValue = passwordVerifyValue; + _password = password; + Initialize(); } internal byte[] IvBytes { get; set; } @@ -56,4 +45,32 @@ internal class WinzipAesEncryptionData WinzipAesKeySize.KeySize256 => 32, _ => throw new InvalidOperationException(), }; + + private void Initialize() + { +#if NET7_0 + var rfc2898 = new Rfc2898DeriveBytes( + _password, + _salt, + RFC2898_ITERATIONS, + HashAlgorithmName.SHA1 + ); +#else + var rfc2898 = new Rfc2898DeriveBytes(_password, _salt, RFC2898_ITERATIONS); +#endif + + KeyBytes = rfc2898.GetBytes(KeySizeInBytes); // 16 or 24 or 32 ??? + IvBytes = rfc2898.GetBytes(KeySizeInBytes); + _generatedVerifyValue = rfc2898.GetBytes(2); + + var verify = BinaryPrimitives.ReadInt16LittleEndian(_passwordVerifyValue); + if (_password != null) + { + var generated = BinaryPrimitives.ReadInt16LittleEndian(_generatedVerifyValue); + if (verify != generated) + { + throw new InvalidFormatException("bad password"); + } + } + } } diff --git a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs index a98ed667..13c2dbe7 100644 --- a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs +++ b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs @@ -3,7 +3,6 @@ namespace SharpCompress.Common.Zip; internal enum ZipCompressionMethod { None = 0, - Shrink = 1, Deflate = 8, Deflate64 = 9, BZip2 = 12, diff --git a/src/SharpCompress/Common/Zip/ZipEntry.cs b/src/SharpCompress/Common/Zip/ZipEntry.cs index c2cecf39..2c544b94 100644 --- a/src/SharpCompress/Common/Zip/ZipEntry.cs +++ b/src/SharpCompress/Common/Zip/ZipEntry.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; using SharpCompress.Common.Zip.Headers; @@ -6,43 +8,67 @@ namespace SharpCompress.Common.Zip; public class ZipEntry : Entry { - private readonly ZipFilePart? _filePart; + private readonly ZipFilePart _filePart; - internal ZipEntry(ZipFilePart? filePart) + internal ZipEntry(ZipFilePart filePart) { - if (filePart == null) + if (filePart != null) { - return; + _filePart = filePart; + LastModifiedTime = Utility.DosDateToDateTime( + filePart.Header.LastModifiedDate, + filePart.Header.LastModifiedTime + ); } - _filePart = filePart; - LastModifiedTime = Utility.DosDateToDateTime( - filePart.Header.LastModifiedDate, - filePart.Header.LastModifiedTime - ); } - public override CompressionType CompressionType => - _filePart?.Header.CompressionMethod switch + public override CompressionType CompressionType + { + get { - ZipCompressionMethod.BZip2 => CompressionType.BZip2, - ZipCompressionMethod.Deflate => CompressionType.Deflate, - ZipCompressionMethod.Deflate64 => CompressionType.Deflate64, - ZipCompressionMethod.LZMA => CompressionType.LZMA, - ZipCompressionMethod.PPMd => CompressionType.PPMd, - ZipCompressionMethod.None => CompressionType.None, - ZipCompressionMethod.Shrink => CompressionType.Shrink, - _ => CompressionType.Unknown - }; + switch (_filePart.Header.CompressionMethod) + { + case ZipCompressionMethod.BZip2: + { + return CompressionType.BZip2; + } + case ZipCompressionMethod.Deflate: + { + return CompressionType.Deflate; + } + case ZipCompressionMethod.Deflate64: + { + return CompressionType.Deflate64; + } + case ZipCompressionMethod.LZMA: + { + return CompressionType.LZMA; + } + case ZipCompressionMethod.PPMd: + { + return CompressionType.PPMd; + } + case ZipCompressionMethod.None: + { + return CompressionType.None; + } + default: + { + return CompressionType.Unknown; + } + } + } + } - public override long Crc => _filePart?.Header.Crc ?? 0; + public override long Crc => _filePart.Header.Crc; - public override string? Key => _filePart?.Header.Name; + public override string Key => _filePart.Header.Name; - public override string? LinkTarget => null; + public override string LinkTarget => null; - public override long CompressedSize => _filePart?.Header.CompressedSize ?? 0; + public override long CompressedSize => _filePart.Header.CompressedSize; - public override long Size => _filePart?.Header.UncompressedSize ?? 0; + public override long Size => _filePart.Header.UncompressedSize; public override DateTime? LastModifiedTime { get; } @@ -53,11 +79,11 @@ public class ZipEntry : Entry public override DateTime? ArchivedTime => null; public override bool IsEncrypted => - FlagUtility.HasFlag(_filePart?.Header.Flags ?? HeaderFlags.None, HeaderFlags.Encrypted); + FlagUtility.HasFlag(_filePart.Header.Flags, HeaderFlags.Encrypted); - public override bool IsDirectory => _filePart?.Header.IsDirectory ?? false; + public override bool IsDirectory => _filePart.Header.IsDirectory; public override bool IsSplitAfter => false; - internal override IEnumerable Parts => _filePart.Empty(); + internal override IEnumerable Parts => _filePart.AsEnumerable(); } diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index e8516150..faefdf15 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -9,7 +9,6 @@ using SharpCompress.Compressors.Deflate; using SharpCompress.Compressors.Deflate64; using SharpCompress.Compressors.LZMA; using SharpCompress.Compressors.PPMd; -using SharpCompress.Compressors.Shrink; using SharpCompress.Compressors.Xz; using SharpCompress.IO; using ZstdSharp; @@ -29,7 +28,7 @@ internal abstract class ZipFilePart : FilePart internal Stream BaseStream { get; } internal ZipFileEntry Header { get; set; } - internal override string? FilePartName => Header.Name; + internal override string FilePartName => Header.Name; internal override Stream GetCompressedStream() { @@ -80,15 +79,6 @@ internal abstract class ZipFilePart : FilePart return new DataDescriptorStream(stream); } - case ZipCompressionMethod.Shrink: - { - return new ShrinkStream( - stream, - CompressionMode.Decompress, - Header.CompressedSize, - Header.UncompressedSize - ); - } case ZipCompressionMethod.Deflate: { return new DeflateStream(stream, CompressionMode.Decompress); @@ -202,7 +192,6 @@ internal abstract class ZipFilePart : FilePart switch (Header.CompressionMethod) { case ZipCompressionMethod.None: - case ZipCompressionMethod.Shrink: case ZipCompressionMethod.Deflate: case ZipCompressionMethod.Deflate64: case ZipCompressionMethod.BZip2: diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 45869ff6..8a58e220 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -55,13 +55,7 @@ internal class ZipHeaderFactory } case POST_DATA_DESCRIPTOR: { - if ( - _lastEntryHeader != null - && FlagUtility.HasFlag( - _lastEntryHeader.NotNull().Flags, - HeaderFlags.UsePostDataDescriptor - ) - ) + if (FlagUtility.HasFlag(_lastEntryHeader!.Flags, HeaderFlags.UsePostDataDescriptor)) { _lastEntryHeader.Crc = reader.ReadUInt32(); _lastEntryHeader.CompressedSize = zip64 @@ -148,8 +142,8 @@ internal class ZipHeaderFactory if (entryHeader.CompressionMethod == ZipCompressionMethod.WinzipAes) { - var data = entryHeader.Extra.SingleOrDefault(x => - x.Type == ExtraDataType.WinZipAes + var data = entryHeader.Extra.SingleOrDefault( + x => x.Type == ExtraDataType.WinZipAes ); if (data != null) { diff --git a/src/SharpCompress/Compressors/BZip2/BZip2Stream.cs b/src/SharpCompress/Compressors/BZip2/BZip2Stream.cs index 2c00ea71..feea12d1 100644 --- a/src/SharpCompress/Compressors/BZip2/BZip2Stream.cs +++ b/src/SharpCompress/Compressors/BZip2/BZip2Stream.cs @@ -69,7 +69,7 @@ public sealed class BZip2Stream : Stream public override void SetLength(long value) => stream.SetLength(value); -#if !NETFRAMEWORK&& !NETSTANDARD2_0 +#if !NETFRAMEWORK && !NETSTANDARD2_0 public override int Read(Span buffer) => stream.Read(buffer); diff --git a/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs b/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs index a467942f..e03a5096 100644 --- a/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs +++ b/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System; using System.IO; @@ -42,17 +42,14 @@ internal class CBZip2InputStream : Stream private static void Cadvise() { //System.out.Println("CRC Error"); - throw new InvalidOperationException("BZip2 error"); + //throw new CCoruptionError(); } private static void BadBGLengths() => Cadvise(); private static void BitStreamEOF() => Cadvise(); - private static void CompressedStreamEOF() - { - throw new InvalidOperationException("BZip2 compressed file ends unexpectedly"); - } + private static void CompressedStreamEOF() => Cadvise(); private void MakeMaps() { @@ -90,7 +87,7 @@ internal class CBZip2InputStream : Stream private int bsBuff; private int bsLive; - private readonly CRC mCrc = new(); + private readonly CRC mCrc = new CRC(); private readonly bool[] inUse = new bool[256]; private int nInUse; diff --git a/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs b/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs index bf01c2c3..a975ffbd 100644 --- a/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs +++ b/src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs @@ -284,7 +284,7 @@ internal sealed class CBZip2OutputStream : Stream private int bytesOut; private int bsBuff; private int bsLive; - private readonly CRC mCrc = new(); + private readonly CRC mCrc = new CRC(); private readonly bool[] inUse = new bool[256]; private int nInUse; diff --git a/src/SharpCompress/Compressors/Deflate/DeflateManager.cs b/src/SharpCompress/Compressors/Deflate/DeflateManager.cs index cccd0237..27ad4018 100644 --- a/src/SharpCompress/Compressors/Deflate/DeflateManager.cs +++ b/src/SharpCompress/Compressors/Deflate/DeflateManager.cs @@ -69,6 +69,7 @@ // ----------------------------------------------------------------------- using System; + using SharpCompress.Algorithms; namespace SharpCompress.Compressors.Deflate; @@ -342,9 +343,9 @@ internal sealed partial class DeflateManager private readonly short[] dyn_dtree; // distance tree private readonly short[] bl_tree; // Huffman tree for bit lengths - private readonly Tree treeLiterals = new(); // desc for literal tree - private readonly Tree treeDistances = new(); // desc for distance tree - private readonly Tree treeBitLengths = new(); // desc for bit length tree + private readonly Tree treeLiterals = new Tree(); // desc for literal tree + private readonly Tree treeDistances = new Tree(); // desc for distance tree + private readonly Tree treeBitLengths = new Tree(); // desc for bit length tree // number of codes at each bit length for an optimal tree private readonly short[] bl_count = new short[InternalConstants.MAX_BITS + 1]; @@ -1787,14 +1788,21 @@ internal sealed partial class DeflateManager return status == BUSY_STATE ? ZlibConstants.Z_DATA_ERROR : ZlibConstants.Z_OK; } - private void SetDeflater() => - DeflateFunction = config.Flavor switch + private void SetDeflater() + { + switch (config.Flavor) { - DeflateFlavor.Store => DeflateNone, - DeflateFlavor.Fast => DeflateFast, - DeflateFlavor.Slow => DeflateSlow, - _ => DeflateFunction - }; + case DeflateFlavor.Store: + DeflateFunction = DeflateNone; + break; + case DeflateFlavor.Fast: + DeflateFunction = DeflateFast; + break; + case DeflateFlavor.Slow: + DeflateFunction = DeflateSlow; + break; + } + } internal int SetParams(CompressionLevel level, CompressionStrategy strategy) { @@ -1951,9 +1959,7 @@ internal sealed partial class DeflateManager // returning Z_STREAM_END instead of Z_BUFF_ERROR. } else if ( - _codec.AvailableBytesIn == 0 - && (int)flush <= old_flush - && flush != FlushType.Finish + _codec.AvailableBytesIn == 0 && (int)flush <= old_flush && flush != FlushType.Finish ) { // workitem 8557 diff --git a/src/SharpCompress/Compressors/Deflate/DeflateStream.cs b/src/SharpCompress/Compressors/Deflate/DeflateStream.cs index 5566e817..05003d7f 100644 --- a/src/SharpCompress/Compressors/Deflate/DeflateStream.cs +++ b/src/SharpCompress/Compressors/Deflate/DeflateStream.cs @@ -366,5 +366,9 @@ public class DeflateStream : Stream #endregion public MemoryStream InputBuffer => - new(_baseStream._z.InputBuffer, _baseStream._z.NextIn, _baseStream._z.AvailableBytesIn); + new MemoryStream( + _baseStream._z.InputBuffer, + _baseStream._z.NextIn, + _baseStream._z.AvailableBytesIn + ); } diff --git a/src/SharpCompress/Compressors/Deflate/GZipStream.cs b/src/SharpCompress/Compressors/Deflate/GZipStream.cs index 0f7beca8..c547df14 100644 --- a/src/SharpCompress/Compressors/Deflate/GZipStream.cs +++ b/src/SharpCompress/Compressors/Deflate/GZipStream.cs @@ -35,7 +35,15 @@ namespace SharpCompress.Compressors.Deflate; public class GZipStream : Stream { - internal static readonly DateTime UNIX_EPOCH = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + internal static readonly DateTime UNIX_EPOCH = new DateTime( + 1970, + 1, + 1, + 0, + 0, + 0, + DateTimeKind.Utc + ); private string? _comment; private string? _fileName; diff --git a/src/SharpCompress/Compressors/Deflate/Inflate.cs b/src/SharpCompress/Compressors/Deflate/Inflate.cs index d768548b..ebea2805 100644 --- a/src/SharpCompress/Compressors/Deflate/Inflate.cs +++ b/src/SharpCompress/Compressors/Deflate/Inflate.cs @@ -64,6 +64,7 @@ // ----------------------------------------------------------------------- using System; + using SharpCompress.Algorithms; namespace SharpCompress.Compressors.Deflate; @@ -105,11 +106,11 @@ internal sealed class InflateBlocks internal int[] blens; // bit lengths of codes internal uint check; // check on output internal object checkfn; // check function - internal InflateCodes codes = new(); // if CODES, current state + internal InflateCodes codes = new InflateCodes(); // if CODES, current state internal int end; // one byte after sliding window internal int[] hufts; // single malloc for tree space internal int index; // index into blens (or border) - internal InfTree inftree = new(); + internal InfTree inftree = new InfTree(); internal int last; // true if this block is the last block internal int left; // if STORED, bytes left to copy private InflateBlockMode mode; // current inflate_block mode diff --git a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs index 94b1491d..19a3c60a 100644 --- a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs +++ b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs @@ -30,8 +30,8 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; using System.IO; -using System.Text; using SharpCompress.Common.Tar.Headers; +using System.Text; namespace SharpCompress.Compressors.Deflate; @@ -102,7 +102,7 @@ internal class ZlibBaseStream : Stream { if (_z is null) { - var wantRfc1950Header = (_flavor == ZlibStreamFlavor.ZLIB); + bool wantRfc1950Header = (_flavor == ZlibStreamFlavor.ZLIB); _z = new ZlibCodec(); if (_compressionMode == CompressionMode.Decompress) { @@ -147,13 +147,13 @@ internal class ZlibBaseStream : Stream z.InputBuffer = buffer; _z.NextIn = offset; _z.AvailableBytesIn = count; - var done = false; + bool done = false; do { _z.OutputBuffer = workingBuffer; _z.NextOut = 0; _z.AvailableBytesOut = _workingBuffer.Length; - var rc = (_wantCompress) ? _z.Deflate(_flushMode) : _z.Inflate(_flushMode); + int rc = (_wantCompress) ? _z.Deflate(_flushMode) : _z.Inflate(_flushMode); if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) { throw new ZlibException((_wantCompress ? "de" : "in") + "flating: " + _z.Message); @@ -181,18 +181,18 @@ internal class ZlibBaseStream : Stream if (_streamMode == StreamMode.Writer) { - var done = false; + bool done = false; do { _z.OutputBuffer = workingBuffer; _z.NextOut = 0; _z.AvailableBytesOut = _workingBuffer.Length; - var rc = + int rc = (_wantCompress) ? _z.Deflate(FlushType.Finish) : _z.Inflate(FlushType.Finish); if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) { - var verb = (_wantCompress ? "de" : "in") + "flating"; + string verb = (_wantCompress ? "de" : "in") + "flating"; if (_z.Message is null) { throw new ZlibException(String.Format("{0}: (rc = {1})", verb, rc)); @@ -225,7 +225,7 @@ internal class ZlibBaseStream : Stream Span intBuf = stackalloc byte[4]; BinaryPrimitives.WriteInt32LittleEndian(intBuf, crc.Crc32Result); _stream.Write(intBuf); - var c2 = (int)(crc.TotalBytesRead & 0x00000000FFFFFFFF); + int c2 = (int)(crc.TotalBytesRead & 0x00000000FFFFFFFF); BinaryPrimitives.WriteInt32LittleEndian(intBuf, c2); _stream.Write(intBuf); } @@ -256,8 +256,8 @@ internal class ZlibBaseStream : Stream { // Make sure we have read to the end of the stream _z.InputBuffer.AsSpan(_z.NextIn, _z.AvailableBytesIn).CopyTo(trailer); - var bytesNeeded = 8 - _z.AvailableBytesIn; - var bytesRead = _stream.Read( + int bytesNeeded = 8 - _z.AvailableBytesIn; + int bytesRead = _stream.Read( trailer.Slice(_z.AvailableBytesIn, bytesNeeded) ); if (bytesNeeded != bytesRead) @@ -275,10 +275,10 @@ internal class ZlibBaseStream : Stream _z.InputBuffer.AsSpan(_z.NextIn, trailer.Length).CopyTo(trailer); } - var crc32_expected = BinaryPrimitives.ReadInt32LittleEndian(trailer); - var crc32_actual = crc.Crc32Result; - var isize_expected = BinaryPrimitives.ReadInt32LittleEndian(trailer.Slice(4)); - var isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF); + Int32 crc32_expected = BinaryPrimitives.ReadInt32LittleEndian(trailer); + Int32 crc32_actual = crc.Crc32Result; + Int32 isize_expected = BinaryPrimitives.ReadInt32LittleEndian(trailer.Slice(4)); + Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF); if (crc32_actual != crc32_expected) { @@ -380,11 +380,11 @@ internal class ZlibBaseStream : Stream private string ReadZeroTerminatedString() { var list = new List(); - var done = false; + bool done = false; do { // workitem 7740 - var n = _stream.Read(_buf1, 0, 1); + int n = _stream.Read(_buf1, 0, 1); if (n != 1) { throw new ZlibException("Unexpected EOF reading GZIP header."); @@ -398,17 +398,17 @@ internal class ZlibBaseStream : Stream list.Add(_buf1[0]); } } while (!done); - var buffer = list.ToArray(); + byte[] buffer = list.ToArray(); return _encoding.GetString(buffer, 0, buffer.Length); } private int _ReadAndValidateGzipHeader() { - var totalBytesRead = 0; + int totalBytesRead = 0; // read the header on the first read Span header = stackalloc byte[10]; - var n = _stream.Read(header); + int n = _stream.Read(header); // workitem 8501: handle edge case (decompress empty stream) if (n == 0) @@ -426,7 +426,7 @@ internal class ZlibBaseStream : Stream throw new ZlibException("Bad GZIP header."); } - var timet = BinaryPrimitives.ReadInt32LittleEndian(header.Slice(4)); + int timet = BinaryPrimitives.ReadInt32LittleEndian(header.Slice(4)); _GzipMtime = TarHeader.EPOCH.AddSeconds(timet); totalBytesRead += n; if ((header[3] & 0x04) == 0x04) @@ -435,8 +435,8 @@ internal class ZlibBaseStream : Stream n = _stream.Read(header.Slice(0, 2)); // 2-byte length field totalBytesRead += n; - var extraLength = (short)(header[0] + header[1] * 256); - var extra = new byte[extraLength]; + short extraLength = (short)(header[0] + header[1] * 256); + byte[] extra = new byte[extraLength]; n = _stream.Read(extra, 0, extra.Length); if (n != extraLength) { @@ -498,7 +498,7 @@ internal class ZlibBaseStream : Stream throw new ZlibException("Cannot Read after Writing."); } - var rc = 0; + int rc = 0; // set up the output of the deflate/inflate codec: _z.OutputBuffer = buffer; diff --git a/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs b/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs index da4117b9..149f7c92 100644 --- a/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs +++ b/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs @@ -4,11 +4,11 @@ #nullable disable +using SharpCompress.Common.Zip; using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; -using SharpCompress.Common.Zip; namespace SharpCompress.Compressors.Deflate64; @@ -118,8 +118,8 @@ public sealed class Deflate64Stream : Stream EnsureNotDisposed(); int bytesRead; - var currentOffset = offset; - var remainingCount = count; + int currentOffset = offset; + int remainingCount = count; while (true) { @@ -142,7 +142,7 @@ public sealed class Deflate64Stream : Stream break; } - var bytes = _stream.Read(_buffer, 0, _buffer.Length); + int bytes = _stream.Read(_buffer, 0, _buffer.Length); if (bytes <= 0) { break; diff --git a/src/SharpCompress/Compressors/Deflate64/DeflateInput.cs b/src/SharpCompress/Compressors/Deflate64/DeflateInput.cs index 304a2a78..6a12df3b 100644 --- a/src/SharpCompress/Compressors/Deflate64/DeflateInput.cs +++ b/src/SharpCompress/Compressors/Deflate64/DeflateInput.cs @@ -22,7 +22,7 @@ internal sealed class DeflateInput Debug.Assert(StartIndex + Count <= Buffer.Length, "Input buffer is in invalid state!"); } - internal InputState DumpState() => new(Count, StartIndex); + internal InputState DumpState() => new InputState(Count, StartIndex); internal void RestoreState(InputState state) { diff --git a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs index e37802bb..051b613e 100644 --- a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs +++ b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs @@ -42,9 +42,11 @@ internal sealed class HuffmanTree private readonly int _tableMask; // huffman tree for static block - public static HuffmanTree StaticLiteralLengthTree { get; } = new(GetStaticLiteralTreeLength()); + public static HuffmanTree StaticLiteralLengthTree { get; } = + new HuffmanTree(GetStaticLiteralTreeLength()); - public static HuffmanTree StaticDistanceTree { get; } = new(GetStaticDistanceTreeLength()); + public static HuffmanTree StaticDistanceTree { get; } = + new HuffmanTree(GetStaticDistanceTreeLength()); public HuffmanTree(byte[] codeLengths) { diff --git a/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs b/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs index 4e11854f..6a3c226b 100644 --- a/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs +++ b/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs @@ -243,8 +243,8 @@ internal sealed class InflaterManaged private void Reset() => _state = //_hasFormatReader ? - //InflaterState.ReadingHeader : // start by reading Header info - InflaterState.ReadingBFinal; // start by reading BFinal bit + //InflaterState.ReadingHeader : // start by reading Header info + InflaterState.ReadingBFinal; // start by reading BFinal bit public void SetInput(byte[] inputBytes, int offset, int length) => _input.SetInput(inputBytes, offset, length); // append the bytes diff --git a/src/SharpCompress/Compressors/Filters/BCJ2Filter.cs b/src/SharpCompress/Compressors/Filters/BCJ2Filter.cs index 1ed531cc..f658b385 100644 --- a/src/SharpCompress/Compressors/Filters/BCJ2Filter.cs +++ b/src/SharpCompress/Compressors/Filters/BCJ2Filter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace SharpCompress.Compressors.Filters; @@ -79,7 +79,7 @@ internal class BCJ2Filter : Stream public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => _baseStream.Length + _data1.Length + _data2.Length; diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARM.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARM.cs index 5d861621..86e90b10 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterARM.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterARM.cs @@ -18,7 +18,7 @@ internal class BCJFilterARM : Filter { if ((buffer[i + 3] & 0xFF) == 0xEB) { - var src = + int src = ((buffer[i + 2] & 0xFF) << 16) | ((buffer[i + 1] & 0xFF) << 8) | (buffer[i] & 0xFF); diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs deleted file mode 100644 index 24f5ab17..00000000 --- a/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Buffers.Binary; -using System.IO; - -namespace SharpCompress.Compressors.Filters; - -internal class BCJFilterARM64 : Filter -{ - private int _pos; - - public BCJFilterARM64(bool isEncoder, Stream baseStream) - : base(isEncoder, baseStream, 8) => _pos = 0; - - protected override int Transform(byte[] buffer, int offset, int count) - { - var end = offset + count - 4; - int i; - - for (i = offset; i <= end; i += 4) - { - uint pc = (uint)(_pos + i - offset); - uint instr = BinaryPrimitives.ReadUInt32LittleEndian( - new ReadOnlySpan(buffer, i, 4) - ); - - if ((instr >> 26) == 0x25) - { - uint src = instr; - instr = 0x94000000; - - pc >>= 2; - if (!_isEncoder) - pc = 0U - pc; - - instr |= (src + pc) & 0x03FFFFFF; - BinaryPrimitives.WriteUInt32LittleEndian(new Span(buffer, i, 4), instr); - } - else if ((instr & 0x9F000000) == 0x90000000) - { - uint src = ((instr >> 29) & 3) | ((instr >> 3) & 0x001FFFFC); - - if (((src + 0x00020000) & 0x001C0000) != 0) - continue; - - instr &= 0x9000001F; - - pc >>= 12; - if (!_isEncoder) - pc = 0U - pc; - - uint dest = src + pc; - instr |= (dest & 3) << 29; - instr |= (dest & 0x0003FFFC) << 3; - instr |= (0U - (dest & 0x00020000)) & 0x00E00000; - BinaryPrimitives.WriteUInt32LittleEndian(new Span(buffer, i, 4), instr); - } - } - - i -= offset; - _pos += i; - return i; - } -} diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs index db5b36f2..d2ad1bbf 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs @@ -18,7 +18,7 @@ internal class BCJFilterARMT : Filter { if ((buffer[i + 1] & 0xF8) == 0xF0 && (buffer[i + 3] & 0xF8) == 0xF8) { - var src = + int src = ((buffer[i + 1] & 0x07) << 19) | ((buffer[i] & 0xFF) << 11) | ((buffer[i + 3] & 0x07) << 8) diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs b/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs index 07eaf319..4d89ba39 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs @@ -52,29 +52,29 @@ internal class BCJFilterIA64 : Filter for (i = offset; i <= end; i += 16) { - var instrTemplate = buffer[i] & 0x1F; - var mask = BRANCH_TABLE[instrTemplate]; + int instrTemplate = buffer[i] & 0x1F; + int mask = BRANCH_TABLE[instrTemplate]; for (int slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41) { if (((mask >>> slot) & 1) == 0) continue; - var bytePos = bitPos >>> 3; - var bitRes = bitPos & 7; + int bytePos = bitPos >>> 3; + int bitRes = bitPos & 7; long instr = 0; - for (var j = 0; j < 6; ++j) + for (int j = 0; j < 6; ++j) { instr |= (buffer[i + bytePos + j] & 0xFFL) << (8 * j); } - var instrNorm = instr >>> bitRes; + long instrNorm = instr >>> bitRes; if (((instrNorm >>> 37) & 0x0F) != 0x05 || ((instrNorm >>> 9) & 0x07) != 0x00) continue; - var src = (int)((instrNorm >>> 13) & 0x0FFFFF); + int src = (int)((instrNorm >>> 13) & 0x0FFFFF); src |= ((int)(instrNorm >>> 36) & 1) << 20; src <<= 4; @@ -93,7 +93,7 @@ internal class BCJFilterIA64 : Filter instr &= (1 << bitRes) - 1; instr |= instrNorm << bitRes; - for (var j = 0; j < 6; ++j) + for (int j = 0; j < 6; ++j) { buffer[i + bytePos + j] = (byte)(instr >>> (8 * j)); } diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs b/src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs index ccfa7480..11ed61a1 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs @@ -18,7 +18,7 @@ internal class BCJFilterPPC : Filter { if ((buffer[i] & 0xFC) == 0x48 && (buffer[i + 3] & 0x03) == 0x01) { - var src = + int src = ((buffer[i] & 0x03) << 24) | ((buffer[i + 1] & 0xFF) << 16) | ((buffer[i + 2] & 0xFF) << 8) diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs b/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs deleted file mode 100644 index 67d9cb52..00000000 --- a/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs +++ /dev/null @@ -1,210 +0,0 @@ -using System; -using System.Buffers.Binary; -using System.IO; - -namespace SharpCompress.Compressors.Filters; - -internal class BCJFilterRISCV : Filter -{ - private int _pos; - - public BCJFilterRISCV(bool isEncoder, Stream baseStream) - : base(isEncoder, baseStream, 8) => _pos = 0; - - private int Decode(byte[] buffer, int offset, int count) - { - if (count < 8) - { - return 0; - } - - var end = offset + count - 8; - int i; - for (i = offset; i <= end; i += 2) - { - uint inst = buffer[i]; - if (inst == 0xEF) - { - uint b1 = buffer[i + 1]; - if ((b1 & 0x0D) != 0) - continue; - - uint b2 = buffer[i + 2]; - uint b3 = buffer[i + 3]; - uint pc = (uint)(_pos + i); - - uint addr = ((b1 & 0xF0) << 13) | (b2 << 9) | (b3 << 1); - - addr -= pc; - - buffer[i + 1] = (byte)((b1 & 0x0F) | ((addr >> 8) & 0xF0)); - - buffer[i + 2] = (byte)( - ((addr >> 16) & 0x0F) | ((addr >> 7) & 0x10) | ((addr << 4) & 0xE0) - ); - - buffer[i + 3] = (byte)(((addr >> 4) & 0x7F) | ((addr >> 13) & 0x80)); - - i += 4 - 2; - } - else if ((inst & 0x7F) == 0x17) - { - uint inst2 = 0; - inst |= (uint)buffer[i + 1] << 8; - inst |= (uint)buffer[i + 2] << 16; - inst |= (uint)buffer[i + 3] << 24; - - if ((inst & 0xE80) != 0) - { - inst2 = BinaryPrimitives.ReadUInt32LittleEndian( - new ReadOnlySpan(buffer, i + 4, 4) - ); - if (((((inst) << 8) ^ (inst2)) & 0xF8003) != 3) - { - i += 6 - 2; - continue; - } - uint addr = inst & 0xFFFFF000; - addr += inst2 >> 20; - - inst = 0x17 | (2 << 7) | (inst2 << 12); - inst2 = addr; - } - else - { - uint inst2_rs1 = inst >> 27; - if ((uint)(((inst) - 0x3117) << 18) >= ((inst2_rs1) & 0x1D)) - { - i += 4 - 2; - continue; - } - - uint addr = BinaryPrimitives.ReadUInt32BigEndian( - new ReadOnlySpan(buffer, i + 4, 4) - ); - - addr -= (uint)(_pos + i); - - inst2 = (inst >> 12) | (addr << 20); - - inst = 0x17 | (inst2_rs1 << 7) | ((addr + 0x800) & 0xFFFFF000); - } - BinaryPrimitives.WriteUInt32LittleEndian(new Span(buffer, i, 4), inst); - BinaryPrimitives.WriteUInt32LittleEndian(new Span(buffer, i + 4, 4), inst2); - - i += 8 - 2; - } - } - i -= offset; - _pos += i; - return i; - } - - private int Encode(byte[] buffer, int offset, int count) - { - if (count < 8) - { - return 0; - } - - var end = offset + count - 8; - int i; - for (i = offset; i <= end; i += 2) - { - uint inst = buffer[i]; - if (inst == 0xEF) - { - uint b1 = buffer[i + 1]; - if ((b1 & 0x0D) != 0) - continue; - - uint b2 = buffer[i + 2]; - uint b3 = buffer[i + 3]; - uint pc = (uint)(_pos + i); - - uint addr = - ((b1 & 0xF0) << 8) - | ((b2 & 0x0F) << 16) - | ((b2 & 0x10) << 7) - | ((b2 & 0xE0) >> 4) - | ((b3 & 0x7F) << 4) - | ((b3 & 0x80) << 13); - - addr += pc; - - buffer[i + 1] = (byte)((b1 & 0x0F) | ((addr >> 13) & 0xF0)); - - buffer[i + 2] = (byte)(addr >> 9); - - buffer[i + 3] = (byte)(addr >> 1); - - i += 4 - 2; - } - else if ((inst & 0x7F) == 0x17) - { - inst |= (uint)buffer[i + 1] << 8; - inst |= (uint)buffer[i + 2] << 16; - inst |= (uint)buffer[i + 3] << 24; - - if ((inst & 0xE80) != 0) - { - uint inst2 = BinaryPrimitives.ReadUInt32LittleEndian( - new ReadOnlySpan(buffer, i + 4, 4) - ); - if (((((inst) << 8) ^ (inst2)) & 0xF8003) != 3) - { - i += 6 - 2; - continue; - } - uint addr = inst & 0xFFFFF000; - addr += (inst2 >> 20) - ((inst2 >> 19) & 0x1000); - - addr += (uint)(_pos + i); - inst = 0x17 | (2 << 7) | (inst2 << 12); - - BinaryPrimitives.WriteUInt32LittleEndian(new Span(buffer, i, 4), inst); - BinaryPrimitives.WriteUInt32BigEndian(new Span(buffer, i + 4, 4), addr); - } - else - { - uint fake_rs1 = inst >> 27; - if ((uint)(((inst) - 0x3117) << 18) >= ((fake_rs1) & 0x1D)) - { - i += 4 - 2; - continue; - } - - uint fake_addr = BinaryPrimitives.ReadUInt32LittleEndian( - new ReadOnlySpan(buffer, i + 4, 4) - ); - - uint fake_inst2 = (inst >> 12) | (fake_addr << 20); - - inst = 0x17 | (fake_rs1 << 7) | (fake_addr & 0xFFFFF000); - - BinaryPrimitives.WriteUInt32LittleEndian(new Span(buffer, i, 4), inst); - BinaryPrimitives.WriteUInt32LittleEndian( - new Span(buffer, i + 4, 4), - fake_inst2 - ); - } - i += 8 - 2; - } - } - i -= offset; - _pos += i; - return i; - } - - protected override int Transform(byte[] buffer, int offset, int count) - { - if (_isEncoder) - { - return Encode(buffer, offset, count); - } - else - { - return Decode(buffer, offset, count); - } - } -} diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs b/src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs index db7c75be..67756d34 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs @@ -21,7 +21,7 @@ internal class BCJFilterSPARC : Filter || (buffer[i] == 0x7F && (buffer[i + 1] & 0xC0) == 0xC0) ) { - var src = + int src = ((buffer[i] & 0xFF) << 24) | ((buffer[i + 1] & 0xFF) << 16) | ((buffer[i + 2] & 0xFF) << 8) diff --git a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs index d198cf8f..9fc439d4 100644 --- a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs +++ b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs @@ -24,27 +24,40 @@ public sealed class BranchExecFilter } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool X86TestByte(byte b) => b == 0x00 || b == 0xFF; + private static bool X86TestByte(byte b) + { + return b == 0x00 || b == 0xFF; + } //Replaced X86Converter with bcj_x86() - https://github.com/torvalds/linux/blob/master/lib/xz/xz_dec_bcj.c //This was to fix an issue decoding a Test zip made with WinZip (that 7zip was also able to read). //The previous version of the code would corrupt 2 bytes in the Test.exe at 0x6CF9 (3D6D - should be 4000) - Test zip: WinZip27.Xz.zipx public static void X86Converter(byte[] buf, uint ip, ref uint state) { - var mask_to_allowed_status = new[] { true, true, true, false, true, false, false, false }; + bool[] mask_to_allowed_status = new[] + { + true, + true, + true, + false, + true, + false, + false, + false + }; - var mask_to_bit_num = new byte[] { 0, 1, 2, 2, 3, 3, 3, 3 }; + byte[] mask_to_bit_num = new byte[] { 0, 1, 2, 2, 3, 3, 3, 3 }; int i; - var prev_pos = -1; - var prev_mask = state & 7; + int prev_pos = -1; + uint prev_mask = state & 7; uint src; uint dest; uint j; byte b; - var pos = ip; + uint pos = ip; - var size = (uint)buf.Length; + uint size = (uint)buf.Length; if (size <= 4) return; diff --git a/src/SharpCompress/Compressors/Filters/DeltaFilter.cs b/src/SharpCompress/Compressors/Filters/DeltaFilter.cs index 85ec9b15..c5fbeb41 100644 --- a/src/SharpCompress/Compressors/Filters/DeltaFilter.cs +++ b/src/SharpCompress/Compressors/Filters/DeltaFilter.cs @@ -23,9 +23,9 @@ namespace SharpCompress.Compressors.Filters protected override int Transform(byte[] buffer, int offset, int count) { - var end = offset + count; + int end = offset + count; - for (var i = offset; i < end; i++) + for (int i = offset; i < end; i++) { buffer[i] += _history[(_distance + _position--) & DISTANCE_MASK]; _history[_position & DISTANCE_MASK] = buffer[i]; diff --git a/src/SharpCompress/Compressors/Filters/Filter.cs b/src/SharpCompress/Compressors/Filters/Filter.cs index aa5e620d..93d95195 100644 --- a/src/SharpCompress/Compressors/Filters/Filter.cs +++ b/src/SharpCompress/Compressors/Filters/Filter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace SharpCompress.Compressors.Filters; @@ -40,7 +40,7 @@ internal abstract class Filter : Stream public override bool CanWrite => _isEncoder; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => _baseStream.Length; diff --git a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs index e89d705a..24823c73 100644 --- a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs +++ b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs @@ -20,8 +20,7 @@ internal sealed class AesDecoderStream : DecoderStream2 public AesDecoderStream(Stream input, byte[] info, IPasswordProvider pass, long limit) { - var password = pass.CryptoGetTextPassword(); - if (password == null) + if (pass.CryptoGetTextPassword() == null) { throw new SharpCompress.Common.CryptographicException( "Encrypted 7Zip archive has no password specified." @@ -36,10 +35,10 @@ internal sealed class AesDecoderStream : DecoderStream2 throw new NotSupportedException("AES decoder does not support padding."); } - Init(info, out var numCyclesPower, out var salt, out var seed); + Init(info, out int numCyclesPower, out byte[] salt, out byte[] seed); - var passwordBytes = Encoding.Unicode.GetBytes(password); - var key = InitKey(numCyclesPower, salt, passwordBytes); + byte[] password = Encoding.Unicode.GetBytes(pass.CryptoGetTextPassword()); + byte[]? key = InitKey(numCyclesPower, salt, password); if (key == null) { throw new InvalidOperationException("Initialized with null key"); @@ -101,7 +100,7 @@ internal sealed class AesDecoderStream : DecoderStream2 do { - var read = mStream.Read(mBuffer, mEnding, mBuffer.Length - mEnding); + int read = mStream.Read(mBuffer, mEnding, mBuffer.Length - mEnding); if (read == 0) { // We are not done decoding and have less than 16 bytes. @@ -134,7 +133,7 @@ internal sealed class AesDecoderStream : DecoderStream2 } // Otherwise we transform directly into the target buffer. - var processed = mDecoder.TransformBlock(mBuffer, mOffset, count & ~15, buffer, offset); + int processed = mDecoder.TransformBlock(mBuffer, mOffset, count & ~15, buffer, offset); mOffset += processed; mWritten += processed; return processed; @@ -144,7 +143,7 @@ internal sealed class AesDecoderStream : DecoderStream2 private void Init(byte[] info, out int numCyclesPower, out byte[] salt, out byte[] iv) { - var bt = info[0]; + byte bt = info[0]; numCyclesPower = bt & 0x3F; if ((bt & 0xC0) == 0) @@ -154,14 +153,14 @@ internal sealed class AesDecoderStream : DecoderStream2 return; } - var saltSize = (bt >> 7) & 1; - var ivSize = (bt >> 6) & 1; + int saltSize = (bt >> 7) & 1; + int ivSize = (bt >> 6) & 1; if (info.Length == 1) { throw new InvalidOperationException(); } - var bt2 = info[1]; + byte bt2 = info[1]; saltSize += (bt2 >> 4); ivSize += (bt2 & 15); if (info.Length < 2 + saltSize + ivSize) @@ -170,13 +169,13 @@ internal sealed class AesDecoderStream : DecoderStream2 } salt = new byte[saltSize]; - for (var i = 0; i < saltSize; i++) + for (int i = 0; i < saltSize; i++) { salt[i] = info[i + 2]; } iv = new byte[16]; - for (var i = 0; i < ivSize; i++) + for (int i = 0; i < ivSize; i++) { iv[i] = info[i + saltSize + 2]; } @@ -199,7 +198,7 @@ internal sealed class AesDecoderStream : DecoderStream2 key[pos] = salt[pos]; } - for (var i = 0; i < pass.Length && pos < 32; i++) + for (int i = 0; i < pass.Length && pos < 32; i++) { key[pos++] = pass[i]; } @@ -208,9 +207,31 @@ internal sealed class AesDecoderStream : DecoderStream2 } else { +#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++) + { + 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++) + { + if (++counter[i] != 0) + { + break; + } + } + } + return sha.GetHashAndReset(); +#else using var sha = SHA256.Create(); - var counter = new byte[8]; - var numRounds = 1L << mNumCyclesPower; + byte[] counter = new byte[8]; + long numRounds = 1L << mNumCyclesPower; for (long round = 0; round < numRounds; round++) { sha.TransformBlock(salt, 0, salt.Length, null, 0); @@ -219,7 +240,7 @@ internal sealed class AesDecoderStream : DecoderStream2 // 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 (var i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { if (++counter[i] != 0) { @@ -230,6 +251,7 @@ internal sealed class AesDecoderStream : DecoderStream2 sha.TransformFinalBlock(counter, 0, 0); return sha.Hash; +#endif } } @@ -239,7 +261,7 @@ internal sealed class AesDecoderStream : DecoderStream2 // Just transform as much as possible so we can feed from it as long as possible. if (mUnderflow == 0) { - var blockSize = (mEnding - mOffset) & ~15; + int blockSize = (mEnding - mOffset) & ~15; mUnderflow = mDecoder.TransformBlock(mBuffer, mOffset, blockSize, mBuffer, mOffset); } diff --git a/src/SharpCompress/Compressors/LZMA/DecoderStream.cs b/src/SharpCompress/Compressors/LZMA/DecoderStream.cs index a3dbf37f..16865351 100644 --- a/src/SharpCompress/Compressors/LZMA/DecoderStream.cs +++ b/src/SharpCompress/Compressors/LZMA/DecoderStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using SharpCompress.Common.SevenZip; using SharpCompress.Compressors.LZMA.Utilites; @@ -14,7 +14,7 @@ internal abstract class DecoderStream2 : Stream public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.cs index 5e987214..4b63a621 100644 --- a/src/SharpCompress/Compressors/LZMA/LZipStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LZipStream.cs @@ -63,18 +63,18 @@ public sealed class LZipStream : Stream var crc32Stream = (Crc32Stream)_stream; crc32Stream.WrappedStream.Dispose(); crc32Stream.Dispose(); - var compressedCount = _countingWritableSubStream.NotNull().Count; + var compressedCount = _countingWritableSubStream!.Count; Span intBuf = stackalloc byte[8]; BinaryPrimitives.WriteUInt32LittleEndian(intBuf, crc32Stream.Crc); - _countingWritableSubStream?.Write(intBuf.Slice(0, 4)); + _countingWritableSubStream.Write(intBuf.Slice(0, 4)); BinaryPrimitives.WriteInt64LittleEndian(intBuf, _writeCount); - _countingWritableSubStream?.Write(intBuf); + _countingWritableSubStream.Write(intBuf); //total with headers BinaryPrimitives.WriteUInt64LittleEndian(intBuf, compressedCount + 6 + 20); - _countingWritableSubStream?.Write(intBuf); + _countingWritableSubStream.Write(intBuf); } _finished = true; } diff --git a/src/SharpCompress/Compressors/LZMA/Log.cs b/src/SharpCompress/Compressors/LZMA/Log.cs index 1431966c..e954e259 100644 --- a/src/SharpCompress/Compressors/LZMA/Log.cs +++ b/src/SharpCompress/Compressors/LZMA/Log.cs @@ -6,7 +6,7 @@ namespace SharpCompress.Compressors.LZMA; internal static class Log { - private static readonly Stack INDENT = new(); + private static readonly Stack INDENT = new Stack(); private static bool NEEDS_INDENT = true; static Log() => INDENT.Push(""); diff --git a/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs b/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs index 1b2fdc81..31039761 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs @@ -11,11 +11,11 @@ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { private class LenDecoder { - private BitDecoder _choice = new(); - private BitDecoder _choice2 = new(); + private BitDecoder _choice = new BitDecoder(); + private BitDecoder _choice2 = new BitDecoder(); private readonly BitTreeDecoder[] _lowCoder = new BitTreeDecoder[Base.K_NUM_POS_STATES_MAX]; private readonly BitTreeDecoder[] _midCoder = new BitTreeDecoder[Base.K_NUM_POS_STATES_MAX]; - private BitTreeDecoder _highCoder = new(Base.K_NUM_HIGH_LEN_BITS); + private BitTreeDecoder _highCoder = new BitTreeDecoder(Base.K_NUM_HIGH_LEN_BITS); private uint _numPosStates; public void Create(uint numPosStates) @@ -173,18 +173,18 @@ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream Base.K_NUM_FULL_DISTANCES - Base.K_END_POS_MODEL_INDEX ]; - private BitTreeDecoder _posAlignDecoder = new(Base.K_NUM_ALIGN_BITS); + private BitTreeDecoder _posAlignDecoder = new BitTreeDecoder(Base.K_NUM_ALIGN_BITS); - private readonly LenDecoder _lenDecoder = new(); - private readonly LenDecoder _repLenDecoder = new(); + private readonly LenDecoder _lenDecoder = new LenDecoder(); + private readonly LenDecoder _repLenDecoder = new LenDecoder(); - private readonly LiteralDecoder _literalDecoder = new(); + private readonly LiteralDecoder _literalDecoder = new LiteralDecoder(); private int _dictionarySize; private uint _posStateMask; - private Base.State _state = new(); + private Base.State _state = new Base.State(); private uint _rep0, _rep1, _rep2, @@ -318,8 +318,9 @@ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream { var posState = (uint)outWindow._total & _posStateMask; if ( - _isMatchDecoders[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState] - .Decode(rangeDecoder) == 0 + _isMatchDecoders[ + (_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState + ].Decode(rangeDecoder) == 0 ) { byte b; @@ -354,8 +355,7 @@ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream if ( _isRep0LongDecoders[ (_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState - ] - .Decode(rangeDecoder) == 0 + ].Decode(rangeDecoder) == 0 ) { _state.UpdateShortRep(); diff --git a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs index 509e54c8..558fe37b 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs @@ -61,7 +61,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties return (uint)(G_FAST_POS[pos >> 26] + 52); } - private Base.State _state = new(); + private Base.State _state = new Base.State(); private byte _previousByte; private readonly uint[] _repDistances = new uint[Base.K_NUM_REP_DISTANCES]; @@ -191,15 +191,15 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties private class LenEncoder { - private BitEncoder _choice = new(); - private BitEncoder _choice2 = new(); + private BitEncoder _choice = new BitEncoder(); + private BitEncoder _choice2 = new BitEncoder(); private readonly BitTreeEncoder[] _lowCoder = new BitTreeEncoder[ Base.K_NUM_POS_STATES_ENCODING_MAX ]; private readonly BitTreeEncoder[] _midCoder = new BitTreeEncoder[ Base.K_NUM_POS_STATES_ENCODING_MAX ]; - private BitTreeEncoder _highCoder = new(Base.K_NUM_HIGH_LEN_BITS); + private BitTreeEncoder _highCoder = new BitTreeEncoder(Base.K_NUM_HIGH_LEN_BITS); public LenEncoder() { @@ -359,7 +359,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties private readonly Optimal[] _optimum = new Optimal[K_NUM_OPTS]; private BinTree _matchFinder; - private readonly RangeCoder.Encoder _rangeEncoder = new(); + private readonly RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); private readonly BitEncoder[] _isMatch = new BitEncoder[ Base.K_NUM_STATES << Base.K_NUM_POS_STATES_BITS_MAX @@ -382,12 +382,12 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties Base.K_NUM_FULL_DISTANCES - Base.K_END_POS_MODEL_INDEX ]; - private BitTreeEncoder _posAlignEncoder = new(Base.K_NUM_ALIGN_BITS); + private BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.K_NUM_ALIGN_BITS); - private readonly LenPriceTableEncoder _lenEncoder = new(); - private readonly LenPriceTableEncoder _repMatchLenEncoder = new(); + private readonly LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); + private readonly LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); - private readonly LiteralEncoder _literalEncoder = new(); + private readonly LiteralEncoder _literalEncoder = new LiteralEncoder(); private readonly uint[] _matchDistances = new uint[(Base.K_MATCH_MAX_LEN * 2) + 2]; @@ -553,8 +553,9 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties if (repIndex == 0) { price = _isRepG0[state._index].GetPrice0(); - price += _isRep0Long[(state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState] - .GetPrice1(); + price += _isRep0Long[ + (state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState + ].GetPrice1(); } else { @@ -712,8 +713,9 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties .GetPrice(!_state.IsCharState(), matchByte, currentByte); _optimum[1].MakeAsChar(); - var matchPrice = _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState] - .GetPrice1(); + var matchPrice = _isMatch[ + (_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState + ].GetPrice1(); var repMatchPrice = matchPrice + _isRep[_state._index].GetPrice1(); if (matchByte == currentByte) @@ -993,8 +995,9 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties var posStateNext = (position + 1) & _posStateMask; var nextRepMatchPrice = curAnd1Price - + _isMatch[(state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext] - .GetPrice1() + + _isMatch[ + (state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext + ].GetPrice1() + _isRep[state2._index].GetPrice1(); { var offset = cur + 1 + lenTest2; @@ -1066,8 +1069,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + GetRepPrice(repIndex, lenTest, state, posState) + _isMatch[ (state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext - ] - .GetPrice0() + ].GetPrice0() + _literalEncoder .GetSubCoder( position + lenTest, @@ -1086,8 +1088,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties curAndLenCharPrice + _isMatch[ (state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext - ] - .GetPrice1(); + ].GetPrice1(); var nextRepMatchPrice = nextMatchPrice + _isRep[state2._index].GetPrice1(); // for(; lenTest2 >= 2; lenTest2--) @@ -1173,8 +1174,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + _isMatch[ (state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext - ] - .GetPrice0() + ].GetPrice0() + _literalEncoder .GetSubCoder( position + lenTest, @@ -1194,8 +1194,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + _isMatch[ (state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext - ] - .GetPrice1(); + ].GetPrice1(); var nextRepMatchPrice = nextMatchPrice + _isRep[state2._index].GetPrice1(); @@ -1244,8 +1243,10 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties return; } - _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState] - .Encode(_rangeEncoder, 1); + _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].Encode( + _rangeEncoder, + 1 + ); _isRep[_state._index].Encode(_rangeEncoder, 0); _state.UpdateMatch(); var len = Base.K_MATCH_MIN_LEN; @@ -1320,8 +1321,10 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties // it's not used ReadMatchDistances(out var len, out var numDistancePairs); var posState = (uint)(_nowPos64) & _posStateMask; - _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState] - .Encode(_rangeEncoder, 0); + _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].Encode( + _rangeEncoder, + 0 + ); _state.UpdateChar(); var curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); _literalEncoder @@ -1727,7 +1730,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties ReadOnlySpan properties ) { - for (var i = 0; i < properties.Length; i++) + for (int i = 0; i < properties.Length; i++) { var prop = properties[i]; switch (propIDs[i]) diff --git a/src/SharpCompress/Compressors/LZMA/LzmaStream.cs b/src/SharpCompress/Compressors/LZMA/LzmaStream.cs index 043cbbad..701b8e64 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaStream.cs @@ -14,8 +14,8 @@ public class LzmaStream : Stream private readonly long _outputSize; private readonly int _dictionarySize; - private readonly OutWindow _outWindow = new(); - private readonly RangeCoder.Decoder _rangeDecoder = new(); + private readonly OutWindow _outWindow = new OutWindow(); + private readonly RangeCoder.Decoder _rangeDecoder = new RangeCoder.Decoder(); private Decoder _decoder; private long _position; @@ -207,23 +207,14 @@ public class LzmaStream : Stream if (_availableBytes == 0 && !_uncompressedChunk) { - // Check range corruption scenario + _rangeDecoder.ReleaseStream(); if ( !_rangeDecoder.IsFinished || (_rangeDecoderLimit >= 0 && _rangeDecoder._total != _rangeDecoderLimit) ) { - // Stream might have End Of Stream marker - _outWindow.SetLimit(toProcess + 1); - if (!_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder)) - { - _rangeDecoder.ReleaseStream(); - throw new DataErrorException(); - } + throw new DataErrorException(); } - - _rangeDecoder.ReleaseStream(); - _inputPosition += _rangeDecoder._total; if (_outWindow.HasPending) { diff --git a/src/SharpCompress/Compressors/LZMA/Registry.cs b/src/SharpCompress/Compressors/LZMA/Registry.cs index eb3e3bdd..f4cfde4b 100644 --- a/src/SharpCompress/Compressors/LZMA/Registry.cs +++ b/src/SharpCompress/Compressors/LZMA/Registry.cs @@ -25,8 +25,6 @@ internal static class DecoderRegistry private const uint K_ARM = 0x03030501; private const uint K_ARMT = 0x03030701; private const uint K_SPARC = 0x03030805; - private const uint K_ARM64 = 0x0A; - private const uint K_RISCV = 0x0B; private const uint K_DEFLATE = 0x040108; private const uint K_B_ZIP2 = 0x040202; private const uint K_ZSTD = 0x4F71101; @@ -68,10 +66,6 @@ internal static class DecoderRegistry return new BCJFilterARMT(false, inStreams.Single()); case K_SPARC: return new BCJFilterSPARC(false, inStreams.Single()); - case K_ARM64: - return new BCJFilterARM64(false, inStreams.Single()); - case K_RISCV: - return new BCJFilterRISCV(false, inStreams.Single()); case K_B_ZIP2: return new BZip2Stream(inStreams.Single(), CompressionMode.Decompress, true); case K_PPMD: diff --git a/src/SharpCompress/Compressors/LZMA/Utilites/IPasswordProvider.cs b/src/SharpCompress/Compressors/LZMA/Utilites/IPasswordProvider.cs index d7d787d2..2f0eb904 100644 --- a/src/SharpCompress/Compressors/LZMA/Utilites/IPasswordProvider.cs +++ b/src/SharpCompress/Compressors/LZMA/Utilites/IPasswordProvider.cs @@ -2,5 +2,5 @@ namespace SharpCompress.Compressors.LZMA.Utilites; internal interface IPasswordProvider { - string? CryptoGetTextPassword(); + string CryptoGetTextPassword(); } diff --git a/src/SharpCompress/Compressors/Lzw/LzwConstants.cs b/src/SharpCompress/Compressors/Lzw/LzwConstants.cs deleted file mode 100644 index 0325adbb..00000000 --- a/src/SharpCompress/Compressors/Lzw/LzwConstants.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace SharpCompress.Compressors.Lzw -{ - /// - /// This class contains constants used for LZW - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage( - "Naming", - "CA1707:Identifiers should not contain underscores", - Justification = "kept for backwards compatibility" - )] - public sealed class LzwConstants - { - /// - /// Magic number found at start of LZW header: 0x1f 0x9d - /// - public const int MAGIC = 0x1f9d; - - /// - /// Maximum number of bits per code - /// - public const int MAX_BITS = 16; - - /* 3rd header byte: - * bit 0..4 Number of compression bits - * bit 5 Extended header - * bit 6 Free - * bit 7 Block mode - */ - - /// - /// Mask for 'number of compression bits' - /// - public const int BIT_MASK = 0x1f; - - /// - /// Indicates the presence of a fourth header byte - /// - public const int EXTENDED_MASK = 0x20; - - //public const int FREE_MASK = 0x40; - - /// - /// Reserved bits - /// - public const int RESERVED_MASK = 0x60; - - /// - /// Block compression: if table is full and compression rate is dropping, - /// clear the dictionary. - /// - public const int BLOCK_MODE_MASK = 0x80; - - /// - /// LZW file header size (in bytes) - /// - public const int HDR_SIZE = 3; - - /// - /// Initial number of bits per code - /// - public const int INIT_BITS = 9; - - private LzwConstants() { } - } -} diff --git a/src/SharpCompress/Compressors/Lzw/LzwStream.cs b/src/SharpCompress/Compressors/Lzw/LzwStream.cs deleted file mode 100644 index 488ba1aa..00000000 --- a/src/SharpCompress/Compressors/Lzw/LzwStream.cs +++ /dev/null @@ -1,597 +0,0 @@ -using System; -using System.IO; -using SharpCompress.Common; - -namespace SharpCompress.Compressors.Lzw -{ - /// - /// This filter stream is used to decompress a LZW format stream. - /// Specifically, a stream that uses the LZC compression method. - /// This file format is usually associated with the .Z file extension. - /// - /// See http://en.wikipedia.org/wiki/Compress - /// See http://wiki.wxwidgets.org/Development:_Z_File_Format - /// - /// The file header consists of 3 (or optionally 4) bytes. The first two bytes - /// contain the magic marker "0x1f 0x9d", followed by a byte of flags. - /// - /// Based on Java code by Ronald Tschalar, which in turn was based on the unlzw.c - /// code in the gzip package. - /// - /// This sample shows how to unzip a compressed file - /// - /// using System; - /// using System.IO; - /// - /// using ICSharpCode.SharpZipLib.Core; - /// using ICSharpCode.SharpZipLib.LZW; - /// - /// class MainClass - /// { - /// public static void Main(string[] args) - /// { - /// using (Stream inStream = new LzwInputStream(File.OpenRead(args[0]))) - /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { - /// byte[] buffer = new byte[4096]; - /// StreamUtils.Copy(inStream, outStream, buffer); - /// // OR - /// inStream.Read(buffer, 0, buffer.Length); - /// // now do something with the buffer - /// } - /// } - /// } - /// - /// - public class LzwStream : Stream - { - public static bool IsLzwStream(Stream stream) - { - try - { - byte[] hdr = new byte[LzwConstants.HDR_SIZE]; - - int result = stream.Read(hdr, 0, hdr.Length); - - // Check the magic marker - if (result < 0) - throw new IncompleteArchiveException("Failed to read LZW header"); - - if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) - { - throw new IncompleteArchiveException( - String.Format( - "Wrong LZW header. Magic bytes don't match. 0x{0:x2} 0x{1:x2}", - hdr[0], - hdr[1] - ) - ); - } - } - catch (Exception) - { - return false; - } - return true; - } - - /// - /// Gets or sets a flag indicating ownership of underlying stream. - /// When the flag is true will close the underlying stream also. - /// - /// The default value is true. - public bool IsStreamOwner { get; set; } = false; - - /// - /// Creates a LzwInputStream - /// - /// - /// The stream to read compressed data from (baseInputStream LZW format) - /// - public LzwStream(Stream baseInputStream) - { - this.baseInputStream = baseInputStream; - } - - /// - /// See - /// - /// - public override int ReadByte() - { - int b = Read(one, 0, 1); - if (b == 1) - return (one[0] & 0xff); - return -1; - } - - /// - /// Reads decompressed data into the provided buffer byte array - /// - /// - /// The array to read and decompress data into - /// - /// - /// The offset indicating where the data should be placed - /// - /// - /// The number of bytes to decompress - /// - /// The number of bytes read. Zero signals the end of stream - public override int Read(byte[] buffer, int offset, int count) - { - if (!headerParsed) - ParseHeader(); - - if (eof) - return 0; - - int start = offset; - - /* Using local copies of various variables speeds things up by as - * much as 30% in Java! Performance not tested in C#. - */ - int[] lTabPrefix = tabPrefix; - byte[] lTabSuffix = tabSuffix; - byte[] lStack = stack; - int lNBits = nBits; - int lMaxCode = maxCode; - int lMaxMaxCode = maxMaxCode; - int lBitMask = bitMask; - int lOldCode = oldCode; - byte lFinChar = finChar; - int lStackP = stackP; - int lFreeEnt = freeEnt; - byte[] lData = data; - int lBitPos = bitPos; - - // empty stack if stuff still left - int sSize = lStack.Length - lStackP; - if (sSize > 0) - { - int num = (sSize >= count) ? count : sSize; - Array.Copy(lStack, lStackP, buffer, offset, num); - offset += num; - count -= num; - lStackP += num; - } - - if (count == 0) - { - stackP = lStackP; - return offset - start; - } - - // loop, filling local buffer until enough data has been decompressed - MainLoop: - do - { - if (end < EXTRA) - { - Fill(); - } - - int bitIn = (got > 0) ? (end - end % lNBits) << 3 : (end << 3) - (lNBits - 1); - - while (lBitPos < bitIn) - { - #region A - - // handle 1-byte reads correctly - if (count == 0) - { - nBits = lNBits; - maxCode = lMaxCode; - maxMaxCode = lMaxMaxCode; - bitMask = lBitMask; - oldCode = lOldCode; - finChar = lFinChar; - stackP = lStackP; - freeEnt = lFreeEnt; - bitPos = lBitPos; - - return offset - start; - } - - // check for code-width expansion - if (lFreeEnt > lMaxCode) - { - int nBytes = lNBits << 3; - lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes; - - lNBits++; - lMaxCode = (lNBits == maxBits) ? lMaxMaxCode : (1 << lNBits) - 1; - - lBitMask = (1 << lNBits) - 1; - lBitPos = ResetBuf(lBitPos); - goto MainLoop; - } - - #endregion A - - #region B - - // read next code - int pos = lBitPos >> 3; - int code = - ( - ( - (lData[pos] & 0xFF) - | ((lData[pos + 1] & 0xFF) << 8) - | ((lData[pos + 2] & 0xFF) << 16) - ) >> (lBitPos & 0x7) - ) & lBitMask; - - lBitPos += lNBits; - - // handle first iteration - if (lOldCode == -1) - { - if (code >= 256) - throw new IncompleteArchiveException( - "corrupt input: " + code + " > 255" - ); - - lFinChar = (byte)(lOldCode = code); - buffer[offset++] = lFinChar; - count--; - continue; - } - - // handle CLEAR code - if (code == TBL_CLEAR && blockMode) - { - Array.Copy(zeros, 0, lTabPrefix, 0, zeros.Length); - lFreeEnt = TBL_FIRST - 1; - - int nBytes = lNBits << 3; - lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes; - lNBits = LzwConstants.INIT_BITS; - lMaxCode = (1 << lNBits) - 1; - lBitMask = lMaxCode; - - // Code tables reset - - lBitPos = ResetBuf(lBitPos); - goto MainLoop; - } - - #endregion B - - #region C - - // setup - int inCode = code; - lStackP = lStack.Length; - - // Handle KwK case - if (code >= lFreeEnt) - { - if (code > lFreeEnt) - { - throw new IncompleteArchiveException( - "corrupt input: code=" + code + ", freeEnt=" + lFreeEnt - ); - } - - lStack[--lStackP] = lFinChar; - code = lOldCode; - } - - // Generate output characters in reverse order - while (code >= 256) - { - lStack[--lStackP] = lTabSuffix[code]; - code = lTabPrefix[code]; - } - - lFinChar = lTabSuffix[code]; - buffer[offset++] = lFinChar; - count--; - - // And put them out in forward order - sSize = lStack.Length - lStackP; - int num = (sSize >= count) ? count : sSize; - Array.Copy(lStack, lStackP, buffer, offset, num); - offset += num; - count -= num; - lStackP += num; - - #endregion C - - #region D - - // generate new entry in table - if (lFreeEnt < lMaxMaxCode) - { - lTabPrefix[lFreeEnt] = lOldCode; - lTabSuffix[lFreeEnt] = lFinChar; - lFreeEnt++; - } - - // Remember previous code - lOldCode = inCode; - - // if output buffer full, then return - if (count == 0) - { - nBits = lNBits; - maxCode = lMaxCode; - bitMask = lBitMask; - oldCode = lOldCode; - finChar = lFinChar; - stackP = lStackP; - freeEnt = lFreeEnt; - bitPos = lBitPos; - - return offset - start; - } - - #endregion D - } // while - - lBitPos = ResetBuf(lBitPos); - } while (got > 0); // do..while - - nBits = lNBits; - maxCode = lMaxCode; - bitMask = lBitMask; - oldCode = lOldCode; - finChar = lFinChar; - stackP = lStackP; - freeEnt = lFreeEnt; - bitPos = lBitPos; - - eof = true; - return offset - start; - } - - /// - /// Moves the unread data in the buffer to the beginning and resets - /// the pointers. - /// - /// - /// - private int ResetBuf(int bitPosition) - { - int pos = bitPosition >> 3; - Array.Copy(data, pos, data, 0, end - pos); - end -= pos; - return 0; - } - - private void Fill() - { - got = baseInputStream.Read(data, end, data.Length - 1 - end); - if (got > 0) - { - end += got; - } - } - - private void ParseHeader() - { - headerParsed = true; - - byte[] hdr = new byte[LzwConstants.HDR_SIZE]; - - int result = baseInputStream.Read(hdr, 0, hdr.Length); - - // Check the magic marker - if (result < 0) - throw new IncompleteArchiveException("Failed to read LZW header"); - - if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) - { - throw new IncompleteArchiveException( - String.Format( - "Wrong LZW header. Magic bytes don't match. 0x{0:x2} 0x{1:x2}", - hdr[0], - hdr[1] - ) - ); - } - - // Check the 3rd header byte - blockMode = (hdr[2] & LzwConstants.BLOCK_MODE_MASK) > 0; - maxBits = hdr[2] & LzwConstants.BIT_MASK; - - if (maxBits > LzwConstants.MAX_BITS) - { - throw new ArchiveException( - "Stream compressed with " - + maxBits - + " bits, but decompression can only handle " - + LzwConstants.MAX_BITS - + " bits." - ); - } - - if ((hdr[2] & LzwConstants.RESERVED_MASK) > 0) - { - throw new ArchiveException("Unsupported bits set in the header."); - } - - // Initialize variables - maxMaxCode = 1 << maxBits; - nBits = LzwConstants.INIT_BITS; - maxCode = (1 << nBits) - 1; - bitMask = maxCode; - oldCode = -1; - finChar = 0; - freeEnt = blockMode ? TBL_FIRST : 256; - - tabPrefix = new int[1 << maxBits]; - tabSuffix = new byte[1 << maxBits]; - stack = new byte[1 << maxBits]; - stackP = stack.Length; - - for (int idx = 255; idx >= 0; idx--) - tabSuffix[idx] = (byte)idx; - } - - #region Stream Overrides - - /// - /// Gets a value indicating whether the current stream supports reading - /// - public override bool CanRead - { - get { return baseInputStream.CanRead; } - } - - /// - /// Gets a value of false indicating seeking is not supported for this stream. - /// - public override bool CanSeek - { - get { return false; } - } - - /// - /// Gets a value of false indicating that this stream is not writeable. - /// - public override bool CanWrite - { - get { return false; } - } - - /// - /// A value representing the length of the stream in bytes. - /// - public override long Length - { - get { return got; } - } - - /// - /// The current position within the stream. - /// Throws a NotSupportedException when attempting to set the position - /// - /// Attempting to set the position - public override long Position - { - get { return baseInputStream.Position; } - set { throw new NotSupportedException("InflaterInputStream Position not supported"); } - } - - /// - /// Flushes the baseInputStream - /// - public override void Flush() - { - baseInputStream.Flush(); - } - - /// - /// Sets the position within the current stream - /// Always throws a NotSupportedException - /// - /// The relative offset to seek to. - /// The defining where to seek from. - /// The new position in the stream. - /// Any access - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException("Seek not supported"); - } - - /// - /// Set the length of the current stream - /// Always throws a NotSupportedException - /// - /// The new length value for the stream. - /// Any access - public override void SetLength(long value) - { - throw new NotSupportedException("InflaterInputStream SetLength not supported"); - } - - /// - /// Writes a sequence of bytes to stream and advances the current position - /// This method always throws a NotSupportedException - /// - /// The buffer containing data to write. - /// The offset of the first byte to write. - /// The number of bytes to write. - /// Any access - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException("InflaterInputStream Write not supported"); - } - - /// - /// Writes one byte to the current stream and advances the current position - /// Always throws a NotSupportedException - /// - /// The byte to write. - /// Any access - public override void WriteByte(byte value) - { - throw new NotSupportedException("InflaterInputStream WriteByte not supported"); - } - - /// - /// Closes the input stream. When - /// is true the underlying stream is also closed. - /// - protected override void Dispose(bool disposing) - { - if (!isClosed) - { - isClosed = true; - if (IsStreamOwner) - { - baseInputStream.Dispose(); - } - } - } - - #endregion Stream Overrides - - #region Instance Fields - - private Stream baseInputStream; - - /// - /// Flag indicating wether this instance has been closed or not. - /// - private bool isClosed; - - private readonly byte[] one = new byte[1]; - private bool headerParsed; - - // string table stuff - private const int TBL_CLEAR = 0x100; - - private const int TBL_FIRST = TBL_CLEAR + 1; - - private int[] tabPrefix = new int[0]; // - private byte[] tabSuffix = new byte[0]; // - private readonly int[] zeros = new int[256]; - private byte[] stack = new byte[0]; // - - // various state - private bool blockMode; - - private int nBits; - private int maxBits; - private int maxMaxCode; - private int maxCode; - private int bitMask; - private int oldCode; - private byte finChar; - private int stackP; - private int freeEnt; - - // input buffer - private readonly byte[] data = new byte[1024 * 8]; - - private int bitPos; - private int end; - private int got; - private bool eof; - private const int EXTRA = 64; - - #endregion Instance Fields - } -} diff --git a/src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs b/src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs index d4e91921..3b2d22ba 100644 --- a/src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs +++ b/src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs @@ -22,7 +22,7 @@ internal class ModelPpm } } - public SubAllocator SubAlloc { get; } = new(); + public SubAllocator SubAlloc { get; } = new SubAllocator(); public virtual See2Context DummySee2Cont => _dummySee2Cont; @@ -137,34 +137,34 @@ internal class ModelPpm // 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'" - private readonly State _tempState1 = new(null); + private readonly State _tempState1 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempState2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly State _tempState2 = new(null); + private readonly State _tempState2 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempState3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly State _tempState3 = new(null); + private readonly State _tempState3 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempState4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly State _tempState4 = new(null); + private readonly State _tempState4 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly StateRef _tempStateRef1 = new(); + private readonly StateRef _tempStateRef1 = new StateRef(); //UPGRADE_NOTE: Final was removed from the declaration of 'tempStateRef2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly StateRef _tempStateRef2 = new(); + private readonly StateRef _tempStateRef2 = new StateRef(); //UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext1 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly PpmContext _tempPpmContext1 = new(null); + private readonly PpmContext _tempPpmContext1 = new PpmContext(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly PpmContext _tempPpmContext2 = new(null); + private readonly PpmContext _tempPpmContext2 = new PpmContext(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly PpmContext _tempPpmContext3 = new(null); + private readonly PpmContext _tempPpmContext3 = new PpmContext(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempPPMContext4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly PpmContext _tempPpmContext4 = new(null); + private readonly PpmContext _tempPpmContext4 = new PpmContext(null); //UPGRADE_NOTE: Final was removed from the declaration of 'ps '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" private readonly int[] _ps = new int[MAX_O]; diff --git a/src/SharpCompress/Compressors/PPMd/H/PPMContext.cs b/src/SharpCompress/Compressors/PPMd/H/PPMContext.cs index e4f98c71..ab00615d 100644 --- a/src/SharpCompress/Compressors/PPMd/H/PPMContext.cs +++ b/src/SharpCompress/Compressors/PPMd/H/PPMContext.cs @@ -64,19 +64,19 @@ internal class PpmContext : Pointer // 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'" - private readonly State _tempState1 = new(null); + private readonly State _tempState1 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempState2 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly State _tempState2 = new(null); + private readonly State _tempState2 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempState3 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly State _tempState3 = new(null); + private readonly State _tempState3 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempState4 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly State _tempState4 = new(null); + private readonly State _tempState4 = new State(null); //UPGRADE_NOTE: Final was removed from the declaration of 'tempState5 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - private readonly State _tempState5 = new(null); + private readonly State _tempState5 = new State(null); private PpmContext _tempPpmContext; //UPGRADE_NOTE: Final was removed from the declaration of 'ps '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" diff --git a/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs b/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs index c4d8aa4b..7b677a93 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs @@ -395,8 +395,10 @@ internal class Allocator unitCountDifference -= unitCount; } - _memoryNodes[UNITS_TO_INDEX[unitCountDifference - 1]] - .Insert(newPointer, unitCountDifference); + _memoryNodes[UNITS_TO_INDEX[unitCountDifference - 1]].Insert( + newPointer, + unitCountDifference + ); } private void GlueFreeBlocks() @@ -455,11 +457,10 @@ internal class Allocator if (INDEX_TO_UNITS[index] != unitCount) { var unitCountDifference = unitCount - INDEX_TO_UNITS[--index]; - _memoryNodes[unitCountDifference - 1] - .Insert( - memoryNode0 + (unitCount - unitCountDifference), - unitCountDifference - ); + _memoryNodes[unitCountDifference - 1].Insert( + memoryNode0 + (unitCount - unitCountDifference), + unitCountDifference + ); } _memoryNodes[index].Insert(memoryNode0, INDEX_TO_UNITS[index]); diff --git a/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs b/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs index c8b411d8..5e978c5c 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs @@ -27,7 +27,7 @@ internal struct MemoryNode { public uint _address; public byte[] _memory; - public static readonly MemoryNode ZERO = new(0, null); + public static readonly MemoryNode ZERO = new MemoryNode(0, null); public const int SIZE = 12; /// @@ -64,7 +64,7 @@ internal struct MemoryNode public MemoryNode Next { get => - new( + new MemoryNode( _memory[_address + 4] | (((uint)_memory[_address + 5]) << 8) | (((uint)_memory[_address + 6]) << 16) @@ -150,7 +150,7 @@ internal struct MemoryNode /// /// public static implicit operator MemoryNode(Pointer pointer) => - new(pointer._address, pointer._memory); + new MemoryNode(pointer._address, pointer._memory); /// /// Allow pointer-like addition on a memory node. diff --git a/src/SharpCompress/Compressors/PPMd/I1/Model.cs b/src/SharpCompress/Compressors/PPMd/I1/Model.cs index 9a1d090f..786cb0e7 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/Model.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/Model.cs @@ -866,8 +866,7 @@ internal partial class Model ); } else if ( - (currentContext.SummaryFrequency += 4) - > 128 + (4 * currentContext.NumberStatistics) + (currentContext.SummaryFrequency += 4) > 128 + (4 * currentContext.NumberStatistics) ) { Refresh((uint)((currentContext.NumberStatistics + 2) >> 1), true, currentContext); diff --git a/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs b/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs index d1a89545..72c557ba 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs @@ -22,7 +22,7 @@ internal struct Pointer { public uint _address; public byte[] _memory; - public static readonly Pointer ZERO = new(0, null); + public static readonly Pointer ZERO = new Pointer(0, null); public const int SIZE = 1; /// @@ -69,7 +69,7 @@ internal struct Pointer /// /// public static implicit operator Pointer(MemoryNode memoryNode) => - new(memoryNode._address, memoryNode._memory); + new Pointer(memoryNode._address, memoryNode._memory); /// /// Allow a to be implicitly converted to a . @@ -77,14 +77,15 @@ internal struct Pointer /// /// public static implicit operator Pointer(Model.PpmContext context) => - new(context._address, context._memory); + new Pointer(context._address, context._memory); /// /// Allow a to be implicitly converted to a . /// /// /// - public static implicit operator Pointer(PpmState state) => new(state._address, state._memory); + public static implicit operator Pointer(PpmState state) => + new Pointer(state._address, state._memory); /// /// Increase the address of a pointer by the given number of bytes. diff --git a/src/SharpCompress/Compressors/PPMd/I1/PpmContext.cs b/src/SharpCompress/Compressors/PPMd/I1/PpmContext.cs index 701039c2..a37d278d 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/PpmContext.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/PpmContext.cs @@ -21,7 +21,7 @@ internal partial class Model { public uint _address; public byte[] _memory; - public static readonly PpmContext ZERO = new(0, null); + public static readonly PpmContext ZERO = new PpmContext(0, null); public const int SIZE = 12; /// @@ -70,7 +70,7 @@ internal partial class Model public PpmState Statistics { get => - new( + new PpmState( _memory[_address + 4] | (((uint)_memory[_address + 5]) << 8) | (((uint)_memory[_address + 6]) << 16) @@ -92,7 +92,7 @@ internal partial class Model public PpmContext Suffix { get => - new( + new PpmContext( _memory[_address + 8] | (((uint)_memory[_address + 9]) << 8) | (((uint)_memory[_address + 10]) << 16) @@ -133,7 +133,7 @@ internal partial class Model /// /// /// - public PpmState FirstState => new(_address + 2, _memory); + public PpmState FirstState => new PpmState(_address + 2, _memory); /// /// Gets or sets the symbol of the first PPM state. This is provided for convenience. The same @@ -164,7 +164,7 @@ internal partial class Model public PpmContext FirstStateSuccessor { get => - new( + new PpmContext( _memory[_address + 4] | (((uint)_memory[_address + 5]) << 8) | (((uint)_memory[_address + 6]) << 16) @@ -186,7 +186,7 @@ internal partial class Model /// /// public static implicit operator PpmContext(Pointer pointer) => - new(pointer._address, pointer._memory); + new PpmContext(pointer._address, pointer._memory); /// /// Allow pointer-like addition on a PPM context. diff --git a/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs b/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs index 02e79a34..757afd00 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs @@ -19,7 +19,7 @@ internal struct PpmState { public uint _address; public byte[] _memory; - public static readonly PpmState ZERO = new(0, null); + public static readonly PpmState ZERO = new PpmState(0, null); public const int SIZE = 6; /// @@ -55,7 +55,7 @@ internal struct PpmState public Model.PpmContext Successor { get => - new( + new Model.PpmContext( _memory[_address + 2] | (((uint)_memory[_address + 3]) << 8) | (((uint)_memory[_address + 4]) << 16) @@ -77,7 +77,7 @@ internal struct PpmState /// /// /// - public PpmState this[int offset] => new((uint)(_address + (offset * SIZE)), _memory); + public PpmState this[int offset] => new PpmState((uint)(_address + (offset * SIZE)), _memory); /// /// Allow a pointer to be implicitly converted to a PPM state. @@ -85,7 +85,7 @@ internal struct PpmState /// /// public static implicit operator PpmState(Pointer pointer) => - new(pointer._address, pointer._memory); + new PpmState(pointer._address, pointer._memory); /// /// Allow pointer-like addition on a PPM state. diff --git a/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs b/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs index eda9c765..1e4adfde 100644 --- a/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs +++ b/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs @@ -128,9 +128,9 @@ internal sealed class MultiVolumeReadOnlyStream : Stream public override bool CanWrite => false; - public byte[] CurrentCrc { get; private set; } + public uint CurrentCrc { get; private set; } - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs deleted file mode 100644 index 7c897176..00000000 --- a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs +++ /dev/null @@ -1,305 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using SharpCompress.Common; -using SharpCompress.Common.Rar.Headers; - -namespace SharpCompress.Compressors.Rar; - -internal class RarBLAKE2spStream : RarStream -{ - private readonly MultiVolumeReadOnlyStream readStream; - private readonly bool disableCRCCheck; - - const uint BLAKE2S_NUM_ROUNDS = 10; - const uint BLAKE2S_FINAL_FLAG = (~(uint)0); - const int BLAKE2S_BLOCK_SIZE = 64; - const int BLAKE2S_DIGEST_SIZE = 32; - const int BLAKE2SP_PARALLEL_DEGREE = 8; - const uint BLAKE2S_INIT_IV_SIZE = 8; - - static readonly UInt32[] k_BLAKE2S_IV = - { - 0x6A09E667U, - 0xBB67AE85U, - 0x3C6EF372U, - 0xA54FF53AU, - 0x510E527FU, - 0x9B05688CU, - 0x1F83D9ABU, - 0x5BE0CD19U - }; - - static readonly byte[][] k_BLAKE2S_Sigma = - { - new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, - new byte[] { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, - new byte[] { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, - new byte[] { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, - new byte[] { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, - new byte[] { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, - new byte[] { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, - new byte[] { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, - new byte[] { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, - new byte[] { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, - }; - - internal class BLAKE2S - { - internal UInt32[] h; - internal UInt32[] t; - internal UInt32[] f; - internal byte[] b; - internal int bufferPosition; - internal UInt32 lastNodeFlag; - UInt32[] dummy; - - public BLAKE2S() - { - h = new uint[BLAKE2S_INIT_IV_SIZE]; - t = new uint[2]; - f = new uint[2]; - b = new byte[BLAKE2S_BLOCK_SIZE]; - dummy = new uint[2]; - } - }; - - internal class BLAKE2SP - { - internal BLAKE2S[] S; - internal int bufferPosition; - - public BLAKE2SP() - { - S = new BLAKE2S[BLAKE2SP_PARALLEL_DEGREE]; - for (var i = 0; i < S.Length; i++) - { - S[i] = new BLAKE2S(); - } - } - }; - - BLAKE2SP _blake2sp; - - byte[] _hash = { }; - - public RarBLAKE2spStream( - IRarUnpack unpack, - FileHeader fileHeader, - MultiVolumeReadOnlyStream readStream - ) - : base(unpack, fileHeader, readStream) - { - this.readStream = readStream; - disableCRCCheck = fileHeader.IsEncrypted; - _hash = fileHeader.FileCrc; - _blake2sp = new BLAKE2SP(); - ResetCrc(); - } - - public byte[] GetCrc() => _hash; - - internal void ResetCrc(BLAKE2S hash) - { - for (UInt32 j = 0; j < BLAKE2S_INIT_IV_SIZE; j++) - { - hash.h[j] = k_BLAKE2S_IV[j]; - } - hash.t[0] = 0; - hash.t[1] = 0; - hash.f[0] = 0; - hash.f[1] = 0; - hash.bufferPosition = 0; - hash.lastNodeFlag = 0; - } - - internal void G( - ref UInt32[] m, - ref byte[] sigma, - int i, - ref UInt32 a, - ref UInt32 b, - ref UInt32 c, - ref UInt32 d - ) - { - a += b + m[sigma[2 * i]]; - d ^= a; - d = (d >> 16) | (d << 16); - c += d; - b ^= c; - b = (b >> 12) | (b << 20); - - a += b + m[sigma[2 * i + 1]]; - d ^= a; - d = (d >> 8) | (d << 24); - c += d; - b ^= c; - b = (b >> 7) | (b << 25); - } - - internal void Compress(BLAKE2S hash) - { - var m = new UInt32[16]; - var v = new UInt32[16]; - - for (var i = 0; i < 16; i++) - { - m[i] = BitConverter.ToUInt32(hash.b, i * 4); - } - - for (var i = 0; i < 8; i++) - { - v[i] = hash.h[i]; - } - - v[8] = k_BLAKE2S_IV[0]; - v[9] = k_BLAKE2S_IV[1]; - v[10] = k_BLAKE2S_IV[2]; - v[11] = k_BLAKE2S_IV[3]; - - v[12] = hash.t[0] ^ k_BLAKE2S_IV[4]; - v[13] = hash.t[1] ^ k_BLAKE2S_IV[5]; - v[14] = hash.f[0] ^ k_BLAKE2S_IV[6]; - v[15] = hash.f[1] ^ k_BLAKE2S_IV[7]; - - for (var r = 0; r < BLAKE2S_NUM_ROUNDS; r++) - { - ref byte[] sigma = ref k_BLAKE2S_Sigma[r]; - - G(ref m, ref sigma, 0, ref v[0], ref v[4], ref v[8], ref v[12]); - G(ref m, ref sigma, 1, ref v[1], ref v[5], ref v[9], ref v[13]); - G(ref m, ref sigma, 2, ref v[2], ref v[6], ref v[10], ref v[14]); - G(ref m, ref sigma, 3, ref v[3], ref v[7], ref v[11], ref v[15]); - G(ref m, ref sigma, 4, ref v[0], ref v[5], ref v[10], ref v[15]); - G(ref m, ref sigma, 5, ref v[1], ref v[6], ref v[11], ref v[12]); - G(ref m, ref sigma, 6, ref v[2], ref v[7], ref v[8], ref v[13]); - G(ref m, ref sigma, 7, ref v[3], ref v[4], ref v[9], ref v[14]); - } - - for (var i = 0; i < 8; i++) - { - hash.h[i] ^= v[i] ^ v[i + 8]; - } - } - - internal void Update(BLAKE2S hash, ReadOnlySpan data, int size) - { - var i = 0; - while (size != 0) - { - var pos = hash.bufferPosition; - var reminder = BLAKE2S_BLOCK_SIZE - pos; - - if (size <= reminder) - { - data.Slice(i, size).CopyTo(new Span(hash.b, pos, size)); - hash.bufferPosition += size; - return; - } - data.Slice(i, reminder).CopyTo(new Span(hash.b, pos, reminder)); - hash.t[0] += BLAKE2S_BLOCK_SIZE; - hash.t[1] += hash.t[0] < BLAKE2S_BLOCK_SIZE ? 1U : 0U; - Compress(hash); - hash.bufferPosition = 0; - i += reminder; - size -= reminder; - } - } - - internal byte[] Final(BLAKE2S hash) - { - hash.t[0] += (uint)hash.bufferPosition; - hash.t[1] += hash.t[0] < hash.bufferPosition ? 1U : 0U; - hash.f[0] = BLAKE2S_FINAL_FLAG; - hash.f[1] = hash.lastNodeFlag; - Array.Clear(hash.b, hash.bufferPosition, BLAKE2S_BLOCK_SIZE - hash.bufferPosition); - Compress(hash); - - var mem = new MemoryStream(); - - for (var i = 0; i < 8; i++) - { - mem.Write(BitConverter.GetBytes(hash.h[i]), 0, 4); - } - - return mem.ToArray(); - } - - public void ResetCrc() - { - _blake2sp.bufferPosition = 0; - - for (UInt32 i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) - { - _blake2sp.S[i].bufferPosition = 0; - ResetCrc(_blake2sp.S[i]); - _blake2sp.S[i].h[0] ^= (BLAKE2S_DIGEST_SIZE | BLAKE2SP_PARALLEL_DEGREE << 16 | 2 << 24); - _blake2sp.S[i].h[2] ^= i; - _blake2sp.S[i].h[3] ^= (BLAKE2S_DIGEST_SIZE << 24); - } - - _blake2sp.S[BLAKE2SP_PARALLEL_DEGREE - 1].lastNodeFlag = BLAKE2S_FINAL_FLAG; - } - - internal void Update(BLAKE2SP hash, ReadOnlySpan data, int size) - { - var i = 0; - var pos = hash.bufferPosition; - while (size != 0) - { - var index = pos / BLAKE2S_BLOCK_SIZE; - var reminder = BLAKE2S_BLOCK_SIZE - (pos & (BLAKE2S_BLOCK_SIZE - 1)); - if (reminder > size) - { - reminder = size; - } - // Update(hash.S[index], data, size); - Update(hash.S[index], data.Slice(i, reminder), reminder); - size -= reminder; - i += reminder; - pos += reminder; - pos &= (BLAKE2S_BLOCK_SIZE * (BLAKE2SP_PARALLEL_DEGREE - 1)); - } - hash.bufferPosition = pos; - } - - internal byte[] Final(BLAKE2SP hash) - { - var h = new BLAKE2S(); - - ResetCrc(h); - h.h[0] ^= (BLAKE2S_DIGEST_SIZE | BLAKE2SP_PARALLEL_DEGREE << 16 | 2 << 24); - h.h[3] ^= (1 << 16 | BLAKE2S_DIGEST_SIZE << 24); - h.lastNodeFlag = BLAKE2S_FINAL_FLAG; - - for (var i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) - { - var digest = Final(_blake2sp.S[i]); - Update(h, digest, BLAKE2S_DIGEST_SIZE); - } - - return Final(h); - } - - public override int Read(byte[] buffer, int offset, int count) - { - var result = base.Read(buffer, offset, count); - if (result != 0) - { - Update(_blake2sp, new ReadOnlySpan(buffer, offset, result), result); - } - else - { - _hash = Final(_blake2sp); - if (!disableCRCCheck && !(GetCrc().SequenceEqual(readStream.CurrentCrc)) && count != 0) - { - // NOTE: we use the last FileHeader in a multipart volume to check CRC - throw new InvalidFormatException("file crc mismatch"); - } - } - - return result; - } -} diff --git a/src/SharpCompress/Compressors/Rar/RarCrcStream.cs b/src/SharpCompress/Compressors/Rar/RarCrcStream.cs index ce42a4bd..98d50b00 100644 --- a/src/SharpCompress/Compressors/Rar/RarCrcStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarCrcStream.cs @@ -1,4 +1,3 @@ -using System; using SharpCompress.Common; using SharpCompress.Common.Rar.Headers; @@ -8,7 +7,6 @@ internal class RarCrcStream : RarStream { private readonly MultiVolumeReadOnlyStream readStream; private uint currentCrc; - private readonly bool disableCRC; public RarCrcStream( IRarUnpack unpack, @@ -18,7 +16,6 @@ internal class RarCrcStream : RarStream : base(unpack, fileHeader, readStream) { this.readStream = readStream; - disableCRC = fileHeader.IsEncrypted; ResetCrc(); } @@ -33,11 +30,7 @@ internal class RarCrcStream : RarStream { currentCrc = RarCRC.CheckCrc(currentCrc, buffer, offset, result); } - else if ( - !disableCRC - && GetCrc() != BitConverter.ToUInt32(readStream.CurrentCrc, 0) - && count != 0 - ) + else if (GetCrc() != readStream.CurrentCrc && count != 0) { // NOTE: we use the last FileHeader in a multipart volume to check CRC throw new InvalidFormatException("file crc mismatch"); diff --git a/src/SharpCompress/Compressors/Rar/RarStream.cs b/src/SharpCompress/Compressors/Rar/RarStream.cs index bf5d3209..0bc2e054 100644 --- a/src/SharpCompress/Compressors/Rar/RarStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarStream.cs @@ -14,7 +14,7 @@ internal class RarStream : Stream private bool fetch; - private byte[] tmpBuffer = BufferPool.Rent(65536); + private byte[] tmpBuffer = new byte[65536]; private int tmpOffset; private int tmpCount; @@ -40,11 +40,6 @@ internal class RarStream : Stream { if (!isDisposed) { - if (disposing) - { - BufferPool.Return(this.tmpBuffer); - this.tmpBuffer = null; - } isDisposed = true; base.Dispose(disposing); readStream.Dispose(); @@ -91,13 +86,6 @@ internal class RarStream : Stream fetch = false; } _position += outTotal; - if (count > 0 && outTotal == 0 && _position != Length) - { - // sanity check, eg if we try to decompress a redir entry - throw new InvalidOperationException( - $"unpacked file size does not match header: expected {Length} found {_position}" - ); - } return outTotal; } @@ -123,7 +111,16 @@ internal class RarStream : Stream } if (count > 0) { - EnsureBufferCapacity(count); + if (tmpBuffer.Length < tmpCount + count) + { + var newBuffer = new byte[ + tmpBuffer.Length * 2 > tmpCount + count + ? tmpBuffer.Length * 2 + : tmpCount + count + ]; + Buffer.BlockCopy(tmpBuffer, 0, newBuffer, 0, tmpCount); + tmpBuffer = newBuffer; + } Buffer.BlockCopy(buffer, offset, tmpBuffer, tmpCount, count); tmpCount += count; tmpOffset = 0; @@ -134,20 +131,4 @@ internal class RarStream : Stream unpack.Suspended = false; } } - - private void EnsureBufferCapacity(int count) - { - if (this.tmpBuffer.Length < this.tmpCount + count) - { - var newLength = - this.tmpBuffer.Length * 2 > this.tmpCount + count - ? this.tmpBuffer.Length * 2 - : this.tmpCount + count; - var newBuffer = BufferPool.Rent(newLength); - Buffer.BlockCopy(this.tmpBuffer, 0, newBuffer, 0, this.tmpCount); - var oldBuffer = this.tmpBuffer; - this.tmpBuffer = newBuffer; - BufferPool.Return(oldBuffer); - } - } } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs index e6d4153d..2ca62d6b 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs @@ -52,19 +52,19 @@ internal sealed partial class Unpack : BitInput, IRarUnpack public int PpmEscChar { get; set; } - private readonly ModelPpm ppm = new(); + private readonly ModelPpm ppm = new ModelPpm(); - private readonly RarVM rarVM = new(); + private readonly RarVM rarVM = new RarVM(); // Filters code, one entry per filter - private readonly List filters = new(); + private readonly List filters = new List(); // Filters stack, several entrances of same filter are possible - private readonly List prgStack = new(); + private readonly List prgStack = new List(); // lengths of preceding blocks, one length per filter. Used to reduce size // required to write block length if lengths are repeating - private readonly List oldFilterLengths = new(); + private readonly List oldFilterLengths = new List(); private int lastFilter; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs index 3a5d008d..15b980da 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs @@ -25,15 +25,15 @@ internal partial class Unpack private readonly AudioVariables[] AudV = new AudioVariables[4]; - private readonly LitDecode LD = new(); + private readonly LitDecode LD = new LitDecode(); - private readonly DistDecode DD = new(); + private readonly DistDecode DD = new DistDecode(); - private readonly LowDistDecode LDD = new(); + private readonly LowDistDecode LDD = new LowDistDecode(); - private readonly RepDecode RD = new(); + private readonly RepDecode RD = new RepDecode(); - private readonly BitDecode BD = new(); + private readonly BitDecode BD = new BitDecode(); private static readonly int[] LDecode = { diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs index b501337b..09f5ee8f 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs @@ -1,4 +1,5 @@ using System; + using SharpCompress.Compressors.Rar.VM; namespace SharpCompress.Compressors.Rar.UnpackV1; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/FragmentedWindow.unpack50frag_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/FragmentedWindow.unpack50frag_cpp.cs index a9a6f280..bfa69829 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/FragmentedWindow.unpack50frag_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/FragmentedWindow.unpack50frag_cpp.cs @@ -1,6 +1,5 @@ #nullable disable -using System; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -8,6 +7,7 @@ using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif +using System; namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs index 22fdc746..53db46d2 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs @@ -1,13 +1,13 @@ -using System; -using System.IO; -using SharpCompress.Common.Rar.Headers; -#if !Rar2017_64bit +#if !Rar2017_64bit using size_t = System.UInt32; #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif +using System; +using System.IO; +using SharpCompress.Common.Rar.Headers; namespace SharpCompress.Compressors.Rar.UnpackV2017; @@ -67,15 +67,15 @@ internal partial class Unpack : IRarUnpack private void UnstoreFile() { - Span b = stackalloc byte[(int)Math.Min(0x10000, DestUnpSize)]; + var b = new byte[0x10000]; do { - var n = readStream.Read(b); + var n = readStream.Read(b, 0, (int)Math.Min(b.Length, DestUnpSize)); if (n == 0) { break; } - writeStream.Write(b.Slice(0, n)); + writeStream.Write(b, 0, n); DestUnpSize -= n; } while (!Suspended); } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs index 62fb3c9d..03614dde 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs @@ -1,12 +1,10 @@ -using uint32 = System.UInt32; - -/*#if !Rar2017_64bit +#if !Rar2017_64bit #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; -#endif*/ - +#endif +using uint32 = System.UInt32; namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs index 51dbff0b..b92af290 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs @@ -1,14 +1,12 @@ -using System; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; -using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local; - -/*#if !Rar2017_64bit +#if !Rar2017_64bit #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; -#endif*/ - +#endif +using System; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local; namespace SharpCompress.Compressors.Rar.UnpackV2017; @@ -373,8 +371,8 @@ internal partial class Unpack private bool ReadTables20() { - Span BitLength = stackalloc byte[checked((int)BC20)]; - Span Table = stackalloc byte[checked((int)MC20 * 4)]; + var BitLength = new byte[BC20]; + var Table = new byte[MC20 * 4]; if (Inp.InAddr > ReadTop - 25) { if (!UnpReadBuf()) @@ -410,13 +408,13 @@ internal partial class Unpack TableSize = NC20 + DC20 + RC20; } - for (int I = 0; I < checked((int)BC20); I++) + for (uint I = 0; I < BC20; I++) { BitLength[I] = (byte)(Inp.getbits() >> 12); Inp.addbits(4); } MakeDecodeTables(BitLength, 0, BlockTables.BD, BC20); - for (int I = 0; I < checked((int)TableSize); ) + for (uint I = 0; I < TableSize; ) { if (Inp.InAddr > ReadTop - 5) { @@ -487,7 +485,8 @@ internal partial class Unpack MakeDecodeTables(Table, (int)NC20, BlockTables.DD, DC20); MakeDecodeTables(Table, (int)(NC20 + DC20), BlockTables.RD, RC20); } - Table.CopyTo(this.UnpOldTable20); + //x memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20)); + Array.Copy(Table, UnpOldTable20, UnpOldTable20.Length); return true; } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs index 143e3d31..f85921bd 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs @@ -1,9 +1,5 @@ -#nullable disable +#nullable disable -using System; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; -using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; -using int64 = System.Int64; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -11,6 +7,11 @@ using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif +using int64 = System.Int64; + +using System; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; namespace SharpCompress.Compressors.Rar.UnpackV2017; @@ -530,6 +531,7 @@ internal partial class Unpack { case FILTER_E8: case FILTER_E8E9: + { var FileOffset = (uint)WrittenFileSize; @@ -568,6 +570,7 @@ internal partial class Unpack } return SrcData; case FILTER_ARM: + { var FileOffset = (uint)WrittenFileSize; // DataSize is unsigned, so we use "CurPos+3" and not "DataSize-3" @@ -750,8 +753,8 @@ internal partial class Unpack } } - Span BitLength = stackalloc byte[checked((int)BC)]; - for (int I = 0; I < BC; I++) + var BitLength = new byte[BC]; + for (uint I = 0; I < BC; I++) { uint Length = (byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); @@ -782,9 +785,9 @@ internal partial class Unpack MakeDecodeTables(BitLength, 0, Tables.BD, BC); - Span Table = stackalloc byte[checked((int)HUFF_TABLE_SIZE)]; - const int TableSize = checked((int)HUFF_TABLE_SIZE); - for (int I = 0; I < TableSize; ) + var Table = new byte[HUFF_TABLE_SIZE]; + const uint TableSize = HUFF_TABLE_SIZE; + for (uint I = 0; I < TableSize; ) { if (!Inp.ExternalBuffer && Inp.InAddr > ReadTop - 5) { diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs index 9c6cbeb0..f9a74440 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs @@ -1,9 +1,5 @@ #nullable disable -using System; -using SharpCompress.Common; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; -using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -12,6 +8,11 @@ using nuint = System.UInt64; using size_t = System.UInt64; #endif +using System; +using SharpCompress.Common; +using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; + namespace SharpCompress.Compressors.Rar.UnpackV2017; internal sealed partial class Unpack : BitInput @@ -29,12 +30,12 @@ internal sealed partial class Unpack : BitInput Suspended = false; UnpAllBuf = false; UnpSomeRead = false; - /*#if RarV2017_RAR_SMP - MaxUserThreads = 1; - UnpThreadPool = CreateThreadPool(); - ReadBufMT = null; - UnpThreadData = null; - #endif*/ +#if RarV2017_RAR_SMP + MaxUserThreads = 1; + UnpThreadPool = CreateThreadPool(); + ReadBufMT = null; + UnpThreadData = null; +#endif MaxWinSize = 0; MaxWinMask = 0; @@ -198,21 +199,21 @@ internal sealed partial class Unpack : BitInput break; #endif case 50: // RAR 5.0 compression algorithm. - /*#if RarV2017_RAR_SMP - if (MaxUserThreads > 1) - { - // We do not use the multithreaded unpack routine to repack RAR archives - // in 'suspended' mode, because unlike the single threaded code it can - // write more than one dictionary for same loop pass. So we would need - // larger buffers of unknown size. Also we do not support multithreading - // in fragmented window mode. - if (!Fragmented) - { - Unpack5MT(Solid); - break; - } - } - #endif*/ +#if RarV2017_RAR_SMP + if (MaxUserThreads > 1) + { + // We do not use the multithreaded unpack routine to repack RAR archives + // in 'suspended' mode, because unlike the single threaded code it can + // write more than one dictionary for same loop pass. So we would need + // larger buffers of unknown size. Also we do not support multithreading + // in fragmented window mode. + if (!Fragmented) + { + Unpack5MT(Solid); + break; + } + } +#endif Unpack5(Solid); break; #if !Rar2017_NOSTRICT @@ -259,7 +260,7 @@ internal sealed partial class Unpack : BitInput // LengthTable contains the length in bits for every element of alphabet. // Dec is the structure to decode Huffman code/ // Size is size of length table and DecodeNum field in Dec structure, - private void MakeDecodeTables(Span LengthTable, int offset, DecodeTable Dec, uint Size) + private void MakeDecodeTables(byte[] LengthTable, int offset, DecodeTable Dec, uint Size) { // Size of alphabet and DecodePos array. Dec.MaxNum = Size; @@ -269,7 +270,7 @@ internal sealed partial class Unpack : BitInput //memset(LengthCount,0,sizeof(LengthCount)); for (size_t I = 0; I < Size; I++) { - LengthCount[LengthTable[checked((int)(offset + I))] & 0xf]++; + LengthCount[LengthTable[offset + I] & 0xf]++; } // We must not calculate the number of zero length codes. @@ -318,7 +319,7 @@ internal sealed partial class Unpack : BitInput for (uint I = 0; I < Size; I++) { // Get the current bit length. - var _CurBitLength = (byte)(LengthTable[checked((int)(offset + I))] & 0xf); + var _CurBitLength = (byte)(LengthTable[offset + I] & 0xf); if (_CurBitLength != 0) { diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs index b81d75c4..584d0b51 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs @@ -1,12 +1,10 @@ -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; - -/*#if !Rar2017_64bit +#if !Rar2017_64bit #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; -#endif*/ - +#endif +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs index 3bba4c94..18cd9697 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; -using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; -using int64 = System.Int64; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -10,6 +5,12 @@ using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif +using int64 = System.Int64; + +using System.Collections.Generic; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; +using System; // TODO: REMOVE THIS... WIP #pragma warning disable 169 @@ -19,6 +20,8 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017; internal static class UnpackGlobal { + + // Maximum allowed number of compressed bits processed in quick mode. public const int MAX_QUICK_DECODE_BITS = 10; @@ -94,11 +97,11 @@ internal struct UnpackBlockHeader internal struct UnpackBlockTables { - public DecodeTable LD; // Decode literals. - public DecodeTable DD; // Decode distances. + public DecodeTable LD; // Decode literals. + public DecodeTable DD; // Decode distances. public DecodeTable LDD; // Decode lower bits of distances. - public DecodeTable RD; // Decode repeating distances. - public DecodeTable BD; // Decode bit lengths in Huffman table. + public DecodeTable RD; // Decode repeating distances. + public DecodeTable BD; // Decode bit lengths in Huffman table. public void Init() { @@ -110,7 +113,8 @@ internal struct UnpackBlockTables } }; -/*#if RarV2017_RAR_SMP + +#if RarV2017_RAR_SMP enum UNP_DEC_TYPE { UNPDT_LITERAL,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER }; @@ -157,7 +161,7 @@ if (Decoded!=NULL) free(Decoded); } }; -#endif*/ +#endif //struct UnpackFilter @@ -167,12 +171,12 @@ internal class UnpackFilter public uint BlockStart; public uint BlockLength; public byte Channels; - // uint Width; // byte PosR; public bool NextWindow; }; + //struct UnpackFilter30 internal class UnpackFilter30 { @@ -191,21 +195,15 @@ internal class UnpackFilter30 internal class AudioVariables // For RAR 2.0 archives only. { - public int K1, - K2, - K3, - K4, - K5; - public int D1, - D2, - D3, - D4; + public int K1, K2, K3, K4, K5; + public int D1, D2, D3, D4; public int LastDelta; public readonly uint[] Dif = new uint[11]; public uint ByteCount; public int LastChar; }; + // We can use the fragmented dictionary in case heap does not have the single // large enough memory block. It is slower than normal dictionary. internal partial class FragmentedWindow @@ -225,8 +223,10 @@ internal partial class FragmentedWindow //size_t GetBlockSize(size_t StartPos,size_t RequiredSize); }; + internal partial class Unpack { + //void Unpack5(bool Solid); //void Unpack5MT(bool Solid); //bool UnpReadBuf(); @@ -254,22 +254,22 @@ internal partial class Unpack //BitInput Inp; private BitInput Inp => this; // hopefully this gets inlined - /*#if RarV2017_RAR_SMP - void InitMT(); - bool UnpackLargeBlock(UnpackThreadData &D); - bool ProcessDecoded(UnpackThreadData &D); - - ThreadPool *UnpThreadPool; - UnpackThreadData *UnpThreadData; - uint MaxUserThreads; - byte *ReadBufMT; - #endif*/ +#if RarV2017_RAR_SMP +void InitMT(); +bool UnpackLargeBlock(UnpackThreadData &D); +bool ProcessDecoded(UnpackThreadData &D); + +ThreadPool *UnpThreadPool; +UnpackThreadData *UnpThreadData; +uint MaxUserThreads; +byte *ReadBufMT; +#endif private byte[] FilterSrcMemory = Array.Empty(); private byte[] FilterDstMemory = Array.Empty(); // Filters code, one entry per filter. - private readonly List Filters = new(); + private readonly List Filters = new List(); private readonly uint[] OldDist = new uint[4]; private uint OldDistPtr; @@ -279,8 +279,7 @@ internal partial class Unpack // array. In RAR3 last distance is always stored in OldDist[0]. private uint LastDist; - private size_t UnpPtr, - WrPtr; + private size_t UnpPtr, WrPtr; // Top border of read packed data. private int ReadTop; @@ -297,7 +296,7 @@ internal partial class Unpack private byte[] Window; - private readonly FragmentedWindow FragWindow = new(); + private readonly FragmentedWindow FragWindow = new FragmentedWindow(); private bool Fragmented; private int64 DestUnpSize; @@ -308,6 +307,7 @@ internal partial class Unpack private int64 WrittenFileSize; private bool FileExtracted; + /***************************** Unpack v 1.5 *********************************/ //void Unpack15(bool Solid); //void ShortLZ(); @@ -320,29 +320,12 @@ internal partial class Unpack //void CopyString15(uint Distance,uint Length); //uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab); - private readonly ushort[] ChSet = new ushort[256], - ChSetA = new ushort[256], - ChSetB = new ushort[256], - ChSetC = new ushort[256]; - private readonly byte[] NToPl = new byte[256], - NToPlB = new byte[256], - NToPlC = new byte[256]; - private uint FlagBuf, - AvrPlc, - AvrPlcB, - AvrLn1, - AvrLn2, - AvrLn3; - private int Buf60, - NumHuf, - StMode, - LCount, - FlagsCnt; - - private uint Nhfb, - Nlzb, - MaxDist3; + private readonly ushort[] ChSet = new ushort[256], ChSetA = new ushort[256], ChSetB = new ushort[256], ChSetC = new ushort[256]; + private readonly byte[] NToPl = new byte[256], NToPlB = new byte[256], NToPlC = new byte[256]; + private uint FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3; + private int Buf60, NumHuf, StMode, LCount, FlagsCnt; + private uint Nhfb, Nlzb, MaxDist3; /***************************** Unpack v 1.5 *********************************/ /***************************** Unpack v 2.0 *********************************/ @@ -352,11 +335,9 @@ internal partial class Unpack private readonly byte[] UnpOldTable20 = new byte[MC20 * 4]; private bool UnpAudioBlock; - private uint UnpChannels, - UnpCurChannel; + private uint UnpChannels, UnpCurChannel; private int UnpChannelDelta; - //void CopyString20(uint Length,uint Distance); //bool ReadTables20(); //void UnpWriteBuf20(); @@ -364,7 +345,6 @@ internal partial class Unpack //void ReadLastTables(); //byte DecodeAudio(int Delta); private AudioVariables[] AudV = new AudioVariables[4]; - /***************************** Unpack v 2.0 *********************************/ /***************************** Unpack v 3.0 *********************************/ @@ -383,8 +363,7 @@ internal partial class Unpack // because we can have a corrupt archive with one algorithm file // followed by another algorithm file with "solid" flag and we do not // want to reuse tables from one algorithm in another. - private bool TablesRead2, - TablesRead5; + private bool TablesRead2, TablesRead5; // Virtual machine to execute filters code. /*#if !RarV2017_RAR5ONLY @@ -393,26 +372,26 @@ internal partial class Unpack // Buffer to read VM filters code. We moved it here from AddVMCode // function to reduce time spent in BitInput constructor. - private readonly BitInput VMCodeInp = new(true); + private readonly BitInput VMCodeInp = new BitInput(true); // Filters code, one entry per filter. - private readonly List Filters30 = new(); + private readonly List Filters30 = new List(); // Filters stack, several entrances of same filter are possible. - private readonly List PrgStack = new(); + private readonly List PrgStack = new List(); // Lengths of preceding data blocks, one length of one last block // for every filter. Used to reduce the size required to write // the data block length if lengths are repeating. - private readonly List OldFilterLengths = new(); + private readonly List OldFilterLengths = new List(); - /*#if RarV2017_RAR_SMP - // More than 8 threads are unlikely to provide a noticeable gain - // for unpacking, but would use the additional memory. - void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);} - - void UnpackDecode(UnpackThreadData &D); - #endif*/ +#if RarV2017_RAR_SMP +// More than 8 threads are unlikely to provide a noticeable gain +// for unpacking, but would use the additional memory. +void SetThreads(uint Threads) {MaxUserThreads=Min(Threads,8);} + +void UnpackDecode(UnpackThreadData &D); +#endif private size_t MaxWinSize; private size_t MaxWinMask; diff --git a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs index f758b8a4..48b25c5c 100644 --- a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs +++ b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs @@ -228,6 +228,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_CMP: + { var value1 = (VMFlags)GetValue(cmd.IsByteMode, Mem, op1); var result = value1 - GetValue(cmd.IsByteMode, Mem, op2); @@ -246,6 +247,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_CMPB: + { var value1 = (VMFlags)GetValue(true, Mem, op1); var result = value1 - GetValue(true, Mem, op2); @@ -263,6 +265,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_CMPD: + { var value1 = (VMFlags)GetValue(false, Mem, op1); var result = value1 - GetValue(false, Mem, op2); @@ -280,6 +283,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_ADD: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var result = (int)( @@ -347,6 +351,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SUB: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var result = (int)( @@ -406,6 +411,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_INC: + { var result = (int)(GetValue(cmd.IsByteMode, Mem, op1) & (0xFFffFFffL + 1L)); if (cmd.IsByteMode) @@ -434,6 +440,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_DEC: + { var result = (int)(GetValue(cmd.IsByteMode, Mem, op1) & (0xFFffFFff - 1)); SetValue(cmd.IsByteMode, Mem, op1, result); @@ -456,6 +463,7 @@ internal sealed class RarVM : BitInput continue; case VMCommands.VM_XOR: + { var result = GetValue(cmd.IsByteMode, Mem, op1) ^ GetValue(cmd.IsByteMode, Mem, op2); @@ -467,6 +475,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_AND: + { var result = GetValue(cmd.IsByteMode, Mem, op1) & GetValue(cmd.IsByteMode, Mem, op2); @@ -478,6 +487,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_OR: + { var result = GetValue(cmd.IsByteMode, Mem, op1) | GetValue(cmd.IsByteMode, Mem, op2); @@ -489,6 +499,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_TEST: + { var result = GetValue(cmd.IsByteMode, Mem, op1) & GetValue(cmd.IsByteMode, Mem, op2); @@ -567,6 +578,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SHL: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -584,6 +596,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SHR: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -597,6 +610,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SAR: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -610,6 +624,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_NEG: + { var result = -GetValue(cmd.IsByteMode, Mem, op1); flags = (VMFlags)( @@ -630,6 +645,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_PUSHA: + { for (int i = 0, SP = R[7] - 4; i < regCount; i++, SP -= 4) { @@ -640,6 +656,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_POPA: + { for (int i = 0, SP = R[7]; i < regCount; i++, SP += 4) { @@ -667,6 +684,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_XCHG: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); SetValue(cmd.IsByteMode, Mem, op1, GetValue(cmd.IsByteMode, Mem, op2)); @@ -675,6 +693,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_MUL: + { var result = (int)( ( @@ -688,6 +707,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_DIV: + { var divider = GetValue(cmd.IsByteMode, Mem, op2); if (divider != 0) @@ -699,6 +719,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_ADC: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var FC = (int)(flags & VMFlags.VM_FC); @@ -728,6 +749,7 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SBB: + { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var FC = (int)(flags & VMFlags.VM_FC); @@ -1109,13 +1131,13 @@ internal sealed class RarVM : BitInput { VMStandardFilterSignature[] stdList = { - new(53, 0xad576887, VMStandardFilters.VMSF_E8), - new(57, 0x3cd7e57e, VMStandardFilters.VMSF_E8E9), - new(120, 0x3769893f, VMStandardFilters.VMSF_ITANIUM), - new(29, 0x0e06077d, VMStandardFilters.VMSF_DELTA), - new(149, 0x1c2c5dc8, VMStandardFilters.VMSF_RGB), - new(216, 0xbc85e701, VMStandardFilters.VMSF_AUDIO), - new(40, 0x46b9c560, VMStandardFilters.VMSF_UPCASE) + new VMStandardFilterSignature(53, 0xad576887, VMStandardFilters.VMSF_E8), + new VMStandardFilterSignature(57, 0x3cd7e57e, VMStandardFilters.VMSF_E8E9), + new VMStandardFilterSignature(120, 0x3769893f, VMStandardFilters.VMSF_ITANIUM), + new VMStandardFilterSignature(29, 0x0e06077d, VMStandardFilters.VMSF_DELTA), + new VMStandardFilterSignature(149, 0x1c2c5dc8, VMStandardFilters.VMSF_RGB), + new VMStandardFilterSignature(216, 0xbc85e701, VMStandardFilters.VMSF_AUDIO), + new VMStandardFilterSignature(40, 0x46b9c560, VMStandardFilters.VMSF_UPCASE) }; var CodeCRC = RarCRC.CheckCrc(0xffffffff, code, 0, code.Length) ^ 0xffffffff; for (var i = 0; i < stdList.Length; i++) @@ -1134,6 +1156,7 @@ internal sealed class RarVM : BitInput { case VMStandardFilters.VMSF_E8: case VMStandardFilters.VMSF_E8E9: + { var dataSize = R[4]; long fileOffset = R[6] & unchecked((int)0xFFffFFff); @@ -1188,6 +1211,7 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_ITANIUM: + { var dataSize = R[4]; long fileOffset = R[6] & unchecked((int)0xFFffFFff); @@ -1245,6 +1269,7 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_DELTA: + { var dataSize = R[4] & unchecked((int)0xFFffFFff); var channels = R[0] & unchecked((int)0xFFffFFff); @@ -1275,6 +1300,7 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_RGB: + { // byte *SrcData=Mem,*DestData=SrcData+DataSize; int dataSize = R[4], @@ -1340,6 +1366,7 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_AUDIO: + { int dataSize = R[4], channels = R[0]; @@ -1470,6 +1497,7 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_UPCASE: + { int dataSize = R[4], srcPos = 0, diff --git a/src/SharpCompress/Compressors/Rar/VM/VMPreparedProgram.cs b/src/SharpCompress/Compressors/Rar/VM/VMPreparedProgram.cs index f1f9e0aa..c0006e09 100644 --- a/src/SharpCompress/Compressors/Rar/VM/VMPreparedProgram.cs +++ b/src/SharpCompress/Compressors/Rar/VM/VMPreparedProgram.cs @@ -4,13 +4,13 @@ namespace SharpCompress.Compressors.Rar.VM; internal class VMPreparedProgram { - internal List Commands = new(); - internal List AltCommands = new(); + internal List Commands = new List(); + internal List AltCommands = new List(); public int CommandCount { get; set; } - internal List GlobalData = new(); - internal List StaticData = new(); + internal List GlobalData = new List(); + internal List StaticData = new List(); // static data contained in DB operators internal int[] InitR = new int[7]; diff --git a/src/SharpCompress/Compressors/Shrink/BitStream.cs b/src/SharpCompress/Compressors/Shrink/BitStream.cs deleted file mode 100644 index 949ee6c3..00000000 --- a/src/SharpCompress/Compressors/Shrink/BitStream.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SharpCompress.Compressors.Shrink -{ - internal class BitStream - { - private byte[] _src; - private int _srcLen; - private int _byteIdx; - private int _bitIdx; - private int _bitsLeft; - private ulong _bitBuffer; - private static uint[] _maskBits = new uint[17] - { - 0U, - 1U, - 3U, - 7U, - 15U, - 31U, - 63U, - (uint)sbyte.MaxValue, - (uint)byte.MaxValue, - 511U, - 1023U, - 2047U, - 4095U, - 8191U, - 16383U, - (uint)short.MaxValue, - (uint)ushort.MaxValue - }; - - public BitStream(byte[] src, int srcLen) - { - _src = src; - _srcLen = srcLen; - _byteIdx = 0; - _bitIdx = 0; - } - - public int BytesRead => (_byteIdx << 3) + _bitIdx; - - private int NextByte() - { - if (_byteIdx >= _srcLen) - { - return 0; - } - - return _src[_byteIdx++]; - } - - public int NextBits(int nbits) - { - var result = 0; - if (nbits > _bitsLeft) - { - int num; - while (_bitsLeft <= 24 && (num = NextByte()) != 1234) - { - _bitBuffer |= (ulong)num << _bitsLeft; - _bitsLeft += 8; - } - } - result = (int)((long)_bitBuffer & (long)_maskBits[nbits]); - _bitBuffer >>= nbits; - _bitsLeft -= nbits; - return result; - } - - public bool Advance(int count) - { - if (_byteIdx > _srcLen) - { - return false; - } - return true; - } - } -} diff --git a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs deleted file mode 100644 index 6ad5ab7c..00000000 --- a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs +++ /dev/null @@ -1,431 +0,0 @@ -using System; - -namespace SharpCompress.Compressors.Shrink -{ - public class HwUnshrink - { - private const int MIN_CODE_SIZE = 9; - private const int MAX_CODE_SIZE = 13; - - private const ushort MAX_CODE = (ushort)((1U << MAX_CODE_SIZE) - 1); - private const ushort INVALID_CODE = ushort.MaxValue; - private const ushort CONTROL_CODE = 256; - private const ushort INC_CODE_SIZE = 1; - private const ushort PARTIAL_CLEAR = 2; - - private const int HASH_BITS = MAX_CODE_SIZE + 1; // For a load factor of 0.5. - private const int HASHTAB_SIZE = 1 << HASH_BITS; - private const ushort UNKNOWN_LEN = ushort.MaxValue; - - private struct CodeTabEntry - { - public int prefixCode; // INVALID_CODE means the entry is invalid. - public byte extByte; - public ushort len; - public int lastDstPos; - } - - private static void CodeTabInit(CodeTabEntry[] codeTab) - { - for (var i = 0; i <= byte.MaxValue; i++) - { - codeTab[i].prefixCode = (ushort)i; - codeTab[i].extByte = (byte)i; - codeTab[i].len = 1; - } - - for (var i = byte.MaxValue + 1; i <= MAX_CODE; i++) - { - codeTab[i].prefixCode = INVALID_CODE; - } - } - - private static void UnshrinkPartialClear(CodeTabEntry[] codeTab, ref CodeQueue queue) - { - var isPrefix = new bool[MAX_CODE + 1]; - int codeQueueSize; - - // Scan for codes that have been used as a prefix. - for (var i = CONTROL_CODE + 1; i <= MAX_CODE; i++) - { - if (codeTab[i].prefixCode != INVALID_CODE) - { - isPrefix[codeTab[i].prefixCode] = true; - } - } - - // Clear "non-prefix" codes in the table; populate the code queue. - codeQueueSize = 0; - for (var i = CONTROL_CODE + 1; i <= MAX_CODE; i++) - { - if (!isPrefix[i]) - { - codeTab[i].prefixCode = INVALID_CODE; - queue.codes[codeQueueSize++] = (ushort)i; - } - } - - queue.codes[codeQueueSize] = INVALID_CODE; // End-of-queue marker. - queue.nextIdx = 0; - } - - private static bool ReadCode( - BitStream stream, - ref int codeSize, - CodeTabEntry[] codeTab, - ref CodeQueue queue, - out int nextCode - ) - { - int code, - controlCode; - - code = (int)stream.NextBits(codeSize); - if (!stream.Advance(codeSize)) - { - nextCode = INVALID_CODE; - return false; - } - - // Handle regular codes (the common case). - if (code != CONTROL_CODE) - { - nextCode = code; - return true; - } - - // Handle control codes. - controlCode = (ushort)stream.NextBits(codeSize); - if (!stream.Advance(codeSize)) - { - nextCode = INVALID_CODE; - return true; - } - - if (controlCode == INC_CODE_SIZE && codeSize < MAX_CODE_SIZE) - { - codeSize++; - return ReadCode(stream, ref codeSize, codeTab, ref queue, out nextCode); - } - - if (controlCode == PARTIAL_CLEAR) - { - UnshrinkPartialClear(codeTab, ref queue); - return ReadCode(stream, ref codeSize, codeTab, ref queue, out nextCode); - } - - nextCode = INVALID_CODE; - return true; - } - - private static void CopyFromPrevPos(byte[] dst, int prevPos, int dstPos, int len) - { - if (dstPos + len > dst.Length) - { - // Not enough room in dst for the sloppy copy below. - Array.Copy(dst, prevPos, dst, dstPos, len); - return; - } - - if (prevPos + len > dstPos) - { - // Benign one-byte overlap possible in the KwKwK case. - //assert(prevPos + len == dstPos + 1); - //assert(dst[prevPos] == dst[prevPos + len - 1]); - } - - Buffer.BlockCopy(dst, prevPos, dst, dstPos, len); - } - - private static UnshrnkStatus OutputCode( - int code, - byte[] dst, - int dstPos, - int dstCap, - int prevCode, - CodeTabEntry[] codeTab, - ref CodeQueue queue, - out byte firstByte, - out int len - ) - { - int prefixCode; - - //assert(code <= MAX_CODE && code != CONTROL_CODE); - //assert(dstPos < dstCap); - firstByte = 0; - if (code <= byte.MaxValue) - { - // Output literal byte. - firstByte = (byte)code; - len = 1; - dst[dstPos] = (byte)code; - return UnshrnkStatus.Ok; - } - - if (codeTab[code].prefixCode == INVALID_CODE || codeTab[code].prefixCode == code) - { - // Reject invalid codes. Self-referential codes may exist in the table but cannot be used. - firstByte = 0; - len = 0; - return UnshrnkStatus.Error; - } - - if (codeTab[code].len != UNKNOWN_LEN) - { - // Output string with known length (the common case). - if (dstCap - dstPos < codeTab[code].len) - { - firstByte = 0; - len = 0; - return UnshrnkStatus.Full; - } - - CopyFromPrevPos(dst, codeTab[code].lastDstPos, dstPos, codeTab[code].len); - firstByte = dst[dstPos]; - len = codeTab[code].len; - return UnshrnkStatus.Ok; - } - - // Output a string of unknown length. - //assert(codeTab[code].len == UNKNOWN_LEN); - prefixCode = codeTab[code].prefixCode; - // assert(prefixCode > CONTROL_CODE); - - if (prefixCode == queue.codes[queue.nextIdx]) - { - // The prefix code hasn't been added yet, but we were just about to: the KwKwK case. - //assert(codeTab[prevCode].prefixCode != INVALID_CODE); - codeTab[prefixCode].prefixCode = prevCode; - codeTab[prefixCode].extByte = firstByte; - codeTab[prefixCode].len = (ushort)(codeTab[prevCode].len + 1); - codeTab[prefixCode].lastDstPos = codeTab[prevCode].lastDstPos; - dst[dstPos] = firstByte; - } - else if (codeTab[prefixCode].prefixCode == INVALID_CODE) - { - // The prefix code is still invalid. - firstByte = 0; - len = 0; - return UnshrnkStatus.Error; - } - - // Output the prefix string, then the extension byte. - len = codeTab[prefixCode].len + 1; - if (dstCap - dstPos < len) - { - firstByte = 0; - len = 0; - return UnshrnkStatus.Full; - } - - CopyFromPrevPos(dst, codeTab[prefixCode].lastDstPos, dstPos, codeTab[prefixCode].len); - dst[dstPos + len - 1] = codeTab[code].extByte; - firstByte = dst[dstPos]; - - // Update the code table now that the string has a length and pos. - //assert(prevCode != code); - codeTab[code].len = (ushort)len; - codeTab[code].lastDstPos = dstPos; - - return UnshrnkStatus.Ok; - } - - public static UnshrnkStatus Unshrink( - byte[] src, - int srcLen, - out int srcUsed, - byte[] dst, - int dstCap, - out int dstUsed - ) - { - var codeTab = new CodeTabEntry[HASHTAB_SIZE]; - var queue = new CodeQueue(); - var stream = new BitStream(src, srcLen); - int codeSize, - dstPos, - len; - int currCode, - prevCode, - newCode; - byte firstByte; - - CodeTabInit(codeTab); - CodeQueueInit(ref queue); - codeSize = MIN_CODE_SIZE; - dstPos = 0; - - // Handle the first code separately since there is no previous code. - if (!ReadCode(stream, ref codeSize, codeTab, ref queue, out currCode)) - { - srcUsed = stream.BytesRead; - dstUsed = 0; - return UnshrnkStatus.Ok; - } - - //assert(currCode != CONTROL_CODE); - if (currCode > byte.MaxValue) - { - srcUsed = stream.BytesRead; - dstUsed = 0; - return UnshrnkStatus.Error; // The first code must be a literal. - } - - if (dstPos == dstCap) - { - srcUsed = stream.BytesRead; - dstUsed = 0; - return UnshrnkStatus.Full; - } - - firstByte = (byte)currCode; - dst[dstPos] = (byte)currCode; - codeTab[currCode].lastDstPos = dstPos; - dstPos++; - - prevCode = currCode; - while (ReadCode(stream, ref codeSize, codeTab, ref queue, out currCode)) - { - if (currCode == INVALID_CODE) - { - srcUsed = stream.BytesRead; - dstUsed = 0; - return UnshrnkStatus.Error; - } - - if (dstPos == dstCap) - { - srcUsed = stream.BytesRead; - dstUsed = 0; - return UnshrnkStatus.Full; - } - - // Handle KwKwK: next code used before being added. - if (currCode == queue.codes[queue.nextIdx]) - { - if (codeTab[prevCode].prefixCode == INVALID_CODE) - { - // The previous code is no longer valid. - srcUsed = stream.BytesRead; - dstUsed = 0; - return UnshrnkStatus.Error; - } - - // Extend the previous code with its first byte. - //assert(currCode != prevCode); - codeTab[currCode].prefixCode = prevCode; - codeTab[currCode].extByte = firstByte; - codeTab[currCode].len = (ushort)(codeTab[prevCode].len + 1); - codeTab[currCode].lastDstPos = codeTab[prevCode].lastDstPos; - //assert(dstPos < dstCap); - dst[dstPos] = firstByte; - } - - // Output the string represented by the current code. - var status = OutputCode( - currCode, - dst, - dstPos, - dstCap, - prevCode, - codeTab, - ref queue, - out firstByte, - out len - ); - if (status != UnshrnkStatus.Ok) - { - srcUsed = stream.BytesRead; - dstUsed = 0; - return status; - } - - // Verify that the output matches walking the prefixes. - var c = currCode; - for (var i = 0; i < len; i++) - { - // assert(codeTab[c].len == len - i); - //assert(codeTab[c].extByte == dst[dstPos + len - i - 1]); - c = codeTab[c].prefixCode; - } - - // Add a new code to the string table if there's room. - // The string is the previous code's string extended with the first byte of the current code's string. - newCode = CodeQueueRemoveNext(ref queue); - if (newCode != INVALID_CODE) - { - //assert(codeTab[prevCode].lastDstPos < dstPos); - codeTab[newCode].prefixCode = prevCode; - codeTab[newCode].extByte = firstByte; - codeTab[newCode].len = (ushort)(codeTab[prevCode].len + 1); - codeTab[newCode].lastDstPos = codeTab[prevCode].lastDstPos; - - if (codeTab[prevCode].prefixCode == INVALID_CODE) - { - // prevCode was invalidated in a partial clearing. Until that code is re-used, the - // string represented by newCode is indeterminate. - codeTab[newCode].len = UNKNOWN_LEN; - } - // If prevCode was invalidated in a partial clearing, it's possible that newCode == prevCode, - // in which case it will never be used or cleared. - } - - codeTab[currCode].lastDstPos = dstPos; - dstPos += len; - - prevCode = currCode; - } - - srcUsed = stream.BytesRead; - dstUsed = dstPos; - - return UnshrnkStatus.Ok; - } - - public enum UnshrnkStatus - { - Ok, - Full, - Error - } - - private struct CodeQueue - { - public int nextIdx; - public ushort[] codes; - } - - private static void CodeQueueInit(ref CodeQueue q) - { - int codeQueueSize; - ushort code; - - codeQueueSize = 0; - q.codes = new ushort[MAX_CODE - CONTROL_CODE + 2]; - - for (code = CONTROL_CODE + 1; code <= MAX_CODE; code++) - { - q.codes[codeQueueSize++] = code; - } - - //assert(codeQueueSize < q.codes.Length); - q.codes[codeQueueSize] = INVALID_CODE; // End-of-queue marker. - q.nextIdx = 0; - } - - private static ushort CodeQueueNext(ref CodeQueue q) => - //assert(q.nextIdx < q.codes.Length); - q.codes[q.nextIdx]; - - private static ushort CodeQueueRemoveNext(ref CodeQueue q) - { - var code = CodeQueueNext(ref q); - if (code != INVALID_CODE) - { - q.nextIdx++; - } - return code; - } - } -} diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs deleted file mode 100644 index 65b2eb37..00000000 --- a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SharpCompress.Compressors.Shrink; - -internal class ShrinkStream : Stream -{ - private Stream inStream; - private CompressionMode _compressionMode; - - private ulong _compressedSize; - private long _uncompressedSize; - private byte[] _byteOut; - private long _outBytesCount; - - public ShrinkStream( - Stream stream, - CompressionMode compressionMode, - long compressedSize, - long uncompressedSize - ) - { - inStream = stream; - _compressionMode = compressionMode; - - _compressedSize = (ulong)compressedSize; - _uncompressedSize = uncompressedSize; - _byteOut = new byte[_uncompressedSize]; - _outBytesCount = 0L; - } - - public override bool CanRead => true; - - public override bool CanSeek => true; - - public override bool CanWrite => false; - - public override long Length => _uncompressedSize; - - public override long Position - { - get => _outBytesCount; - set => throw new NotImplementedException(); - } - - public override void Flush() => throw new NotImplementedException(); - - public override int Read(byte[] buffer, int offset, int count) - { - if (inStream.Position == (long)_compressedSize) - { - return 0; - } - var src = new byte[_compressedSize]; - inStream.Read(src, offset, (int)_compressedSize); - var srcUsed = 0; - var dstUsed = 0; - - HwUnshrink.Unshrink( - src, - (int)_compressedSize, - out srcUsed, - _byteOut, - (int)_uncompressedSize, - out dstUsed - ); - _outBytesCount = _byteOut.Length; - - for (var index = 0; index < _outBytesCount; ++index) - { - buffer[offset + index] = _byteOut[index]; - } - var tmp = _outBytesCount; - _outBytesCount = 0; - return (int)tmp; - } - - public override long Seek(long offset, SeekOrigin origin) => - throw new NotImplementedException(); - - public override void SetLength(long value) => throw new NotImplementedException(); - - public override void Write(byte[] buffer, int offset, int count) => - throw new NotImplementedException(); -} diff --git a/src/SharpCompress/Compressors/Xz/ReadOnlyStream.cs b/src/SharpCompress/Compressors/Xz/ReadOnlyStream.cs index 75188483..71614df9 100644 --- a/src/SharpCompress/Compressors/Xz/ReadOnlyStream.cs +++ b/src/SharpCompress/Compressors/Xz/ReadOnlyStream.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System; using System.IO; @@ -23,7 +23,7 @@ public abstract class ReadOnlyStream : Stream set => throw new NotSupportedException(); } - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); diff --git a/src/SharpCompress/Compressors/Xz/XZBlock.cs b/src/SharpCompress/Compressors/Xz/XZBlock.cs index ddd7eaf3..ea907609 100644 --- a/src/SharpCompress/Compressors/Xz/XZBlock.cs +++ b/src/SharpCompress/Compressors/Xz/XZBlock.cs @@ -14,7 +14,7 @@ public sealed class XZBlock : XZReadOnlyStream public int BlockHeaderSize => (_blockHeaderSizeByte + 1) * 4; public ulong? CompressedSize { get; private set; } public ulong? UncompressedSize { get; private set; } - public Stack Filters { get; private set; } = new(); + public Stack Filters { get; private set; } = new Stack(); public bool HeaderIsLoaded { get; private set; } private CheckType _checkType; private readonly int _checkSize; diff --git a/src/SharpCompress/Compressors/Xz/XZIndex.cs b/src/SharpCompress/Compressors/Xz/XZIndex.cs index ddfd7c99..631f27b2 100644 --- a/src/SharpCompress/Compressors/Xz/XZIndex.cs +++ b/src/SharpCompress/Compressors/Xz/XZIndex.cs @@ -13,7 +13,7 @@ public class XZIndex private readonly BinaryReader _reader; public long StreamStartPosition { get; private set; } public ulong NumberOfRecords { get; private set; } - public List Records { get; } = new(); + public List Records { get; } = new List(); private readonly bool _indexMarkerAlreadyVerified; diff --git a/src/SharpCompress/Crypto/BlockTransformer.cs b/src/SharpCompress/Crypto/BlockTransformer.cs deleted file mode 100644 index ed9ead44..00000000 --- a/src/SharpCompress/Crypto/BlockTransformer.cs +++ /dev/null @@ -1,19 +0,0 @@ -#nullable disable - -using System; -using System.Security.Cryptography; - -namespace SharpCompress.Crypto; - -internal class BlockTransformer(ICryptoTransform transformer) : IDisposable -{ - public byte[] ProcessBlock(ReadOnlySpan cipherText) - { - var decryptedBytes = new byte[cipherText.Length]; - transformer.TransformBlock(cipherText.ToArray(), 0, cipherText.Length, decryptedBytes, 0); - - return decryptedBytes; - } - - public void Dispose() { } -} diff --git a/src/SharpCompress/Crypto/Crc32Stream.cs b/src/SharpCompress/Crypto/Crc32Stream.cs index 5f5ccd87..7f0af6ca 100644 --- a/src/SharpCompress/Crypto/Crc32Stream.cs +++ b/src/SharpCompress/Crypto/Crc32Stream.cs @@ -6,17 +6,27 @@ using System.IO; namespace SharpCompress.Crypto; [CLSCompliant(false)] -public sealed class Crc32Stream(Stream stream, uint polynomial, uint seed) : Stream +public sealed class Crc32Stream : Stream { - public const uint DEFAULT_POLYNOMIAL = 0xedb88320u; - public const uint DEFAULT_SEED = 0xffffffffu; + public const uint DefaultPolynomial = 0xedb88320u; + public const uint DefaultSeed = 0xffffffffu; - private static uint[] _defaultTable; + private static uint[] defaultTable; - private readonly uint[] _table = InitializeTable(polynomial); + private readonly uint[] table; + private uint hash; + + private readonly Stream stream; public Crc32Stream(Stream stream) - : this(stream, DEFAULT_POLYNOMIAL, DEFAULT_SEED) { } + : this(stream, DefaultPolynomial, DefaultSeed) { } + + public Crc32Stream(Stream stream, uint polynomial, uint seed) + { + this.stream = stream; + table = InitializeTable(polynomial); + hash = seed; + } public Stream WrappedStream => stream; @@ -35,20 +45,20 @@ public sealed class Crc32Stream(Stream stream, uint polynomial, uint seed) : Str { stream.Write(buffer); - seed = CalculateCrc(_table, seed, buffer); + hash = CalculateCrc(table, hash, buffer); } #endif public override void Write(byte[] buffer, int offset, int count) { stream.Write(buffer, offset, count); - seed = CalculateCrc(_table, seed, buffer.AsSpan(offset, count)); + hash = CalculateCrc(table, hash, buffer.AsSpan(offset, count)); } public override void WriteByte(byte value) { stream.WriteByte(value); - seed = CalculateCrc(_table, seed, value); + hash = CalculateCrc(table, hash, value); } public override bool CanRead => stream.CanRead; @@ -61,21 +71,21 @@ public sealed class Crc32Stream(Stream stream, uint polynomial, uint seed) : Str set => throw new NotSupportedException(); } - public uint Crc => ~seed; + public uint Crc => ~hash; - public static uint Compute(byte[] buffer) => Compute(DEFAULT_SEED, buffer); + public static uint Compute(byte[] buffer) => Compute(DefaultSeed, buffer); public static uint Compute(uint seed, byte[] buffer) => - Compute(DEFAULT_POLYNOMIAL, seed, buffer); + Compute(DefaultPolynomial, seed, buffer); public static uint Compute(uint polynomial, uint seed, ReadOnlySpan buffer) => ~CalculateCrc(InitializeTable(polynomial), seed, buffer); private static uint[] InitializeTable(uint polynomial) { - if (polynomial == DEFAULT_POLYNOMIAL && _defaultTable != null) + if (polynomial == DefaultPolynomial && defaultTable != null) { - return _defaultTable; + return defaultTable; } var createTable = new uint[256]; @@ -97,9 +107,9 @@ public sealed class Crc32Stream(Stream stream, uint polynomial, uint seed) : Str createTable[i] = entry; } - if (polynomial == DEFAULT_POLYNOMIAL) + if (polynomial == DefaultPolynomial) { - _defaultTable = createTable; + defaultTable = createTable; } return createTable; diff --git a/src/SharpCompress/Crypto/CryptoException.cs b/src/SharpCompress/Crypto/CryptoException.cs new file mode 100644 index 00000000..234fd5e5 --- /dev/null +++ b/src/SharpCompress/Crypto/CryptoException.cs @@ -0,0 +1,14 @@ +using System; + +namespace SharpCompress.Crypto; + +public class CryptoException : Exception +{ + public CryptoException() { } + + public CryptoException(string message) + : base(message) { } + + public CryptoException(string message, Exception exception) + : base(message, exception) { } +} diff --git a/src/SharpCompress/Crypto/DataLengthException.cs b/src/SharpCompress/Crypto/DataLengthException.cs new file mode 100644 index 00000000..828c1a8f --- /dev/null +++ b/src/SharpCompress/Crypto/DataLengthException.cs @@ -0,0 +1,24 @@ +using System; + +namespace SharpCompress.Crypto; + +public class DataLengthException : CryptoException +{ + /** + * base constructor. + */ + + public DataLengthException() { } + + /** + * create a DataLengthException with the given message. + * + * @param message the message to be carried with the exception. + */ + + public DataLengthException(string message) + : base(message) { } + + public DataLengthException(string message, Exception exception) + : base(message, exception) { } +} diff --git a/src/SharpCompress/Crypto/IBlockCipher.cs b/src/SharpCompress/Crypto/IBlockCipher.cs new file mode 100644 index 00000000..50eb5fb3 --- /dev/null +++ b/src/SharpCompress/Crypto/IBlockCipher.cs @@ -0,0 +1,33 @@ +using System; + +namespace SharpCompress.Crypto; + +/// Base interface for a symmetric key block cipher. +public interface IBlockCipher +{ + /// The name of the algorithm this cipher implements. + string AlgorithmName { get; } + + /// Initialise the cipher. + /// Initialise for encryption if true, for decryption if false. + /// The key or other data required by the cipher. + void Init(bool forEncryption, ICipherParameters parameters); + + /// The block size for this cipher, in bytes. + int GetBlockSize(); + + /// Indicates whether this cipher can handle partial blocks. + bool IsPartialBlockOkay { get; } + + /// Process a block. + /// The input buffer. + /// The output buffer. + /// If input block is wrong size, or outBuf too small. + /// The number of bytes processed and produced. + int ProcessBlock(ReadOnlySpan inBuf, Span outBuf); + + /// + /// Reset the cipher to the same state as it was after the last init (if there was one). + /// + void Reset(); +} diff --git a/src/SharpCompress/Crypto/ICipherParameters.cs b/src/SharpCompress/Crypto/ICipherParameters.cs new file mode 100644 index 00000000..9934637a --- /dev/null +++ b/src/SharpCompress/Crypto/ICipherParameters.cs @@ -0,0 +1,3 @@ +namespace SharpCompress.Crypto; + +public interface ICipherParameters { } diff --git a/src/SharpCompress/Crypto/KeyParameter.cs b/src/SharpCompress/Crypto/KeyParameter.cs new file mode 100644 index 00000000..fce334f9 --- /dev/null +++ b/src/SharpCompress/Crypto/KeyParameter.cs @@ -0,0 +1,39 @@ +using System; + +namespace SharpCompress.Crypto; + +public class KeyParameter : ICipherParameters +{ + private readonly byte[] key; + + public KeyParameter(byte[] key) + { + if (key is null) + { + throw new ArgumentNullException(nameof(key)); + } + + this.key = (byte[])key.Clone(); + } + + public KeyParameter(byte[] key, int keyOff, int keyLen) + { + if (key is null) + { + throw new ArgumentNullException(nameof(key)); + } + if (keyOff < 0 || keyOff > key.Length) + { + throw new ArgumentOutOfRangeException(nameof(keyOff)); + } + if (keyLen < 0 || (keyOff + keyLen) > key.Length) + { + throw new ArgumentOutOfRangeException(nameof(keyLen)); + } + + this.key = new byte[keyLen]; + Array.Copy(key, keyOff, this.key, 0, keyLen); + } + + public byte[] GetKey() => (byte[])key.Clone(); +} diff --git a/src/SharpCompress/Crypto/RijndaelEngine.cs b/src/SharpCompress/Crypto/RijndaelEngine.cs new file mode 100644 index 00000000..98dd5bc1 --- /dev/null +++ b/src/SharpCompress/Crypto/RijndaelEngine.cs @@ -0,0 +1,1909 @@ +using System; + +namespace SharpCompress.Crypto; + +public sealed class RijndaelEngine : IBlockCipher +{ + private const int MAXROUNDS = 14; + + private const int MAXKC = (256 / 4); + + private static ReadOnlySpan Logtable => + new byte[] + { + 0, + 0, + 25, + 1, + 50, + 2, + 26, + 198, + 75, + 199, + 27, + 104, + 51, + 238, + 223, + 3, + 100, + 4, + 224, + 14, + 52, + 141, + 129, + 239, + 76, + 113, + 8, + 200, + 248, + 105, + 28, + 193, + 125, + 194, + 29, + 181, + 249, + 185, + 39, + 106, + 77, + 228, + 166, + 114, + 154, + 201, + 9, + 120, + 101, + 47, + 138, + 5, + 33, + 15, + 225, + 36, + 18, + 240, + 130, + 69, + 53, + 147, + 218, + 142, + 150, + 143, + 219, + 189, + 54, + 208, + 206, + 148, + 19, + 92, + 210, + 241, + 64, + 70, + 131, + 56, + 102, + 221, + 253, + 48, + 191, + 6, + 139, + 98, + 179, + 37, + 226, + 152, + 34, + 136, + 145, + 16, + 126, + 110, + 72, + 195, + 163, + 182, + 30, + 66, + 58, + 107, + 40, + 84, + 250, + 133, + 61, + 186, + 43, + 121, + 10, + 21, + 155, + 159, + 94, + 202, + 78, + 212, + 172, + 229, + 243, + 115, + 167, + 87, + 175, + 88, + 168, + 80, + 244, + 234, + 214, + 116, + 79, + 174, + 233, + 213, + 231, + 230, + 173, + 232, + 44, + 215, + 117, + 122, + 235, + 22, + 11, + 245, + 89, + 203, + 95, + 176, + 156, + 169, + 81, + 160, + 127, + 12, + 246, + 111, + 23, + 196, + 73, + 236, + 216, + 67, + 31, + 45, + 164, + 118, + 123, + 183, + 204, + 187, + 62, + 90, + 251, + 96, + 177, + 134, + 59, + 82, + 161, + 108, + 170, + 85, + 41, + 157, + 151, + 178, + 135, + 144, + 97, + 190, + 220, + 252, + 188, + 149, + 207, + 205, + 55, + 63, + 91, + 209, + 83, + 57, + 132, + 60, + 65, + 162, + 109, + 71, + 20, + 42, + 158, + 93, + 86, + 242, + 211, + 171, + 68, + 17, + 146, + 217, + 35, + 32, + 46, + 137, + 180, + 124, + 184, + 38, + 119, + 153, + 227, + 165, + 103, + 74, + 237, + 222, + 197, + 49, + 254, + 24, + 13, + 99, + 140, + 128, + 192, + 247, + 112, + 7 + }; + + private static ReadOnlySpan Alogtable => + new byte[] + { + 0, + 3, + 5, + 15, + 17, + 51, + 85, + 255, + 26, + 46, + 114, + 150, + 161, + 248, + 19, + 53, + 95, + 225, + 56, + 72, + 216, + 115, + 149, + 164, + 247, + 2, + 6, + 10, + 30, + 34, + 102, + 170, + 229, + 52, + 92, + 228, + 55, + 89, + 235, + 38, + 106, + 190, + 217, + 112, + 144, + 171, + 230, + 49, + 83, + 245, + 4, + 12, + 20, + 60, + 68, + 204, + 79, + 209, + 104, + 184, + 211, + 110, + 178, + 205, + 76, + 212, + 103, + 169, + 224, + 59, + 77, + 215, + 98, + 166, + 241, + 8, + 24, + 40, + 120, + 136, + 131, + 158, + 185, + 208, + 107, + 189, + 220, + 127, + 129, + 152, + 179, + 206, + 73, + 219, + 118, + 154, + 181, + 196, + 87, + 249, + 16, + 48, + 80, + 240, + 11, + 29, + 39, + 105, + 187, + 214, + 97, + 163, + 254, + 25, + 43, + 125, + 135, + 146, + 173, + 236, + 47, + 113, + 147, + 174, + 233, + 32, + 96, + 160, + 251, + 22, + 58, + 78, + 210, + 109, + 183, + 194, + 93, + 231, + 50, + 86, + 250, + 21, + 63, + 65, + 195, + 94, + 226, + 61, + 71, + 201, + 64, + 192, + 91, + 237, + 44, + 116, + 156, + 191, + 218, + 117, + 159, + 186, + 213, + 100, + 172, + 239, + 42, + 126, + 130, + 157, + 188, + 223, + 122, + 142, + 137, + 128, + 155, + 182, + 193, + 88, + 232, + 35, + 101, + 175, + 234, + 37, + 111, + 177, + 200, + 67, + 197, + 84, + 252, + 31, + 33, + 99, + 165, + 244, + 7, + 9, + 27, + 45, + 119, + 153, + 176, + 203, + 70, + 202, + 69, + 207, + 74, + 222, + 121, + 139, + 134, + 145, + 168, + 227, + 62, + 66, + 198, + 81, + 243, + 14, + 18, + 54, + 90, + 238, + 41, + 123, + 141, + 140, + 143, + 138, + 133, + 148, + 167, + 242, + 13, + 23, + 57, + 75, + 221, + 124, + 132, + 151, + 162, + 253, + 28, + 36, + 108, + 180, + 199, + 82, + 246, + 1, + 3, + 5, + 15, + 17, + 51, + 85, + 255, + 26, + 46, + 114, + 150, + 161, + 248, + 19, + 53, + 95, + 225, + 56, + 72, + 216, + 115, + 149, + 164, + 247, + 2, + 6, + 10, + 30, + 34, + 102, + 170, + 229, + 52, + 92, + 228, + 55, + 89, + 235, + 38, + 106, + 190, + 217, + 112, + 144, + 171, + 230, + 49, + 83, + 245, + 4, + 12, + 20, + 60, + 68, + 204, + 79, + 209, + 104, + 184, + 211, + 110, + 178, + 205, + 76, + 212, + 103, + 169, + 224, + 59, + 77, + 215, + 98, + 166, + 241, + 8, + 24, + 40, + 120, + 136, + 131, + 158, + 185, + 208, + 107, + 189, + 220, + 127, + 129, + 152, + 179, + 206, + 73, + 219, + 118, + 154, + 181, + 196, + 87, + 249, + 16, + 48, + 80, + 240, + 11, + 29, + 39, + 105, + 187, + 214, + 97, + 163, + 254, + 25, + 43, + 125, + 135, + 146, + 173, + 236, + 47, + 113, + 147, + 174, + 233, + 32, + 96, + 160, + 251, + 22, + 58, + 78, + 210, + 109, + 183, + 194, + 93, + 231, + 50, + 86, + 250, + 21, + 63, + 65, + 195, + 94, + 226, + 61, + 71, + 201, + 64, + 192, + 91, + 237, + 44, + 116, + 156, + 191, + 218, + 117, + 159, + 186, + 213, + 100, + 172, + 239, + 42, + 126, + 130, + 157, + 188, + 223, + 122, + 142, + 137, + 128, + 155, + 182, + 193, + 88, + 232, + 35, + 101, + 175, + 234, + 37, + 111, + 177, + 200, + 67, + 197, + 84, + 252, + 31, + 33, + 99, + 165, + 244, + 7, + 9, + 27, + 45, + 119, + 153, + 176, + 203, + 70, + 202, + 69, + 207, + 74, + 222, + 121, + 139, + 134, + 145, + 168, + 227, + 62, + 66, + 198, + 81, + 243, + 14, + 18, + 54, + 90, + 238, + 41, + 123, + 141, + 140, + 143, + 138, + 133, + 148, + 167, + 242, + 13, + 23, + 57, + 75, + 221, + 124, + 132, + 151, + 162, + 253, + 28, + 36, + 108, + 180, + 199, + 82, + 246, + 1 + }; + + private static ReadOnlySpan S => + new byte[] + { + 99, + 124, + 119, + 123, + 242, + 107, + 111, + 197, + 48, + 1, + 103, + 43, + 254, + 215, + 171, + 118, + 202, + 130, + 201, + 125, + 250, + 89, + 71, + 240, + 173, + 212, + 162, + 175, + 156, + 164, + 114, + 192, + 183, + 253, + 147, + 38, + 54, + 63, + 247, + 204, + 52, + 165, + 229, + 241, + 113, + 216, + 49, + 21, + 4, + 199, + 35, + 195, + 24, + 150, + 5, + 154, + 7, + 18, + 128, + 226, + 235, + 39, + 178, + 117, + 9, + 131, + 44, + 26, + 27, + 110, + 90, + 160, + 82, + 59, + 214, + 179, + 41, + 227, + 47, + 132, + 83, + 209, + 0, + 237, + 32, + 252, + 177, + 91, + 106, + 203, + 190, + 57, + 74, + 76, + 88, + 207, + 208, + 239, + 170, + 251, + 67, + 77, + 51, + 133, + 69, + 249, + 2, + 127, + 80, + 60, + 159, + 168, + 81, + 163, + 64, + 143, + 146, + 157, + 56, + 245, + 188, + 182, + 218, + 33, + 16, + 255, + 243, + 210, + 205, + 12, + 19, + 236, + 95, + 151, + 68, + 23, + 196, + 167, + 126, + 61, + 100, + 93, + 25, + 115, + 96, + 129, + 79, + 220, + 34, + 42, + 144, + 136, + 70, + 238, + 184, + 20, + 222, + 94, + 11, + 219, + 224, + 50, + 58, + 10, + 73, + 6, + 36, + 92, + 194, + 211, + 172, + 98, + 145, + 149, + 228, + 121, + 231, + 200, + 55, + 109, + 141, + 213, + 78, + 169, + 108, + 86, + 244, + 234, + 101, + 122, + 174, + 8, + 186, + 120, + 37, + 46, + 28, + 166, + 180, + 198, + 232, + 221, + 116, + 31, + 75, + 189, + 139, + 138, + 112, + 62, + 181, + 102, + 72, + 3, + 246, + 14, + 97, + 53, + 87, + 185, + 134, + 193, + 29, + 158, + 225, + 248, + 152, + 17, + 105, + 217, + 142, + 148, + 155, + 30, + 135, + 233, + 206, + 85, + 40, + 223, + 140, + 161, + 137, + 13, + 191, + 230, + 66, + 104, + 65, + 153, + 45, + 15, + 176, + 84, + 187, + 22 + }; + + private static ReadOnlySpan Si => + new byte[] + { + 82, + 9, + 106, + 213, + 48, + 54, + 165, + 56, + 191, + 64, + 163, + 158, + 129, + 243, + 215, + 251, + 124, + 227, + 57, + 130, + 155, + 47, + 255, + 135, + 52, + 142, + 67, + 68, + 196, + 222, + 233, + 203, + 84, + 123, + 148, + 50, + 166, + 194, + 35, + 61, + 238, + 76, + 149, + 11, + 66, + 250, + 195, + 78, + 8, + 46, + 161, + 102, + 40, + 217, + 36, + 178, + 118, + 91, + 162, + 73, + 109, + 139, + 209, + 37, + 114, + 248, + 246, + 100, + 134, + 104, + 152, + 22, + 212, + 164, + 92, + 204, + 93, + 101, + 182, + 146, + 108, + 112, + 72, + 80, + 253, + 237, + 185, + 218, + 94, + 21, + 70, + 87, + 167, + 141, + 157, + 132, + 144, + 216, + 171, + 0, + 140, + 188, + 211, + 10, + 247, + 228, + 88, + 5, + 184, + 179, + 69, + 6, + 208, + 44, + 30, + 143, + 202, + 63, + 15, + 2, + 193, + 175, + 189, + 3, + 1, + 19, + 138, + 107, + 58, + 145, + 17, + 65, + 79, + 103, + 220, + 234, + 151, + 242, + 207, + 206, + 240, + 180, + 230, + 115, + 150, + 172, + 116, + 34, + 231, + 173, + 53, + 133, + 226, + 249, + 55, + 232, + 28, + 117, + 223, + 110, + 71, + 241, + 26, + 113, + 29, + 41, + 197, + 137, + 111, + 183, + 98, + 14, + 170, + 24, + 190, + 27, + 252, + 86, + 62, + 75, + 198, + 210, + 121, + 32, + 154, + 219, + 192, + 254, + 120, + 205, + 90, + 244, + 31, + 221, + 168, + 51, + 136, + 7, + 199, + 49, + 177, + 18, + 16, + 89, + 39, + 128, + 236, + 95, + 96, + 81, + 127, + 169, + 25, + 181, + 74, + 13, + 45, + 229, + 122, + 159, + 147, + 201, + 156, + 239, + 160, + 224, + 59, + 77, + 174, + 42, + 245, + 176, + 200, + 235, + 187, + 60, + 131, + 83, + 153, + 97, + 23, + 43, + 4, + 126, + 186, + 119, + 214, + 38, + 225, + 105, + 20, + 99, + 85, + 33, + 12, + 125 + }; + + private static ReadOnlySpan rcon => + new byte[] + { + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91 + }; + + private static readonly byte[][] shifts0 = + { + new byte[] { 0, 8, 16, 24 }, + new byte[] { 0, 8, 16, 24 }, + new byte[] { 0, 8, 16, 24 }, + new byte[] { 0, 8, 16, 32 }, + new byte[] { 0, 8, 24, 32 } + }; + + private static readonly byte[][] shifts1 = + { + new byte[] { 0, 24, 16, 8 }, + new byte[] { 0, 32, 24, 16 }, + new byte[] { 0, 40, 32, 24 }, + new byte[] { 0, 48, 40, 24 }, + new byte[] { 0, 56, 40, 32 } + }; + + /** + * multiply two elements of GF(2^m) + * needed for MixColumn and InvMixColumn + */ + + private byte Mul0x2(int b) + { + if (b != 0) + { + return Alogtable[25 + (Logtable[b] & 0xff)]; + } + return 0; + } + + private byte Mul0x3(int b) + { + if (b != 0) + { + return Alogtable[1 + (Logtable[b] & 0xff)]; + } + return 0; + } + + private byte Mul0x9(int b) + { + if (b >= 0) + { + return Alogtable[199 + b]; + } + return 0; + } + + private byte Mul0xb(int b) + { + if (b >= 0) + { + return Alogtable[104 + b]; + } + return 0; + } + + private byte Mul0xd(int b) + { + if (b >= 0) + { + return Alogtable[238 + b]; + } + return 0; + } + + private byte Mul0xe(int b) + { + if (b >= 0) + { + return Alogtable[223 + b]; + } + return 0; + } + + /** + * xor corresponding text input and round key input bytes + */ + + private void KeyAddition(long[] rk) + { + A0 ^= rk[0]; + A1 ^= rk[1]; + A2 ^= rk[2]; + A3 ^= rk[3]; + } + + private long Shift(long r, int shift) + { + //return (((long)((ulong) r >> shift) | (r << (BC - shift)))) & BC_MASK; + + var temp = (ulong)r >> shift; + + // NB: This corrects for Mono Bug #79087 (fixed in 1.1.17) + if (shift > 31) + { + temp &= 0xFFFFFFFFUL; + } + + return ((long)temp | (r << (BC - shift))) & BC_MASK; + } + + /** + * Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + + private void ShiftRow(byte[] shiftsSC) + { + A1 = Shift(A1, shiftsSC[1]); + A2 = Shift(A2, shiftsSC[2]); + A3 = Shift(A3, shiftsSC[3]); + } + + private long ApplyS(long r, ReadOnlySpan box) + { + long res = 0; + + for (var j = 0; j < BC; j += 8) + { + res |= (long)(box[(int)((r >> j) & 0xff)] & 0xff) << j; + } + + return res; + } + + /** + * Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + + private void Substitution(ReadOnlySpan box) + { + A0 = ApplyS(A0, box); + A1 = ApplyS(A1, box); + A2 = ApplyS(A2, box); + A3 = ApplyS(A3, box); + } + + /** + * Mix the bytes of every column in a linear way + */ + + private void MixColumn() + { + long r0, + r1, + r2, + r3; + + r0 = r1 = r2 = r3 = 0; + + for (var j = 0; j < BC; j += 8) + { + var a0 = (int)((A0 >> j) & 0xff); + var a1 = (int)((A1 >> j) & 0xff); + var a2 = (int)((A2 >> j) & 0xff); + var a3 = (int)((A3 >> j) & 0xff); + + r0 |= (long)((Mul0x2(a0) ^ Mul0x3(a1) ^ a2 ^ a3) & 0xff) << j; + + r1 |= (long)((Mul0x2(a1) ^ Mul0x3(a2) ^ a3 ^ a0) & 0xff) << j; + + r2 |= (long)((Mul0x2(a2) ^ Mul0x3(a3) ^ a0 ^ a1) & 0xff) << j; + + r3 |= (long)((Mul0x2(a3) ^ Mul0x3(a0) ^ a1 ^ a2) & 0xff) << j; + } + + A0 = r0; + A1 = r1; + A2 = r2; + A3 = r3; + } + + /** + * Mix the bytes of every column in a linear way + * This is the opposite operation of Mixcolumn + */ + + private void InvMixColumn() + { + long r0, + r1, + r2, + r3; + + r0 = r1 = r2 = r3 = 0; + for (var j = 0; j < BC; j += 8) + { + var a0 = (int)((A0 >> j) & 0xff); + var a1 = (int)((A1 >> j) & 0xff); + var a2 = (int)((A2 >> j) & 0xff); + var a3 = (int)((A3 >> j) & 0xff); + + // + // pre-lookup the log table + // + a0 = (a0 != 0) ? (Logtable[a0 & 0xff] & 0xff) : -1; + a1 = (a1 != 0) ? (Logtable[a1 & 0xff] & 0xff) : -1; + a2 = (a2 != 0) ? (Logtable[a2 & 0xff] & 0xff) : -1; + a3 = (a3 != 0) ? (Logtable[a3 & 0xff] & 0xff) : -1; + + r0 |= (long)((Mul0xe(a0) ^ Mul0xb(a1) ^ Mul0xd(a2) ^ Mul0x9(a3)) & 0xff) << j; + + r1 |= (long)((Mul0xe(a1) ^ Mul0xb(a2) ^ Mul0xd(a3) ^ Mul0x9(a0)) & 0xff) << j; + + r2 |= (long)((Mul0xe(a2) ^ Mul0xb(a3) ^ Mul0xd(a0) ^ Mul0x9(a1)) & 0xff) << j; + + r3 |= (long)((Mul0xe(a3) ^ Mul0xb(a0) ^ Mul0xd(a1) ^ Mul0x9(a2)) & 0xff) << j; + } + + A0 = r0; + A1 = r1; + A2 = r2; + A3 = r3; + } + + /** + * Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits + */ + + private long[][] GenerateWorkingKey(byte[] key) + { + int t, + rconpointer = 0; + var keyBits = key.Length * 8; + var tk = new byte[4, MAXKC]; + + //long[,] W = new long[MAXROUNDS+1,4]; + var W = new long[MAXROUNDS + 1][]; + + for (var i = 0; i < MAXROUNDS + 1; i++) + { + W[i] = new long[4]; + } + + var KC = keyBits switch + { + 128 => 4, + 160 => 5, + 192 => 6, + 224 => 7, + 256 => 8, + _ => throw new ArgumentException("Key length not 128/160/192/224/256 bits."), + }; + if (keyBits >= blockBits) + { + ROUNDS = KC + 6; + } + else + { + ROUNDS = (BC / 8) + 6; + } + + // + // copy the key into the processing area + // + var index = 0; + + for (var i = 0; i < key.Length; i++) + { + tk[i % 4, i / 4] = key[index++]; + } + + t = 0; + + // + // copy values into round key array + // + for (var j = 0; (j < KC) && (t < (ROUNDS + 1) * (BC / 8)); j++, t++) + { + for (var i = 0; i < 4; i++) + { + W[t / (BC / 8)][i] |= (long)(tk[i, j] & 0xff) << ((t * 8) % BC); + } + } + + // + // while not enough round key material calculated + // calculate new values + // + while (t < (ROUNDS + 1) * (BC / 8)) + { + for (var i = 0; i < 4; i++) + { + tk[i, 0] ^= S[tk[(i + 1) % 4, KC - 1] & 0xff]; + } + tk[0, 0] ^= rcon[rconpointer++]; + + if (KC <= 6) + { + for (var j = 1; j < KC; j++) + { + for (var i = 0; i < 4; i++) + { + tk[i, j] ^= tk[i, j - 1]; + } + } + } + else + { + for (var j = 1; j < 4; j++) + { + for (var i = 0; i < 4; i++) + { + tk[i, j] ^= tk[i, j - 1]; + } + } + for (var i = 0; i < 4; i++) + { + tk[i, 4] ^= S[tk[i, 3] & 0xff]; + } + for (var j = 5; j < KC; j++) + { + for (var i = 0; i < 4; i++) + { + tk[i, j] ^= tk[i, j - 1]; + } + } + } + + // + // copy values into round key array + // + for (var j = 0; (j < KC) && (t < (ROUNDS + 1) * (BC / 8)); j++, t++) + { + for (var i = 0; i < 4; i++) + { + W[t / (BC / 8)][i] |= (long)(tk[i, j] & 0xff) << ((t * 8) % (BC)); + } + } + } + return W; + } + + private readonly int BC; + private readonly long BC_MASK; + private int ROUNDS; + private readonly int blockBits; + private long[][]? workingKey; + private long A0, + A1, + A2, + A3; + private bool forEncryption; + private readonly byte[] shifts0SC; + private readonly byte[] shifts1SC; + + /** + * default constructor - 128 bit block size. + */ + + public RijndaelEngine() + : this(128) { } + + /** + * basic constructor - set the cipher up for a given blocksize + * + * @param blocksize the blocksize in bits, must be 128, 192, or 256. + */ + + public RijndaelEngine(int blockBits) + { + switch (blockBits) + { + case 128: + BC = 32; + BC_MASK = 0xffffffffL; + shifts0SC = shifts0[0]; + shifts1SC = shifts1[0]; + break; + case 160: + BC = 40; + BC_MASK = 0xffffffffffL; + shifts0SC = shifts0[1]; + shifts1SC = shifts1[1]; + break; + case 192: + BC = 48; + BC_MASK = 0xffffffffffffL; + shifts0SC = shifts0[2]; + shifts1SC = shifts1[2]; + break; + case 224: + BC = 56; + BC_MASK = 0xffffffffffffffL; + shifts0SC = shifts0[3]; + shifts1SC = shifts1[3]; + break; + case 256: + BC = 64; + BC_MASK = unchecked((long)0xffffffffffffffffL); + shifts0SC = shifts0[4]; + shifts1SC = shifts1[4]; + break; + default: + throw new ArgumentException("unknown blocksize to Rijndael"); + } + + this.blockBits = blockBits; + } + + /** + * initialise a Rijndael cipher. + * + * @param forEncryption whether or not we are for encryption. + * @param parameters the parameters required to set up the cipher. + * @exception ArgumentException if the parameters argument is + * inappropriate. + */ + + public void Init(bool forEncryption, ICipherParameters parameters) + { + if (parameters is KeyParameter parameter) + { + workingKey = GenerateWorkingKey(parameter.GetKey()); + this.forEncryption = forEncryption; + return; + } + + throw new ArgumentException( + "invalid parameter passed to Rijndael init - " + parameters.GetType() + ); + } + + public string AlgorithmName => "Rijndael"; + + public bool IsPartialBlockOkay => false; + + public int GetBlockSize() => BC / 2; + + public int ProcessBlock(ReadOnlySpan input, Span output) + { + if (workingKey is null) + { + throw new InvalidOperationException("Rijndael engine not initialised"); + } + + if (BC / 2 > input.Length) + { + throw new DataLengthException("input buffer too short"); + } + + if (BC / 2 > output.Length) + { + throw new DataLengthException("output buffer too short"); + } + + UnPackBlock(input); + + if (forEncryption) + { + EncryptBlock(workingKey); + } + else + { + DecryptBlock(workingKey); + } + + PackBlock(output); + + return BC / 2; + } + + public void Reset() { } + + private void UnPackBlock(ReadOnlySpan bytes) + { + var index = 0; + + A0 = bytes[index++] & 0xff; + A1 = bytes[index++] & 0xff; + A2 = bytes[index++] & 0xff; + A3 = bytes[index++] & 0xff; + + for (var j = 8; j != BC; j += 8) + { + A0 |= (long)(bytes[index++] & 0xff) << j; + A1 |= (long)(bytes[index++] & 0xff) << j; + A2 |= (long)(bytes[index++] & 0xff) << j; + A3 |= (long)(bytes[index++] & 0xff) << j; + } + } + + private void PackBlock(Span bytes) + { + var index = 0; + + for (var j = 0; j != BC; j += 8) + { + bytes[index++] = (byte)(A0 >> j); + bytes[index++] = (byte)(A1 >> j); + bytes[index++] = (byte)(A2 >> j); + bytes[index++] = (byte)(A3 >> j); + } + } + + private void EncryptBlock(long[][] rk) + { + int r; + + // + // begin with a key addition + // + KeyAddition(rk[0]); + + // + // ROUNDS-1 ordinary rounds + // + for (r = 1; r < ROUNDS; r++) + { + Substitution(S); + ShiftRow(shifts0SC); + MixColumn(); + KeyAddition(rk[r]); + } + + // + // Last round is special: there is no MixColumn + // + Substitution(S); + ShiftRow(shifts0SC); + KeyAddition(rk[ROUNDS]); + } + + private void DecryptBlock(long[][] rk) + { + int r; + + // To decrypt: apply the inverse operations of the encrypt routine, + // in opposite order + // + // (KeyAddition is an involution: it 's equal to its inverse) + // (the inverse of Substitution with table S is Substitution with the inverse table of S) + // (the inverse of Shiftrow is Shiftrow over a suitable distance) + // + + // First the special round: + // without InvMixColumn + // with extra KeyAddition + // + KeyAddition(rk[ROUNDS]); + Substitution(Si); + ShiftRow(shifts1SC); + + // + // ROUNDS-1 ordinary rounds + // + for (r = ROUNDS - 1; r > 0; r--) + { + KeyAddition(rk[r]); + InvMixColumn(); + Substitution(Si); + ShiftRow(shifts1SC); + } + + // + // End with the extra key addition + // + KeyAddition(rk[0]); + } +} diff --git a/src/SharpCompress/Factories/Factory.cs b/src/SharpCompress/Factories/Factory.cs index baef3b85..7ec68508 100644 --- a/src/SharpCompress/Factories/Factory.cs +++ b/src/SharpCompress/Factories/Factory.cs @@ -19,7 +19,7 @@ public abstract class Factory : IFactory RegisterFactory(new TarFactory()); } - private static readonly HashSet _factories = new(); + private static readonly HashSet _factories = new HashSet(); /// /// Gets the collection of registered . diff --git a/src/SharpCompress/Factories/GZipFactory.cs b/src/SharpCompress/Factories/GZipFactory.cs index be1b4931..5e522f5b 100644 --- a/src/SharpCompress/Factories/GZipFactory.cs +++ b/src/SharpCompress/Factories/GZipFactory.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; + using SharpCompress.Archives; using SharpCompress.Archives.GZip; using SharpCompress.Archives.Tar; diff --git a/src/SharpCompress/Factories/TarFactory.cs b/src/SharpCompress/Factories/TarFactory.cs index 715a05d2..61965b86 100644 --- a/src/SharpCompress/Factories/TarFactory.cs +++ b/src/SharpCompress/Factories/TarFactory.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; using System.IO; + using SharpCompress.Archives; using SharpCompress.Archives.Tar; using SharpCompress.Common; using SharpCompress.Compressors; using SharpCompress.Compressors.BZip2; using SharpCompress.Compressors.LZMA; -using SharpCompress.Compressors.Lzw; using SharpCompress.Compressors.Xz; using SharpCompress.IO; using SharpCompress.Readers; @@ -161,19 +161,6 @@ public class TarFactory } } - rewindableStream.Rewind(false); - if (LzwStream.IsLzwStream(rewindableStream)) - { - rewindableStream.Rewind(false); - var testStream = new LzwStream(rewindableStream); - if (TarArchive.IsTarFile(testStream)) - { - rewindableStream.Rewind(true); - reader = new TarReader(rewindableStream, options, CompressionType.Lzw); - return true; - } - } - return false; } diff --git a/src/SharpCompress/Factories/ZipFactory.cs b/src/SharpCompress/Factories/ZipFactory.cs index 780d2a9c..dca697dc 100644 --- a/src/SharpCompress/Factories/ZipFactory.cs +++ b/src/SharpCompress/Factories/ZipFactory.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; + using SharpCompress.Archives; using SharpCompress.Archives.Zip; using SharpCompress.Common; diff --git a/src/SharpCompress/IO/BufferedSubStream.cs b/src/SharpCompress/IO/BufferedSubStream.cs index 243d1ca9..99e2bfef 100644 --- a/src/SharpCompress/IO/BufferedSubStream.cs +++ b/src/SharpCompress/IO/BufferedSubStream.cs @@ -1,16 +1,24 @@ -using System; +using System; using System.IO; namespace SharpCompress.IO; -internal class BufferedSubStream(Stream stream, long origin, long bytesToRead) - : NonDisposingStream(stream, throwOnDispose: false) +internal class BufferedSubStream : NonDisposingStream { - private int _cacheOffset; - private int _cacheLength; - private readonly byte[] _cache = new byte[32 << 10]; + private long position; + private int cacheOffset; + private int cacheLength; + private readonly byte[] cache; - private long BytesLeftToRead { get; set; } = bytesToRead; + public BufferedSubStream(Stream stream, long origin, long bytesToRead) + : base(stream, throwOnDispose: false) + { + position = origin; + BytesLeftToRead = bytesToRead; + cache = new byte[32 << 10]; + } + + private long BytesLeftToRead { get; set; } public override bool CanRead => true; @@ -18,7 +26,7 @@ internal class BufferedSubStream(Stream stream, long origin, long bytesToRead) public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => BytesLeftToRead; @@ -37,22 +45,22 @@ internal class BufferedSubStream(Stream stream, long origin, long bytesToRead) if (count > 0) { - if (_cacheLength == 0) + if (cacheLength == 0) { - _cacheOffset = 0; - Stream.Position = origin; - _cacheLength = Stream.Read(_cache, 0, _cache.Length); - origin += _cacheLength; + cacheOffset = 0; + Stream.Position = position; + cacheLength = Stream.Read(cache, 0, cache.Length); + position += cacheLength; } - if (count > _cacheLength) + if (count > cacheLength) { - count = _cacheLength; + count = cacheLength; } - Buffer.BlockCopy(_cache, _cacheOffset, buffer, offset, count); - _cacheOffset += count; - _cacheLength -= count; + Buffer.BlockCopy(cache, cacheOffset, buffer, offset, count); + cacheOffset += count; + cacheLength -= count; BytesLeftToRead -= count; } diff --git a/src/SharpCompress/IO/DataDescriptorStream.cs b/src/SharpCompress/IO/DataDescriptorStream.cs index 1802556c..8ba9eb0f 100644 --- a/src/SharpCompress/IO/DataDescriptorStream.cs +++ b/src/SharpCompress/IO/DataDescriptorStream.cs @@ -8,18 +8,18 @@ public class DataDescriptorStream : Stream { private readonly Stream _stream; private long _start; - private int _searchPosition; + private int _search_position; private bool _isDisposed; private bool _done; - private static byte[] _dataDescriptorMarker = new byte[] { 0x50, 0x4b, 0x07, 0x08 }; - private static long _dataDescriptorSize = 24; + private static byte[] DataDescriptorMarker = new byte[] { 0x50, 0x4b, 0x07, 0x08 }; + private static long DataDescriptorSize = 24; public DataDescriptorStream(Stream stream) { _stream = stream; _start = _stream.Position; - _searchPosition = 0; + _search_position = 0; _done = false; } @@ -45,13 +45,13 @@ public class DataDescriptorStream : Stream public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => _stream.Length; public override long Position { - get => _stream.Position - _start; + get => _stream.Position; set => _stream.Position = value; } @@ -60,20 +60,20 @@ public class DataDescriptorStream : Stream var br = new BinaryReader(stream); br.ReadUInt32(); br.ReadUInt32(); // CRC32 can be checked if we calculate it - var compressedSize = br.ReadUInt32(); - var uncompressedSize = br.ReadUInt32(); - var uncompressed64Bit = br.ReadInt64(); + var compressed_size = br.ReadUInt32(); + var uncompressed_size = br.ReadUInt32(); + var uncompressed_64bit = br.ReadInt64(); - stream.Position -= _dataDescriptorSize; + stream.Position -= DataDescriptorSize; - var test64Bit = ((long)uncompressedSize << 32) | compressedSize; + var test_64bit = ((long)uncompressed_size << 32) | compressed_size; - if (test64Bit == size && test64Bit == uncompressed64Bit) + if (test_64bit == size && test_64bit == uncompressed_64bit) { return true; } - if (compressedSize == size && compressedSize == uncompressedSize) + if (compressed_size == size && compressed_size == uncompressed_size) { return true; } @@ -88,24 +88,24 @@ public class DataDescriptorStream : Stream return 0; } - var read = _stream.Read(buffer, offset, count); + int read = _stream.Read(buffer, offset, count); - for (var i = 0; i < read; i++) + for (int i = 0; i < read; i++) { - if (buffer[offset + i] == _dataDescriptorMarker[_searchPosition]) + if (buffer[offset + i] == DataDescriptorMarker[_search_position]) { - _searchPosition++; + _search_position++; - if (_searchPosition == 4) + if (_search_position == 4) { - _searchPosition = 0; + _search_position = 0; - if (read - i > _dataDescriptorSize) + if (read - i > DataDescriptorSize) { var check = new MemoryStream( buffer, offset + i - 3, - (int)_dataDescriptorSize + (int)DataDescriptorSize ); _done = validate_data_descriptor( check, @@ -131,15 +131,15 @@ public class DataDescriptorStream : Stream } else { - _searchPosition = 0; + _search_position = 0; } } - if (_searchPosition > 0) + if (_search_position > 0) { - read -= _searchPosition; - _stream.Position -= _searchPosition; - _searchPosition = 0; + read -= _search_position; + _stream.Position -= _search_position; + _search_position = 0; } return read; diff --git a/src/SharpCompress/IO/ListeningStream.cs b/src/SharpCompress/IO/ListeningStream.cs index 0acf1056..a1bf715b 100644 --- a/src/SharpCompress/IO/ListeningStream.cs +++ b/src/SharpCompress/IO/ListeningStream.cs @@ -5,13 +5,13 @@ namespace SharpCompress.IO; internal class ListeningStream : Stream { - private long _currentEntryTotalReadBytes; - private readonly IExtractionListener _listener; + private long currentEntryTotalReadBytes; + private readonly IExtractionListener listener; public ListeningStream(IExtractionListener listener, Stream stream) { Stream = stream; - this._listener = listener; + this.listener = listener; } protected override void Dispose(bool disposing) @@ -44,8 +44,8 @@ internal class ListeningStream : Stream public override int Read(byte[] buffer, int offset, int count) { var read = Stream.Read(buffer, offset, count); - _currentEntryTotalReadBytes += read; - _listener.FireCompressedBytesRead(_currentEntryTotalReadBytes, _currentEntryTotalReadBytes); + currentEntryTotalReadBytes += read; + listener.FireCompressedBytesRead(currentEntryTotalReadBytes, currentEntryTotalReadBytes); return read; } @@ -57,8 +57,8 @@ internal class ListeningStream : Stream return -1; } - ++_currentEntryTotalReadBytes; - _listener.FireCompressedBytesRead(_currentEntryTotalReadBytes, _currentEntryTotalReadBytes); + ++currentEntryTotalReadBytes; + listener.FireCompressedBytesRead(currentEntryTotalReadBytes, currentEntryTotalReadBytes); return value; } diff --git a/src/SharpCompress/IO/ReadOnlySubStream.cs b/src/SharpCompress/IO/ReadOnlySubStream.cs index cd39335e..c0b39d54 100644 --- a/src/SharpCompress/IO/ReadOnlySubStream.cs +++ b/src/SharpCompress/IO/ReadOnlySubStream.cs @@ -29,7 +29,7 @@ internal class ReadOnlySubStream : NonDisposingStream public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => throw new NotSupportedException(); @@ -72,8 +72,8 @@ internal class ReadOnlySubStream : NonDisposingStream #if !NETFRAMEWORK && !NETSTANDARD2_0 public override int Read(Span buffer) { - var sliceLen = BytesLeftToRead < buffer.Length ? BytesLeftToRead : buffer.Length; - var read = Stream.Read(buffer.Slice(0, (int)sliceLen)); + var slice_len = BytesLeftToRead < buffer.Length ? BytesLeftToRead : buffer.Length; + var read = Stream.Read(buffer.Slice(0, (int)slice_len)); if (read > 0) { BytesLeftToRead -= read; diff --git a/src/SharpCompress/IO/RewindableStream.cs b/src/SharpCompress/IO/RewindableStream.cs index c7febd1d..ccdc8ee0 100644 --- a/src/SharpCompress/IO/RewindableStream.cs +++ b/src/SharpCompress/IO/RewindableStream.cs @@ -5,98 +5,98 @@ namespace SharpCompress.IO; public class RewindableStream : Stream { - private readonly Stream _stream; - private MemoryStream _bufferStream = new(); - private bool _isRewound; - private bool _isDisposed; + private readonly Stream stream; + private MemoryStream bufferStream = new MemoryStream(); + private bool isRewound; + private bool isDisposed; - public RewindableStream(Stream stream) => this._stream = stream; + public RewindableStream(Stream stream) => this.stream = stream; internal bool IsRecording { get; private set; } protected override void Dispose(bool disposing) { - if (_isDisposed) + if (isDisposed) { return; } - _isDisposed = true; + isDisposed = true; base.Dispose(disposing); if (disposing) { - _stream.Dispose(); + stream.Dispose(); } } public void Rewind(bool stopRecording) { - _isRewound = true; + isRewound = true; IsRecording = !stopRecording; - _bufferStream.Position = 0; + bufferStream.Position = 0; } public void Rewind(MemoryStream buffer) { - if (_bufferStream.Position >= buffer.Length) + if (bufferStream.Position >= buffer.Length) { - _bufferStream.Position -= buffer.Length; + bufferStream.Position -= buffer.Length; } else { - _bufferStream.TransferTo(buffer); + bufferStream.TransferTo(buffer); //create new memorystream to allow proper resizing as memorystream could be a user provided buffer //https://github.com/adamhathcock/sharpcompress/issues/306 - _bufferStream = new MemoryStream(); + bufferStream = new MemoryStream(); buffer.Position = 0; - buffer.TransferTo(_bufferStream); - _bufferStream.Position = 0; + buffer.TransferTo(bufferStream); + bufferStream.Position = 0; } - _isRewound = true; + isRewound = true; } public void StartRecording() { //if (isRewound && bufferStream.Position != 0) // throw new System.NotImplementedException(); - if (_bufferStream.Position != 0) + if (bufferStream.Position != 0) { - var data = _bufferStream.ToArray(); - var position = _bufferStream.Position; - _bufferStream.SetLength(0); - _bufferStream.Write(data, (int)position, data.Length - (int)position); - _bufferStream.Position = 0; + var data = bufferStream.ToArray(); + var position = bufferStream.Position; + bufferStream.SetLength(0); + bufferStream.Write(data, (int)position, data.Length - (int)position); + bufferStream.Position = 0; } IsRecording = true; } public override bool CanRead => true; - public override bool CanSeek => _stream.CanSeek; + public override bool CanSeek => stream.CanSeek; public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); - public override long Length => _stream.Length; + public override long Length => stream.Length; public override long Position { - get => _stream.Position + _bufferStream.Position - _bufferStream.Length; + get => stream.Position + bufferStream.Position - bufferStream.Length; set { - if (!_isRewound) + if (!isRewound) { - _stream.Position = value; + stream.Position = value; } - else if (value < _stream.Position - _bufferStream.Length || value >= _stream.Position) + else if (value < stream.Position - bufferStream.Length || value >= stream.Position) { - _stream.Position = value; - _isRewound = false; - _bufferStream.SetLength(0); + stream.Position = value; + isRewound = false; + bufferStream.SetLength(0); } else { - _bufferStream.Position = value - _stream.Position + _bufferStream.Length; + bufferStream.Position = value - stream.Position + bufferStream.Length; } } } @@ -110,32 +110,32 @@ public class RewindableStream : Stream return 0; } int read; - if (_isRewound && _bufferStream.Position != _bufferStream.Length) + if (isRewound && bufferStream.Position != bufferStream.Length) { // don't read more than left - var readCount = Math.Min(count, (int)(_bufferStream.Length - _bufferStream.Position)); - read = _bufferStream.Read(buffer, offset, readCount); + var readCount = Math.Min(count, (int)(bufferStream.Length - bufferStream.Position)); + read = bufferStream.Read(buffer, offset, readCount); if (read < readCount) { - var tempRead = _stream.Read(buffer, offset + read, count - read); + var tempRead = stream.Read(buffer, offset + read, count - read); if (IsRecording) { - _bufferStream.Write(buffer, offset + read, tempRead); + bufferStream.Write(buffer, offset + read, tempRead); } read += tempRead; } - if (_bufferStream.Position == _bufferStream.Length && !IsRecording) + if (bufferStream.Position == bufferStream.Length && !IsRecording) { - _isRewound = false; - _bufferStream.SetLength(0); + isRewound = false; + bufferStream.SetLength(0); } return read; } - read = _stream.Read(buffer, offset, count); + read = stream.Read(buffer, offset, count); if (IsRecording) { - _bufferStream.Write(buffer, offset, read); + bufferStream.Write(buffer, offset, read); } return read; } diff --git a/src/SharpCompress/IO/SourceStream.cs b/src/SharpCompress/IO/SourceStream.cs index 46c0a3f6..26ce0af1 100644 --- a/src/SharpCompress/IO/SourceStream.cs +++ b/src/SharpCompress/IO/SourceStream.cs @@ -11,8 +11,8 @@ public class SourceStream : Stream private long _prevSize; private readonly List _files; private readonly List _streams; - private readonly Func? _getFilePart; - private readonly Func? _getStreamPart; + private readonly Func _getFilePart; + private readonly Func _getStreamPart; private int _stream; public SourceStream(FileInfo file, Func getPart, ReaderOptions options) @@ -38,8 +38,8 @@ public class SourceStream : Stream if (!IsFileMode) { _streams.Add(stream!); - _getStreamPart = getStreamPart; - _getFilePart = _ => null; + _getStreamPart = getStreamPart!; + _getFilePart = _ => null!; if (stream is FileStream fileStream) { _files.Add(new FileInfo(fileStream.Name)); @@ -49,8 +49,8 @@ public class SourceStream : Stream { _files.Add(file!); _streams.Add(_files[0].OpenRead()); - _getFilePart = getFilePart; - _getStreamPart = _ => null; + _getFilePart = getFilePart!; + _getStreamPart = _ => null!; } _stream = 0; _prevSize = 0; @@ -78,7 +78,7 @@ public class SourceStream : Stream { if (IsFileMode) { - var f = _getFilePart.NotNull("GetFilePart is null")(_streams.Count); + var f = _getFilePart(_streams.Count); if (f == null) { _stream = _streams.Count - 1; @@ -90,7 +90,7 @@ public class SourceStream : Stream } else { - var s = _getStreamPart.NotNull("GetStreamPart is null")(_streams.Count); + var s = _getStreamPart(_streams.Count); if (s == null) { _stream = _streams.Count - 1; diff --git a/src/SharpCompress/Lazy.cs b/src/SharpCompress/Lazy.cs new file mode 100644 index 00000000..7a6abd55 --- /dev/null +++ b/src/SharpCompress/Lazy.cs @@ -0,0 +1,27 @@ +#nullable disable + +using System; + +namespace SharpCompress; + +public class Lazy +{ + private readonly Func _lazyFunc; + private bool _evaluated; + private T _value; + + public Lazy(Func lazyFunc) => _lazyFunc = lazyFunc; + + public T Value + { + get + { + if (!_evaluated) + { + _value = _lazyFunc(); + _evaluated = true; + } + return _value; + } + } +} diff --git a/src/SharpCompress/LazyReadOnlyCollection.cs b/src/SharpCompress/LazyReadOnlyCollection.cs index cc9cb3fd..8f5ee834 100644 --- a/src/SharpCompress/LazyReadOnlyCollection.cs +++ b/src/SharpCompress/LazyReadOnlyCollection.cs @@ -8,7 +8,7 @@ namespace SharpCompress; internal sealed class LazyReadOnlyCollection : ICollection { - private readonly List backing = new(); + private readonly List backing = new List(); private readonly IEnumerator source; private bool fullyLoaded; diff --git a/src/SharpCompress/NotNullExtensions.cs b/src/SharpCompress/NotNullExtensions.cs deleted file mode 100644 index 88e95c41..00000000 --- a/src/SharpCompress/NotNullExtensions.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; - -namespace SharpCompress; - -public static class NotNullExtensions -{ - public static IEnumerable Empty(this IEnumerable? source) => - source ?? Enumerable.Empty(); - - public static IEnumerable Empty(this T? source) - { - if (source is null) - { - return Enumerable.Empty(); - } - return source.AsEnumerable(); - } - -#if NETFRAMEWORK || NETSTANDARD - public static T NotNull(this T? obj, string? message = null) - where T : class - { - if (obj is null) - { - throw new ArgumentNullException(message ?? "Value is null"); - } - return obj; - } - - public static T NotNull(this T? obj, string? message = null) - where T : struct - { - if (obj is null) - { - throw new ArgumentNullException(message ?? "Value is null"); - } - return obj.Value; - } -#else - - public static T NotNull( - [NotNull] this T? obj, - [CallerArgumentExpression(nameof(obj))] string? paramName = null - ) - where T : class - { - ArgumentNullException.ThrowIfNull(obj, paramName); - return obj; - } - - public static T NotNull( - [NotNull] this T? obj, - [CallerArgumentExpression(nameof(obj))] string? paramName = null - ) - where T : struct - { - ArgumentNullException.ThrowIfNull(obj, paramName); - return obj.Value; - } -#endif -} diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index b36acd53..7927937f 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -13,9 +13,9 @@ public abstract class AbstractReader : IReader, IReaderExtracti where TEntry : Entry where TVolume : Volume { - private bool _completed; - private IEnumerator? _entriesForCurrentReadStream; - private bool _wroteCurrentEntry; + private bool completed; + private IEnumerator? entriesForCurrentReadStream; + private bool wroteCurrentEntry; public event EventHandler>? EntryExtractionProgress; @@ -35,18 +35,18 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// /// Current volume that the current entry resides in /// - public abstract TVolume? Volume { get; } + public abstract TVolume Volume { get; } /// /// Current file entry /// - public TEntry Entry => _entriesForCurrentReadStream.NotNull().Current; + public TEntry Entry => entriesForCurrentReadStream!.Current; #region IDisposable Members public void Dispose() { - _entriesForCurrentReadStream?.Dispose(); + entriesForCurrentReadStream?.Dispose(); Volume?.Dispose(); } @@ -61,7 +61,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// public void Cancel() { - if (!_completed) + if (!completed) { Cancelled = true; } @@ -69,35 +69,35 @@ public abstract class AbstractReader : IReader, IReaderExtracti public bool MoveToNextEntry() { - if (_completed) + if (completed) { return false; } if (Cancelled) { - throw new ReaderCancelledException("Reader has been cancelled."); + throw new InvalidOperationException("Reader has been cancelled."); } - if (_entriesForCurrentReadStream is null) + if (entriesForCurrentReadStream is null) { return LoadStreamForReading(RequestInitialStream()); } - if (!_wroteCurrentEntry) + if (!wroteCurrentEntry) { SkipEntry(); } - _wroteCurrentEntry = false; + wroteCurrentEntry = false; if (NextEntryForCurrentStream()) { return true; } - _completed = true; + completed = true; return false; } protected bool LoadStreamForReading(Stream stream) { - _entriesForCurrentReadStream?.Dispose(); - if (stream is null || !stream.CanRead) + entriesForCurrentReadStream?.Dispose(); + if ((stream is null) || (!stream.CanRead)) { throw new MultipartStreamRequiredException( "File is split into multiple archives: '" @@ -105,15 +105,13 @@ public abstract class AbstractReader : IReader, IReaderExtracti + "'. A new readable stream is required. Use Cancel if it was intended." ); } - _entriesForCurrentReadStream = GetEntries(stream).GetEnumerator(); - return _entriesForCurrentReadStream.MoveNext(); + entriesForCurrentReadStream = GetEntries(stream).GetEnumerator(); + return entriesForCurrentReadStream.MoveNext(); } - protected virtual Stream RequestInitialStream() => - Volume.NotNull("Volume isn't loaded.").Stream; + protected virtual Stream RequestInitialStream() => Volume.Stream; - internal virtual bool NextEntryForCurrentStream() => - _entriesForCurrentReadStream.NotNull().MoveNext(); + internal virtual bool NextEntryForCurrentStream() => entriesForCurrentReadStream!.MoveNext(); protected abstract IEnumerable GetEntries(Stream stream); @@ -151,7 +149,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti public void WriteEntryTo(Stream writableStream) { - if (_wroteCurrentEntry) + if (wroteCurrentEntry) { throw new ArgumentException("WriteEntryTo or OpenEntryStream can only be called once."); } @@ -168,7 +166,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti } Write(writableStream); - _wroteCurrentEntry = true; + wroteCurrentEntry = true; } internal void Write(Stream writeStream) @@ -180,19 +178,20 @@ public abstract class AbstractReader : IReader, IReaderExtracti public EntryStream OpenEntryStream() { - if (_wroteCurrentEntry) + if (wroteCurrentEntry) { throw new ArgumentException("WriteEntryTo or OpenEntryStream can only be called once."); } var stream = GetEntryStream(); - _wroteCurrentEntry = true; + wroteCurrentEntry = true; return stream; } /// /// Retains a reference to the entry stream, so we can check whether it completed later. /// - protected EntryStream CreateEntryStream(Stream decompressed) => new(this, decompressed); + protected EntryStream CreateEntryStream(Stream decompressed) => + new EntryStream(this, decompressed); protected virtual EntryStream GetEntryStream() => CreateEntryStream(Entry.Parts.First().GetCompressedStream()); diff --git a/src/SharpCompress/Readers/GZip/GZipReader.cs b/src/SharpCompress/Readers/GZip/GZipReader.cs index 73bc4a9d..27394cc7 100644 --- a/src/SharpCompress/Readers/GZip/GZipReader.cs +++ b/src/SharpCompress/Readers/GZip/GZipReader.cs @@ -7,8 +7,8 @@ namespace SharpCompress.Readers.GZip; public class GZipReader : AbstractReader { - private GZipReader(Stream stream, ReaderOptions options) - : base(options, ArchiveType.GZip) => Volume = new GZipVolume(stream, options, 0); + internal GZipReader(Stream stream, ReaderOptions options) + : base(options, ArchiveType.GZip) => Volume = new GZipVolume(stream, options); public override GZipVolume Volume { get; } diff --git a/src/SharpCompress/Readers/Rar/MultiVolumeRarReader.cs b/src/SharpCompress/Readers/Rar/MultiVolumeRarReader.cs index 556ca9f5..76899e0c 100644 --- a/src/SharpCompress/Readers/Rar/MultiVolumeRarReader.cs +++ b/src/SharpCompress/Readers/Rar/MultiVolumeRarReader.cs @@ -17,7 +17,7 @@ internal class MultiVolumeRarReader : RarReader internal MultiVolumeRarReader(IEnumerable streams, ReaderOptions options) : base(options) => this.streams = streams.GetEnumerator(); - protected override void ValidateArchive(RarVolume archive) { } + internal override void ValidateArchive(RarVolume archive) { } protected override Stream RequestInitialStream() { diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index 2398cfac..da8c132b 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -14,16 +13,17 @@ namespace SharpCompress.Readers.Rar; public abstract class RarReader : AbstractReader { private RarVolume? volume; - private Lazy UnpackV2017 { get; } = - new(() => new Compressors.Rar.UnpackV2017.Unpack()); - private Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); + internal Lazy UnpackV2017 { get; } = + new Lazy(() => new Compressors.Rar.UnpackV2017.Unpack()); + internal Lazy UnpackV1 { get; } = + new Lazy(() => new Compressors.Rar.UnpackV1.Unpack()); internal RarReader(ReaderOptions options) : base(options, ArchiveType.Rar) { } - protected abstract void ValidateArchive(RarVolume archive); + internal abstract void ValidateArchive(RarVolume archive); - public override RarVolume? Volume => volume; + public override RarVolume Volume => volume!; /// /// Opens a RarReader for Non-seeking usage with a single volume @@ -51,7 +51,7 @@ public abstract class RarReader : AbstractReader protected override IEnumerable GetEntries(Stream stream) { - volume = new RarReaderVolume(stream, Options, 0); + volume = new RarReaderVolume(stream, Options); foreach (var fp in volume.ReadFileParts()) { ValidateArchive(volume); @@ -64,11 +64,6 @@ public abstract class RarReader : AbstractReader protected override EntryStream GetEntryStream() { - if (Entry.IsRedir) - { - throw new InvalidOperationException("no stream for redirect entry"); - } - var stream = new MultiVolumeReadOnlyStream( CreateFilePartEnumerableForCurrentEntry().Cast(), this @@ -77,14 +72,6 @@ public abstract class RarReader : AbstractReader { return CreateEntryStream(new RarCrcStream(UnpackV1.Value, Entry.FileHeader, stream)); } - - if (Entry.FileHeader.FileCrc.Length > 5) - { - return CreateEntryStream( - new RarBLAKE2spStream(UnpackV2017.Value, Entry.FileHeader, stream) - ); - } - return CreateEntryStream(new RarCrcStream(UnpackV2017.Value, Entry.FileHeader, stream)); } } diff --git a/src/SharpCompress/Readers/Rar/RarReaderVolume.cs b/src/SharpCompress/Readers/Rar/RarReaderVolume.cs index d614260a..85beb897 100644 --- a/src/SharpCompress/Readers/Rar/RarReaderVolume.cs +++ b/src/SharpCompress/Readers/Rar/RarReaderVolume.cs @@ -8,7 +8,7 @@ namespace SharpCompress.Readers.Rar; public class RarReaderVolume : RarVolume { - internal RarReaderVolume(Stream stream, ReaderOptions options, int index) + internal RarReaderVolume(Stream stream, ReaderOptions options, int index = 0) : base(StreamingMode.Streaming, stream, options, index) { } internal override RarFilePart CreateFilePart(MarkHeader markHeader, FileHeader fileHeader) => diff --git a/src/SharpCompress/Readers/Rar/SingleVolumeRarReader.cs b/src/SharpCompress/Readers/Rar/SingleVolumeRarReader.cs index 165c92f7..768aa115 100644 --- a/src/SharpCompress/Readers/Rar/SingleVolumeRarReader.cs +++ b/src/SharpCompress/Readers/Rar/SingleVolumeRarReader.cs @@ -11,7 +11,7 @@ internal class SingleVolumeRarReader : RarReader internal SingleVolumeRarReader(Stream stream, ReaderOptions options) : base(options) => this.stream = stream; - protected override void ValidateArchive(RarVolume archive) + internal override void ValidateArchive(RarVolume archive) { if (archive.IsMultiVolume) { diff --git a/src/SharpCompress/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index a686dc11..c9802e46 100644 --- a/src/SharpCompress/Readers/Tar/TarReader.cs +++ b/src/SharpCompress/Readers/Tar/TarReader.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using SharpCompress.Archives.GZip; @@ -8,10 +8,9 @@ using SharpCompress.Common.Tar; using SharpCompress.Compressors; using SharpCompress.Compressors.BZip2; using SharpCompress.Compressors.Deflate; -using SharpCompress.Compressors.LZMA; -using SharpCompress.Compressors.Lzw; -using SharpCompress.Compressors.Xz; using SharpCompress.IO; +using SharpCompress.Compressors.LZMA; +using SharpCompress.Compressors.Xz; namespace SharpCompress.Readers.Tar; @@ -31,16 +30,33 @@ public class TarReader : AbstractReader protected override Stream RequestInitialStream() { var stream = base.RequestInitialStream(); - return compressionType switch + switch (compressionType) { - CompressionType.BZip2 => new BZip2Stream(stream, CompressionMode.Decompress, false), - CompressionType.GZip => new GZipStream(stream, CompressionMode.Decompress), - CompressionType.LZip => new LZipStream(stream, CompressionMode.Decompress), - CompressionType.Xz => new XZStream(stream), - CompressionType.Lzw => new LzwStream(stream), - CompressionType.None => stream, - _ => throw new NotSupportedException("Invalid compression type: " + compressionType) - }; + case CompressionType.BZip2: + { + return new BZip2Stream(stream, CompressionMode.Decompress, false); + } + case CompressionType.GZip: + { + return new GZipStream(stream, CompressionMode.Decompress); + } + case CompressionType.LZip: + { + return new LZipStream(stream, CompressionMode.Decompress); + } + case CompressionType.Xz: + { + return new XZStream(stream); + } + case CompressionType.None: + { + return stream; + } + default: + { + throw new NotSupportedException("Invalid compression type: " + compressionType); + } + } } #region Open @@ -55,12 +71,12 @@ public class TarReader : AbstractReader { stream.CheckNotNull(nameof(stream)); options = options ?? new ReaderOptions(); - var rewindableStream = new RewindableStream(stream); + RewindableStream rewindableStream = new RewindableStream(stream); rewindableStream.StartRecording(); if (GZipArchive.IsGZipFile(rewindableStream)) { rewindableStream.Rewind(false); - var testStream = new GZipStream(rewindableStream, CompressionMode.Decompress); + GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress); if (TarArchive.IsTarFile(testStream)) { rewindableStream.Rewind(true); @@ -73,7 +89,11 @@ public class TarReader : AbstractReader if (BZip2Stream.IsBZip2(rewindableStream)) { rewindableStream.Rewind(false); - var testStream = new BZip2Stream(rewindableStream, CompressionMode.Decompress, false); + BZip2Stream testStream = new BZip2Stream( + rewindableStream, + CompressionMode.Decompress, + false + ); if (TarArchive.IsTarFile(testStream)) { rewindableStream.Rewind(true); @@ -86,7 +106,7 @@ public class TarReader : AbstractReader if (LZipStream.IsLZipFile(rewindableStream)) { rewindableStream.Rewind(false); - var testStream = new LZipStream(rewindableStream, CompressionMode.Decompress); + LZipStream testStream = new LZipStream(rewindableStream, CompressionMode.Decompress); if (TarArchive.IsTarFile(testStream)) { rewindableStream.Rewind(true); diff --git a/src/SharpCompress/Readers/Zip/ZipReader.cs b/src/SharpCompress/Readers/Zip/ZipReader.cs index cda3f3f8..b00690f0 100644 --- a/src/SharpCompress/Readers/Zip/ZipReader.cs +++ b/src/SharpCompress/Readers/Zip/ZipReader.cs @@ -69,6 +69,7 @@ public class ZipReader : AbstractReader switch (h.ZipHeaderType) { case ZipHeaderType.LocalEntry: + { yield return new ZipEntry( new StreamingZipFilePart((LocalEntryHeader)h, stream) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index cbceba12..efdd0a47 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -2,14 +2,14 @@ SharpCompress - Pure C# Decompression/Compression en-US - 0.37.2 - 0.37.2 - 0.37.2 + 0.34.1 + 0.34.1 + 0.34.1 Adam Hathcock - net462;netstandard2.0;netstandard2.1;net6.0;net8.0 + net462;netstandard2.0;netstandard2.1;net6.0;net7.0 SharpCompress ../../SharpCompress.snk - true + False SharpCompress rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz https://github.com/adamhathcock/sharpcompress @@ -17,39 +17,28 @@ Copyright (c) 2014 Adam Hathcock false false - SharpCompress is a compression library for NET Standard 2.0/NET Standard 2.1/NET 6.0/NET 8.0 that can unrar, decompress 7zip, decompress xz, zip/unzip, tar/untar lzip/unlzip, bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented. + SharpCompress is a compression library for NET Standard 2.0/2.1/NET 6.0/NET 7.0 that can unrar, decompress 7zip, decompress xz, zip/unzip, tar/untar lzip/unlzip, bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented. true true snupkg + true latest - true - README.md + True - - true - - - - all - - - + + + + - - + + + + + - - - - - - - - + + - - - diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index bcecafb4..9471c3e1 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -9,7 +9,8 @@ namespace SharpCompress; [CLSCompliant(false)] public static class Utility { - public static ReadOnlyCollection ToReadOnly(this ICollection items) => new(items); + public static ReadOnlyCollection ToReadOnly(this ICollection items) => + new ReadOnlyCollection(items); /// /// Performs an unsigned bitwise right shift with the specified number @@ -277,42 +278,8 @@ public static class Utility long total = 0; while (ReadTransferBlock(source, array, out var count)) { - destination.Write(array, 0, count); total += count; - } - return total; - } - finally - { - ArrayPool.Shared.Return(array); - } - } - - public static long TransferTo(this Stream source, Stream destination, long maxLength) - { - var array = GetTransferByteArray(); - var maxReadSize = array.Length; - try - { - long total = 0; - var remaining = maxLength; - if (remaining < maxReadSize) - { - maxReadSize = (int)remaining; - } - while (ReadTransferBlock(source, array, maxReadSize, out var count)) - { destination.Write(array, 0, count); - total += count; - if (remaining - count < 0) - { - break; - } - remaining -= count; - if (remaining < maxReadSize) - { - maxReadSize = (int)remaining; - } } return total; } @@ -352,16 +319,6 @@ public static class Utility private static bool ReadTransferBlock(Stream source, byte[] array, out int count) => (count = source.Read(array, 0, array.Length)) != 0; - private static bool ReadTransferBlock(Stream source, byte[] array, int size, out int count) - { - if (size > array.Length) - { - size = array.Length; - } - count = source.Read(array, 0, size); - return count != 0; - } - private static byte[] GetTransferByteArray() => ArrayPool.Shared.Rent(81920); public static bool ReadFully(this Stream stream, byte[] buffer) diff --git a/src/SharpCompress/Writers/AbstractWriter.cs b/src/SharpCompress/Writers/AbstractWriter.cs index 1820c986..209c49f7 100644 --- a/src/SharpCompress/Writers/AbstractWriter.cs +++ b/src/SharpCompress/Writers/AbstractWriter.cs @@ -1,24 +1,28 @@ -using System; +#nullable disable + +using System; using System.IO; using SharpCompress.Common; namespace SharpCompress.Writers; -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. -public abstract class AbstractWriter(ArchiveType type, WriterOptions writerOptions) : IWriter +public abstract class AbstractWriter : IWriter { private bool _isDisposed; - //always initializes the stream + protected AbstractWriter(ArchiveType type, WriterOptions writerOptions) + { + WriterType = type; + WriterOptions = writerOptions; + } - protected void InitializeStream(Stream stream) => OutputStream = stream; + protected void InitalizeStream(Stream stream) => OutputStream = stream; protected Stream OutputStream { get; private set; } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public ArchiveType WriterType { get; } = type; + public ArchiveType WriterType { get; } - protected WriterOptions WriterOptions { get; } = writerOptions; + protected WriterOptions WriterOptions { get; } public abstract void Write(string filename, Stream source, DateTime? modificationTime); diff --git a/src/SharpCompress/Writers/GZip/GZipWriter.cs b/src/SharpCompress/Writers/GZip/GZipWriter.cs index f30fdb55..5c990a7d 100644 --- a/src/SharpCompress/Writers/GZip/GZipWriter.cs +++ b/src/SharpCompress/Writers/GZip/GZipWriter.cs @@ -18,7 +18,7 @@ public sealed class GZipWriter : AbstractWriter { destination = NonDisposingStream.Create(destination); } - InitializeStream( + InitalizeStream( new GZipStream( destination, CompressionMode.Compress, diff --git a/src/SharpCompress/Writers/IWriterFactory.cs b/src/SharpCompress/Writers/IWriterFactory.cs index 094a5553..8e7bc701 100644 --- a/src/SharpCompress/Writers/IWriterFactory.cs +++ b/src/SharpCompress/Writers/IWriterFactory.cs @@ -1,4 +1,5 @@ using System.IO; + using SharpCompress.Factories; namespace SharpCompress.Writers; diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index a3e572f1..2427db37 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -32,16 +32,19 @@ public class TarWriter : AbstractWriter case CompressionType.None: break; case CompressionType.BZip2: + { destination = new BZip2Stream(destination, CompressionMode.Compress, false); } break; case CompressionType.GZip: + { destination = new GZipStream(destination, CompressionMode.Compress); } break; case CompressionType.LZip: + { destination = new LZipStream(destination, CompressionMode.Compress); } @@ -53,7 +56,7 @@ public class TarWriter : AbstractWriter ); } } - InitializeStream(destination); + InitalizeStream(destination); } public override void Write(string filename, Stream source, DateTime? modificationTime) => @@ -87,7 +90,8 @@ public class TarWriter : AbstractWriter header.Name = NormalizeFilename(filename); header.Size = realSize; header.Write(OutputStream); - size = source.TransferTo(OutputStream, realSize); + + size = source.TransferTo(OutputStream); PadTo512(size.Value); } diff --git a/src/SharpCompress/Writers/WriterFactory.cs b/src/SharpCompress/Writers/WriterFactory.cs index 50e1fdfc..fcbf2d68 100644 --- a/src/SharpCompress/Writers/WriterFactory.cs +++ b/src/SharpCompress/Writers/WriterFactory.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; + using SharpCompress.Common; namespace SharpCompress.Writers; @@ -9,8 +10,8 @@ public static class WriterFactory { public static IWriter Open(Stream stream, ArchiveType archiveType, WriterOptions writerOptions) { - var factory = Factories - .Factory.Factories.OfType() + var factory = Factories.Factory.Factories + .OfType() .FirstOrDefault(item => item.KnownArchiveType == archiveType); if (factory != null) diff --git a/src/SharpCompress/Writers/WriterOptions.cs b/src/SharpCompress/Writers/WriterOptions.cs index e71f86f6..9d323c2b 100644 --- a/src/SharpCompress/Writers/WriterOptions.cs +++ b/src/SharpCompress/Writers/WriterOptions.cs @@ -9,5 +9,5 @@ public class WriterOptions : OptionsBase public CompressionType CompressionType { get; set; } public static implicit operator WriterOptions(CompressionType compressionType) => - new(compressionType); + new WriterOptions(compressionType); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index 1fb66a2b..e1fd222c 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -19,7 +19,7 @@ public class ZipWriter : AbstractWriter { private readonly CompressionType compressionType; private readonly CompressionLevel compressionLevel; - private readonly List entries = new(); + private readonly List entries = new List(); private readonly string zipComment; private long streamPosition; private PpmdProperties? ppmdProps; @@ -42,14 +42,14 @@ public class ZipWriter : AbstractWriter { destination = NonDisposingStream.Create(destination); } - InitializeStream(destination); + InitalizeStream(destination); } private PpmdProperties PpmdProperties => ppmdProps ??= new PpmdProperties(); protected override void Dispose(bool isDisposing) { - if (isDisposing && OutputStream is not null) + if (isDisposing) { ulong size = 0; foreach (var entry in entries) @@ -61,16 +61,34 @@ public class ZipWriter : AbstractWriter base.Dispose(isDisposing); } - private static ZipCompressionMethod ToZipCompressionMethod(CompressionType compressionType) => - compressionType switch + private static ZipCompressionMethod ToZipCompressionMethod(CompressionType compressionType) + { + switch (compressionType) { - CompressionType.None => ZipCompressionMethod.None, - CompressionType.Deflate => ZipCompressionMethod.Deflate, - CompressionType.BZip2 => ZipCompressionMethod.BZip2, - CompressionType.LZMA => ZipCompressionMethod.LZMA, - CompressionType.PPMd => ZipCompressionMethod.PPMd, - _ => throw new InvalidFormatException("Invalid compression method: " + compressionType) - }; + case CompressionType.None: + { + return ZipCompressionMethod.None; + } + case CompressionType.Deflate: + { + return ZipCompressionMethod.Deflate; + } + case CompressionType.BZip2: + { + return ZipCompressionMethod.BZip2; + } + case CompressionType.LZMA: + { + return ZipCompressionMethod.LZMA; + } + case CompressionType.PPMd: + { + return ZipCompressionMethod.PPMd; + } + default: + throw new InvalidFormatException("Invalid compression method: " + compressionType); + } + } public override void Write(string entryPath, Stream source, DateTime? modificationTime) => Write( @@ -114,7 +132,7 @@ public class ZipWriter : AbstractWriter streamPosition += headersize; return new ZipWritingStream( this, - OutputStream.NotNull(), + OutputStream, entry, compression, options.DeflateCompressionLevel ?? compressionLevel @@ -286,10 +304,7 @@ public class ZipWriter : AbstractWriter // Write normal end of central directory record OutputStream.Write(stackalloc byte[] { 80, 75, 5, 6, 0, 0, 0, 0 }); - BinaryPrimitives.WriteUInt16LittleEndian( - intBuf, - (ushort)(entries.Count < 0xFFFF ? entries.Count : 0xFFFF) - ); + BinaryPrimitives.WriteUInt16LittleEndian(intBuf, (ushort)entries.Count); OutputStream.Write(intBuf.Slice(0, 2)); OutputStream.Write(intBuf.Slice(0, 2)); BinaryPrimitives.WriteUInt32LittleEndian(intBuf, sizevalue); @@ -306,7 +321,7 @@ public class ZipWriter : AbstractWriter internal class ZipWritingStream : Stream { - private readonly CRC32 crc = new(); + private readonly CRC32 crc = new CRC32(); private readonly ZipCentralDirectoryEntry entry; private readonly Stream originalStream; private readonly Stream writeStream; @@ -419,14 +434,13 @@ public class ZipWriter : AbstractWriter return; } - var countingCount = counting?.Count ?? 0; entry.Crc = (uint)crc.Crc32Result; - entry.Compressed = countingCount; + entry.Compressed = counting!.Count; entry.Decompressed = decompressed; var zip64 = entry.Compressed >= uint.MaxValue || entry.Decompressed >= uint.MaxValue; - var compressedvalue = zip64 ? uint.MaxValue : (uint)countingCount; + var compressedvalue = zip64 ? uint.MaxValue : (uint)counting.Count; var decompressedvalue = zip64 ? uint.MaxValue : (uint)entry.Decompressed; if (originalStream.CanSeek) @@ -434,7 +448,7 @@ public class ZipWriter : AbstractWriter originalStream.Position = (long)(entry.HeaderOffset + 6); originalStream.WriteByte(0); - if (countingCount == 0 && entry.Decompressed == 0) + if (counting.Count == 0 && entry.Decompressed == 0) { // set compression to STORED for zero byte files (no compression data) originalStream.Position = (long)(entry.HeaderOffset + 8); @@ -521,12 +535,11 @@ public class ZipWriter : AbstractWriter // if we can prevent the writes from happening if (entry.Zip64HeaderOffset == 0) { - var countingCount = counting?.Count ?? 0; // Pre-check, the counting.Count is not exact, as we do not know the size before having actually compressed it if ( limitsExceeded || ((decompressed + (uint)count) > uint.MaxValue) - || (countingCount + (uint)count) > uint.MaxValue + || (counting!.Count + (uint)count) > uint.MaxValue ) { throw new NotSupportedException( @@ -541,9 +554,8 @@ public class ZipWriter : AbstractWriter if (entry.Zip64HeaderOffset == 0) { - var countingCount = counting?.Count ?? 0; // Post-check, this is accurate - if ((decompressed > uint.MaxValue) || countingCount > uint.MaxValue) + if ((decompressed > uint.MaxValue) || counting!.Count > uint.MaxValue) { // We have written the data, so the archive is now broken // Throwing the exception here, allows us to avoid diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json deleted file mode 100644 index b06d9c98..00000000 --- a/src/SharpCompress/packages.lock.json +++ /dev/null @@ -1,338 +0,0 @@ -{ - "version": 2, - "dependencies": { - ".NETFramework,Version=v4.6.2": { - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.NETFramework.ReferenceAssemblies": { - "type": "Direct", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==", - "dependencies": { - "Microsoft.NETFramework.ReferenceAssemblies.net462": "1.0.3" - } - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "System.Memory": { - "type": "Direct", - "requested": "[4.5.5, )", - "resolved": "4.5.5", - "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "ZstdSharp.Port": { - "type": "Direct", - "requested": "[0.8.0, )", - "resolved": "0.8.0", - "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "System.Memory": "4.5.5" - } - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.NETFramework.ReferenceAssemblies.net462": { - "type": "Transitive", - "resolved": "1.0.3", - "contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - } - }, - ".NETStandard,Version=v2.0": { - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "NETStandard.Library": { - "type": "Direct", - "requested": "[2.0.3, )", - "resolved": "2.0.3", - "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0" - } - }, - "System.Memory": { - "type": "Direct", - "requested": "[4.5.5, )", - "resolved": "4.5.5", - "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.4.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "ZstdSharp.Port": { - "type": "Direct", - "requested": "[0.8.0, )", - "resolved": "0.8.0", - "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "System.Memory": "4.5.5" - } - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - } - }, - ".NETStandard,Version=v2.1": { - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==" - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "ZstdSharp.Port": { - "type": "Direct", - "requested": "[0.8.0, )", - "resolved": "0.8.0", - "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Memory": { - "type": "CentralTransitive", - "requested": "[4.5.5, )", - "resolved": "4.5.5", - "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.4.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - } - }, - "net6.0": { - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "ZstdSharp.Port": { - "type": "Direct", - "requested": "[0.8.0, )", - "resolved": "0.8.0", - "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==" - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - } - }, - "net8.0": { - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[8.0.4, )", - "resolved": "8.0.4", - "contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw==" - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" - } - }, - "ZstdSharp.Port": { - "type": "Direct", - "requested": "[0.8.0, )", - "resolved": "0.8.0", - "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==" - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - } - } - } -} \ No newline at end of file diff --git a/tests/SharpCompress.Test/ADCTest.cs b/tests/SharpCompress.Test/ADCTest.cs index 8ef40a17..11bb2fb0 100644 --- a/tests/SharpCompress.Test/ADCTest.cs +++ b/tests/SharpCompress.Test/ADCTest.cs @@ -24,6 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System.IO; +using SharpCompress.Compressors; using SharpCompress.Compressors.ADC; using SharpCompress.Compressors.Deflate; using SharpCompress.Crypto; @@ -31,7 +32,7 @@ using Xunit; namespace SharpCompress.Test; -public class AdcTest : TestBase +public class ADCTest : TestBase { [Fact] public void TestBuffer() @@ -64,14 +65,14 @@ public class AdcTest : TestBase } [Fact] - public void TestAdcStreamWholeChunk() + public void TestADCStreamWholeChunk() { using var decFs = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "adc_decompressed.bin")); var decompressed = new byte[decFs.Length]; decFs.Read(decompressed, 0, decompressed.Length); using var cmpFs = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "adc_compressed.bin")); - using var decStream = new ADCStream(cmpFs); + using var decStream = new ADCStream(cmpFs, CompressionMode.Decompress); var test = new byte[262144]; decStream.Read(test, 0, test.Length); @@ -80,14 +81,14 @@ public class AdcTest : TestBase } [Fact] - public void TestAdcStream() + public void TestADCStream() { using var decFs = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "adc_decompressed.bin")); var decompressed = new byte[decFs.Length]; decFs.Read(decompressed, 0, decompressed.Length); using var cmpFs = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "adc_compressed.bin")); - using var decStream = new ADCStream(cmpFs); + using var decStream = new ADCStream(cmpFs, CompressionMode.Decompress); using var decMs = new MemoryStream(); var test = new byte[512]; var count = 0; @@ -114,11 +115,11 @@ public class AdcTest : TestBase decFs.Seek(0, SeekOrigin.Begin); - var crc32A = crcStream.Crc; + var crc32a = crcStream.Crc; - var crc32B = Crc32Stream.Compute(memory.ToArray()); + var crc32b = Crc32Stream.Compute(memory.ToArray()); - Assert.Equal(crc32, crc32A); - Assert.Equal(crc32, crc32B); + Assert.Equal(crc32, crc32a); + Assert.Equal(crc32, crc32b); } } diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index 7d94b29d..08377a0e 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -101,7 +101,7 @@ public class ArchiveTests : ReaderTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -138,12 +138,19 @@ public class ArchiveTests : ReaderTests ) ) { - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + try { - entry.WriteToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } - ); + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + { + entry.WriteToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + ); + } + } + catch (IndexOutOfRangeException) + { + throw; } } VerifyFiles(); @@ -170,12 +177,19 @@ public class ArchiveTests : ReaderTests ) ) { - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + try { - entry.WriteToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } - ); + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + { + entry.WriteToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + ); + } + } + catch (IndexOutOfRangeException) + { + throw; } } VerifyFiles(); @@ -192,29 +206,39 @@ public class ArchiveTests : ReaderTests testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x)) ); - private void ArchiveOpenEntryVolumeIndexTest( + protected void ArchiveOpenEntryVolumeIndexTest( int[][] results, ReaderOptions? readerOptions, IEnumerable testArchives ) { var src = testArchives.ToArray(); - using var archive = ArchiveFactory.Open(src.Select(f => new FileInfo(f)), readerOptions); - var idx = 0; - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + using var archive = ArchiveFactory.Open( + testArchives.Select(f => new FileInfo(f)), + readerOptions + ); + try { - Assert.Equal(entry.VolumeIndexFirst, results[idx][0]); - Assert.Equal(entry.VolumeIndexLast, results[idx][1]); - Assert.Equal( - src[entry.VolumeIndexFirst], - archive.Volumes.First(a => a.Index == entry.VolumeIndexFirst).FileName - ); - Assert.Equal( - src[entry.VolumeIndexLast], - archive.Volumes.First(a => a.Index == entry.VolumeIndexLast).FileName - ); + var idx = 0; + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + { + Assert.Equal(entry.VolumeIndexFirst, results[idx][0]); + Assert.Equal(entry.VolumeIndexLast, results[idx][1]); + Assert.Equal( + src[entry.VolumeIndexFirst], + archive.Volumes.First(a => a.Index == entry.VolumeIndexFirst).FileName + ); + Assert.Equal( + src[entry.VolumeIndexLast], + archive.Volumes.First(a => a.Index == entry.VolumeIndexLast).FileName + ); - idx++; + idx++; + } + } + catch (IndexOutOfRangeException) + { + throw; } } @@ -227,32 +251,13 @@ public class ArchiveTests : ReaderTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } VerifyFiles(); } - protected void ArchiveFileSkip( - string testArchive, - string fileOrder, - ReaderOptions? readerOptions = null - ) - { - if (!Environment.OSVersion.IsWindows()) - { - fileOrder = fileOrder.Replace('\\', '/'); - } - var expected = new Stack(fileOrder.Split(' ')); - testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); - using var archive = ArchiveFactory.Open(testArchive, readerOptions); - foreach (var entry in archive.Entries) - { - Assert.Equal(expected.Pop(), entry.Key); - } - } - /// /// Demonstrate the ExtractionOptions.PreserveFileTime and ExtractionOptions.PreserveAttributes extract options /// @@ -265,7 +270,7 @@ public class ArchiveTests : ReaderTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true, @@ -281,25 +286,25 @@ public class ArchiveTests : ReaderTests protected void ArchiveDeltaDistanceRead(string testArchive) { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); - using var archive = ArchiveFactory.Open(testArchive); - using var reader = archive.ExtractAllEntries(); - while (reader.MoveToNextEntry()) - { - if (!reader.Entry.IsDirectory) + using (var archive = Archives.ArchiveFactory.Open(testArchive, null)) + using (var reader = archive.ExtractAllEntries()) + while (reader.MoveToNextEntry()) { - var memory = new MemoryStream(); - reader.WriteEntryTo(memory); - - memory.Position = 0; - - for (var y = 0; y < 9; y++) - for (var x = 0; x < 256; x++) + if (!reader.Entry.IsDirectory) { - Assert.Equal(x, memory.ReadByte()); - } + var memory = new MemoryStream(); + reader.WriteEntryTo(memory); - Assert.Equal(-1, memory.ReadByte()); + memory.Position = 0; + + for (int y = 0; y < 9; y++) + for (int x = 0; x < 256; x++) + { + Assert.Equal(x, memory.ReadByte()); + } + + Assert.Equal((int)-1, memory.ReadByte()); + } } - } } } diff --git a/tests/SharpCompress.Test/BZip2/BZip2ReaderTests.cs b/tests/SharpCompress.Test/BZip2/BZip2ReaderTests.cs deleted file mode 100644 index e0fa0583..00000000 --- a/tests/SharpCompress.Test/BZip2/BZip2ReaderTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.IO; -using SharpCompress.Common; -using SharpCompress.IO; -using SharpCompress.Readers; -using SharpCompress.Readers.GZip; -using Xunit; - -namespace SharpCompress.Test.BZip2; - -public class BZip2ReaderTests : ReaderTests -{ - [Fact] - public void BZip2_Reader_Factory() - { - Stream stream = new MemoryStream( - new byte[] { 0x42, 0x5a, 0x68, 0x34, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0x35 } - ); - Assert.Throws(typeof(InvalidOperationException), () => ReaderFactory.Open(stream)); - } -} diff --git a/tests/SharpCompress.Test/Filters/BranchExecTests.cs b/tests/SharpCompress.Test/Filters/BranchExecTests.cs index ca9686a4..5c576dcc 100644 --- a/tests/SharpCompress.Test/Filters/BranchExecTests.cs +++ b/tests/SharpCompress.Test/Filters/BranchExecTests.cs @@ -12,8 +12,9 @@ namespace SharpCompress.Test.Filters; public class BranchExecTests { - private static byte[] X86ResultData { get; } = - [ + private static byte[] x86resultData { get; } = + new byte[] + { 0x12, 0x00, 0x00, @@ -91,11 +92,12 @@ public class BranchExecTests 0x00, 0x00, 0x1C, - 0x00 - ]; + 0x00, + }; - private static byte[] X86Data { get; } = - [ + private static byte[] x86Data { get; } = + new byte[] + { 0x12, 0x00, 0x00, @@ -173,11 +175,12 @@ public class BranchExecTests 0x00, 0x00, 0x1C, - 0x00 - ]; + 0x00, + }; - private static byte[] PpcResultData { get; } = - [ + private static byte[] ppcResultData { get; } = + new byte[] + { 0xF8, 0x6B, 0x2E, @@ -274,10 +277,11 @@ public class BranchExecTests 0xB2, 0xD4, 0xED - ]; + }; - private static byte[] PpcData { get; } = - [ + private static byte[] ppcData { get; } = + new byte[] + { 0xF8, 0x6B, 0x2E, @@ -374,10 +378,11 @@ public class BranchExecTests 0xB2, 0xD4, 0xED - ]; + }; - private static byte[] ArmResultData { get; } = - [ + private static byte[] armResultData { get; } = + new byte[] + { 0x7C, 0xFC, 0x0A, @@ -474,10 +479,11 @@ public class BranchExecTests 0xC6, 0x8F, 0xE2 - ]; + }; - private static byte[] ArmData { get; } = - [ + private static byte[] armData { get; } = + new byte[] + { 0x7C, 0xFC, 0x0A, @@ -574,10 +580,11 @@ public class BranchExecTests 0xC6, 0x8F, 0xE2 - ]; + }; - private static byte[] ArmtResultData { get; } = - [ + private static byte[] armtResultData { get; } = + new byte[] + { 0x95, 0x23, 0xB6, @@ -690,10 +697,11 @@ public class BranchExecTests 0xED, 0x11, 0x0F - ]; + }; - private static byte[] ArmtData { get; } = - [ + private static byte[] armtData { get; } = + new byte[] + { 0x95, 0x23, 0xB6, @@ -806,10 +814,11 @@ public class BranchExecTests 0xED, 0x11, 0x0F - ]; + }; - private static byte[] Ia64ResultData { get; } = - [ + private static byte[] ia64ResultData { get; } = + new byte[] + { 0x4D, 0xF8, 0xF2, @@ -906,10 +915,11 @@ public class BranchExecTests 0x72, 0xD5, 0x0D - ]; + }; - private static byte[] Ia64Data { get; } = - [ + private static byte[] ia64Data { get; } = + new byte[] + { 0x4D, 0xF8, 0xF2, @@ -1006,10 +1016,11 @@ public class BranchExecTests 0x72, 0xD5, 0x0D - ]; + }; - private static byte[] SparcResultData { get; } = - [ + private static byte[] sparcResultData { get; } = + new byte[] + { 0x78, 0x2E, 0x73, @@ -1087,11 +1098,12 @@ public class BranchExecTests 0x91, 0x00, 0x10, - 0x00 - ]; + 0x00, + }; - private static byte[] SparcData { get; } = - [ + private static byte[] sparcData { get; } = + new byte[] + { 0x78, 0x2E, 0x73, @@ -1169,8 +1181,8 @@ public class BranchExecTests 0x91, 0x00, 0x10, - 0x00 - ]; + 0x00, + }; private void CompareBuffer(byte[] testBuffer, byte[] targetBuffer) => Assert.Equal(testBuffer, targetBuffer); @@ -1180,53 +1192,53 @@ public class BranchExecTests { uint state = 0; uint ip = 0x2000; - var testData = X86Data; + var testData = x86Data; BranchExecFilter.X86Converter(testData, ip, ref state); - CompareBuffer(testData, X86ResultData); + CompareBuffer(testData, x86resultData); } [Fact] - public void PowerPcConverterDecodeTest() + public void PowerPCConverterDecodeTest() { uint ip = 0x6A0; - var testData = PpcData; + var testData = ppcData; BranchExecFilter.PowerPCConverter(testData, ip); - CompareBuffer(testData, PpcResultData); + CompareBuffer(testData, ppcResultData); } [Fact] - public void ArmConverteDecoderTest() + public void ARMConverteDecoderTest() { uint ip = 0x3C00; - var testData = ArmData; + var testData = armData; BranchExecFilter.ARMConverter(testData, ip); - CompareBuffer(testData, ArmResultData); + CompareBuffer(testData, armResultData); } [Fact] - public void ArmtConverterDecodeTest() + public void ARMTConverterDecodeTest() { uint ip = 0xA00; - var testData = ArmtData; + var testData = armtData; BranchExecFilter.ARMTConverter(testData, ip); - CompareBuffer(testData, ArmtResultData); + CompareBuffer(testData, armtResultData); } [Fact] - public void Ia64ConverterDecodeTest() + public void IA64ConverterDecodeTest() { uint ip = 0xAA0; - var testData = Ia64Data; + var testData = ia64Data; BranchExecFilter.IA64Converter(testData, ip); - CompareBuffer(testData, Ia64ResultData); + CompareBuffer(testData, ia64ResultData); } [Fact] - public void SparcConverterDecodeTest() + public void SPARCConverterDecodeTest() { uint ip = 0x100; - var testData = SparcData; + var testData = sparcData; BranchExecFilter.SPARCConverter(testData, ip); - CompareBuffer(testData, SparcResultData); + CompareBuffer(testData, sparcResultData); } } diff --git a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs index a8e215f7..e47c339c 100644 --- a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs @@ -3,8 +3,6 @@ using System.IO; using System.Linq; using SharpCompress.Archives; using SharpCompress.Archives.GZip; -using SharpCompress.Archives.Tar; -using SharpCompress.Common; using Xunit; namespace SharpCompress.Test.GZip; @@ -20,7 +18,7 @@ public class GZipArchiveTests : ArchiveTests using (var archive = ArchiveFactory.Open(stream)) { var entry = archive.Entries.First(); - entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key)); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar")); @@ -42,7 +40,7 @@ public class GZipArchiveTests : ArchiveTests using (var archive = GZipArchive.Open(stream)) { var entry = archive.Entries.First(); - entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key)); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar")); @@ -94,8 +92,7 @@ public class GZipArchiveTests : ArchiveTests Assert.Equal(size, tarStream.Length); using (var entryStream = archiveEntry.OpenEntryStream()) { - var result = TarArchive.IsTarFile(entryStream); - Assert.True(result); + var result = Archives.Tar.TarArchive.IsTarFile(entryStream); } Assert.Equal(size, tarStream.Length); using (var entryStream = archiveEntry.OpenEntryStream()) @@ -107,7 +104,7 @@ public class GZipArchiveTests : ArchiveTests } [Fact] - public void TestGzCrcWithMostSignificantBitNotNegative() + public void TestGzCrcWithMostSignificaltBitNotNegative() { using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")); using var archive = GZipArchive.Open(stream); @@ -117,12 +114,4 @@ public class GZipArchiveTests : ArchiveTests Assert.InRange(entry.Crc, 0L, 0xFFFFFFFFL); } } - - [Fact] - public void TestGzArchiveTypeGzip() - { - using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")); - using var archive = GZipArchive.Open(stream); - Assert.Equal(archive.Type, ArchiveType.GZip); - } } diff --git a/tests/SharpCompress.Test/GZip/GZipReaderTests.cs b/tests/SharpCompress.Test/GZip/GZipReaderTests.cs index 9d475fd5..b5a3d501 100644 --- a/tests/SharpCompress.Test/GZip/GZipReaderTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipReaderTests.cs @@ -1,7 +1,6 @@ using System.IO; using SharpCompress.Common; using SharpCompress.IO; -using SharpCompress.Readers.GZip; using Xunit; namespace SharpCompress.Test.GZip; @@ -18,7 +17,7 @@ public class GZipReaderTests : ReaderTests { //read only as GZip itme using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")); - using var reader = GZipReader.Open(new RewindableStream(stream)); + using var reader = Readers.GZip.GZipReader.Open(new RewindableStream(stream)); while (reader.MoveToNextEntry()) // Crash here { Assert.NotEqual(0, reader.Entry.Size); diff --git a/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs index 56cd0161..194e7788 100644 --- a/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs +++ b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace SharpCompress.Test.Mocks; @@ -7,26 +7,30 @@ namespace SharpCompress.Test.Mocks; // CryptoStream doesn't always trigger the Flush, so this class is used instead // See https://referencesource.microsoft.com/#mscorlib/system/security/cryptography/cryptostream.cs,141 -public class FlushOnDisposeStream(Stream innerStream) : Stream +public class FlushOnDisposeStream : Stream, IDisposable { - public override bool CanRead => innerStream.CanRead; + private Stream inner; + + public FlushOnDisposeStream(Stream innerStream) => inner = innerStream; + + public override bool CanRead => inner.CanRead; public override bool CanSeek => false; public override bool CanWrite => false; - public override long Length => innerStream.Length; + public override long Length => inner.Length; public override long Position { - get => innerStream.Position; - set => innerStream.Position = value; + get => inner.Position; + set => inner.Position = value; } - public override void Flush() { } + public override void Flush() => throw new NotImplementedException(); public override int Read(byte[] buffer, int offset, int count) => - innerStream.Read(buffer, offset, count); + inner.Read(buffer, offset, count); public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); @@ -40,8 +44,8 @@ public class FlushOnDisposeStream(Stream innerStream) : Stream { if (disposing) { - innerStream.Flush(); - innerStream.Close(); + inner.Flush(); + inner.Close(); } base.Dispose(disposing); diff --git a/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs b/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs index 180b8416..cef93a38 100644 --- a/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs +++ b/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs @@ -1,12 +1,16 @@ -using System; +using System; using System.IO; namespace SharpCompress.Test.Mocks; -public class ForwardOnlyStream(Stream stream) : Stream +public class ForwardOnlyStream : Stream { + private readonly Stream stream; + public bool IsDisposed { get; private set; } + public ForwardOnlyStream(Stream stream) => this.stream = stream; + protected override void Dispose(bool disposing) { if (!IsDisposed) @@ -25,7 +29,7 @@ public class ForwardOnlyStream(Stream stream) : Stream public override bool CanSeek => false; public override bool CanWrite => false; - public override void Flush() { } + public override void Flush() => throw new NotSupportedException(); public override long Length => throw new NotSupportedException(); diff --git a/tests/SharpCompress.Test/Mocks/TestStream.cs b/tests/SharpCompress.Test/Mocks/TestStream.cs index da7d65cc..66923df3 100644 --- a/tests/SharpCompress.Test/Mocks/TestStream.cs +++ b/tests/SharpCompress.Test/Mocks/TestStream.cs @@ -2,13 +2,23 @@ namespace SharpCompress.Test.Mocks; -public class TestStream(Stream stream, bool read, bool write, bool seek) : Stream +public class TestStream : Stream { + private readonly Stream stream; + public TestStream(Stream stream) : this(stream, stream.CanRead, stream.CanWrite, stream.CanSeek) { } public bool IsDisposed { get; private set; } + public TestStream(Stream stream, bool read, bool write, bool seek) + { + this.stream = stream; + CanRead = read; + CanWrite = write; + CanSeek = seek; + } + protected override void Dispose(bool disposing) { base.Dispose(disposing); @@ -16,11 +26,11 @@ public class TestStream(Stream stream, bool read, bool write, bool seek) : Strea IsDisposed = true; } - public override bool CanRead { get; } = read; + public override bool CanRead { get; } - public override bool CanSeek { get; } = seek; + public override bool CanSeek { get; } - public override bool CanWrite { get; } = write; + public override bool CanWrite { get; } public override void Flush() => stream.Flush(); diff --git a/tests/SharpCompress.Test/OperatingSystemExtensions.cs b/tests/SharpCompress.Test/OperatingSystemExtensions.cs deleted file mode 100644 index c8ca768e..00000000 --- a/tests/SharpCompress.Test/OperatingSystemExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace SharpCompress.Test; - -public static class OperatingSystemExtensions -{ - public static bool IsWindows(this OperatingSystem os) => - os.Platform == PlatformID.Win32NT - || os.Platform == PlatformID.Win32Windows - || os.Platform == PlatformID.Win32S; -} diff --git a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs index 373af692..6496e15e 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs @@ -22,16 +22,11 @@ public class RarArchiveTests : ArchiveTests () => ReadRarPassword("Rar.encrypted_filesAndHeader.rar", null) ); - [Fact] - public void Rar5_EncryptedFileAndHeader_Archive() => + /*[Fact] + public void Rar5_EncryptedFileAndHeader_Archive() + { ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test"); - - [Fact] - public void Rar5_EncryptedFileAndHeader_Archive_Err() => - Assert.Throws( - typeof(CryptographicException), - () => ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "failed") - ); + }*/ [Fact] public void Rar5_EncryptedFileAndHeader_NoPasswordExceptionTest() => @@ -44,23 +39,20 @@ public class RarArchiveTests : ArchiveTests public void Rar_EncryptedFileOnly_Archive() => ReadRarPassword("Rar.encrypted_filesOnly.rar", "test"); - [Fact] - public void Rar_EncryptedFileOnly_Archive_Err() => - Assert.Throws( - typeof(CryptographicException), - () => ReadRarPassword("Rar5.encrypted_filesOnly.rar", "failed") - ); - - [Fact] - public void Rar5_EncryptedFileOnly_Archive() => + /*[Fact] + public void Rar5_EncryptedFileOnly_Archive() + { ReadRarPassword("Rar5.encrypted_filesOnly.rar", "test"); + }*/ [Fact] public void Rar_Encrypted_Archive() => ReadRarPassword("Rar.Encrypted.rar", "test"); - [Fact] - public void Rar5_Encrypted_Archive() => + /*[Fact] + public void Rar5_Encrypted_Archive() + { ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test"); + }*/ private void ReadRarPassword(string testArchive, string? password) { @@ -68,7 +60,7 @@ public class RarArchiveTests : ArchiveTests using ( var archive = RarArchive.Open( stream, - new ReaderOptions { Password = password, LeaveStreamOpen = true } + new ReaderOptions() { Password = password, LeaveStreamOpen = true } ) ) { @@ -79,7 +71,7 @@ public class RarArchiveTests : ArchiveTests Assert.Equal(CompressionType.Rar, entry.CompressionType); entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -98,7 +90,7 @@ public class RarArchiveTests : ArchiveTests using ( var archive = RarArchive.Open( Path.Combine(TEST_ARCHIVES_PATH, archiveName), - new ReaderOptions { Password = password, LeaveStreamOpen = true } + new ReaderOptions() { Password = password, LeaveStreamOpen = true } ) ) { @@ -106,7 +98,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -137,7 +129,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -146,13 +138,13 @@ public class RarArchiveTests : ArchiveTests public void Rar_Jpg_ArchiveStreamRead() { using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.jpeg.jpg")); - using (var archive = RarArchive.Open(stream, new ReaderOptions { LookForHeader = true })) + using (var archive = RarArchive.Open(stream, new ReaderOptions() { LookForHeader = true })) { foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -175,7 +167,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -229,28 +221,30 @@ public class RarArchiveTests : ArchiveTests [Fact] public void Rar_Multi_ArchiveStreamRead() => DoRar_Multi_ArchiveStreamRead( - [ + new[] + { "Rar.multi.part01.rar", "Rar.multi.part02.rar", "Rar.multi.part03.rar", "Rar.multi.part04.rar", "Rar.multi.part05.rar", "Rar.multi.part06.rar" - ], + }, false ); [Fact] public void Rar5_Multi_ArchiveStreamRead() => DoRar_Multi_ArchiveStreamRead( - [ + new[] + { "Rar5.multi.part01.rar", "Rar5.multi.part02.rar", "Rar5.multi.part03.rar", "Rar5.multi.part04.rar", "Rar5.multi.part05.rar", "Rar5.multi.part06.rar" - ], + }, false ); @@ -264,7 +258,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -272,14 +266,15 @@ public class RarArchiveTests : ArchiveTests [Fact] public void Rar5_MultiSolid_ArchiveStreamRead() => DoRar_Multi_ArchiveStreamRead( - [ + new[] + { "Rar.multi.solid.part01.rar", "Rar.multi.solid.part02.rar", "Rar.multi.solid.part03.rar", "Rar.multi.solid.part04.rar", "Rar.multi.solid.part05.rar", "Rar.multi.solid.part06.rar" - ], + }, true ); @@ -317,7 +312,7 @@ public class RarArchiveTests : ArchiveTests using ( var archive = RarArchive.Open( Path.Combine(TEST_ARCHIVES_PATH, "Rar.jpeg.jpg"), - new ReaderOptions { LookForHeader = true } + new ReaderOptions() { LookForHeader = true } ) ) { @@ -325,7 +320,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -341,7 +336,8 @@ public class RarArchiveTests : ArchiveTests [Fact] public void Rar2_Multi_ArchiveStreamRead() => DoRar_Multi_ArchiveStreamRead( - [ + new[] + { "Rar2.multi.rar", "Rar2.multi.r00", "Rar2.multi.r01", @@ -349,7 +345,7 @@ public class RarArchiveTests : ArchiveTests "Rar2.multi.r03", "Rar2.multi.r04", "Rar2.multi.r05" - ], + }, false ); @@ -463,7 +459,8 @@ public class RarArchiveTests : ArchiveTests [Fact] public void Rar4_Multi_ArchiveStreamRead() => DoRar_Multi_ArchiveStreamRead( - [ + new[] + { "Rar4.multi.part01.rar", "Rar4.multi.part02.rar", "Rar4.multi.part03.rar", @@ -471,7 +468,7 @@ public class RarArchiveTests : ArchiveTests "Rar4.multi.part05.rar", "Rar4.multi.part06.rar", "Rar4.multi.part07.rar" - ], + }, false ); @@ -480,14 +477,15 @@ public class RarArchiveTests : ArchiveTests public void Rar4_Split_ArchiveStreamRead() => ArchiveStreamMultiRead( null, - [ + new[] + { "Rar4.split.001", "Rar4.split.002", "Rar4.split.003", "Rar4.split.004", "Rar4.split.005", "Rar4.split.006" - ] + } ); //will detect and load other files @@ -514,14 +512,15 @@ public class RarArchiveTests : ArchiveTests public void Rar4_Split_ArchiveStreamFirstFileRead() => ArchiveStreamMultiRead( null, - [ - "Rar4.split.001" + new[] + { + "Rar4.split.001", //"Rar4.split.002", //"Rar4.split.003", //"Rar4.split.004", //"Rar4.split.005", //"Rar4.split.006" - ] + } ); //open with ArchiveFactory.Open and stream @@ -554,11 +553,12 @@ public class RarArchiveTests : ArchiveTests [Fact] public void Rar4_Multi_ArchiveOpenEntryVolumeIndexTest() => ArchiveOpenEntryVolumeIndexTest( - [ - [0, 1], //exe - Rar4.multi.part01.rar to Rar4.multi.part02.rar - [1, 5], //jpg - Rar4.multi.part02.rar to Rar4.multi.part06.rar - [5, 6] //txt - Rar4.multi.part06.rar to Rar4.multi.part07.rar - ], + new[] + { + new[] { 0, 1 }, //exe - Rar4.multi.part01.rar to Rar4.multi.part02.rar + new[] { 1, 5 }, //jpg - Rar4.multi.part02.rar to Rar4.multi.part06.rar + new[] { 5, 6 } //txt - Rar4.multi.part06.rar to Rar4.multi.part07.rar + }, null, "Rar4.multi.part01.rar", "Rar4.multi.part02.rar", @@ -600,37 +600,4 @@ public class RarArchiveTests : ArchiveTests Assert.True(archive.IsMultipartVolume()); Assert.False(archive.IsFirstVolume()); } - - [Fact] - public void Rar5_CRC_Blake2_Archive() => ArchiveFileRead("Rar5.crc_blake2.rar"); - - [Fact] - void Rar_Iterate_Archive() => - ArchiveFileSkip("Rar.rar", "Failure jpg exe Empty jpg\\test.jpg exe\\test.exe тест.txt"); - - [Fact] - public void Rar2_Iterate_Archive() => - ArchiveFileSkip("Rar2.rar", "Failure Empty тест.txt jpg\\test.jpg exe\\test.exe jpg exe"); - - [Fact] - public void Rar4_Iterate_Archive() => - ArchiveFileSkip("Rar4.rar", "Failure Empty jpg exe тест.txt jpg\\test.jpg exe\\test.exe"); - - [Fact] - public void Rar5_Iterate_Archive() => - ArchiveFileSkip("Rar5.rar", "Failure jpg exe Empty тест.txt jpg\\test.jpg exe\\test.exe"); - - [Fact] - public void Rar_Encrypted_Iterate_Archive() => - ArchiveFileSkip( - "Rar.encrypted_filesOnly.rar", - "Failure jpg exe Empty тест.txt jpg\\test.jpg exe\\test.exe" - ); - - [Fact] - public void Rar5_Encrypted_Iterate_Archive() => - ArchiveFileSkip( - "Rar5.encrypted_filesOnly.rar", - "Failure jpg exe Empty тест.txt jpg\\test.jpg exe\\test.exe" - ); } diff --git a/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs b/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs index 70015fcf..f2b1913c 100644 --- a/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs +++ b/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs @@ -11,10 +11,10 @@ namespace SharpCompress.Test.Rar; /// public class RarHeaderFactoryTest : TestBase { - private readonly RarHeaderFactory _rarHeaderFactory; + private readonly RarHeaderFactory rarHeaderFactory; public RarHeaderFactoryTest() => - _rarHeaderFactory = new RarHeaderFactory( + rarHeaderFactory = new RarHeaderFactory( StreamingMode.Seekable, new ReaderOptions { LeaveStreamOpen = true } ); @@ -40,11 +40,11 @@ public class RarHeaderFactoryTest : TestBase FileMode.Open, FileAccess.Read ); - foreach (var header in _rarHeaderFactory.ReadHeaders(stream)) + foreach (var header in rarHeaderFactory.ReadHeaders(stream)) { if (header.HeaderType == HeaderType.Archive || header.HeaderType == HeaderType.Crypt) { - Assert.Equal(isEncrypted, _rarHeaderFactory.IsEncrypted); + Assert.Equal(isEncrypted, rarHeaderFactory.IsEncrypted); break; } } diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index 6ba605a5..097b0fc8 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -13,27 +13,29 @@ public class RarReaderTests : ReaderTests [Fact] public void Rar_Multi_Reader() => DoRar_Multi_Reader( - [ + new[] + { "Rar.multi.part01.rar", "Rar.multi.part02.rar", "Rar.multi.part03.rar", "Rar.multi.part04.rar", "Rar.multi.part05.rar", "Rar.multi.part06.rar" - ] + } ); [Fact] public void Rar5_Multi_Reader() => DoRar_Multi_Reader( - [ + new[] + { "Rar5.multi.part01.rar", "Rar5.multi.part02.rar", "Rar5.multi.part03.rar", "Rar5.multi.part04.rar", "Rar5.multi.part05.rar", "Rar5.multi.part06.rar" - ] + } ); private void DoRar_Multi_Reader(string[] archives) @@ -50,7 +52,7 @@ public class RarReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -60,14 +62,15 @@ public class RarReaderTests : ReaderTests [Fact] public void Rar_Multi_Reader_Encrypted() => DoRar_Multi_Reader_Encrypted( - [ + new[] + { "Rar.EncryptedParts.part01.rar", "Rar.EncryptedParts.part02.rar", "Rar.EncryptedParts.part03.rar", "Rar.EncryptedParts.part04.rar", "Rar.EncryptedParts.part05.rar", "Rar.EncryptedParts.part06.rar" - ] + } ); private void DoRar_Multi_Reader_Encrypted(string[] archives) => @@ -78,7 +81,7 @@ public class RarReaderTests : ReaderTests archives .Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)) .Select(p => File.OpenRead(p)), - new ReaderOptions { Password = "test" } + new ReaderOptions() { Password = "test" } ) ) { @@ -86,7 +89,7 @@ public class RarReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -96,27 +99,29 @@ public class RarReaderTests : ReaderTests [Fact] public void Rar_Multi_Reader_Delete_Files() => DoRar_Multi_Reader_Delete_Files( - [ + new[] + { "Rar.multi.part01.rar", "Rar.multi.part02.rar", "Rar.multi.part03.rar", "Rar.multi.part04.rar", "Rar.multi.part05.rar", "Rar.multi.part06.rar" - ] + } ); [Fact] public void Rar5_Multi_Reader_Delete_Files() => DoRar_Multi_Reader_Delete_Files( - [ + new[] + { "Rar5.multi.part01.rar", "Rar5.multi.part02.rar", "Rar5.multi.part03.rar", "Rar5.multi.part04.rar", "Rar5.multi.part05.rar", "Rar5.multi.part06.rar" - ] + } ); private void DoRar_Multi_Reader_Delete_Files(string[] archives) @@ -138,7 +143,7 @@ public class RarReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -166,28 +171,33 @@ public class RarReaderTests : ReaderTests [Fact] public void Rar5_Reader() => Read("Rar5.rar", CompressionType.Rar); - [Fact] - public void Rar5_CRC_Blake2_Reader() => Read("Rar5.crc_blake2.rar", CompressionType.Rar); - [Fact] public void Rar_EncryptedFileAndHeader_Reader() => ReadRar("Rar.encrypted_filesAndHeader.rar", "test"); - [Fact] - public void Rar5_EncryptedFileAndHeader_Reader() => + /*[Fact] + public void Rar5_EncryptedFileAndHeader_Reader() + { ReadRar("Rar5.encrypted_filesAndHeader.rar", "test"); + }*/ [Fact] public void Rar_EncryptedFileOnly_Reader() => ReadRar("Rar.encrypted_filesOnly.rar", "test"); - [Fact] - public void Rar5_EncryptedFileOnly_Reader() => ReadRar("Rar5.encrypted_filesOnly.rar", "test"); + /*[Fact] + public void Rar5_EncryptedFileOnly_Reader() + { + ReadRar("Rar5.encrypted_filesOnly.rar", "test"); + }*/ [Fact] public void Rar_Encrypted_Reader() => ReadRar("Rar.Encrypted.rar", "test"); - [Fact] - public void Rar5_Encrypted_Reader() => ReadRar("Rar5.encrypted_filesOnly.rar", "test"); + /*[Fact] + public void Rar5_Encrypted_Reader() + { + ReadRar("Rar5.encrypted_filesOnly.rar", "test"); + }*/ private void ReadRar(string testArchive, string password) => Read(testArchive, CompressionType.Rar, new ReaderOptions { Password = password }); @@ -209,7 +219,7 @@ public class RarReaderTests : ReaderTests { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); using var entryStream = reader.OpenEntryStream(); - var file = Path.GetFileName(reader.Entry.Key).NotNull(); + var file = Path.GetFileName(reader.Entry.Key); var folder = Path.GetDirectoryName(reader.Entry.Key) ?? throw new ArgumentNullException(); @@ -234,14 +244,16 @@ public class RarReaderTests : ReaderTests using ( var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.Audio_program.rar")) ) - using (var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true })) + using ( + var reader = ReaderFactory.Open(stream, new ReaderOptions() { LookForHeader = true }) + ) { while (reader.MoveToNextEntry()) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -255,14 +267,14 @@ public class RarReaderTests : ReaderTests public void Rar_Jpg_Reader() { using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.jpeg.jpg"))) - using (var reader = RarReader.Open(stream, new ReaderOptions { LookForHeader = true })) + using (var reader = RarReader.Open(stream, new ReaderOptions() { LookForHeader = true })) { while (reader.MoveToNextEntry()) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -272,12 +284,6 @@ public class RarReaderTests : ReaderTests [Fact] public void Rar_Solid_Reader() => Read("Rar.solid.rar", CompressionType.Rar); - [Fact] - public void Rar_Comment_Reader() => Read("Rar.comment.rar", CompressionType.Rar); - - [Fact] - public void Rar5_Comment_Reader() => Read("Rar5.comment.rar", CompressionType.Rar); - [Fact] public void Rar5_Solid_Reader() => Read("Rar5.solid.rar", CompressionType.Rar); @@ -290,15 +296,15 @@ public class RarReaderTests : ReaderTests private void DoRar_Solid_Skip_Reader(string filename) { using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename)); - using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true }); + using var reader = ReaderFactory.Open(stream, new ReaderOptions() { LookForHeader = true }); while (reader.MoveToNextEntry()) { - if (reader.Entry.Key.NotNull().Contains("jpg")) + if (reader.Entry.Key.Contains("jpg")) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -313,15 +319,15 @@ public class RarReaderTests : ReaderTests private void DoRar_Reader_Skip(string filename) { using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename)); - using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true }); + using var reader = ReaderFactory.Open(stream, new ReaderOptions() { LookForHeader = true }); while (reader.MoveToNextEntry()) { - if (reader.Entry.Key.NotNull().Contains("jpg")) + if (reader.Entry.Key.Contains("jpg")) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -341,15 +347,19 @@ public class RarReaderTests : ReaderTests "Rar.EncryptedParts.part06.rar" }; - using var reader = RarReader.Open( - archives - .Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)) - .Select(p => File.OpenRead(p)), - new ReaderOptions { Password = "test" } - ); - while (reader.MoveToNextEntry()) + using ( + var reader = RarReader.Open( + archives + .Select(s => Path.Combine(TEST_ARCHIVES_PATH, s)) + .Select(p => File.OpenRead(p)), + new ReaderOptions() { Password = "test" } + ) + ) { - // + while (reader.MoveToNextEntry()) + { + // + } } } @@ -359,7 +369,7 @@ public class RarReaderTests : ReaderTests ); using var reader = ReaderFactory.Open( stream, - new ReaderOptions { LookForHeader = true } + new ReaderOptions() { LookForHeader = true } ); while (reader.MoveToNextEntry()) { @@ -367,55 +377,4 @@ public class RarReaderTests : ReaderTests } } } - - [Fact] - public void Rar_Iterate_Reader() => - Iterate( - "Rar.rar", - "Failure jpg exe Empty jpg\\test.jpg exe\\test.exe тест.txt", - CompressionType.Rar - ); - - [Fact] - public void Rar2_Iterate_Archive() => - Iterate( - "Rar2.rar", - "Failure Empty тест.txt jpg\\test.jpg exe\\test.exe jpg exe", - CompressionType.Rar - ); - - [Fact] - public void Rar4_Iterate_Archive() => - Iterate( - "Rar4.rar", - "Failure Empty jpg exe тест.txt jpg\\test.jpg exe\\test.exe", - CompressionType.Rar - ); - - [Fact] - public void Rar5_Iterate_Archive() => - Iterate( - "Rar5.rar", - "Failure jpg exe Empty тест.txt jpg\\test.jpg exe\\test.exe", - CompressionType.Rar - ); - - [Fact] - public void Rar_Encrypted_Iterate_Archive() => - Iterate( - "Rar.encrypted_filesOnly.rar", - "Failure jpg exe Empty тест.txt jpg\\test.jpg exe\\test.exe", - CompressionType.Rar - ); - - [Fact] - public void Rar5_Encrypted_Iterate_Archive() => - Assert.Throws( - () => - Iterate( - "Rar5.encrypted_filesOnly.rar", - "Failure jpg exe Empty тест.txt jpg\\test.jpg exe\\test.exe", - CompressionType.Rar - ) - ); } diff --git a/tests/SharpCompress.Test/ReaderTests.cs b/tests/SharpCompress.Test/ReaderTests.cs index 7ea1d7b7..be1dbe07 100644 --- a/tests/SharpCompress.Test/ReaderTests.cs +++ b/tests/SharpCompress.Test/ReaderTests.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using System.IO; using SharpCompress.Common; using SharpCompress.IO; @@ -64,33 +62,9 @@ public abstract class ReaderTests : TestBase Assert.Equal(expectedCompression, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } } - - protected void Iterate( - string testArchive, - string fileOrder, - CompressionType expectedCompression, - ReaderOptions? options = null - ) - { - if (!Environment.OSVersion.IsWindows()) - { - fileOrder = fileOrder.Replace('\\', '/'); - } - var expected = new Stack(fileOrder.Split(' ')); - - testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); - using var file = File.OpenRead(testArchive); - using var forward = new ForwardOnlyStream(file); - using var reader = ReaderFactory.Open(forward, options); - while (reader.MoveToNextEntry()) - { - Assert.Equal(expectedCompression, reader.Entry.CompressionType); - Assert.Equal(expected.Pop(), reader.Entry.Key); - } - } } diff --git a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs index 32d978a2..e77e288c 100644 --- a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs +++ b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs @@ -25,17 +25,17 @@ public class SevenZipArchiveTests : ArchiveTests [Fact] public void SevenZipArchive_LZMAAES_StreamRead() => - ArchiveStreamRead("7Zip.LZMA.Aes.7z", new ReaderOptions { Password = "testpassword" }); + ArchiveStreamRead("7Zip.LZMA.Aes.7z", new ReaderOptions() { Password = "testpassword" }); [Fact] public void SevenZipArchive_LZMAAES_PathRead() => - ArchiveFileRead("7Zip.LZMA.Aes.7z", new ReaderOptions { Password = "testpassword" }); + ArchiveFileRead("7Zip.LZMA.Aes.7z", new ReaderOptions() { Password = "testpassword" }); [Fact] public void SevenZipArchive_LZMAAES_NoPasswordExceptionTest() => Assert.Throws( typeof(CryptographicException), - () => ArchiveFileRead("7Zip.LZMA.Aes.7z", new ReaderOptions { Password = null }) + () => ArchiveFileRead("7Zip.LZMA.Aes.7z", new ReaderOptions() { Password = null }) ); //was failing with ArgumentNullException not CryptographicException like rar [Fact] @@ -135,9 +135,6 @@ public class SevenZipArchiveTests : ArchiveTests ) ); - [Fact] - public void SevenZipArchive_EOS_FileRead() => ArchiveFileRead("7Zip.eos.7z"); - [Fact] public void SevenZipArchive_Delta_FileRead() => ArchiveFileRead("7Zip.delta.7z"); @@ -162,12 +159,6 @@ public class SevenZipArchiveTests : ArchiveTests [Fact] public void SevenZipArchive_SPARC_FileRead() => ArchiveFileRead("7Zip.SPARC.7z"); - [Fact] - public void SevenZipArchive_ARM64_FileRead() => ArchiveFileRead("7Zip.ARM64.7z"); - - [Fact] - public void SevenZipArchive_RISCV_FileRead() => ArchiveFileRead("7Zip.RISCV.7z"); - [Fact] public void SevenZipArchive_Filters_FileRead() => ArchiveFileRead("7Zip.Filters.7z"); @@ -182,7 +173,7 @@ public class SevenZipArchiveTests : ArchiveTests using (var archive = SevenZipArchive.Open(stream)) { var entry = archive.Entries.First(); - entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key)); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "7Zip.Tar.tar")); diff --git a/tests/SharpCompress.Test/SharpCompress.Test.csproj b/tests/SharpCompress.Test/SharpCompress.Test.csproj index 3bfeaa3e..c20664a7 100644 --- a/tests/SharpCompress.Test/SharpCompress.Test.csproj +++ b/tests/SharpCompress.Test/SharpCompress.Test.csproj @@ -1,6 +1,6 @@  - net8.0;net462 + net7.0;net462 SharpCompress.Test SharpCompress.Test @@ -8,13 +8,16 @@ - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - + diff --git a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs index 2eea6607..2f336329 100644 --- a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs +++ b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs @@ -1,5 +1,6 @@ using System; using System.Buffers; +using System.Buffers.Binary; using System.IO; using SharpCompress.Compressors.LZMA; using Xunit; @@ -19,8 +20,9 @@ public class LzmaStreamTests Assert.Equal('X', decompressor.ReadByte()); } - private static byte[] LzmaData { get; } = - [ + private static byte[] lzmaData { get; } = + new byte[] + { 0x5D, 0x00, 0x20, @@ -175,13 +177,14 @@ public class LzmaStreamTests 0x76, 0x03, 0x90 - ]; + }; /// - /// The decoded data for . + /// The decoded data for . /// - private static byte[] LzmaResultData { get; } = - [ + private static byte[] lzmaResultData { get; } = + new byte[] + { 0x01, 0x00, 0xFD, @@ -510,12 +513,12 @@ public class LzmaStreamTests 0x00, 0x00, 0x00 - ]; + }; [Fact] public void TestLzmaBuffer() { - var input = new MemoryStream(LzmaData); + var input = new MemoryStream(lzmaData); using var output = new MemoryStream(); var properties = new byte[5]; input.Read(properties, 0, 5); @@ -528,15 +531,19 @@ public class LzmaStreamTests coder.SetDecoderProperties(properties); coder.Code(input, output, input.Length, fileLength, null); - Assert.Equal(output.ToArray(), LzmaResultData); + Assert.Equal(output.ToArray(), lzmaResultData); } [Fact] public void TestLzmaStreamEncodingWritesData() { - using var inputStream = new MemoryStream(LzmaResultData); + using MemoryStream inputStream = new MemoryStream(lzmaResultData); using MemoryStream outputStream = new(); - using var lzmaStream = new LzmaStream(LzmaEncoderProperties.Default, false, outputStream); + using LzmaStream lzmaStream = new LzmaStream( + LzmaEncoderProperties.Default, + false, + outputStream + ); inputStream.CopyTo(lzmaStream); lzmaStream.Close(); Assert.NotEqual(0, outputStream.Length); @@ -545,9 +552,13 @@ public class LzmaStreamTests [Fact] public void TestLzmaEncodingAccuracy() { - var input = new MemoryStream(LzmaResultData); + var input = new MemoryStream(lzmaResultData); var compressed = new MemoryStream(); - var lzmaEncodingStream = new LzmaStream(LzmaEncoderProperties.Default, false, compressed); + LzmaStream lzmaEncodingStream = new LzmaStream( + LzmaEncoderProperties.Default, + false, + compressed + ); input.CopyTo(lzmaEncodingStream); lzmaEncodingStream.Close(); compressed.Position = 0; @@ -558,10 +569,10 @@ public class LzmaStreamTests compressed, compressed.Length, output, - LzmaResultData.LongLength + lzmaResultData.LongLength ); - Assert.Equal(output.ToArray(), LzmaResultData); + Assert.Equal(output.ToArray(), lzmaResultData); } private static void DecompressLzmaStream( @@ -572,7 +583,7 @@ public class LzmaStreamTests long decompressedSize ) { - var lzmaStream = new LzmaStream( + LzmaStream lzmaStream = new LzmaStream( properties, compressedStream, compressedSize, @@ -581,12 +592,12 @@ public class LzmaStreamTests false ); - var buffer = ArrayPool.Shared.Rent(1024); + byte[] buffer = ArrayPool.Shared.Rent(1024); long totalRead = 0; while (totalRead < decompressedSize) { - var toRead = (int)Math.Min(buffer.Length, decompressedSize - totalRead); - var read = lzmaStream.Read(buffer, 0, toRead); + int toRead = (int)Math.Min(buffer.Length, decompressedSize - totalRead); + int read = lzmaStream.Read(buffer, 0, toRead); if (read > 0) { decompressedStream.Write(buffer, 0, read); diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index bbf96c00..dddb32a6 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -1,15 +1,15 @@ using System; using System.IO; using System.Linq; -using System.Text; using SharpCompress.Archives; using SharpCompress.Archives.Tar; using SharpCompress.Common; -using SharpCompress.Readers; -using SharpCompress.Readers.Tar; using SharpCompress.Writers; -using SharpCompress.Writers.Tar; using Xunit; +using System.Text; +using SharpCompress.Readers; +using SharpCompress.Writers.Tar; +using SharpCompress.Readers.Tar; namespace SharpCompress.Test.Tar; @@ -26,10 +26,10 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_FileName_Exactly_100_Characters() { - var archive = "Tar_FileName_Exactly_100_Characters.tar"; + string archive = "Tar_FileName_Exactly_100_Characters.tar"; // create the 100 char filename - var filename = + string filename = "filename_with_exactly_100_characters_______________________________________________________________X"; // Step 1: create a tar file containing a file with the test name @@ -37,7 +37,7 @@ public class TarArchiveTests : ArchiveTests using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.None)) using (Stream inputStream = new MemoryStream()) { - var sw = new StreamWriter(inputStream); + StreamWriter sw = new StreamWriter(inputStream); sw.Write("dummy filecontent"); sw.Flush(); @@ -46,7 +46,7 @@ public class TarArchiveTests : ArchiveTests } // Step 2: check if the written tar file can be read correctly - var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); + string unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); using (var archive2 = TarArchive.Open(unmodified)) { Assert.Equal(1, archive2.Entries.Count); @@ -65,27 +65,29 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_NonUstarArchiveWithLongNameDoesNotSkipEntriesAfterTheLongOne() { - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "very long filename.tar"); - using var archive = TarArchive.Open(unmodified); - Assert.Equal(5, archive.Entries.Count); - Assert.Contains("very long filename/", archive.Entries.Select(entry => entry.Key)); - Assert.Contains( - "very long filename/very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename.jpg", - archive.Entries.Select(entry => entry.Key) - ); - Assert.Contains("z_file 1.txt", archive.Entries.Select(entry => entry.Key)); - Assert.Contains("z_file 2.txt", archive.Entries.Select(entry => entry.Key)); - Assert.Contains("z_file 3.txt", archive.Entries.Select(entry => entry.Key)); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "very long filename.tar"); + using (var archive = TarArchive.Open(unmodified)) + { + Assert.Equal(5, archive.Entries.Count); + Assert.Contains("very long filename/", archive.Entries.Select(entry => entry.Key)); + Assert.Contains( + "very long filename/very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename very long filename.jpg", + archive.Entries.Select(entry => entry.Key) + ); + Assert.Contains("z_file 1.txt", archive.Entries.Select(entry => entry.Key)); + Assert.Contains("z_file 2.txt", archive.Entries.Select(entry => entry.Key)); + Assert.Contains("z_file 3.txt", archive.Entries.Select(entry => entry.Key)); + } } [Fact] public void Tar_VeryLongFilepathReadback() { - var archive = "Tar_VeryLongFilepathReadback.tar"; + string archive = "Tar_VeryLongFilepathReadback.tar"; // create a very long filename - var longFilename = ""; - for (var i = 0; i < 600; i = longFilename.Length) + string longFilename = ""; + for (int i = 0; i < 600; i = longFilename.Length) { longFilename += i.ToString("D10") + "-"; } @@ -97,7 +99,7 @@ public class TarArchiveTests : ArchiveTests using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.None)) using (Stream inputStream = new MemoryStream()) { - var sw = new StreamWriter(inputStream); + StreamWriter sw = new StreamWriter(inputStream); sw.Write("dummy filecontent"); sw.Flush(); @@ -106,7 +108,7 @@ public class TarArchiveTests : ArchiveTests } // Step 2: check if the written tar file can be read correctly - var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); + string unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); using (var archive2 = TarArchive.Open(unmodified)) { Assert.Equal(1, archive2.Entries.Count); @@ -125,37 +127,39 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_UstarArchivePathReadLongName() { - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "ustar with long names.tar"); - using var archive = TarArchive.Open(unmodified); - Assert.Equal(6, archive.Entries.Count); - Assert.Contains("Directory/", archive.Entries.Select(entry => entry.Key)); - Assert.Contains( - "Directory/Some file with veeeeeeeeeery loooooooooong name", - archive.Entries.Select(entry => entry.Key) - ); - Assert.Contains( - "Directory/Directory with veeeeeeeeeery loooooooooong name/", - archive.Entries.Select(entry => entry.Key) - ); - Assert.Contains( - "Directory/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name", - archive.Entries.Select(entry => entry.Key) - ); - Assert.Contains( - "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/", - archive.Entries.Select(entry => entry.Key) - ); - Assert.Contains( - "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name", - archive.Entries.Select(entry => entry.Key) - ); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "ustar with long names.tar"); + using (var archive = TarArchive.Open(unmodified)) + { + Assert.Equal(6, archive.Entries.Count); + Assert.Contains("Directory/", archive.Entries.Select(entry => entry.Key)); + Assert.Contains( + "Directory/Some file with veeeeeeeeeery loooooooooong name", + archive.Entries.Select(entry => entry.Key) + ); + Assert.Contains( + "Directory/Directory with veeeeeeeeeery loooooooooong name/", + archive.Entries.Select(entry => entry.Key) + ); + Assert.Contains( + "Directory/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name", + archive.Entries.Select(entry => entry.Key) + ); + Assert.Contains( + "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/", + archive.Entries.Select(entry => entry.Key) + ); + Assert.Contains( + "Directory/Directory with veeeeeeeeeery loooooooooong name/Directory with veeeeeeeeeery loooooooooong name/Some file with veeeeeeeeeery loooooooooong name", + archive.Entries.Select(entry => entry.Key) + ); + } } [Fact] public void Tar_Create_New() { - var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"); - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); + string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); // var aropt = new Ar @@ -163,7 +167,7 @@ public class TarArchiveTests : ArchiveTests { archive.AddAllFromDirectory(ORIGINAL_FILES_PATH); var twopt = new TarWriterOptions(CompressionType.None, true); - twopt.ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(866) }; + twopt.ArchiveEncoding = new ArchiveEncoding() { Default = Encoding.GetEncoding(866) }; archive.SaveTo(scratchPath, twopt); } CompareArchivesByPath(unmodified, scratchPath); @@ -172,10 +176,10 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_Random_Write_Add() { - var jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg"); - var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.mod.tar"); - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.mod.tar"); - var modified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); + string jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg"); + string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.mod.tar"); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.mod.tar"); + string modified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); using (var archive = TarArchive.Open(unmodified)) { @@ -188,14 +192,14 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_Random_Write_Remove() { - var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.mod.tar"); - var modified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.mod.tar"); - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); + string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.mod.tar"); + string modified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.mod.tar"); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); using (var archive = TarArchive.Open(unmodified)) { - var entry = archive.Entries.Single(x => - x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + var entry = archive.Entries.Single( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ); archive.RemoveEntry(entry); archive.SaveTo(scratchPath, CompressionType.None); @@ -206,19 +210,23 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_Containing_Rar_Archive() { - var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); - using Stream stream = File.OpenRead(archiveFullPath); - using var archive = ArchiveFactory.Open(stream); - Assert.True(archive.Type == ArchiveType.Tar); + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); + using (Stream stream = File.OpenRead(archiveFullPath)) + using (IArchive archive = ArchiveFactory.Open(stream)) + { + Assert.True(archive.Type == ArchiveType.Tar); + } } [Fact] public void Tar_Empty_Archive() { - var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.Empty.tar"); - using Stream stream = File.OpenRead(archiveFullPath); - using var archive = ArchiveFactory.Open(stream); - Assert.True(archive.Type == ArchiveType.Tar); + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.Empty.tar"); + using (Stream stream = File.OpenRead(archiveFullPath)) + using (IArchive archive = ArchiveFactory.Open(stream)) + { + Assert.True(archive.Type == ArchiveType.Tar); + } } [Theory] @@ -226,24 +234,26 @@ public class TarArchiveTests : ArchiveTests [InlineData(128)] public void Tar_Japanese_Name(int length) { - using var mstm = new MemoryStream(); - var enc = new ArchiveEncoding { Default = Encoding.UTF8 }; - var twopt = new TarWriterOptions(CompressionType.None, true); - twopt.ArchiveEncoding = enc; - var fname = new string((char)0x3042, length); - using (var tw = new TarWriter(mstm, twopt)) - using (var input = new MemoryStream(new byte[32])) + using (var mstm = new MemoryStream()) { - tw.Write(fname, input, null); - } - using (var inputMemory = new MemoryStream(mstm.ToArray())) - { - var tropt = new ReaderOptions { ArchiveEncoding = enc }; - using (var tr = TarReader.Open(inputMemory, tropt)) + var enc = new ArchiveEncoding() { Default = Encoding.UTF8 }; + var twopt = new TarWriterOptions(CompressionType.None, true); + twopt.ArchiveEncoding = enc; + var fname = new string((char)0x3042, length); + using (var tw = new TarWriter(mstm, twopt)) + using (var input = new MemoryStream(new byte[32])) { - while (tr.MoveToNextEntry()) + tw.Write(fname, input, null); + } + using (var inputMemory = new MemoryStream(mstm.ToArray())) + { + var tropt = new ReaderOptions() { ArchiveEncoding = enc }; + using (var tr = TarReader.Open(inputMemory, tropt)) { - Assert.Equal(fname, tr.Entry.Key); + while (tr.MoveToNextEntry()) + { + Assert.Equal(fname, tr.Entry.Key); + } } } } @@ -259,32 +269,36 @@ public class TarArchiveTests : ArchiveTests }; var testBytes = Encoding.UTF8.GetBytes("This is a test."); - using var memoryStream = new MemoryStream(); - using (var tarWriter = new TarWriter(memoryStream, tarWriterOptions)) - using (var testFileStream = new MemoryStream(testBytes)) + using (var memoryStream = new MemoryStream()) { - tarWriter.Write("test1.txt", testFileStream); - testFileStream.Position = 0; - tarWriter.Write("test2.txt", testFileStream); - } - - memoryStream.Position = 0; - - var numberOfEntries = 0; - - using (var archiveFactory = TarArchive.Open(memoryStream)) - { - foreach (var entry in archiveFactory.Entries) + using (var tarWriter = new TarWriter(memoryStream, tarWriterOptions)) + using (var testFileStream = new MemoryStream(testBytes)) { - ++numberOfEntries; - - using var tarEntryStream = entry.OpenEntryStream(); - using var testFileStream = new MemoryStream(); - tarEntryStream.CopyTo(testFileStream); - Assert.Equal(testBytes.Length, testFileStream.Length); + tarWriter.Write("test1.txt", testFileStream); + testFileStream.Position = 0; + tarWriter.Write("test2.txt", testFileStream); } - } - Assert.Equal(2, numberOfEntries); + memoryStream.Position = 0; + + var numberOfEntries = 0; + + using (var archiveFactory = TarArchive.Open(memoryStream)) + { + foreach (var entry in archiveFactory.Entries) + { + ++numberOfEntries; + + using (var tarEntryStream = entry.OpenEntryStream()) + using (var testFileStream = new MemoryStream()) + { + tarEntryStream.CopyTo(testFileStream); + Assert.Equal(testBytes.Length, testFileStream.Length); + } + } + } + + Assert.Equal(2, numberOfEntries); + } } } diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index 3b6a6a88..76629363 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -19,30 +19,31 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_Skip() { - using Stream stream = new ForwardOnlyStream( - File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar")) - ); - using var reader = ReaderFactory.Open(stream); - var x = 0; - while (reader.MoveToNextEntry()) + using ( + Stream stream = new ForwardOnlyStream( + File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar")) + ) + ) + using (IReader reader = ReaderFactory.Open(stream)) { - if (!reader.Entry.IsDirectory) + int x = 0; + while (reader.MoveToNextEntry()) { - x++; - if (x % 2 == 0) + if (!reader.Entry.IsDirectory) { - reader.WriteEntryToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } - ); + x++; + if (x % 2 == 0) + { + reader.WriteEntryToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + ); + } } } } } - [Fact] - public void Tar_Z_Reader() => Read("Tar.tar.Z", CompressionType.Lzw); - [Fact] public void Tar_BZip2_Reader() => Read("Tar.tar.bz2", CompressionType.BZip2); @@ -55,9 +56,6 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_Xz_Reader() => Read("Tar.tar.xz", CompressionType.Xz); - [Fact] - public void Tar_GZip_OldGnu_Reader() => Read("Tar.oldgnu.tar.gz", CompressionType.GZip); - [Fact] public void Tar_BZip2_Entry_Stream() { @@ -69,20 +67,24 @@ public class TarReaderTests : ReaderTests if (!reader.Entry.IsDirectory) { Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType); - using var entryStream = reader.OpenEntryStream(); - var file = Path.GetFileName(reader.Entry.Key); - var folder = - Path.GetDirectoryName(reader.Entry.Key) - ?? throw new ArgumentNullException(); - var destdir = Path.Combine(SCRATCH_FILES_PATH, folder); - if (!Directory.Exists(destdir)) + using (var entryStream = reader.OpenEntryStream()) { - Directory.CreateDirectory(destdir); - } - var destinationFileName = Path.Combine(destdir, file.NotNull()); + string file = Path.GetFileName(reader.Entry.Key); + string folder = + Path.GetDirectoryName(reader.Entry.Key) + ?? throw new ArgumentNullException(); + string destdir = Path.Combine(SCRATCH_FILES_PATH, folder); + if (!Directory.Exists(destdir)) + { + Directory.CreateDirectory(destdir); + } + string destinationFileName = Path.Combine(destdir, file); - using var fs = File.OpenWrite(destinationFileName); - entryStream.TransferTo(fs); + using (FileStream fs = File.OpenWrite(destinationFileName)) + { + entryStream.TransferTo(fs); + } + } } } } @@ -105,7 +107,7 @@ public class TarReaderTests : ReaderTests { if (!reader.Entry.IsDirectory) { - filePaths.Add(reader.Entry.Key.NotNull("Entry Key is null")); + filePaths.Add(reader.Entry.Key); } } } @@ -125,77 +127,79 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_BZip2_Skip_Entry_Stream() { - using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2")); - using var reader = TarReader.Open(stream); - var names = new List(); - while (reader.MoveToNextEntry()) + using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2"))) + using (var reader = TarReader.Open(stream)) { - if (!reader.Entry.IsDirectory) + List names = new List(); + while (reader.MoveToNextEntry()) { - Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType); - using var entryStream = reader.OpenEntryStream(); - entryStream.SkipEntry(); - names.Add(reader.Entry.Key.NotNull()); + if (!reader.Entry.IsDirectory) + { + Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType); + using (var entryStream = reader.OpenEntryStream()) + { + entryStream.SkipEntry(); + names.Add(reader.Entry.Key); + } + } } + Assert.Equal(3, names.Count); } - Assert.Equal(3, names.Count); } [Fact] public void Tar_Containing_Rar_Reader() { - var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); - using Stream stream = File.OpenRead(archiveFullPath); - using var reader = ReaderFactory.Open(stream); - Assert.True(reader.ArchiveType == ArchiveType.Tar); + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); + using (Stream stream = File.OpenRead(archiveFullPath)) + using (IReader reader = ReaderFactory.Open(stream)) + { + Assert.True(reader.ArchiveType == ArchiveType.Tar); + } } [Fact] public void Tar_With_TarGz_With_Flushed_EntryStream() { - var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsTarGz.tar"); - using Stream stream = File.OpenRead(archiveFullPath); - using var reader = ReaderFactory.Open(stream); - Assert.True(reader.MoveToNextEntry()); - Assert.Equal("inner.tar.gz", reader.Entry.Key); + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsTarGz.tar"); + using (Stream stream = File.OpenRead(archiveFullPath)) + using (IReader reader = ReaderFactory.Open(stream)) + { + Assert.True(reader.MoveToNextEntry()); + Assert.Equal("inner.tar.gz", reader.Entry.Key); - using var entryStream = reader.OpenEntryStream(); - using var flushingStream = new FlushOnDisposeStream(entryStream); - - // Extract inner.tar.gz - using var innerReader = ReaderFactory.Open(flushingStream); - Assert.True(innerReader.MoveToNextEntry()); - Assert.Equal("test", innerReader.Entry.Key); + using (var entryStream = reader.OpenEntryStream()) + { + using (FlushOnDisposeStream flushingStream = new FlushOnDisposeStream(entryStream)) + { + // Extract inner.tar.gz + using (var innerReader = ReaderFactory.Open(flushingStream)) + { + Assert.True(innerReader.MoveToNextEntry()); + Assert.Equal("test", innerReader.Entry.Key); + } + } + } + } } [Fact] public void Tar_Broken_Stream() { - var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"); - using Stream stream = File.OpenRead(archiveFullPath); - using var reader = ReaderFactory.Open(stream); - var memoryStream = new MemoryStream(); + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"); + using (Stream stream = File.OpenRead(archiveFullPath)) + using (IReader reader = ReaderFactory.Open(stream)) + { + var memoryStream = new MemoryStream(); - Assert.True(reader.MoveToNextEntry()); - Assert.True(reader.MoveToNextEntry()); - reader.WriteEntryTo(memoryStream); - stream.Close(); - Assert.Throws(() => reader.MoveToNextEntry()); - } - - [Fact] - public void Tar_Corrupted() - { - var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "TarCorrupted.tar"); - using Stream stream = File.OpenRead(archiveFullPath); - using var reader = ReaderFactory.Open(stream); - var memoryStream = new MemoryStream(); - - Assert.True(reader.MoveToNextEntry()); - Assert.True(reader.MoveToNextEntry()); - reader.WriteEntryTo(memoryStream); - stream.Close(); - Assert.Throws(() => reader.MoveToNextEntry()); + Action action = () => reader.MoveToNextEntry(); + var exception = Record.Exception(action); + Assert.Null(exception); + reader.MoveToNextEntry(); + reader.WriteEntryTo(memoryStream); + stream.Close(); + Assert.Throws(action); + } } #if !NETFRAMEWORK @@ -205,55 +209,61 @@ public class TarReaderTests : ReaderTests var isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( System.Runtime.InteropServices.OSPlatform.Windows ); - using Stream stream = File.OpenRead( - Path.Combine(TEST_ARCHIVES_PATH, "TarWithSymlink.tar.gz") - ); - using var reader = TarReader.Open(stream); - while (reader.MoveToNextEntry()) + using ( + Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "TarWithSymlink.tar.gz")) + ) + using (var reader = TarReader.Open(stream)) { - if (reader.Entry.IsDirectory) + List names = new List(); + while (reader.MoveToNextEntry()) { - continue; - } - reader.WriteEntryToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions + if (reader.Entry.IsDirectory) { - ExtractFullPath = true, - Overwrite = true, - WriteSymbolicLink = (sourcePath, targetPath) => + continue; + } + reader.WriteEntryToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions() { - if (!isWindows) + ExtractFullPath = true, + Overwrite = true, + WriteSymbolicLink = (sourcePath, targetPath) => { - var link = new Mono.Unix.UnixSymbolicLinkInfo(sourcePath); - if (File.Exists(sourcePath)) + if (!isWindows) { - link.Delete(); // equivalent to ln -s -f + var link = new Mono.Unix.UnixSymbolicLinkInfo(sourcePath); + if (File.Exists(sourcePath)) + { + link.Delete(); // equivalent to ln -s -f + } + link.CreateSymbolicLinkTo(targetPath); } - link.CreateSymbolicLinkTo(targetPath); } } - } - ); - if (!isWindows) - { - if (reader.Entry.LinkTarget != null) + ); + if (!isWindows) { - var path = Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key.NotNull()); - var link = new Mono.Unix.UnixSymbolicLinkInfo(path); - if (link.HasContents) + if (reader.Entry.LinkTarget != null) { - // need to convert the link to an absolute path for comparison - var target = reader.Entry.LinkTarget; - var realTarget = Path.GetFullPath( - Path.Combine($"{Path.GetDirectoryName(path)}", target) - ); + var path = System.IO.Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key); + var link = new Mono.Unix.UnixSymbolicLinkInfo(path); + if (link.HasContents) + { + // need to convert the link to an absolute path for comparison + var target = reader.Entry.LinkTarget; + var realTarget = System.IO.Path.GetFullPath( + System.IO.Path.Combine( + $"{System.IO.Path.GetDirectoryName(path)}", + target + ) + ); - Assert.Equal(realTarget, link.GetContents().ToString()); - } - else - { - Assert.True(false, "Symlink has no target"); + Assert.Equal(realTarget, link.GetContents().ToString()); + } + else + { + Assert.True(false, "Symlink has no target"); + } } } } diff --git a/tests/SharpCompress.Test/TestBase.cs b/tests/SharpCompress.Test/TestBase.cs index 184e6442..3ad1fe79 100644 --- a/tests/SharpCompress.Test/TestBase.cs +++ b/tests/SharpCompress.Test/TestBase.cs @@ -10,15 +10,15 @@ namespace SharpCompress.Test; public class TestBase : IDisposable { - private readonly string SOLUTION_BASE_PATH; - protected readonly string TEST_ARCHIVES_PATH; - protected readonly string ORIGINAL_FILES_PATH; - protected readonly string MISC_TEST_FILES_PATH; - private readonly string SCRATCH_BASE_PATH; - protected readonly string SCRATCH_FILES_PATH; - protected readonly string SCRATCH2_FILES_PATH; + private string SOLUTION_BASE_PATH; + protected string TEST_ARCHIVES_PATH; + protected string ORIGINAL_FILES_PATH; + protected string MISC_TEST_FILES_PATH; + private string SCRATCH_BASE_PATH; + public string SCRATCH_FILES_PATH; + protected string SCRATCH2_FILES_PATH; - protected TestBase() + public TestBase() { var index = AppDomain.CurrentDomain.BaseDirectory.IndexOf( "SharpCompress.Test", @@ -110,14 +110,14 @@ public class TestBase : IDisposable Assert.True(extracted.Contains(orig.Key)); CompareFilesByPath(orig.Single(), extracted[orig.Key].Single()); - CompareFilesByTimeAndAttribute(orig.Single(), extracted[orig.Key].Single()); + CompareFilesByTimeAndAttribut(orig.Single(), extracted[orig.Key].Single()); } } /// /// Verifies the files by extension also check modified time and attributes. /// - private void VerifyFilesByExtensionEx() + protected void VerifyFilesByExtensionEx() { var extracted = Directory .EnumerateFiles(SCRATCH_FILES_PATH, "*.*", SearchOption.AllDirectories) @@ -133,7 +133,7 @@ public class TestBase : IDisposable Assert.True(extracted.Contains(orig.Key)); CompareFilesByPath(orig.Single(), extracted[orig.Key].Single()); - CompareFilesByTimeAndAttribute(orig.Single(), extracted[orig.Key].Single()); + CompareFilesByTimeAndAttribut(orig.Single(), extracted[orig.Key].Single()); } } @@ -194,7 +194,7 @@ public class TestBase : IDisposable } } - private void CompareFilesByTimeAndAttribute(string file1, string file2) + protected void CompareFilesByTimeAndAttribut(string file1, string file2) { var fi1 = new FileInfo(file1); var fi2 = new FileInfo(file2); @@ -216,8 +216,8 @@ public class TestBase : IDisposable while (archive1.MoveToNextEntry()) { Assert.True(archive2.MoveToNextEntry()); - archive1Entries.Add(archive1.Entry.Key.NotNull()); - archive2Entries.Add(archive2.Entry.Key.NotNull()); + archive1Entries.Add(archive1.Entry.Key); + archive2Entries.Add(archive2.Entry.Key); } Assert.False(archive2.MoveToNextEntry()); } diff --git a/tests/SharpCompress.Test/WriterTests.cs b/tests/SharpCompress.Test/WriterTests.cs index 50695ef1..64ed6d2c 100644 --- a/tests/SharpCompress.Test/WriterTests.cs +++ b/tests/SharpCompress.Test/WriterTests.cs @@ -9,9 +9,9 @@ namespace SharpCompress.Test; public class WriterTests : TestBase { - private readonly ArchiveType _type; + private readonly ArchiveType type; - protected WriterTests(ArchiveType type) => _type = type; + protected WriterTests(ArchiveType type) => this.type = type; protected void Write( CompressionType compressionType, @@ -26,7 +26,7 @@ public class WriterTests : TestBase writerOptions.ArchiveEncoding.Default = encoding ?? Encoding.Default; - using var writer = WriterFactory.Open(stream, _type, writerOptions); + using var writer = WriterFactory.Open(stream, type, writerOptions); writer.WriteAll(ORIGINAL_FILES_PATH, "*", SearchOption.AllDirectories); } CompareArchivesByPath( @@ -43,7 +43,7 @@ public class WriterTests : TestBase using var reader = ReaderFactory.Open(NonDisposingStream.Create(stream), readerOptions); reader.WriteAllToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true } + new ExtractionOptions() { ExtractFullPath = true } ); } VerifyFiles(); diff --git a/tests/SharpCompress.Test/Xz/Crc32Tests.cs b/tests/SharpCompress.Test/Xz/Crc32Tests.cs index eaa0b100..52b71078 100644 --- a/tests/SharpCompress.Test/Xz/Crc32Tests.cs +++ b/tests/SharpCompress.Test/Xz/Crc32Tests.cs @@ -6,16 +6,16 @@ namespace SharpCompress.Test.Xz; public class Crc32Tests { - private const string SIMPLE_STRING = @"The quick brown fox jumps over the lazy dog."; - private readonly byte[] _simpleBytes = Encoding.ASCII.GetBytes(SIMPLE_STRING); - private const string SIMPLE_STRING2 = + private const string SimpleString = @"The quick brown fox jumps over the lazy dog."; + private readonly byte[] SimpleBytes = Encoding.ASCII.GetBytes(SimpleString); + private const string SimpleString2 = @"Life moves pretty fast. If you don't stop and look around once in a while, you could miss it."; - private readonly byte[] _simpleBytes2 = Encoding.ASCII.GetBytes(SIMPLE_STRING2); + private readonly byte[] SimpleBytes2 = Encoding.ASCII.GetBytes(SimpleString2); [Fact] public void ShortAsciiString() { - var actual = Crc32.Compute(_simpleBytes); + var actual = Crc32.Compute(SimpleBytes); Assert.Equal((uint)0x519025e9, actual); } @@ -23,7 +23,7 @@ public class Crc32Tests [Fact] public void ShortAsciiString2() { - var actual = Crc32.Compute(_simpleBytes2); + var actual = Crc32.Compute(SimpleBytes2); Assert.Equal((uint)0x6ee3ad88, actual); } diff --git a/tests/SharpCompress.Test/Xz/Crc64Tests.cs b/tests/SharpCompress.Test/Xz/Crc64Tests.cs index 8cf71e1e..79912e48 100644 --- a/tests/SharpCompress.Test/Xz/Crc64Tests.cs +++ b/tests/SharpCompress.Test/Xz/Crc64Tests.cs @@ -6,16 +6,16 @@ namespace SharpCompress.Test.Xz; public class Crc64Tests { - private const string SIMPLE_STRING = @"The quick brown fox jumps over the lazy dog."; - private readonly byte[] _simpleBytes = Encoding.ASCII.GetBytes(SIMPLE_STRING); - private const string SIMPLE_STRING2 = + private const string SimpleString = @"The quick brown fox jumps over the lazy dog."; + private readonly byte[] SimpleBytes = Encoding.ASCII.GetBytes(SimpleString); + private const string SimpleString2 = @"Life moves pretty fast. If you don't stop and look around once in a while, you could miss it."; - private readonly byte[] _simpleBytes2 = Encoding.ASCII.GetBytes(SIMPLE_STRING2); + private readonly byte[] SimpleBytes2 = Encoding.ASCII.GetBytes(SimpleString2); [Fact] public void ShortAsciiString() { - var actual = Crc64.Compute(_simpleBytes); + var actual = Crc64.Compute(SimpleBytes); Assert.Equal((ulong)0x7E210EB1B03E5A1D, actual); } @@ -23,7 +23,7 @@ public class Crc64Tests [Fact] public void ShortAsciiString2() { - var actual = Crc64.Compute(_simpleBytes2); + var actual = Crc64.Compute(SimpleBytes2); Assert.Equal((ulong)0x416B4150508661EE, actual); } diff --git a/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs b/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs index bc16789d..427a7b98 100644 --- a/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs @@ -9,56 +9,56 @@ using Xunit; namespace SharpCompress.Test.Xz.Filters; -public class BcjTests : XzTestsBase +public class BCJTests : XZTestsBase { - private readonly ArmFilter _armFilter; - private readonly ArmThumbFilter _armtFilter; - private readonly IA64Filter _ia64Filter; - private readonly PowerPCFilter _ppcFilter; - private readonly SparcFilter _sparcFilter; - private readonly X86Filter _x86Filter; + private readonly ArmFilter armFilter; + private readonly ArmThumbFilter armtFilter; + private readonly IA64Filter ia64Filter; + private readonly PowerPCFilter ppcFilter; + private readonly SparcFilter sparcFilter; + private readonly X86Filter x86Filter; - public BcjTests() + public BCJTests() { - _armFilter = new ArmFilter(); - _armtFilter = new ArmThumbFilter(); - _ia64Filter = new IA64Filter(); - _ppcFilter = new PowerPCFilter(); - _sparcFilter = new SparcFilter(); - _x86Filter = new X86Filter(); + armFilter = new ArmFilter(); + armtFilter = new ArmThumbFilter(); + ia64Filter = new IA64Filter(); + ppcFilter = new PowerPCFilter(); + sparcFilter = new SparcFilter(); + x86Filter = new X86Filter(); } [Fact] public void IsOnlyAllowedLast() { - Assert.False(_armFilter.AllowAsLast); - Assert.True(_armFilter.AllowAsNonLast); + Assert.False(armFilter.AllowAsLast); + Assert.True(armFilter.AllowAsNonLast); - Assert.False(_armtFilter.AllowAsLast); - Assert.True(_armtFilter.AllowAsNonLast); + Assert.False(armtFilter.AllowAsLast); + Assert.True(armtFilter.AllowAsNonLast); - Assert.False(_ia64Filter.AllowAsLast); - Assert.True(_ia64Filter.AllowAsNonLast); + Assert.False(ia64Filter.AllowAsLast); + Assert.True(ia64Filter.AllowAsNonLast); - Assert.False(_ppcFilter.AllowAsLast); - Assert.True(_ppcFilter.AllowAsNonLast); + Assert.False(ppcFilter.AllowAsLast); + Assert.True(ppcFilter.AllowAsNonLast); - Assert.False(_sparcFilter.AllowAsLast); - Assert.True(_sparcFilter.AllowAsNonLast); + Assert.False(sparcFilter.AllowAsLast); + Assert.True(sparcFilter.AllowAsNonLast); - Assert.False(_x86Filter.AllowAsLast); - Assert.True(_x86Filter.AllowAsNonLast); + Assert.False(x86Filter.AllowAsLast); + Assert.True(x86Filter.AllowAsNonLast); } [Fact] public void ChangesStreamSize() { - Assert.False(_armFilter.ChangesDataSize); - Assert.False(_armtFilter.ChangesDataSize); - Assert.False(_ia64Filter.ChangesDataSize); - Assert.False(_ppcFilter.ChangesDataSize); - Assert.False(_sparcFilter.ChangesDataSize); - Assert.False(_x86Filter.ChangesDataSize); + Assert.False(armFilter.ChangesDataSize); + Assert.False(armtFilter.ChangesDataSize); + Assert.False(ia64Filter.ChangesDataSize); + Assert.False(ppcFilter.ChangesDataSize); + Assert.False(sparcFilter.ChangesDataSize); + Assert.False(x86Filter.ChangesDataSize); } [Theory] @@ -67,22 +67,22 @@ public class BcjTests : XzTestsBase public void OnlyAcceptsOneByte(byte[] bytes) { InvalidDataException ex; - ex = Assert.Throws(() => _armFilter.Init(bytes)); + ex = Assert.Throws(() => armFilter.Init(bytes)); Assert.Equal("ARM properties unexpected length", ex.Message); - ex = Assert.Throws(() => _armtFilter.Init(bytes)); + ex = Assert.Throws(() => armtFilter.Init(bytes)); Assert.Equal("ARM Thumb properties unexpected length", ex.Message); - ex = Assert.Throws(() => _ia64Filter.Init(bytes)); + ex = Assert.Throws(() => ia64Filter.Init(bytes)); Assert.Equal("IA64 properties unexpected length", ex.Message); - ex = Assert.Throws(() => _ppcFilter.Init(bytes)); + ex = Assert.Throws(() => ppcFilter.Init(bytes)); Assert.Equal("PPC properties unexpected length", ex.Message); - ex = Assert.Throws(() => _sparcFilter.Init(bytes)); + ex = Assert.Throws(() => sparcFilter.Init(bytes)); Assert.Equal("SPARC properties unexpected length", ex.Message); - ex = Assert.Throws(() => _x86Filter.Init(bytes)); + ex = Assert.Throws(() => x86Filter.Init(bytes)); Assert.Equal("X86 properties unexpected length", ex.Message); } } diff --git a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs index e77bc2f8..83eed21c 100644 --- a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs @@ -1,25 +1,25 @@ using System; +using Xunit; using System.IO; using SharpCompress.Compressors.Xz.Filters; -using Xunit; namespace SharpCompress.Test.Xz.Filters; -public class Lzma2Tests : XzTestsBase +public class Lzma2Tests : XZTestsBase { - private readonly Lzma2Filter _filter; + private readonly Lzma2Filter filter; - public Lzma2Tests() => _filter = new Lzma2Filter(); + public Lzma2Tests() => filter = new Lzma2Filter(); [Fact] public void IsOnlyAllowedLast() { - Assert.True(_filter.AllowAsLast); - Assert.False(_filter.AllowAsNonLast); + Assert.True(filter.AllowAsLast); + Assert.False(filter.AllowAsNonLast); } [Fact] - public void ChangesStreamSize() => Assert.True(_filter.ChangesDataSize); + public void ChangesStreamSize() => Assert.True(filter.ChangesDataSize); [Theory] [InlineData(0, (uint)4 * 1024)] @@ -31,18 +31,18 @@ public class Lzma2Tests : XzTestsBase [InlineData(40, (uint)(1024 * 1024 * 1024 - 1) * 4 + 3)] public void CalculatesDictionarySize(byte inByte, uint dicSize) { - _filter.Init([inByte]); - Assert.Equal(_filter.DictionarySize, dicSize); + filter.Init(new[] { inByte }); + Assert.Equal(filter.DictionarySize, dicSize); } [Fact] public void CalculatesDictionarySizeError() { uint temp; - _filter.Init([41]); + filter.Init(new byte[] { 41 }); var ex = Assert.Throws(() => { - temp = _filter.DictionarySize; + temp = filter.DictionarySize; }); Assert.Equal("Dictionary size greater than UInt32.Max", ex.Message); } @@ -52,14 +52,14 @@ public class Lzma2Tests : XzTestsBase [InlineData(new byte[] { 0, 0 })] public void OnlyAcceptsOneByte(byte[] bytes) { - var ex = Assert.Throws(() => _filter.Init(bytes)); + var ex = Assert.Throws(() => filter.Init(bytes)); Assert.Equal("LZMA properties unexpected length", ex.Message); } [Fact] public void ReservedBytesThrow() { - var ex = Assert.Throws(() => _filter.Init([0xC0])); + var ex = Assert.Throws(() => filter.Init(new byte[] { 0xC0 })); Assert.Equal("Reserved bits used in LZMA properties", ex.Message); } } diff --git a/tests/SharpCompress.Test/Xz/XZBlockTests.cs b/tests/SharpCompress.Test/Xz/XZBlockTests.cs index 78873590..87e68d93 100644 --- a/tests/SharpCompress.Test/Xz/XZBlockTests.cs +++ b/tests/SharpCompress.Test/Xz/XZBlockTests.cs @@ -5,7 +5,7 @@ using Xunit; namespace SharpCompress.Test.Xz; -public class XzBlockTests : XzTestsBase +public class XZBlockTests : XZTestsBase { protected override void Rewind(Stream stream) => stream.Position = 12; @@ -28,10 +28,10 @@ public class XzBlockTests : XzTestsBase { var bytes = new byte[] { 0 }; using Stream indexBlockStream = new MemoryStream(bytes); - var xzBlock = new XZBlock(indexBlockStream, CheckType.CRC64, 8); + var XZBlock = new XZBlock(indexBlockStream, CheckType.CRC64, 8); Assert.Throws(() => { - ReadBytes(xzBlock, 1); + ReadBytes(XZBlock, 1); }); } @@ -42,10 +42,10 @@ public class XzBlockTests : XzTestsBase bytes[20]++; using Stream badCrcStream = new MemoryStream(bytes); Rewind(badCrcStream); - var xzBlock = new XZBlock(badCrcStream, CheckType.CRC64, 8); + var XZBlock = new XZBlock(badCrcStream, CheckType.CRC64, 8); var ex = Assert.Throws(() => { - ReadBytes(xzBlock, 1); + ReadBytes(XZBlock, 1); }); Assert.Equal("Block header corrupt", ex.Message); } @@ -53,24 +53,24 @@ public class XzBlockTests : XzTestsBase [Fact] public void CanReadM() { - var xzBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); - Assert.Equal(Encoding.ASCII.GetBytes("M"), ReadBytes(xzBlock, 1)); + var XZBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); + Assert.Equal(Encoding.ASCII.GetBytes("M"), ReadBytes(XZBlock, 1)); } [Fact] public void CanReadMary() { - var xzBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); - Assert.Equal(Encoding.ASCII.GetBytes("M"), ReadBytes(xzBlock, 1)); - Assert.Equal(Encoding.ASCII.GetBytes("a"), ReadBytes(xzBlock, 1)); - Assert.Equal(Encoding.ASCII.GetBytes("ry"), ReadBytes(xzBlock, 2)); + var XZBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); + Assert.Equal(Encoding.ASCII.GetBytes("M"), ReadBytes(XZBlock, 1)); + Assert.Equal(Encoding.ASCII.GetBytes("a"), ReadBytes(XZBlock, 1)); + Assert.Equal(Encoding.ASCII.GetBytes("ry"), ReadBytes(XZBlock, 2)); } [Fact] public void CanReadPoemWithStreamReader() { - var xzBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); - var sr = new StreamReader(xzBlock); + var XZBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); + var sr = new StreamReader(XZBlock); Assert.Equal(sr.ReadToEnd(), Original); } @@ -78,8 +78,8 @@ public class XzBlockTests : XzTestsBase public void NoopWhenNoPadding() { // CompressedStream's only block has no padding. - var xzBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); - var sr = new StreamReader(xzBlock); + var XZBlock = new XZBlock(CompressedStream, CheckType.CRC64, 8); + var sr = new StreamReader(XZBlock); sr.ReadToEnd(); Assert.Equal(0L, CompressedStream.Position % 4L); } @@ -88,8 +88,8 @@ public class XzBlockTests : XzTestsBase public void SkipsPaddingWhenPresent() { // CompressedIndexedStream's first block has 1-byte padding. - var xzBlock = new XZBlock(CompressedIndexedStream, CheckType.CRC64, 8); - var sr = new StreamReader(xzBlock); + var XZBlock = new XZBlock(CompressedIndexedStream, CheckType.CRC64, 8); + var sr = new StreamReader(XZBlock); sr.ReadToEnd(); Assert.Equal(0L, CompressedIndexedStream.Position % 4L); } diff --git a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs index 8815b7a9..3fa9dc86 100644 --- a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs +++ b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs @@ -1,24 +1,26 @@ -using System.IO; using SharpCompress.Compressors.Xz; +using System.IO; using Xunit; namespace SharpCompress.Test.Xz; -public class XzHeaderTests : XzTestsBase +public class XZHeaderTests : XZTestsBase { [Fact] public void ChecksMagicNumber() { var bytes = (byte[])Compressed.Clone(); bytes[3]++; - using Stream badMagicNumberStream = new MemoryStream(bytes); - var br = new BinaryReader(badMagicNumberStream); - var header = new XZHeader(br); - var ex = Assert.Throws(() => + using (Stream badMagicNumberStream = new MemoryStream(bytes)) { - header.Process(); - }); - Assert.Equal("Invalid XZ Stream", ex.Message); + BinaryReader br = new BinaryReader(badMagicNumberStream); + var header = new XZHeader(br); + var ex = Assert.Throws(() => + { + header.Process(); + }); + Assert.Equal("Invalid XZ Stream", ex.Message); + } } [Fact] @@ -26,38 +28,42 @@ public class XzHeaderTests : XzTestsBase { var bytes = (byte[])Compressed.Clone(); bytes[8]++; - using Stream badCrcStream = new MemoryStream(bytes); - var br = new BinaryReader(badCrcStream); - var header = new XZHeader(br); - var ex = Assert.Throws(() => + using (Stream badCrcStream = new MemoryStream(bytes)) { - header.Process(); - }); - Assert.Equal("Stream header corrupt", ex.Message); + BinaryReader br = new BinaryReader(badCrcStream); + var header = new XZHeader(br); + var ex = Assert.Throws(() => + { + header.Process(); + }); + Assert.Equal("Stream header corrupt", ex.Message); + } } [Fact] public void BadVersionIfCrcOkButStreamFlagUnknown() { var bytes = (byte[])Compressed.Clone(); - byte[] streamFlags = [0x00, 0xF4]; - var crc = Crc32.Compute(streamFlags).ToLittleEndianBytes(); + byte[] streamFlags = { 0x00, 0xF4 }; + byte[] crc = Crc32.Compute(streamFlags).ToLittleEndianBytes(); streamFlags.CopyTo(bytes, 6); crc.CopyTo(bytes, 8); - using Stream badFlagStream = new MemoryStream(bytes); - var br = new BinaryReader(badFlagStream); - var header = new XZHeader(br); - var ex = Assert.Throws(() => + using (Stream badFlagStream = new MemoryStream(bytes)) { - header.Process(); - }); - Assert.Equal("Unknown XZ Stream Version", ex.Message); + BinaryReader br = new BinaryReader(badFlagStream); + var header = new XZHeader(br); + var ex = Assert.Throws(() => + { + header.Process(); + }); + Assert.Equal("Unknown XZ Stream Version", ex.Message); + } } [Fact] public void ProcessesBlockCheckType() { - var br = new BinaryReader(CompressedStream); + BinaryReader br = new BinaryReader(CompressedStream); var header = new XZHeader(br); header.Process(); Assert.Equal(CheckType.CRC64, header.BlockCheckType); @@ -66,7 +72,7 @@ public class XzHeaderTests : XzTestsBase [Fact] public void CanCalculateBlockCheckSize() { - var br = new BinaryReader(CompressedStream); + BinaryReader br = new BinaryReader(CompressedStream); var header = new XZHeader(br); header.Process(); Assert.Equal(8, header.BlockCheckSize); diff --git a/tests/SharpCompress.Test/Xz/XZIndexTests.cs b/tests/SharpCompress.Test/Xz/XZIndexTests.cs index b00b9d1a..9c9d15bf 100644 --- a/tests/SharpCompress.Test/Xz/XZIndexTests.cs +++ b/tests/SharpCompress.Test/Xz/XZIndexTests.cs @@ -1,10 +1,10 @@ -using System.IO; -using SharpCompress.Compressors.Xz; +using SharpCompress.Compressors.Xz; +using System.IO; using Xunit; namespace SharpCompress.Test.Xz; -public class XzIndexTests : XzTestsBase +public class XZIndexTests : XZTestsBase { protected override void RewindEmpty(Stream stream) => stream.Position = 12; @@ -15,25 +15,29 @@ public class XzIndexTests : XzTestsBase [Fact] public void RecordsStreamStartOnInit() { - using Stream badStream = new MemoryStream([1, 2, 3, 4, 5]); - var br = new BinaryReader(badStream); - var index = new XZIndex(br, false); - Assert.Equal(0, index.StreamStartPosition); + using (Stream badStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 })) + { + BinaryReader br = new BinaryReader(badStream); + var index = new XZIndex(br, false); + Assert.Equal(0, index.StreamStartPosition); + } } [Fact] public void ThrowsIfHasNoIndexMarker() { - using Stream badStream = new MemoryStream([1, 2, 3, 4, 5]); - var br = new BinaryReader(badStream); - var index = new XZIndex(br, false); - Assert.Throws(() => index.Process()); + using (Stream badStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 })) + { + BinaryReader br = new BinaryReader(badStream); + var index = new XZIndex(br, false); + Assert.Throws(() => index.Process()); + } } [Fact] public void ReadsNoRecord() { - var br = new BinaryReader(CompressedEmptyStream); + BinaryReader br = new BinaryReader(CompressedEmptyStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)0, index.NumberOfRecords); @@ -42,7 +46,7 @@ public class XzIndexTests : XzTestsBase [Fact] public void ReadsOneRecord() { - var br = new BinaryReader(CompressedStream); + BinaryReader br = new BinaryReader(CompressedStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)1, index.NumberOfRecords); @@ -51,7 +55,7 @@ public class XzIndexTests : XzTestsBase [Fact] public void ReadsMultipleRecords() { - var br = new BinaryReader(CompressedIndexedStream); + BinaryReader br = new BinaryReader(CompressedIndexedStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)2, index.NumberOfRecords); @@ -60,7 +64,7 @@ public class XzIndexTests : XzTestsBase [Fact] public void ReadsFirstRecord() { - var br = new BinaryReader(CompressedStream); + BinaryReader br = new BinaryReader(CompressedStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)OriginalBytes.Length, index.Records[0].UncompressedSize); @@ -70,12 +74,31 @@ public class XzIndexTests : XzTestsBase public void SkipsPadding() { // Index with 3-byte padding. - using Stream badStream = new MemoryStream( - [0x00, 0x01, 0x10, 0x80, 0x01, 0x00, 0x00, 0x00, 0xB1, 0x01, 0xD9, 0xC9, 0xFF] - ); - var br = new BinaryReader(badStream); - var index = new XZIndex(br, false); - index.Process(); - Assert.Equal(0L, badStream.Position % 4L); + using ( + Stream badStream = new MemoryStream( + new byte[] + { + 0x00, + 0x01, + 0x10, + 0x80, + 0x01, + 0x00, + 0x00, + 0x00, + 0xB1, + 0x01, + 0xD9, + 0xC9, + 0xFF + } + ) + ) + { + BinaryReader br = new BinaryReader(badStream); + var index = new XZIndex(br, false); + index.Process(); + Assert.Equal(0L, badStream.Position % 4L); + } } } diff --git a/tests/SharpCompress.Test/Xz/XZStreamTests.cs b/tests/SharpCompress.Test/Xz/XZStreamTests.cs index 02c5020c..1f50fb40 100644 --- a/tests/SharpCompress.Test/Xz/XZStreamTests.cs +++ b/tests/SharpCompress.Test/Xz/XZStreamTests.cs @@ -1,35 +1,41 @@ -using System.IO; -using SharpCompress.Compressors.Xz; +using SharpCompress.Compressors.Xz; +using System.IO; using Xunit; namespace SharpCompress.Test.Xz; -public class XzStreamTests : XzTestsBase +public class XZStreamTests : XZTestsBase { [Fact] public void CanReadEmptyStream() { - var xz = new XZStream(CompressedEmptyStream); - using var sr = new StreamReader(xz); - var uncompressed = sr.ReadToEnd(); - Assert.Equal(OriginalEmpty, uncompressed); + XZStream xz = new XZStream(CompressedEmptyStream); + using (var sr = new StreamReader(xz)) + { + string uncompressed = sr.ReadToEnd(); + Assert.Equal(OriginalEmpty, uncompressed); + } } [Fact] public void CanReadStream() { - var xz = new XZStream(CompressedStream); - using var sr = new StreamReader(xz); - var uncompressed = sr.ReadToEnd(); - Assert.Equal(Original, uncompressed); + XZStream xz = new XZStream(CompressedStream); + using (var sr = new StreamReader(xz)) + { + string uncompressed = sr.ReadToEnd(); + Assert.Equal(Original, uncompressed); + } } [Fact] public void CanReadIndexedStream() { - var xz = new XZStream(CompressedIndexedStream); - using var sr = new StreamReader(xz); - var uncompressed = sr.ReadToEnd(); - Assert.Equal(OriginalIndexed, uncompressed); + XZStream xz = new XZStream(CompressedIndexedStream); + using (var sr = new StreamReader(xz)) + { + string uncompressed = sr.ReadToEnd(); + Assert.Equal(OriginalIndexed, uncompressed); + } } } diff --git a/tests/SharpCompress.Test/Xz/XZTestsBase.cs b/tests/SharpCompress.Test/Xz/XZTestsBase.cs index a679934e..5a1b5cbb 100644 --- a/tests/SharpCompress.Test/Xz/XZTestsBase.cs +++ b/tests/SharpCompress.Test/Xz/XZTestsBase.cs @@ -4,9 +4,9 @@ using System.Text; namespace SharpCompress.Test.Xz; -public abstract class XzTestsBase : IDisposable +public abstract class XZTestsBase : IDisposable { - public XzTestsBase() + public XZTestsBase() { RewindEmpty(CompressedEmptyStream); Rewind(CompressedStream); @@ -29,7 +29,8 @@ public abstract class XzTestsBase : IDisposable protected Stream CompressedEmptyStream { get; } = new MemoryStream(CompressedEmpty); protected static byte[] CompressedEmpty { get; } = - [ + new byte[] + { 0xfd, 0x37, 0x7a, @@ -62,7 +63,7 @@ public abstract class XzTestsBase : IDisposable 0x01, 0x59, 0x5a - ]; + }; protected static byte[] OriginalEmptyBytes => Encoding.ASCII.GetBytes(OriginalEmpty); @@ -71,7 +72,8 @@ public abstract class XzTestsBase : IDisposable protected Stream CompressedStream { get; } = new MemoryStream(Compressed); protected static byte[] Compressed { get; } = - [ + new byte[] + { 0xfd, 0x37, 0x7a, @@ -452,7 +454,7 @@ public abstract class XzTestsBase : IDisposable 0x04, 0x59, 0x5a - ]; + }; protected static byte[] OriginalBytes => Encoding.ASCII.GetBytes(Original); protected static string Original { get; } = @@ -479,7 +481,8 @@ public abstract class XzTestsBase : IDisposable protected Stream CompressedIndexedStream { get; } = new MemoryStream(CompressedIndexed); protected static byte[] CompressedIndexed { get; } = - [ + new byte[] + { 0xfd, 0x37, 0x7a, @@ -1120,7 +1123,7 @@ public abstract class XzTestsBase : IDisposable 0x01, 0x59, 0x5a - ]; + }; protected static byte[] OriginalIndexedBytes => Encoding.ASCII.GetBytes(OriginalIndexed); diff --git a/tests/SharpCompress.Test/Zip/Zip64Tests.cs b/tests/SharpCompress.Test/Zip/Zip64Tests.cs index a89b1128..739867f7 100644 --- a/tests/SharpCompress.Test/Zip/Zip64Tests.cs +++ b/tests/SharpCompress.Test/Zip/Zip64Tests.cs @@ -3,8 +3,6 @@ using System.IO; using System.Linq; using SharpCompress.Archives; using SharpCompress.Common; -using SharpCompress.Common.Zip; -using SharpCompress.Compressors.Deflate; using SharpCompress.Readers; using SharpCompress.Readers.Zip; using SharpCompress.Test.Mocks; @@ -25,27 +23,27 @@ public class Zip64Tests : WriterTests [Trait("format", "zip64")] public void Zip64_Single_Large_File() => // One single file, requires zip64 - RunSingleTest(1, FOUR_GB_LIMIT, setZip64: true, forwardOnly: false); + RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: true, forward_only: false); [Trait("format", "zip64")] public void Zip64_Two_Large_Files() => // One single file, requires zip64 - RunSingleTest(2, FOUR_GB_LIMIT, setZip64: true, forwardOnly: false); + RunSingleTest(2, FOUR_GB_LIMIT, set_zip64: true, forward_only: false); [Trait("format", "zip64")] public void Zip64_Two_Small_files() => // Multiple files, does not require zip64 - RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: false, forwardOnly: false); + RunSingleTest(2, FOUR_GB_LIMIT / 2, set_zip64: false, forward_only: false); [Trait("format", "zip64")] public void Zip64_Two_Small_files_stream() => // Multiple files, does not require zip64, and works with streams - RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: false, forwardOnly: true); + RunSingleTest(2, FOUR_GB_LIMIT / 2, set_zip64: false, forward_only: true); [Trait("format", "zip64")] public void Zip64_Two_Small_Files_Zip64() => // Multiple files, use zip64 even though it is not required - RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: true, forwardOnly: false); + RunSingleTest(2, FOUR_GB_LIMIT / 2, set_zip64: true, forward_only: false); [Trait("format", "zip64")] public void Zip64_Single_Large_File_Fail() @@ -53,7 +51,7 @@ public class Zip64Tests : WriterTests try { // One single file, should fail - RunSingleTest(1, FOUR_GB_LIMIT, setZip64: false, forwardOnly: false); + RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: false, forward_only: false); throw new InvalidOperationException("Test did not fail?"); } catch (NotSupportedException) { } @@ -65,7 +63,7 @@ public class Zip64Tests : WriterTests try { // One single file, should fail (fast) with zip64 - RunSingleTest(1, FOUR_GB_LIMIT, setZip64: true, forwardOnly: true); + RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: true, forward_only: true); throw new InvalidOperationException("Test did not fail?"); } catch (NotSupportedException) { } @@ -77,7 +75,7 @@ public class Zip64Tests : WriterTests try { // One single file, should fail once the write discovers the problem - RunSingleTest(1, FOUR_GB_LIMIT, setZip64: false, forwardOnly: true); + RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: false, forward_only: true); throw new InvalidOperationException("Test did not fail?"); } catch (NotSupportedException) { } @@ -86,9 +84,9 @@ public class Zip64Tests : WriterTests public void RunSingleTest( long files, long filesize, - bool setZip64, - bool forwardOnly, - long writeChunkSize = 1024 * 1024, + bool set_zip64, + bool forward_only, + long write_chunk_size = 1024 * 1024, string filename = "zip64-test.zip" ) { @@ -101,7 +99,7 @@ public class Zip64Tests : WriterTests if (!File.Exists(filename)) { - CreateZipArchive(filename, files, filesize, writeChunkSize, setZip64, forwardOnly); + CreateZipArchive(filename, files, filesize, write_chunk_size, set_zip64, forward_only); } var resForward = ReadForwardOnly(filename); @@ -140,20 +138,23 @@ public class Zip64Tests : WriterTests long files, long filesize, long chunksize, - bool setZip64, - bool forwardOnly + bool set_zip64, + bool forward_only ) { var data = new byte[chunksize]; // Use deflate for speed - var opts = new ZipWriterOptions(CompressionType.Deflate) { UseZip64 = setZip64 }; + var opts = new ZipWriterOptions(CompressionType.Deflate) { UseZip64 = set_zip64 }; // Use no compression to ensure we hit the limits (actually inflates a bit, but seems better than using method==Store) - var eo = new ZipWriterEntryOptions { DeflateCompressionLevel = CompressionLevel.None }; + var eo = new ZipWriterEntryOptions() + { + DeflateCompressionLevel = Compressors.Deflate.CompressionLevel.None + }; using var zip = File.OpenWrite(filename); - using var st = forwardOnly ? (Stream)new ForwardOnlyStream(zip) : zip; + using var st = forward_only ? (Stream)new ForwardOnlyStream(zip) : zip; using var zipWriter = (ZipWriter)WriterFactory.Open(st, ArchiveType.Zip, opts); for (var i = 0; i < files; i++) { @@ -172,9 +173,9 @@ public class Zip64Tests : WriterTests { long count = 0; long size = 0; - ZipEntry? prev = null; + Common.Zip.ZipEntry? prev = null; using (var fs = File.OpenRead(filename)) - using (var rd = ZipReader.Open(fs, new ReaderOptions { LookForHeader = false })) + using (var rd = ZipReader.Open(fs, new ReaderOptions() { LookForHeader = false })) { while (rd.MoveToNextEntry()) { diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index 494e02c9..fde87dc6 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -16,14 +16,6 @@ public class ZipArchiveTests : ArchiveTests { public ZipArchiveTests() => UseExtensionInsteadOfNameToVerify = true; - [Fact] - public void Zip_Shrink_ArchiveStreamRead() - { - UseExtensionInsteadOfNameToVerify = true; - UseCaseInsensitiveToVerify = true; - ArchiveStreamRead("Zip.shrink.zip"); - } - [Fact] public void Zip_ZipX_ArchiveStreamRead() => ArchiveStreamRead("Zip.zipx"); @@ -186,14 +178,14 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Random_Write_Remove() { - var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip"); - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); - var modified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod.zip"); + string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip"); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); + string modified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod.zip"); using (var archive = ZipArchive.Open(unmodified)) { - var entry = archive.Entries.Single(x => - x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + var entry = archive.Entries.Single( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ); archive.RemoveEntry(entry); @@ -208,10 +200,10 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Random_Write_Add() { - var jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg"); - var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip"); - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod.zip"); - var modified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod2.zip"); + string jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg"); + string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Zip.deflate.mod.zip"); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod.zip"); + string modified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.mod2.zip"); using (var archive = ZipArchive.Open(unmodified)) { @@ -228,12 +220,12 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Save_Twice() { - var scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); - var scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); + string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); + string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); using (var arc = ZipArchive.Create()) { - var str = "test.txt"; + string str = "test.txt"; var source = new MemoryStream(Encoding.UTF8.GetBytes(str)); arc.AddEntry("test.txt", source, true, source.Length); arc.SaveTo(scratchPath1, CompressionType.Deflate); @@ -246,38 +238,42 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Removal_Poly() { - var scratchPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); + string scratchPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); - using var vfs = (ZipArchive)ArchiveFactory.Open(scratchPath); - var e = vfs.Entries.First(v => - v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ); - vfs.RemoveEntry(e); - Assert.Null( - vfs.Entries.FirstOrDefault(v => - v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ) - ); - Assert.Null( - ((IArchive)vfs).Entries.FirstOrDefault(v => - v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ) - ); + using (ZipArchive vfs = (ZipArchive)ArchiveFactory.Open(scratchPath)) + { + var e = vfs.Entries.First( + v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ); + vfs.RemoveEntry(e); + Assert.Null( + vfs.Entries.FirstOrDefault( + v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ) + ); + Assert.Null( + ((IArchive)vfs).Entries.FirstOrDefault( + v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ) + ); + } } [Fact] public void Zip_Create_NoDups() { - using var arc = ZipArchive.Create(); - arc.AddEntry("1.txt", new MemoryStream()); - Assert.Throws(() => arc.AddEntry("\\1.txt", new MemoryStream())); + using (var arc = ZipArchive.Create()) + { + arc.AddEntry("1.txt", new MemoryStream()); + Assert.Throws(() => arc.AddEntry("\\1.txt", new MemoryStream())); + } } [Fact] public void Zip_Create_Same_Stream() { - var scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); - var scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); + string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); + string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); using (var arc = ZipArchive.Create()) { @@ -322,8 +318,8 @@ public class ZipArchiveTests : ArchiveTests } File.Copy(file, newFileName); } - var scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); + string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); using (var archive = ZipArchive.Create()) { @@ -389,19 +385,19 @@ public class ZipArchiveTests : ArchiveTests } File.Copy(file, newFileName); } - var scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); + string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); using (var archive = ZipArchive.Create()) { archive.AddAllFromDirectory(SCRATCH_FILES_PATH); archive.RemoveEntry( - archive.Entries.Single(x => - x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + archive.Entries.Single( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); Assert.Null( - archive.Entries.FirstOrDefault(x => - x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + archive.Entries.FirstOrDefault( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); } @@ -414,7 +410,7 @@ public class ZipArchiveTests : ArchiveTests using ( var reader = ZipArchive.Open( Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES.zip"), - new ReaderOptions { Password = "test" } + new ReaderOptions() { Password = "test" } ) ) { @@ -422,7 +418,7 @@ public class ZipArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -432,32 +428,40 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Deflate_WinzipAES_MultiOpenEntryStream() { - using var reader = ZipArchive.Open( - Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES2.zip"), - new ReaderOptions { Password = "test" } - ); - foreach (var entry in reader.Entries.Where(x => !x.IsDirectory)) + using ( + var reader = ZipArchive.Open( + Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES2.zip"), + new ReaderOptions() { Password = "test" } + ) + ) { - var stream = entry.OpenEntryStream(); - Assert.NotNull(stream); - var ex = Record.Exception(() => stream = entry.OpenEntryStream()); - Assert.Null(ex); + foreach (var entry in reader.Entries.Where(x => !x.IsDirectory)) + { + var stream = entry.OpenEntryStream(); + Assert.NotNull(stream); + var ex = Record.Exception(() => stream = entry.OpenEntryStream()); + Assert.Null(ex); + } } } [Fact] public void Zip_Read_Volume_Comment() { - using var reader = ZipArchive.Open( - Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.zip"), - new ReaderOptions { Password = "test" } - ); - var isComplete = reader.IsComplete; - Assert.Equal(1, reader.Volumes.Count); + using ( + var reader = ZipArchive.Open( + Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.zip"), + new ReaderOptions() { Password = "test" } + ) + ) + { + var isComplete = reader.IsComplete; + Assert.Equal(1, reader.Volumes.Count); - var expectedComment = - "Encoding:utf-8 || Compression:Deflate levelDefault || Encrypt:None || ZIP64:Always\r\nCreated at 2017-Jan-23 14:10:43 || DotNetZip Tool v1.9.1.8\r\nTest zip64 archive"; - Assert.Equal(expectedComment, reader.Volumes.First().Comment); + string expectedComment = + "Encoding:utf-8 || Compression:Deflate levelDefault || Encrypt:None || ZIP64:Always\r\nCreated at 2017-Jan-23 14:10:43 || DotNetZip Tool v1.9.1.8\r\nTest zip64 archive"; + Assert.Equal(expectedComment, reader.Volumes.First().Comment); + } } [Fact] @@ -466,7 +470,7 @@ public class ZipArchiveTests : ArchiveTests using ( var reader = ZipArchive.Open( Path.Combine(TEST_ARCHIVES_PATH, "Zip.bzip2.pkware.zip"), - new ReaderOptions { Password = "test" } + new ReaderOptions() { Password = "test" } ) ) { @@ -474,7 +478,7 @@ public class ZipArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -484,10 +488,10 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Random_Entry_Access() { - var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); + string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); - var a = ZipArchive.Open(unmodified); - var count = 0; + ZipArchive a = ZipArchive.Open(unmodified); + int count = 0; foreach (var e in a.Entries) { count++; @@ -498,7 +502,7 @@ public class ZipArchiveTests : ArchiveTests a.Dispose(); a = ZipArchive.Open(unmodified); - var count2 = 0; + int count2 = 0; foreach (var e in a.Entries) { @@ -514,7 +518,7 @@ public class ZipArchiveTests : ArchiveTests } } - var count3 = 0; + int count3 = 0; foreach (var e in a.Entries) { count3++; @@ -526,21 +530,29 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Deflate_PKWear_Multipy_Entry_Access() { - var zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.pkware.zip"); + string zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.pkware.zip"); - using var fileStream = File.Open(zipFile, FileMode.Open); - using var archive = ArchiveFactory.Open( - fileStream, - new ReaderOptions { Password = "12345678" } - ); - var entries = archive.Entries.Where(entry => !entry.IsDirectory); - foreach (var entry in entries) + using (FileStream fileStream = File.Open(zipFile, FileMode.Open)) { - for (var i = 0; i < 100; i++) + using ( + IArchive archive = ArchiveFactory.Open( + fileStream, + new ReaderOptions { Password = "12345678" } + ) + ) { - using var memoryStream = new MemoryStream(); - using var entryStream = entry.OpenEntryStream(); - entryStream.CopyTo(memoryStream); + var entries = archive.Entries.Where(entry => !entry.IsDirectory); + foreach (IArchiveEntry entry in entries) + { + for (var i = 0; i < 100; i++) + { + using (var memoryStream = new MemoryStream()) + using (Stream entryStream = entry.OpenEntryStream()) + { + entryStream.CopyTo(memoryStream); + } + } + } } } } @@ -551,17 +563,19 @@ public class ZipArchiveTests : ArchiveTests //windows only because of the paths Skip.IfNot(Environment.OSVersion.Platform == PlatformID.Win32NT); - var zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.Evil.zip"); + string zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.Evil.zip"); Assert.ThrowsAny(() => { - using var archive = ZipArchive.Open(zipFile); - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + using (var archive = ZipArchive.Open(zipFile)) { - entry.WriteToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } - ); + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) + { + entry.WriteToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + ); + } } }); } @@ -576,7 +590,9 @@ public class ZipArchiveTests : ArchiveTests { MemoryStream stream = new NonSeekableMemoryStream(); - using (var zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate)) + using ( + IWriter zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate) + ) { zipWriter.Write("foo.txt", new MemoryStream(Array.Empty())); zipWriter.Write("foo2.txt", new MemoryStream(new byte[10])); @@ -589,14 +605,16 @@ public class ZipArchiveTests : ArchiveTests { foreach (var entry in zipArchive.Entries) { - using var entryStream = entry.OpenEntryStream(); - var tempStream = new MemoryStream(); - const int bufSize = 0x1000; - var buf = new byte[bufSize]; - var bytesRead = 0; - while ((bytesRead = entryStream.Read(buf, 0, bufSize)) > 0) + using (var entryStream = entry.OpenEntryStream()) { - tempStream.Write(buf, 0, bytesRead); + MemoryStream tempStream = new MemoryStream(); + const int bufSize = 0x1000; + byte[] buf = new byte[bufSize]; + int bytesRead = 0; + while ((bytesRead = entryStream.Read(buf, 0, bufSize)) > 0) + { + tempStream.Write(buf, 0, bytesRead); + } } } } @@ -605,105 +623,119 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_BadLocalExtra_Read() { - var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.badlocalextra.zip"); + string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.badlocalextra.zip"); - using var za = ZipArchive.Open(zipPath); - var ex = Record.Exception(() => + using (ZipArchive za = ZipArchive.Open(zipPath)) { - var firstEntry = za.Entries.First(x => x.Key == "first.txt"); - var buffer = new byte[4096]; + var ex = Record.Exception(() => + { + var firstEntry = za.Entries.First(x => x.Key == "first.txt"); + var buffer = new byte[4096]; - using var memoryStream = new MemoryStream(); - using var firstStream = firstEntry.OpenEntryStream(); - firstStream.CopyTo(memoryStream); - Assert.Equal(199, memoryStream.Length); - }); + using (var memoryStream = new MemoryStream()) + using (var firstStream = firstEntry.OpenEntryStream()) + { + firstStream.CopyTo(memoryStream); + Assert.Equal(199, memoryStream.Length); + } + }); - Assert.Null(ex); + Assert.Null(ex); + } } [Fact] public void Zip_NoCompression_DataDescriptors_Read() { - var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.datadescriptors.zip"); + string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.datadescriptors.zip"); - using var za = ZipArchive.Open(zipPath); - var firstEntry = za.Entries.First(x => x.Key == "first.txt"); - var buffer = new byte[4096]; - - using (var memoryStream = new MemoryStream()) - using (var firstStream = firstEntry.OpenEntryStream()) + using (ZipArchive za = ZipArchive.Open(zipPath)) { - firstStream.CopyTo(memoryStream); - Assert.Equal(199, memoryStream.Length); - } + var firstEntry = za.Entries.First(x => x.Key == "first.txt"); + var buffer = new byte[4096]; - var len1 = 0; - var buffer1 = new byte[firstEntry.Size + 256]; + using (var memoryStream = new MemoryStream()) + using (var firstStream = firstEntry.OpenEntryStream()) + { + firstStream.CopyTo(memoryStream); + Assert.Equal(199, memoryStream.Length); + } - using (var firstStream = firstEntry.OpenEntryStream()) - { - len1 = firstStream.Read(buffer1, 0, buffer.Length); - } + var len1 = 0; + var buffer1 = new byte[firstEntry.Size + 256]; - Assert.Equal(199, len1); + using (var firstStream = firstEntry.OpenEntryStream()) + { + len1 = firstStream.Read(buffer1, 0, buffer.Length); + } -#if !NETFRAMEWORK - var len2 = 0; - var buffer2 = new byte[firstEntry.Size + 256]; + Assert.Equal(199, len1); - using (var firstStream = firstEntry.OpenEntryStream()) - { - len2 = firstStream.Read(buffer2.AsSpan()); - } - Assert.Equal(len1, len2); - Assert.Equal(buffer1, buffer2); +#if !NETFRAMEWORK && !NETSTANDARD2_0 + var len2 = 0; + var buffer2 = new byte[firstEntry.Size + 256]; + + using (var firstStream = firstEntry.OpenEntryStream()) + { + len2 = firstStream.Read(buffer2.AsSpan()); + } + Assert.Equal(len1, len2); + Assert.Equal(buffer1, buffer2); #endif + } } [Fact] public void Zip_LongComment_Read() { - var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.LongComment.zip"); + string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.LongComment.zip"); - using var za = ZipArchive.Open(zipPath); - var count = za.Entries.Count; - Assert.Equal(1, count); + using (ZipArchive za = ZipArchive.Open(zipPath)) + { + var count = za.Entries.Count; + Assert.Equal(1, count); + } } [Fact] public void Zip_Zip64_CompressedSizeExtraOnly_Read() { - var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.compressedonly.zip"); + string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.compressedonly.zip"); - using var za = ZipArchive.Open(zipPath); - var firstEntry = za.Entries.First(x => x.Key == "test/test.txt"); + using (ZipArchive za = ZipArchive.Open(zipPath)) + { + var firstEntry = za.Entries.First(x => x.Key == "test/test.txt"); - using var memoryStream = new MemoryStream(); - using var firstStream = firstEntry.OpenEntryStream(); - firstStream.CopyTo(memoryStream); - Assert.Equal(15, memoryStream.Length); + using (var memoryStream = new MemoryStream()) + using (var firstStream = firstEntry.OpenEntryStream()) + { + firstStream.CopyTo(memoryStream); + Assert.Equal(15, memoryStream.Length); + } + } } [Fact] public void Zip_Uncompressed_Read_All() { - var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip"); - using var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read); - var archive = ArchiveFactory.Open(stream); - var reader = archive.ExtractAllEntries(); - var entries = 0; - while (reader.MoveToNextEntry()) + string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip"); + using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read)) { - using (var entryStream = reader.OpenEntryStream()) - using (var target = new MemoryStream()) + IArchive archive = ArchiveFactory.Open(stream); + IReader reader = archive.ExtractAllEntries(); + int entries = 0; + while (reader.MoveToNextEntry()) { - entryStream.CopyTo(target); - } + using (var entryStream = reader.OpenEntryStream()) + using (var target = new MemoryStream()) + { + entryStream.CopyTo(target); + } - entries++; + entries++; + } + Assert.Equal(4, entries); } - Assert.Equal(4, entries); } [Fact] @@ -718,17 +750,19 @@ public class ZipArchiveTests : ArchiveTests "DEADBEEF" }; var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip"); - using var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read); - var archive = ArchiveFactory.Open(stream); - var reader = archive.ExtractAllEntries(); - var x = 0; - while (reader.MoveToNextEntry()) + using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read)) { - Assert.Equal(keys[x], reader.Entry.Key); - x++; - } + IArchive archive = ArchiveFactory.Open(stream); + IReader reader = archive.ExtractAllEntries(); + int x = 0; + while (reader.MoveToNextEntry()) + { + Assert.Equal(keys[x], reader.Entry.Key); + x++; + } - Assert.Equal(4, x); + Assert.Equal(4, x); + } } [Fact] @@ -737,7 +771,7 @@ public class ZipArchiveTests : ArchiveTests var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.UnicodePathExtra.zip"); using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read)) { - var archive = ArchiveFactory.Open( + IArchive archive = ArchiveFactory.Open( stream, new ReaderOptions { @@ -747,13 +781,13 @@ public class ZipArchiveTests : ArchiveTests } } ); - var reader = archive.ExtractAllEntries(); + IReader reader = archive.ExtractAllEntries(); reader.MoveToNextEntry(); Assert.Equal("궖귛궖귙귪궖귗귪궖귙_wav.frq", reader.Entry.Key); } using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read)) { - var archive = ArchiveFactory.Open( + IArchive archive = ArchiveFactory.Open( stream, new ReaderOptions { @@ -763,7 +797,7 @@ public class ZipArchiveTests : ArchiveTests } } ); - var reader = archive.ExtractAllEntries(); + IReader reader = archive.ExtractAllEntries(); reader.MoveToNextEntry(); Assert.Equal("きょきゅんきゃんきゅ_wav.frq", reader.Entry.Key); } diff --git a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs index 3296bcb0..e5254c19 100644 --- a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using SharpCompress.Archives; using SharpCompress.Common; using SharpCompress.IO; using SharpCompress.Readers; @@ -71,7 +70,7 @@ public class ZipReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -109,7 +108,7 @@ public class ZipReaderTests : ReaderTests using ( Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Zip.bzip2.pkware.zip")) ) - using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" })) + using (var reader = ZipReader.Open(stream, new ReaderOptions() { Password = "test" })) { while (reader.MoveToNextEntry()) { @@ -118,7 +117,7 @@ public class ZipReaderTests : ReaderTests Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -140,7 +139,7 @@ public class ZipReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -161,7 +160,7 @@ public class ZipReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -177,7 +176,7 @@ public class ZipReaderTests : ReaderTests Path.Combine(TEST_ARCHIVES_PATH, "Zip.lzma.WinzipAES.zip") ) ) - using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" })) + using (var reader = ZipReader.Open(stream, new ReaderOptions() { Password = "test" })) { while (reader.MoveToNextEntry()) { @@ -186,7 +185,7 @@ public class ZipReaderTests : ReaderTests Assert.Equal(CompressionType.Unknown, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -202,7 +201,7 @@ public class ZipReaderTests : ReaderTests Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.WinzipAES.zip") ) ) - using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" })) + using (var reader = ZipReader.Open(stream, new ReaderOptions() { Password = "test" })) { while (reader.MoveToNextEntry()) { @@ -211,7 +210,7 @@ public class ZipReaderTests : ReaderTests Assert.Equal(CompressionType.Unknown, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); } } @@ -224,7 +223,7 @@ public class ZipReaderTests : ReaderTests { var count = 0; using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "zipcrypto.zip"))) - using (var reader = ZipReader.Open(stream, new ReaderOptions { Password = "test" })) + using (var reader = ZipReader.Open(stream, new ReaderOptions() { Password = "test" })) { while (reader.MoveToNextEntry()) { @@ -233,7 +232,7 @@ public class ZipReaderTests : ReaderTests Assert.Equal(CompressionType.None, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } ); count++; } @@ -365,7 +364,7 @@ public class ZipReaderTests : ReaderTests { var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "64bitstream.zip.7z"); using var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read); - var archive = ArchiveFactory.Open(stream); + var archive = Archives.ArchiveFactory.Open(stream); var reader = archive.ExtractAllEntries(); reader.MoveToNextEntry(); var zipReader = ZipReader.Open(reader.OpenEntryStream()); diff --git a/tests/SharpCompress.Test/Zip/ZipWriterTests.cs b/tests/SharpCompress.Test/Zip/ZipWriterTests.cs index 55435b4a..530397bd 100644 --- a/tests/SharpCompress.Test/Zip/ZipWriterTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipWriterTests.cs @@ -1,4 +1,5 @@ using System.Text; + using SharpCompress.Common; using Xunit; diff --git a/tests/SharpCompress.Test/packages.lock.json b/tests/SharpCompress.Test/packages.lock.json deleted file mode 100644 index baeef64f..00000000 --- a/tests/SharpCompress.Test/packages.lock.json +++ /dev/null @@ -1,368 +0,0 @@ -{ - "version": 2, - "dependencies": { - ".NETFramework,Version=v4.6.2": { - "FluentAssertions": { - "type": "Direct", - "requested": "[6.12.0, )", - "resolved": "6.12.0", - "contentHash": "ZXhHT2YwP9lajrwSKbLlFqsmCCvFJMoRSK9t7sImfnCyd0OB3MhgxdoMcVqxbq1iyxD6mD2fiackWmBb7ayiXQ==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.0" - } - }, - "Microsoft.NET.Test.Sdk": { - "type": "Direct", - "requested": "[17.9.0, )", - "resolved": "17.9.0", - "contentHash": "7GUNAUbJYn644jzwLm5BD3a2p9C1dmP8Hr6fDPDxgItQk9hBs1Svdxzz07KQ/UphMSmgza9AbijBJGmw5D658A==", - "dependencies": { - "Microsoft.CodeCoverage": "17.9.0" - } - }, - "Microsoft.NETFramework.ReferenceAssemblies": { - "type": "Direct", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==", - "dependencies": { - "Microsoft.NETFramework.ReferenceAssemblies.net462": "1.0.3" - } - }, - "xunit": { - "type": "Direct", - "requested": "[2.7.1, )", - "resolved": "2.7.1", - "contentHash": "9o050yCLzPvHxbrAkaHnI1j+YfPvRw+/ncvKbTfzIhO4JvQA0rPgoICJxXHMkscfgXmLFwZ8107ehnMUVzE23A==", - "dependencies": { - "xunit.analyzers": "1.12.0", - "xunit.assert": "2.7.1", - "xunit.core": "[2.7.1]" - } - }, - "xunit.runner.visualstudio": { - "type": "Direct", - "requested": "[2.5.8, )", - "resolved": "2.5.8", - "contentHash": "ZJTm71neOfZcUnqdyY0A0Qgcg1162DoOq6+VpCCsOaD9rwCK5alcjOEHeu17sEekzq4qNv3kyelx6lUMsAt/eA==", - "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "17.9.0" - } - }, - "Xunit.SkippableFact": { - "type": "Direct", - "requested": "[1.4.13, )", - "resolved": "1.4.13", - "contentHash": "IyzZNvJEtXGlXrzxDiSbtH5Lyxf4iJdRQADuyjGdDf00LjXRLJwIoezQNFhFGKTMtvk8IIgaSHxW4mAV4O7b8A==", - "dependencies": { - "Validation": "2.4.18", - "xunit.extensibility.execution": "2.4.0" - } - }, - "Microsoft.CodeCoverage": { - "type": "Transitive", - "resolved": "17.9.0", - "contentHash": "RGD37ZSrratfScYXm7M0HjvxMxZyWZL4jm+XgMZbkIY1UPgjUpbNA/t+WTGj/rC/0Hm9A3IrH3ywbKZkOCnoZA==" - }, - "Microsoft.NETFramework.ReferenceAssemblies.net462": { - "type": "Transitive", - "resolved": "1.0.3", - "contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ==" - }, - "Microsoft.TestPlatform.ObjectModel": { - "type": "Transitive", - "resolved": "17.9.0", - "contentHash": "1ilw/8vgmjLyKU+2SKXKXaOqpYFJCQfGqGz+x0cosl981VzjrY74Sv6qAJv+neZMZ9ZMxF3ArN6kotaQ4uvEBw==", - "dependencies": { - "System.Reflection.Metadata": "1.6.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "1.5.0", - "contentHash": "EXKiDFsChZW0RjrZ4FYHu9aW6+P4MCgEDCklsVseRfhoO0F+dXeMSsMRAlVXIo06kGJ/zv+2w1a2uc2+kxxSaQ==" - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==", - "dependencies": { - "System.Collections.Immutable": "1.5.0" - } - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "Validation": { - "type": "Transitive", - "resolved": "2.4.18", - "contentHash": "NfvWJ1QeuZ1FQCkqgXTu1cOkRkbNCfxs4Tat+abXLwom6OXbULVhRGp34BTvVB4XPxj6VIAl7KfLfStXMt/Ehw==" - }, - "xunit.abstractions": { - "type": "Transitive", - "resolved": "2.0.3", - "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" - }, - "xunit.analyzers": { - "type": "Transitive", - "resolved": "1.12.0", - "contentHash": "w23LH3aXade2WXKvXi0oA/uV15fpgUMjsPq1x91iQckzgWApgAiijNHmfFQtqNPm41wfrdbRl7nSJRd0yux/dw==" - }, - "xunit.assert": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "JqvXS4yX+PtJn5BuqoKkYav7I0g4nXcxRbGTomDwVQjFccOdyfYKpuPOHX/DqrPCcL+MIHrGVdP3bveUXlvdnA==" - }, - "xunit.core": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "hcODgS+RXdjmXq0zQzmRbERQgY+bAGGx1bdH3370t/8CTGmIEU2qAc1dQAjIRpARsacR0cj6LLJDUF5BNQNKTQ==", - "dependencies": { - "xunit.extensibility.core": "[2.7.1]", - "xunit.extensibility.execution": "[2.7.1]" - } - }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "yLX4XlBFkvNYCzf+DEzlNk45KsSlu9W93IJHBmtUP96qZ9XyRYDFlwMj6BCcOhDKVNrZxSM8bqu4F/Qud4ehxA==", - "dependencies": { - "xunit.abstractions": "2.0.3" - } - }, - "xunit.extensibility.execution": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "ei3dKF8agj4UKkJ6KkaZ5/Gcif3if6hBsyzegIQJonZDSKZFvb0AyKtyOhDfggBaXVL5iXZExITdRkfjC95yhw==", - "dependencies": { - "xunit.extensibility.core": "[2.7.1]" - } - }, - "sharpcompress": { - "type": "Project", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "[8.0.0, )", - "System.Memory": "[4.5.5, )", - "System.Text.Encoding.CodePages": "[8.0.0, )", - "ZstdSharp.Port": "[0.8.0, )" - } - }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "CentralTransitive", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "System.Memory": { - "type": "CentralTransitive", - "requested": "[4.5.5, )", - "resolved": "4.5.5", - "contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.Text.Encoding.CodePages": { - "type": "CentralTransitive", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "ZstdSharp.Port": { - "type": "CentralTransitive", - "requested": "[0.8.0, )", - "resolved": "0.8.0", - "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "System.Memory": "4.5.5" - } - } - }, - "net8.0": { - "FluentAssertions": { - "type": "Direct", - "requested": "[6.12.0, )", - "resolved": "6.12.0", - "contentHash": "ZXhHT2YwP9lajrwSKbLlFqsmCCvFJMoRSK9t7sImfnCyd0OB3MhgxdoMcVqxbq1iyxD6mD2fiackWmBb7ayiXQ==", - "dependencies": { - "System.Configuration.ConfigurationManager": "4.4.0" - } - }, - "Microsoft.NET.Test.Sdk": { - "type": "Direct", - "requested": "[17.9.0, )", - "resolved": "17.9.0", - "contentHash": "7GUNAUbJYn644jzwLm5BD3a2p9C1dmP8Hr6fDPDxgItQk9hBs1Svdxzz07KQ/UphMSmgza9AbijBJGmw5D658A==", - "dependencies": { - "Microsoft.CodeCoverage": "17.9.0", - "Microsoft.TestPlatform.TestHost": "17.9.0" - } - }, - "Mono.Posix.NETStandard": { - "type": "Direct", - "requested": "[1.0.0, )", - "resolved": "1.0.0", - "contentHash": "vSN/L1uaVwKsiLa95bYu2SGkF0iY3xMblTfxc8alSziPuVfJpj3geVqHGAA75J7cZkMuKpFVikz82Lo6y6LLdA==" - }, - "xunit": { - "type": "Direct", - "requested": "[2.7.1, )", - "resolved": "2.7.1", - "contentHash": "9o050yCLzPvHxbrAkaHnI1j+YfPvRw+/ncvKbTfzIhO4JvQA0rPgoICJxXHMkscfgXmLFwZ8107ehnMUVzE23A==", - "dependencies": { - "xunit.analyzers": "1.12.0", - "xunit.assert": "2.7.1", - "xunit.core": "[2.7.1]" - } - }, - "xunit.runner.visualstudio": { - "type": "Direct", - "requested": "[2.5.8, )", - "resolved": "2.5.8", - "contentHash": "ZJTm71neOfZcUnqdyY0A0Qgcg1162DoOq6+VpCCsOaD9rwCK5alcjOEHeu17sEekzq4qNv3kyelx6lUMsAt/eA==" - }, - "Xunit.SkippableFact": { - "type": "Direct", - "requested": "[1.4.13, )", - "resolved": "1.4.13", - "contentHash": "IyzZNvJEtXGlXrzxDiSbtH5Lyxf4iJdRQADuyjGdDf00LjXRLJwIoezQNFhFGKTMtvk8IIgaSHxW4mAV4O7b8A==", - "dependencies": { - "Validation": "2.4.18", - "xunit.extensibility.execution": "2.4.0" - } - }, - "Microsoft.CodeCoverage": { - "type": "Transitive", - "resolved": "17.9.0", - "contentHash": "RGD37ZSrratfScYXm7M0HjvxMxZyWZL4jm+XgMZbkIY1UPgjUpbNA/t+WTGj/rC/0Hm9A3IrH3ywbKZkOCnoZA==" - }, - "Microsoft.TestPlatform.ObjectModel": { - "type": "Transitive", - "resolved": "17.9.0", - "contentHash": "1ilw/8vgmjLyKU+2SKXKXaOqpYFJCQfGqGz+x0cosl981VzjrY74Sv6qAJv+neZMZ9ZMxF3ArN6kotaQ4uvEBw==", - "dependencies": { - "System.Reflection.Metadata": "1.6.0" - } - }, - "Microsoft.TestPlatform.TestHost": { - "type": "Transitive", - "resolved": "17.9.0", - "contentHash": "Spmg7Wx49Ya3SxBjyeAR+nQpjMTKZwTwpZ7KyeOTIqI/WHNPnBU4HUvl5kuHPQAwGWqMy4FGZja1HvEwvoaDiA==", - "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "17.9.0", - "Newtonsoft.Json": "13.0.1" - } - }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "13.0.1", - "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" - }, - "System.Configuration.ConfigurationManager": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==", - "dependencies": { - "System.Security.Cryptography.ProtectedData": "4.4.0" - } - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" - }, - "System.Security.Cryptography.ProtectedData": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog==" - }, - "Validation": { - "type": "Transitive", - "resolved": "2.4.18", - "contentHash": "NfvWJ1QeuZ1FQCkqgXTu1cOkRkbNCfxs4Tat+abXLwom6OXbULVhRGp34BTvVB4XPxj6VIAl7KfLfStXMt/Ehw==" - }, - "xunit.abstractions": { - "type": "Transitive", - "resolved": "2.0.3", - "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" - }, - "xunit.analyzers": { - "type": "Transitive", - "resolved": "1.12.0", - "contentHash": "w23LH3aXade2WXKvXi0oA/uV15fpgUMjsPq1x91iQckzgWApgAiijNHmfFQtqNPm41wfrdbRl7nSJRd0yux/dw==" - }, - "xunit.assert": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "JqvXS4yX+PtJn5BuqoKkYav7I0g4nXcxRbGTomDwVQjFccOdyfYKpuPOHX/DqrPCcL+MIHrGVdP3bveUXlvdnA==" - }, - "xunit.core": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "hcODgS+RXdjmXq0zQzmRbERQgY+bAGGx1bdH3370t/8CTGmIEU2qAc1dQAjIRpARsacR0cj6LLJDUF5BNQNKTQ==", - "dependencies": { - "xunit.extensibility.core": "[2.7.1]", - "xunit.extensibility.execution": "[2.7.1]" - } - }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "yLX4XlBFkvNYCzf+DEzlNk45KsSlu9W93IJHBmtUP96qZ9XyRYDFlwMj6BCcOhDKVNrZxSM8bqu4F/Qud4ehxA==", - "dependencies": { - "xunit.abstractions": "2.0.3" - } - }, - "xunit.extensibility.execution": { - "type": "Transitive", - "resolved": "2.7.1", - "contentHash": "ei3dKF8agj4UKkJ6KkaZ5/Gcif3if6hBsyzegIQJonZDSKZFvb0AyKtyOhDfggBaXVL5iXZExITdRkfjC95yhw==", - "dependencies": { - "xunit.extensibility.core": "[2.7.1]" - } - }, - "sharpcompress": { - "type": "Project", - "dependencies": { - "ZstdSharp.Port": "[0.8.0, )" - } - }, - "ZstdSharp.Port": { - "type": "CentralTransitive", - "requested": "[0.8.0, )", - "resolved": "0.8.0", - "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==" - } - } - } -} \ No newline at end of file diff --git a/tests/TestArchives/Archives/7Zip.ARM64.7z b/tests/TestArchives/Archives/7Zip.ARM64.7z deleted file mode 100644 index 2e9d6293..00000000 Binary files a/tests/TestArchives/Archives/7Zip.ARM64.7z and /dev/null differ diff --git a/tests/TestArchives/Archives/7Zip.Filters.7z b/tests/TestArchives/Archives/7Zip.Filters.7z index d066779b..ea15f3b2 100644 Binary files a/tests/TestArchives/Archives/7Zip.Filters.7z and b/tests/TestArchives/Archives/7Zip.Filters.7z differ diff --git a/tests/TestArchives/Archives/7Zip.RISCV.7z b/tests/TestArchives/Archives/7Zip.RISCV.7z deleted file mode 100644 index b65c517b..00000000 Binary files a/tests/TestArchives/Archives/7Zip.RISCV.7z and /dev/null differ diff --git a/tests/TestArchives/Archives/7Zip.eos.7z b/tests/TestArchives/Archives/7Zip.eos.7z deleted file mode 100644 index 2fe951ad..00000000 Binary files a/tests/TestArchives/Archives/7Zip.eos.7z and /dev/null differ diff --git a/tests/TestArchives/Archives/Rar.comment.rar b/tests/TestArchives/Archives/Rar.comment.rar deleted file mode 100644 index b0a909c7..00000000 Binary files a/tests/TestArchives/Archives/Rar.comment.rar and /dev/null differ diff --git a/tests/TestArchives/Archives/Rar5.comment.rar b/tests/TestArchives/Archives/Rar5.comment.rar deleted file mode 100644 index d3a65de9..00000000 Binary files a/tests/TestArchives/Archives/Rar5.comment.rar and /dev/null differ diff --git a/tests/TestArchives/Archives/Tar.oldgnu.tar.gz b/tests/TestArchives/Archives/Tar.oldgnu.tar.gz deleted file mode 100644 index fbffb7a2..00000000 Binary files a/tests/TestArchives/Archives/Tar.oldgnu.tar.gz and /dev/null differ diff --git a/tests/TestArchives/Archives/Tar.tar.Z b/tests/TestArchives/Archives/Tar.tar.Z deleted file mode 100644 index 0eb90fb1..00000000 Binary files a/tests/TestArchives/Archives/Tar.tar.Z and /dev/null differ diff --git a/tests/TestArchives/Archives/TarCorrupted.tar b/tests/TestArchives/Archives/TarCorrupted.tar deleted file mode 100644 index a21c4fe5..00000000 Binary files a/tests/TestArchives/Archives/TarCorrupted.tar and /dev/null differ diff --git a/tests/TestArchives/Archives/Zip.shrink.zip b/tests/TestArchives/Archives/Zip.shrink.zip deleted file mode 100644 index 697c7e00..00000000 Binary files a/tests/TestArchives/Archives/Zip.shrink.zip and /dev/null differ