From ed4099eb126afe4e6f05aaf29b84e614ba520c6e Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Fri, 10 Nov 2023 23:36:14 -0600 Subject: [PATCH 0001/1333] Throw ReaderCancelledException on reader cancelled --- .../Common/ReaderCancelledException.cs | 13 +++++++++++++ src/SharpCompress/Readers/AbstractReader.cs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/SharpCompress/Common/ReaderCancelledException.cs diff --git a/src/SharpCompress/Common/ReaderCancelledException.cs b/src/SharpCompress/Common/ReaderCancelledException.cs new file mode 100644 index 00000000..91e59289 --- /dev/null +++ b/src/SharpCompress/Common/ReaderCancelledException.cs @@ -0,0 +1,13 @@ +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/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 7927937f..285f0f84 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -75,7 +75,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti } if (Cancelled) { - throw new InvalidOperationException("Reader has been cancelled."); + throw new ReaderCancelledException("Reader has been cancelled."); } if (entriesForCurrentReadStream is null) { From 43f86bcab820ed3ddb025735bd29af30f17ac11c Mon Sep 17 00:00:00 2001 From: Caelan Sayler Date: Tue, 14 Nov 2023 16:34:58 +0000 Subject: [PATCH 0002/1333] Revert change disabling strong name signing in 92df1ec --- src/SharpCompress/SharpCompress.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index efdd0a47..f2ee3d10 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -9,7 +9,7 @@ net462;netstandard2.0;netstandard2.1;net6.0;net7.0 SharpCompress ../../SharpCompress.snk - False + true SharpCompress rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz https://github.com/adamhathcock/sharpcompress @@ -23,7 +23,7 @@ snupkg true latest - True + true From 7080c2abd0d5d01070f695fc4d828f34cc777551 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 15 Nov 2023 11:05:30 +0000 Subject: [PATCH 0003/1333] Update csharpier and fix formatting --- .config/dotnet-tools.json | 2 +- src/SharpCompress/Archives/ArchiveFactory.cs | 3 ++- src/SharpCompress/Archives/Rar/RarArchive.cs | 6 ++--- .../Archives/SevenZip/SevenZipArchive.cs | 12 ++++++---- .../Common/Rar/Headers/FileHeader.cs | 9 ++++--- src/SharpCompress/Common/Rar/RarVolume.cs | 10 ++++---- .../Common/ReaderCancelledException.cs | 1 - .../Common/Tar/TarReadOnlySubStream.cs | 4 ++-- .../Common/Zip/ZipHeaderFactory.cs | 6 ++--- .../Compressors/Deflate/DeflateManager.cs | 5 ++-- .../Compressors/Deflate/Inflate.cs | 1 - .../Compressors/Deflate/ZlibBaseStream.cs | 2 +- .../Compressors/Deflate64/Deflate64Stream.cs | 2 +- .../Compressors/PPMd/I1/Model.cs | 3 ++- .../Compressors/Rar/UnpackV1/Unpack.cs | 7 +++--- .../Compressors/Rar/UnpackV1/UnpackUtility.cs | 1 - .../FragmentedWindow.unpack50frag_cpp.cs | 2 +- .../Compressors/Rar/UnpackV2017/Unpack.cs | 8 +++---- .../Rar/UnpackV2017/Unpack.rawint_hpp.cs | 5 ++-- .../Rar/UnpackV2017/Unpack.unpack20_cpp.cs | 7 +++--- .../Rar/UnpackV2017/Unpack.unpack50_cpp.cs | 9 ++++--- .../Rar/UnpackV2017/Unpack.unpack_cpp.cs | 9 ++++--- .../UnpackV2017/Unpack.unpackinline_cpp.cs | 3 ++- src/SharpCompress/Factories/GZipFactory.cs | 1 - src/SharpCompress/Factories/TarFactory.cs | 1 - src/SharpCompress/Factories/ZipFactory.cs | 1 - src/SharpCompress/Readers/Tar/TarReader.cs | 2 +- src/SharpCompress/Writers/IWriterFactory.cs | 1 - src/SharpCompress/Writers/WriterFactory.cs | 5 ++-- tests/SharpCompress.Test/ArchiveTests.cs | 8 +++---- .../SharpCompress.Test/Tar/TarArchiveTests.cs | 14 +++++------ .../SharpCompress.Test/Tar/TarReaderTests.cs | 23 +++++++++++------- tests/SharpCompress.Test/TestBase.cs | 8 +++---- .../Xz/Filters/Lzma2Tests.cs | 2 +- tests/SharpCompress.Test/Xz/XZHeaderTests.cs | 2 +- tests/SharpCompress.Test/Xz/XZIndexTests.cs | 4 ++-- tests/SharpCompress.Test/Xz/XZStreamTests.cs | 4 ++-- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 24 +++++++++---------- .../SharpCompress.Test/Zip/ZipWriterTests.cs | 1 - 39 files changed, 111 insertions(+), 107 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index ef84a272..3cf567c5 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "csharpier": { - "version": "0.25.0", + "version": "0.26.1", "commands": [ "dotnet-csharpier" ] diff --git a/src/SharpCompress/Archives/ArchiveFactory.cs b/src/SharpCompress/Archives/ArchiveFactory.cs index cd0952f1..2e859599 100644 --- a/src/SharpCompress/Archives/ArchiveFactory.cs +++ b/src/SharpCompress/Archives/ArchiveFactory.cs @@ -25,7 +25,8 @@ public static class ArchiveFactory public static IWritableArchive Create(ArchiveType type) { - var factory = Factory.Factories + var factory = Factory + .Factories .OfType() .FirstOrDefault(item => item.KnownArchiveType == type); diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 29d733f6..e9c580fe 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -40,9 +40,9 @@ public class RarArchive : AbstractArchive streams[1].Position = 0; SrcStream.Position = 0; - return srcStream.Streams.Select( - a => new StreamRarArchiveVolume(a, ReaderOptions, idx++) - ); + return srcStream + .Streams + .Select(a => new StreamRarArchiveVolume(a, ReaderOptions, idx++)); } else //split mode or single file { diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index 7577b43d..99fe962d 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -236,11 +236,13 @@ public class SevenZipArchive : AbstractArchive x.Type == ExtraDataType.WinZipAes - ); + var data = entryHeader + .Extra + .SingleOrDefault(x => x.Type == ExtraDataType.WinZipAes); if (data != null) { var keySize = (WinzipAesKeySize)data.DataBytes[4]; diff --git a/src/SharpCompress/Compressors/Deflate/DeflateManager.cs b/src/SharpCompress/Compressors/Deflate/DeflateManager.cs index 27ad4018..06cf0005 100644 --- a/src/SharpCompress/Compressors/Deflate/DeflateManager.cs +++ b/src/SharpCompress/Compressors/Deflate/DeflateManager.cs @@ -69,7 +69,6 @@ // ----------------------------------------------------------------------- using System; - using SharpCompress.Algorithms; namespace SharpCompress.Compressors.Deflate; @@ -1959,7 +1958,9 @@ internal sealed partial class DeflateManager // returning Z_STREAM_END instead of Z_BUFF_ERROR. } else if ( - _codec.AvailableBytesIn == 0 && (int)flush <= old_flush && flush != FlushType.Finish + _codec.AvailableBytesIn == 0 + && (int)flush <= old_flush + && flush != FlushType.Finish ) { // workitem 8557 diff --git a/src/SharpCompress/Compressors/Deflate/Inflate.cs b/src/SharpCompress/Compressors/Deflate/Inflate.cs index ebea2805..37227b3d 100644 --- a/src/SharpCompress/Compressors/Deflate/Inflate.cs +++ b/src/SharpCompress/Compressors/Deflate/Inflate.cs @@ -64,7 +64,6 @@ // ----------------------------------------------------------------------- using System; - using SharpCompress.Algorithms; namespace SharpCompress.Compressors.Deflate; diff --git a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs index 19a3c60a..8248e900 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 SharpCompress.Common.Tar.Headers; using System.Text; +using SharpCompress.Common.Tar.Headers; namespace SharpCompress.Compressors.Deflate; diff --git a/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs b/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs index 149f7c92..3eda232c 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; diff --git a/src/SharpCompress/Compressors/PPMd/I1/Model.cs b/src/SharpCompress/Compressors/PPMd/I1/Model.cs index 786cb0e7..9a1d090f 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/Model.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/Model.cs @@ -866,7 +866,8 @@ internal partial class Model ); } else if ( - (currentContext.SummaryFrequency += 4) > 128 + (4 * currentContext.NumberStatistics) + (currentContext.SummaryFrequency += 4) + > 128 + (4 * currentContext.NumberStatistics) ) { Refresh((uint)((currentContext.NumberStatistics + 2) >> 1), true, currentContext); diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs index 2ca62d6b..728d0f85 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs @@ -1269,9 +1269,10 @@ internal sealed partial class Unpack : BitInput, IRarUnpack if (CurSize < DataSize + RarVM.VM_FIXEDGLOBALSIZE) { // StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize); - StackFilter.Program.GlobalData.SetSize( - DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize - ); + StackFilter + .Program + .GlobalData + .SetSize(DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize); } var offset = RarVM.VM_FIXEDGLOBALSIZE; globalData = StackFilter.Program.GlobalData; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs index 09f5ee8f..b501337b 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/UnpackUtility.cs @@ -1,5 +1,4 @@ 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 bfa69829..a9a6f280 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/FragmentedWindow.unpack50frag_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/FragmentedWindow.unpack50frag_cpp.cs @@ -1,5 +1,6 @@ #nullable disable +using System; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -7,7 +8,6 @@ using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif -using System; namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs index 53db46d2..450b4694 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs @@ -1,13 +1,13 @@ -#if !Rar2017_64bit +using System; +using System.IO; +using SharpCompress.Common.Rar.Headers; +#if !Rar2017_64bit using size_t = System.UInt32; #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif -using System; -using System.IO; -using SharpCompress.Common.Rar.Headers; namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs index 03614dde..333c7ae7 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs @@ -1,10 +1,11 @@ -#if !Rar2017_64bit +using uint32 = System.UInt32; +#if !Rar2017_64bit #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif -using uint32 = System.UInt32; + 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 b92af290..a7863588 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs @@ -1,12 +1,13 @@ +using System; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local; #if !Rar2017_64bit #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif -using System; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; -using static SharpCompress.Compressors.Rar.UnpackV2017.Unpack.Unpack20Local; + namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs index f85921bd..82294e27 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs @@ -1,5 +1,9 @@ #nullable disable +using System; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; +using int64 = System.Int64; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -7,11 +11,6 @@ using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif -using int64 = System.Int64; - -using System; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; -using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs index f9a74440..b8d1c78a 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs @@ -1,5 +1,9 @@ #nullable disable +using System; +using SharpCompress.Common; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -8,11 +12,6 @@ using nuint = System.UInt64; using size_t = System.UInt64; #endif -using System; -using SharpCompress.Common; -using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; - namespace SharpCompress.Compressors.Rar.UnpackV2017; internal sealed partial class Unpack : BitInput diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs index 584d0b51..1d53ae5b 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs @@ -1,10 +1,11 @@ +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; #if !Rar2017_64bit #else using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; + namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Factories/GZipFactory.cs b/src/SharpCompress/Factories/GZipFactory.cs index 5e522f5b..be1b4931 100644 --- a/src/SharpCompress/Factories/GZipFactory.cs +++ b/src/SharpCompress/Factories/GZipFactory.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; - using SharpCompress.Archives; using SharpCompress.Archives.GZip; using SharpCompress.Archives.Tar; diff --git a/src/SharpCompress/Factories/TarFactory.cs b/src/SharpCompress/Factories/TarFactory.cs index 61965b86..54c24c02 100644 --- a/src/SharpCompress/Factories/TarFactory.cs +++ b/src/SharpCompress/Factories/TarFactory.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; - using SharpCompress.Archives; using SharpCompress.Archives.Tar; using SharpCompress.Common; diff --git a/src/SharpCompress/Factories/ZipFactory.cs b/src/SharpCompress/Factories/ZipFactory.cs index dca697dc..780d2a9c 100644 --- a/src/SharpCompress/Factories/ZipFactory.cs +++ b/src/SharpCompress/Factories/ZipFactory.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; - using SharpCompress.Archives; using SharpCompress.Archives.Zip; using SharpCompress.Common; diff --git a/src/SharpCompress/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index c9802e46..34f337a6 100644 --- a/src/SharpCompress/Readers/Tar/TarReader.cs +++ b/src/SharpCompress/Readers/Tar/TarReader.cs @@ -8,9 +8,9 @@ using SharpCompress.Common.Tar; using SharpCompress.Compressors; using SharpCompress.Compressors.BZip2; using SharpCompress.Compressors.Deflate; -using SharpCompress.IO; using SharpCompress.Compressors.LZMA; using SharpCompress.Compressors.Xz; +using SharpCompress.IO; namespace SharpCompress.Readers.Tar; diff --git a/src/SharpCompress/Writers/IWriterFactory.cs b/src/SharpCompress/Writers/IWriterFactory.cs index 8e7bc701..094a5553 100644 --- a/src/SharpCompress/Writers/IWriterFactory.cs +++ b/src/SharpCompress/Writers/IWriterFactory.cs @@ -1,5 +1,4 @@ using System.IO; - using SharpCompress.Factories; namespace SharpCompress.Writers; diff --git a/src/SharpCompress/Writers/WriterFactory.cs b/src/SharpCompress/Writers/WriterFactory.cs index fcbf2d68..1f14f6bb 100644 --- a/src/SharpCompress/Writers/WriterFactory.cs +++ b/src/SharpCompress/Writers/WriterFactory.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; - using SharpCompress.Common; namespace SharpCompress.Writers; @@ -10,7 +9,9 @@ public static class WriterFactory { public static IWriter Open(Stream stream, ArchiveType archiveType, WriterOptions writerOptions) { - var factory = Factories.Factory.Factories + var factory = Factories + .Factory + .Factories .OfType() .FirstOrDefault(item => item.KnownArchiveType == archiveType); diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index 08377a0e..33bd0ba7 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -298,10 +298,10 @@ public class ArchiveTests : ReaderTests memory.Position = 0; for (int y = 0; y < 9; y++) - for (int x = 0; x < 256; x++) - { - Assert.Equal(x, memory.ReadByte()); - } + for (int x = 0; x < 256; x++) + { + Assert.Equal(x, memory.ReadByte()); + } Assert.Equal((int)-1, memory.ReadByte()); } diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index dddb32a6..711b14c1 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.Writers; -using Xunit; -using System.Text; using SharpCompress.Readers; -using SharpCompress.Writers.Tar; using SharpCompress.Readers.Tar; +using SharpCompress.Writers; +using SharpCompress.Writers.Tar; +using Xunit; namespace SharpCompress.Test.Tar; @@ -198,9 +198,9 @@ public class TarArchiveTests : ArchiveTests using (var archive = TarArchive.Open(unmodified)) { - var entry = archive.Entries.Single( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ); + var entry = archive + .Entries + .Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)); archive.RemoveEntry(entry); archive.SaveTo(scratchPath, CompressionType.None); } diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index 76629363..218eb43f 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -206,9 +206,11 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_GZip_With_Symlink_Entries() { - var isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( - System.Runtime.InteropServices.OSPlatform.Windows - ); + 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")) ) @@ -251,12 +253,15 @@ public class TarReaderTests : ReaderTests { // 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 - ) - ); + var realTarget = System + .IO + .Path + .GetFullPath( + System + .IO + .Path + .Combine($"{System.IO.Path.GetDirectoryName(path)}", target) + ); Assert.Equal(realTarget, link.GetContents().ToString()); } diff --git a/tests/SharpCompress.Test/TestBase.cs b/tests/SharpCompress.Test/TestBase.cs index 3ad1fe79..b4966c31 100644 --- a/tests/SharpCompress.Test/TestBase.cs +++ b/tests/SharpCompress.Test/TestBase.cs @@ -20,10 +20,10 @@ public class TestBase : IDisposable public TestBase() { - var index = AppDomain.CurrentDomain.BaseDirectory.IndexOf( - "SharpCompress.Test", - StringComparison.OrdinalIgnoreCase - ); + var index = AppDomain + .CurrentDomain + .BaseDirectory + .IndexOf("SharpCompress.Test", StringComparison.OrdinalIgnoreCase); var path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, index); SOLUTION_BASE_PATH = Path.GetDirectoryName(path) ?? throw new ArgumentNullException(); diff --git a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs index 83eed21c..ff5dd467 100644 --- a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs @@ -1,7 +1,7 @@ using System; -using Xunit; using System.IO; using SharpCompress.Compressors.Xz.Filters; +using Xunit; namespace SharpCompress.Test.Xz.Filters; diff --git a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs index 3fa9dc86..e187b47a 100644 --- a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs +++ b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs @@ -1,5 +1,5 @@ -using SharpCompress.Compressors.Xz; using System.IO; +using SharpCompress.Compressors.Xz; using Xunit; namespace SharpCompress.Test.Xz; diff --git a/tests/SharpCompress.Test/Xz/XZIndexTests.cs b/tests/SharpCompress.Test/Xz/XZIndexTests.cs index 9c9d15bf..ccbf81b7 100644 --- a/tests/SharpCompress.Test/Xz/XZIndexTests.cs +++ b/tests/SharpCompress.Test/Xz/XZIndexTests.cs @@ -1,5 +1,5 @@ -using SharpCompress.Compressors.Xz; -using System.IO; +using System.IO; +using SharpCompress.Compressors.Xz; using Xunit; namespace SharpCompress.Test.Xz; diff --git a/tests/SharpCompress.Test/Xz/XZStreamTests.cs b/tests/SharpCompress.Test/Xz/XZStreamTests.cs index 1f50fb40..1b5a9343 100644 --- a/tests/SharpCompress.Test/Xz/XZStreamTests.cs +++ b/tests/SharpCompress.Test/Xz/XZStreamTests.cs @@ -1,5 +1,5 @@ -using SharpCompress.Compressors.Xz; -using System.IO; +using System.IO; +using SharpCompress.Compressors.Xz; using Xunit; namespace SharpCompress.Test.Xz; diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index fde87dc6..080ae318 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -184,9 +184,9 @@ public class ZipArchiveTests : ArchiveTests using (var archive = ZipArchive.Open(unmodified)) { - var entry = archive.Entries.Single( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ); + var entry = archive + .Entries + .Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)); archive.RemoveEntry(entry); WriterOptions writerOptions = new ZipWriterOptions(CompressionType.Deflate); @@ -252,9 +252,9 @@ public class ZipArchiveTests : ArchiveTests ) ); Assert.Null( - ((IArchive)vfs).Entries.FirstOrDefault( - v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ) + ((IArchive)vfs) + .Entries + .FirstOrDefault(v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) ); } } @@ -391,14 +391,14 @@ public class ZipArchiveTests : ArchiveTests { archive.AddAllFromDirectory(SCRATCH_FILES_PATH); archive.RemoveEntry( - archive.Entries.Single( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ) + archive + .Entries + .Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) ); Assert.Null( - archive.Entries.FirstOrDefault( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) - ) + archive + .Entries + .FirstOrDefault(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) ); } Directory.Delete(SCRATCH_FILES_PATH, true); diff --git a/tests/SharpCompress.Test/Zip/ZipWriterTests.cs b/tests/SharpCompress.Test/Zip/ZipWriterTests.cs index 530397bd..55435b4a 100644 --- a/tests/SharpCompress.Test/Zip/ZipWriterTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipWriterTests.cs @@ -1,5 +1,4 @@ using System.Text; - using SharpCompress.Common; using Xunit; From d28a278d632b1442ebdf17ee2c4e22be03f27f43 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 15 Nov 2023 11:10:05 +0000 Subject: [PATCH 0004/1333] Comment out flag to allow formatting --- .../Rar/UnpackV2017/Unpack.unpack_cpp.cs | 42 +++---- .../Compressors/Rar/UnpackV2017/unpack_hpp.cs | 115 +++++++++++------- 2 files changed, 89 insertions(+), 68 deletions(-) diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs index b8d1c78a..38c21c9f 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs @@ -29,12 +29,12 @@ internal sealed partial class Unpack : BitInput Suspended = false; UnpAllBuf = false; UnpSomeRead = false; -#if RarV2017_RAR_SMP - MaxUserThreads = 1; - UnpThreadPool = CreateThreadPool(); - ReadBufMT = null; - UnpThreadData = null; -#endif + /*#if RarV2017_RAR_SMP + MaxUserThreads = 1; + UnpThreadPool = CreateThreadPool(); + ReadBufMT = null; + UnpThreadData = null; + #endif*/ MaxWinSize = 0; MaxWinMask = 0; @@ -198,21 +198,21 @@ internal sealed partial class Unpack : BitInput break; #endif case 50: // RAR 5.0 compression algorithm. -#if RarV2017_RAR_SMP - if (MaxUserThreads > 1) - { - // We do not use the multithreaded unpack routine to repack RAR archives - // in 'suspended' mode, because unlike the single threaded code it can - // write more than one dictionary for same loop pass. So we would need - // larger buffers of unknown size. Also we do not support multithreading - // in fragmented window mode. - if (!Fragmented) - { - Unpack5MT(Solid); - break; - } - } -#endif + /*#if RarV2017_RAR_SMP + if (MaxUserThreads > 1) + { + // We do not use the multithreaded unpack routine to repack RAR archives + // in 'suspended' mode, because unlike the single threaded code it can + // write more than one dictionary for same loop pass. So we would need + // larger buffers of unknown size. Also we do not support multithreading + // in fragmented window mode. + if (!Fragmented) + { + Unpack5MT(Solid); + break; + } + } + #endif*/ Unpack5(Solid); break; #if !Rar2017_NOSTRICT diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs index 18cd9697..4f77fc07 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs @@ -1,3 +1,8 @@ +using System; +using System.Collections.Generic; +using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; +using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; +using int64 = System.Int64; #if !Rar2017_64bit using size_t = System.UInt32; #else @@ -5,12 +10,6 @@ using nint = System.Int64; using nuint = System.UInt64; using size_t = System.UInt64; #endif -using int64 = System.Int64; - -using System.Collections.Generic; -using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; -using static SharpCompress.Compressors.Rar.UnpackV2017.UnpackGlobal; -using System; // TODO: REMOVE THIS... WIP #pragma warning disable 169 @@ -20,8 +19,6 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017; internal static class UnpackGlobal { - - // Maximum allowed number of compressed bits processed in quick mode. public const int MAX_QUICK_DECODE_BITS = 10; @@ -97,11 +94,11 @@ internal struct UnpackBlockHeader internal struct UnpackBlockTables { - public DecodeTable LD; // Decode literals. - public DecodeTable DD; // Decode distances. + public DecodeTable LD; // Decode literals. + public DecodeTable DD; // Decode distances. public DecodeTable LDD; // Decode lower bits of distances. - public DecodeTable RD; // Decode repeating distances. - public DecodeTable BD; // Decode bit lengths in Huffman table. + public DecodeTable RD; // Decode repeating distances. + public DecodeTable BD; // Decode bit lengths in Huffman table. public void Init() { @@ -113,8 +110,7 @@ internal struct UnpackBlockTables } }; - -#if RarV2017_RAR_SMP +/*#if RarV2017_RAR_SMP enum UNP_DEC_TYPE { UNPDT_LITERAL,UNPDT_MATCH,UNPDT_FULLREP,UNPDT_REP,UNPDT_FILTER }; @@ -161,7 +157,7 @@ if (Decoded!=NULL) free(Decoded); } }; -#endif +#endif*/ //struct UnpackFilter @@ -171,12 +167,12 @@ internal class UnpackFilter public uint BlockStart; public uint BlockLength; public byte Channels; + // uint Width; // byte PosR; public bool NextWindow; }; - //struct UnpackFilter30 internal class UnpackFilter30 { @@ -195,15 +191,21 @@ internal class UnpackFilter30 internal class AudioVariables // For RAR 2.0 archives only. { - public int K1, K2, K3, K4, K5; - public int D1, D2, D3, D4; + public int K1, + K2, + K3, + K4, + K5; + public int D1, + D2, + D3, + D4; public int LastDelta; public readonly uint[] Dif = new uint[11]; public uint ByteCount; public int LastChar; }; - // We can use the fragmented dictionary in case heap does not have the single // large enough memory block. It is slower than normal dictionary. internal partial class FragmentedWindow @@ -223,10 +225,8 @@ internal partial class FragmentedWindow //size_t GetBlockSize(size_t StartPos,size_t RequiredSize); }; - internal partial class Unpack { - //void Unpack5(bool Solid); //void Unpack5MT(bool Solid); //bool UnpReadBuf(); @@ -254,16 +254,16 @@ internal partial class Unpack //BitInput Inp; private BitInput Inp => this; // hopefully this gets inlined -#if RarV2017_RAR_SMP -void InitMT(); -bool UnpackLargeBlock(UnpackThreadData &D); -bool ProcessDecoded(UnpackThreadData &D); - -ThreadPool *UnpThreadPool; -UnpackThreadData *UnpThreadData; -uint MaxUserThreads; -byte *ReadBufMT; -#endif + /*#if RarV2017_RAR_SMP + void InitMT(); + bool UnpackLargeBlock(UnpackThreadData &D); + bool ProcessDecoded(UnpackThreadData &D); + + ThreadPool *UnpThreadPool; + UnpackThreadData *UnpThreadData; + uint MaxUserThreads; + byte *ReadBufMT; + #endif*/ private byte[] FilterSrcMemory = Array.Empty(); private byte[] FilterDstMemory = Array.Empty(); @@ -279,7 +279,8 @@ byte *ReadBufMT; // array. In RAR3 last distance is always stored in OldDist[0]. private uint LastDist; - private size_t UnpPtr, WrPtr; + private size_t UnpPtr, + WrPtr; // Top border of read packed data. private int ReadTop; @@ -307,7 +308,6 @@ byte *ReadBufMT; private int64 WrittenFileSize; private bool FileExtracted; - /***************************** Unpack v 1.5 *********************************/ //void Unpack15(bool Solid); //void ShortLZ(); @@ -320,12 +320,29 @@ byte *ReadBufMT; //void CopyString15(uint Distance,uint Length); //uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab); - private readonly ushort[] ChSet = new ushort[256], ChSetA = new ushort[256], ChSetB = new ushort[256], ChSetC = new ushort[256]; - private readonly byte[] NToPl = new byte[256], NToPlB = new byte[256], NToPlC = new byte[256]; - private uint FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3; - private int Buf60, NumHuf, StMode, LCount, FlagsCnt; + private readonly ushort[] ChSet = new ushort[256], + ChSetA = new ushort[256], + ChSetB = new ushort[256], + ChSetC = new ushort[256]; + private readonly byte[] NToPl = new byte[256], + NToPlB = new byte[256], + NToPlC = new byte[256]; + private uint FlagBuf, + AvrPlc, + AvrPlcB, + AvrLn1, + AvrLn2, + AvrLn3; + private int Buf60, + NumHuf, + StMode, + LCount, + FlagsCnt; + + private uint Nhfb, + Nlzb, + MaxDist3; - private uint Nhfb, Nlzb, MaxDist3; /***************************** Unpack v 1.5 *********************************/ /***************************** Unpack v 2.0 *********************************/ @@ -335,9 +352,11 @@ byte *ReadBufMT; private readonly byte[] UnpOldTable20 = new byte[MC20 * 4]; private bool UnpAudioBlock; - private uint UnpChannels, UnpCurChannel; + private uint UnpChannels, + UnpCurChannel; private int UnpChannelDelta; + //void CopyString20(uint Length,uint Distance); //bool ReadTables20(); //void UnpWriteBuf20(); @@ -345,6 +364,7 @@ byte *ReadBufMT; //void ReadLastTables(); //byte DecodeAudio(int Delta); private AudioVariables[] AudV = new AudioVariables[4]; + /***************************** Unpack v 2.0 *********************************/ /***************************** Unpack v 3.0 *********************************/ @@ -363,7 +383,8 @@ byte *ReadBufMT; // because we can have a corrupt archive with one algorithm file // followed by another algorithm file with "solid" flag and we do not // want to reuse tables from one algorithm in another. - private bool TablesRead2, TablesRead5; + private bool TablesRead2, + TablesRead5; // Virtual machine to execute filters code. /*#if !RarV2017_RAR5ONLY @@ -385,13 +406,13 @@ byte *ReadBufMT; // the data block length if lengths are repeating. private readonly List 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; From dc89c8858e31d242b1fa9254ed2f2f04f4420521 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 15 Nov 2023 11:14:39 +0000 Subject: [PATCH 0005/1333] comment out more C++ bits --- .../Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs | 5 +++-- .../Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs | 5 +++-- .../Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs index 333c7ae7..62fb3c9d 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.rawint_hpp.cs @@ -1,10 +1,11 @@ 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*/ 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 a7863588..397fd334 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs @@ -1,12 +1,13 @@ 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*/ namespace SharpCompress.Compressors.Rar.UnpackV2017; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs index 1d53ae5b..b81d75c4 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpackinline_cpp.cs @@ -1,10 +1,11 @@ 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*/ namespace SharpCompress.Compressors.Rar.UnpackV2017; From 67be0cd9d7f14e48eca1d851cb17ee6383357f1f Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 15 Nov 2023 11:32:51 +0000 Subject: [PATCH 0006/1333] Mark for 0.34.2 --- src/SharpCompress/SharpCompress.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index f2ee3d10..2c38668c 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -2,9 +2,9 @@ SharpCompress - Pure C# Decompression/Compression en-US - 0.34.1 - 0.34.1 - 0.34.1 + 0.34.2 + 0.34.2 + 0.34.2 Adam Hathcock net462;netstandard2.0;netstandard2.1;net6.0;net7.0 SharpCompress From ca49176b971f8b48631b2bbb30d02b112b963767 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Mon, 4 Dec 2023 20:19:11 +0100 Subject: [PATCH 0007/1333] Dont crash on reading rar5 comment --- .../Common/Rar/Headers/RarHeaderFactory.cs | 9 ++++++++- src/SharpCompress/Common/Rar/RarVolume.cs | 10 +++++----- tests/SharpCompress.Test/Rar/RarReaderTests.cs | 6 ++++++ tests/TestArchives/Archives/Rar.comment.rar | Bin 0 -> 60074 bytes tests/TestArchives/Archives/Rar5.comment.rar | Bin 0 -> 60112 bytes 5 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 tests/TestArchives/Archives/Rar.comment.rar create mode 100644 tests/TestArchives/Archives/Rar5.comment.rar diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index d371166d..de44e309 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -105,7 +105,14 @@ public class RarHeaderFactory case HeaderCodeV.RAR5_SERVICE_HEADER: { var fh = new FileHeader(header, reader, HeaderType.Service); - SkipData(fh, reader); + if (fh.FileName == "CMT") + { + fh.PackedStream = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize); + } + else + { + SkipData(fh, reader); + } return fh; } diff --git a/src/SharpCompress/Common/Rar/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index 078e3ffe..7be719ec 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -70,11 +70,11 @@ public abstract class RarVolume : Volume var part = CreateFilePart(lastMarkHeader!, fh); var buffer = new byte[fh.CompressedSize]; part.GetCompressedStream().Read(buffer, 0, buffer.Length); - Comment = System - .Text - .Encoding - .UTF8 - .GetString(buffer, 0, buffer.Length - 1); + Comment = System.Text.Encoding.UTF8.GetString( + buffer, + 0, + buffer.Length - 1 + ); } } break; diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index 097b0fc8..1fdbeef9 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -284,6 +284,12 @@ public class RarReaderTests : ReaderTests [Fact] public void Rar_Solid_Reader() => Read("Rar.solid.rar", CompressionType.Rar); + [Fact] + public void Rar_Comment_Reader() => Read("Rar.comment.rar", CompressionType.Rar); + + [Fact] + public void Rar5_Comment_Reader() => Read("Rar5.comment.rar", CompressionType.Rar); + [Fact] public void Rar5_Solid_Reader() => Read("Rar5.solid.rar", CompressionType.Rar); diff --git a/tests/TestArchives/Archives/Rar.comment.rar b/tests/TestArchives/Archives/Rar.comment.rar new file mode 100644 index 0000000000000000000000000000000000000000..b0a909c7ebab737f772c62694f8c3b710403556a GIT binary patch literal 60074 zcmV)EK)}CJVR9iF2LL97yN;u9^S2_P9N0TzZFf%K-@St<%&C)$2nyhkw4QRT0|5TY`*<>>Y}EW?%qbB47iY~TQW8x)+~eIo z55qsE$6#u$JH_1F;ja%H_R3|Z8FWJ^?D#JatAas78ZD1u;b|B05NdCC zA16^re9lmySmKLGz08p^NIzGsYDvS*g8z^ST#6g8!PdCa(nBdj8cf>Q%Au;&H~lYe z|3Pz~qUKI>OhI|ePma7YBxL*i^PK9Fwt2{xr}zDT@b~&aAKc)_`bhzPtK7KJDR}QN zm`?4~yz{opk2;qyEOo{XGr8GYpjsw|B^^QVk?+G^!{{&;IY8 z99SFTwZ@~O&)A?%bhV&}bgd1M0$cg#e%kux{ImM*ph@((7#iBsX}K;R!3TTISYY~1 zCHmZ!f1;6Z+VwT2>G()VAa0cdLDWqGB~GWTT!^x8q!R*mVyW`sZRKMx1%u4LJFlAi z4K6VzWW5XX8-Deb)V!QB_O9n!b7n;w6h0ul+o}YN@!=+2smEF#&!N!0EMDhX z(>oxwEE+whw)D0{e@T9~wK-(>`T9@gv-T(9vr*4S`D89+Lw+IR#*ww!&V0XedXPuS zeK`gCCjKJFq6yAunjv|;uxMv)(r>;7)isPnbka!|$0)tZK!|RgQ_h-b*a9tGkv6ZI zB~#mTj-#AAlcG+`n-I)stlVXyYnpUsM#}rX@wws-HQbyWKfeDT4+pE)V0hH~IK8|> z{r$MO>~DHFcjdGKPBLy>)F8UqJprI>IPUrb#iLe-FYi*#mO3EXBr+t*u5^aZ=JA$f+?U~}gM=g5|M2&Xs6f6S6ZZ1W~^ z3TCWxytgKA5Xa4_JvH!NRh5UI^i4OY+)Ixy>3=Y>GE^&qkjx0wBieVIa-ocHi{);4 zN~_Ktca-1WUC10YZiU(#l0+D4+D$J*`WW`LXouK=x-g>#Euj+Pnl?5CW>gXwvzJN) zAw4!Ry+dc6?^MQix&-*$qM%`c1;b2GS}OHVvnS{qw1h++TBn_4nw>~R+h}Zi4z)YYc8IM)L}G#3LU*> z%14$RC@>o#dY&w&rJ3j!iuf!47(6eGrpm*z0d=8JiSd!N#s*cDgH{8Ua<&S7onAUC zCZAzlYnEQHP$65h_Lb?jvcC^&4Uba6&8%|&u!8aa1tsmWU9o{aX?-$)X!T{@0xqM} zswdq2Hw13fnr?!n#LoTKRKj&-3T`U^6GjO(IT=Fzs`cpT^{jY#4vm6hu&0!KKS0Ad zJ`3ME`UO>#x{X;QycJ74>IY&*@mDuBxgRbILD=$Y#G95L%|m&OPL)qTz9K^PufmzM zeo^Nsqn~Aorh5c<=%O3!LQ~FrIDL5~%23@Dt4npw06N za*8Q-qtBC0P!jk~(YQ)+wd)ccAcR8;ty}B}mq>N$E*yqZ4!s4F-O}T~dgaK-^7_ng zOhp^%?1Sos7HNw?hl3Swkz7!mdy4RFh99{6daQ5`ntCTcSE30YBWSsYtGq@1_J5{VNb#CCpMdriUDGM^o0hb&K27Anr8-oK zX{n{6MSSr@p(c+ZH{sOSTK3S*_8t%F)i%^_cdTKQGbz&y*|T5hrVd{T@mC?Wi+0b7T(s@&vv2K=`Yxy<8#FRn_~~C zD!D$JnVq49T?K|zywFfG>2cNKBiaWw?yAbq92z-1^uHar+V7Q&t6-5f*vkdT$$X-Z zG?hhU&}jUQ`CSu5;CZc89OM_zBT-1U7z)`;1B$V=sz>XTjPtiW%EK22;XwUDO_*W1 z(*96~QoOwi@-0p7C6W!P?g}Ju#NsH#si@lL#s=?Q%aWV}P6u8sSbhor6_dB1ucJz~ z831lY1D(8-SPHS)-5z|6LaZm6xrK>z5yD&HPwr;l#_OvR`}ku*aHc z<;`g#5Kb_VS=gTU?;u}1RBYBQWdsDEU|=jAdTFLxc5Kw^gXU?2#&huSvkB)XKRQL) z3O%3;zl=VPHj>Ya|HTn@Xp({{&?5(+_*bbg>5BtZbeFo=wMwxwYM9IxmtV_h3?Dn^S>vy$6U6SS?#mSXLG_!ERBqr>Nci5!|2fHruV%?hv0snheK|?aLX>We{mPg70k{mhvhH;{SeM=}>U$<>C9} zc~vs=LD%qpE$qM1MTh=(QuBqQs>NlW-b?Lpjc((>Y$5Q-wv(h-mxP-;4Qj7*9$*Lhh6M|bGt`Fu|Cgo8lj*cWq=zfi;`wEq zen@({%WKGvhu~-)i&|)t56!yv&_22VebsHRe2^D&gW`*!7f$&7k%k9N&UriJ7q`>$04oRSg_TzX_$97gzb>l)y$Iu8~^k61k-gwi#&vXEH)K zL9GN-DVW%88Wim0>`ZaRqe72Z5ZY347C?SrYfVs@8IsmDsgh~ejVAAXqM8doOUqC- zp)^!aU8!tN4olU)1e;fL{Lri+UnA!SN-cUFsenaGb7;Y28iDd&DowmS4g`(RQ~HCA z2z@hbvo>5#>ok0ab#8MDDm6ja)lg$S#6ydihvt3T?6SdA2ux%ZZ3|>NMOC7zk{3_h z6$hc^W2^3O>J-la!)lGDi~d4ynpBUdjb& zB2*u=k`9f&;EZi06RhN}n(F@y!vvRK2q=-R!BM0;xY&Ebd$C3O+(d}R6S>_3;}Pu0 zKQEm4>hB+0!NT#tZA(v!+mo63@O zM6DSoNJ#Dx?n(E!1n7VuA>I9A;?O}A;b)maC= z&7CM_#)QtexL*D{|K^)>j*CJ&%>1E^&wZ#g?}$N@+S=qB{R10LA-Oj2Q0vqt*^nsO zTl#_lc)zh4DmK5Thxy8c3-DSKVVkXG5)rl>W2h{}he%ZPfAP|pY!zATPpHb;vLG5o zsk?4tNDIJd4O5>_1rE;zV>pCtozs}qKCS{Br&>IsjT9?G;55)V8H(m#h$H3I#{q<1 zg21m0;Bd&p^Xc1312(e~tIL!)^{7!LN}#}YX{Unnm(#8xMB?66ld;HAcLIDcuWPi} zsd*X@+0tvf$fUuuQKpRVh7E9fl}JN!7cG%#smPEX(= z@*nSwo*8>eAQ#yHy~5Zo7`jO(b*WP`_86(hz-V?bMm&m5*h`N_K#9q0r!SrR$dc9s zLpH7it_aIt#ftD*Yr!u4_8%Z9g4YwwA|XG^xE7s3#a)>$4(hSDE+^>div3%@!GJlx zIU=^tzb+_=)3;q=84z4lKd(&nvi*nl4e3)eWe5Y+{Nd3qujK|Cw|hj{HB`(>)|E3) zSq`PusoV~^*#bKFu0pT+hNHHco3euqN3J=Jp?i5bO>;T9r{Ruf#}HRufrRs z0!y8tp-}|-dX~VXbR?V4+#({2_)Jd9r~`=_Bc~T?j$vKhiojJZQf~9g4}f+~E(xZt zulr+NikT1<&aALcL}gJ)@^!F8z*od*TYK6S?TUdq$c0fsed`th6$CYmzhz#;E|psm zrt8RNoadjm0GF+VN*4>-6HUzzioV=I0}D@*LUk;4a0JqYOThu!*VAS!-2u{xyjB=T zCZPYU*B273t(?vZ|5pMOWDu21VuW8)OO&?U!3N$_%H@Hb?Q=xJ4 zntCYTsv-BmxxBuLNj`kqAoK-ztFDI7N_LiZqw<}@6hD(~$NTv0|9qtaeW81sU1QKJ z0y|Z10>;c_2Rm>>aT%%$vcNP7S0|aPOxRJWs&+oPo;rC7cJh^y5RMWVyU;k=U-G69 zrT|vFSxgoz%$V7l341%t4CAGBv`rs%O7uS^krb#Rr+|eAF%2e`xJf^KTAI$%+u0mZ z&Jk8-P}lP^6gtvD{_qc!OPiU~N|w{2U-+(y(c9MX3MLDko%_nJ5~H`!R5G%s5Whcl z)r>O(ZXwKZ@uh=H4sB+tTKShkuR{R0s9VY0H!;_WAk76#r_sM}qF2&P#JEdi{cs{+ z6C7U9mp{#x=H!v185w_hHci4%aeh{Yi&~klz5_h5b$@CMeXf}r@Z<=&)M$67j{a#d zop2CXUi<+Y7M_^80S5;s4y;L0BT7IzTd218O#^)9xN@OAa$=7lh3D!FJh`qMpn^hU zd59ihe`=eD8mSRt)Qh88+g+Oz{^<)r^xEA>oa~Q2_5EfVHD5zA8IAj;cwI8}{uS zz|WcaVc5uhaj^Bc>ciJQhRw1H%v(Z?ua&2M5V0DdBFvR?iT2xs42n#UbN=`(-l9~+ zGb$VVe3iP=483?smB6q3aLe*J{Z?nVW1UJL5)Ha6zaNq}#wiIY>DMw&EoF6w-ZJPp z|JRsV*Rdm<&6t;(W{KuDn=u|JT1pb`^;yg%F`X69U0O-`?!tE#{4PpH{I6^IE%~kubRB*r!{AgsvW` z>q!Bd%8>-qf+dkor!fGoeSi(xgK~CY+@vO?8BH;%%Gqn7M`FG1ElEBj$gr**i@-o2 zDuj);N_Bwulv|E8Kq%C;t-JIGSkB4>EgdLA=5DKDZWj$ZDwb9c2t{DU^F0F+AtbJl zN!@9pNJkPbX9x>6hqCyKK+NqcZe^evj@Lw6nMsf?VhGz`|JzHnx5ykk&=Hr27<9hSm@LLxsuvVx%*v7h_M$T3{iDLk zzwSt=Xk1fX!G^79*v?Pqott&5S#uO{kvt%;T+ZH=#;R-pzd@83n4@KB#}%M~K5Do$ zb{(M#4vUSsqF2(njsW90!wc$a{HEb${tL*H+z!m1K8iKu>23zp3I~2RfVfKq6w0d7 zKbR%Pj`Lm_U4m&PNNGDtF%Za0kz#95zbuqFh(%I4*^N$-(*{nK%Aq+b58Q7eNUtIv5$lYvyE3D6JWsc5-b)#mw0@m$^D7(p391;Q2GZT%h&G30K%x{afm~xO z%P3e<-WEQEIF5Zl2DfeKV~dMDco#%l0Bee=5JS6boiu=>jZ}6hVj?=jYkS=T5W4pK zJPd1`D3>kGnAxmD;Rk;Y=egP5?M`4+y79?}HFvMu10#L`_a`-BeVyvU`aFo1wW4VV zOBe&{(@TPyzT&qvQnCd)@XTniw;fr&&V-&A>Jh;s)dp2)TT5}SO!EV|%=`Ifu(7A- z*5S+1VvLLOk`{v8Gn5Y5TqPh@V<}*)CWP$ZE|7$-&`JW(K@iUvoTL z18HucM^pq3+=K(SGseFN4O#Jmv+CeILA$#S)DUBDqr>%buWn+v>8~kB+fLA&%T*Du z)>2|u8n6`HHT%eTd{#Byr${Te1-%+MM{dUjqFwH#6G!9?K8 zXd6=Zc`6J=`)J^lke&yt&R8Xi7Xyp?P%IkYou|(L4_W9hCe02(N8u}48er@=$F4$o zd>Ui$=?qZ87Bdx6D^AS?2VO-W%NNw;!G;S^JrJ}M#4YE2?7?<1fK89A#hpd9Gm?eL?P5boF7x3pQimfTL(mf1Xh*Dt?_TP4>VqDabVvqreCQZ{uOn#HQ^oa*Fo=_o`>K-#D^@vYFIl0s@xmnNlLpAy`2 zs0Qad}n<2uyclLLisTb9^3d2VsgC* zA8q7(1FN`z8aH}g@R0B@mCn*X4v`~I@0o7}fxUnQ2Wr7Fpt!vbuk;9~sloTu2 ziY}EGBQX{R92&n~NhYLcW`*VuY?|eFP0XPN8#_EPE#^`j2tZB|W#qRR#QI9ynSh$` z4uer$mIP3ZpG2$0he;zSHd#}9<`pL9C`4}Z;)XSk#4<46FR;GG2ijYuV~z6j5Bb9M zXfBpz4R944xCaYCU#jE3f@oULBW_ugpAe01Or}m4!&KIA6Eb%ZS~;)+(L%;~ zXj!GI9oZJie@AC5f_IT)lzab6+$DBWY7pF0ZfxBEe z#>oN^2HQp4MEI!aTqeW0#9WOaok&zI+FQD@8OG|dvE&#KR)#5qbIZl=#*d^>$`Rt# z&|<-%(PIG{M>#g?ia~#I>BKsM^ODaDeU~bnM2xd-%0jgZ z_BbI)h)>(L4tDFixzgZKYp2IIk9W@P@Ku>e#|%@EXd)YMNQUoQNqAwWZ_3r;6t-jF zD$=>o4_6%Z;Nhd1XJN5OJG1<|FJaDN>|CU}uJ>Mm1Qfl%?Y8$;EA??#Fpb*#Ph$vf zW4(^7ijXdP#_|s0^hO1+3EuDPOpc@u5erElj4!^1fQr+G6&HTzdIi5^KL=^Vs|mYK zjtB;Y*mT5s!V7@7rk%|1IitHU2SRtAg2W=+&|QN|e)Rcp1pq7$yLZUU094JWRbmc_ zcfQsbrWu5W&rA{<&9r7A|1b$j3=|5$OK`?33*+MG-Tu+JfSE4aXo`6bO*`+WqnVt! z?(uuGXh#F!3$L{W9)A==TU#y7YJe?;&}>vz^x_ZhcK?hSh1~dghqgfKJZMyv_{ihvnb~AuBQHkBE)Go@7yFSLiKa zEDnf5Zles z&J`x9CAi!^7+`7{fuVA4S;ed?ZH<|i{2_0DNp4@EbTphqKfSg5OOJc7guQ^}m5E-K zFBl^#w-Ik(L5`ZcrzPbDOV|h4xS?`uW>$N_xWsf#=e?Z=(r#5t_;^O3Tll-7BROt^+GHSAr zSNACk{@O885YfYjU<+cY&k<1Q?~(Zsph|h8QwDct846Ma*F&PA1q6K$6y47jAA@2Pg01mzQ0G@LEocK5J$=+cXFqwcJI;8Lw z{Bm&>==%<*c`XCI?5IZ$_r-ToCypBG(lqSWHXWg}=3^aTgHV!i@iUGmkV`Q;cG~GSR-Y3vfWH2%fLi9b&W$C!F^9Dm}`kT6MeASzhljWCUq$0vv1KuMRblOW)z#qW4{j9$V7*(Iv_w zinLhoEo(}FbZS>`%^M&OeGD!2t7a%x9}~k=QYwe^v<4Zxj8Z_SW~UCDHP6ypNwEdd zp0WU6Yu)aGgTAMlirL06*psno1j$#Hu2 zTZjy){AMauTywN0umCSbU(SUu;|qraxqrrBh%E3W zOTXQA5E>~Nez*T1m|Y`8;@k%y!xZqyKp;Kc{a^21K_)3HX;Nnee^a9M?)>0F%14=i ze_ex(2OKjeGUg`eIz^5PT?}N6h@uU5J%k8}?V@EICA=Wu^S>NVwnO24(PTq}sdal$ z0Sv6F*SV{|!>>=uB{ks9hR_n&KsBLDJ`&Io^mf zEk4$*62DT>i3K*6T@_Qe?5=8~K~*Hu{gmqZizqyxGi$660tyN%4%)Yg*i25W zKUI!stpwR#3$kgRh&rr!a_WPl3AGzzk77oU3!)hjJp5SUol`V#3?vLH3?O|=wcJ+XKb0o>0=Jey`WwiDAEg9s^$>_vR4pt ziHuC{AgnK?2~NeTC-+I-hVe9vt&hxOm5yVIZTqpbFZ>dqzL0}N%uVNJC3>_q{S{jK z_dyVdsGbNreu!z%i>>b?4>f78A|!r05p7ZfmkRZFLAKM1VO{$Qh>Pru(t*SLq1mO5 zIyMfWrCojJ*ADGOz#<%Y0JE)^NQkExq9Nwe<0&1d0VB$k?pOt<0r^BJwaF@YNz=Hi z=$LfUcxOI#UdjVN&*p$kgl?Y3bGM0kp=DOI_}bdHsYeq1qaFr9joywoD4wH2aieR2 zegu;54h%SB#o%{N3+ENWW*3qo#wtxAflt9A|Ln(6&}~G@B{iCmzuzQW<0uJl401th^HzEleYL#SEaa8{`PBW}$EM zMAf^FeBiUmv5J(@Zv~n_eW7E1y*Gwj=>(s-DRjhFuf!0RSG76H(0n1rRqe#|Ol6pX zxVTvoG;cqXp~^N2-oXvHJ$I%JuV2=lQB#4&nDho*tER^A%vd6)QXQ~s8@-q+hSlqR zLqJ)MM~nPY?i07%fYmH+q&=*a|cLb<| z;;VILvv~)*^=HNerH>5{n%TD>8oICiy(w`5*HHPL)0X^vZ$QLGpu`YWh2rIPvK*y% z5M16YWq!NE-vNc`T$eJ&7T1vuKa?%HYbrE755V?E?AWscO6SoUM;C_FEpc|OUDNll z@_WFtDD#d?y3}KZ zloe5VgYTc=CU_}<&j1dbXm}YK|AZYkA?}qOk~-vdNX{drMG4OroaS@J=Lc74yGNdn zJsZ?-QRt)5M*SP~a1p?CYoYViuT|f}F)v2=c_Hu2M$~3!R&6%CYkmlmxfyBSoGJp3 zBx69uLko0wZj|*?7z!Wx5?VXtg&qJ}>~zF^FWv{2lQdi34+HvSnKC&kqCkdlWx`&- zJ=UU?s{1ZdSF6>4<5(kaJePH-#;3=^KZ6eb#Xr0ZfKLY?4gi?=SMWiv`w3jT!|#Ee zSux+Sf_s7QoR2*oiZ}?G6xpZ19(e?01FU*6=&(hCE74wx)K;Rg6^NRNxjYw4&&r3) zxO<;RWv0Ts9l*87U^#p8cn6W2$zi*E+HBFc|NE)^)Y&*)>4_Z4vQEf)-h|wMNM|>N z?%hq3+Pa%3B`f}*bn^q>l#h^)j*kHv^lFj9_=PbqM)+Of9P~__!u&4&beUf|PHm?N z0vW;I1i!h2TBC)}znv$&-_DckC_7*sBru5-Wf9S%rABcUsNsA>%>6ig@34y$e2LsI ziljI^LXFz}o8rROjOfOW*$l9UAP!AwF7F2`J&_C*i)H=t83?mL;8C}G-o&u@bJNMj ztjx>?tizX(S$paag zX12X{@q`Vgf0AC&z%&ih|oq_Ei=sQ4fTy-wjeQQz_MY^avgunG&U%&~4 zE!oOCEqlJcnMlLu8i&U7LYW|i`~`)Igx&=ED~gDOE*eoaEPZ+{c}%PbFn{Z;2Se}u zrLsc+mS~;NI}DwEiyT3AN@v< zjex@lcd`h!?U#>ngur;KqvNB5Q>S+Na^Jz2R83mq{j9{w@Q1{DQU({nIoW(?ZgBv{ z)uoT_!OY6g0SP~coOW>DoWNy!QI|p~GF`{OYa+*!ss6i0+A$?135rTa z%*J9|mayjRPhK|Dl90*9E!wDupjA}IV-4;Nc#Uc^xoV6iN5R$zmVjwJP?wP+BKuOo{v8fdSD?WpDeMF#!Y#7iu+C(RZL zSX~yC*ufV{Q2AHNqh;#V<{fDD5`3&f{x`uiV1dlu=`?M=^Q^{2{3a1cDWpq$V>I=+W@U>$I~cD$~)A z4oZ>H(Mp~>bZ_c3!PQWvjFw#pIF80pXwQozp)w*Fe!%ICds5axd}nKW#EI;6<*G8b zg(Oxub635?xjT{pyOM-HkRii{`RmuB({mV>i;oCnZ}8WEoYCuV*D4_*;FmfV=6Twr86 z$34htKyv*nW&0E7ESf53Tk&=$XlwarXcu|>yYCL!*gN8K*Q$dch^r;`Ihp2Vm-~@< z$S+~Fy_u83Af9IOY_l;Xro(_DYDK$6Ap|ZYLDi)9!ddZEjEQ)Ly@S|`nbPkhOLJfgWO=OS-gJbLl)krAet=;P)&&uaTT(jgN~&Bgb)Cy z?_5CnhsFsN-Vi&w#o@e*+W9ejyFK#(4{fRkLS`BhTrl)BDNXAv1spPs+cdqGyLR zqrpyRBy?|mq#d$&c8eWMgI|f=ll<4T2F6H$EC7TUJg9arQAze#q%sR%M)xs(Iayo0 zq8(sbs4||n9I-n~FW4b+bYnSmyZFcA`cCDVRV6p(={{4EJZT2O2R$a|OkA!S#siyn9f}MQHQ8tp&U%W*zeOLfu2xLvND6r3N>LC=ZWE zH=>o;P0Gra9YVq;y8HpyF`Ze`W?1lxtUNUKl1s7UfJJ`hZUAag`l|*z4%yP(WPgP@0fwhsU(W1PJgpW4hWL zKe*s9J)?=AI5zf`AD?Z3gco(<&4}#WsNpNvbF_)ZX7YzHU3$RWFEjBGGG26OL3)~* z;D=>b!W(%(3n7=<8YR{N#}tQVF0XcBPn2?&gYfo-z8TQ`X%Y_+wP&5>4Kh8?m+NX>gn0Jm194N#y2IIf|%Y_e6{h$c|+;uRAwWs~r}g zF)BNR@}CI}`YFN`Xq;y~qHzV2h$~Yv5d`@;9wANi=O`ivXbB--%y~(f9GpK6xUsmh zQ1z7F@@l*DVk`me^go97J0$V}UiIGgjI*VCf;x*G?9=4v+pOx|oIkOK^4@HjIfKta ziMX8o(koNmnGK3-`ZlfAr3TSW@QK1-=if70;OOW`bGJ%tm@3o3A%#|Gpl@`3X;@TV z%107DX^{87{UIJ(@$w#u;@Bq-ONd=W`cxu2rAPMBiACA>TVQVNXE^Nbv$g%y)Is^M zoXZg_J$P*rxZ)cAkL95B7q5fY+VZa1+lHjRBBb`2;xxb{yqXGy+w+Jc;ce1l1jKjC zA?lIwh+8C7L(Ty6yw8to>M@D?8M%(^aLau8nJH+x21;x(@F zlx0WPlyCWJEi0w`3ZDk-`ALoQ4d>26enAaDbEvbcy#0KRwgZ^q(h1fFVyUCvP;O{E z>=U2Eq;eEa_B28_VqMJTH+_RXRkfqM-pybhw==i3K=g!rDWhtWDoe2i`bOVU;b)gv zcY^jkV)bXy%vLZyggGz=>QK^1hCWzdF0bpwbYz3EDd@sHUBvG_Q@^{rE}*JKH%J6a z(=e30jx>>vOU)%>o>2e+QSo}a*Hf;_=1WrEDEDr=g6RE2m=0z#e{-JEc6u3jRZPCA zz83Wfuxs+c@|1&pKC+bw=>!?Ab-pzN24?=VuzS3ad)$loeqOy!9`14N1^C7wf8H0n zin=Zm0eI{a_*_SlFcHrKs20@`YJfmv9r`zaq_}S=1t4u}xVK?>xCQsE3|u-e3|qNg z_*pDi{UbPg6va4o?o3S(QXz}a-FXxlB^BaV6EcFURBcYr!>VJ{M7*WaBOpShFQg&6 z+tr#o(nbAFv6pvMHp;Ny3%d>%cCCH2*!Ukk5)oCQ#z*Yn-s0BvJ1UG>Kh;^vUXi@l z3?6jyX1s)(O_z@4EEB1)>g*?tt_F|yVC1aK%U0>Dj?{a?4$xm zkI+RK!c;xjgkK5!#iI}z;##~`RIE>m11n%oD@iD9)*(`{$^7Ih*Rq3g+VIV)vL%-G z8fFiH8K(#$ccM})Y#&SGM9_F9;menKoD5xe_yX+@5_o2SP$NV6!&cGWfa&Mqa+F9= zUZ=~s#@V-n`fE&ZapUhO4K5rwt7069IRGhZFhRs7<%$%eNLBZqp zCAqG4e&EFA)!;dx<{=y_jfy$Q$r3KYC)1gcoCu)KUrx^g=63*E9-A3K2SNgK%^6XQ z1|d!+?cM+riAU^pMzBvFn_x=Y{;y!jG`gL=O~=YWg5vYmf{2m8`#kS4%=QK&&a^GP zJ9lU{?RR)qhWzIq5HRmQUEwemOCKLG2t)Gthp={4-{%2KMye}zO9v0lxZed=FI~PQ z#$w=Db4A@5YgG-d!~Ceo5rbxd57$?o1_)E56#XI((P1BcGPUbnRWDjT4(g?cP6JSa z2%hpiHiJ?KG^q#Y22V#CXFN5D==V89pkOLg(cjxGzaV@&GxMAq_f11v;Ks(;y}QC=uF%AiV54%?`kgMZ*=9$)bqi z@FHA%uo`6X4Y4>-(8EuF=6!YL%_!0tVZxdhwDIM#I>m!6YcD#rciFWY8^Yt4&eT{~ zM2IRvgw=Nz9J;9FG#+VCVUxJs4Aow^A|8ONV6Q1%? zg%A1Jgxm)_uIY;OpA+ar30hDcog!cH7O8dj#PIX2VGU<0Im1GCGYx3DFEWZ64_qmV zvk4^mUT|1LHM|mdMq2>a%KSv-p|&M{Vm)xgM%750Ez2(ecZb3X!zG6?4FDQxk$EPo z;c?T;)Ms%C9qf8WVH~nsLR60 zYg4bs;bG}XoS^WeRUO>8mwI-J9*kbXTGmeJ<@$q`Y7fh_Z_#+O5dRMqqkQ)<A2g_Cu9m`s&$WPaX z)%a?lLTP#*-cRY`&iet!69KKaz_|`WA5#Ny#xxPHQs%D#*8x=E6E1dr7c>{Jjmw7j z_9(wU!i3qa`^`qz6|H6KZvqGMK|q!C$GQ>l9VoW_xg_cm#PIe@+TF+lhsHU_wj&$Ys|ha zLC5zr!3MXh`$&p zxU1)wd|bs^)z$7x=WjY&(}ofBQr<3I06LSmu5*rd zS$qef8NcF2%u(1|=ln#bj^l@F6Fk64t8aC3x%I!Ke)p(8^>T`Z@3fscYDyW%wu=kg zrDdA;9#x3hiGl}zQhseYQ|s$@^I&A$cjomAGUI#?qHafGuAOR47Hbr*$?X#rJrK+l zJdLfkyNE*Qp%QmawOMX`3#s-LEeqfg&a5EzI78V)h!*i%hio9MHK#GcsgDP1V$%t^ z(g|6O#cpAcv8brR$ZG3L;ecSM-2Q3DyLt*P2-T!JgGWWX23tG;ps4r5sr&Rjwp_sm z%oA9W4?XAdeINo<<(z#`eo4=2)>v~2Cv0g( zHh!ghl|iH|8V)>Kb-=!kbEPR?q7U2Rgg(Cl15n^_M-7mw;LbxLJCqZer+zy0VLCaL zI-i`4_E5!V=8*dJ;Yb<*p8>4t4yR=?8|@uehpBB_R~luA zOr;m8gB*`v`$e+GlmvWTRgB}$pO6TSb*qN9(SKCYEPW!Cp*`u6J_x?#7}O43M!Af0 zs>@(JRxEiw^L405E+FtN^;-;{NRX<1FZ>k^OKA*%fII$|;jrOu1O=Oledh zH3E*hyewoFtgVlgbvWgqE0agMK~aXe9mOVBCvBW3l;Lu~Qo1smab|-U5?tEU>JGGZ z$>rAqZfBRB+BXdvj75rJm5@c8@)V(38kskX+T>U8Gl$JM)vS96S2c#ci7kYXE+2q- zQH9ws``DKIb8S||i@=_DGz{YShXVG;a8Sz3dVp{$v#BfkG7Zu?pgc)Mv z_E_1cWyx9k+Pt|vT~2UkJrw3%XbJ)H^GdHNaud+<^ncvcuR{ZA@$ zrhX67{_{=;5E|Py9Tz(8gXAOd=uciNN2!5rl&~!%9N&<$pe6yGd%`>5eT{X6fZucQ z296y78Wvi}Nd!>lH96$V{y`9KX~RD`Q{;&`_gc7ROzT0Yw~xG#EZpQcFOk$p5^ zoUJUJ;yEi<9i6{aPQae6Nu&eimZYbJMs}`z;)w#~hC!T5BIYn{$Rk{iGdW*9`7^5} z!({nenaKPC!Uq;m=~L0Z92=8f@_e#WVm~9rXor9pwL$)F%Pd99I+n*Zr&7ZB9z?m#1VmEU=qggl zLoJPE`=B4Auf99ybhwx?*L1jwSywPH9u4l+-)@|XjXXh^-H(-uol}c}MMhXbKk(f> z?5!sRV9>t>)$QLB+|k>(qZvHD9FS>!n3X!A#jLKHWrF&`QT|K*hTA zDeZiqMDx2B4$V6?h({c@e6bk#W|{yTKDfUotRu?|wyoKOG*u60mZ4}xTxsaPXBw00qtT6Pu$Tp zb+70y^W!kbhjUkNYrhveDk2MMzR~PeD8N5Tj z-mr!%x~;ZjV`5QHVE#7M8GI%6H@R41=lgiY<=in~3cWCnYT{+zC;zhn*@pikxedT0 z<;+XF#WC=BLsOpmI%eF<0m1GCYMbDHMGYl>2-}Vm&0hO97Pf*CbS}Ll<{NN_t)%$k zr?Y9Q4wiH3LK%C>9RtT@Z1qXZM9~b$al&Ey!dZb9!`rNfww?^`Y7aU6N;)JzctZSP z(zq6MgI!miA7{jV?dE>UDtgB$r_>#w1Rc<)PJ6JwSWf^x9){r*ACp7R0WCT-GI&MBA zYCB$+?*!pFWS=N*1R2n}w!2ua*m^G^>bU+&!s4A3(ENc~iU2AGNtEr!fm%0&)^K=|jSIRa<8L4udTwzg zp@%7rP>NDF!vaQBn2Egnj~>0VXqo^pXjrr3np{|98q?oTc-%a-w%y+BQQD}5pwHXA z(lqzs%%vD_76%`!zVjR6_!p2fe1*o-s-yAA)Em@wxheMXgTO^^nRnC+;Ymo{Tffhz z#R?<+49Q6^ql`D|fZ1 zEPM&p7Gp{rES%|gWinf7X^JmDf}A&BT%txV;JF3B;}o+@ISJVk{SJ!8VY1@J1?k8j z5CHkizl;%lflQErQg2@3)m)APwV=;ojn&0SA8@-{nRO!9!omTIGK35zKe%?@i6cG4 z>=x>=hT(lE8nsS|GL%eG0k#9oWzsuEeLEa!%;0)KEdHn;gP(9sy~s)3zK*z=mgbbQ3wQXP=TW{n-zvvD$O1kNXPbw-icE}vhRk9U z+NR846u%e<|4d_1++J=+rn*I7tR06gjn{hg=<3;X4p_|(hf!gCe?U7nhs4Q>(ILc9 z6P9>{;~q(~-wTC2)>h~DZl`&{mR{0~sG9U5qo4Qp)rxdZ$uorR|P zL@kj*c0dI&HhUnL$f27=>UW=d8X9=!5ZT9*FioONGX*gv72Q-fskHXZ@dcwj; z3OOq=<>tpDbjsSVJn4flbghTk9$sf+MZ{aEKcw?0;fRW|u=#0T%_J9cp`Kt`)QQ^p zd_Wl(Hlg9K-DRMJLAztM+GM$DM-thRdPK}LNPdn>mXaNLr-rt_Y?x8cv&f;{H^N3VL&9MK}2kNkRMPfxus(A7UbxJT}g>s5HNG0~8q zZK)sVAOu|n?dKE!cuR+RGk z`0n2kPl5E@JN{n4*SN{`S-T#f~i6pP|KMeeXyUE-sjA+6w%Ga$tn#AQ+bo-r33 zhs2MTkKISoM#UZSJ~}Ot*dsWO$??ts{ZMtX!amYJg&)q3rjI2b zl%$Np7N`CEFsX3DpL5z_Dv3mU-qjx1I{t5-`F5SMHKa4LWL_x?V4KxG9e{tH0QsPo zeS&^Jo=uO_VN2`>@R2y(yXF5lB&~@O-56PC?v4+|*i%$gZt4ShqBsdXcB@%MM4ZU? z8AYho>B(~^HIx%i%Ldxs;#Wm4iaS;*7q<~#W+naiKHM$6&hLA;$W{mN>3H>i;GF7Cr6+EXj-2|43*K%j4n6>2P7I^@ zr#3zYEZoONC=a9gq5jqaskg~F^U`2?LU3;uF#orh$=`k5JunU+MyGZi^t8!m;A8^S zG-(Y0kU^%UDVfJOse$(--@y;t=N#C76;HX{_#aEF5Bak$rBFWv76I6F7@!8D!P{pq%C(S0^$mad?SDNsrJ)g(vqvExnzA2p z_TnSqKCb+nc_i(2P2W5J6XlqE9T@#=n4CwNy0pdI3;cg^fGX|yq4_hV7vH5p?KdPG=+ZWV39wG+Vo8(7zN3+HU;FGt>CHQ3R z;*x~P-M;PS5Pbi>KyJOsI~H#UyvI26eu@v2sAkVqgMTN0o^O6tlj{f3|4CN`+rhrH zg9Lidul46%$@sZNK+>7B>M8>zSD}N|U?2D@)l+S^pC|~(Db9!dbl;Ufo-%K9yQ!w1+it0MG{#$`P9sfDXU7oNZ2=R> zbwD}GQ@=f6{)em!Pm&!C5M{p(e98k7VJ(t>TwLPd7e=RfNkA`kGrHYe?y4Jj|C*{J zw$%qg4xn5&n>wR&3XsiA?*X&%fX}RCPd$Khq1co#l`t!+2aN^mfl3t>C%6)(;-p;RBsc}|8>hF6TqOy;JWerMty z+86avzsCXp=!|Wk02zs?$~mT*hjbm%mfEe`%m+{%~U* z2L8+F(*cFuDN$>v)zDBBS?!K=Gkd=W!2=44_jN=TstXTlF!cOZaXfT};B6XBbky#y3J_4iLfNOYTY5dXR zQ7uifL%|J1fTzq0!H zI1ldl_MyBngvJEx9X8u?AF{6v*0kafhT4APby9F{pVLyJ5UDpbrQ6M=EJ_$)!(Z)j zg1%%|jw#0zsW*@mL#uqEOgr{a<@VIu>THo7UD)LWh207I8*EzzJYq%i)MU4f!*=Vz zryGP_$oqG6EOAnlr{sCbnr3h}!K%`-Xw)b10iBUaJkr3tU zw_;y~Y-CVvx6p0HTiwMe&4fI$Ldy>49>?77{)`p;5Q}8fY*0!nN-cEl2FXZrpfw0t zp&F#^l96mGaf}Ddo;XA9>FMdIV+(KYJQMsCKkE-}_UwEF%22j*3ePB^EaDUBLF7QBq)s^rD7Z}zf4C;q;!xnu{ z+^78A+uKwpWry>_hu3Z1O;M$VOEmj(bNjOXr>UDa+%}>AMLTU$ANC7ztJyGpzCb}* zp3`1NojPBje%t^uGy8Ceu$=B0=jqejFJka}Q|hZB`XTk^b*;lZh!h%^0r(j@v> z6rVUE^KEwl8s(aMtN1z>c}_9)qDZY{Nmh0;B8K2kY!cgV-0%@Mwl?~LL% zU}pOF#|aq(Yf;}LPLBN^{U4}{L~s$+BJ~|AJ>ONDn%#>s`xU>;J%#Cln<>?v#wLGhNU}%Yt$3{avBtV>Yes#5&lw^f8s~~ zY7_j0DgC5l@`;$c^=4$fDu^_wgdTAJf8p=^Jo=OWhxn(~&+sE%_pa~=+16H)I6xn5 zY3R`(9LIPW=El?Cz{^4EkeQ#}wcfI%5UH#{tbG&n& zW1pmGtxe5D%tXxQBStY*{FKCIVqzvDb2-P)krkazYw(;_F{=H4On=isN;y5{uf8p; zN@pL?1Q7rv7#aS#n2q_QqT`Nyy`L^`%kx&O`Xu86U(hB$KMO_&KVA0y67Qt- zz$t%sZ~el6e13kAe2e?YCPLyNq9h?AfbBW8x4NmT0RBw)`}5@t|9A)V$~k}uI3Mi% zZx(Gz|B>DPZ%P;b9F4w_pXPw_{Q81EviYE+e$Vd@e6BxK2dDfo zAO0N}^#8;tXVd-X4-d^6|0DizcysA1h<=R7_tQqdHXlj-e477;0iV{!zC*tu|B(mC zhvofC{hp}k017{>|JsQE?VB6_vsiyNlkf0UQ-8^Sl@MetMgJ>nrSlAjzuifftY`WW z=YU<$)%E|(lAZoX9r?X)`%m@$lk#1U*31v;?s{Fe?zwIjm z7H%tk*01|mz_nu^@`C+QpVj>7n5OER*Z81DzbaMf82z`Y^v|Ry`Jg5TfPc{peJ}dHzh4EZpU?lM5dUhO zFZ|%2${U*gA8Y2ee1*EYZ)at5|F7AbnSY4L`%{nSGe_VX|5i4*0^-lg`}6_+4zK%% z(wdY%^&UU$5!{67eOnY=t)Sze0;mCZ>Bs{(B{BA&*f5Gep75?9KmG#h{#c@2`>@8s zWAOD8tQpVkS>%dr6n0UQFr4)DG9$iQuY3Nd~yE;9@O{`%?QlJxtMJ6}@^A!+e> zah5gvTGkp-tu7hp$~>UKwdba0Qdgk{ZFt@AHLL~@;u1-q5t~J{Xb%} z^F)k}4~&1BmmdNDa>xJvk}>{w{^9EXT>#*CCN)Z*wZQCzTpOxuT4f1t^|^a(m5;qrXJvk`ICMcpo+LKu(b ztS^>(?)T7fF#VBwz3L0r;c-9EYZrSp>io<&&y)sF$oe2%P;qC_wRnZ5`IY&fF4(=& z`)VIDD!b+27vfh1u7QK!i0wZw zO>fGp(k#hH`C*IlrA6B+zGQCi$jkGz&Iu;7kM3&=?*SnIao<{-iVHHuH<4icMEyswJ*Du2vMH6sXI+{W;ZF7|sLI_}T)ziSz)=7`cvzxC4r5 zSPe-YPv7Sge+^__b~5%q_f3l;MH1m@Ft@UgY#9VAM|a=dZyPY|y*4xk?{-;xwA57J zr|1?D9lX(JvYkY`Mc5v-3|hv@6~D5&qN}6W?ApQ{v8R7C3C%NTj29$(MU4Qpz7oOe zd}h|&(%j9mIA+i_tRY|S+xUQg;6qa7C+d-2b9P`eN9kxwBymkc-0UJ+k;r)go||V$ zO%PyHuluL}M#t0d{~9rN&TN05bi)-Yc;ru5Aoz}?^wtD=bQe8iExYOOhjKkjO1TB z@DY6aI+1@)iawhPE;!H54JH3sT>sz|0b`MrE!NP-{mbmA(9hEb#=q7yI5s)-2L3~X zqr<DhCM>gfzRy5|Bl6mzdmSx z?Ku}W@nFEv(6dM6!Y+mMT^IqfVZwfi`f%w-ZIpYY<<3BWjF=xY>r+{jtl)+;LGL-h z{c+DKD=aNF>6>*8&Je#DBBLXub^8hG3Mxu!oyDcK#nt8Z24;4S`%6<>W239HyTi-V z---*z2MG)0hK-Jokdcz}dF1_5GgEVuv(xk*%6f{Ls=CVB>q}c}dyAiS)!r5!CN3~c ze2kp{x<3sqJx`9Vuzk(l?fwoC99(~ahQHou|I-2{`M-mI2Mv#Yx%?-O%^^4Qzk`QK z)4OBLu0-uy3;9sY-0WkQt z%6&hDx<7wOhCcTUewiQ$|B5b0@WqUFA*3s{%oVc}IX*H~j;kJAfbhQu$RkaLh`MCq$Vq-{M2qNjGfHH(pwVl-_4c>zdv;ITd z9sHA6SJwsXVavrALCgP5KUOn_C$Z~#l(RY^^mPn3`Dv|p->IQwOi7Fy2I^d~K&@{_ zusAC4=TIe`S3w*rBhq74OIK8HXJYx~i6DADmQ8o|nyTvjyl82D|1;rx_CW;zzt%%- zz3xkWQ!G%~pYpUBe^I+ON z&`6qS<-kB&y}Vk|jOxs*dc(y|4d3By`s$^SbfaMm9U5UfPv0F{!u>|)5SJ>r_YK*T zVm>jN!MFgH0P$f)rYYS z^C8qif9XV0>+_bx>mI<51TD9W%nah_1$yE?yUhr&K{&ySeSZSY;8t zOFsS1)&||{+&t*iR#^Ca+6W=3o-)Mh4Pn;wC~j|cZm?U)b410;1xW3>zRhq$*-CMO z;7wnCMflkwVTo9yY9?V2cg&-W)Fk>MWDam((esQ%tA>}h=oBf&RLhm>is@U@OH;jWu#qWvk>juy zlNi0ACySvN?RNZnJa6Y&^bR+&%_+>2Sd3aHD05FvtC(7={8Td0w%1CYgFjSPF8ko7 znlMe_%sg(|1i2q|EpkcM{w^8!i`yG&gm?}`TUwp%ct)MtxYZS#oGQ*%n`FW`yD>#J zUbw#HaDO8y=cv(e;(_G<+^1{Zkm$!#Bhr@AF~d1}zBM#jSNX~NX3h2d8v0I|Zhk2I zx`))-UDUaoJ{cFa-yoB^9L;IZwZv@=XPp>ZxLC5`yKe538;_qBBs%v8=^tix8~s_@y~&$XKA<0d|FcKmTGcD3Vo{KwN_w1+Awv~~sBnQl6V zD~{UteyT$#_#cBY_QBhetP89k$`}klA-8V-iDkE#|JH<5tbuolT!p5tp zk*5`zRk3qau5qk!O`j$C*t{rXn1daUQYj*Wh}j}vG3?sb#j4JaCH9f6fcl4;0mrmp zG-K6Re_+#f(z-Owgp`xP)V02PLEoJMBS1JCPTswdh;Wvz-4|L?OWu-4j-muEy1W{f zpPZ^g8%}9Vp$uGcUVyaGy2!&sC$b@}q%}I7P-l4uFHkPNHfUbkyVu7>PabAoPl3-a%#>&{v?Inw>u1V_2S%_x6!dPiFsHBtA2BChac@UR7RIamA zB^=-ezk6sBjKd3Eb;Myz&I9ERsti{q zB}5(?kc}la2+~ftQoC^=(WwP2;5`X8ZlDB-`SS1${mw289?7a3bA9}!qalQj+Rxu* zSxCcM8=Q>?rjw|J|6mT>ZQI9mV+JiLYw+ieg@uu*w#FH%$lDf8|7YF3#OP-QPHg6{ zJ$InHc^lQ5nuzH+*86Y_I{P}>XYy)u*&G|Y?+y+djSF++tvLdkd|^2oJzj9)`lxS$usKvorgr6HhJ%qLqp%^k-EV zv2BPay`!~1+t%gB72pwN((QQCO?K494~K3!QIcA&=H)T!<2m@N3%vFdXFe$4WndmK zC#~7ft$C_iGx!6-TXkkkU6kp<d9J8Um**>zE`UR6NSJz7P)3)BKaP@@*> zc@iCoHo1IgO_7hj34yqFHvy0#5KPtwH0PB^b?2BKy4q(gt$paM+-=u5*-F;0 zd}K#>9Hon*rZQ67)a%Q7!f#vOE!-PMQ#4iWTAo7sS|HWKEO-KOPwyn#vov__JI;)G zk64f|lh;?0OPlb}z^a!tq@zxJl-%PuSb4fC)t2Y<4CQ_t>(Hw8BfcsPWWrc&+h@N* z0mf38+Y56Bw_@rKMI~I!@MEI&@gPQ}^wiRk&I8bk9MyYx;Dm)knN8pX%a3?(AMiR( z@(Seej=n{`i``&D1cAe4S4yTpEWGQ(#&UlSSecb+z=eaCc!|xU=-_Sk62k@B^taOJiEo!lu%C!Jb??iGX%!S?SwL{?rsu4Qmw|HxIA?>4 z!_EYb5|s~#^l}r%?Owj%)9Zy9n3_0&8D~-VE~MgY_eK~4W)&!eemD_w!C8XpdP|Y6 z_eZ#&HuB7`0dtenjKwF($Xaoka}$1`?=0vBeV8H4fb5bEl|H>CQ|}5i`oyMpgOOK( zI6iEUYtE>OZ37;Cn^Sm2>Zl4c)93fUU%EF*=xpQ#24cep1Nj3{Z%&$emmOpxD$Q5B zu?&3#Ci3fwu_|6|&34q;8D=*XE&0Kle>a~IWj!g9yH}fhOAp6jD8duAA&`gt8uC}hsc!JOJ0zlX?|OSOq{*>mZQ!)gw7>;V_}qMmPoN(I;3 zCJ`5K!HqMc%y{H5Jyg9PO%Idg`mKu05be z)R{S;j%%@~v*7ns>nyijc@BK?m=Y6>T0P=AJE$Sh5l~ymdvC=G-OE~WDDhtUDLtJm z`ojkIE)0Ryq(R~qbA)YNsWD#-3j{Nzz&=V;nv`bx_Sw50-s(K(M*hgM>s=j;8o-B5 zKx97^SN#Z{zhMI>ncnCp7N}&}DG~%?On%@BKc5v-viFR2$SsTDEicsu(TVyvHVEIq0`G6hT` zqd!0piE=o7V1SI-y&@ECx#e7Euwqo(o1gtU(nrne%VaVz?5C5_ikL$hW4Zpk1p=M` zKHa=?8&9qI+8!>bjEWbXdpEs18mv1`3Zx69yZ9Z>#vJvGPiW-!NVx#0C@5?!)jIakfcg}hUXc~D?a6N=$8OsWHILQzdM1mJgknt%mTMPj^PPNV_NNAB4n`xM;HU@x`w zZ&~?+I^S>;!$?4->4W>vI1;L&COoZ{mWHb)-ux^vG_-E3$n~nspBv`W7%Z_FHcbUPrN>tuknk= zu1jXNf2av*O8~*A7xV}s?QjX(NSi{On?RqPBsrOuZF;Latb@Ka88Y&1(+&Z$k=+cu8p ze(4^^R{s=uu`|Ud=kRH6GkMq5!sS32o5g$`hKH!#Q`>aju%A{l7BWVHnA%H}wms2y zfQYsJ98Si@%S=`uayLHt$*axGKw|YbKKcxR`Fx|Um5Z@Jnz4Z-1Vms52Y*YS4+l>a z+eUQX2HL)yb?eJA019G0GBq5t+=eD5)#ZXc#S1N&zrT}T_LcmL*_5nf!yWd*`2>Y# zb+2o0jkH9+L`t?Ppm}&ht+!^`RD`~|#F{Tlsd`WDi|K82R7T8embE9cUQqrbkTEK6 ziWNgyOf&cJ+B@}e^e)LIX$?4JWiV1@p}c`6y9c08PQ1JZVNWLV9%4HpZAOn0alTJx;zaZ5>SRknN^2o6CZxL}uoI zn2sCN^I!Kv!!{xcSho;YP)c(dGjbamN}xl=?)61EuiQ!|ck~4r71iz+ND_|qF!4<< zFe^+SqGh)0b6QX*VpBIU7cj+l(9!7ktE@Bdq9J*H9X^$xA&Ou;P)T|a^q?MHJ3=Yw z1g;kIEwW#sX!Gv3wfX=Kc&}4%y5D9Ru8irpn1sZ3Jb3Qho($vv8)KaKX{(`29t|%Prf0KGxpGsKWLyw#bf6TcpL*LH?N+&u`BB?l2#uIOA4?tJ5RDItcCmBvpQY8FqFD)*YDTQ z{>oj90ce|~B2$qpOE83e8d3or%b#9WtMT8wO6!eV0=As%Xx37+{;3&)dK%$$4*-(pxKV-=|yyH{>a&C~E>(75{x z{t^Q#j;r;N;L6u>B_5H29%oyJieKNBmuj~`fv&Y<$J|(vV<>FN;N>oDpWBpU!z}9CEg@md96+`KBQgR3A#1NtR!$h z;NW^HLQF!N`a!~XDvM_%s90e49ggA9G5w zh6b4a(Q^FbAqx?>BE!13+sv$CD;{b)dkMBy*Uf)9XRexL0~EL-+{{#?w`shSU23jJ zc7e10ELgD71hSZL+Y_}>0(;gX+L<=RVB^BV%2jPQ-n@DyFkZ%1&T2SJ^GyOTPATsh?Qpj4D zh7H?K{i`CO13{tJgF(&D0$;;#NU#T+6W6#Yb5zOO-cHUQX zSsMY=Q$0tNsujIq_{vI}P1hwOtQj+j+^l5cwb*5ADGIE?vlg%_cHG`IZtIg{thn|8 zTFktpa}`yClj~z->CK@qU&l1H*L%FxmECS_>biGPTqdKwGU0t2=|>{ahV!(}G?nj3 z{m(qVntVDw0s25y2!=KFtIB1HiIA2H8kt2_1>p7i{?YtB5=m%$mMt$zW`S$x zFy1pda=UEY0*K}|UYY3VEUVhg0l5jwf3t9YCu=@xcd|1LjbokpM5LhI(mzqu$xS{D>n=?^jJ)@5d>)Qk&5iO>HH{M(AY^as$7#K|Ss2Vl4egG@=b0=!ihO885aD z{jGSu?*qf9ThchcAj#FYbf`x%_E2pOdloPppUN#yZmE~H7}nF-bWdKVS^=E3^!Rrw zYVfu>3=Az47THy&O_3z>x5ZejO1~V5ZSpsrp-|r+f?@S_-QXr!hUuXQ(>t+Nx?|sn z2YtnQklb6hDZa=1JP27dr?8fheC*egM$BXjJuO&IS7N=6&FLz%DfzD#``<<&u(2jWdnLdnfHJqo@3x=Ch>qGl$a|iaM zni^Z5H;TPcvipmfAv6&VP4}UJsd>RR8v@-n08xG@KKM9}@><7Z5h+csctXO}OT3y* zv>$6`nd#Tf(Kx}YHrpBY>4WBj&!b2Q1eC8X0Vt<}#Z^2zd}A;sYMSp{iaE41Uq>E_ z{($&x(K7}{@^Ey43{-14h-nUV#4ZzyyZp}-z>78#ASW~M)^FrK$cZW#_YKv`{nXQK z=kg4Ubn`D4X?mxoR#05~q_OXefMQXIbxUDbu7MUOm6qjv=YMy>s_($xuNC46(z1hz zQ(f^6H&vn)mL&-6^rU^vYA7r`39v6!$~Re2=znW8)+9~I(&I^f_| z`XElN)ZL`CTdI_IBFh53Q%9Q*dmrS}Io@UX^5h_jJ6Rz%2E$a&RhMvFi2xH!qOQ@x1jKs7uSg{7v^)GO@ohu~_YoyeK4k8NN+OUkQT>6r zbS=~@CE^R2^QN0Z->-gsD%U~Litm-|)0JcjZ*zJhY_V`Xt>aYQ=D3C-J|A8r#wMO7 za2zik#aogUSy61PsA{=2IY>VA@f(4I!a920(oy%o$1^(}(R@Ki=m3P;)gj}^2~0Mk zc#kWw2K1q>6|SyM^u*Pn-KvIG*Fz)NUFP7B8*y#dc~~*)Blx5gJyck374K%cVw!Gr zdM4@lOlu85a-ldU`C%W8>0-qcFU7;xC+WldB~Lii*%{c>}qCL9Q zf1;J(*waPesiK#Rh$-A-PzN3TmK3ZbFdw|QaxUsF>%W@eG7QOJmJ-RsWI z45JlZ8?+^kBY~3?IyoERGOu^x<=VL(@Qyyw=hBjjzXMS5YQy&H#+q7`J)Q;|G-ADD zrTZOV>Jp_p1n8>4>G^@ty|&Sa72Z+)kUXzM8l@Vh9bI;Ib3AaC_v8C~hi1fn`D{5No2sds`60Vp!8o3MB}dg3u9jss@arPNCr)&|m* zm5!PyR&T@3JCXeWCg3Ni?r9I#kvXpdnUE`_SkNjGaQ_P~LJ7-7V4~kc3_oA-wN^^e zZ6w~BR!x_kAfIH+Z2rJCGjwcMINC}t&aD3*A0XJ2dkKDkifs!Ys&BaA)LNG`lCitO zRBqe7^ggT3tdf*0$T9Pox^j<*RFrMH+d7Y&W(FaOl`ztn!`0|qz*KCrDu=3+cF|)^ z*n5ehgFCwLc6TeL20VlO;{Ock&LB;rZIs~KOQE)P{VQ%1=}|<09C^Gu`hn?p)P1jI z5Ph~uzQ&2Y_?lUtgh)wi7s-3l_4Nf(qMa@}aPiy{ICvf~McMqGI0Z&F48{6%drAtp z_562>gwi+`#(@^$$rds0?Q_`mEywqdV1*S2YQ{naNAarH0335?Vv7y2B5&GVN#F7; zqi3BeTUWUFhA4L>`KRa*ZEPg3hY;71yrBaz%Tf!RbhcvJzE{ni9dpsw_ONd!y=0;d*SGQsue zXOmLwCIqvobJP~a-Kh6nYD^0p2G+BCtkw#>+GZUQW6bF1*r3{j=ZRy`Zbu3qpEEsy zLyp(L_UhGKTwUidMv)`gZED%`g^cedbE1~W#s;*OG8KCwE6Thvx;ge;v1Gme<>x{UIJc zrRGa-9KU>3`G5fU(>fmDN@2=0M`A;q+rM-%Z&x@rd<`P6WJ{uUdKovM>`w{M+Pv=b znB8Jl0Ybs=-+zWN=Tx|OlR5zfB;W>rVGpM|S7qb`a$LV|(9mQ$SJQ%0*6F868lrk~ zN`~k9VkHdt@5#@pR#hC;ofK6-&{*%};Cs0n`Lp-YF|&JDDlIj>_nl6%!8=+i>)Nyv zlNUDU%@O09_>QZu?)&9{U{tx2yv(WxeygQxz~z;gYLo2sIAml_^w^b=GfbYL%Jat{ z4NUUx{5;QWn4|#BHh`7ZE(LYPlG2@dh<=a4wF=3ys%wQ<}(Vr#4Mfl9+<4 zc=U_Z2x0@1xyqMrTydkST_e3H1jAjb2-9tob8PMnJUX&c>5m`Kge*`X4)y?F=8T|*&*2cgE1xemP>6knJMr% z(;p}?FM(5G<;-7=nDc=@SDcM=pbY9c2267Dm@=8i^gN1deS~r2t9!zRMPTH-3jxM) z+VPSHXi;HHRMhJo3u$Cj26|t~j(I!SN8~gKG0@x7%;K_4F})Q!)*OF)eBx~6`}?bN zWHdA(J=?PIE)BB}GM5%cHNLzZs*#)T2I8~Xg8j0bS;tf0pWlVt%7q#jPkkbrUSptD zI>Dk{CmHJdtscNWoa(uwoA&gwCqBra=^&bMWo7cQ2$IjhBNE+*V2&1z&zP}lz=5l{ zYwB$9!~A9;eUrrcK;6S!K^_nHdJicsoKg-{pk7u^TaRsO-rKmFWj)kd7<(v;Es`vX zY7s)2xJc9Tx_wp?CgU$DFA`3En)?M^PKLl66%s&}Qqivwt!zJLHCQ#6HQipzB2yaf zdGl>3Tg|N&Im|g&40ZCqbwrdB*~{dEsTPQBo}L>i>}(rir~3`}Ca-)E3TaSkG49%$ zX`B3{PuPda!`?mh?D*3mYuZQ6dbQ?~g+OiPS`8|m&$&GzTRLs7&{In-BAY7n>;xl& zME1~w(ck&UcLZX$9XLaw5<^icd<5skI!Oc^2!pB7exBo2^rn;E*E55Cf< zDj3LKnGlZ=-SV-%WaK-RxkWYtZe>EpV3_9XV%QHvr!N%0dzy2eQZw_f{G z#MyzBSb#!=wT)gVtL~wm@y>>(#)f)tJQ7GS>5zfS6tIOLd~;5!Rg71dVIkHl;Wjg|H=+Z8Gl>H^{jEa5^ly7|GtnwA0@*xx8gxliX8uSwLaDMXap!|scW&{%0Q?}Jm z-I-%?3%rQp3>k&DrT4LP{?R#6Fl%My@S4aob+&Z6upWu=k0mZ8ETeg?{eqb1Y#p&R-LDl&r#+cR4Z5_@1k{vj^Rtv(1!U zaHq1NvCY)jUqvpi5JB6WBva|-JXgl*@VjoNn!mPzFL_n71{rlX$nN&XZ(}0>(9Jj@ zGU&s)W`mHu*Gaa$abWDqQF=WRw*b;VKpFJ%Rz;k&DTiVS@~q4eLp#mQ2tBmpcZ{J^ zWqGSXVAkO(r&T+YkGrC}Z=l%on)YJ{Kvf*$(WuLl7o`|`F?iSh!TU(m1^R*?rnRp3 zdyZ8*?h03p{Lb5~UGhmZ%XvB3^Bs^`TfWkTlqP0JrWRkI(z?5&) zMVIFxgCTDE$ps~+zJCw4MbM-T-?s57Cep5eFNDo{Os zw0!*JqV0Q6+ciag1lFKQv;rT(rtC~L&&|m~0l7#{=k}6J@~>*FpNtV5#~3pP6aC)_ z7Ff*fz?T`s6)dkoYvuWmF{-J3_m=aqS6&3mu4W`+1>IGk@n$}Qy$4e*oMYFK(g$#` zIlFqH+?Ukn2lQ{FxfCgbdUI61>SToN*Tq9><|W{IZ>Vkb8j=sd*g)y(&}NFNSbcuo z%1zIRlj&=i^b-!=Y@8|Z5j^uY?EMbAD@3+^euSXk-}(HNapNI?GsZPBaUJwQT^gO- zT?iFb=QLxce=!^9E*=m(hVhx(sNT4&*Z0Pq*Zy_7RuZj9GnshT`kOBsT^g>2y=zB2 zBfU|z)q7kMQL9=nb~^@`n8;JkxD;2DJ2??t{}?5THn}Ie_~Q>r50Nq+uW6*UrNlFVio`6?(X6zH7WsdFlQ6Q`2BP%h#XZ2*soKW(lR z925w~te(iJMpr!***&eHoydG-;h0lSuBllLgj4fRbdX|{C1BSvP^=PJU0Jrq8^gdX zE*X5i?j`N&bbJ3)erz_+2H+Q}_MStLCNlk+>YOlvM|_D%%?}j8-R8(70!CK$bcq$# z471~z5kkemuD^4`Z`;yDhmO%H&95w9JI&nO!|jt^R%j|QCsxOFV9{N&TX(C3J}Kl> zJ#QLON^3tjKMUIHp6%w|RaGL}FA(3h6m86~>)=|4VDXKk-5Fjy(2g3CIK1f$M2I#W zu-nhTxMvW$8W^xoa)puRBGnS}Un|IIEGZ4G5__w$Y1ln7GNEUlW~#7X?{OTXqqRwI z?xX~g|t_+ke+Q+l2I{P&cOtQYu(OY3T;ah3 zvwa;_*d=XiYN$eP24&Mo11LzXs|ii zBH)0muEw%RY?d?zAGM3Ic&6Zmd~?~Svr1=$l_S3!K+viIMKtZO2|v@-j=4bVw>LWK z>E7Kp#(5`wyu_B_qs*?U-tg1|BvS@l{%eM70&3IIWPNV6+m=OtE~I|8!J?OTT=C<> zkKiTUz*P4HI~y%_%T;pVd6Vajb1+n{Km?rLeA;>-&EZUY_wP!gUEtB^4XHVi#U?b_ z=f`p4w=3$MQEB*F`*}A5jI$dmpACRf`>biM5ctHq|`xjPR6c zYmOB%RF7G2Nl4N<_6ugxS83%OvBl*X4$-d2+Yt?n&gU8LEg~Z($9`zF>dP6Vm!h74 zJ}U#L?Chn96=4Z=ss~X(depVnol>&7*U+}lDU_z@nD0wLr(GSjgP-=TwRS|n`h4w~ z+ghTpGvCPwD1f6vSFWHNI^gu3whV)PrxyzwTTI+&gGp`c?xpC#*}FCYuanz+_KR~y z|7nwbS8d3w!^q~A`g>76>m}qfM2%9bZ1yOe$mW;Lc;pt;tr5rTHdC+O`{zRW7+X$-Fxx~*o1doax#a)SHxLjmM2Np%dAV+t zw<4>R9l8GJZ8cln)5|okuQ8rY_8!~6j{@sgVb~exgCe~AOkHYPbg@93i7H>+&cNuP zDSIevm!WY6RVj%a$II7wW}lH>aP#7+LwhhZJx#u@MVx86s@O%0lS>#{6pW!b>IYWx z?RonKk(t{w+C3@-3ZljI^FU^M462Nl_X`f(es8%n;Wk)9xG;#Je{KpvBY2}((n(`8 z?S1mvRZzEFdRjyZKDanD(6HuYd$u2sL~2}Z&*kN3Lij8)h$>5;B@emy&0=vt=OIOl z9y+O#Q8@vWb^(hjsr35FB%Ur^q!{-J=dtnqbtv^{Lnvu0KJrXUpb*r1RT$K61aeh$ z!*z#zmqwC3oi_DTk5f;CmVS{pLS7O0xrK{VpE0kE5^&AIBQ=HcHFFp$D^9tGU&?)F zyXfXv1+UVA^-0)+?na|iu6p%`X9=idun~2RwS%< z6jps1>PqUU_Vyy}I`ce3v#p!?_fxt&`q>E(p;p-E9*TOTdV(T=7HThm`1NCO%EBT;pGTB5AXB-r73_{xzY)!s_o^l#FY2)YVb-U*s>(j{G2-%mhBp7>O8Kgd6U@(6cw7B=J6&n4(%+>o8B>dZub&zf4pc2$Ctqo( z=yJL*j5IUXz6mbDx#zm=h~IM3d%f4H*dcL{sf$v7pO~iI(ZxcCjNrUZ_9$g=BWb#DG#vEsjLe+8pa)~K>3y%gdq?EK z5P@q_m4%^U^vTp}>?;IaMGIA1vCi|j4tC~v=M#(8Th%PZFN&Zfa6IpS6Ji?;js(fB z7RTAD*OpjppQ#JW-Ac;@*94Z%Y;v=CEI#)1GCCU4ZTu+`(4Kdk<+{k*y*^8*$|wRC zbX(NqZ-d9fdX`$IabTmTlL-rV#oUt(mW8XRHdb zCwtYM7kF%CGV9!Q&IJegSECBh>gl}3#0^|MSA<^R@f*Q4v+Psr>AmMN_lm2&Lo&&( zm8i2|;8B0Wjlrfk(tuNbLeINc?R*ENwUcLwaK-8cL6<`T$BMsKTPXLNbC19TqM^1> z_n077-)j#F_T!CW7eYk^4v0j#HQ^=%pFDfP4Li1YuB4$#1D0?TE_vJDc7-eulwB7M zosrx%Xwkag3b~#Vtzjf&)Vev*NfVx8y`#eK6JCV54vUZA#sxjh6_{+L^Ln0k-3KmZ zCLWZJ0!?IbZHz`K-+v?=%9uFl=goaL+A&~l=VN#9lUfOS3?4={>5%W!W#+L?9sA)+p{M?&&t*A<0msB=A*O zML+Z!iZf0aszJf*M0R2pt*#o?$uuISwE^~5Z}``3j@A9v~&-X&Lf!yxEsbMWb9j&dVFrwn_Jrs_^OoON;14e%q33qz)Qcq0ktuu$zR)Bm(vih z9vw6vOT+|Q2iUMxZR}K3N#wA)_j`|z+FU%#ei6*9F`y5t;pccE1%zR~wL`2UC zG7O^&QSl+kU&=J6GczVWgF?2;^H%niRK0|Q<#f1DEGd)gF*((#5-rnnfWt5RbjsD& zw=$&9>|)rtWL>OAyMd`DCPXX+imeW*n);!&w5ust$U)CjD@s`(%uvGiqxY*~H~)~O z>jMt0I|5a6z*{oGa_CcuWW-E(J&K1_@R7+3|+0P_bhD>@3`s8r$Y(>cK$5VE7-nvfJ1 z*@(AiO$U49!;rRSdC=UGZ*jfNphr{uh?*Gg^{&Wv%_NMlveLOVj4F)x(-x5nJz77>361J3x zxmS_vqYTGs+uZS7^+{(?wf~aUEvw0PN6ksdoA$55@>UtdKDjbT&;i3rUr^z0^Kscq z&M)OX1Pyj~p)AK z$Rj>3WV^K;6kGZP-)_9-qiQ+q2pxLf3cZBw8{-t=1~jiG3d=baDzs~yJ-WDr)Ei8< zuM$*eq9cZv%#;R*ikHY*XhekB5!S7vjYXvB$RR7g+s3){fMWhESfz%F* z5_)ZoDcq=&<02=K59ZR3s^N(l+i1WqX(Gp5Xq|_4zD!m)r$&+OB_m)5-AID|g)TNYPPQ!GS^0(G`GZ2Sv~< zh`?+HSp--{6J`a1+6)AXNsM4&2x2TZfSM78AZO{^%xV%6iJ9_swEGVD?XD$VD}bFp z`rp3!@e&O*!iFkC>gU3`pa`&a^l6$2%^)Z)&&AFH(?#|oG|f_Q=qk26&+2H;;f$Q= zetI-XuuA3X8D&*5hWNVCzpu~rq669hcw}gBXkd77Y;b^lc!ZbMPD)5fN_1RcRqH}L z28amp1pyr~eMKMKweLVdQ*TsSVr6P;YDG|Udva%bUubG(|Ifz|A0QwlBPBQ|CpczF zK}lx+|9StJZNU%%5FkW7U-;htI~_tGL_hTHUV#559|Xk(e~JSh|G-E4NB!UWfBFQ4 zKly(V|DHZ1LFqb36Cw2~G99^*B*92diWe%8)*fBt>z=Z@LGyE$t9xW}zn-FR{box4 z_GN$kNW6dlv_EeDEARh5;$!`QNA|cM+X{k2ES{n-+duy${(m-VX&J-)T#(>di#Q$( zX0)W$QDfATaI>1}velL_v6FSXOAeSj825HacYl{*D#eA*Xl~7Vg|E_DH+)7&f*13` zE~J!EMt6TtpBggj*}L5CT5FNmHyWlgM()HxVH`SB`qg^MCiA5Mc$TKwB3 zis(h!{*uV?*9s9FRqYMARAx;FE0zb(BYVRMKZP}6toH!%`O9dIw-^tenaZvjn~)_!I%DZSJ0sUhL&l(3xOpLHW_5MWmK%Sc zE;A06WitDWdEO1&I#(!S{Np90m2l%39GB^!Y^~pY-ID^cludXzV?a;0G-Oxk%%r3P zi16{W4lVqzz;B>uEm})rVDSc%V3eHFB6$_mUZ_4K=#yDWac-orM{|HVhM#g>d#WA4Yrz0>;CN3ee>-_S2 zzdi2FqSh6CVx^x)bG!ewbaDj}JQ>9my{MnSq4m+Zz(A{CT?|Fkk$Hh{`T-oOV&f(j;L4AaKm6>A0zXb~x;yBkUj7{In{df4# z!3lAe!?k^`gSg>F3mT9HXuoRnL;7<~X;rLj-}W?B9_v85XpLGiB$GnG4c*Fx@%&U) zGp)4v4512hTP1=g2f}mCnILLFRI_17+U(st-uSQK^6}yEsMr z!s%5bk_x4&WvilQYEQHHj@#6Ge${;o4Z>Sm%)}*KH#7;VJRFWtL(%h(toO}#05r8) z1$_1vSa_|XnxaF@XR>3h@4xJ&hJiMlWy2 z*V!~BaNUJ)`<_xY8znZvtaQ>Uu(L<$?1gihz3MB-S<~S!q^z!iTC4dedrA-Mge{e z`lzz~mwqih5K?irnTp4gFF_Urrua?V;qd`I2O zK`9@%x;uRKB8eMMM$gNtXKvC|Vv0j4yHnsb8Tr;xVltIs`(c+=dD{JPDWn4KF>J(| z6XR;ia`=0XXH*edEL;@al->TR)}FA!!U(=t=H1p_ZrukqyRPW8=Y=O+5FQYXvl)!c z-mqKVflxb!4fiU%LX~oH$`xP5j~y`>RUR*m-`1-paz!F)f{v05nxJ?~_o= z@3(7Y*ZpeNMU~<$y)!1?u=4GS1{UA^{7K*vuhe`FQ^0 zoWUlx@knIzMWCZUTu6rOznfyg6C&h9G#L{LUg>!pzGst^5bM@oH>}k2Bfggef4akXpj{IZeDt!*E_Mz{a8~QYg)M zJVmeaG>JP-)V6x@-_;ynPE4}Q7O5)b6wpB1;V%0u>KTPGtoVzG51u$7Jq6LP=(#J$ zx7HH$MhJ31^7OklnUko=1y-Ac@Jer{Gg-4Wlw%10+up^6`-hOeOYwfOAgPf?3P~B% zx$sK~YvE9nG$-&D4YAk$2et`|iHxt8xKa&lHyfW50FT9M&kj{9ks8HtXbc!?y3Nfl z6cEXfaeP`6&nxoAjrE0wr!So6S;REa2Iy|>x-WmR#rW^pXs=21Vh1*eb1{~CTSXVg zUg%ii1(QMUHC^IVFE=1m=E~t)55~ZC`^@RsZs8zxUWFE!@zlX156u#rG1McW+RVEU z*rCPt@>kWQTn^+npcyCGT3GO^{XDb2F26BWkRdg_)#SyY;D3!yM__?N#9>O z$@Z5~#qNxLf0;Y%FLyotl+PUiYT(HBACi3EN4Clzy z@DP-N)O_*bMj2fzDTr3vmOw3j^VpNvxTXB#y@ojdk#lW6R28qUFu{DxW1S zlYegU8#l&pq|uQ(cS10G-{#I+iF~xWrgJb*;CGBJAfQ%2Vdivrw5=;JQ>@f{Vw{sf zUCZ-j`+lgzETR5xNH{pnMiB_&4hM$+VZ2*v5PKm@{2W|#XQK}k%@7;v#8X2nXZz$d zwI_W2#Uh=tRl8Cm!J2V2#}qIJRNo}AG*6lfF->PRlC)jwmsV|wmWicqE%9gIp)d-0 z&?u}I>zaU~Zp231KTalg<`w+c>7ax98D|+Wg@i(IiWFubl(My8xc(ex^CG~)rszmAzkq(aXPWHx22U<#+Mc2l4#O?loNPmyxM$}&Yi>sutN{fys zM0*Y%6{iVzN5PI#QrJqp`8Oo8-PpJr$PncLoehjo=2OgD`Hjl-T1;hU{+TK%l~(zZ)r;W1hM@&@ zYa!&qb-t-E?jt^Dtr6=ZVh&FqHS?+A^}ORIo!{CM%8sn)c2)yXLKnx(H#Wm76(DQ; z#P}&vTT2=&eBe=zvCh=N>qw#gGrnFKj@+WGZ5M{<&JsX@69O@I#a6|964&&9KqjZW z3z%;vmmoGNEyxG?qs%0x=yS?m;A^?m#k-YC< z23VBcV{Q4zd#bOD^I9rXHlo?ttMIdt(wBgjBNuKu?7hpUa__=W(n%V?GY15~`VlBr zbBq^ZLZ09Kgmhm`d*nBRhsSriX}hZXvA{D@n6?Q})+*&3lNbY?;`3_H(9u&wWFc}U zFe{lA@}uIqeVEx|7s+2_^GPnc8x~8GO+v9#}{N8Jw|3q5I`l8yo3S%Jbt`Co={{M2pJu43gPoZ|rgO8FBf~ z%;P=hun!nzT$n$B$WBwP=;PZQrJ!j|C3BRzKS(tvF&k`{A(;%NB3&lM_V$2ox!LJ7 z5fF5i!c4|i%DdIHR9z-Q6qLy_ius>OD~_#!QN6fve0y;hi1DB4JgfMyW-5h=|KI`jUdabc$z( zBgqw_kzrF`F0jM~R6237V+bZ43ZCM)i;Ud*gFbt?Kcf}i^&+%=VFFR1g! zWfu#WbG`P#Bd9N}>1LocIP#L(ANVEIY7XO#`xBkNQ|DrEL^rql ze{#a)M`-pIim)ktL3}a?{H%1yhGlmnt2dLKz}2+pgbuOjX$0dSG={o}Ik0ZYWOfzk zcPQ%g6N=EfrXP|UMI9XZPNw+>Lf0(juE4tB#mqhxRCK_9Kor{OZ~q-!jAv;4C(J)< z)n(D(F7iQWISZZ|M=mb|%2+A_cVauR$qP|)h2Zg?x za%m+#$$~+7&IjMb8@C3Uxheif_9oUX1M*b|ID7y~THXy`vb(Olef(U+_&7*)Tqt&A z9gv1mbk-Y~@OH8O-aySHK91*q7b^-*+up6QDx*~PD5;0FsNenyS2n{Z$`(~}>%6p? z{7v;8>49%U+~ha>JX2rEyjYOB6Q7M7J~h85e00UE#bvx87rmikI;;ZH(RDJLf@VcrcD;-3SXfSuI2*iz}fe`#=Zd_N^w5^_Wb?< zRm)okeltcqDC|C7*wVqN$5=7jxpY#+q%_f8Y#%e`tQ-^}wI;{WWsGMgdt6X*tb>G3 z{6j~b!3bn{lkXm%8}HNL6d1U+zQ2^OQ@M`d^}#>%h1Mqxn@RFDaHk>^`+m;=7#J z{f_*4a+x7s3zzW}Nd3$jbr1;XC0?4Ec~j_ZK3M0oMvT3nshnrT;&7<5#T?T`4W{lm zYq53S@d8Z*05ET=GHbD3!&xyIKhmjxdL_H8-Him77f*A9T_JsIe+G}(`#D)(;aJX; zjZb9y;HyDbMI!nw>1#bXrplv7DR&C~_rRp>WVz{<(A}gZfzh%iDJ%5+?J6)p#k0eq zbGFf&NK5KIGw(Eko%5lDK&=j@W3XNpt(0DzS3~}?!TLzckFcFM^2+B)C2l*T zpE-pTY{C3<+#@=Z*;d&?VN*5_#X#~9IGh}ii+|C+Np@x`2;v{_G3k#LRrk@3)*c_= zW^MFfnj6evB;`{(4oPyG>}H^}Y8*S6gFAOyFhIa2t= z{Xe4;elE$5ta`(Mp9mTFvB_wWK9(RbMb|AT41Dqcp0IkjMOVHssA%R|S4gXJFOul{ zwe`N_-&AD!>`;RtZr~{fi?xoJ)1n-<7*?8eosHn$%>6!0a!V7c-e%@uP^hG6y z`TqK|Q-FbWx~!?B`}#4=wHNdNW#>GYhxxhV%dL=xXR9K`XE%R7LN8>n?XXafPS{?U zKFFGzg0-$SUL_Yb+j&2m+9orwrM0hGMfKNWUkh?R9LMQ zvWDe}aUh5HGut|7*&F3ZQZdNaGul|OLRbEJFSY!HK$+Lv)%OQ%d|!IXK;r=yCNdR= zD8THK$rN$V61g-RsVJ_3PDPs9q#@~;C}Bmo!;$JOLFWRk%QLoiQ{+XGZE>OL^F%q z!&!z!lVhAf-H~Txr;GC$k>gW80@-F*6!{tJIL5PT+Zjhb!OUrHD{U5`i6-vG;*7alu4f zY)EwU{{V`GkzbGi<MM6ivEH9TD=aTyqhcYrVJhJ}zaQl#oqWzuI=rR~ zHDo1V4=c_zEY`lNX*&P}^{vy(1&VF=Hw zHO6{PniCn!d7!+`HiRPM^f}M0lp1<3G*Yi#w2%$ub2%ex^k(mWV%cd#Dq5yG+CF-! zMcg4TxV&=XY|;w+YxY?bUhkC*JB0;n_|)T|Spe+Ds3pk9ZIP2bhD0hB#M*u?XG`2} zUj}i&*8d}i74p zjTlKLXa0>#@HsAEk*m`!NEB32awlZMV+jQdp=4-?7^jG!}^4Cql(mg^6k+wl~;fbifiCa6n3QMfF8{5eBm>rK58!j z_Fbw$z0AZxo4tQaF!E%G2Y|QYm*#+7Eng^9pH+DxI#Y(ruM=XBQa)9b^x^kbp?>$D zA*?Nz*?EK6(DC&i_=-X0oC-CvQLj+3+`&vJ@}h=DCTP)lhU7#{!9v!P3%EgW$r z^dI$ZGn3YJU6tF!GmSo|7>hTgby4gwOV_wx<$wSv+U0&USL!I2#Eb7GghO+?m7Aj2 z_K&byff%yjJ>5RgN@Kq(cKEcaFOm4Ml+SF2 z0k_cv7V|5P)hbBFz}nl1HaTV`szH=`eH9#Q*$VP37nUuVn63al#v9{J@glz@eXY@1 zdI4P@Qha*@Kh!`UrW%(@Jw>F`N}}svq^n7ogd4LiO^I-f^Pgz)T%x8x>(j$6zh0PR z%R-2anR5)!D5|=rBh4aK*Jky#YbVk9C|*4QvNq;<@#F%^Z_>3zB~8KOW-qLtNume3 zY42`hWEPXsou3hTq{#jxnhCxoZ@sKao#AaDhG*ovQ8G&YXZu+-6HER~ z>-=q$_o@fQjC?XvyUj4kUQ0r*Js7lxX6EC9N<-`r@uVc~3(VqAE5 ziaAjqcg^XSZ9$~WE=>C|@OV#}4!J(`1gqN4(X_penUbkKAyVYFNYK-|DKZ@YLQQsq61PPU8Jh;fcB zl=%}cS6xWF;@rxVx2<)3;gO+c6=do<1*+eet@roOdfMyor2T&6h!B4uacBKH4qtjy zM9uFb8{tw$E#*!mIeJXb`-p~7I)})nl(~y9#|?$tXOvVrJgdAbElvV3LD`fjUz9i2 zJv8qd)TUNhO>}>tyxJ$zA7XxMde6}kdrn|zj&oxV0Bg$5ly2Z7=#XMPM@+Y*zp3T_ z3S{i@PSX0rwTA*I5q}bIu54Gz$7^vdBr$6mO@#Rm3nA2x5fC6<(u<%Kg=zk&N0@;$ z&?MU`LkwPS5KWF)@qGYPqWzwwa6b#nMNJ%Gf%~%a4!puqxtrAaQh|LwZ8;p z+oFS7#bBZ87ARX{3t&Z7(x>Rq(fv*-tzvReQWvOorVUPDBr=_NX^^kF{#^?I>xFTJ z!C?JSIpajC=!ja$;?L9cKrN3Q+018)_r`DaG*|H_34?_(uos}~D<(|cF&@=ir>%h& z))t7}mVBlhIfi+?m6s<f&W)Jh$JCdT8^ZO+-7-5Ao-SiqH|cx$}I2&8XlU2nYOR&2UH&-de5`i zp7znN$@_Aclt-DYRIUE`-V~Gmyd}Ti!;d44Ib7@&0S=j60kGvSDlD}te6;LGeUgeA zQKB8Ec(C~2Qyw7+m`M&o>rk9a#-kq(P}GMh9$0ndn5AM2{uthx8&teLU-#S)dz)Uh zpqt?X*dwKh1(%5jy8FaXtye2YO@QbzBSkxiRM^q-`ApkW6m%Ncds&S#!O$^Kd;|qL zjDe4C9Vl5WDo@aSdW~Rr3>tj)tVA*E@#R5CQVzB|VYvcs8gd32+;VWu@RF>UUusJc znIwzV`DKFQOM8rC#R|uEm8_t`)QQBUY9}#iX-j|q@%ayeBj;ex(xr! zlUHeugTi!#9<5TNFi%2Kvrhfb5M!Y;Xy<9As}t39MD5=k*VN3wy~h1yaE7GjZC@e` zcdPmV77O1zxD^F>AM2*OVTaL0&cKVJjz~DGcbcEf;=$Epm3&P4`;CwCfKyzb{H)RP z(ag14|8>w|MN+Q1`Bc&RDX)~L3SH5>WLZY>*IiGv?3R5BTaKt{yd>4K{MADFJ;pM1470E} zdK#L&K~nr8uj8VEALmWpQDj{Im6)AuqMK6lrF3Ok5e`GnbU(Eid`}j5W;&%wJ9JDq zU*w8<%bfUcbR^1llBxN)daNRkh~^-*g>Tfiz_dH@VRfD#{(xpUBJ3(KQ5R9k*$UK- z)yghbrSXWaT<2+CwQ`@wH>Sc(eeX$9%%ELHxM=8zmm|ss?5Y0kb?7V?$7fh4EM$g2 zK-bpdS|uV5WlUZLK_Nj1Lta(+9yN2wPIv{wH*W+@-c`Ad%PiGA~ zFc^@YK40@6S*|7tTA!JqWpW``cO5wVz0m30)cjYz2>dsu^Aid+d7d#c7kskVd8;3~ z4~x!;PSvPtEJ0RPzHL7-Q~UoKkxFr0rZ~hx9e(_1o;n-fZClLOT?|;!ZqC6Gp2;r4 z@-t*;q&p16gQB`(q$EIkrLnuE%Y~wzLY9)8q0-TI6wX5$55@VxI`LIg7{S6yTCw)K zEr^_(Z(Ph-T0FjMW%g^^_oF=@ec3vOyAdgl_2BBc+Va-mwy(ilQ;rKM%=n5YtX+aD zH=aQbDf?cvez(NtCACq;?Z{>lLJ9=M^K>o5l6Uh*gK#@`GFcA;|66khe@Q&3zvj>D zlDyNDY?0ve37y>;U%5*knCF7w_n-Up;&uhnxOkU655}B?)!6+eYUT2DjTd zVs8So`$Ci4L!`U0jGGPd`LcCx&OrPin~(t7O;DZHlU?`8*Eq1U9MWk8e28$LBX7Hc z-Qy@zB)bG!E%2F>0Bd~-0D~}&wApqdj554m?7syrVC$C=YhTLiH4IC&E-5dAp0<>) ze(^F=k2aaKQWzxocU#74$%kWi|DzRO&++MseqVh_Z!&OKfkW{PNkcJ>)4<{R-xa1f za}@?)b$xq~j6gcr%J5LMT;Y%)RlDs@qkPG+=p}Wvb>Z8A24uzX>iLvtnV^Pyo37q( zBlYX1B^Sl(Exk=m-VU276u!L7(w|c-PpiRXM$HX2sZ`c!%Hi$9lrCI_2SlRgOPlsQ zeClPs-@CtQ-(;`$PRE=8A1CNo`fYP1?VSz#(^aI-9~QsGl)b0Vce6!8LKj3AiZ6i$ zW(a|33ZcPZ#y!hZ*oP(JN*D1@J!3tEx)o2lo`nJ9iZq)K82E5%j#zjTdh^o-;!1w7 z$^RZXti#|Exz3@usQfJV833d>t-snUQNjv;GuC`nX~Z}*NjpiFyC!`p=zySDbZF;L zY#VoxM?}3w7ijQ`BG41}*@C6R)C2ehq9tSoCx;wk5yKsJT=J<&9}{k`)x({>5#l-|jt zVoID=Z%r8LZTLTsc~u(o5mQ&mYV8#@imbET*TbQy=!EgvtbDrmR%=eJE*z7^JZ-&e zu!p*VJLLS)-J_7W!4(Zq2r+BW^TP^P+Esir<82POeV$4*`5bl!QRwlStCO=D3XZKq zkJl`|32M!H8#s!Y+Ks>Hmol{UybYAKs0%chD;%U#=Gp8ZL?onxyg_;m_)$6`DP}-5 z87)y(H=}2}DBVN_?(LtTilj0L&|${PC?Ssam?D0HL>EQa*7+toR-5v#(Dli9aBv6F!F_&Tf0;u`m zQ5TBBCi|E?u7D)+LHXfT12*E}mJ)XW$i4cw0tV}r!&pOPpM_u>G59IgX2qhl;fx)x z!KDPvAo+DM{!*kWlUWlfKp0LmCCX}6>Q6dBgX90IysI0MP^w^gwa1x7 z(85rWW6&F9mEw86#r>%$@va4VziDWt%>Rq_;e9nsEMl^y67f;WmLoe|e(ggapM1RU z-o!vP|E3X@-uE?Y-kIL6zZ){`GjQ>fvudRt>V%`k4D?Ogd$qwd;m>f2q$6FG@Iaum zY+=kY_2MLK@Agd_7Y_a>12_pInbb^1VcIYwqgS8E>Zzv@Q+od%BmTFI4`rBxKurDl z453dmP%7qo{>#3wL#Mn=xg--HuLKRuXO5pdXb z+(fuPwCWLPuq>TMqS=I9cRI_IbUKUhE*g)%DjJtjOS@>$dJR%)%ZF>Ho9 z;=1*~HM|et6zlLfww5?RSkt^mG7=N=ZyX?R-|~Dplk$1EDysBTp57{p#4hFezD*ei z9hP9~eQ+P*!w?Pdr~(;!h&h8Cf9a)FC;V*FDQECm zMjI4u*MuD;6avfeq9SirfH z1fNCU%t3LMZ~JY>1<)A3UDm@KYgwOAjobu8iooy; zMY6>{BLf=V4e*rT@49Ycj};#ay4&7^41a4b$K5k!7b@R05ibs-vFa1F0OhW6Q_`m+ zPIcR@3sTmbSun}O8*H`)Wv#N-_%Q;KQ_LMH>ZZ(bRw0CBHC8; zN}^-MX(ku=Z2UGgRk6**0p}?g*6qwOznZxZ5t3T=x$g3~EZadXbvhK-c)3P682gRK z$wT9*Iw_fFY4Oclf5opS0pQDg9WQG$tLlr&^Pz?{@+hX*72g!PvHzDeNc0xmuX{|> zoXeL9bEfY2tha__r_AR{E%6kKp{0sc6#QRDx$=F)%0Lx0T*g7adVh7!_Yl{1Y$zI>1P+;qcrk6=7yid zLpNVEf>JG)eT|#ICngC~AZ~hh6Zf-qZLb?rQEY9V^Hbg{)!>>lnFeaofJA@R4;-e? zWT%ReNp**p01c@!_Mbvqo6khco~ZO3!OU)iD$#K>MhBUX4FbUItk)xv+7=8y4n@!d z^OC6MyRF8UoFMbD#jc}vE-J*kwfig3n>6dtHV)-fP2Az!>2Eu(Ya$6oJrdt$3QC)9 z!^bAx1t+>wVomi(r(|C&X9`;PN&~&bL+fK38o5r&ynjF-8qUxP zYcOLo!?sbL+R_qHw|0-RbxA}7tru1dsBOk->yaUki9fa*QP?I)o_StpNuQT;GL|K9 zLL9yVcx(h&EX0B3`4LbdOS~=&_s#UFO=&F&x8dismH<>Fh=W_@_40n@PvGrW@OTBI zh37<_dheON!Zypu-QcqK$|CsLX~|=ePADVefz%VpNp-u|b}y_J1xM??S4$Q1%%FsU zygE4aTId8>_YOlsi6u59C?>7%PY|^Y9KDc!f3kbeL$;h>JM5x)3x1`2%t}7WzX^L8 zGfchH%Le-f#b+^z&(xMSj>Ez&b}F=4NC0$5lRk9FrP}k!t-Mvuck5e@i^csYT87lm z$=^184@7|ltorVACX?if5bQy>pRqkSfz-Ei-c!JA5>lgg461uU`GL3E_bK_eIG+Lv zUhZRz*Mj!#+49FMCH9-%=koC_Po&L+sVM~916z#7Df+>r{1}LIDj&21Q>}~We-5OO5s;Qt4DRuS& z<(MQC#iNX-a60yV9oO}SuHg4dt$rP6IK!HnPE2I}B)$sl+ln2tA2;@4GN>(V8WEu8 zV~f*lf=n8=IX+mQBbYkwb9rh7_hQn=`Y-InYg09N@9i*fS?T}*&ntR|t&TtxybpLK z^s8p|oC^M{9$cXU(NSVl8Bl5Wm{3Gz&rGKrL2|>^=ct`XzWzOhuCWv=txH9UedIAy zsSPvBO-gOoyc$!Ge-5Iiqsz5qC(^>E<3GQ?fid zDn@L@%zBJ>Tfs*^MSXUPkRzkbSGApG?y z&l%$tU~tW>0%#Sf84k=jEAtes5gtoum^GqN6F9ptOY$fnx5eAU!Y9Z|6o_XJKdJ#H z-#T&QbC3+VIrX&c|97iziJy@=i%Uk!J{L=tz(Q&!+D$Ut60jsbr=a`##tePGN=)dp znW3@RVy}g=00E#qBsshD5s35p!EMu}c*H6RVDCBxgJlL&pJ(JNoI{Q2ai8)8OIDUVj#Inhn`vg|}KTx~2TuNRc%1O+e zrL*-!l_32;K=1t3_(&iL3si6A3n-?s3wz=YtvG3*1+r@ka znWduJ$g&!v=dYfvCsUoO74#qSSoWzr*QnZ_%eP6#Kc2z#=Q$@s4M(-ZA1+?2*33^d z=a>`ez?t`xt0`HraelY56nCPy8yK1#FZTbByb04aO zSJK$3^CUg#<1C(2&~Y1NT)bP)GSD!x$~km^&_uCXqRFuI7P_(E8NMicMf<~$!13ea zHm8%4Eu!xt}wj8%OvZPfY;H5HKlA zgrnY4I^+0!vdJ{yk8)G0MC@T8jqT6?%T#DTCOD{ie*M3NZQ4GyUqN0hyxVzNztmy; zw9_yQXzv)`+zENlnT=%AS-FPE35JO<&UT|Fralm$lPhr?x33I%R}pf-dLWC_SL4(? zqTpb?lpqhh^VQht#~>gE*U^neQ6G(JvB8$eyrU+#0mtpU{IK!!Y$kl zX+LhUCpu=&vOBGWdPNJCL(02cEa0#n$H7N4%3q9P8=e2vKkES?8ub3QfI0@j6+ll$ zQ7*N=qvvXAVGSaK*&~khHGpZ)0xo7tje-I!u1abCQ%~Pawy;*$OzLEF%h|bkPnhdyitmhx5o2viQkX*^PKjqI+n^^BSmXg@8?p?ABA(6pOhI|{?+j|{fz4x;407=J(^ zvtI7p<6zb&emNA;=tEtT3jXK?=(eJlnQMh%t^k$St?j%C;$<=}a>jNGRSI7W^>VuB ziOP<{Kq{L=ZW1+FMrzxNx7CzxGdr8>)lI4|qN4f3u@jGGwrE3M zK%JeP33>pW$}axdtjE+;0qZU6f{T2$PA`3REd+SHUy}m;x2#v)Dc3HL>P~i!D7GTj zUJPo(lS+29>I}IZhQ&u(4Gkc9le1ahXF;4eFZTKHkVMC^*M0vX=TN}d@P}YF6XvH= zOTgadQG}Wlt-}}<(7F*wZc(X({4LTUU%d7t=|APqiNCf#plpf}6KFbpQhES*{`H9- zfgK)_F<&rbq!x6ye~(SWX9|!TK&EZfj@bDZmkE@>ixN;uJr50Ja&`+~V@f$_W;bzM zQ^gXNXY(AJffc3zFZwl4Mv$>K> zL)l1=rIft$@xS^)NuZ+SzV_zIQx}e3tD7!Z6wvMP%=UN2O4LXlrw}1{sJKwy^>`o6 z!{Y_ougag-w*Pf#Ud?alB9moqW2TbP2Gp>V79rJTQb|W(d=%QAch1a0SwF*@ zg`3#0^#^i}4zrxum06%O~FnM5{ds!FBjV+`snUkH*omA@D8Vr9{DB|--?p5$V*RaG$2u-Z-Vj!7k#3WX7V*J z$JJq!{&)1y-bZpmALWSM@-muH)U*|NY6RZAa=p}*&})|>7^iUADpwY-GWM7(ziihD zP)d5lGn6PGRw#T9DspUK2RZKX`cIzH(6|Q8)g_4vzFWqGS(#xh$ot-#^?IbzL$|&< z!(F3kDqzdhU>RWy4!SKFcAfk2eXZpLqh^-UE?ggeh;f2t^X={y7rZQKXVGuy1Y;Rp z-Dm3|Xi*cD*R_?F!3Kfc(uHBfxXIxDOV`5V(UbAJ-X#ODu_wrhhfVOYDL(nYc3;Z< zKnN2HwB8O(yUX9TCOs(fD(#nTdq+l7^{l{^GvP~ZGPkAhp=|ysFVreKMo4oN783Ga zAH}Za>uOb7yO2tnQ7~A(p?!q^!l1IwZKpk|4gq0Tjf?Nv zB(GrQqh;>kojlG-UPuqE^}}c46=L8Cq-zLj2@M4BN6>)v_Q)q&5MdqB036E8H}7-? zUm9W{efhTNtb&QAXw5?&a=ZkK%un0W13~!uuV?xIe#u}@nM@#lViCEneSFG4cF5Ex7}x`^!_X3S;eNxD;E_QpHrk5)}UdFAD&aqaq(meueC z;rNj5x4O5~7Bbgvxbv`lFpbed`0JUwtpRT^%C6}0 z$E_ZMLq$_;o{T?W?^A8ygDQ|0)PQfhS*ssN)oF}Io*HlV zoFH&Ar(;s{S?&!Qt#~p=aor*hr4KollBtZ)xA{2(T|?h7kUcttWL~fdl>Z@?KEm$! zAo;fbsAhZ+#Y0Xp33A13ok7j#=ZI~PMRgIFeyu-EqMszbEWb%luZG*M61Ioe`ED9d z)}CWeAIB+(kEj0Nl!_|X?nyLLM+8*<$nem0&!DM`UQmMF1`c%2p@I-B^bo79s@meV zT!_5AQqs4iL3_HB6hu$FEHw!8c#FhYNqL(ST&J=0XncuVN zZdPJ_oFW~sggVIvE#RqbQlUihjKcwg_8eXE{FQa36b3UetMZ!S|+PmzqhEdw#7)(;qhXvE-H@b+uH+@}x)`#)F&{o28i zyG}9X1F^LWC@-n9B-H_^1&jtNREDK5Z7^Q1^i!u^h?~ zG0D8vHVz(P<_EvlTqBf0=>7c6lscqa-1H(&FmCECr1zip3#syM0%B23_xH45&83F$e0fK{k`dMP|(olKr&qs8Y%|1O%!%ZMoFu=q`Bz-=U1~wSClE zTi3HyZa!btAhPwpiFVyCEO%<{@?va4Pm%uV#xqe({x;L`pLo)EOF+9Y`IX;&> z^`_+sG6p4z|9fl`v+Ra35y{er^eQsW6uW%Ko$9C9`bEGXW+FnXr^#_LldyW%u&T^H zo2bMzqn@r7g(_4s!2fkV*&DN6RtNb#CtRXs6><>lI?sftbqlSg`>;SOt2K!kIOzJz zPG&~U=Uva7RU=&C|8pvLH?TYv!0UPayki}BE*ZTeA%4TNu+V4ezZdqD4T=$3@pl!MR9Bb) ze77#VJb7VCfNO*W*$DdOXODFV@>Zh#tTN+ZE1sR@%PRhyjeE1RgC$=e!gjHw@wQ`r!ZcMT;|b?G2z3vqbT|8VFx|*yTP6rx7T2C_Cx6NzX z6z>ei|DZCw#9G2FnzXk(`M757M%)CFhPD4eV zh#fSk^b**sd=R=(_uAE}eqan7-}ira0^S@=xYhfiF8knXZe19gWE%KCXhk(|U=qc0 zJxzHwZ#~F>uhI-KIrE_ET`E58DcM;g2*gBnv_$Sp?#fpw_psf3FAt&q|Aw5XHC%mK zTs|sCZ%s3R7thM8q2s1RhOX2s*ym@fxWH;I=zi9jsn0L3aBo=T!Fp_x94eL2jgDeq zEY+8w{^OPtg%fQZ$wsUN)&3mp^;$m^PYjQ|-Qm+NRcSEA&i>kuffsNn`kuO(@4E-y zA6dPDkP3lIV5S?3D(ZDx=%VUJrB&%ia%2);?=;2-(UoR&dfrP#^~%n2siS8h^B_eR z?`oIqSY4a!)~B!1NN8!)5|y6l>ojnN1_*W1^;b9`ko&Gz$Qjk6{y2fR(uTHGlK?p)ijXqQ$4w}{73K~lKY_|GOot>d$8-GF%M#kg52&5) zj=S>xDJI$xFNT{8AP2Yp{st7`Ip11H{?s!sA)-g8VGoL*bPlQk(Zb4W zza5CXtH+Ju<_qrs%y&{3U+yRX8EJKAXed4{JjMa({|tNbTY7j_+X;=A%ycrjql8nr zEcvc&V+XY|x{%uODi!#m>$0Ze(XHl0saQY8){&mAr<0lXPTu8=+1rotNOF9tu$kg& z?)s|jpRPZX8wQdQ;p$RAsFfAbx^WbAxUNH!cDQb6#EYUV+MVB|+Zg4ib8~PIoM!1V z{XFjJXEe!*ke>q+PmVP<_smoo#`|1Eg#M0GweCGzjDdmKKjr_1h+kD4IU@I~U}hM< zSv9Lk@CAcjMNoH<&Ge<{&o$4M6+(65%vdv~5c>^VHtq=H| zF-{ni1lC09@wpdhs(We*20{+ow;sE(W458k>Qp&upE}GW+&H)O*%u%+q&nD@iMFhJ z?6nq`l}2*xy^~cN+|Pzy{+tsN-66e(2PcFdV?i`1+^?Rw8pb7uKKg(2C4;L?a z3V=7u(;8a+0eB{y4+UMg1g6=&ny4wKP4^0x7lpAor)~_viz;4%ibcr!UTT~`P42n& z`gEpV{S;)ZT%o_%?;BY1k9LNNJMdXANTtM=of961hFOmDQQ_2K8&1t6HY2&-x{ zZS6aWl9sgr$a=G|{jwp5zKz<;#LdrwzrLA?_do-9hP7}u0$T7*LcG51 z4CwZcw};0cAB)0Y+*N3m({Xw}zn{}ZXVGfolT=Ze&&#jt?pbuje1>CP7fqpT$qIwo z#b$6(`N5`TRp-Xh`HQ9A-zG_$Jwr-Fm zvMcj-oYOo;S$}XJwaU9ZrW=Bf@PA4!EPO2Y8B9U009tQVekS|Rlz-g^%&@&;uJI9_ zALB!GXr)I$fHa|n%Py+8hOR~WzB{+g`96GNPvSuOYhB6<$J$!!BLWfdU%O9Bo)&^4 zQJkPdTt-Ve$W`d>SGpD7CL7tHK{7Uo6=DQ21bHC`yS;XqKb~@TRx~7Zun81d0Wy4T z75QdnJgOYVF#=0zv6u{un1Pfn%2$@VKgj8^kMqVi6MRUwlwZ6l&X}dzRBVXq!8XWc z_CbmX*>t>|Ngdk9fE8NtGcgZy-jA!J#m^8k$=~)s(uE2{PwZ&gcTT`UBZrOh6 zI~nl>I5X#(qUU%vshA$U;P#{U`)Kb^6pl5|X_0eGF^*OEY!r8l7qr@S8jxKZI_N&I zIj+^z4u&~$2nbJOG`1KO_*yHmvmpNI?v0eJy`s^HTj0-OE9(56;-wnc0rNA{1h3U-E!RvsND4BaytVdtLOvmpmohd!dvfrRO2Yg7-0cB1+#S4lByWP!*$Flr zVb`4LaJ~@#icC004Qwgd#$gtCyHzIcjQH^yXI%3fECSPKhM?y~Wb3Ug&6!nOda^pR zNaGFh@B3vK%y<;O9t=MfOVYY|CiUqg{yoaPdF}`0RGj8Ja|Ti2ty`1qANRyquFbD) zkPU0|4B2CR6;sUXTUxD!LTqnu)~#c6St#|6M@7FQk5hOY;Fc-{b>|M{&^mMsfYqmy z+K5=Jkdvn`P$GH`WB^&O1b_c=Ow)JWjVQLOmICL`_h;1jAl_3>^7l+ymR z4t)N9M4((Ils&co#w07$w{ydf&O+(UY@g7JIhev1FQ-vme2{#qKu{>F!g;AP%FxJ+ zn0FAK(~=pma#S2lFJ%HIZ_NJs;`jFbz%LW6Va?qy@yccevX2EvK(_;C4Xl7)Z_n9L zgY@VmQ~GVYF}u@YDK>BFseSah=3G(QPkdqs4wNV*81av*S&Epk`8N^ASm`nU9MlIei6fXu2Qo=GBGdJlY(wCPSTDXx7!H z4gV4CG)hO%rv4J?^3wEbte!`#NE6Yl?$hNc7v$ho6a5=0iuk0DKKR32?02V?2i|hm z4%2aw%&!u;lg>6^qwhAq!)p>2C;1nSq+fjs++khYi&S1QPo!MzplQ1-uJm0K+&D!p zp$ab=D@??5;;{0iMe$i+^H>UB<~G~#Fu_bB8GYCcqQRgmGi{~|`2JrDDHnYRPJq(- zhLw9=-H*+gnk3==^5Lqd^@hRFZOP8)(SV(r$0V0V=1G(Wsai-ttz`-+&BlL3#!;=|5R%GA-KH3%7xVL z+5Tvf5PJQ+vvAMXO(A^7J!9#u$&M1X$e97?UrnFp9pjx}tjXWonv6gR@aojBwYyE; zJLSJ`9{p#_JkWRdxoHF|2gk_Ui2)QQ%BHmp?bg@{Hm|i&w5ea*0d3nl56^=mso3DX zy7*-DzmV^+mMzHg%dvg%`fomcU66M_PVG?F>n8Gbp&Ji12&-AwL}E?Yb&H?O1VylZ zp;QPxb5!!EQ^ic2nSS3{`HsL2!R2Zedz75T*jqP?^izU@A)dkp{&YQzL;DeBDP;6l zm+~$=L=rE=+k=y5MRzP4rGtZ~xjA3UOlqx7u{nl-W;yWke-ujw`92%KU^mOuJj8}j zM$Za{40r(&jGesMMI=zx{4?_J`Dc({%8KsivbNFBE+vx%IGUu4sEKZHR|a_W!kJo6 z^z=CU8mmzY=pOf+-EupF2DuW%bL-`t3kB6>b2FdQr6@BtF3skBzQvzA=9KmCAKtB1 z@ESzi>Z@9G9?IZYP(ELlHO}5=_`zLw{|!9G*1QefLGdX+MBuqwvbnMv{{R1PWp(%N zF?sg#pI-1cQ1mCMA-z#Er=CI~X2nYLSd>oOMt`iBJ)fYJ;D3i%$+wkc*yKGb?F8(bE15`6GdD%mr>!GE;8T#e#{3TT9Q0F-*> zI~O=KhBW1lKBTK!b48&q;u<=K7t3F18vKSb34y0Zy#wD%;;+38H`EfY_OEIYcKAZ{ z9QUUt63Jc{y%YmQ4cn&5I&8;I^{jNX3iUSXzt)oYAi~gG)mQLIqIky2>c+X}?Ehye zHCbHYqYUMDpVnVOXe(*`>OUT86UvRvbghL1AzHMoo;=kMb#!9t`FQk0O$hB;wRwY+ z`HF|hB6Yt}IXf)d{87MKJnZT=R~+@FtpP+s&!bsN4h%c_a78LCPpJ_E!2$`cAqE;U zfNvQCBEO9xcKF@wo+CG9f{ooiV8;Th{Vs9&C>ayVF`^H&ni5DHXgqWIO*RBDUa}4> zmrL4i&s8F<0nB44TqUX87iB;c#VV2CFV}-9jEKs(DxU=%z4q;y9WSFos3s7*4wU#H)}MD(=VAU^b0vHKD9gL7Tr%8M3q@4%i;i2RVY| ztjNs+7h-;UcP9GZ+UN;6=2Trd^(KDAf@V*gAeyAUQT7V}qXm?G@0~&@Sx- zf+u<|PEUu@bnRVR#{u#`>r;TwchT+1hM%2uJLr(}SMuF#77pvBtG>jo$_5uLA_onm z3NY}7Fn$1D{2~R$ihjZqDhcl~%mkZ!P7LSrM-h940#1yy9)_Os8R8uXUFv`UD2p&) z>MFw~qMi-pb_r?vy3ojm~SYj=czPv|IJo zgts@I5l|#{6nZPDuviP4x#+a@EpUXXWdJ`=VL1C`o6mUtm|!1S^*}_&19^W%92}C7 zEuh!PFYH!myGn6XA;0uzLLCOYV$8-DDseq?v_1N0I1Eh(HPTN3^^}T(X9zIu48m=( zDTl{tj7P{625@$#Z#nx<$Dj!`5$j%HFSNL9A7y8dD{@4H(FX(!3P6#Q%aA-!-6UbF z&1TA|%B8v+i99@$RmFcm!Z?Ss*Hm7PVqUQdLR-*we&ei$b`Zy&U-M#B{K=PFvJy}7 zuE?aN(0iSDX>z4rmabTa%X#f-Nv!1ita*D1*|E2J`72zt^7{&pNBnbVzY%w|io*si zIzXFeRSpOI>CFigi!dOq6ON(Hi>da~KlLeuJ z0Q@xj`Ir=HgqOFfNNFXq#ZDgB6%|^Kp_$0w@<5A|(j-2QGl%EbT-}V1F%E)K zvX-e7>-BLjo?zKWU6Z9@Q^3~00000000000ssI207Qr7J`^wm01yBG0A+Y(0Pu78jcRsu@Q^3~00000 n000000ssI202+wpJ`^wm01yBG0BUe&0PuqWlf*rH06+%-=+>2Z literal 0 HcmV?d00001 diff --git a/tests/TestArchives/Archives/Rar5.comment.rar b/tests/TestArchives/Archives/Rar5.comment.rar new file mode 100644 index 0000000000000000000000000000000000000000..d3a65de9527e808943bb6242256c2f4f97204793 GIT binary patch literal 60112 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 Date: Mon, 4 Dec 2023 20:28:16 +0100 Subject: [PATCH 0008/1333] Resharpier fix --- src/SharpCompress/Common/Rar/RarVolume.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/SharpCompress/Common/Rar/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index 7be719ec..da42ff24 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using SharpCompress.Common.Rar.Headers; using SharpCompress.IO; using SharpCompress.Readers; @@ -70,11 +71,7 @@ public abstract class RarVolume : Volume var part = CreateFilePart(lastMarkHeader!, fh); var buffer = new byte[fh.CompressedSize]; part.GetCompressedStream().Read(buffer, 0, buffer.Length); - Comment = System.Text.Encoding.UTF8.GetString( - buffer, - 0, - buffer.Length - 1 - ); + Comment = Encoding.UTF8.GetString(buffer, 0, buffer.Length - 1); } } break; From 18c7f580939ca745d9a26165f6d6f8cd9aa6ec44 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Mon, 4 Dec 2023 22:35:11 +0100 Subject: [PATCH 0009/1333] Handle tar files generated with tar -H oldgnu that has large uid/gid values --- .../Common/Tar/Headers/TarHeader.cs | 24 +++++++++++++++--- .../SharpCompress.Test/Tar/TarReaderTests.cs | 3 +++ tests/TestArchives/Archives/Tar.oldgnu.tar.gz | Bin 0 -> 61354 bytes 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/TestArchives/Archives/Tar.oldgnu.tar.gz diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index ef86ab00..0e379e6b 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System; using System.Buffers.Binary; @@ -132,8 +132,8 @@ internal sealed class TarHeader Mode |= 0b1_000_000_000; } - UserId = ReadAsciiInt64Base8(buffer, 108, 7); - GroupId = ReadAsciiInt64Base8(buffer, 116, 7); + UserId = ReadAsciiInt64Base8oldGnu(buffer, 108, 7); + GroupId = ReadAsciiInt64Base8oldGnu(buffer, 116, 7); var unixTimeStamp = ReadAsciiInt64Base8(buffer, 136, 11); LastModifiedTime = EPOCH.AddSeconds(unixTimeStamp).ToLocalTime(); @@ -249,6 +249,24 @@ internal sealed class TarHeader return Convert.ToInt64(s, 8); } + private static long ReadAsciiInt64Base8oldGnu(byte[] buffer, int offset, int count) + { + if (buffer[offset] == 0x80 && buffer[offset + 1] == 0x00) + { + return buffer[offset + 4] << 24 + | buffer[offset + 5] << 16 + | buffer[offset + 6] << 8 + | buffer[offset + 7]; + } + var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls(); + + if (string.IsNullOrEmpty(s)) + { + return 0; + } + return Convert.ToInt64(s, 8); + } + private static long ReadAsciiInt64(byte[] buffer, int offset, int count) { var s = Encoding.UTF8.GetString(buffer, offset, count).TrimNulls(); diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index 218eb43f..4952b702 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -56,6 +56,9 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_Xz_Reader() => Read("Tar.tar.xz", CompressionType.Xz); + [Fact] + public void Tar_GZip_OldGnu_Reader() => Read("Tar.oldgnu.tar.gz", CompressionType.GZip); + [Fact] public void Tar_BZip2_Entry_Stream() { diff --git a/tests/TestArchives/Archives/Tar.oldgnu.tar.gz b/tests/TestArchives/Archives/Tar.oldgnu.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..fbffb7a2d348fec7606819aec17ccaa045317b6d GIT binary patch literal 61354 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 Date: Sat, 9 Dec 2023 13:41:35 +0100 Subject: [PATCH 0010/1333] LZMA EOS marker detection --- .../Compressors/LZMA/LzmaStream.cs | 13 +++++++++++-- .../SevenZip/SevenZipArchiveTests.cs | 3 +++ tests/TestArchives/Archives/7Zip.eos.7z | Bin 0 -> 58811 bytes 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/TestArchives/Archives/7Zip.eos.7z diff --git a/src/SharpCompress/Compressors/LZMA/LzmaStream.cs b/src/SharpCompress/Compressors/LZMA/LzmaStream.cs index 701b8e64..8e7d4adc 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaStream.cs @@ -207,14 +207,23 @@ public class LzmaStream : Stream if (_availableBytes == 0 && !_uncompressedChunk) { - _rangeDecoder.ReleaseStream(); + // Check range corruption scenario if ( !_rangeDecoder.IsFinished || (_rangeDecoderLimit >= 0 && _rangeDecoder._total != _rangeDecoderLimit) ) { - throw new DataErrorException(); + // Stream might have End Of Stream marker + _outWindow.SetLimit(toProcess + 1); + if (!_decoder.Code(_dictionarySize, _outWindow, _rangeDecoder)) + { + _rangeDecoder.ReleaseStream(); + throw new DataErrorException(); + } } + + _rangeDecoder.ReleaseStream(); + _inputPosition += _rangeDecoder._total; if (_outWindow.HasPending) { diff --git a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs index e77e288c..184559d1 100644 --- a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs +++ b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs @@ -135,6 +135,9 @@ public class SevenZipArchiveTests : ArchiveTests ) ); + [Fact] + public void SevenZipArchive_EOS_FileRead() => ArchiveFileRead("7Zip.eos.7z"); + [Fact] public void SevenZipArchive_Delta_FileRead() => ArchiveFileRead("7Zip.delta.7z"); diff --git a/tests/TestArchives/Archives/7Zip.eos.7z b/tests/TestArchives/Archives/7Zip.eos.7z new file mode 100644 index 0000000000000000000000000000000000000000..2fe951ad48fc3d2d75ebd7f752991efa1690378d GIT binary patch literal 58811 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 Date: Mon, 11 Dec 2023 09:35:30 +0000 Subject: [PATCH 0011/1333] Bump actions/setup-dotnet from 3 to 4 Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3 to 4. - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](https://github.com/actions/setup-dotnet/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dotnetcore.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 4486b23f..63da3a2e 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-dotnet@v3 + - uses: actions/setup-dotnet@v4 with: dotnet-version: 7.0.x - name: NuGet Caching From d678275dee2ffa823c02b8845031498c8e961cec Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Sat, 16 Dec 2023 02:53:09 +0100 Subject: [PATCH 0012/1333] Implement RAR5 decryption --- .../Archives/Rar/SeekableFilePart.cs | 11 +- src/SharpCompress/Common/Rar/CryptKey3.cs | 87 + src/SharpCompress/Common/Rar/CryptKey5.cs | 97 + .../Common/Rar/Headers/ArchiveCryptHeader.cs | 42 +- .../Common/Rar/Headers/FileHeader.cs | 61 +- src/SharpCompress/Common/Rar/Headers/Flags.cs | 11 + .../Common/Rar/Headers/RarHeader.cs | 2 +- .../Common/Rar/Headers/RarHeaderFactory.cs | 32 +- src/SharpCompress/Common/Rar/ICryptKey.cs | 12 + .../Common/Rar/Rar5CryptoInfo.cs | 59 + .../Common/Rar/RarCryptoBinaryReader.cs | 45 +- .../Common/Rar/RarCryptoWrapper.cs | 16 +- src/SharpCompress/Common/Rar/RarRijndael.cs | 114 - src/SharpCompress/Crypto/BlockTransformer.cs | 32 + src/SharpCompress/Crypto/RijndaelEngine.cs | 1909 ----------------- .../SharpCompress.Test/Rar/RarArchiveTests.cs | 32 +- 16 files changed, 425 insertions(+), 2137 deletions(-) create mode 100644 src/SharpCompress/Common/Rar/CryptKey3.cs create mode 100644 src/SharpCompress/Common/Rar/CryptKey5.cs create mode 100644 src/SharpCompress/Common/Rar/ICryptKey.cs create mode 100644 src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs delete mode 100644 src/SharpCompress/Common/Rar/RarRijndael.cs create mode 100644 src/SharpCompress/Crypto/BlockTransformer.cs delete mode 100644 src/SharpCompress/Crypto/RijndaelEngine.cs diff --git a/src/SharpCompress/Archives/Rar/SeekableFilePart.cs b/src/SharpCompress/Archives/Rar/SeekableFilePart.cs index 08aceb13..13048d4c 100644 --- a/src/SharpCompress/Archives/Rar/SeekableFilePart.cs +++ b/src/SharpCompress/Archives/Rar/SeekableFilePart.cs @@ -25,10 +25,19 @@ internal class SeekableFilePart : RarFilePart internal override Stream GetCompressedStream() { stream.Position = FileHeader.DataStartPosition; + if (FileHeader.R4Salt != null) { - return new RarCryptoWrapper(stream, password!, FileHeader.R4Salt); + var cryptKey = new CryptKey3(password!); + return new RarCryptoWrapper(stream, FileHeader.R4Salt, cryptKey); } + + if (FileHeader.Rar5CryptoInfo != null) + { + var cryptKey = new CryptKey5(password!, FileHeader.Rar5CryptoInfo); + return new RarCryptoWrapper(stream, FileHeader.Rar5CryptoInfo.Salt, cryptKey); + } + return stream; } diff --git a/src/SharpCompress/Common/Rar/CryptKey3.cs b/src/SharpCompress/Common/Rar/CryptKey3.cs new file mode 100644 index 00000000..254c692f --- /dev/null +++ b/src/SharpCompress/Common/Rar/CryptKey3.cs @@ -0,0 +1,87 @@ +#nullable disable + +using System.Security.Cryptography; +using System.Text; +using SharpCompress.Common.Rar.Headers; + +namespace SharpCompress.Common.Rar; + +internal class CryptKey3 : ICryptKey +{ + const int AES_128 = 128; + + private string _password; + + public CryptKey3(string password) + { + _password = password ?? ""; + } + + public ICryptoTransform Transformer(byte[] salt) + { + var aesIV = new byte[EncryptionConstV5.SIZE_INITV]; + + var rawLength = 2 * _password.Length; + var rawPassword = new byte[rawLength + EncryptionConstV5.SIZE_SALT30]; + var passwordBytes = Encoding.UTF8.GetBytes(_password); + for (var i = 0; i < _password.Length; i++) + { + rawPassword[i * 2] = passwordBytes[i]; + rawPassword[(i * 2) + 1] = 0; + } + + for (var i = 0; i < salt.Length; i++) + { + rawPassword[i + rawLength] = salt[i]; + } + + var msgDigest = SHA1.Create(); + const int noOfRounds = (1 << 18); + const int iblock = 3; + + byte[] digest; + var data = new byte[(rawPassword.Length + iblock) * noOfRounds]; + + //TODO slow code below, find ways to optimize + for (var i = 0; i < noOfRounds; i++) + { + rawPassword.CopyTo(data, i * (rawPassword.Length + iblock)); + + data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i; + data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8); + data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)(i >> 16); + + if (i % (noOfRounds / EncryptionConstV5.SIZE_INITV) == 0) + { + digest = msgDigest.ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock)); + aesIV[i / (noOfRounds / EncryptionConstV5.SIZE_INITV)] = digest[19]; + } + } + digest = msgDigest.ComputeHash(data); + //slow code ends + + var aesKey = new byte[EncryptionConstV5.SIZE_INITV]; + for (var i = 0; i < 4; i++) + { + for (var j = 0; j < 4; j++) + { + aesKey[(i * 4) + j] = (byte)( + ( + ((digest[i * 4] * 0x1000000) & 0xff000000) + | (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000) + | (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00) + | (uint)(digest[(i * 4) + 3] & 0xff) + ) >> (j * 8) + ); + } + } + + var aes = Aes.Create(); + aes.KeySize = AES_128; + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.None; + aes.Key = aesKey; + aes.IV = aesIV; + return aes.CreateDecryptor(); + } +} diff --git a/src/SharpCompress/Common/Rar/CryptKey5.cs b/src/SharpCompress/Common/Rar/CryptKey5.cs new file mode 100644 index 00000000..46044368 --- /dev/null +++ b/src/SharpCompress/Common/Rar/CryptKey5.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using SharpCompress.Common.Rar.Headers; + +namespace SharpCompress.Common.Rar; + +internal class CryptKey5 : ICryptKey +{ + const int AES_256 = 256; + const int DERIVED_KEY_LENGTH = 0x10; + const int SHA256_DIGEST_SIZE = 32; + + private string _password; + private Rar5CryptoInfo _cryptoInfo; + private byte[] _pswCheck = { }; + private byte[] _hashKey = { }; + + public CryptKey5(string password, Rar5CryptoInfo rar5CryptoInfo) + { + _password = password; + _cryptoInfo = rar5CryptoInfo; + } + + public byte[] PswCheck => _pswCheck; + + public byte[] HashKey => _hashKey; + + private static List GenerateRarPBKDF2Key( + string password, + byte[] salt, + int iterations, + int keyLength + ) + { + using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password))) + { + byte[] block = hmac.ComputeHash(salt); + byte[] finalHash = (byte[])block.Clone(); + + var loop = new int[] { iterations, 17, 17 }; + var res = new List { }; + + for (int x = 0; x < 3; x++) + { + for (int i = 1; i < loop[x]; i++) + { + block = hmac.ComputeHash(block); + for (int j = 0; j < finalHash.Length; j++) + { + finalHash[j] ^= block[j]; + } + } + + res.Add((byte[])finalHash.Clone()); + } + + return res; + } + } + + public ICryptoTransform Transformer(byte[] salt) + { + int iterations = (1 << _cryptoInfo.LG2Count); // Adjust the number of iterations as needed + + var salt_rar5 = salt.Concat(new byte[] { 0, 0, 0, 1 }); + var derivedKey = GenerateRarPBKDF2Key( + _password, + salt_rar5.ToArray(), + iterations, + DERIVED_KEY_LENGTH + ); + + _hashKey = derivedKey[1]; + + _pswCheck = new byte[EncryptionConstV5.SIZE_PSWCHECK]; + + for (int i = 0; i < SHA256_DIGEST_SIZE; i++) + { + _pswCheck[i % EncryptionConstV5.SIZE_PSWCHECK] ^= derivedKey[2][i]; + } + + if (_cryptoInfo.UsePswCheck && !_cryptoInfo.PswCheck.SequenceEqual(_pswCheck)) + { + throw new CryptographicException("The password did not match."); + } + + var aes = Aes.Create(); + aes.KeySize = AES_256; + aes.Mode = CipherMode.CBC; + aes.Padding = PaddingMode.None; + aes.Key = derivedKey[0]; + aes.IV = _cryptoInfo.InitV; + return aes.CreateDecryptor(); + } +} diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs index 619e8fc9..a907002d 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs @@ -1,50 +1,22 @@ #nullable disable +using System; +using System.Security.Cryptography; + using SharpCompress.IO; +using SharpCompress.Common.Rar.Headers; namespace SharpCompress.Common.Rar.Headers; internal class ArchiveCryptHeader : RarHeader { - private const int CRYPT_VERSION = 0; // Supported encryption version. - private const int SIZE_SALT50 = 16; - private const int SIZE_PSWCHECK = 8; - private const int SIZE_PSWCHECK_CSUM = 4; - private const int CRYPT5_KDF_LG2_COUNT_MAX = 24; // LOG2 of maximum accepted iteration count. - - private bool _usePswCheck; - private uint _lg2Count; // Log2 of PBKDF2 repetition count. - private byte[] _salt; - private byte[] _pswCheck; - private byte[] _pswCheckCsm; - public ArchiveCryptHeader(RarHeader header, RarCrcBinaryReader reader) : base(header, reader, HeaderType.Crypt) { } + public Rar5CryptoInfo CryptInfo = new Rar5CryptoInfo(); + protected override void ReadFinish(MarkingBinaryReader reader) { - var cryptVersion = reader.ReadRarVIntUInt32(); - if (cryptVersion > CRYPT_VERSION) - { - //error? - return; - } - var encryptionFlags = reader.ReadRarVIntUInt32(); - _usePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK); - _lg2Count = reader.ReadRarVIntByte(1); - - //UsePswCheck = HasHeaderFlag(EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK); - if (_lg2Count > CRYPT5_KDF_LG2_COUNT_MAX) - { - //error? - return; - } - - _salt = reader.ReadBytes(SIZE_SALT50); - if (_usePswCheck) - { - _pswCheck = reader.ReadBytes(SIZE_PSWCHECK); - _pswCheckCsm = reader.ReadBytes(SIZE_PSWCHECK_CSUM); - } + CryptInfo = new Rar5CryptoInfo(reader,false); } } diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index 0663baf9..3775f036 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -2,6 +2,8 @@ using System; using System.IO; +using System.Linq; +using System.Security.Cryptography; using System.Text; using SharpCompress.IO; #if !Rar2017_64bit @@ -103,7 +105,13 @@ internal class FileHeader : RarHeader throw new InvalidFormatException("rar5 header size / extra size inconsistency"); } - isEncryptedRar5 = false; + const ushort FHEXTRA_CRYPT = 0x01; + const ushort FHEXTRA_HASH = 0x02; + const ushort FHEXTRA_HTIME = 0x03; + // const ushort FHEXTRA_VERSION = 0x04; + // const ushort FHEXTRA_REDIR = 0x05; + // const ushort FHEXTRA_UOWNER = 0x06; + // const ushort FHEXTRA_SUBDATA = 0x07; while (RemainingHeaderBytes(reader) > 0) { @@ -113,21 +121,34 @@ internal class FileHeader : RarHeader switch (type) { //TODO - case 1: // file encryption + case FHEXTRA_CRYPT: // file encryption { - isEncryptedRar5 = true; + Rar5CryptoInfo = new Rar5CryptoInfo(reader, true); - //var version = reader.ReadRarVIntByte(); - //if (version != 0) throw new InvalidFormatException("unknown encryption algorithm " + version); + if (Rar5CryptoInfo.PswCheck.All(singleByte => singleByte == 0)) + { + Rar5CryptoInfo = null; + } } break; - // case 2: // file hash - // { - // - // } - // break; - case 3: // file time + case FHEXTRA_HASH: + + { + const uint FHEXTRA_HASH_BLAKE2 = 0x0; + const uint HASH_BLAKE2 = 0x03; + const int BLAKE2_DIGEST_SIZE = 0x20; + if ((uint)reader.ReadRarVInt() == FHEXTRA_HASH_BLAKE2) + { + var hash = HASH_BLAKE2; + var digest = reader.ReadBytes(BLAKE2_DIGEST_SIZE); + + throw new InvalidFormatException("Not yet implemented " + hash); + } + // enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2}; + } + break; + case FHEXTRA_HTIME: // file time { var flags = reader.ReadRarVIntUInt16(); @@ -147,22 +168,22 @@ internal class FileHeader : RarHeader } break; //TODO - // case 4: // file version + // case FHEXTRA_VERSION: // file version // { // // } // break; - // case 5: // file system redirection + // case FHEXTRA_REDIR: // file system redirection // { // // } // break; - // case 6: // unix owner + // case FHEXTRA_UOWNER: // unix owner // { // // } // break; - // case 7: // service data + // case FHEXTRA_SUBDATA: // service data // { // // } @@ -254,7 +275,6 @@ internal class FileHeader : RarHeader var fileNameBytes = reader.ReadBytes(nameSize); - const int saltSize = 8; const int newLhdSize = 32; switch (HeaderCode) @@ -292,7 +312,7 @@ internal class FileHeader : RarHeader var datasize = HeaderSize - newLhdSize - nameSize; if (HasFlag(FileFlagsV4.SALT)) { - datasize -= saltSize; + datasize -= EncryptionConstV5.SIZE_SALT30; } if (datasize > 0) { @@ -313,7 +333,7 @@ internal class FileHeader : RarHeader if (HasFlag(FileFlagsV4.SALT)) { - R4Salt = reader.ReadBytes(saltSize); + R4Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT30); } if (HasFlag(FileFlagsV4.EXT_TIME)) { @@ -431,7 +451,7 @@ internal class FileHeader : RarHeader internal size_t WindowSize { get; private set; } internal byte[] R4Salt { get; private set; } - + internal Rar5CryptoInfo Rar5CryptoInfo { get; private set; } private byte HostOs { get; set; } internal uint FileAttributes { get; private set; } internal long CompressedSize { get; private set; } @@ -449,8 +469,7 @@ internal class FileHeader : RarHeader public bool IsDirectory => HasFlag(IsRar5 ? FileFlagsV5.DIRECTORY : FileFlagsV4.DIRECTORY); - private bool isEncryptedRar5 = false; - public bool IsEncrypted => IsRar5 ? isEncryptedRar5 : HasFlag(FileFlagsV4.PASSWORD); + public bool IsEncrypted => IsRar5 ? Rar5CryptoInfo != null : HasFlag(FileFlagsV4.PASSWORD); internal DateTime? FileLastModifiedTime { get; private set; } diff --git a/src/SharpCompress/Common/Rar/Headers/Flags.cs b/src/SharpCompress/Common/Rar/Headers/Flags.cs index 5a52f001..3414d1a3 100644 --- a/src/SharpCompress/Common/Rar/Headers/Flags.cs +++ b/src/SharpCompress/Common/Rar/Headers/Flags.cs @@ -50,6 +50,17 @@ internal static class EncryptionFlagsV5 public const uint FHEXTRA_CRYPT_HASHMAC = 0x02; } +internal static class EncryptionConstV5 +{ + public const int VERSION = 0; + public const uint CRYPT5_KDF_LG2_COUNT_MAX = 0x24; + public const int SIZE_SALT30 = 0x08; + public const int SIZE_SALT50 = 0x10; + public const int SIZE_INITV = 0x10; + public const int SIZE_PSWCHECK = 0x08; + public const int SIZE_PSWCHECK_CSUM = 0x04; +} + internal static class HeaderFlagsV5 { public const ushort HAS_EXTRA = 0x0001; diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs index 81002fc4..0d8648e8 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 de44e309..e38cb629 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; using System.IO; +using System.Linq; +using SharpCompress.Common.Rar; using SharpCompress.IO; using SharpCompress.Readers; @@ -9,6 +11,8 @@ public class RarHeaderFactory { private bool _isRar5; + private Rar5CryptoInfo? _cryptInfo; + public RarHeaderFactory(StreamingMode mode, ReaderOptions options) { StreamingMode = mode; @@ -53,7 +57,19 @@ public class RarHeaderFactory "Encrypted Rar archive has no password specified." ); } - reader = new RarCryptoBinaryReader(stream, Options.Password); + + if (_isRar5 && _cryptInfo != null) + { + _cryptInfo.ReadInitV(new MarkingBinaryReader(stream)); + var _headerKey = new CryptKey5(Options.Password!, _cryptInfo); + + reader = new RarCryptoBinaryReader(stream, _headerKey, _cryptInfo.Salt); + } + else + { + var key = new CryptKey3(Options.Password); + reader = new RarCryptoBinaryReader(stream, key); + } } var header = RarHeader.TryReadBase(reader, _isRar5, Options.ArchiveEncoding); @@ -140,7 +156,7 @@ public class RarHeaderFactory { var ms = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize); - if (fh.R4Salt is null) + if (fh.R4Salt is null && fh.Rar5CryptoInfo is null) { fh.PackedStream = ms; } @@ -148,8 +164,10 @@ public class RarHeaderFactory { fh.PackedStream = new RarCryptoWrapper( ms, - Options.Password!, - fh.R4Salt + fh.R4Salt is null ? fh.Rar5CryptoInfo.Salt : fh.R4Salt, + fh.R4Salt is null + ? new CryptKey5(Options.Password!, fh.Rar5CryptoInfo) + : new CryptKey3(Options.Password!) ); } } @@ -168,9 +186,11 @@ public class RarHeaderFactory } case HeaderCodeV.RAR5_ARCHIVE_ENCRYPTION_HEADER: { - var ch = new ArchiveCryptHeader(header, reader); + var cryptoHeader = new ArchiveCryptHeader(header, reader); IsEncrypted = true; - return ch; + _cryptInfo = cryptoHeader.CryptInfo; + + return cryptoHeader; } default: { diff --git a/src/SharpCompress/Common/Rar/ICryptKey.cs b/src/SharpCompress/Common/Rar/ICryptKey.cs new file mode 100644 index 00000000..b4188a17 --- /dev/null +++ b/src/SharpCompress/Common/Rar/ICryptKey.cs @@ -0,0 +1,12 @@ +using System.IO; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +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 new file mode 100644 index 00000000..28053a3d --- /dev/null +++ b/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs @@ -0,0 +1,59 @@ +using System; +using System.Security.Cryptography; +using SharpCompress.Common.Rar.Headers; +using SharpCompress.IO; + +namespace SharpCompress.Common.Rar; + +internal class Rar5CryptoInfo +{ + public Rar5CryptoInfo() { } + + public Rar5CryptoInfo(MarkingBinaryReader reader, bool readInitV) + { + var cryptVersion = reader.ReadRarVIntUInt32(); + if (cryptVersion > EncryptionConstV5.VERSION) + { + throw new CryptographicException($"Unsupported crypto version of {cryptVersion}"); + } + var encryptionFlags = reader.ReadRarVIntUInt32(); + UsePswCheck = FlagUtility.HasFlag(encryptionFlags, EncryptionFlagsV5.CHFL_CRYPT_PSWCHECK); + LG2Count = reader.ReadRarVIntByte(1); + + if (LG2Count > EncryptionConstV5.CRYPT5_KDF_LG2_COUNT_MAX) + { + throw new CryptographicException($"Unsupported LG2 count of {LG2Count}."); + } + + Salt = reader.ReadBytes(EncryptionConstV5.SIZE_SALT50); + + if (readInitV) // File header needs to read IV here + { + ReadInitV(reader); + } + + if (UsePswCheck) + { + PswCheck = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK); + var _pswCheckCsm = reader.ReadBytes(EncryptionConstV5.SIZE_PSWCHECK_CSUM); + + var sha = SHA256.Create(); + UsePswCheck = sha.ComputeHash(PswCheck).AsSpan().StartsWith(_pswCheckCsm.AsSpan()); + } + } + + public void ReadInitV(MarkingBinaryReader reader) + { + InitV = reader.ReadBytes(EncryptionConstV5.SIZE_INITV); + } + + public bool UsePswCheck = false; + + public int LG2Count = 0; + + public byte[] InitV = { }; + + public byte[] Salt = { }; + + public byte[] PswCheck = { }; +} diff --git a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs index 0be6e74e..982821c3 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs @@ -1,27 +1,30 @@ -using System.Collections.Generic; +#nullable disable + +using System.Collections.Generic; using System.IO; +using SharpCompress.Common.Rar.Headers; +using SharpCompress.Crypto; namespace SharpCompress.Common.Rar; internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader { - private RarRijndael _rijndael; - private byte[] _salt; - private readonly string _password; + private BlockTransformer _rijndael; private readonly Queue _data = new Queue(); private long _readCount; - public RarCryptoBinaryReader(Stream stream, string password) + public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey) : base(stream) { - _password = password; + var salt = base.ReadBytes(EncryptionConstV5.SIZE_SALT30); + _readCount += EncryptionConstV5.SIZE_SALT30; + _rijndael = new BlockTransformer(cryptKey.Transformer(salt)); + } - // coderb: not sure why this was being done at this logical point - //SkipQueue(); - var salt = ReadBytes(8); - - _salt = salt; - _rijndael = RarRijndael.InitializeFrom(_password, salt); + public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey, byte[] salt) + : base(stream) + { + _rijndael = new BlockTransformer(cryptKey.Transformer(salt)); } // track read count ourselves rather than using the underlying stream since we buffer @@ -36,28 +39,14 @@ internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader public override void Mark() => _readCount = 0; - private bool UseEncryption => _salt != null; - public override byte ReadByte() { - if (UseEncryption) - { - return ReadAndDecryptBytes(1)[0]; - } - - _readCount++; - return base.ReadByte(); + return ReadAndDecryptBytes(1)[0]; } public override byte[] ReadBytes(int count) { - if (UseEncryption) - { - return ReadAndDecryptBytes(count); - } - - _readCount += count; - return base.ReadBytes(count); + return ReadAndDecryptBytes(count); } private byte[] ReadAndDecryptBytes(int count) diff --git a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index a1cee046..1907108c 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -2,20 +2,20 @@ using System; using System.Collections.Generic; using System.IO; +using SharpCompress.Crypto; + namespace SharpCompress.Common.Rar; internal sealed class RarCryptoWrapper : Stream { private readonly Stream _actualStream; - private readonly byte[] _salt; - private RarRijndael _rijndael; + private BlockTransformer _rijndael; private readonly Queue _data = new Queue(); - public RarCryptoWrapper(Stream actualStream, string password, byte[] salt) + public RarCryptoWrapper(Stream actualStream, byte[] salt, ICryptKey key) { _actualStream = actualStream; - _salt = salt; - _rijndael = RarRijndael.InitializeFrom(password ?? "", salt); + _rijndael = new BlockTransformer(key.Transformer(salt)); } public override void Flush() => throw new NotSupportedException(); @@ -26,10 +26,6 @@ internal sealed class RarCryptoWrapper : Stream public override int Read(byte[] buffer, int offset, int count) { - if (_salt is null) - { - return _actualStream.Read(buffer, offset, count); - } return ReadAndDecrypt(buffer, offset, count); } @@ -41,7 +37,7 @@ internal sealed class RarCryptoWrapper : Stream if (sizeToRead > 0) { var alignedSize = sizeToRead + ((~sizeToRead + 1) & 0xf); - Span cipherText = stackalloc byte[RarRijndael.CRYPTO_BLOCK_SIZE]; + Span cipherText = stackalloc byte[16]; for (var i = 0; i < alignedSize / 16; i++) { //long ax = System.currentTimeMillis(); diff --git a/src/SharpCompress/Common/Rar/RarRijndael.cs b/src/SharpCompress/Common/Rar/RarRijndael.cs deleted file mode 100644 index 94592639..00000000 --- a/src/SharpCompress/Common/Rar/RarRijndael.cs +++ /dev/null @@ -1,114 +0,0 @@ -#nullable disable - -using System; -using System.Security.Cryptography; -using System.Text; -using SharpCompress.Crypto; - -namespace SharpCompress.Common.Rar; - -internal class RarRijndael : IDisposable -{ - internal const int CRYPTO_BLOCK_SIZE = 16; - - private readonly string _password; - private readonly byte[] _salt; - private byte[] _aesInitializationVector; - private RijndaelEngine _rijndael; - - private RarRijndael(string password, byte[] salt) - { - _password = password; - _salt = salt; - } - - private void Initialize() - { - _rijndael = new RijndaelEngine(); - _aesInitializationVector = new byte[CRYPTO_BLOCK_SIZE]; - var rawLength = 2 * _password.Length; - var rawPassword = new byte[rawLength + 8]; - var passwordBytes = Encoding.UTF8.GetBytes(_password); - for (var i = 0; i < _password.Length; i++) - { - rawPassword[i * 2] = passwordBytes[i]; - rawPassword[(i * 2) + 1] = 0; - } - for (var i = 0; i < _salt.Length; i++) - { - rawPassword[i + rawLength] = _salt[i]; - } - - const int noOfRounds = (1 << 18); - const int iblock = 3; - byte[] digest; - var data = new byte[(rawPassword.Length + iblock) * noOfRounds]; - - //TODO slow code below, find ways to optimize - for (var i = 0; i < noOfRounds; i++) - { - rawPassword.CopyTo(data, i * (rawPassword.Length + iblock)); - - data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 0] = (byte)i; - data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 1] = (byte)(i >> 8); - data[(i * (rawPassword.Length + iblock)) + rawPassword.Length + 2] = (byte)( - i >> CRYPTO_BLOCK_SIZE - ); - - if (i % (noOfRounds / CRYPTO_BLOCK_SIZE) == 0) - { - digest = SHA1.Create() - .ComputeHash(data, 0, (i + 1) * (rawPassword.Length + iblock)); - _aesInitializationVector[i / (noOfRounds / CRYPTO_BLOCK_SIZE)] = digest[19]; - } - } - digest = SHA1.Create().ComputeHash(data); - //slow code ends - - var aesKey = new byte[CRYPTO_BLOCK_SIZE]; - for (var i = 0; i < 4; i++) - { - for (var j = 0; j < 4; j++) - { - aesKey[(i * 4) + j] = (byte)( - ( - ((digest[i * 4] * 0x1000000) & 0xff000000) - | (uint)((digest[(i * 4) + 1] * 0x10000) & 0xff0000) - | (uint)((digest[(i * 4) + 2] * 0x100) & 0xff00) - | (uint)(digest[(i * 4) + 3] & 0xff) - ) >> (j * 8) - ); - } - } - - _rijndael.Init(false, new KeyParameter(aesKey)); - } - - public static RarRijndael InitializeFrom(string password, byte[] salt) - { - var rijndael = new RarRijndael(password, salt); - rijndael.Initialize(); - return rijndael; - } - - public byte[] ProcessBlock(ReadOnlySpan 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/Crypto/BlockTransformer.cs b/src/SharpCompress/Crypto/BlockTransformer.cs new file mode 100644 index 00000000..bcb937d0 --- /dev/null +++ b/src/SharpCompress/Crypto/BlockTransformer.cs @@ -0,0 +1,32 @@ +#nullable disable + +using System; +using System.Security.Cryptography; + +namespace SharpCompress.Crypto; + +internal class BlockTransformer : IDisposable +{ + private ICryptoTransform _transform; + + public BlockTransformer(ICryptoTransform transformer) + { + _transform = transformer; + } + + public byte[] ProcessBlock(ReadOnlySpan cipherText) + { + var decryptedBytes = new byte[cipherText.Length]; + var bytes = _transform.TransformBlock( + cipherText.ToArray(), + 0, + cipherText.Length, + decryptedBytes, + 0 + ); + + return decryptedBytes; + } + + public void Dispose() { } +} diff --git a/src/SharpCompress/Crypto/RijndaelEngine.cs b/src/SharpCompress/Crypto/RijndaelEngine.cs deleted file mode 100644 index 98dd5bc1..00000000 --- a/src/SharpCompress/Crypto/RijndaelEngine.cs +++ /dev/null @@ -1,1909 +0,0 @@ -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/tests/SharpCompress.Test/Rar/RarArchiveTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs index 6496e15e..acc5bdc8 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs @@ -22,11 +22,16 @@ public class RarArchiveTests : ArchiveTests () => ReadRarPassword("Rar.encrypted_filesAndHeader.rar", null) ); - /*[Fact] - public void Rar5_EncryptedFileAndHeader_Archive() - { + [Fact] + public void Rar5_EncryptedFileAndHeader_Archive() => ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test"); - }*/ + + [Fact] + public void Rar5_EncryptedFileAndHeader_Archive_Err() => + Assert.Throws( + typeof(CryptographicException), + () => ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "failed") + ); [Fact] public void Rar5_EncryptedFileAndHeader_NoPasswordExceptionTest() => @@ -39,20 +44,23 @@ public class RarArchiveTests : ArchiveTests public void Rar_EncryptedFileOnly_Archive() => ReadRarPassword("Rar.encrypted_filesOnly.rar", "test"); - /*[Fact] - public void Rar5_EncryptedFileOnly_Archive() - { + [Fact] + public void Rar_EncryptedFileOnly_Archive_Err() => + Assert.Throws( + typeof(CryptographicException), + () => ReadRarPassword("Rar5.encrypted_filesOnly.rar", "failed") + ); + + [Fact] + public void Rar5_EncryptedFileOnly_Archive() => ReadRarPassword("Rar5.encrypted_filesOnly.rar", "test"); - }*/ [Fact] public void Rar_Encrypted_Archive() => ReadRarPassword("Rar.Encrypted.rar", "test"); - /*[Fact] - public void Rar5_Encrypted_Archive() - { + [Fact] + public void Rar5_Encrypted_Archive() => ReadRarPassword("Rar5.encrypted_filesAndHeader.rar", "test"); - }*/ private void ReadRarPassword(string testArchive, string? password) { From 619e44b30f571999b83e544af7f634341407df35 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Sat, 16 Dec 2023 03:08:51 +0100 Subject: [PATCH 0013/1333] CSharpier fixes --- src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs | 5 ++--- src/SharpCompress/Common/Rar/ICryptKey.cs | 6 +----- src/SharpCompress/Common/Rar/RarCryptoWrapper.cs | 1 - 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs index a907002d..529b85cc 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs @@ -2,9 +2,8 @@ using System; using System.Security.Cryptography; - -using SharpCompress.IO; using SharpCompress.Common.Rar.Headers; +using SharpCompress.IO; namespace SharpCompress.Common.Rar.Headers; @@ -17,6 +16,6 @@ internal class ArchiveCryptHeader : RarHeader protected override void ReadFinish(MarkingBinaryReader reader) { - CryptInfo = new Rar5CryptoInfo(reader,false); + CryptInfo = new Rar5CryptoInfo(reader, false); } } diff --git a/src/SharpCompress/Common/Rar/ICryptKey.cs b/src/SharpCompress/Common/Rar/ICryptKey.cs index b4188a17..94f068f5 100644 --- a/src/SharpCompress/Common/Rar/ICryptKey.cs +++ b/src/SharpCompress/Common/Rar/ICryptKey.cs @@ -1,11 +1,7 @@ -using System.IO; -using System.Collections.Generic; -using System.Linq; using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; namespace SharpCompress.Common.Rar; + internal interface ICryptKey { ICryptoTransform Transformer(byte[] salt); diff --git a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index 1907108c..5f5e8de7 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; - using SharpCompress.Crypto; namespace SharpCompress.Common.Rar; From c0e01ac13201493bceacb8683291b907e4cf627d Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:01:54 +0000 Subject: [PATCH 0014/1333] Use dotnet 8 and update deps --- global.json | 2 +- .../Common/Zip/WinzipAesEncryptionData.cs | 16 ++++++++-------- src/SharpCompress/SharpCompress.csproj | 12 ++++++------ .../SharpCompress.Test/SharpCompress.Test.csproj | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/global.json b/global.json index e6e67e4e..d3492186 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "7.0.101", + "version": "8.0.101", "rollForward": "latestFeature" } } diff --git a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs index 251b919e..50cda154 100644 --- a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs @@ -48,15 +48,15 @@ internal class WinzipAesEncryptionData private void Initialize() { -#if NET7_0 - var rfc2898 = new Rfc2898DeriveBytes( - _password, - _salt, - RFC2898_ITERATIONS, - HashAlgorithmName.SHA1 - ); -#else +#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 ??? diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 2c38668c..d3719849 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -6,7 +6,7 @@ 0.34.2 0.34.2 Adam Hathcock - net462;netstandard2.0;netstandard2.1;net6.0;net7.0 + net462;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0 SharpCompress ../../SharpCompress.snk true @@ -27,18 +27,18 @@ - - + + - + - + - + diff --git a/tests/SharpCompress.Test/SharpCompress.Test.csproj b/tests/SharpCompress.Test/SharpCompress.Test.csproj index c20664a7..e1f75276 100644 --- a/tests/SharpCompress.Test/SharpCompress.Test.csproj +++ b/tests/SharpCompress.Test/SharpCompress.Test.csproj @@ -1,6 +1,6 @@  - net7.0;net462 + net8.0;net462 SharpCompress.Test SharpCompress.Test @@ -8,13 +8,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + From ea3a96eead729e694ecd82be5642bad650434b5f Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:04:04 +0000 Subject: [PATCH 0015/1333] update and rerun csharpier --- .config/dotnet-tools.json | 2 +- global.json | 2 +- src/SharpCompress/Archives/ArchiveFactory.cs | 3 +-- src/SharpCompress/Archives/Rar/RarArchive.cs | 6 ++--- .../Archives/SevenZip/SevenZipArchive.cs | 12 ++++------ .../Common/Zip/WinzipAesEncryptionData.cs | 10 ++++---- .../Common/Zip/ZipHeaderFactory.cs | 6 ++--- .../Compressors/Rar/UnpackV1/Unpack.cs | 7 +++--- src/SharpCompress/Writers/WriterFactory.cs | 4 +--- .../SharpCompress.Test/Tar/TarArchiveTests.cs | 6 ++--- .../SharpCompress.Test/Tar/TarReaderTests.cs | 23 +++++++----------- tests/SharpCompress.Test/TestBase.cs | 8 +++---- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 24 +++++++++---------- 13 files changed, 51 insertions(+), 62 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 3cf567c5..9e8f2784 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "csharpier": { - "version": "0.26.1", + "version": "0.26.7", "commands": [ "dotnet-csharpier" ] diff --git a/global.json b/global.json index d3492186..391ba3c2 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.101", + "version": "8.0.100", "rollForward": "latestFeature" } } diff --git a/src/SharpCompress/Archives/ArchiveFactory.cs b/src/SharpCompress/Archives/ArchiveFactory.cs index 2e859599..3f479327 100644 --- a/src/SharpCompress/Archives/ArchiveFactory.cs +++ b/src/SharpCompress/Archives/ArchiveFactory.cs @@ -26,8 +26,7 @@ public static class ArchiveFactory public static IWritableArchive Create(ArchiveType type) { var factory = Factory - .Factories - .OfType() + .Factories.OfType() .FirstOrDefault(item => item.KnownArchiveType == type); if (factory != null) diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index e9c580fe..29d733f6 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -40,9 +40,9 @@ public class RarArchive : AbstractArchive streams[1].Position = 0; SrcStream.Position = 0; - return srcStream - .Streams - .Select(a => new StreamRarArchiveVolume(a, ReaderOptions, idx++)); + return srcStream.Streams.Select( + a => new StreamRarArchiveVolume(a, ReaderOptions, idx++) + ); } else //split mode or single file { diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index 99fe962d..7577b43d 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -236,13 +236,11 @@ public class SevenZipArchive : AbstractArchive x.Type == ExtraDataType.WinZipAes); + var data = entryHeader.Extra.SingleOrDefault( + x => x.Type == ExtraDataType.WinZipAes + ); if (data != null) { var keySize = (WinzipAesKeySize)data.DataBytes[4]; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs index 728d0f85..2ca62d6b 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs @@ -1269,10 +1269,9 @@ internal sealed partial class Unpack : BitInput, IRarUnpack if (CurSize < DataSize + RarVM.VM_FIXEDGLOBALSIZE) { // StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize); - StackFilter - .Program - .GlobalData - .SetSize(DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize); + StackFilter.Program.GlobalData.SetSize( + DataSize + RarVM.VM_FIXEDGLOBALSIZE - CurSize + ); } var offset = RarVM.VM_FIXEDGLOBALSIZE; globalData = StackFilter.Program.GlobalData; diff --git a/src/SharpCompress/Writers/WriterFactory.cs b/src/SharpCompress/Writers/WriterFactory.cs index 1f14f6bb..50e1fdfc 100644 --- a/src/SharpCompress/Writers/WriterFactory.cs +++ b/src/SharpCompress/Writers/WriterFactory.cs @@ -10,9 +10,7 @@ public static class WriterFactory public static IWriter Open(Stream stream, ArchiveType archiveType, WriterOptions writerOptions) { var factory = Factories - .Factory - .Factories - .OfType() + .Factory.Factories.OfType() .FirstOrDefault(item => item.KnownArchiveType == archiveType); if (factory != null) diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index 711b14c1..490698b2 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -198,9 +198,9 @@ public class TarArchiveTests : ArchiveTests using (var archive = TarArchive.Open(unmodified)) { - var entry = archive - .Entries - .Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)); + var entry = archive.Entries.Single( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ); archive.RemoveEntry(entry); archive.SaveTo(scratchPath, CompressionType.None); } diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index 4952b702..e3a27296 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -209,11 +209,9 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_GZip_With_Symlink_Entries() { - var isWindows = System - .Runtime - .InteropServices - .RuntimeInformation - .IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows); + 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")) ) @@ -256,15 +254,12 @@ public class TarReaderTests : ReaderTests { // 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) - ); + var realTarget = System.IO.Path.GetFullPath( + System.IO.Path.Combine( + $"{System.IO.Path.GetDirectoryName(path)}", + target + ) + ); Assert.Equal(realTarget, link.GetContents().ToString()); } diff --git a/tests/SharpCompress.Test/TestBase.cs b/tests/SharpCompress.Test/TestBase.cs index b4966c31..3ad1fe79 100644 --- a/tests/SharpCompress.Test/TestBase.cs +++ b/tests/SharpCompress.Test/TestBase.cs @@ -20,10 +20,10 @@ public class TestBase : IDisposable public TestBase() { - var index = AppDomain - .CurrentDomain - .BaseDirectory - .IndexOf("SharpCompress.Test", StringComparison.OrdinalIgnoreCase); + var index = AppDomain.CurrentDomain.BaseDirectory.IndexOf( + "SharpCompress.Test", + StringComparison.OrdinalIgnoreCase + ); var path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, index); SOLUTION_BASE_PATH = Path.GetDirectoryName(path) ?? throw new ArgumentNullException(); diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index 080ae318..fde87dc6 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -184,9 +184,9 @@ public class ZipArchiveTests : ArchiveTests using (var archive = ZipArchive.Open(unmodified)) { - var entry = archive - .Entries - .Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)); + var entry = archive.Entries.Single( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ); archive.RemoveEntry(entry); WriterOptions writerOptions = new ZipWriterOptions(CompressionType.Deflate); @@ -252,9 +252,9 @@ public class ZipArchiveTests : ArchiveTests ) ); Assert.Null( - ((IArchive)vfs) - .Entries - .FirstOrDefault(v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) + ((IArchive)vfs).Entries.FirstOrDefault( + v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ) ); } } @@ -391,14 +391,14 @@ public class ZipArchiveTests : ArchiveTests { archive.AddAllFromDirectory(SCRATCH_FILES_PATH); archive.RemoveEntry( - archive - .Entries - .Single(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) + archive.Entries.Single( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ) ); Assert.Null( - archive - .Entries - .FirstOrDefault(x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) + archive.Entries.FirstOrDefault( + x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ) ); } Directory.Delete(SCRATCH_FILES_PATH, true); From 4f7a0d3ad00f06f1b34e2cdb460eaf3fccbec7c8 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:08:06 +0000 Subject: [PATCH 0016/1333] CI to dotnet 8 --- .github/workflows/dotnetcore.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 63da3a2e..ee43e5d0 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -17,7 +17,8 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x + cache: true - name: NuGet Caching uses: actions/cache@v3 with: From e4c4db534cfed188d31ad2c3f6b08c75194e0d24 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:09:31 +0000 Subject: [PATCH 0017/1333] build for dotnet 8 --- build/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Program.cs b/build/Program.cs index 9475a66b..acafec41 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -61,7 +61,7 @@ Target( Target( Test, DependsOn(Build), - ForEach("net7.0", "net462"), + ForEach("net8.0", "net462"), framework => { IEnumerable GetFiles(string d) From 30a31de45b33d09e3d0744ed76abdccb1771a21b Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:13:14 +0000 Subject: [PATCH 0018/1333] add lock files --- Directory.Build.props | 5 + build/Program.cs | 2 +- build/packages.lock.json | 25 + src/SharpCompress/packages.lock.json | 381 ++++++ tests/SharpCompress.Test/packages.lock.json | 1274 +++++++++++++++++++ 5 files changed, 1686 insertions(+), 1 deletion(-) create mode 100644 build/packages.lock.json create mode 100644 src/SharpCompress/packages.lock.json create mode 100644 tests/SharpCompress.Test/packages.lock.json diff --git a/Directory.Build.props b/Directory.Build.props index 4b343bf8..73a39104 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -10,5 +10,10 @@ true False False + + true + true + true + false diff --git a/build/Program.cs b/build/Program.cs index acafec41..dccaa600 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -47,7 +47,7 @@ Target( Run("dotnet", "csharpier --check ."); } ); -Target(Restore, DependsOn(Format), () => Run("dotnet", "restore")); +Target(Restore, DependsOn(Format), () => Run("dotnet", "restore --locked-mode")); Target( Build, diff --git a/build/packages.lock.json b/build/packages.lock.json new file mode 100644 index 00000000..2481f67d --- /dev/null +++ b/build/packages.lock.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "dependencies": { + "net7.0": { + "Bullseye": { + "type": "Direct", + "requested": "[4.2.1, )", + "resolved": "4.2.1", + "contentHash": "LQ/YuE1TSxCPfn5qGwf7RpS4jGhXEES1ylsHUNbPKdyJqbh+3VRLcxhS2aUHM9wOKaLR7uISuaiHBYc5Idfatw==" + }, + "Glob": { + "type": "Direct", + "requested": "[1.1.9, )", + "resolved": "1.1.9", + "contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw==" + }, + "SimpleExec": { + "type": "Direct", + "requested": "[11.0.0, )", + "resolved": "11.0.0", + "contentHash": "4r/YxcXlD9yk0XGdU07gUFey6ZiWu7LxG76l9d9xTDfObOcLvug1Xa9loQYuqs2nEviyTgicD1Svragh2qzlOA==" + } + } + } +} \ No newline at end of file diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json new file mode 100644 index 00000000..ffde6d1c --- /dev/null +++ b/src/SharpCompress/packages.lock.json @@ -0,0 +1,381 @@ +{ + "version": 1, + "dependencies": { + ".NETFramework,Version=v4.6.2": { + "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.7.4, )", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "5.0.0", + "System.Memory": "4.5.5" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "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.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.7.4, )", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "5.0.0", + "System.Memory": "4.5.5" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "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.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.7.4, )", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", + "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.Memory": { + "type": "Transitive", + "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.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==" + } + }, + "net6.0": { + "Microsoft.NET.ILLink.Analyzers": { + "type": "Direct", + "requested": "[7.0.100-1.23211.1, )", + "resolved": "7.0.100-1.23211.1", + "contentHash": "0GvbEgDGcUQA9KuWcQU1WwYHXt1tBzNr1Nls/M57rM7NA/AndFwCaCEoJpJkmxRY7xLlPDBnmGp8h5+FNqUngg==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[7.0.100-1.23211.1, )", + "resolved": "7.0.100-1.23211.1", + "contentHash": "tvG8XZYLjT0o3WicCyKBZysVWo1jC9HdCFmNRmddx3WbAz0UCsd0qKZqpiEo99VLA8Re+FzWK51OcRldQPbt2Q==" + }, + "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.7.4, )", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" + }, + "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==" + } + }, + "net7.0": { + "Microsoft.NET.ILLink.Analyzers": { + "type": "Direct", + "requested": "[7.0.100-1.23211.1, )", + "resolved": "7.0.100-1.23211.1", + "contentHash": "0GvbEgDGcUQA9KuWcQU1WwYHXt1tBzNr1Nls/M57rM7NA/AndFwCaCEoJpJkmxRY7xLlPDBnmGp8h5+FNqUngg==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[7.0.100-1.23211.1, )", + "resolved": "7.0.100-1.23211.1", + "contentHash": "tvG8XZYLjT0o3WicCyKBZysVWo1jC9HdCFmNRmddx3WbAz0UCsd0qKZqpiEo99VLA8Re+FzWK51OcRldQPbt2Q==" + }, + "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.7.4, )", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" + }, + "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.0, )", + "resolved": "8.0.0", + "contentHash": "B3etT5XQ2nlWkZGO2m/ytDYrOmSsQG1XNBaM6ZYlX5Ch/tDrMFadr0/mK6gjZwaQc55g+5+WZMw4Cz3m8VEF7g==" + }, + "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.7.4, )", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" + }, + "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/packages.lock.json b/tests/SharpCompress.Test/packages.lock.json new file mode 100644 index 00000000..c793349b --- /dev/null +++ b/tests/SharpCompress.Test/packages.lock.json @@ -0,0 +1,1274 @@ +{ + "version": 1, + "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.8.0, )", + "resolved": "17.8.0", + "contentHash": "BmTYGbD/YuDHmApIENdoyN1jCk0Rj1fJB0+B/fVekyTdVidr91IlzhqzytiUgaEAzL1ZJcYCme0MeBMYvJVzvw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.8.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.6.3, )", + "resolved": "2.6.3", + "contentHash": "4CoGp3iKZORZ9aaHdPrFcdlDBRI/ZFRyDZWJuP7r2idULEtWf+k0yGT80cF/v6nE/MQDXLMIuSGDIrHuPLC/+Q==", + "dependencies": { + "xunit.analyzers": "1.7.0", + "xunit.assert": "2.6.3", + "xunit.core": "[2.6.3]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.5.5, )", + "resolved": "2.5.5", + "contentHash": "AJsBBn8S00ZxdXPSIp8s+NcBQMO9tcll1UVCfGNoEi1DUH2z3f4Y1epV9nYbhgG6wFoTKJP6YuLT2MeTPV9gnA==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.8.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.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.8.0", + "contentHash": "KC8SXWbGIdoFVdlxKk9WHccm0llm9HypcHMLUUFabRiTS3SO2fQXNZfdiF3qkEdTJhbRrxhdRxjL4jbtwPq4Ew==" + }, + "Microsoft.NETFramework.ReferenceAssemblies.net462": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.8.0", + "contentHash": "AYy6vlpGMfz5kOFq99L93RGbqftW/8eQTqjT9iGXW6s9MRP3UdtY8idJ8rJcjeSja8A18IhIro5YnH3uv1nz4g==", + "dependencies": { + "NuGet.Frameworks": "6.5.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "6.5.0", + "contentHash": "QWINE2x3MbTODsWT1Gh71GaGb5icBz4chS8VYvTgsBnsi8esgN6wtHhydd7fvToWECYGq7T4cgBBDiKD/363fg==" + }, + "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.Memory": { + "type": "Transitive", + "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.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.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", + "dependencies": { + "System.Memory": "4.5.5", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "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.7.0", + "contentHash": "lAcpaB0KnjWETbPDMsDPoQi6zS0uXUYopmyTQDWvILJWcL9jwMxXXGmDLptlMA6vGi5Z0LtudsYN+dEUTmuHaA==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "7JWrjxDIAwF1vBZyENu4BZaddNJijIQcIQcc+73sJPWaqzDmseysTYv2jR0IWBsWIGa6LSfMO/3+dH0fsHL5Wg==" + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "rlrm//9cNAlCkh3p5mdggzfchZlcXowUVK3UPqKiaN7G0Wu7gOUNLLZej9twnwTCVe1h3FEi9PRwzXMMXpFwSQ==", + "dependencies": { + "xunit.extensibility.core": "[2.6.3]", + "xunit.extensibility.execution": "[2.6.3]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "qWCpmK4nxFBsf68r35AgnrW6B+xjTCpjJYfJkaBaini4Myl/2P/Ro6WocVtJfpHilkatitVFgM3XVR0jthdJlQ==", + "dependencies": { + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "I+9OA9a6WVia40bxJi3KaxVcjTE1ouHqD0QcrjHA/hLl7Ozb5eQmV7ecLu3gRZlPLdcVN+If8IZcEmqytmLtkA==", + "dependencies": { + "xunit.extensibility.core": "[2.6.3]" + } + }, + "ZstdSharp.Port": { + "type": "Transitive", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "5.0.0", + "System.Memory": "4.5.5" + } + }, + "sharpcompress": { + "type": "Project", + "dependencies": { + "System.Memory": "[4.5.5, )", + "System.Text.Encoding.CodePages": "[8.0.0, )", + "ZstdSharp.Port": "[0.7.4, )" + } + } + }, + "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.8.0, )", + "resolved": "17.8.0", + "contentHash": "BmTYGbD/YuDHmApIENdoyN1jCk0Rj1fJB0+B/fVekyTdVidr91IlzhqzytiUgaEAzL1ZJcYCme0MeBMYvJVzvw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.8.0", + "Microsoft.TestPlatform.TestHost": "17.8.0" + } + }, + "Mono.Posix.NETStandard": { + "type": "Direct", + "requested": "[1.0.0, )", + "resolved": "1.0.0", + "contentHash": "vSN/L1uaVwKsiLa95bYu2SGkF0iY3xMblTfxc8alSziPuVfJpj3geVqHGAA75J7cZkMuKpFVikz82Lo6y6LLdA==" + }, + "xunit": { + "type": "Direct", + "requested": "[2.6.3, )", + "resolved": "2.6.3", + "contentHash": "4CoGp3iKZORZ9aaHdPrFcdlDBRI/ZFRyDZWJuP7r2idULEtWf+k0yGT80cF/v6nE/MQDXLMIuSGDIrHuPLC/+Q==", + "dependencies": { + "xunit.analyzers": "1.7.0", + "xunit.assert": "2.6.3", + "xunit.core": "[2.6.3]" + } + }, + "xunit.runner.visualstudio": { + "type": "Direct", + "requested": "[2.5.5, )", + "resolved": "2.5.5", + "contentHash": "AJsBBn8S00ZxdXPSIp8s+NcBQMO9tcll1UVCfGNoEi1DUH2z3f4Y1epV9nYbhgG6wFoTKJP6YuLT2MeTPV9gnA==" + }, + "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.8.0", + "contentHash": "KC8SXWbGIdoFVdlxKk9WHccm0llm9HypcHMLUUFabRiTS3SO2fQXNZfdiF3qkEdTJhbRrxhdRxjL4jbtwPq4Ew==" + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.8.0", + "contentHash": "AYy6vlpGMfz5kOFq99L93RGbqftW/8eQTqjT9iGXW6s9MRP3UdtY8idJ8rJcjeSja8A18IhIro5YnH3uv1nz4g==", + "dependencies": { + "NuGet.Frameworks": "6.5.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.8.0", + "contentHash": "9ivcl/7SGRmOT0YYrHQGohWiT5YCpkmy/UEzldfVisLm6QxbLaK3FAJqZXI34rnRLmqqDCeMQxKINwmKwAPiDw==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.8.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "6.5.0", + "contentHash": "QWINE2x3MbTODsWT1Gh71GaGb5icBz4chS8VYvTgsBnsi8esgN6wtHhydd7fvToWECYGq7T4cgBBDiKD/363fg==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "4.4.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "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.7.0", + "contentHash": "lAcpaB0KnjWETbPDMsDPoQi6zS0uXUYopmyTQDWvILJWcL9jwMxXXGmDLptlMA6vGi5Z0LtudsYN+dEUTmuHaA==" + }, + "xunit.assert": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "7JWrjxDIAwF1vBZyENu4BZaddNJijIQcIQcc+73sJPWaqzDmseysTYv2jR0IWBsWIGa6LSfMO/3+dH0fsHL5Wg==" + }, + "xunit.core": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "rlrm//9cNAlCkh3p5mdggzfchZlcXowUVK3UPqKiaN7G0Wu7gOUNLLZej9twnwTCVe1h3FEi9PRwzXMMXpFwSQ==", + "dependencies": { + "xunit.extensibility.core": "[2.6.3]", + "xunit.extensibility.execution": "[2.6.3]" + } + }, + "xunit.extensibility.core": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "qWCpmK4nxFBsf68r35AgnrW6B+xjTCpjJYfJkaBaini4Myl/2P/Ro6WocVtJfpHilkatitVFgM3XVR0jthdJlQ==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.abstractions": "2.0.3" + } + }, + "xunit.extensibility.execution": { + "type": "Transitive", + "resolved": "2.6.3", + "contentHash": "I+9OA9a6WVia40bxJi3KaxVcjTE1ouHqD0QcrjHA/hLl7Ozb5eQmV7ecLu3gRZlPLdcVN+If8IZcEmqytmLtkA==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "xunit.extensibility.core": "[2.6.3]" + } + }, + "ZstdSharp.Port": { + "type": "Transitive", + "resolved": "0.7.4", + "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" + }, + "sharpcompress": { + "type": "Project", + "dependencies": { + "ZstdSharp.Port": "[0.7.4, )" + } + } + } + } +} \ No newline at end of file From b78643f2d8d09a799bdba4592851bc39897c15b8 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:15:15 +0000 Subject: [PATCH 0019/1333] update upload artifact --- .github/workflows/dotnetcore.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index ee43e5d0..6ebfde70 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -27,7 +27,7 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - run: dotnet run --project build/build.csproj - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: ${{ matrix.os }}-sharpcompress.nupkg path: artifacts/* From cee3a9c11de6605fdf4f218191cba759924d97ea Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:15:26 +0000 Subject: [PATCH 0020/1333] Revert "add lock files" This reverts commit 30a31de45b33d09e3d0744ed76abdccb1771a21b. --- Directory.Build.props | 5 - build/Program.cs | 2 +- build/packages.lock.json | 25 - src/SharpCompress/packages.lock.json | 381 ------ tests/SharpCompress.Test/packages.lock.json | 1274 ------------------- 5 files changed, 1 insertion(+), 1686 deletions(-) delete mode 100644 build/packages.lock.json delete mode 100644 src/SharpCompress/packages.lock.json delete mode 100644 tests/SharpCompress.Test/packages.lock.json diff --git a/Directory.Build.props b/Directory.Build.props index 73a39104..4b343bf8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -10,10 +10,5 @@ true False False - - true - true - true - false diff --git a/build/Program.cs b/build/Program.cs index dccaa600..acafec41 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -47,7 +47,7 @@ Target( Run("dotnet", "csharpier --check ."); } ); -Target(Restore, DependsOn(Format), () => Run("dotnet", "restore --locked-mode")); +Target(Restore, DependsOn(Format), () => Run("dotnet", "restore")); Target( Build, diff --git a/build/packages.lock.json b/build/packages.lock.json deleted file mode 100644 index 2481f67d..00000000 --- a/build/packages.lock.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net7.0": { - "Bullseye": { - "type": "Direct", - "requested": "[4.2.1, )", - "resolved": "4.2.1", - "contentHash": "LQ/YuE1TSxCPfn5qGwf7RpS4jGhXEES1ylsHUNbPKdyJqbh+3VRLcxhS2aUHM9wOKaLR7uISuaiHBYc5Idfatw==" - }, - "Glob": { - "type": "Direct", - "requested": "[1.1.9, )", - "resolved": "1.1.9", - "contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw==" - }, - "SimpleExec": { - "type": "Direct", - "requested": "[11.0.0, )", - "resolved": "11.0.0", - "contentHash": "4r/YxcXlD9yk0XGdU07gUFey6ZiWu7LxG76l9d9xTDfObOcLvug1Xa9loQYuqs2nEviyTgicD1Svragh2qzlOA==" - } - } - } -} \ No newline at end of file diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json deleted file mode 100644 index ffde6d1c..00000000 --- a/src/SharpCompress/packages.lock.json +++ /dev/null @@ -1,381 +0,0 @@ -{ - "version": 1, - "dependencies": { - ".NETFramework,Version=v4.6.2": { - "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.7.4, )", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "System.Memory": "4.5.5" - } - }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "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.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.7.4, )", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "System.Memory": "4.5.5" - } - }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "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.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.7.4, )", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", - "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.Memory": { - "type": "Transitive", - "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.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==" - } - }, - "net6.0": { - "Microsoft.NET.ILLink.Analyzers": { - "type": "Direct", - "requested": "[7.0.100-1.23211.1, )", - "resolved": "7.0.100-1.23211.1", - "contentHash": "0GvbEgDGcUQA9KuWcQU1WwYHXt1tBzNr1Nls/M57rM7NA/AndFwCaCEoJpJkmxRY7xLlPDBnmGp8h5+FNqUngg==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[7.0.100-1.23211.1, )", - "resolved": "7.0.100-1.23211.1", - "contentHash": "tvG8XZYLjT0o3WicCyKBZysVWo1jC9HdCFmNRmddx3WbAz0UCsd0qKZqpiEo99VLA8Re+FzWK51OcRldQPbt2Q==" - }, - "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.7.4, )", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" - }, - "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==" - } - }, - "net7.0": { - "Microsoft.NET.ILLink.Analyzers": { - "type": "Direct", - "requested": "[7.0.100-1.23211.1, )", - "resolved": "7.0.100-1.23211.1", - "contentHash": "0GvbEgDGcUQA9KuWcQU1WwYHXt1tBzNr1Nls/M57rM7NA/AndFwCaCEoJpJkmxRY7xLlPDBnmGp8h5+FNqUngg==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[7.0.100-1.23211.1, )", - "resolved": "7.0.100-1.23211.1", - "contentHash": "tvG8XZYLjT0o3WicCyKBZysVWo1jC9HdCFmNRmddx3WbAz0UCsd0qKZqpiEo99VLA8Re+FzWK51OcRldQPbt2Q==" - }, - "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.7.4, )", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" - }, - "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.0, )", - "resolved": "8.0.0", - "contentHash": "B3etT5XQ2nlWkZGO2m/ytDYrOmSsQG1XNBaM6ZYlX5Ch/tDrMFadr0/mK6gjZwaQc55g+5+WZMw4Cz3m8VEF7g==" - }, - "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.7.4, )", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" - }, - "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/packages.lock.json b/tests/SharpCompress.Test/packages.lock.json deleted file mode 100644 index c793349b..00000000 --- a/tests/SharpCompress.Test/packages.lock.json +++ /dev/null @@ -1,1274 +0,0 @@ -{ - "version": 1, - "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.8.0, )", - "resolved": "17.8.0", - "contentHash": "BmTYGbD/YuDHmApIENdoyN1jCk0Rj1fJB0+B/fVekyTdVidr91IlzhqzytiUgaEAzL1ZJcYCme0MeBMYvJVzvw==", - "dependencies": { - "Microsoft.CodeCoverage": "17.8.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.6.3, )", - "resolved": "2.6.3", - "contentHash": "4CoGp3iKZORZ9aaHdPrFcdlDBRI/ZFRyDZWJuP7r2idULEtWf+k0yGT80cF/v6nE/MQDXLMIuSGDIrHuPLC/+Q==", - "dependencies": { - "xunit.analyzers": "1.7.0", - "xunit.assert": "2.6.3", - "xunit.core": "[2.6.3]" - } - }, - "xunit.runner.visualstudio": { - "type": "Direct", - "requested": "[2.5.5, )", - "resolved": "2.5.5", - "contentHash": "AJsBBn8S00ZxdXPSIp8s+NcBQMO9tcll1UVCfGNoEi1DUH2z3f4Y1epV9nYbhgG6wFoTKJP6YuLT2MeTPV9gnA==", - "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "17.8.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.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.CodeCoverage": { - "type": "Transitive", - "resolved": "17.8.0", - "contentHash": "KC8SXWbGIdoFVdlxKk9WHccm0llm9HypcHMLUUFabRiTS3SO2fQXNZfdiF3qkEdTJhbRrxhdRxjL4jbtwPq4Ew==" - }, - "Microsoft.NETFramework.ReferenceAssemblies.net462": { - "type": "Transitive", - "resolved": "1.0.3", - "contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ==" - }, - "Microsoft.TestPlatform.ObjectModel": { - "type": "Transitive", - "resolved": "17.8.0", - "contentHash": "AYy6vlpGMfz5kOFq99L93RGbqftW/8eQTqjT9iGXW6s9MRP3UdtY8idJ8rJcjeSja8A18IhIro5YnH3uv1nz4g==", - "dependencies": { - "NuGet.Frameworks": "6.5.0", - "System.Reflection.Metadata": "1.6.0" - } - }, - "NuGet.Frameworks": { - "type": "Transitive", - "resolved": "6.5.0", - "contentHash": "QWINE2x3MbTODsWT1Gh71GaGb5icBz4chS8VYvTgsBnsi8esgN6wtHhydd7fvToWECYGq7T4cgBBDiKD/363fg==" - }, - "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.Memory": { - "type": "Transitive", - "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.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.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "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.7.0", - "contentHash": "lAcpaB0KnjWETbPDMsDPoQi6zS0uXUYopmyTQDWvILJWcL9jwMxXXGmDLptlMA6vGi5Z0LtudsYN+dEUTmuHaA==" - }, - "xunit.assert": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "7JWrjxDIAwF1vBZyENu4BZaddNJijIQcIQcc+73sJPWaqzDmseysTYv2jR0IWBsWIGa6LSfMO/3+dH0fsHL5Wg==" - }, - "xunit.core": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "rlrm//9cNAlCkh3p5mdggzfchZlcXowUVK3UPqKiaN7G0Wu7gOUNLLZej9twnwTCVe1h3FEi9PRwzXMMXpFwSQ==", - "dependencies": { - "xunit.extensibility.core": "[2.6.3]", - "xunit.extensibility.execution": "[2.6.3]" - } - }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "qWCpmK4nxFBsf68r35AgnrW6B+xjTCpjJYfJkaBaini4Myl/2P/Ro6WocVtJfpHilkatitVFgM3XVR0jthdJlQ==", - "dependencies": { - "xunit.abstractions": "2.0.3" - } - }, - "xunit.extensibility.execution": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "I+9OA9a6WVia40bxJi3KaxVcjTE1ouHqD0QcrjHA/hLl7Ozb5eQmV7ecLu3gRZlPLdcVN+If8IZcEmqytmLtkA==", - "dependencies": { - "xunit.extensibility.core": "[2.6.3]" - } - }, - "ZstdSharp.Port": { - "type": "Transitive", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "System.Memory": "4.5.5" - } - }, - "sharpcompress": { - "type": "Project", - "dependencies": { - "System.Memory": "[4.5.5, )", - "System.Text.Encoding.CodePages": "[8.0.0, )", - "ZstdSharp.Port": "[0.7.4, )" - } - } - }, - "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.8.0, )", - "resolved": "17.8.0", - "contentHash": "BmTYGbD/YuDHmApIENdoyN1jCk0Rj1fJB0+B/fVekyTdVidr91IlzhqzytiUgaEAzL1ZJcYCme0MeBMYvJVzvw==", - "dependencies": { - "Microsoft.CodeCoverage": "17.8.0", - "Microsoft.TestPlatform.TestHost": "17.8.0" - } - }, - "Mono.Posix.NETStandard": { - "type": "Direct", - "requested": "[1.0.0, )", - "resolved": "1.0.0", - "contentHash": "vSN/L1uaVwKsiLa95bYu2SGkF0iY3xMblTfxc8alSziPuVfJpj3geVqHGAA75J7cZkMuKpFVikz82Lo6y6LLdA==" - }, - "xunit": { - "type": "Direct", - "requested": "[2.6.3, )", - "resolved": "2.6.3", - "contentHash": "4CoGp3iKZORZ9aaHdPrFcdlDBRI/ZFRyDZWJuP7r2idULEtWf+k0yGT80cF/v6nE/MQDXLMIuSGDIrHuPLC/+Q==", - "dependencies": { - "xunit.analyzers": "1.7.0", - "xunit.assert": "2.6.3", - "xunit.core": "[2.6.3]" - } - }, - "xunit.runner.visualstudio": { - "type": "Direct", - "requested": "[2.5.5, )", - "resolved": "2.5.5", - "contentHash": "AJsBBn8S00ZxdXPSIp8s+NcBQMO9tcll1UVCfGNoEi1DUH2z3f4Y1epV9nYbhgG6wFoTKJP6YuLT2MeTPV9gnA==" - }, - "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.8.0", - "contentHash": "KC8SXWbGIdoFVdlxKk9WHccm0llm9HypcHMLUUFabRiTS3SO2fQXNZfdiF3qkEdTJhbRrxhdRxjL4jbtwPq4Ew==" - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - }, - "Microsoft.NETCore.Targets": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" - }, - "Microsoft.TestPlatform.ObjectModel": { - "type": "Transitive", - "resolved": "17.8.0", - "contentHash": "AYy6vlpGMfz5kOFq99L93RGbqftW/8eQTqjT9iGXW6s9MRP3UdtY8idJ8rJcjeSja8A18IhIro5YnH3uv1nz4g==", - "dependencies": { - "NuGet.Frameworks": "6.5.0", - "System.Reflection.Metadata": "1.6.0" - } - }, - "Microsoft.TestPlatform.TestHost": { - "type": "Transitive", - "resolved": "17.8.0", - "contentHash": "9ivcl/7SGRmOT0YYrHQGohWiT5YCpkmy/UEzldfVisLm6QxbLaK3FAJqZXI34rnRLmqqDCeMQxKINwmKwAPiDw==", - "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "17.8.0", - "Newtonsoft.Json": "13.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "NETStandard.Library": { - "type": "Transitive", - "resolved": "1.6.1", - "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.AppContext": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Console": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.Compression.ZipFile": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Linq": "4.3.0", - "System.Linq.Expressions": "4.3.0", - "System.Net.Http": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Net.Sockets": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Timer": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0", - "System.Xml.XDocument": "4.3.0" - } - }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "13.0.1", - "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" - }, - "NuGet.Frameworks": { - "type": "Transitive", - "resolved": "6.5.0", - "contentHash": "QWINE2x3MbTODsWT1Gh71GaGb5icBz4chS8VYvTgsBnsi8esgN6wtHhydd7fvToWECYGq7T4cgBBDiKD/363fg==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", - "dependencies": { - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" - } - }, - "runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", - "dependencies": { - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "System.AppContext": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Collections.Concurrent": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Configuration.ConfigurationManager": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "gWwQv/Ug1qWJmHCmN17nAbxJYmQBM/E94QxKLksvUiiKB1Ld3Sc/eK1lgmbSjDFxkQhVuayI/cGFZhpBSodLrg==", - "dependencies": { - "System.Security.Cryptography.ProtectedData": "4.4.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.DiagnosticSource": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.Compression.ZipFile": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.FileSystem.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Linq": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Linq.Expressions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Linq": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Emit.Lightweight": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Reflection.TypeExtensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.ObjectModel": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", - "dependencies": { - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit.ILGeneration": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit.Lightweight": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.TypeExtensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Runtime.Numerics": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", - "dependencies": { - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Security.Cryptography.ProtectedData": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog==" - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Text.RegularExpressions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Xml.ReaderWriter": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Extensions": "4.3.0" - } - }, - "System.Xml.XDocument": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0" - } - }, - "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.7.0", - "contentHash": "lAcpaB0KnjWETbPDMsDPoQi6zS0uXUYopmyTQDWvILJWcL9jwMxXXGmDLptlMA6vGi5Z0LtudsYN+dEUTmuHaA==" - }, - "xunit.assert": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "7JWrjxDIAwF1vBZyENu4BZaddNJijIQcIQcc+73sJPWaqzDmseysTYv2jR0IWBsWIGa6LSfMO/3+dH0fsHL5Wg==" - }, - "xunit.core": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "rlrm//9cNAlCkh3p5mdggzfchZlcXowUVK3UPqKiaN7G0Wu7gOUNLLZej9twnwTCVe1h3FEi9PRwzXMMXpFwSQ==", - "dependencies": { - "xunit.extensibility.core": "[2.6.3]", - "xunit.extensibility.execution": "[2.6.3]" - } - }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "qWCpmK4nxFBsf68r35AgnrW6B+xjTCpjJYfJkaBaini4Myl/2P/Ro6WocVtJfpHilkatitVFgM3XVR0jthdJlQ==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.abstractions": "2.0.3" - } - }, - "xunit.extensibility.execution": { - "type": "Transitive", - "resolved": "2.6.3", - "contentHash": "I+9OA9a6WVia40bxJi3KaxVcjTE1ouHqD0QcrjHA/hLl7Ozb5eQmV7ecLu3gRZlPLdcVN+If8IZcEmqytmLtkA==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.extensibility.core": "[2.6.3]" - } - }, - "ZstdSharp.Port": { - "type": "Transitive", - "resolved": "0.7.4", - "contentHash": "ziptnotpUJr51afwXJQ5Wc03dvDiZAdmxS08s1g7SHn/VzbyZUXdH6yORk/zaNjzUOEE6pVZ0Nqztab0rYROgQ==" - }, - "sharpcompress": { - "type": "Project", - "dependencies": { - "ZstdSharp.Port": "[0.7.4, )" - } - } - } - } -} \ No newline at end of file From 32aa9877c0ff3e384fe62c564db16d476e458218 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:16:02 +0000 Subject: [PATCH 0021/1333] remove caching --- .github/workflows/dotnetcore.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 6ebfde70..27d73e23 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -18,14 +18,6 @@ jobs: - uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x - cache: true - - 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 with: From 2d14ecf58b1089f56810750a3796c1b0492879f9 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:20:44 +0000 Subject: [PATCH 0022/1333] add readme --- src/SharpCompress/SharpCompress.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index d3719849..ce822e44 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -14,6 +14,7 @@ rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz https://github.com/adamhathcock/sharpcompress MIT + ../README.md Copyright (c) 2014 Adam Hathcock false false From 80718a461b5022d16e5948bca2e7401956560506 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:24:00 +0000 Subject: [PATCH 0023/1333] fix readme? --- src/SharpCompress/SharpCompress.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index ce822e44..41e45820 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -14,7 +14,7 @@ rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz https://github.com/adamhathcock/sharpcompress MIT - ../README.md + ../../README.md Copyright (c) 2014 Adam Hathcock false false From b986bf675f4ecdbcd4b272be226ccecef71cece5 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:31:33 +0000 Subject: [PATCH 0024/1333] just remove readme --- src/SharpCompress/SharpCompress.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 41e45820..d3719849 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -14,7 +14,6 @@ rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz https://github.com/adamhathcock/sharpcompress MIT - ../../README.md Copyright (c) 2014 Adam Hathcock false false From 372a2c8375048610e3a9c240ab3c58fc5781ab88 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 18 Dec 2023 09:59:46 +0000 Subject: [PATCH 0025/1333] Mark for 0.35.0 --- src/SharpCompress/SharpCompress.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index d3719849..c5bd96d9 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -2,9 +2,9 @@ SharpCompress - Pure C# Decompression/Compression en-US - 0.34.2 - 0.34.2 - 0.34.2 + 0.35.0 + 0.35.0 + 0.35.0 Adam Hathcock net462;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0 SharpCompress From d4fb17cf66d1ee3e527005375651a0f98868f410 Mon Sep 17 00:00:00 2001 From: Daniel Nash Date: Fri, 22 Dec 2023 11:12:46 -0500 Subject: [PATCH 0026/1333] ZipWriter: Write correct EOCD record when more than 65,535 files 0xFFFF will be written to the EOCD to signal to use the ZIP64 CentralDirectory record when the number of files is 65,535 or more. Fixes #791 --- src/SharpCompress/Writers/Zip/ZipWriter.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index e1fd222c..e1bb53e9 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -304,7 +304,10 @@ 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); + BinaryPrimitives.WriteUInt16LittleEndian( + intBuf, + (ushort)(entries.Count < 0xFFFF ? entries.Count : 0xFFFF) + ); OutputStream.Write(intBuf.Slice(0, 2)); OutputStream.Write(intBuf.Slice(0, 2)); BinaryPrimitives.WriteUInt32LittleEndian(intBuf, sizevalue); From 388bbe047e7be4a89eb3e6171c1cc3a44ce348e1 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Tue, 2 Jan 2024 20:46:55 +0100 Subject: [PATCH 0027/1333] Blake2 Archive test OK --- .../Archives/Rar/RarArchiveEntry.cs | 4 +- .../Common/Rar/Headers/FileHeader.cs | 28 +- src/SharpCompress/Common/Rar/RarEntry.cs | 2 +- .../Rar/MultiVolumeReadOnlyStream.cs | 2 +- .../Compressors/Rar/RarBLAKE2spStream.cs | 288 ++++++++++++++++++ .../Compressors/Rar/RarCrcStream.cs | 4 +- src/SharpCompress/Readers/Rar/RarReader.cs | 6 + .../SharpCompress.Test/Rar/RarArchiveTests.cs | 3 + .../SharpCompress.Test/Rar/RarReaderTests.cs | 21 +- 9 files changed, 323 insertions(+), 35 deletions(-) create mode 100644 src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs diff --git a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs index 5885210a..1ad252d1 100644 --- a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs +++ b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs @@ -1,3 +1,5 @@ + +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -40,7 +42,7 @@ public class RarArchiveEntry : RarEntry, IArchiveEntry get { CheckIncomplete(); - return parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc; + return BitConverter.ToUInt32( parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc, 0); } } diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index 3775f036..57cd5c71 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -18,7 +18,7 @@ namespace SharpCompress.Common.Rar.Headers; internal class FileHeader : RarHeader { - private uint _fileCrc; + private byte[] _hash; public FileHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) : base(header, reader, headerType) { } @@ -53,7 +53,7 @@ internal class FileHeader : RarHeader if (HasFlag(FileFlagsV5.HAS_CRC32)) { - FileCrc = reader.ReadUInt32(); + FileCrc = reader.ReadBytes(4); } var compressionInfo = reader.ReadRarVIntUInt16(); @@ -136,14 +136,12 @@ internal class FileHeader : RarHeader { const uint FHEXTRA_HASH_BLAKE2 = 0x0; - const uint HASH_BLAKE2 = 0x03; + // const uint HASH_BLAKE2 = 0x03; const int BLAKE2_DIGEST_SIZE = 0x20; if ((uint)reader.ReadRarVInt() == FHEXTRA_HASH_BLAKE2) { - var hash = HASH_BLAKE2; - var digest = reader.ReadBytes(BLAKE2_DIGEST_SIZE); - - throw new InvalidFormatException("Not yet implemented " + hash); + // var hash = HASH_BLAKE2; + _hash = reader.ReadBytes(BLAKE2_DIGEST_SIZE); } // enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2}; } @@ -242,7 +240,7 @@ internal class FileHeader : RarHeader HostOs = reader.ReadByte(); - FileCrc = reader.ReadUInt32(); + FileCrc = reader.ReadBytes(4); FileLastModifiedTime = Utility.DosDateToDateTime(reader.ReadUInt32()); @@ -414,18 +412,10 @@ internal class FileHeader : RarHeader private bool HasFlag(ushort flag) => (Flags & flag) == flag; - internal uint FileCrc + internal byte[] FileCrc { - get - { - if (IsRar5 && !HasFlag(FileFlagsV5.HAS_CRC32)) - { - //!!! rar5: - throw new InvalidOperationException("TODO rar5"); - } - return _fileCrc; - } - private set => _fileCrc = value; + get => _hash; + private set => _hash = value; } // 0 - storing diff --git a/src/SharpCompress/Common/Rar/RarEntry.cs b/src/SharpCompress/Common/Rar/RarEntry.cs index 7f280e4a..92149e14 100644 --- a/src/SharpCompress/Common/Rar/RarEntry.cs +++ b/src/SharpCompress/Common/Rar/RarEntry.cs @@ -20,7 +20,7 @@ public abstract class RarEntry : Entry /// /// The File's 32 bit CRC Hash /// - public override long Crc => FileHeader.FileCrc; + public override long Crc => BitConverter.ToUInt32( FileHeader.FileCrc, 0 ); /// /// The path of the file internal to the Rar Archive. diff --git a/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs b/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs index 1e4adfde..460d92eb 100644 --- a/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs +++ b/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs @@ -128,7 +128,7 @@ internal sealed class MultiVolumeReadOnlyStream : Stream public override bool CanWrite => false; - public uint CurrentCrc { get; private set; } + public byte[] CurrentCrc { get; private set; } public override void Flush() => throw new NotSupportedException(); diff --git a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs new file mode 100644 index 00000000..5c6c5ce2 --- /dev/null +++ b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs @@ -0,0 +1,288 @@ + +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; + + 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 (int 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; + this._hash = fileHeader.FileCrc; + this._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) + { + UInt32[] m = new UInt32[16]; + UInt32[] v = new UInt32[16]; + + for (int i = 0; i < 16; i++) + { + m[i] = BitConverter.ToUInt32(hash.b, i * 4); + } + + for (int 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( int 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( int i = 0; i < 8; i++ ) + { + hash.h[i] ^= v[i] ^ v[i + 8]; + } + } + + internal void Update(BLAKE2S hash, ReadOnlySpan data, int size) + { + int 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(int 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) + { + int 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(int 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 (!(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 98d50b00..372abb43 100644 --- a/src/SharpCompress/Compressors/Rar/RarCrcStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarCrcStream.cs @@ -1,3 +1,5 @@ + +using System; using SharpCompress.Common; using SharpCompress.Common.Rar.Headers; @@ -30,7 +32,7 @@ internal class RarCrcStream : RarStream { currentCrc = RarCRC.CheckCrc(currentCrc, buffer, offset, result); } - else if (GetCrc() != readStream.CurrentCrc && count != 0) + else if (GetCrc() != BitConverter.ToUInt32(readStream.CurrentCrc, 0) && 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/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index da8c132b..695d47b0 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -72,6 +72,12 @@ 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/tests/SharpCompress.Test/Rar/RarArchiveTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs index acc5bdc8..42e76299 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs @@ -608,4 +608,7 @@ public class RarArchiveTests : ArchiveTests Assert.True(archive.IsMultipartVolume()); Assert.False(archive.IsFirstVolume()); } + + [Fact] + public void Rar5_CRC_Blake2_Archive() => ArchiveFileRead("Rar5.crc_blake2.rar"); } diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index 1fdbeef9..fc78b01c 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -171,33 +171,30 @@ 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() - { + [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() - { + [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 }); From f8a0069a5dbe1d73c78824847c9e6579008440d6 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Tue, 2 Jan 2024 21:18:49 +0100 Subject: [PATCH 0028/1333] Calc checksum when encrypted is not working for RAR5, disable for now --- README.md | 2 +- .../Compressors/Rar/RarBLAKE2spStream.cs | 97 +++++++++++-------- .../Compressors/Rar/RarCrcStream.cs | 9 +- 3 files changed, 65 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 20681105..8eb4c10d 100644 --- a/README.md +++ b/README.md @@ -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 support +* RAR 5 decryption crc check support * 7Zip writing * Zip64 (Need writing and extend Reading) * Multi-volume Zip support. diff --git a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs index 5c6c5ce2..d3e90c4c 100644 --- a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs @@ -1,4 +1,3 @@ - using System; using System.IO; using System.Linq; @@ -11,31 +10,40 @@ 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 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 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 }, - }; + 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 { @@ -84,8 +92,9 @@ internal class RarBLAKE2spStream : RarStream : base(unpack, fileHeader, readStream) { this.readStream = readStream; - this._hash = fileHeader.FileCrc; - this._blake2sp = new BLAKE2SP(); + disableCRCCheck = fileHeader.IsEncrypted; + _hash = fileHeader.FileCrc; + _blake2sp = new BLAKE2SP(); ResetCrc(); } @@ -105,18 +114,26 @@ internal class RarBLAKE2spStream : RarStream 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) + 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 ); + d = (d >> 16) | (d << 16); c += d; b ^= c; - b = ( b >> 12 ) | ( b << 20 ); + b = (b >> 12) | (b << 20); a += b + m[sigma[2 * i + 1]]; d ^= a; - d = ( d >> 8 ) | ( d << 24 ); + d = (d >> 8) | (d << 24); c += d; b ^= c; b = (b >> 7) | (b << 25); @@ -147,7 +164,7 @@ internal class RarBLAKE2spStream : RarStream v[14] = hash.f[0] ^ k_BLAKE2S_IV[6]; v[15] = hash.f[1] ^ k_BLAKE2S_IV[7]; - for( int r = 0; r < BLAKE2S_NUM_ROUNDS; r++) + for (int r = 0; r < BLAKE2S_NUM_ROUNDS; r++) { ref byte[] sigma = ref k_BLAKE2S_Sigma[r]; @@ -161,7 +178,7 @@ internal class RarBLAKE2spStream : RarStream G(ref m, ref sigma, 7, ref v[3], ref v[4], ref v[9], ref v[14]); } - for( int i = 0; i < 8; i++ ) + for (int i = 0; i < 8; i++) { hash.h[i] ^= v[i] ^ v[i + 8]; } @@ -170,12 +187,12 @@ internal class RarBLAKE2spStream : RarStream internal void Update(BLAKE2S hash, ReadOnlySpan data, int size) { int i = 0; - while(size != 0) + while (size != 0) { var pos = hash.bufferPosition; var reminder = BLAKE2S_BLOCK_SIZE - pos; - if(size <= reminder ) + if (size <= reminder) { data.Slice(i, size).CopyTo(new Span(hash.b, pos, size)); hash.bufferPosition += size; @@ -202,9 +219,9 @@ internal class RarBLAKE2spStream : RarStream var mem = new MemoryStream(); - for(int i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { - mem.Write( BitConverter.GetBytes(hash.h[i]), 0, 4 ); + mem.Write(BitConverter.GetBytes(hash.h[i]), 0, 4); } return mem.ToArray(); @@ -214,7 +231,7 @@ internal class RarBLAKE2spStream : RarStream { _blake2sp.bufferPosition = 0; - for( UInt32 i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++ ) + for (UInt32 i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) { _blake2sp.S[i].bufferPosition = 0; ResetCrc(_blake2sp.S[i]); @@ -230,16 +247,16 @@ internal class RarBLAKE2spStream : RarStream { int i = 0; var pos = hash.bufferPosition; - while( size != 0 ) + while (size != 0) { var index = pos / BLAKE2S_BLOCK_SIZE; - var reminder = BLAKE2S_BLOCK_SIZE - (pos & ( BLAKE2S_BLOCK_SIZE -1 ) ); - if( reminder > 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); + Update(hash.S[index], data.Slice(i, reminder), reminder); size -= reminder; i += reminder; pos += reminder; @@ -257,7 +274,7 @@ internal class RarBLAKE2spStream : RarStream h.h[3] ^= (1 << 16 | BLAKE2S_DIGEST_SIZE << 24); h.lastNodeFlag = BLAKE2S_FINAL_FLAG; - for(int i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) + for (int i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) { var digest = Final(_blake2sp.S[i]); Update(h, digest, BLAKE2S_DIGEST_SIZE); @@ -271,12 +288,12 @@ internal class RarBLAKE2spStream : RarStream var result = base.Read(buffer, offset, count); if (result != 0) { - Update(_blake2sp, new ReadOnlySpan(buffer,offset,result), result); + Update(_blake2sp, new ReadOnlySpan(buffer, offset, result), result); } else { _hash = Final(_blake2sp); - if (!(GetCrc().SequenceEqual(readStream.CurrentCrc)) && count != 0) + 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"); diff --git a/src/SharpCompress/Compressors/Rar/RarCrcStream.cs b/src/SharpCompress/Compressors/Rar/RarCrcStream.cs index 372abb43..ce42a4bd 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; @@ -9,6 +8,7 @@ internal class RarCrcStream : RarStream { private readonly MultiVolumeReadOnlyStream readStream; private uint currentCrc; + private readonly bool disableCRC; public RarCrcStream( IRarUnpack unpack, @@ -18,6 +18,7 @@ internal class RarCrcStream : RarStream : base(unpack, fileHeader, readStream) { this.readStream = readStream; + disableCRC = fileHeader.IsEncrypted; ResetCrc(); } @@ -32,7 +33,11 @@ internal class RarCrcStream : RarStream { currentCrc = RarCRC.CheckCrc(currentCrc, buffer, offset, result); } - else if (GetCrc() != BitConverter.ToUInt32(readStream.CurrentCrc, 0) && count != 0) + else if ( + !disableCRC + && GetCrc() != BitConverter.ToUInt32(readStream.CurrentCrc, 0) + && count != 0 + ) { // NOTE: we use the last FileHeader in a multipart volume to check CRC throw new InvalidFormatException("file crc mismatch"); From 8b02795d699bf2730f9b7f16b34c4db25cedd635 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Tue, 2 Jan 2024 21:25:40 +0100 Subject: [PATCH 0029/1333] CSharpier --- src/SharpCompress/Archives/Rar/RarArchiveEntry.cs | 6 ++++-- src/SharpCompress/Common/Rar/RarEntry.cs | 2 +- src/SharpCompress/Readers/Rar/RarReader.cs | 4 +++- tests/SharpCompress.Test/Rar/RarReaderTests.cs | 6 ++---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs index 1ad252d1..fa59b295 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; @@ -42,7 +41,10 @@ public class RarArchiveEntry : RarEntry, IArchiveEntry get { CheckIncomplete(); - return BitConverter.ToUInt32( parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc, 0); + return BitConverter.ToUInt32( + parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc, + 0 + ); } } diff --git a/src/SharpCompress/Common/Rar/RarEntry.cs b/src/SharpCompress/Common/Rar/RarEntry.cs index 92149e14..655264ec 100644 --- a/src/SharpCompress/Common/Rar/RarEntry.cs +++ b/src/SharpCompress/Common/Rar/RarEntry.cs @@ -20,7 +20,7 @@ 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 => BitConverter.ToUInt32(FileHeader.FileCrc, 0); /// /// The path of the file internal to the Rar Archive. diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index 695d47b0..a9ddb1fe 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -75,7 +75,9 @@ public abstract class RarReader : AbstractReader if (Entry.FileHeader.FileCrc.Length > 5) { - return CreateEntryStream(new RarBLAKE2spStream(UnpackV2017.Value, Entry.FileHeader, stream)); + return CreateEntryStream( + new RarBLAKE2spStream(UnpackV2017.Value, Entry.FileHeader, stream) + ); } return CreateEntryStream(new RarCrcStream(UnpackV2017.Value, Entry.FileHeader, stream)); diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index fc78b01c..3f1ebe25 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -186,15 +186,13 @@ public class RarReaderTests : ReaderTests public void Rar_EncryptedFileOnly_Reader() => ReadRar("Rar.encrypted_filesOnly.rar", "test"); [Fact] - public void Rar5_EncryptedFileOnly_Reader() => - ReadRar("Rar5.encrypted_filesOnly.rar", "test"); + 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"); + 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 }); From 6c157def4b84f17c69d9291dd8db7761442b67ad Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Thu, 4 Jan 2024 21:16:07 +0100 Subject: [PATCH 0030/1333] set empty string if password not set --- src/SharpCompress/Common/Rar/CryptKey5.cs | 2 +- tests/SharpCompress.Test/ArchiveTests.cs | 17 +++++++ .../SharpCompress.Test/Rar/RarArchiveTests.cs | 30 +++++++++++ .../SharpCompress.Test/Rar/RarReaderTests.cs | 51 +++++++++++++++++++ tests/SharpCompress.Test/ReaderTests.cs | 23 +++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/Common/Rar/CryptKey5.cs b/src/SharpCompress/Common/Rar/CryptKey5.cs index 46044368..5b4d3981 100644 --- a/src/SharpCompress/Common/Rar/CryptKey5.cs +++ b/src/SharpCompress/Common/Rar/CryptKey5.cs @@ -19,7 +19,7 @@ internal class CryptKey5 : ICryptKey public CryptKey5(string password, Rar5CryptoInfo rar5CryptoInfo) { - _password = password; + _password = password ?? ""; _cryptoInfo = rar5CryptoInfo; } diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index 33bd0ba7..ea37b279 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -258,6 +258,23 @@ public class ArchiveTests : ReaderTests VerifyFiles(); } + protected void ArchiveFileSkip( + string testArchive, + string fileOrder, + ReaderOptions? readerOptions = null + ) + { + 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 /// diff --git a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs index 42e76299..729b7425 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs @@ -611,4 +611,34 @@ public class RarArchiveTests : ArchiveTests [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/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index 3f1ebe25..2690148c 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -378,4 +378,55 @@ 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 be1dbe07..fc91f102 100644 --- a/tests/SharpCompress.Test/ReaderTests.cs +++ b/tests/SharpCompress.Test/ReaderTests.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.IO; using SharpCompress.Common; using SharpCompress.IO; @@ -67,4 +68,26 @@ public abstract class ReaderTests : TestBase } } } + + protected void Iterate( + string testArchive, + string fileOrder, + CompressionType expectedCompression, + ReaderOptions? options = null + ) + { + 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); + } + } + } } From f7c6edf8499558fd88d6dfce7d7aaabf08648404 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Thu, 4 Jan 2024 23:33:39 +0100 Subject: [PATCH 0031/1333] Fix reporting size / position --- src/SharpCompress/IO/DataDescriptorStream.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/IO/DataDescriptorStream.cs b/src/SharpCompress/IO/DataDescriptorStream.cs index 8ba9eb0f..ab06a407 100644 --- a/src/SharpCompress/IO/DataDescriptorStream.cs +++ b/src/SharpCompress/IO/DataDescriptorStream.cs @@ -51,7 +51,7 @@ public class DataDescriptorStream : Stream public override long Position { - get => _stream.Position; + get => _stream.Position - _start; set => _stream.Position = value; } From 46d4b26ebadb8dc2d715628ebbc30ca3d9295054 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Fri, 5 Jan 2024 00:35:24 +0100 Subject: [PATCH 0032/1333] Fix testing under Linux --- tests/SharpCompress.Test/ArchiveTests.cs | 6 ++++++ tests/SharpCompress.Test/ReaderTests.cs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index ea37b279..ca9a4a16 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -264,6 +264,12 @@ public class ArchiveTests : ReaderTests ReaderOptions? readerOptions = null ) { +#if !NETFRAMEWORK + if (!OperatingSystem.IsWindows()) + { + fileOrder = fileOrder.Replace('\\', '/'); + } +#endif var expected = new Stack(fileOrder.Split(' ')); testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using (var archive = ArchiveFactory.Open(testArchive, readerOptions)) diff --git a/tests/SharpCompress.Test/ReaderTests.cs b/tests/SharpCompress.Test/ReaderTests.cs index fc91f102..00ad69e9 100644 --- a/tests/SharpCompress.Test/ReaderTests.cs +++ b/tests/SharpCompress.Test/ReaderTests.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using SharpCompress.Common; @@ -76,6 +77,12 @@ public abstract class ReaderTests : TestBase ReaderOptions? options = null ) { +#if !NETFRAMEWORK + if (!OperatingSystem.IsWindows()) + { + fileOrder = fileOrder.Replace('\\', '/'); + } +#endif var expected = new Stack(fileOrder.Split(' ')); testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); From e0a5ed4bdbf4cfe98c740ec2241d4d9482fe18d1 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Fri, 5 Jan 2024 09:50:58 +0100 Subject: [PATCH 0033/1333] Expose file attributes --- src/SharpCompress/Common/Rar/RarEntry.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/Common/Rar/RarEntry.cs b/src/SharpCompress/Common/Rar/RarEntry.cs index 655264ec..639c9d94 100644 --- a/src/SharpCompress/Common/Rar/RarEntry.cs +++ b/src/SharpCompress/Common/Rar/RarEntry.cs @@ -55,7 +55,12 @@ public abstract class RarEntry : Entry public override bool IsEncrypted => FileHeader.IsEncrypted; /// - /// Entry is password protected and encrypted and cannot be extracted. + /// Entry Windows file attributes + /// + public override int? Attrib => (int)FileHeader.FileAttributes; + + /// + /// Entry is a directory /// public override bool IsDirectory => FileHeader.IsDirectory; From 4477833b1d44a7a60c3e92dcf4587d9d0060f883 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Sat, 6 Jan 2024 00:14:34 +0100 Subject: [PATCH 0034/1333] Issue 771, remove throw on flush for readonly streams --- src/SharpCompress/Common/Rar/RarCryptoWrapper.cs | 2 +- src/SharpCompress/Common/SevenZip/ArchiveReader.cs | 2 +- src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs | 4 ++-- .../Common/Zip/PkwareTraditionalCryptoStream.cs | 7 ++----- src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs | 2 +- src/SharpCompress/Compressors/Filters/BCJ2Filter.cs | 4 ++-- src/SharpCompress/Compressors/Filters/Filter.cs | 4 ++-- src/SharpCompress/Compressors/LZMA/DecoderStream.cs | 4 ++-- .../Compressors/Rar/MultiVolumeReadOnlyStream.cs | 2 +- src/SharpCompress/Compressors/Xz/ReadOnlyStream.cs | 4 ++-- src/SharpCompress/IO/BufferedSubStream.cs | 4 ++-- src/SharpCompress/IO/DataDescriptorStream.cs | 2 +- src/SharpCompress/IO/ReadOnlySubStream.cs | 2 +- src/SharpCompress/IO/RewindableStream.cs | 2 +- tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs | 4 ++-- tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs | 4 ++-- 16 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index 5f5e8de7..e3403ecd 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -17,7 +17,7 @@ internal sealed class RarCryptoWrapper : Stream _rijndael = new BlockTransformer(key.Transformer(salt)); } - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); diff --git a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs index 42b5b6b2..c1376ad9 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs @@ -1393,7 +1393,7 @@ internal class ArchiveReader public override bool CanWrite => false; - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs b/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs index d61b04a2..2a340dea 100644 --- a/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs +++ b/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using SharpCompress.IO; @@ -47,7 +47,7 @@ internal class TarReadOnlySubStream : NonDisposingStream public override bool CanWrite => false; - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs index 273a7a3c..6ac48c6f 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,10 +87,7 @@ internal class PkwareTraditionalCryptoStream : Stream _stream.Write(encrypted, 0, encrypted.Length); } - public override void Flush() - { - //throw new NotSupportedException(); - } + public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); diff --git a/src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs b/src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs index 093ac034..5742458a 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() => throw new NotSupportedException(); + public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) { diff --git a/src/SharpCompress/Compressors/Filters/BCJ2Filter.cs b/src/SharpCompress/Compressors/Filters/BCJ2Filter.cs index f658b385..1ed531cc 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() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => _baseStream.Length + _data1.Length + _data2.Length; diff --git a/src/SharpCompress/Compressors/Filters/Filter.cs b/src/SharpCompress/Compressors/Filters/Filter.cs index 93d95195..aa5e620d 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() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => _baseStream.Length; diff --git a/src/SharpCompress/Compressors/LZMA/DecoderStream.cs b/src/SharpCompress/Compressors/LZMA/DecoderStream.cs index 16865351..a3dbf37f 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() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs b/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs index 460d92eb..eda9c765 100644 --- a/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs +++ b/src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs @@ -130,7 +130,7 @@ internal sealed class MultiVolumeReadOnlyStream : Stream public byte[] CurrentCrc { get; private set; } - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/Compressors/Xz/ReadOnlyStream.cs b/src/SharpCompress/Compressors/Xz/ReadOnlyStream.cs index 71614df9..75188483 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() => throw new NotSupportedException(); + public override void Flush() { } public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); diff --git a/src/SharpCompress/IO/BufferedSubStream.cs b/src/SharpCompress/IO/BufferedSubStream.cs index 99e2bfef..0b98f9d0 100644 --- a/src/SharpCompress/IO/BufferedSubStream.cs +++ b/src/SharpCompress/IO/BufferedSubStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace SharpCompress.IO; @@ -26,7 +26,7 @@ internal class BufferedSubStream : NonDisposingStream public override bool CanWrite => false; - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => BytesLeftToRead; diff --git a/src/SharpCompress/IO/DataDescriptorStream.cs b/src/SharpCompress/IO/DataDescriptorStream.cs index 8ba9eb0f..b9a97389 100644 --- a/src/SharpCompress/IO/DataDescriptorStream.cs +++ b/src/SharpCompress/IO/DataDescriptorStream.cs @@ -45,7 +45,7 @@ public class DataDescriptorStream : Stream public override bool CanWrite => false; - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => _stream.Length; diff --git a/src/SharpCompress/IO/ReadOnlySubStream.cs b/src/SharpCompress/IO/ReadOnlySubStream.cs index c0b39d54..55c5b575 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() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => throw new NotSupportedException(); diff --git a/src/SharpCompress/IO/RewindableStream.cs b/src/SharpCompress/IO/RewindableStream.cs index ccdc8ee0..ff7fe3d0 100644 --- a/src/SharpCompress/IO/RewindableStream.cs +++ b/src/SharpCompress/IO/RewindableStream.cs @@ -75,7 +75,7 @@ public class RewindableStream : Stream public override bool CanWrite => false; - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => stream.Length; diff --git a/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs index 194e7788..062351a1 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; @@ -27,7 +27,7 @@ public class FlushOnDisposeStream : Stream, IDisposable set => inner.Position = value; } - public override void Flush() => throw new NotImplementedException(); + public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) => inner.Read(buffer, offset, count); diff --git a/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs b/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs index cef93a38..e18bd707 100644 --- a/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs +++ b/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; namespace SharpCompress.Test.Mocks; @@ -29,7 +29,7 @@ public class ForwardOnlyStream : Stream public override bool CanSeek => false; public override bool CanWrite => false; - public override void Flush() => throw new NotSupportedException(); + public override void Flush() { } public override long Length => throw new NotSupportedException(); From d69559e9c7c22b832004ff931c3f1493c51e3bad Mon Sep 17 00:00:00 2001 From: Daniel Nash Date: Fri, 12 Jan 2024 09:15:22 -0500 Subject: [PATCH 0035/1333] Add support for the UnixTimeExtraField in Zip files Fixes #802 --- .../Zip/Headers/DirectoryEntryHeader.cs | 30 +++++++ .../Common/Zip/Headers/LocalEntryHeader.cs | 30 +++++++ .../Headers/LocalEntryHeaderExtraFactory.cs | 84 ++++++++++++++++++- 3 files changed, 142 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index fc2cb262..184bdfa3 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs @@ -85,6 +85,36 @@ 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 93cc55ac..d0a87100 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs @@ -64,6 +64,36 @@ 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 80ec9b8f..88e4a187 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,7 +13,8 @@ internal enum ExtraDataType : ushort // Third Party Mappings // -Info-ZIP Unicode Path Extra Field UnicodePathExtraField = 0x7075, - Zip64ExtendedInformationExtraField = 0x0001 + Zip64ExtendedInformationExtraField = 0x0001, + UnixTimeExtraField = 0x5455 } internal class ExtraData @@ -145,6 +146,84 @@ 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) => @@ -154,6 +233,7 @@ 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) }; } From f515ff36b684b395c1e65043e17ab442fd65c1f0 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 15 Jan 2024 08:21:36 +0000 Subject: [PATCH 0036/1333] Mark for 0.36.0 --- src/SharpCompress/SharpCompress.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index c5bd96d9..318b5de8 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -2,9 +2,9 @@ SharpCompress - Pure C# Decompression/Compression en-US - 0.35.0 - 0.35.0 - 0.35.0 + 0.36.0 + 0.36.0 + 0.36.0 Adam Hathcock net462;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0 SharpCompress From 14c973558b975d6288788fe53882517283b5a4ec Mon Sep 17 00:00:00 2001 From: Daniel Nash Date: Fri, 26 Jan 2024 10:54:41 -0500 Subject: [PATCH 0037/1333] Zip: Use last modified time from basic header when validating zip decryption The last modified time used for zip decryption validation must be the one from the basic header. If UnixTimeExtraFields are present, the previous implementation was attempting to verify against that value instead. Fixed #804 --- .../Common/Zip/Headers/DirectoryEntryHeader.cs | 4 ++-- .../Common/Zip/Headers/LocalEntryHeader.cs | 4 ++-- .../Common/Zip/Headers/ZipFileEntry.cs | 18 ++++++++++++++++++ .../Zip/PkwareTraditionalEncryptionData.cs | 2 +- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index 184bdfa3..ef40a6f3 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(); - LastModifiedTime = reader.ReadUInt16(); - LastModifiedDate = reader.ReadUInt16(); + OriginalLastModifiedTime = LastModifiedTime = reader.ReadUInt16(); + OriginalLastModifiedDate = LastModifiedDate = reader.ReadUInt16(); Crc = reader.ReadUInt32(); CompressedSize = reader.ReadUInt32(); UncompressedSize = reader.ReadUInt32(); diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs index d0a87100..a7c83b24 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(); - LastModifiedTime = reader.ReadUInt16(); - LastModifiedDate = reader.ReadUInt16(); + OriginalLastModifiedTime = LastModifiedTime = reader.ReadUInt16(); + OriginalLastModifiedDate = LastModifiedDate = reader.ReadUInt16(); Crc = reader.ReadUInt32(); CompressedSize = reader.ReadUInt32(); UncompressedSize = reader.ReadUInt32(); diff --git a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs index 98d230f5..edba3ebe 100644 --- a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs +++ b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs @@ -67,8 +67,26 @@ internal abstract class ZipFileEntry : ZipHeader 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; } diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs index 353000d8..d6c4e96d 100644 --- a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs @@ -39,7 +39,7 @@ internal class PkwareTraditionalEncryptionData { throw new CryptographicException("The password did not match."); } - if (plainTextHeader[11] != (byte)((header.LastModifiedTime >> 8) & 0xff)) + if (plainTextHeader[11] != (byte)((header.OriginalLastModifiedTime >> 8) & 0xff)) { throw new CryptographicException("The password did not match."); } From 225aaab4f4cd62b94277aed73c5fed507afb6c1a Mon Sep 17 00:00:00 2001 From: Twan van Dongen Date: Sat, 27 Jan 2024 18:28:46 +0100 Subject: [PATCH 0038/1333] Support for decompressing Zip Shrink (method:1) added --- src/SharpCompress/Common/CompressionType.cs | 3 +- .../Common/Zip/ZipCompressionMethod.cs | 1 + src/SharpCompress/Common/Zip/ZipEntry.cs | 4 + src/SharpCompress/Common/Zip/ZipFilePart.cs | 6 + .../Compressors/Shrink/BitStream.cs | 86 ++++ .../Compressors/Shrink/HwUnshrink.cs | 394 ++++++++++++++++++ .../Compressors/Shrink/ShrinkStream.cs | 67 +++ .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 8 + tests/TestArchives/Archives/Zip.shrink.zip | Bin 0 -> 71199 bytes 9 files changed, 568 insertions(+), 1 deletion(-) create mode 100644 src/SharpCompress/Compressors/Shrink/BitStream.cs create mode 100644 src/SharpCompress/Compressors/Shrink/HwUnshrink.cs create mode 100644 src/SharpCompress/Compressors/Shrink/ShrinkStream.cs create mode 100644 tests/TestArchives/Archives/Zip.shrink.zip diff --git a/src/SharpCompress/Common/CompressionType.cs b/src/SharpCompress/Common/CompressionType.cs index 11263245..b26e5a95 100644 --- a/src/SharpCompress/Common/CompressionType.cs +++ b/src/SharpCompress/Common/CompressionType.cs @@ -14,5 +14,6 @@ public enum CompressionType LZip, Xz, Unknown, - Deflate64 + Deflate64, + Shrink } diff --git a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs index 13c2dbe7..a98ed667 100644 --- a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs +++ b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs @@ -3,6 +3,7 @@ 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 2c544b94..61e1b6af 100644 --- a/src/SharpCompress/Common/Zip/ZipEntry.cs +++ b/src/SharpCompress/Common/Zip/ZipEntry.cs @@ -52,6 +52,10 @@ public class ZipEntry : Entry { return CompressionType.None; } + case ZipCompressionMethod.Shrink: + { + return CompressionType.Shrink; + } default: { return CompressionType.Unknown; diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index faefdf15..0463c97f 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -9,6 +9,7 @@ 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; @@ -79,6 +80,10 @@ 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); @@ -192,6 +197,7 @@ 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/Compressors/Shrink/BitStream.cs b/src/SharpCompress/Compressors/Shrink/BitStream.cs new file mode 100644 index 00000000..76b59041 --- /dev/null +++ b/src/SharpCompress/Compressors/Shrink/BitStream.cs @@ -0,0 +1,86 @@ +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) + { + int 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 new file mode 100644 index 00000000..ca3dcbe6 --- /dev/null +++ b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs @@ -0,0 +1,394 @@ +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 (int i = 0; i <= byte.MaxValue; i++) + { + codeTab[i].prefixCode = (ushort)i; + codeTab[i].extByte = (byte)i; + codeTab[i].len = 1; + } + + for (int i = byte.MaxValue + 1; i <= MAX_CODE; i++) + { + codeTab[i].prefixCode = INVALID_CODE; + } + } + + private static void UnshrinkPartialClear(CodeTabEntry[] codeTab, ref CodeQueue queue) + { + bool[] isPrefix = new bool[MAX_CODE + 1]; + int codeQueueSize; + + // Scan for codes that have been used as a prefix. + for (int 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 (int 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) + { + CodeTabEntry[] codeTab = new CodeTabEntry[HASHTAB_SIZE]; + CodeQueue 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. + UnshrnkStatus 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 (int 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); + return q.codes[q.nextIdx]; + } + private static ushort CodeQueueRemoveNext(ref CodeQueue q) + { + ushort 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 new file mode 100644 index 00000000..7926d093 --- /dev/null +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs @@ -0,0 +1,67 @@ +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; + } + byte[] src = new byte[_compressedSize]; + inStream.Read(src, offset, (int)_compressedSize); + int srcUsed = 0; + int dstUsed = 0; + + HwUnshrink.Unshrink(src, (int)_compressedSize, out srcUsed, _byteOut, (int)_uncompressedSize, out dstUsed); + _outBytesCount = _byteOut.Length; + + for (int 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/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index fde87dc6..ebcb4243 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -16,6 +16,14 @@ 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"); diff --git a/tests/TestArchives/Archives/Zip.shrink.zip b/tests/TestArchives/Archives/Zip.shrink.zip new file mode 100644 index 0000000000000000000000000000000000000000..697c7e0047de844f03018b358fdc988dbd33cd4d GIT binary patch literal 71199 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 P2WeV`#>N Date: Sat, 27 Jan 2024 18:59:56 +0100 Subject: [PATCH 0039/1333] Refrormatted using CSharpier --- src/SharpCompress/Common/Zip/ZipFilePart.cs | 7 ++- .../Compressors/Shrink/BitStream.cs | 37 ++++++------ .../Compressors/Shrink/HwUnshrink.cs | 59 +++++++++++++++---- .../Compressors/Shrink/ShrinkStream.cs | 32 ++++++++-- 4 files changed, 100 insertions(+), 35 deletions(-) diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index 0463c97f..f8a0e8a8 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -82,7 +82,12 @@ internal abstract class ZipFilePart : FilePart } case ZipCompressionMethod.Shrink: { - return new ShrinkStream(stream, CompressionMode.Decompress, Header.CompressedSize, Header.UncompressedSize); + return new ShrinkStream( + stream, + CompressionMode.Decompress, + Header.CompressedSize, + Header.UncompressedSize + ); } case ZipCompressionMethod.Deflate: { diff --git a/src/SharpCompress/Compressors/Shrink/BitStream.cs b/src/SharpCompress/Compressors/Shrink/BitStream.cs index 76b59041..ef01e2af 100644 --- a/src/SharpCompress/Compressors/Shrink/BitStream.cs +++ b/src/SharpCompress/Compressors/Shrink/BitStream.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; - namespace SharpCompress.Compressors.Shrink { internal class BitStream @@ -14,26 +13,26 @@ namespace SharpCompress.Compressors.Shrink private int _byteIdx; private int _bitIdx; private int _bitsLeft; - private ulong _bitBuffer; + 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 + 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) diff --git a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs index ca3dcbe6..04f38c2b 100644 --- a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs +++ b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs @@ -69,9 +69,16 @@ namespace SharpCompress.Compressors.Shrink queue.nextIdx = 0; } - private static bool ReadCode(BitStream stream, ref int codeSize, CodeTabEntry[] codeTab, ref CodeQueue queue, out int nextCode) + private static bool ReadCode( + BitStream stream, + ref int codeSize, + CodeTabEntry[] codeTab, + ref CodeQueue queue, + out int nextCode + ) { - int code, controlCode; + int code, + controlCode; code = (int)stream.NextBits(codeSize); if (!stream.Advance(codeSize)) @@ -130,8 +137,17 @@ namespace SharpCompress.Compressors.Shrink 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) + 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; @@ -174,7 +190,7 @@ namespace SharpCompress.Compressors.Shrink // Output a string of unknown length. //assert(codeTab[code].len == UNKNOWN_LEN); prefixCode = codeTab[code].prefixCode; - // assert(prefixCode > CONTROL_CODE); + // assert(prefixCode > CONTROL_CODE); if (prefixCode == queue.codes[queue.nextIdx]) { @@ -215,13 +231,24 @@ namespace SharpCompress.Compressors.Shrink return UnshrnkStatus.Ok; } - public static UnshrnkStatus Unshrink(byte[] src, int srcLen, out int srcUsed, byte[] dst, int dstCap, out int dstUsed) + public static UnshrnkStatus Unshrink( + byte[] src, + int srcLen, + out int srcUsed, + byte[] dst, + int dstCap, + out int dstUsed + ) { CodeTabEntry[] codeTab = new CodeTabEntry[HASHTAB_SIZE]; CodeQueue queue = new CodeQueue(); var stream = new BitStream(src, srcLen); - int codeSize, dstPos, len; - int currCode, prevCode, newCode; + int codeSize, + dstPos, + len; + int currCode, + prevCode, + newCode; byte firstByte; CodeTabInit(codeTab); @@ -296,7 +323,17 @@ namespace SharpCompress.Compressors.Shrink } // Output the string represented by the current code. - UnshrnkStatus status = OutputCode(currCode, dst, dstPos, dstCap, prevCode, codeTab, ref queue, out firstByte, out len); + UnshrnkStatus status = OutputCode( + currCode, + dst, + dstPos, + dstCap, + prevCode, + codeTab, + ref queue, + out firstByte, + out len + ); if (status != UnshrnkStatus.Ok) { srcUsed = stream.BytesRead; @@ -308,7 +345,7 @@ namespace SharpCompress.Compressors.Shrink var c = currCode; for (int i = 0; i < len; i++) { - // assert(codeTab[c].len == len - i); + // assert(codeTab[c].len == len - i); //assert(codeTab[c].extByte == dst[dstPos + len - i - 1]); c = codeTab[c].prefixCode; } @@ -376,11 +413,13 @@ namespace SharpCompress.Compressors.Shrink 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); return q.codes[q.nextIdx]; } + private static ushort CodeQueueRemoveNext(ref CodeQueue q) { ushort code = CodeQueueNext(ref q); diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs index 7926d093..52bba1ad 100644 --- a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs @@ -17,7 +17,12 @@ internal class ShrinkStream : Stream private byte[] _byteOut; private long _outBytesCount; - public ShrinkStream(Stream stream, CompressionMode compressionMode, long compressedSize, long uncompressedSize) + public ShrinkStream( + Stream stream, + CompressionMode compressionMode, + long compressedSize, + long uncompressedSize + ) { inStream = stream; _compressionMode = compressionMode; @@ -36,9 +41,14 @@ internal class ShrinkStream : Stream public override long Length => _uncompressedSize; - public override long Position { get => _outBytesCount; set => throw new NotImplementedException(); } + 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) @@ -50,7 +60,14 @@ internal class ShrinkStream : Stream int srcUsed = 0; int dstUsed = 0; - HwUnshrink.Unshrink(src, (int)_compressedSize, out srcUsed, _byteOut, (int)_uncompressedSize, out dstUsed); + HwUnshrink.Unshrink( + src, + (int)_compressedSize, + out srcUsed, + _byteOut, + (int)_uncompressedSize, + out dstUsed + ); _outBytesCount = _byteOut.Length; for (int index = 0; index < _outBytesCount; ++index) @@ -61,7 +78,12 @@ internal class ShrinkStream : Stream _outBytesCount = 0; return (int)tmp; } - public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); + + 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(); + + public override void Write(byte[] buffer, int offset, int count) => + throw new NotImplementedException(); } From 226ce340f28bd783eac157700681609389d581c9 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 14 Mar 2024 03:52:10 -0400 Subject: [PATCH 0040/1333] rar5 read FHEXTRA_REDIR and expose via RarEntry NOTE: api user should skip entries where RarEntry.IsRedir is true and not call OpenEntryStream() --- .../Common/Rar/Headers/FileHeader.cs | 26 ++++++++++++++----- src/SharpCompress/Common/Rar/Headers/Flags.cs | 14 ++++++++++ src/SharpCompress/Common/Rar/RarEntry.cs | 4 +++ .../Compressors/Rar/RarStream.cs | 7 +++++ src/SharpCompress/Readers/Rar/RarReader.cs | 6 +++++ 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index 57cd5c71..86b56055 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -109,7 +109,7 @@ internal class FileHeader : RarHeader const ushort FHEXTRA_HASH = 0x02; const ushort FHEXTRA_HTIME = 0x03; // const ushort FHEXTRA_VERSION = 0x04; - // const ushort FHEXTRA_REDIR = 0x05; + const ushort FHEXTRA_REDIR = 0x05; // const ushort FHEXTRA_UOWNER = 0x06; // const ushort FHEXTRA_SUBDATA = 0x07; @@ -120,7 +120,6 @@ internal class FileHeader : RarHeader var type = reader.ReadRarVIntUInt16(); switch (type) { - //TODO case FHEXTRA_CRYPT: // file encryption { @@ -171,11 +170,17 @@ internal class FileHeader : RarHeader // // } // break; - // case FHEXTRA_REDIR: // file system redirection - // { - // - // } - // 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 // { // @@ -189,6 +194,7 @@ 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 @@ -437,6 +443,12 @@ 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; } diff --git a/src/SharpCompress/Common/Rar/Headers/Flags.cs b/src/SharpCompress/Common/Rar/Headers/Flags.cs index 3414d1a3..990dbc99 100644 --- a/src/SharpCompress/Common/Rar/Headers/Flags.cs +++ b/src/SharpCompress/Common/Rar/Headers/Flags.cs @@ -157,3 +157,17 @@ 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/RarEntry.cs b/src/SharpCompress/Common/Rar/RarEntry.cs index 639c9d94..30de1037 100644 --- a/src/SharpCompress/Common/Rar/RarEntry.cs +++ b/src/SharpCompress/Common/Rar/RarEntry.cs @@ -66,6 +66,10 @@ public abstract class RarEntry : Entry 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/Compressors/Rar/RarStream.cs b/src/SharpCompress/Compressors/Rar/RarStream.cs index 0bc2e054..cebc81a1 100644 --- a/src/SharpCompress/Compressors/Rar/RarStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarStream.cs @@ -86,6 +86,13 @@ 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; } diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index a9ddb1fe..ac346262 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -64,6 +65,11 @@ 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 From 93e181cfd99421a77cfe8f357d2cf7182616fbef Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 08:29:30 +0000 Subject: [PATCH 0041/1333] update csharpier --- .config/dotnet-tools.json | 2 +- src/SharpCompress/Archives/Rar/RarArchive.cs | 8 ++-- .../Zip/Headers/DirectoryEntryHeader.cs | 4 +- .../Common/Zip/Headers/LocalEntryHeader.cs | 4 +- .../Common/Zip/StreamingZipHeaderFactory.cs | 13 +++---- .../Common/Zip/ZipHeaderFactory.cs | 4 +- .../Compressors/Deflate64/InflaterManaged.cs | 4 +- .../Compressors/LZMA/LzmaDecoder.cs | 8 ++-- .../Compressors/LZMA/LzmaEncoder.cs | 39 +++++++++---------- .../Compressors/PPMd/I1/Allocator.cs | 15 ++++--- .../SharpCompress.Test/Tar/TarArchiveTests.cs | 4 +- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 24 ++++++------ 12 files changed, 63 insertions(+), 66 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 9e8f2784..a4713c52 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "csharpier": { - "version": "0.26.7", + "version": "0.27.3", "commands": [ "dotnet-csharpier" ] diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 29d733f6..5d1883f5 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -40,9 +40,11 @@ public class RarArchive : AbstractArchive streams[1].Position = 0; SrcStream.Position = 0; - return srcStream.Streams.Select( - a => new StreamRarArchiveVolume(a, ReaderOptions, idx++) - ); + return srcStream.Streams.Select(a => new StreamRarArchiveVolume( + a, + ReaderOptions, + idx++ + )); } else //split mode or single file { diff --git a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs index ef40a6f3..2b26d298 100644 --- a/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.cs @@ -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) { diff --git a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs index a7c83b24..1e3dc62d 100644 --- a/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs +++ b/src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.cs @@ -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) { diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index e76a2856..34dd8798 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -97,13 +97,12 @@ 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/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 8a58e220..628cbb20 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -142,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/Deflate64/InflaterManaged.cs b/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs index 6a3c226b..4e11854f 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/LZMA/LzmaDecoder.cs b/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs index 31039761..b460e1be 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs @@ -318,9 +318,8 @@ 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; @@ -355,7 +354,8 @@ 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 558fe37b..e42f8069 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs @@ -553,9 +553,8 @@ 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 { @@ -713,9 +712,8 @@ 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) @@ -995,9 +993,8 @@ 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; @@ -1069,7 +1066,8 @@ 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, @@ -1088,7 +1086,8 @@ 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--) @@ -1174,7 +1173,8 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + _isMatch[ (state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext - ].GetPrice0() + ] + .GetPrice0() + _literalEncoder .GetSubCoder( position + lenTest, @@ -1194,7 +1194,8 @@ 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(); @@ -1243,10 +1244,8 @@ 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; @@ -1321,10 +1320,8 @@ 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 diff --git a/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs b/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs index 7b677a93..c4d8aa4b 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/Allocator.cs @@ -395,10 +395,8 @@ 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() @@ -457,10 +455,11 @@ 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/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index 490698b2..f1eba627 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -198,8 +198,8 @@ public class TarArchiveTests : ArchiveTests using (var archive = TarArchive.Open(unmodified)) { - var entry = archive.Entries.Single( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + var entry = archive.Entries.Single(x => + x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ); archive.RemoveEntry(entry); archive.SaveTo(scratchPath, CompressionType.None); diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index ebcb4243..94012e74 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -192,8 +192,8 @@ public class ZipArchiveTests : ArchiveTests using (var archive = ZipArchive.Open(unmodified)) { - var entry = archive.Entries.Single( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + var entry = archive.Entries.Single(x => + x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ); archive.RemoveEntry(entry); @@ -250,18 +250,18 @@ public class ZipArchiveTests : ArchiveTests using (ZipArchive vfs = (ZipArchive)ArchiveFactory.Open(scratchPath)) { - var e = vfs.Entries.First( - v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + 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) + vfs.Entries.FirstOrDefault(v => + v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); Assert.Null( - ((IArchive)vfs).Entries.FirstOrDefault( - v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ((IArchive)vfs).Entries.FirstOrDefault(v => + v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); } @@ -399,13 +399,13 @@ public class ZipArchiveTests : ArchiveTests { archive.AddAllFromDirectory(SCRATCH_FILES_PATH); archive.RemoveEntry( - archive.Entries.Single( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + archive.Entries.Single(x => + x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); Assert.Null( - archive.Entries.FirstOrDefault( - x => x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + archive.Entries.FirstOrDefault(x => + x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); } From 0299232cb52031416a6f95b355ad84621f6b1043 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 08:37:17 +0000 Subject: [PATCH 0042/1333] just using rider to clean up --- src/SharpCompress/Common/Rar/CryptKey5.cs | 32 +- tests/SharpCompress.Test/ADCTest.cs | 5 +- tests/SharpCompress.Test/ArchiveTests.cs | 115 +++---- .../Filters/BranchExecTests.cs | 12 - .../GZip/GZipArchiveTests.cs | 3 +- .../GZip/GZipReaderTests.cs | 3 +- .../SharpCompress.Test/Rar/RarArchiveTests.cs | 22 +- .../SharpCompress.Test/Rar/RarReaderTests.cs | 48 ++- tests/SharpCompress.Test/ReaderTests.cs | 13 +- .../SevenZip/SevenZipArchiveTests.cs | 6 +- .../Streams/LzmaStreamTests.cs | 3 - .../SharpCompress.Test/Tar/TarArchiveTests.cs | 174 +++++------ .../SharpCompress.Test/Tar/TarReaderTests.cs | 224 ++++++-------- tests/SharpCompress.Test/WriterTests.cs | 2 +- tests/SharpCompress.Test/Xz/XZHeaderTests.cs | 48 ++- tests/SharpCompress.Test/Xz/XZIndexTests.cs | 68 ++-- tests/SharpCompress.Test/Xz/XZStreamTests.cs | 24 +- tests/SharpCompress.Test/Xz/XZTestsBase.cs | 3 - tests/SharpCompress.Test/Zip/Zip64Tests.cs | 11 +- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 290 ++++++++---------- .../SharpCompress.Test/Zip/ZipReaderTests.cs | 25 +- 21 files changed, 487 insertions(+), 644 deletions(-) diff --git a/src/SharpCompress/Common/Rar/CryptKey5.cs b/src/SharpCompress/Common/Rar/CryptKey5.cs index 5b4d3981..31e2c7b8 100644 --- a/src/SharpCompress/Common/Rar/CryptKey5.cs +++ b/src/SharpCompress/Common/Rar/CryptKey5.cs @@ -34,30 +34,28 @@ internal class CryptKey5 : ICryptKey int keyLength ) { - using (HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password))) + using HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)); + byte[] block = hmac.ComputeHash(salt); + byte[] finalHash = (byte[])block.Clone(); + + var loop = new int[] { iterations, 17, 17 }; + var res = new List { }; + + for (int x = 0; x < 3; x++) { - byte[] block = hmac.ComputeHash(salt); - byte[] finalHash = (byte[])block.Clone(); - - var loop = new int[] { iterations, 17, 17 }; - var res = new List { }; - - for (int x = 0; x < 3; x++) + for (int i = 1; i < loop[x]; i++) { - for (int i = 1; i < loop[x]; i++) + block = hmac.ComputeHash(block); + for (int j = 0; j < finalHash.Length; j++) { - block = hmac.ComputeHash(block); - for (int j = 0; j < finalHash.Length; j++) - { - finalHash[j] ^= block[j]; - } + finalHash[j] ^= block[j]; } - - res.Add((byte[])finalHash.Clone()); } - return res; + res.Add((byte[])finalHash.Clone()); } + + return res; } public ICryptoTransform Transformer(byte[] salt) diff --git a/tests/SharpCompress.Test/ADCTest.cs b/tests/SharpCompress.Test/ADCTest.cs index 11bb2fb0..66349a07 100644 --- a/tests/SharpCompress.Test/ADCTest.cs +++ b/tests/SharpCompress.Test/ADCTest.cs @@ -24,7 +24,6 @@ // 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; @@ -72,7 +71,7 @@ public class ADCTest : TestBase 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, CompressionMode.Decompress); + using var decStream = new ADCStream(cmpFs); var test = new byte[262144]; decStream.Read(test, 0, test.Length); @@ -88,7 +87,7 @@ public class ADCTest : TestBase 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, CompressionMode.Decompress); + using var decStream = new ADCStream(cmpFs); using var decMs = new MemoryStream(); var test = new byte[512]; var count = 0; diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index ca9a4a16..f4e92b15 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,19 +138,12 @@ public class ArchiveTests : ReaderTests ) ) { - try + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) { - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) - { - entry.WriteToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } - ); - } - } - catch (IndexOutOfRangeException) - { - throw; + entry.WriteToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); } } VerifyFiles(); @@ -177,19 +170,12 @@ public class ArchiveTests : ReaderTests ) ) { - try + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) { - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) - { - entry.WriteToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } - ); - } - } - catch (IndexOutOfRangeException) - { - throw; + entry.WriteToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); } } VerifyFiles(); @@ -206,7 +192,7 @@ public class ArchiveTests : ReaderTests testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x)) ); - protected void ArchiveOpenEntryVolumeIndexTest( + private void ArchiveOpenEntryVolumeIndexTest( int[][] results, ReaderOptions? readerOptions, IEnumerable testArchives @@ -217,28 +203,21 @@ public class ArchiveTests : ReaderTests testArchives.Select(f => new FileInfo(f)), readerOptions ); - try + var idx = 0; + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) { - 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 - ); + 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++; - } - } - catch (IndexOutOfRangeException) - { - throw; + idx++; } } @@ -251,7 +230,7 @@ public class ArchiveTests : ReaderTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -272,12 +251,10 @@ public class ArchiveTests : ReaderTests #endif var expected = new Stack(fileOrder.Split(' ')); testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); - using (var archive = ArchiveFactory.Open(testArchive, readerOptions)) + using var archive = ArchiveFactory.Open(testArchive, readerOptions); + foreach (var entry in archive.Entries) { - foreach (var entry in archive.Entries) - { - Assert.Equal(expected.Pop(), entry.Key); - } + Assert.Equal(expected.Pop(), entry.Key); } } @@ -293,7 +270,7 @@ public class ArchiveTests : ReaderTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() + new ExtractionOptions { ExtractFullPath = true, Overwrite = true, @@ -309,25 +286,25 @@ public class ArchiveTests : ReaderTests protected void ArchiveDeltaDistanceRead(string testArchive) { testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); - using (var archive = Archives.ArchiveFactory.Open(testArchive, null)) - using (var reader = archive.ExtractAllEntries()) - while (reader.MoveToNextEntry()) + using var archive = ArchiveFactory.Open(testArchive); + using var reader = archive.ExtractAllEntries(); + while (reader.MoveToNextEntry()) + { + if (!reader.Entry.IsDirectory) { - if (!reader.Entry.IsDirectory) + var memory = new MemoryStream(); + reader.WriteEntryTo(memory); + + memory.Position = 0; + + for (int y = 0; y < 9; y++) + for (int x = 0; x < 256; x++) { - var memory = new MemoryStream(); - reader.WriteEntryTo(memory); - - 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()); + Assert.Equal(x, memory.ReadByte()); } + + Assert.Equal(-1, memory.ReadByte()); } + } } } diff --git a/tests/SharpCompress.Test/Filters/BranchExecTests.cs b/tests/SharpCompress.Test/Filters/BranchExecTests.cs index 5c576dcc..e43318a9 100644 --- a/tests/SharpCompress.Test/Filters/BranchExecTests.cs +++ b/tests/SharpCompress.Test/Filters/BranchExecTests.cs @@ -13,7 +13,6 @@ namespace SharpCompress.Test.Filters; public class BranchExecTests { private static byte[] x86resultData { get; } = - new byte[] { 0x12, 0x00, @@ -96,7 +95,6 @@ public class BranchExecTests }; private static byte[] x86Data { get; } = - new byte[] { 0x12, 0x00, @@ -179,7 +177,6 @@ public class BranchExecTests }; private static byte[] ppcResultData { get; } = - new byte[] { 0xF8, 0x6B, @@ -280,7 +277,6 @@ public class BranchExecTests }; private static byte[] ppcData { get; } = - new byte[] { 0xF8, 0x6B, @@ -381,7 +377,6 @@ public class BranchExecTests }; private static byte[] armResultData { get; } = - new byte[] { 0x7C, 0xFC, @@ -482,7 +477,6 @@ public class BranchExecTests }; private static byte[] armData { get; } = - new byte[] { 0x7C, 0xFC, @@ -583,7 +577,6 @@ public class BranchExecTests }; private static byte[] armtResultData { get; } = - new byte[] { 0x95, 0x23, @@ -700,7 +693,6 @@ public class BranchExecTests }; private static byte[] armtData { get; } = - new byte[] { 0x95, 0x23, @@ -817,7 +809,6 @@ public class BranchExecTests }; private static byte[] ia64ResultData { get; } = - new byte[] { 0x4D, 0xF8, @@ -918,7 +909,6 @@ public class BranchExecTests }; private static byte[] ia64Data { get; } = - new byte[] { 0x4D, 0xF8, @@ -1019,7 +1009,6 @@ public class BranchExecTests }; private static byte[] sparcResultData { get; } = - new byte[] { 0x78, 0x2E, @@ -1102,7 +1091,6 @@ public class BranchExecTests }; private static byte[] sparcData { get; } = - new byte[] { 0x78, 0x2E, diff --git a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs index e47c339c..5b497d9f 100644 --- a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using SharpCompress.Archives; using SharpCompress.Archives.GZip; +using SharpCompress.Archives.Tar; using Xunit; namespace SharpCompress.Test.GZip; @@ -92,7 +93,7 @@ public class GZipArchiveTests : ArchiveTests Assert.Equal(size, tarStream.Length); using (var entryStream = archiveEntry.OpenEntryStream()) { - var result = Archives.Tar.TarArchive.IsTarFile(entryStream); + var result = TarArchive.IsTarFile(entryStream); } Assert.Equal(size, tarStream.Length); using (var entryStream = archiveEntry.OpenEntryStream()) diff --git a/tests/SharpCompress.Test/GZip/GZipReaderTests.cs b/tests/SharpCompress.Test/GZip/GZipReaderTests.cs index b5a3d501..9d475fd5 100644 --- a/tests/SharpCompress.Test/GZip/GZipReaderTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipReaderTests.cs @@ -1,6 +1,7 @@ using System.IO; using SharpCompress.Common; using SharpCompress.IO; +using SharpCompress.Readers.GZip; using Xunit; namespace SharpCompress.Test.GZip; @@ -17,7 +18,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 = Readers.GZip.GZipReader.Open(new RewindableStream(stream)); + using var reader = GZipReader.Open(new RewindableStream(stream)); while (reader.MoveToNextEntry()) // Crash here { Assert.NotEqual(0, reader.Entry.Size); diff --git a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs index 729b7425..513ba277 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs @@ -68,7 +68,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 +79,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 +98,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 +106,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -137,7 +137,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -146,13 +146,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 +175,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -266,7 +266,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -320,7 +320,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 } ) ) { @@ -328,7 +328,7 @@ public class RarArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index 2690148c..981bd8ee 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -52,7 +52,7 @@ public class RarReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -81,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" } ) ) { @@ -89,7 +89,7 @@ public class RarReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -143,7 +143,7 @@ public class RarReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -239,16 +239,14 @@ 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 } ); } } @@ -262,14 +260,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 } ); } } @@ -297,7 +295,7 @@ 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.Contains("jpg")) @@ -305,7 +303,7 @@ public class RarReaderTests : ReaderTests Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -320,7 +318,7 @@ 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.Contains("jpg")) @@ -328,7 +326,7 @@ public class RarReaderTests : ReaderTests Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -348,19 +346,15 @@ 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" } - ) - ) + 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()) { - while (reader.MoveToNextEntry()) - { - // - } + // } } @@ -370,7 +364,7 @@ public class RarReaderTests : ReaderTests ); using var reader = ReaderFactory.Open( stream, - new ReaderOptions() { LookForHeader = true } + new ReaderOptions { LookForHeader = true } ); while (reader.MoveToNextEntry()) { diff --git a/tests/SharpCompress.Test/ReaderTests.cs b/tests/SharpCompress.Test/ReaderTests.cs index 00ad69e9..a5f00d97 100644 --- a/tests/SharpCompress.Test/ReaderTests.cs +++ b/tests/SharpCompress.Test/ReaderTests.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using SharpCompress.Common; @@ -64,7 +63,7 @@ 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 } ); } } @@ -88,13 +87,11 @@ public abstract class ReaderTests : TestBase 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)) + using var reader = ReaderFactory.Open(forward, options); + while (reader.MoveToNextEntry()) { - while (reader.MoveToNextEntry()) - { - Assert.Equal(expectedCompression, reader.Entry.CompressionType); - Assert.Equal(expected.Pop(), reader.Entry.Key); - } + 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 184559d1..226ba4d8 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] diff --git a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs index 2f336329..46d1a3d3 100644 --- a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs +++ b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs @@ -1,6 +1,5 @@ using System; using System.Buffers; -using System.Buffers.Binary; using System.IO; using SharpCompress.Compressors.LZMA; using Xunit; @@ -21,7 +20,6 @@ public class LzmaStreamTests } private static byte[] lzmaData { get; } = - new byte[] { 0x5D, 0x00, @@ -183,7 +181,6 @@ public class LzmaStreamTests /// The decoded data for . ///

private static byte[] lzmaResultData { get; } = - new byte[] { 0x01, 0x00, diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index f1eba627..c39bbbd8 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -66,18 +66,16 @@ public class TarArchiveTests : ArchiveTests public void Tar_NonUstarArchiveWithLongNameDoesNotSkipEntriesAfterTheLongOne() { 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)); - } + 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] @@ -128,31 +126,29 @@ public class TarArchiveTests : ArchiveTests public void Tar_UstarArchivePathReadLongName() { 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) - ); - } + 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] @@ -167,7 +163,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); @@ -211,22 +207,18 @@ public class TarArchiveTests : ArchiveTests public void Tar_Containing_Rar_Archive() { 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); - } + using Stream stream = File.OpenRead(archiveFullPath); + using IArchive archive = ArchiveFactory.Open(stream); + Assert.True(archive.Type == ArchiveType.Tar); } [Fact] public void Tar_Empty_Archive() { 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); - } + using Stream stream = File.OpenRead(archiveFullPath); + using IArchive archive = ArchiveFactory.Open(stream); + Assert.True(archive.Type == ArchiveType.Tar); } [Theory] @@ -234,26 +226,24 @@ public class TarArchiveTests : ArchiveTests [InlineData(128)] public void Tar_Japanese_Name(int length) { - using (var mstm = new MemoryStream()) + 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])) { - 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])) + 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)) { - 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)) + while (tr.MoveToNextEntry()) { - while (tr.MoveToNextEntry()) - { - Assert.Equal(fname, tr.Entry.Key); - } + Assert.Equal(fname, tr.Entry.Key); } } } @@ -269,36 +259,32 @@ public class TarArchiveTests : ArchiveTests }; var testBytes = Encoding.UTF8.GetBytes("This is a test."); - using (var memoryStream = new MemoryStream()) + using var memoryStream = new MemoryStream(); + using (var tarWriter = new TarWriter(memoryStream, tarWriterOptions)) + using (var testFileStream = new MemoryStream(testBytes)) { - using (var tarWriter = new TarWriter(memoryStream, tarWriterOptions)) - using (var testFileStream = new MemoryStream(testBytes)) - { - 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) - { - ++numberOfEntries; - - using (var tarEntryStream = entry.OpenEntryStream()) - using (var testFileStream = new MemoryStream()) - { - tarEntryStream.CopyTo(testFileStream); - Assert.Equal(testBytes.Length, testFileStream.Length); - } - } - } - - Assert.Equal(2, numberOfEntries); + 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) + { + ++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 e3a27296..a74f70cd 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -19,26 +19,22 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_Skip() { - using ( - Stream stream = new ForwardOnlyStream( - File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar")) - ) - ) - using (IReader reader = ReaderFactory.Open(stream)) + using Stream stream = new ForwardOnlyStream( + File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar")) + ); + using IReader reader = ReaderFactory.Open(stream); + int x = 0; + while (reader.MoveToNextEntry()) { - int x = 0; - while (reader.MoveToNextEntry()) + if (!reader.Entry.IsDirectory) { - if (!reader.Entry.IsDirectory) + x++; + if (x % 2 == 0) { - x++; - if (x % 2 == 0) - { - reader.WriteEntryToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } - ); - } + reader.WriteEntryToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); } } } @@ -70,24 +66,20 @@ public class TarReaderTests : ReaderTests if (!reader.Entry.IsDirectory) { Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType); - using (var entryStream = reader.OpenEntryStream()) + using var entryStream = reader.OpenEntryStream(); + 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)) { - 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 (FileStream fs = File.OpenWrite(destinationFileName)) - { - entryStream.TransferTo(fs); - } + Directory.CreateDirectory(destdir); } + string destinationFileName = Path.Combine(destdir, file); + + using FileStream fs = File.OpenWrite(destinationFileName); + entryStream.TransferTo(fs); } } } @@ -130,143 +122,121 @@ 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)) + using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2")); + using var reader = TarReader.Open(stream); + List names = new List(); + while (reader.MoveToNextEntry()) { - List names = new List(); - while (reader.MoveToNextEntry()) + if (!reader.Entry.IsDirectory) { - 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(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() { 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); - } + 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() { 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 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 (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); - } - } - } - } + 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() { 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(); + using Stream stream = File.OpenRead(archiveFullPath); + using IReader reader = ReaderFactory.Open(stream); + var memoryStream = new MemoryStream(); - Action action = () => reader.MoveToNextEntry(); - var exception = Record.Exception(action); - Assert.Null(exception); - reader.MoveToNextEntry(); - reader.WriteEntryTo(memoryStream); - stream.Close(); - Assert.Throws(action); - } + Action action = () => reader.MoveToNextEntry(); + var exception = Record.Exception(action); + Assert.Null(exception); + reader.MoveToNextEntry(); + reader.WriteEntryTo(memoryStream); + stream.Close(); + Assert.Throws(action); } #if !NETFRAMEWORK [Fact] public void Tar_GZip_With_Symlink_Entries() { - var isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform( - System.Runtime.InteropServices.OSPlatform.Windows + var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + using Stream stream = File.OpenRead( + Path.Combine(TEST_ARCHIVES_PATH, "TarWithSymlink.tar.gz") ); - using ( - Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "TarWithSymlink.tar.gz")) - ) - using (var reader = TarReader.Open(stream)) + using var reader = TarReader.Open(stream); + List names = new List(); + while (reader.MoveToNextEntry()) { - List names = new List(); - while (reader.MoveToNextEntry()) + if (reader.Entry.IsDirectory) { - if (reader.Entry.IsDirectory) + continue; + } + reader.WriteEntryToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions { - continue; - } - reader.WriteEntryToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions() + ExtractFullPath = true, + Overwrite = true, + WriteSymbolicLink = (sourcePath, targetPath) => { - ExtractFullPath = true, - Overwrite = true, - WriteSymbolicLink = (sourcePath, targetPath) => + if (!isWindows) { - if (!isWindows) + var link = new UnixSymbolicLinkInfo(sourcePath); + if (File.Exists(sourcePath)) { - var link = new Mono.Unix.UnixSymbolicLinkInfo(sourcePath); - if (File.Exists(sourcePath)) - { - link.Delete(); // equivalent to ln -s -f - } - link.CreateSymbolicLinkTo(targetPath); + link.Delete(); // equivalent to ln -s -f } + link.CreateSymbolicLinkTo(targetPath); } } - ); - if (!isWindows) + } + ); + if (!isWindows) + { + if (reader.Entry.LinkTarget != null) { - if (reader.Entry.LinkTarget != null) + var path = Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key); + var link = new UnixSymbolicLinkInfo(path); + if (link.HasContents) { - 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 - ) - ); + // 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) + ); - 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/WriterTests.cs b/tests/SharpCompress.Test/WriterTests.cs index 64ed6d2c..7b33e377 100644 --- a/tests/SharpCompress.Test/WriterTests.cs +++ b/tests/SharpCompress.Test/WriterTests.cs @@ -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/XZHeaderTests.cs b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs index e187b47a..318056d2 100644 --- a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs +++ b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs @@ -11,16 +11,14 @@ public class XZHeaderTests : XZTestsBase { var bytes = (byte[])Compressed.Clone(); bytes[3]++; - using (Stream badMagicNumberStream = new MemoryStream(bytes)) + using Stream badMagicNumberStream = new MemoryStream(bytes); + BinaryReader br = new BinaryReader(badMagicNumberStream); + var header = new XZHeader(br); + var ex = Assert.Throws(() => { - BinaryReader br = new BinaryReader(badMagicNumberStream); - var header = new XZHeader(br); - var ex = Assert.Throws(() => - { - header.Process(); - }); - Assert.Equal("Invalid XZ Stream", ex.Message); - } + header.Process(); + }); + Assert.Equal("Invalid XZ Stream", ex.Message); } [Fact] @@ -28,16 +26,14 @@ public class XZHeaderTests : XZTestsBase { var bytes = (byte[])Compressed.Clone(); bytes[8]++; - using (Stream badCrcStream = new MemoryStream(bytes)) + using Stream badCrcStream = new MemoryStream(bytes); + BinaryReader br = new BinaryReader(badCrcStream); + var header = new XZHeader(br); + var ex = Assert.Throws(() => { - BinaryReader br = new BinaryReader(badCrcStream); - var header = new XZHeader(br); - var ex = Assert.Throws(() => - { - header.Process(); - }); - Assert.Equal("Stream header corrupt", ex.Message); - } + header.Process(); + }); + Assert.Equal("Stream header corrupt", ex.Message); } [Fact] @@ -48,16 +44,14 @@ public class XZHeaderTests : XZTestsBase byte[] crc = Crc32.Compute(streamFlags).ToLittleEndianBytes(); streamFlags.CopyTo(bytes, 6); crc.CopyTo(bytes, 8); - using (Stream badFlagStream = new MemoryStream(bytes)) + using Stream badFlagStream = new MemoryStream(bytes); + BinaryReader br = new BinaryReader(badFlagStream); + var header = new XZHeader(br); + var ex = Assert.Throws(() => { - BinaryReader br = new BinaryReader(badFlagStream); - var header = new XZHeader(br); - var ex = Assert.Throws(() => - { - header.Process(); - }); - Assert.Equal("Unknown XZ Stream Version", ex.Message); - } + header.Process(); + }); + Assert.Equal("Unknown XZ Stream Version", ex.Message); } [Fact] diff --git a/tests/SharpCompress.Test/Xz/XZIndexTests.cs b/tests/SharpCompress.Test/Xz/XZIndexTests.cs index ccbf81b7..2d024e8d 100644 --- a/tests/SharpCompress.Test/Xz/XZIndexTests.cs +++ b/tests/SharpCompress.Test/Xz/XZIndexTests.cs @@ -15,23 +15,19 @@ public class XZIndexTests : XZTestsBase [Fact] public void RecordsStreamStartOnInit() { - 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); - } + 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(new byte[] { 1, 2, 3, 4, 5 })) - { - BinaryReader 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] @@ -74,31 +70,27 @@ public class XZIndexTests : XZTestsBase public void SkipsPadding() { // Index with 3-byte padding. - 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); - } + 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 1b5a9343..7bff0ff5 100644 --- a/tests/SharpCompress.Test/Xz/XZStreamTests.cs +++ b/tests/SharpCompress.Test/Xz/XZStreamTests.cs @@ -10,32 +10,26 @@ public class XZStreamTests : XZTestsBase public void CanReadEmptyStream() { XZStream xz = new XZStream(CompressedEmptyStream); - using (var sr = new StreamReader(xz)) - { - string uncompressed = sr.ReadToEnd(); - Assert.Equal(OriginalEmpty, uncompressed); - } + using var sr = new StreamReader(xz); + string uncompressed = sr.ReadToEnd(); + Assert.Equal(OriginalEmpty, uncompressed); } [Fact] public void CanReadStream() { XZStream xz = new XZStream(CompressedStream); - using (var sr = new StreamReader(xz)) - { - string uncompressed = sr.ReadToEnd(); - Assert.Equal(Original, uncompressed); - } + using var sr = new StreamReader(xz); + string uncompressed = sr.ReadToEnd(); + Assert.Equal(Original, uncompressed); } [Fact] public void CanReadIndexedStream() { XZStream xz = new XZStream(CompressedIndexedStream); - using (var sr = new StreamReader(xz)) - { - string uncompressed = sr.ReadToEnd(); - Assert.Equal(OriginalIndexed, uncompressed); - } + 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 5a1b5cbb..0b88dc52 100644 --- a/tests/SharpCompress.Test/Xz/XZTestsBase.cs +++ b/tests/SharpCompress.Test/Xz/XZTestsBase.cs @@ -29,7 +29,6 @@ public abstract class XZTestsBase : IDisposable protected Stream CompressedEmptyStream { get; } = new MemoryStream(CompressedEmpty); protected static byte[] CompressedEmpty { get; } = - new byte[] { 0xfd, 0x37, @@ -72,7 +71,6 @@ public abstract class XZTestsBase : IDisposable protected Stream CompressedStream { get; } = new MemoryStream(Compressed); protected static byte[] Compressed { get; } = - new byte[] { 0xfd, 0x37, @@ -481,7 +479,6 @@ public abstract class XZTestsBase : IDisposable protected Stream CompressedIndexedStream { get; } = new MemoryStream(CompressedIndexed); protected static byte[] CompressedIndexed { get; } = - new byte[] { 0xfd, 0x37, diff --git a/tests/SharpCompress.Test/Zip/Zip64Tests.cs b/tests/SharpCompress.Test/Zip/Zip64Tests.cs index 739867f7..c4c4c987 100644 --- a/tests/SharpCompress.Test/Zip/Zip64Tests.cs +++ b/tests/SharpCompress.Test/Zip/Zip64Tests.cs @@ -3,6 +3,8 @@ 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; @@ -148,10 +150,7 @@ public class Zip64Tests : WriterTests 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 = Compressors.Deflate.CompressionLevel.None - }; + var eo = new ZipWriterEntryOptions { DeflateCompressionLevel = CompressionLevel.None }; using var zip = File.OpenWrite(filename); using var st = forward_only ? (Stream)new ForwardOnlyStream(zip) : zip; @@ -173,9 +172,9 @@ public class Zip64Tests : WriterTests { long count = 0; long size = 0; - Common.Zip.ZipEntry? prev = null; + 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 94012e74..fee99aaf 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -248,33 +248,27 @@ public class ZipArchiveTests : ArchiveTests { string scratchPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); - using (ZipArchive vfs = (ZipArchive)ArchiveFactory.Open(scratchPath)) - { - var e = vfs.Entries.First(v => + 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) - ); - 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) - ) - ); - } + ) + ); + 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] @@ -418,7 +412,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" } ) ) { @@ -426,7 +420,7 @@ public class ZipArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -436,40 +430,32 @@ 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" } - ) - ) + 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)) { - 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); - } + 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); - 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); - } + 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] @@ -478,7 +464,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" } ) ) { @@ -486,7 +472,7 @@ public class ZipArchiveTests : ArchiveTests { entry.WriteToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -540,27 +526,19 @@ public class ZipArchiveTests : ArchiveTests { string zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.pkware.zip"); - using (FileStream fileStream = File.Open(zipFile, FileMode.Open)) + using FileStream fileStream = File.Open(zipFile, FileMode.Open); + using IArchive archive = ArchiveFactory.Open( + fileStream, + new ReaderOptions { Password = "12345678" } + ); + var entries = archive.Entries.Where(entry => !entry.IsDirectory); + foreach (IArchiveEntry entry in entries) { - using ( - IArchive archive = ArchiveFactory.Open( - fileStream, - new ReaderOptions { Password = "12345678" } - ) - ) + for (var i = 0; i < 100; i++) { - 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); - } - } - } + using var memoryStream = new MemoryStream(); + using Stream entryStream = entry.OpenEntryStream(); + entryStream.CopyTo(memoryStream); } } } @@ -575,15 +553,13 @@ public class ZipArchiveTests : ArchiveTests Assert.ThrowsAny(() => { - using (var archive = ZipArchive.Open(zipFile)) + using var archive = ZipArchive.Open(zipFile); + foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) { - foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory)) - { - entry.WriteToDirectory( - SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } - ); - } + entry.WriteToDirectory( + SCRATCH_FILES_PATH, + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } + ); } }); } @@ -613,16 +589,14 @@ public class ZipArchiveTests : ArchiveTests { foreach (var entry in zipArchive.Entries) { - using (var entryStream = entry.OpenEntryStream()) + using var entryStream = entry.OpenEntryStream(); + MemoryStream tempStream = new MemoryStream(); + const int bufSize = 0x1000; + byte[] buf = new byte[bufSize]; + int bytesRead = 0; + while ((bytesRead = entryStream.Read(buf, 0, bufSize)) > 0) { - 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); - } + tempStream.Write(buf, 0, bytesRead); } } } @@ -633,23 +607,19 @@ public class ZipArchiveTests : ArchiveTests { string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.badlocalextra.zip"); - using (ZipArchive za = ZipArchive.Open(zipPath)) + using ZipArchive za = ZipArchive.Open(zipPath); + var ex = Record.Exception(() => { - var ex = Record.Exception(() => - { - var firstEntry = za.Entries.First(x => x.Key == "first.txt"); - var buffer = new byte[4096]; + 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] @@ -657,40 +627,38 @@ public class ZipArchiveTests : ArchiveTests { string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.datadescriptors.zip"); - using (ZipArchive za = ZipArchive.Open(zipPath)) + using ZipArchive 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()) { - var firstEntry = za.Entries.First(x => x.Key == "first.txt"); - var buffer = new byte[4096]; + 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); - } + var len1 = 0; + var buffer1 = new byte[firstEntry.Size + 256]; - var len1 = 0; - var buffer1 = new byte[firstEntry.Size + 256]; + using (var firstStream = firstEntry.OpenEntryStream()) + { + len1 = firstStream.Read(buffer1, 0, buffer.Length); + } - using (var firstStream = firstEntry.OpenEntryStream()) - { - len1 = firstStream.Read(buffer1, 0, buffer.Length); - } - - Assert.Equal(199, len1); + Assert.Equal(199, len1); #if !NETFRAMEWORK && !NETSTANDARD2_0 - var len2 = 0; - var buffer2 = new byte[firstEntry.Size + 256]; + 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 + using (var firstStream = firstEntry.OpenEntryStream()) + { + len2 = firstStream.Read(buffer2.AsSpan()); } + Assert.Equal(len1, len2); + Assert.Equal(buffer1, buffer2); +#endif } [Fact] @@ -698,11 +666,9 @@ public class ZipArchiveTests : ArchiveTests { string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.LongComment.zip"); - using (ZipArchive 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] @@ -710,40 +676,34 @@ public class ZipArchiveTests : ArchiveTests { string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.compressedonly.zip"); - using (ZipArchive 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() { string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip"); - using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read)) + using var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read); + IArchive archive = ArchiveFactory.Open(stream); + IReader reader = archive.ExtractAllEntries(); + int entries = 0; + while (reader.MoveToNextEntry()) { - IArchive archive = ArchiveFactory.Open(stream); - IReader reader = archive.ExtractAllEntries(); - int entries = 0; - while (reader.MoveToNextEntry()) + using (var entryStream = reader.OpenEntryStream()) + using (var target = new MemoryStream()) { - using (var entryStream = reader.OpenEntryStream()) - using (var target = new MemoryStream()) - { - entryStream.CopyTo(target); - } - - entries++; + entryStream.CopyTo(target); } - Assert.Equal(4, entries); + + entries++; } + Assert.Equal(4, entries); } [Fact] @@ -758,19 +718,17 @@ 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)) + using var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read); + IArchive archive = ArchiveFactory.Open(stream); + IReader reader = archive.ExtractAllEntries(); + int x = 0; + while (reader.MoveToNextEntry()) { - 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(keys[x], reader.Entry.Key); + x++; } + + Assert.Equal(4, x); } [Fact] diff --git a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs index e5254c19..3296bcb0 100644 --- a/tests/SharpCompress.Test/Zip/ZipReaderTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipReaderTests.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using SharpCompress.Archives; using SharpCompress.Common; using SharpCompress.IO; using SharpCompress.Readers; @@ -70,7 +71,7 @@ public class ZipReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -108,7 +109,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()) { @@ -117,7 +118,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 } ); } } @@ -139,7 +140,7 @@ public class ZipReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -160,7 +161,7 @@ public class ZipReaderTests : ReaderTests { reader.WriteEntryToDirectory( SCRATCH_FILES_PATH, - new ExtractionOptions() { ExtractFullPath = true, Overwrite = true } + new ExtractionOptions { ExtractFullPath = true, Overwrite = true } ); } } @@ -176,7 +177,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()) { @@ -185,7 +186,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 } ); } } @@ -201,7 +202,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()) { @@ -210,7 +211,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 } ); } } @@ -223,7 +224,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()) { @@ -232,7 +233,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++; } @@ -364,7 +365,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 = Archives.ArchiveFactory.Open(stream); + var archive = ArchiveFactory.Open(stream); var reader = archive.ExtractAllEntries(); reader.MoveToNextEntry(); var zipReader = ZipReader.Open(reader.OpenEntryStream()); From 2715ae645d4b44e8ae17add990589bafb4bea14f Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 08:38:12 +0000 Subject: [PATCH 0043/1333] use var --- src/SharpCompress/Algorithms/Adler32.cs | 66 +++++------ .../Archives/ArchiveVolumeFactory.cs | 2 +- .../Archives/Rar/RarArchiveVolumeFactory.cs | 2 +- .../Archives/Zip/ZipArchiveVolumeFactory.cs | 2 +- src/SharpCompress/Common/ExtractionMethods.cs | 10 +- src/SharpCompress/Common/Rar/CryptKey5.cs | 16 +-- .../Common/Tar/TarReadOnlySubStream.cs | 4 +- .../Compressors/Deflate/ZlibBaseStream.cs | 44 ++++---- .../Compressors/Deflate64/Deflate64Stream.cs | 6 +- .../Compressors/Filters/BCJFilterARM.cs | 2 +- .../Compressors/Filters/BCJFilterARMT.cs | 2 +- .../Compressors/Filters/BCJFilterIA64.cs | 16 +-- .../Compressors/Filters/BCJFilterPPC.cs | 2 +- .../Compressors/Filters/BCJFilterSPARC.cs | 2 +- .../Compressors/Filters/BranchExecFilter.cs | 22 +--- .../Compressors/Filters/DeltaFilter.cs | 4 +- .../Compressors/LZMA/AesDecoderStream.cs | 40 +++---- .../Compressors/LZMA/LzmaEncoder.cs | 2 +- .../Compressors/Rar/RarBLAKE2spStream.cs | 22 ++-- .../Compressors/Shrink/BitStream.cs | 2 +- .../Compressors/Shrink/HwUnshrink.cs | 20 ++-- .../Compressors/Shrink/ShrinkStream.cs | 8 +- src/SharpCompress/IO/DataDescriptorStream.cs | 4 +- src/SharpCompress/Readers/Tar/TarReader.cs | 12 +- tests/SharpCompress.Test/ArchiveTests.cs | 4 +- .../Streams/LzmaStreamTests.cs | 22 ++-- .../SharpCompress.Test/Tar/TarArchiveTests.cs | 48 ++++---- .../SharpCompress.Test/Tar/TarReaderTests.cs | 28 ++--- tests/SharpCompress.Test/Xz/XZHeaderTests.cs | 12 +- tests/SharpCompress.Test/Xz/XZIndexTests.cs | 14 +-- tests/SharpCompress.Test/Xz/XZStreamTests.cs | 12 +- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 106 +++++++++--------- 32 files changed, 267 insertions(+), 291 deletions(-) diff --git a/src/SharpCompress/Algorithms/Adler32.cs b/src/SharpCompress/Algorithms/Adler32.cs index 1f094c13..10dbfc4d 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. - Vector128 vsum = Sse2.Add(accumulator.GetLower(), accumulator.GetUpper()); + var 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) { - Vector128 vsum = Sse2.Add(accumulator.GetLower(), accumulator.GetUpper()); // add upper lane to lower lane + var 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) { - uint s1 = adler & 0xFFFF; - uint s2 = (adler >> 16) & 0xFFFF; + var s1 = adler & 0xFFFF; + var s2 = (adler >> 16) & 0xFFFF; // Process the data in blocks. - uint length = (uint)buffer.Length; - uint blocks = length / BlockSize; + var length = (uint)buffer.Length; + var blocks = length / BlockSize; length -= blocks * BlockSize; fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { fixed (byte* tapPtr = &MemoryMarshal.GetReference(Tap1Tap2)) { - byte* localBufferPtr = bufferPtr; + var localBufferPtr = bufferPtr; // _mm_setr_epi8 on x86 - Vector128 tap1 = Sse2.LoadVector128((sbyte*)tapPtr); - Vector128 tap2 = Sse2.LoadVector128((sbyte*)(tapPtr + 0x10)); - Vector128 zero = Vector128.Zero; + var tap1 = Sse2.LoadVector128((sbyte*)tapPtr); + var tap2 = Sse2.LoadVector128((sbyte*)(tapPtr + 0x10)); + var zero = Vector128.Zero; var ones = Vector128.Create((short)1); while (blocks > 0) { - uint n = NMAX / BlockSize; /* The NMAX constraint. */ + var 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. - Vector128 v_ps = Vector128.CreateScalar(s1 * n); - Vector128 v_s2 = Vector128.CreateScalar(s2); - Vector128 v_s1 = Vector128.Zero; + var v_ps = Vector128.CreateScalar(s1 * n); + var v_s2 = Vector128.CreateScalar(s2); + var v_s1 = Vector128.Zero; do { // Load 32 input bytes. - Vector128 bytes1 = Sse3.LoadDquVector128(localBufferPtr); - Vector128 bytes2 = Sse3.LoadDquVector128(localBufferPtr + 0x10); + var bytes1 = Sse3.LoadDquVector128(localBufferPtr); + var 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()); - Vector128 mad1 = Ssse3.MultiplyAddAdjacent(bytes1, tap1); + var 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()); - Vector128 mad2 = Ssse3.MultiplyAddAdjacent(bytes2, tap2); + var 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) { - uint s1 = adler & 0xFFFF; - uint s2 = (adler >> 16) & 0xFFFF; - uint length = (uint)buffer.Length; + var s1 = adler & 0xFFFF; + var s2 = (adler >> 16) & 0xFFFF; + var length = (uint)buffer.Length; fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) { - byte* localBufferPtr = bufferPtr; + var localBufferPtr = bufferPtr; - Vector256 zero = Vector256.Zero; + var 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) { - int k = length < NMAX ? (int)length : (int)NMAX; + var k = length < NMAX ? (int)length : (int)NMAX; k -= k % 32; length -= (uint)k; - Vector256 vs10 = vs1; - Vector256 vs3 = Vector256.Zero; + var vs10 = vs1; + var vs3 = Vector256.Zero; while (k >= 32) { // Load 32 input bytes. - Vector256 block = Avx.LoadVector256(localBufferPtr); + var block = Avx.LoadVector256(localBufferPtr); // Sum of abs diff, resulting in 2 x int32's - Vector256 vs1sad = Avx2.SumAbsoluteDifferences(block, zero); + var vs1sad = Avx2.SumAbsoluteDifferences(block, zero); vs1 = Avx2.Add(vs1, vs1sad.AsUInt32()); vs3 = Avx2.Add(vs3, vs10); // sum 32 uint8s to 16 shorts. - Vector256 vshortsum2 = Avx2.MultiplyAddAdjacent(block, dot2v); + var vshortsum2 = Avx2.MultiplyAddAdjacent(block, dot2v); // sum 16 shorts to 8 uint32s. - Vector256 vsum2 = Avx2.MultiplyAddAdjacent(vshortsum2, dot3v); + var 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) { - uint s1 = adler & 0xFFFF; - uint s2 = (adler >> 16) & 0xFFFF; + var s1 = adler & 0xFFFF; + var s2 = (adler >> 16) & 0xFFFF; uint k; fixed (byte* bufferPtr = buffer) { var localBufferPtr = bufferPtr; - uint length = (uint)buffer.Length; + var length = (uint)buffer.Length; while (length > 0) { diff --git a/src/SharpCompress/Archives/ArchiveVolumeFactory.cs b/src/SharpCompress/Archives/ArchiveVolumeFactory.cs index d8f5535f..81a5d4fd 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 ... - Match m = Regex.Match(part1.Name, @"^(.*\.)([0-9]+)$", RegexOptions.IgnoreCase); + var m = Regex.Match(part1.Name, @"^(.*\.)([0-9]+)$", RegexOptions.IgnoreCase); if (m.Success) item = new FileInfo( Path.Combine( diff --git a/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs b/src/SharpCompress/Archives/Rar/RarArchiveVolumeFactory.cs index 72ccf60f..f5ce89b8 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 .... - Match m = Regex.Match(part1.Name, @"^(.*\.part)([0-9]+)(\.rar)$", RegexOptions.IgnoreCase); + var 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/Zip/ZipArchiveVolumeFactory.cs b/src/SharpCompress/Archives/Zip/ZipArchiveVolumeFactory.cs index fdaa85b9..1b2f093d 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 - Match m = Regex.Match(part1.Name, @"^(.*\.)(zipx?|zx?[0-9]+)$", RegexOptions.IgnoreCase); + var m = Regex.Match(part1.Name, @"^(.*\.)(zipx?|zx?[0-9]+)$", RegexOptions.IgnoreCase); if (m.Success) item = new FileInfo( Path.Combine( diff --git a/src/SharpCompress/Common/ExtractionMethods.cs b/src/SharpCompress/Common/ExtractionMethods.cs index c8e5896e..a470637a 100644 --- a/src/SharpCompress/Common/ExtractionMethods.cs +++ b/src/SharpCompress/Common/ExtractionMethods.cs @@ -16,7 +16,7 @@ internal static class ExtractionMethods ) { string destinationFileName; - string fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory); + var fullDestinationDirectoryPath = Path.GetFullPath(destinationDirectory); //check for trailing slash. if ( @@ -36,11 +36,11 @@ internal static class ExtractionMethods options ??= new ExtractionOptions() { Overwrite = true }; - string file = Path.GetFileName(entry.Key); + var file = Path.GetFileName(entry.Key); if (options.ExtractFullPath) { - string folder = Path.GetDirectoryName(entry.Key)!; - string destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder)); + var folder = Path.GetDirectoryName(entry.Key)!; + var destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder)); if (!Directory.Exists(destdir)) { @@ -102,7 +102,7 @@ internal static class ExtractionMethods } else { - FileMode fm = FileMode.Create; + var fm = FileMode.Create; options ??= new ExtractionOptions() { Overwrite = true }; if (!options.Overwrite) diff --git a/src/SharpCompress/Common/Rar/CryptKey5.cs b/src/SharpCompress/Common/Rar/CryptKey5.cs index 31e2c7b8..0b802691 100644 --- a/src/SharpCompress/Common/Rar/CryptKey5.cs +++ b/src/SharpCompress/Common/Rar/CryptKey5.cs @@ -34,19 +34,19 @@ internal class CryptKey5 : ICryptKey int keyLength ) { - using HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(password)); - byte[] block = hmac.ComputeHash(salt); - byte[] finalHash = (byte[])block.Clone(); + 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 (int x = 0; x < 3; x++) + for (var x = 0; x < 3; x++) { - for (int i = 1; i < loop[x]; i++) + for (var i = 1; i < loop[x]; i++) { block = hmac.ComputeHash(block); - for (int j = 0; j < finalHash.Length; j++) + for (var j = 0; j < finalHash.Length; j++) { finalHash[j] ^= block[j]; } @@ -60,7 +60,7 @@ internal class CryptKey5 : ICryptKey public ICryptoTransform Transformer(byte[] salt) { - int iterations = (1 << _cryptoInfo.LG2Count); // Adjust the number of iterations as needed + 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( @@ -74,7 +74,7 @@ internal class CryptKey5 : ICryptKey _pswCheck = new byte[EncryptionConstV5.SIZE_PSWCHECK]; - for (int i = 0; i < SHA256_DIGEST_SIZE; i++) + for (var i = 0; i < SHA256_DIGEST_SIZE; i++) { _pswCheck[i % EncryptionConstV5.SIZE_PSWCHECK] ^= derivedKey[2][i]; } diff --git a/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs b/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs index 2a340dea..09a2fdb8 100644 --- a/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs +++ b/src/SharpCompress/Common/Tar/TarReadOnlySubStream.cs @@ -63,7 +63,7 @@ internal class TarReadOnlySubStream : NonDisposingStream { count = (int)BytesLeftToRead; } - int read = Stream.Read(buffer, offset, count); + var read = Stream.Read(buffer, offset, count); if (read > 0) { BytesLeftToRead -= read; @@ -78,7 +78,7 @@ internal class TarReadOnlySubStream : NonDisposingStream { return -1; } - int value = Stream.ReadByte(); + var value = Stream.ReadByte(); if (value != -1) { --BytesLeftToRead; diff --git a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs index 8248e900..94b1491d 100644 --- a/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs +++ b/src/SharpCompress/Compressors/Deflate/ZlibBaseStream.cs @@ -102,7 +102,7 @@ internal class ZlibBaseStream : Stream { if (_z is null) { - bool wantRfc1950Header = (_flavor == ZlibStreamFlavor.ZLIB); + var 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; - bool done = false; + var done = false; do { _z.OutputBuffer = workingBuffer; _z.NextOut = 0; _z.AvailableBytesOut = _workingBuffer.Length; - int rc = (_wantCompress) ? _z.Deflate(_flushMode) : _z.Inflate(_flushMode); + var 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) { - bool done = false; + var done = false; do { _z.OutputBuffer = workingBuffer; _z.NextOut = 0; _z.AvailableBytesOut = _workingBuffer.Length; - int rc = + var rc = (_wantCompress) ? _z.Deflate(FlushType.Finish) : _z.Inflate(FlushType.Finish); if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) { - string verb = (_wantCompress ? "de" : "in") + "flating"; + var 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); - int c2 = (int)(crc.TotalBytesRead & 0x00000000FFFFFFFF); + var 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); - int bytesNeeded = 8 - _z.AvailableBytesIn; - int bytesRead = _stream.Read( + var bytesNeeded = 8 - _z.AvailableBytesIn; + var 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); } - 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); + 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); if (crc32_actual != crc32_expected) { @@ -380,11 +380,11 @@ internal class ZlibBaseStream : Stream private string ReadZeroTerminatedString() { var list = new List(); - bool done = false; + var done = false; do { // workitem 7740 - int n = _stream.Read(_buf1, 0, 1); + var 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); - byte[] buffer = list.ToArray(); + var buffer = list.ToArray(); return _encoding.GetString(buffer, 0, buffer.Length); } private int _ReadAndValidateGzipHeader() { - int totalBytesRead = 0; + var totalBytesRead = 0; // read the header on the first read Span header = stackalloc byte[10]; - int n = _stream.Read(header); + var 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."); } - int timet = BinaryPrimitives.ReadInt32LittleEndian(header.Slice(4)); + var 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; - short extraLength = (short)(header[0] + header[1] * 256); - byte[] extra = new byte[extraLength]; + var extraLength = (short)(header[0] + header[1] * 256); + var 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."); } - int rc = 0; + var 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 3eda232c..da4117b9 100644 --- a/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs +++ b/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs @@ -118,8 +118,8 @@ public sealed class Deflate64Stream : Stream EnsureNotDisposed(); int bytesRead; - int currentOffset = offset; - int remainingCount = count; + var currentOffset = offset; + var remainingCount = count; while (true) { @@ -142,7 +142,7 @@ public sealed class Deflate64Stream : Stream break; } - int bytes = _stream.Read(_buffer, 0, _buffer.Length); + var bytes = _stream.Read(_buffer, 0, _buffer.Length); if (bytes <= 0) { break; diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARM.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARM.cs index 86e90b10..5d861621 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) { - int src = + var src = ((buffer[i + 2] & 0xFF) << 16) | ((buffer[i + 1] & 0xFF) << 8) | (buffer[i] & 0xFF); diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs index d2ad1bbf..db5b36f2 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) { - int src = + var 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 4d89ba39..07eaf319 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) { - int instrTemplate = buffer[i] & 0x1F; - int mask = BRANCH_TABLE[instrTemplate]; + var instrTemplate = buffer[i] & 0x1F; + var mask = BRANCH_TABLE[instrTemplate]; for (int slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41) { if (((mask >>> slot) & 1) == 0) continue; - int bytePos = bitPos >>> 3; - int bitRes = bitPos & 7; + var bytePos = bitPos >>> 3; + var bitRes = bitPos & 7; long instr = 0; - for (int j = 0; j < 6; ++j) + for (var j = 0; j < 6; ++j) { instr |= (buffer[i + bytePos + j] & 0xFFL) << (8 * j); } - long instrNorm = instr >>> bitRes; + var instrNorm = instr >>> bitRes; if (((instrNorm >>> 37) & 0x0F) != 0x05 || ((instrNorm >>> 9) & 0x07) != 0x00) continue; - int src = (int)((instrNorm >>> 13) & 0x0FFFFF); + var 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 (int j = 0; j < 6; ++j) + for (var 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 11ed61a1..ccfa7480 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) { - int src = + var src = ((buffer[i] & 0x03) << 24) | ((buffer[i + 1] & 0xFF) << 16) | ((buffer[i + 2] & 0xFF) << 8) diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs b/src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs index 67756d34..db7c75be 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) ) { - int src = + var 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 9fc439d4..f70d6c11 100644 --- a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs +++ b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs @@ -34,30 +34,20 @@ public sealed class BranchExecFilter //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) { - bool[] mask_to_allowed_status = new[] - { - true, - true, - true, - false, - true, - false, - false, - false - }; + var mask_to_allowed_status = new[] { true, true, true, false, true, false, false, false }; - byte[] mask_to_bit_num = new byte[] { 0, 1, 2, 2, 3, 3, 3, 3 }; + var mask_to_bit_num = new byte[] { 0, 1, 2, 2, 3, 3, 3, 3 }; int i; - int prev_pos = -1; - uint prev_mask = state & 7; + var prev_pos = -1; + var prev_mask = state & 7; uint src; uint dest; uint j; byte b; - uint pos = ip; + var pos = ip; - uint size = (uint)buf.Length; + var 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 c5fbeb41..85ec9b15 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) { - int end = offset + count; + var end = offset + count; - for (int i = offset; i < end; i++) + for (var i = offset; i < end; i++) { buffer[i] += _history[(_distance + _position--) & DISTANCE_MASK]; _history[_position & DISTANCE_MASK] = buffer[i]; diff --git a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs index 24823c73..8e884c97 100644 --- a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs +++ b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs @@ -35,10 +35,10 @@ internal sealed class AesDecoderStream : DecoderStream2 throw new NotSupportedException("AES decoder does not support padding."); } - Init(info, out int numCyclesPower, out byte[] salt, out byte[] seed); + Init(info, out var numCyclesPower, out var salt, out var seed); - byte[] password = Encoding.Unicode.GetBytes(pass.CryptoGetTextPassword()); - byte[]? key = InitKey(numCyclesPower, salt, password); + var password = Encoding.Unicode.GetBytes(pass.CryptoGetTextPassword()); + var key = InitKey(numCyclesPower, salt, password); if (key == null) { throw new InvalidOperationException("Initialized with null key"); @@ -100,7 +100,7 @@ internal sealed class AesDecoderStream : DecoderStream2 do { - int read = mStream.Read(mBuffer, mEnding, mBuffer.Length - mEnding); + var read = mStream.Read(mBuffer, mEnding, mBuffer.Length - mEnding); if (read == 0) { // We are not done decoding and have less than 16 bytes. @@ -133,7 +133,7 @@ internal sealed class AesDecoderStream : DecoderStream2 } // Otherwise we transform directly into the target buffer. - int processed = mDecoder.TransformBlock(mBuffer, mOffset, count & ~15, buffer, offset); + var processed = mDecoder.TransformBlock(mBuffer, mOffset, count & ~15, buffer, offset); mOffset += processed; mWritten += processed; return processed; @@ -143,7 +143,7 @@ internal sealed class AesDecoderStream : DecoderStream2 private void Init(byte[] info, out int numCyclesPower, out byte[] salt, out byte[] iv) { - byte bt = info[0]; + var bt = info[0]; numCyclesPower = bt & 0x3F; if ((bt & 0xC0) == 0) @@ -153,14 +153,14 @@ internal sealed class AesDecoderStream : DecoderStream2 return; } - int saltSize = (bt >> 7) & 1; - int ivSize = (bt >> 6) & 1; + var saltSize = (bt >> 7) & 1; + var ivSize = (bt >> 6) & 1; if (info.Length == 1) { throw new InvalidOperationException(); } - byte bt2 = info[1]; + var bt2 = info[1]; saltSize += (bt2 >> 4); ivSize += (bt2 & 15); if (info.Length < 2 + saltSize + ivSize) @@ -169,13 +169,13 @@ internal sealed class AesDecoderStream : DecoderStream2 } salt = new byte[saltSize]; - for (int i = 0; i < saltSize; i++) + for (var i = 0; i < saltSize; i++) { salt[i] = info[i + 2]; } iv = new byte[16]; - for (int i = 0; i < ivSize; i++) + for (var i = 0; i < ivSize; i++) { iv[i] = info[i + saltSize + 2]; } @@ -198,7 +198,7 @@ internal sealed class AesDecoderStream : DecoderStream2 key[pos] = salt[pos]; } - for (int i = 0; i < pass.Length && pos < 32; i++) + for (var i = 0; i < pass.Length && pos < 32; i++) { key[pos++] = pass[i]; } @@ -208,9 +208,9 @@ 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; + using var sha = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); + var counter = new byte[8]; + var numRounds = 1L << mNumCyclesPower; for (long round = 0; round < numRounds; round++) { sha.AppendData(salt, 0, salt.Length); @@ -219,7 +219,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 (int i = 0; i < 8; i++) + for (var i = 0; i < 8; i++) { if (++counter[i] != 0) { @@ -230,8 +230,8 @@ internal sealed class AesDecoderStream : DecoderStream2 return sha.GetHashAndReset(); #else using var sha = SHA256.Create(); - byte[] counter = new byte[8]; - long numRounds = 1L << mNumCyclesPower; + var counter = new byte[8]; + var numRounds = 1L << mNumCyclesPower; for (long round = 0; round < numRounds; round++) { sha.TransformBlock(salt, 0, salt.Length, null, 0); @@ -240,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 (int i = 0; i < 8; i++) + for (var i = 0; i < 8; i++) { if (++counter[i] != 0) { @@ -261,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) { - int blockSize = (mEnding - mOffset) & ~15; + var blockSize = (mEnding - mOffset) & ~15; mUnderflow = mDecoder.TransformBlock(mBuffer, mOffset, blockSize, mBuffer, mOffset); } diff --git a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs index e42f8069..7a231289 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs @@ -1727,7 +1727,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties ReadOnlySpan properties ) { - for (int i = 0; i < properties.Length; i++) + for (var i = 0; i < properties.Length; i++) { var prop = properties[i]; switch (propIDs[i]) diff --git a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs index d3e90c4c..7c897176 100644 --- a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs @@ -73,7 +73,7 @@ internal class RarBLAKE2spStream : RarStream public BLAKE2SP() { S = new BLAKE2S[BLAKE2SP_PARALLEL_DEGREE]; - for (int i = 0; i < S.Length; i++) + for (var i = 0; i < S.Length; i++) { S[i] = new BLAKE2S(); } @@ -141,15 +141,15 @@ internal class RarBLAKE2spStream : RarStream internal void Compress(BLAKE2S hash) { - UInt32[] m = new UInt32[16]; - UInt32[] v = new UInt32[16]; + var m = new UInt32[16]; + var v = new UInt32[16]; - for (int i = 0; i < 16; i++) + for (var i = 0; i < 16; i++) { m[i] = BitConverter.ToUInt32(hash.b, i * 4); } - for (int i = 0; i < 8; i++) + for (var i = 0; i < 8; i++) { v[i] = hash.h[i]; } @@ -164,7 +164,7 @@ internal class RarBLAKE2spStream : RarStream v[14] = hash.f[0] ^ k_BLAKE2S_IV[6]; v[15] = hash.f[1] ^ k_BLAKE2S_IV[7]; - for (int r = 0; r < BLAKE2S_NUM_ROUNDS; r++) + for (var r = 0; r < BLAKE2S_NUM_ROUNDS; r++) { ref byte[] sigma = ref k_BLAKE2S_Sigma[r]; @@ -178,7 +178,7 @@ internal class RarBLAKE2spStream : RarStream G(ref m, ref sigma, 7, ref v[3], ref v[4], ref v[9], ref v[14]); } - for (int i = 0; i < 8; i++) + for (var i = 0; i < 8; i++) { hash.h[i] ^= v[i] ^ v[i + 8]; } @@ -186,7 +186,7 @@ internal class RarBLAKE2spStream : RarStream internal void Update(BLAKE2S hash, ReadOnlySpan data, int size) { - int i = 0; + var i = 0; while (size != 0) { var pos = hash.bufferPosition; @@ -219,7 +219,7 @@ internal class RarBLAKE2spStream : RarStream var mem = new MemoryStream(); - for (int i = 0; i < 8; i++) + for (var i = 0; i < 8; i++) { mem.Write(BitConverter.GetBytes(hash.h[i]), 0, 4); } @@ -245,7 +245,7 @@ internal class RarBLAKE2spStream : RarStream internal void Update(BLAKE2SP hash, ReadOnlySpan data, int size) { - int i = 0; + var i = 0; var pos = hash.bufferPosition; while (size != 0) { @@ -274,7 +274,7 @@ internal class RarBLAKE2spStream : RarStream h.h[3] ^= (1 << 16 | BLAKE2S_DIGEST_SIZE << 24); h.lastNodeFlag = BLAKE2S_FINAL_FLAG; - for (int i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) + for (var i = 0; i < BLAKE2SP_PARALLEL_DEGREE; i++) { var digest = Final(_blake2sp.S[i]); Update(h, digest, BLAKE2S_DIGEST_SIZE); diff --git a/src/SharpCompress/Compressors/Shrink/BitStream.cs b/src/SharpCompress/Compressors/Shrink/BitStream.cs index ef01e2af..949ee6c3 100644 --- a/src/SharpCompress/Compressors/Shrink/BitStream.cs +++ b/src/SharpCompress/Compressors/Shrink/BitStream.cs @@ -57,7 +57,7 @@ namespace SharpCompress.Compressors.Shrink public int NextBits(int nbits) { - int result = 0; + var result = 0; if (nbits > _bitsLeft) { int num; diff --git a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs index 04f38c2b..3eb10e6b 100644 --- a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs +++ b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs @@ -27,14 +27,14 @@ namespace SharpCompress.Compressors.Shrink private static void CodeTabInit(CodeTabEntry[] codeTab) { - for (int i = 0; i <= byte.MaxValue; i++) + for (var i = 0; i <= byte.MaxValue; i++) { codeTab[i].prefixCode = (ushort)i; codeTab[i].extByte = (byte)i; codeTab[i].len = 1; } - for (int i = byte.MaxValue + 1; i <= MAX_CODE; i++) + for (var i = byte.MaxValue + 1; i <= MAX_CODE; i++) { codeTab[i].prefixCode = INVALID_CODE; } @@ -42,11 +42,11 @@ namespace SharpCompress.Compressors.Shrink private static void UnshrinkPartialClear(CodeTabEntry[] codeTab, ref CodeQueue queue) { - bool[] isPrefix = new bool[MAX_CODE + 1]; + var isPrefix = new bool[MAX_CODE + 1]; int codeQueueSize; // Scan for codes that have been used as a prefix. - for (int i = CONTROL_CODE + 1; i <= MAX_CODE; i++) + for (var i = CONTROL_CODE + 1; i <= MAX_CODE; i++) { if (codeTab[i].prefixCode != INVALID_CODE) { @@ -56,7 +56,7 @@ namespace SharpCompress.Compressors.Shrink // Clear "non-prefix" codes in the table; populate the code queue. codeQueueSize = 0; - for (int i = CONTROL_CODE + 1; i <= MAX_CODE; i++) + for (var i = CONTROL_CODE + 1; i <= MAX_CODE; i++) { if (!isPrefix[i]) { @@ -240,8 +240,8 @@ namespace SharpCompress.Compressors.Shrink out int dstUsed ) { - CodeTabEntry[] codeTab = new CodeTabEntry[HASHTAB_SIZE]; - CodeQueue queue = new CodeQueue(); + var codeTab = new CodeTabEntry[HASHTAB_SIZE]; + var queue = new CodeQueue(); var stream = new BitStream(src, srcLen); int codeSize, dstPos, @@ -323,7 +323,7 @@ namespace SharpCompress.Compressors.Shrink } // Output the string represented by the current code. - UnshrnkStatus status = OutputCode( + var status = OutputCode( currCode, dst, dstPos, @@ -343,7 +343,7 @@ namespace SharpCompress.Compressors.Shrink // Verify that the output matches walking the prefixes. var c = currCode; - for (int i = 0; i < len; i++) + for (var i = 0; i < len; i++) { // assert(codeTab[c].len == len - i); //assert(codeTab[c].extByte == dst[dstPos + len - i - 1]); @@ -422,7 +422,7 @@ namespace SharpCompress.Compressors.Shrink private static ushort CodeQueueRemoveNext(ref CodeQueue q) { - ushort code = CodeQueueNext(ref q); + var code = CodeQueueNext(ref q); if (code != INVALID_CODE) { q.nextIdx++; diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs index 52bba1ad..65b2eb37 100644 --- a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs @@ -55,10 +55,10 @@ internal class ShrinkStream : Stream { return 0; } - byte[] src = new byte[_compressedSize]; + var src = new byte[_compressedSize]; inStream.Read(src, offset, (int)_compressedSize); - int srcUsed = 0; - int dstUsed = 0; + var srcUsed = 0; + var dstUsed = 0; HwUnshrink.Unshrink( src, @@ -70,7 +70,7 @@ internal class ShrinkStream : Stream ); _outBytesCount = _byteOut.Length; - for (int index = 0; index < _outBytesCount; ++index) + for (var index = 0; index < _outBytesCount; ++index) { buffer[offset + index] = _byteOut[index]; } diff --git a/src/SharpCompress/IO/DataDescriptorStream.cs b/src/SharpCompress/IO/DataDescriptorStream.cs index b4af4b53..45708338 100644 --- a/src/SharpCompress/IO/DataDescriptorStream.cs +++ b/src/SharpCompress/IO/DataDescriptorStream.cs @@ -88,9 +88,9 @@ public class DataDescriptorStream : Stream return 0; } - int read = _stream.Read(buffer, offset, count); + var read = _stream.Read(buffer, offset, count); - for (int i = 0; i < read; i++) + for (var i = 0; i < read; i++) { if (buffer[offset + i] == DataDescriptorMarker[_search_position]) { diff --git a/src/SharpCompress/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index 34f337a6..d029376c 100644 --- a/src/SharpCompress/Readers/Tar/TarReader.cs +++ b/src/SharpCompress/Readers/Tar/TarReader.cs @@ -71,12 +71,12 @@ public class TarReader : AbstractReader { stream.CheckNotNull(nameof(stream)); options = options ?? new ReaderOptions(); - RewindableStream rewindableStream = new RewindableStream(stream); + var rewindableStream = new RewindableStream(stream); rewindableStream.StartRecording(); if (GZipArchive.IsGZipFile(rewindableStream)) { rewindableStream.Rewind(false); - GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress); + var testStream = new GZipStream(rewindableStream, CompressionMode.Decompress); if (TarArchive.IsTarFile(testStream)) { rewindableStream.Rewind(true); @@ -89,11 +89,7 @@ public class TarReader : AbstractReader if (BZip2Stream.IsBZip2(rewindableStream)) { rewindableStream.Rewind(false); - BZip2Stream testStream = new BZip2Stream( - rewindableStream, - CompressionMode.Decompress, - false - ); + var testStream = new BZip2Stream(rewindableStream, CompressionMode.Decompress, false); if (TarArchive.IsTarFile(testStream)) { rewindableStream.Rewind(true); @@ -106,7 +102,7 @@ public class TarReader : AbstractReader if (LZipStream.IsLZipFile(rewindableStream)) { rewindableStream.Rewind(false); - LZipStream testStream = new LZipStream(rewindableStream, CompressionMode.Decompress); + var testStream = new LZipStream(rewindableStream, CompressionMode.Decompress); if (TarArchive.IsTarFile(testStream)) { rewindableStream.Rewind(true); diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index f4e92b15..dc0aa979 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -297,8 +297,8 @@ public class ArchiveTests : ReaderTests memory.Position = 0; - for (int y = 0; y < 9; y++) - for (int x = 0; x < 256; x++) + for (var y = 0; y < 9; y++) + for (var x = 0; x < 256; x++) { Assert.Equal(x, memory.ReadByte()); } diff --git a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs index 46d1a3d3..ea002d62 100644 --- a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs +++ b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs @@ -534,13 +534,9 @@ public class LzmaStreamTests [Fact] public void TestLzmaStreamEncodingWritesData() { - using MemoryStream inputStream = new MemoryStream(lzmaResultData); + using var inputStream = new MemoryStream(lzmaResultData); using MemoryStream outputStream = new(); - using LzmaStream lzmaStream = new LzmaStream( - LzmaEncoderProperties.Default, - false, - outputStream - ); + using var lzmaStream = new LzmaStream(LzmaEncoderProperties.Default, false, outputStream); inputStream.CopyTo(lzmaStream); lzmaStream.Close(); Assert.NotEqual(0, outputStream.Length); @@ -551,11 +547,7 @@ public class LzmaStreamTests { var input = new MemoryStream(lzmaResultData); var compressed = new MemoryStream(); - LzmaStream lzmaEncodingStream = new LzmaStream( - LzmaEncoderProperties.Default, - false, - compressed - ); + var lzmaEncodingStream = new LzmaStream(LzmaEncoderProperties.Default, false, compressed); input.CopyTo(lzmaEncodingStream); lzmaEncodingStream.Close(); compressed.Position = 0; @@ -580,7 +572,7 @@ public class LzmaStreamTests long decompressedSize ) { - LzmaStream lzmaStream = new LzmaStream( + var lzmaStream = new LzmaStream( properties, compressedStream, compressedSize, @@ -589,12 +581,12 @@ public class LzmaStreamTests false ); - byte[] buffer = ArrayPool.Shared.Rent(1024); + var buffer = ArrayPool.Shared.Rent(1024); long totalRead = 0; while (totalRead < decompressedSize) { - int toRead = (int)Math.Min(buffer.Length, decompressedSize - totalRead); - int read = lzmaStream.Read(buffer, 0, toRead); + var toRead = (int)Math.Min(buffer.Length, decompressedSize - totalRead); + var 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 c39bbbd8..1ee6b783 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -26,10 +26,10 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_FileName_Exactly_100_Characters() { - string archive = "Tar_FileName_Exactly_100_Characters.tar"; + var archive = "Tar_FileName_Exactly_100_Characters.tar"; // create the 100 char filename - string filename = + var 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()) { - StreamWriter sw = new StreamWriter(inputStream); + var 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 - string unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); + var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); using (var archive2 = TarArchive.Open(unmodified)) { Assert.Equal(1, archive2.Entries.Count); @@ -65,7 +65,7 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_NonUstarArchiveWithLongNameDoesNotSkipEntriesAfterTheLongOne() { - string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "very long filename.tar"); + 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)); @@ -81,11 +81,11 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_VeryLongFilepathReadback() { - string archive = "Tar_VeryLongFilepathReadback.tar"; + var archive = "Tar_VeryLongFilepathReadback.tar"; // create a very long filename - string longFilename = ""; - for (int i = 0; i < 600; i = longFilename.Length) + var longFilename = ""; + for (var i = 0; i < 600; i = longFilename.Length) { longFilename += i.ToString("D10") + "-"; } @@ -97,7 +97,7 @@ public class TarArchiveTests : ArchiveTests using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.None)) using (Stream inputStream = new MemoryStream()) { - StreamWriter sw = new StreamWriter(inputStream); + var sw = new StreamWriter(inputStream); sw.Write("dummy filecontent"); sw.Flush(); @@ -106,7 +106,7 @@ public class TarArchiveTests : ArchiveTests } // Step 2: check if the written tar file can be read correctly - string unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); + var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive); using (var archive2 = TarArchive.Open(unmodified)) { Assert.Equal(1, archive2.Entries.Count); @@ -125,7 +125,7 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_UstarArchivePathReadLongName() { - string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "ustar with long names.tar"); + 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)); @@ -154,8 +154,8 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_Create_New() { - string scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"); - string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); + var scratchPath = Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"); + var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Tar.noEmptyDirs.tar"); // var aropt = new Ar @@ -172,10 +172,10 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_Random_Write_Add() { - 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"); + 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"); using (var archive = TarArchive.Open(unmodified)) { @@ -188,9 +188,9 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_Random_Write_Remove() { - 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"); + 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"); using (var archive = TarArchive.Open(unmodified)) { @@ -206,18 +206,18 @@ public class TarArchiveTests : ArchiveTests [Fact] public void Tar_Containing_Rar_Archive() { - string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); + var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); using Stream stream = File.OpenRead(archiveFullPath); - using IArchive archive = ArchiveFactory.Open(stream); + using var archive = ArchiveFactory.Open(stream); Assert.True(archive.Type == ArchiveType.Tar); } [Fact] public void Tar_Empty_Archive() { - string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.Empty.tar"); + var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.Empty.tar"); using Stream stream = File.OpenRead(archiveFullPath); - using IArchive archive = ArchiveFactory.Open(stream); + using var archive = ArchiveFactory.Open(stream); Assert.True(archive.Type == ArchiveType.Tar); } diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index a74f70cd..718b75ed 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -22,8 +22,8 @@ public class TarReaderTests : ReaderTests using Stream stream = new ForwardOnlyStream( File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar")) ); - using IReader reader = ReaderFactory.Open(stream); - int x = 0; + using var reader = ReaderFactory.Open(stream); + var x = 0; while (reader.MoveToNextEntry()) { if (!reader.Entry.IsDirectory) @@ -67,18 +67,18 @@ public class TarReaderTests : ReaderTests { Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType); using var entryStream = reader.OpenEntryStream(); - string file = Path.GetFileName(reader.Entry.Key); - string folder = + var file = Path.GetFileName(reader.Entry.Key); + var folder = Path.GetDirectoryName(reader.Entry.Key) ?? throw new ArgumentNullException(); - string destdir = Path.Combine(SCRATCH_FILES_PATH, folder); + var destdir = Path.Combine(SCRATCH_FILES_PATH, folder); if (!Directory.Exists(destdir)) { Directory.CreateDirectory(destdir); } - string destinationFileName = Path.Combine(destdir, file); + var destinationFileName = Path.Combine(destdir, file); - using FileStream fs = File.OpenWrite(destinationFileName); + using var fs = File.OpenWrite(destinationFileName); entryStream.TransferTo(fs); } } @@ -141,23 +141,23 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_Containing_Rar_Reader() { - string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); + var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsRar.tar"); using Stream stream = File.OpenRead(archiveFullPath); - using IReader reader = ReaderFactory.Open(stream); + using var reader = ReaderFactory.Open(stream); Assert.True(reader.ArchiveType == ArchiveType.Tar); } [Fact] public void Tar_With_TarGz_With_Flushed_EntryStream() { - string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsTarGz.tar"); + var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsTarGz.tar"); using Stream stream = File.OpenRead(archiveFullPath); - using IReader reader = ReaderFactory.Open(stream); + using var reader = ReaderFactory.Open(stream); Assert.True(reader.MoveToNextEntry()); Assert.Equal("inner.tar.gz", reader.Entry.Key); using var entryStream = reader.OpenEntryStream(); - using FlushOnDisposeStream flushingStream = new FlushOnDisposeStream(entryStream); + using var flushingStream = new FlushOnDisposeStream(entryStream); // Extract inner.tar.gz using var innerReader = ReaderFactory.Open(flushingStream); @@ -168,9 +168,9 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_Broken_Stream() { - string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"); + var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"); using Stream stream = File.OpenRead(archiveFullPath); - using IReader reader = ReaderFactory.Open(stream); + using var reader = ReaderFactory.Open(stream); var memoryStream = new MemoryStream(); Action action = () => reader.MoveToNextEntry(); diff --git a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs index 318056d2..7ce7dd48 100644 --- a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs +++ b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs @@ -12,7 +12,7 @@ public class XZHeaderTests : XZTestsBase var bytes = (byte[])Compressed.Clone(); bytes[3]++; using Stream badMagicNumberStream = new MemoryStream(bytes); - BinaryReader br = new BinaryReader(badMagicNumberStream); + var br = new BinaryReader(badMagicNumberStream); var header = new XZHeader(br); var ex = Assert.Throws(() => { @@ -27,7 +27,7 @@ public class XZHeaderTests : XZTestsBase var bytes = (byte[])Compressed.Clone(); bytes[8]++; using Stream badCrcStream = new MemoryStream(bytes); - BinaryReader br = new BinaryReader(badCrcStream); + var br = new BinaryReader(badCrcStream); var header = new XZHeader(br); var ex = Assert.Throws(() => { @@ -41,11 +41,11 @@ public class XZHeaderTests : XZTestsBase { var bytes = (byte[])Compressed.Clone(); byte[] streamFlags = { 0x00, 0xF4 }; - byte[] crc = Crc32.Compute(streamFlags).ToLittleEndianBytes(); + var crc = Crc32.Compute(streamFlags).ToLittleEndianBytes(); streamFlags.CopyTo(bytes, 6); crc.CopyTo(bytes, 8); using Stream badFlagStream = new MemoryStream(bytes); - BinaryReader br = new BinaryReader(badFlagStream); + var br = new BinaryReader(badFlagStream); var header = new XZHeader(br); var ex = Assert.Throws(() => { @@ -57,7 +57,7 @@ public class XZHeaderTests : XZTestsBase [Fact] public void ProcessesBlockCheckType() { - BinaryReader br = new BinaryReader(CompressedStream); + var br = new BinaryReader(CompressedStream); var header = new XZHeader(br); header.Process(); Assert.Equal(CheckType.CRC64, header.BlockCheckType); @@ -66,7 +66,7 @@ public class XZHeaderTests : XZTestsBase [Fact] public void CanCalculateBlockCheckSize() { - BinaryReader br = new BinaryReader(CompressedStream); + var 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 2d024e8d..f87f7b9b 100644 --- a/tests/SharpCompress.Test/Xz/XZIndexTests.cs +++ b/tests/SharpCompress.Test/Xz/XZIndexTests.cs @@ -16,7 +16,7 @@ public class XZIndexTests : XZTestsBase public void RecordsStreamStartOnInit() { using Stream badStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 }); - BinaryReader br = new BinaryReader(badStream); + var br = new BinaryReader(badStream); var index = new XZIndex(br, false); Assert.Equal(0, index.StreamStartPosition); } @@ -25,7 +25,7 @@ public class XZIndexTests : XZTestsBase public void ThrowsIfHasNoIndexMarker() { using Stream badStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 }); - BinaryReader br = new BinaryReader(badStream); + var br = new BinaryReader(badStream); var index = new XZIndex(br, false); Assert.Throws(() => index.Process()); } @@ -33,7 +33,7 @@ public class XZIndexTests : XZTestsBase [Fact] public void ReadsNoRecord() { - BinaryReader br = new BinaryReader(CompressedEmptyStream); + var br = new BinaryReader(CompressedEmptyStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)0, index.NumberOfRecords); @@ -42,7 +42,7 @@ public class XZIndexTests : XZTestsBase [Fact] public void ReadsOneRecord() { - BinaryReader br = new BinaryReader(CompressedStream); + var br = new BinaryReader(CompressedStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)1, index.NumberOfRecords); @@ -51,7 +51,7 @@ public class XZIndexTests : XZTestsBase [Fact] public void ReadsMultipleRecords() { - BinaryReader br = new BinaryReader(CompressedIndexedStream); + var br = new BinaryReader(CompressedIndexedStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)2, index.NumberOfRecords); @@ -60,7 +60,7 @@ public class XZIndexTests : XZTestsBase [Fact] public void ReadsFirstRecord() { - BinaryReader br = new BinaryReader(CompressedStream); + var br = new BinaryReader(CompressedStream); var index = new XZIndex(br, false); index.Process(); Assert.Equal((ulong)OriginalBytes.Length, index.Records[0].UncompressedSize); @@ -88,7 +88,7 @@ public class XZIndexTests : XZTestsBase 0xFF } ); - BinaryReader br = new BinaryReader(badStream); + var 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 7bff0ff5..dfbcf0ca 100644 --- a/tests/SharpCompress.Test/Xz/XZStreamTests.cs +++ b/tests/SharpCompress.Test/Xz/XZStreamTests.cs @@ -9,27 +9,27 @@ public class XZStreamTests : XZTestsBase [Fact] public void CanReadEmptyStream() { - XZStream xz = new XZStream(CompressedEmptyStream); + var xz = new XZStream(CompressedEmptyStream); using var sr = new StreamReader(xz); - string uncompressed = sr.ReadToEnd(); + var uncompressed = sr.ReadToEnd(); Assert.Equal(OriginalEmpty, uncompressed); } [Fact] public void CanReadStream() { - XZStream xz = new XZStream(CompressedStream); + var xz = new XZStream(CompressedStream); using var sr = new StreamReader(xz); - string uncompressed = sr.ReadToEnd(); + var uncompressed = sr.ReadToEnd(); Assert.Equal(Original, uncompressed); } [Fact] public void CanReadIndexedStream() { - XZStream xz = new XZStream(CompressedIndexedStream); + var xz = new XZStream(CompressedIndexedStream); using var sr = new StreamReader(xz); - string uncompressed = sr.ReadToEnd(); + var uncompressed = sr.ReadToEnd(); Assert.Equal(OriginalIndexed, uncompressed); } } diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index fee99aaf..1948b26a 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -186,9 +186,9 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Random_Write_Remove() { - 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"); + 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"); using (var archive = ZipArchive.Open(unmodified)) { @@ -208,10 +208,10 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Random_Write_Add() { - 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"); + 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"); using (var archive = ZipArchive.Open(unmodified)) { @@ -228,12 +228,12 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Save_Twice() { - string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); - string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); + var scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); + var scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); using (var arc = ZipArchive.Create()) { - string str = "test.txt"; + var 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,9 +246,9 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Removal_Poly() { - string scratchPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); + var scratchPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); - using ZipArchive vfs = (ZipArchive)ArchiveFactory.Open(scratchPath); + using var vfs = (ZipArchive)ArchiveFactory.Open(scratchPath); var e = vfs.Entries.First(v => v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)); vfs.RemoveEntry(e); Assert.Null( @@ -274,8 +274,8 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Create_Same_Stream() { - string scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); - string scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); + var scratchPath1 = Path.Combine(SCRATCH_FILES_PATH, "a.zip"); + var scratchPath2 = Path.Combine(SCRATCH_FILES_PATH, "b.zip"); using (var arc = ZipArchive.Create()) { @@ -320,8 +320,8 @@ public class ZipArchiveTests : ArchiveTests } File.Copy(file, newFileName); } - string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); - string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); + var scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); + var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); using (var archive = ZipArchive.Create()) { @@ -387,7 +387,7 @@ public class ZipArchiveTests : ArchiveTests } File.Copy(file, newFileName); } - string scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); + var scratchPath = Path.Combine(SCRATCH2_FILES_PATH, "Zip.deflate.noEmptyDirs.zip"); using (var archive = ZipArchive.Create()) { @@ -453,7 +453,7 @@ public class ZipArchiveTests : ArchiveTests var isComplete = reader.IsComplete; Assert.Equal(1, reader.Volumes.Count); - string expectedComment = + 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); } @@ -482,10 +482,10 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Random_Entry_Access() { - string unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); + var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.noEmptyDirs.zip"); - ZipArchive a = ZipArchive.Open(unmodified); - int count = 0; + var a = ZipArchive.Open(unmodified); + var count = 0; foreach (var e in a.Entries) { count++; @@ -496,7 +496,7 @@ public class ZipArchiveTests : ArchiveTests a.Dispose(); a = ZipArchive.Open(unmodified); - int count2 = 0; + var count2 = 0; foreach (var e in a.Entries) { @@ -512,7 +512,7 @@ public class ZipArchiveTests : ArchiveTests } } - int count3 = 0; + var count3 = 0; foreach (var e in a.Entries) { count3++; @@ -524,20 +524,20 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Deflate_PKWear_Multipy_Entry_Access() { - string zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.pkware.zip"); + var zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.deflate.pkware.zip"); - using FileStream fileStream = File.Open(zipFile, FileMode.Open); - using IArchive archive = ArchiveFactory.Open( + 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 (IArchiveEntry entry in entries) + foreach (var entry in entries) { for (var i = 0; i < 100; i++) { using var memoryStream = new MemoryStream(); - using Stream entryStream = entry.OpenEntryStream(); + using var entryStream = entry.OpenEntryStream(); entryStream.CopyTo(memoryStream); } } @@ -549,7 +549,7 @@ public class ZipArchiveTests : ArchiveTests //windows only because of the paths Skip.IfNot(Environment.OSVersion.Platform == PlatformID.Win32NT); - string zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.Evil.zip"); + var zipFile = Path.Combine(TEST_ARCHIVES_PATH, "Zip.Evil.zip"); Assert.ThrowsAny(() => { @@ -574,9 +574,7 @@ public class ZipArchiveTests : ArchiveTests { MemoryStream stream = new NonSeekableMemoryStream(); - using ( - IWriter zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate) - ) + using (var 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])); @@ -590,10 +588,10 @@ public class ZipArchiveTests : ArchiveTests foreach (var entry in zipArchive.Entries) { using var entryStream = entry.OpenEntryStream(); - MemoryStream tempStream = new MemoryStream(); + var tempStream = new MemoryStream(); const int bufSize = 0x1000; - byte[] buf = new byte[bufSize]; - int bytesRead = 0; + var buf = new byte[bufSize]; + var bytesRead = 0; while ((bytesRead = entryStream.Read(buf, 0, bufSize)) > 0) { tempStream.Write(buf, 0, bytesRead); @@ -605,9 +603,9 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_BadLocalExtra_Read() { - string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.badlocalextra.zip"); + var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.badlocalextra.zip"); - using ZipArchive za = ZipArchive.Open(zipPath); + using var za = ZipArchive.Open(zipPath); var ex = Record.Exception(() => { var firstEntry = za.Entries.First(x => x.Key == "first.txt"); @@ -625,9 +623,9 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_NoCompression_DataDescriptors_Read() { - string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.datadescriptors.zip"); + var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.none.datadescriptors.zip"); - using ZipArchive za = ZipArchive.Open(zipPath); + using var za = ZipArchive.Open(zipPath); var firstEntry = za.Entries.First(x => x.Key == "first.txt"); var buffer = new byte[4096]; @@ -664,9 +662,9 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_LongComment_Read() { - string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.LongComment.zip"); + var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.LongComment.zip"); - using ZipArchive za = ZipArchive.Open(zipPath); + using var za = ZipArchive.Open(zipPath); var count = za.Entries.Count; Assert.Equal(1, count); } @@ -674,9 +672,9 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Zip64_CompressedSizeExtraOnly_Read() { - string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.compressedonly.zip"); + var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.zip64.compressedonly.zip"); - using ZipArchive za = ZipArchive.Open(zipPath); + using var za = ZipArchive.Open(zipPath); var firstEntry = za.Entries.First(x => x.Key == "test/test.txt"); using var memoryStream = new MemoryStream(); @@ -688,11 +686,11 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Uncompressed_Read_All() { - string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip"); + var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip"); using var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read); - IArchive archive = ArchiveFactory.Open(stream); - IReader reader = archive.ExtractAllEntries(); - int entries = 0; + var archive = ArchiveFactory.Open(stream); + var reader = archive.ExtractAllEntries(); + var entries = 0; while (reader.MoveToNextEntry()) { using (var entryStream = reader.OpenEntryStream()) @@ -719,9 +717,9 @@ public class ZipArchiveTests : ArchiveTests }; var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip"); using var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read); - IArchive archive = ArchiveFactory.Open(stream); - IReader reader = archive.ExtractAllEntries(); - int x = 0; + var archive = ArchiveFactory.Open(stream); + var reader = archive.ExtractAllEntries(); + var x = 0; while (reader.MoveToNextEntry()) { Assert.Equal(keys[x], reader.Entry.Key); @@ -737,7 +735,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)) { - IArchive archive = ArchiveFactory.Open( + var archive = ArchiveFactory.Open( stream, new ReaderOptions { @@ -747,13 +745,13 @@ public class ZipArchiveTests : ArchiveTests } } ); - IReader reader = archive.ExtractAllEntries(); + var reader = archive.ExtractAllEntries(); reader.MoveToNextEntry(); Assert.Equal("궖귛궖귙귪궖귗귪궖귙_wav.frq", reader.Entry.Key); } using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read)) { - IArchive archive = ArchiveFactory.Open( + var archive = ArchiveFactory.Open( stream, new ReaderOptions { @@ -763,7 +761,7 @@ public class ZipArchiveTests : ArchiveTests } } ); - IReader reader = archive.ExtractAllEntries(); + var reader = archive.ExtractAllEntries(); reader.MoveToNextEntry(); Assert.Equal("きょきゅんきゃんきゅ_wav.frq", reader.Entry.Key); } From 5f13e245f007ea65f66446ae73d4f778c223a541 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 08:53:08 +0000 Subject: [PATCH 0044/1333] more clean up on tests --- tests/SharpCompress.Test/ADCTest.cs | 14 ++-- tests/SharpCompress.Test/ArchiveTests.cs | 5 +- .../Filters/BranchExecTests.cs | 58 +++++++------- .../Mocks/FlushOnDisposeStream.cs | 18 ++--- .../Mocks/ForwardOnlyStream.cs | 8 +- tests/SharpCompress.Test/Mocks/TestStream.cs | 22 +++--- .../Rar/RarHeaderFactoryTest.cs | 8 +- tests/SharpCompress.Test/ReaderTests.cs | 1 + .../Streams/LzmaStreamTests.cs | 18 ++--- .../SharpCompress.Test/Tar/TarReaderTests.cs | 16 ++-- tests/SharpCompress.Test/WriterTests.cs | 6 +- tests/SharpCompress.Test/Xz/Crc32Tests.cs | 12 +-- tests/SharpCompress.Test/Xz/Crc64Tests.cs | 12 +-- .../SharpCompress.Test/Xz/Filters/BCJTests.cs | 76 +++++++++---------- .../Xz/Filters/Lzma2Tests.cs | 24 +++--- tests/SharpCompress.Test/Xz/XZBlockTests.cs | 34 ++++----- tests/SharpCompress.Test/Xz/XZHeaderTests.cs | 2 +- tests/SharpCompress.Test/Xz/XZIndexTests.cs | 2 +- tests/SharpCompress.Test/Xz/XZStreamTests.cs | 2 +- tests/SharpCompress.Test/Xz/XZTestsBase.cs | 4 +- tests/SharpCompress.Test/Zip/Zip64Tests.cs | 32 ++++---- 21 files changed, 187 insertions(+), 187 deletions(-) diff --git a/tests/SharpCompress.Test/ADCTest.cs b/tests/SharpCompress.Test/ADCTest.cs index 66349a07..8ef40a17 100644 --- a/tests/SharpCompress.Test/ADCTest.cs +++ b/tests/SharpCompress.Test/ADCTest.cs @@ -31,7 +31,7 @@ using Xunit; namespace SharpCompress.Test; -public class ADCTest : TestBase +public class AdcTest : TestBase { [Fact] public void TestBuffer() @@ -64,7 +64,7 @@ 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]; @@ -80,7 +80,7 @@ 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]; @@ -114,11 +114,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 dc0aa979..41135e7d 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -199,10 +199,7 @@ public class ArchiveTests : ReaderTests ) { var src = testArchives.ToArray(); - using var archive = ArchiveFactory.Open( - testArchives.Select(f => new FileInfo(f)), - readerOptions - ); + 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)) { diff --git a/tests/SharpCompress.Test/Filters/BranchExecTests.cs b/tests/SharpCompress.Test/Filters/BranchExecTests.cs index e43318a9..00d724b9 100644 --- a/tests/SharpCompress.Test/Filters/BranchExecTests.cs +++ b/tests/SharpCompress.Test/Filters/BranchExecTests.cs @@ -12,7 +12,7 @@ namespace SharpCompress.Test.Filters; public class BranchExecTests { - private static byte[] x86resultData { get; } = + private static byte[] X86ResultData { get; } = { 0x12, 0x00, @@ -94,7 +94,7 @@ public class BranchExecTests 0x00, }; - private static byte[] x86Data { get; } = + private static byte[] X86Data { get; } = { 0x12, 0x00, @@ -176,7 +176,7 @@ public class BranchExecTests 0x00, }; - private static byte[] ppcResultData { get; } = + private static byte[] PpcResultData { get; } = { 0xF8, 0x6B, @@ -276,7 +276,7 @@ public class BranchExecTests 0xED }; - private static byte[] ppcData { get; } = + private static byte[] PpcData { get; } = { 0xF8, 0x6B, @@ -376,7 +376,7 @@ public class BranchExecTests 0xED }; - private static byte[] armResultData { get; } = + private static byte[] ArmResultData { get; } = { 0x7C, 0xFC, @@ -476,7 +476,7 @@ public class BranchExecTests 0xE2 }; - private static byte[] armData { get; } = + private static byte[] ArmData { get; } = { 0x7C, 0xFC, @@ -576,7 +576,7 @@ public class BranchExecTests 0xE2 }; - private static byte[] armtResultData { get; } = + private static byte[] ArmtResultData { get; } = { 0x95, 0x23, @@ -692,7 +692,7 @@ public class BranchExecTests 0x0F }; - private static byte[] armtData { get; } = + private static byte[] ArmtData { get; } = { 0x95, 0x23, @@ -808,7 +808,7 @@ public class BranchExecTests 0x0F }; - private static byte[] ia64ResultData { get; } = + private static byte[] Ia64ResultData { get; } = { 0x4D, 0xF8, @@ -908,7 +908,7 @@ public class BranchExecTests 0x0D }; - private static byte[] ia64Data { get; } = + private static byte[] Ia64Data { get; } = { 0x4D, 0xF8, @@ -1008,7 +1008,7 @@ public class BranchExecTests 0x0D }; - private static byte[] sparcResultData { get; } = + private static byte[] SparcResultData { get; } = { 0x78, 0x2E, @@ -1090,7 +1090,7 @@ public class BranchExecTests 0x00, }; - private static byte[] sparcData { get; } = + private static byte[] SparcData { get; } = { 0x78, 0x2E, @@ -1180,53 +1180,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/Mocks/FlushOnDisposeStream.cs b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs index 062351a1..ab9b7c78 100644 --- a/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs +++ b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs @@ -9,28 +9,28 @@ namespace SharpCompress.Test.Mocks; public class FlushOnDisposeStream : Stream, IDisposable { - private Stream inner; + private Stream _inner; - public FlushOnDisposeStream(Stream innerStream) => inner = innerStream; + public FlushOnDisposeStream(Stream innerStream) => _inner = innerStream; - public override bool CanRead => inner.CanRead; + public override bool CanRead => _inner.CanRead; public override bool CanSeek => false; public override bool CanWrite => false; - public override long Length => inner.Length; + public override long Length => _inner.Length; public override long Position { - get => inner.Position; - set => inner.Position = value; + get => _inner.Position; + set => _inner.Position = value; } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) => - inner.Read(buffer, offset, count); + _inner.Read(buffer, offset, count); public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); @@ -44,8 +44,8 @@ public class FlushOnDisposeStream : Stream, IDisposable { if (disposing) { - inner.Flush(); - inner.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 e18bd707..bdaac761 100644 --- a/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs +++ b/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs @@ -5,11 +5,11 @@ namespace SharpCompress.Test.Mocks; public class ForwardOnlyStream : Stream { - private readonly Stream stream; + private readonly Stream _stream; public bool IsDisposed { get; private set; } - public ForwardOnlyStream(Stream stream) => this.stream = stream; + public ForwardOnlyStream(Stream stream) => _stream = stream; protected override void Dispose(bool disposing) { @@ -17,7 +17,7 @@ public class ForwardOnlyStream : Stream { if (disposing) { - stream.Dispose(); + _stream.Dispose(); IsDisposed = true; base.Dispose(disposing); } @@ -40,7 +40,7 @@ public class ForwardOnlyStream : Stream } public override int Read(byte[] buffer, int offset, int count) => - stream.Read(buffer, offset, count); + _stream.Read(buffer, offset, count); public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); diff --git a/tests/SharpCompress.Test/Mocks/TestStream.cs b/tests/SharpCompress.Test/Mocks/TestStream.cs index 66923df3..daa39fc2 100644 --- a/tests/SharpCompress.Test/Mocks/TestStream.cs +++ b/tests/SharpCompress.Test/Mocks/TestStream.cs @@ -4,7 +4,7 @@ namespace SharpCompress.Test.Mocks; public class TestStream : Stream { - private readonly Stream stream; + private readonly Stream _stream; public TestStream(Stream stream) : this(stream, stream.CanRead, stream.CanWrite, stream.CanSeek) { } @@ -13,7 +13,7 @@ public class TestStream : Stream public TestStream(Stream stream, bool read, bool write, bool seek) { - this.stream = stream; + _stream = stream; CanRead = read; CanWrite = write; CanSeek = seek; @@ -22,7 +22,7 @@ public class TestStream : Stream protected override void Dispose(bool disposing) { base.Dispose(disposing); - stream.Dispose(); + _stream.Dispose(); IsDisposed = true; } @@ -32,23 +32,23 @@ public class TestStream : Stream public override bool CanWrite { get; } - public override void Flush() => stream.Flush(); + public override void Flush() => _stream.Flush(); - public override long Length => stream.Length; + public override long Length => _stream.Length; public override long Position { - get => stream.Position; - set => stream.Position = value; + get => _stream.Position; + set => _stream.Position = value; } public override int Read(byte[] buffer, int offset, int count) => - stream.Read(buffer, offset, count); + _stream.Read(buffer, offset, count); - public override long Seek(long offset, SeekOrigin origin) => stream.Seek(offset, origin); + public override long Seek(long offset, SeekOrigin origin) => _stream.Seek(offset, origin); - public override void SetLength(long value) => stream.SetLength(value); + public override void SetLength(long value) => _stream.SetLength(value); public override void Write(byte[] buffer, int offset, int count) => - stream.Write(buffer, offset, count); + _stream.Write(buffer, offset, count); } diff --git a/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs b/tests/SharpCompress.Test/Rar/RarHeaderFactoryTest.cs index f2b1913c..70015fcf 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/ReaderTests.cs b/tests/SharpCompress.Test/ReaderTests.cs index a5f00d97..b62dd4d2 100644 --- a/tests/SharpCompress.Test/ReaderTests.cs +++ b/tests/SharpCompress.Test/ReaderTests.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using SharpCompress.Common; diff --git a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs index ea002d62..492a96fd 100644 --- a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs +++ b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs @@ -19,7 +19,7 @@ public class LzmaStreamTests Assert.Equal('X', decompressor.ReadByte()); } - private static byte[] lzmaData { get; } = + private static byte[] LzmaData { get; } = { 0x5D, 0x00, @@ -178,9 +178,9 @@ public class LzmaStreamTests }; /// - /// The decoded data for . + /// The decoded data for . /// - private static byte[] lzmaResultData { get; } = + private static byte[] LzmaResultData { get; } = { 0x01, 0x00, @@ -515,7 +515,7 @@ public class LzmaStreamTests [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,13 +528,13 @@ 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 var inputStream = new MemoryStream(LzmaResultData); using MemoryStream outputStream = new(); using var lzmaStream = new LzmaStream(LzmaEncoderProperties.Default, false, outputStream); inputStream.CopyTo(lzmaStream); @@ -545,7 +545,7 @@ 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); input.CopyTo(lzmaEncodingStream); @@ -558,10 +558,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( diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index 718b75ed..a1667d7d 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -6,6 +6,11 @@ using SharpCompress.Readers; using SharpCompress.Readers.Tar; using SharpCompress.Test.Mocks; using Xunit; +#if !NETFRAMEWORK +using System.Runtime.InteropServices; +using Mono.Unix; +#endif + namespace SharpCompress.Test.Tar; @@ -124,7 +129,7 @@ public class TarReaderTests : ReaderTests { using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.bz2")); using var reader = TarReader.Open(stream); - List names = new List(); + var names = new List(); while (reader.MoveToNextEntry()) { if (!reader.Entry.IsDirectory) @@ -173,13 +178,11 @@ public class TarReaderTests : ReaderTests using var reader = ReaderFactory.Open(stream); var memoryStream = new MemoryStream(); - Action action = () => reader.MoveToNextEntry(); - var exception = Record.Exception(action); - Assert.Null(exception); - reader.MoveToNextEntry(); + Assert.True(reader.MoveToNextEntry()); + Assert.True(reader.MoveToNextEntry()); reader.WriteEntryTo(memoryStream); stream.Close(); - Assert.Throws(action); + Assert.Throws(() => reader.MoveToNextEntry()); } #if !NETFRAMEWORK @@ -191,7 +194,6 @@ public class TarReaderTests : ReaderTests Path.Combine(TEST_ARCHIVES_PATH, "TarWithSymlink.tar.gz") ); using var reader = TarReader.Open(stream); - List names = new List(); while (reader.MoveToNextEntry()) { if (reader.Entry.IsDirectory) diff --git a/tests/SharpCompress.Test/WriterTests.cs b/tests/SharpCompress.Test/WriterTests.cs index 7b33e377..50695ef1 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) => this.type = type; + protected WriterTests(ArchiveType type) => _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( diff --git a/tests/SharpCompress.Test/Xz/Crc32Tests.cs b/tests/SharpCompress.Test/Xz/Crc32Tests.cs index 52b71078..eaa0b100 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 SimpleString = @"The quick brown fox jumps over the lazy dog."; - private readonly byte[] SimpleBytes = Encoding.ASCII.GetBytes(SimpleString); - private const string SimpleString2 = + 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 = @"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(SimpleString2); + private readonly byte[] _simpleBytes2 = Encoding.ASCII.GetBytes(SIMPLE_STRING2); [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 79912e48..8cf71e1e 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 SimpleString = @"The quick brown fox jumps over the lazy dog."; - private readonly byte[] SimpleBytes = Encoding.ASCII.GetBytes(SimpleString); - private const string SimpleString2 = + 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 = @"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(SimpleString2); + private readonly byte[] _simpleBytes2 = Encoding.ASCII.GetBytes(SIMPLE_STRING2); [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 427a7b98..bc16789d 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 ff5dd467..c5b34f93 100644 --- a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs @@ -5,21 +5,21 @@ 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(new[] { inByte }); - Assert.Equal(filter.DictionarySize, dicSize); + _filter.Init(new[] { inByte }); + Assert.Equal(_filter.DictionarySize, dicSize); } [Fact] public void CalculatesDictionarySizeError() { uint temp; - filter.Init(new byte[] { 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(new byte[] { 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 87e68d93..78873590 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 7ce7dd48..ba684c2d 100644 --- a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs +++ b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs @@ -4,7 +4,7 @@ using Xunit; namespace SharpCompress.Test.Xz; -public class XZHeaderTests : XZTestsBase +public class XzHeaderTests : XzTestsBase { [Fact] public void ChecksMagicNumber() diff --git a/tests/SharpCompress.Test/Xz/XZIndexTests.cs b/tests/SharpCompress.Test/Xz/XZIndexTests.cs index f87f7b9b..341e8a42 100644 --- a/tests/SharpCompress.Test/Xz/XZIndexTests.cs +++ b/tests/SharpCompress.Test/Xz/XZIndexTests.cs @@ -4,7 +4,7 @@ using Xunit; namespace SharpCompress.Test.Xz; -public class XZIndexTests : XZTestsBase +public class XzIndexTests : XzTestsBase { protected override void RewindEmpty(Stream stream) => stream.Position = 12; diff --git a/tests/SharpCompress.Test/Xz/XZStreamTests.cs b/tests/SharpCompress.Test/Xz/XZStreamTests.cs index dfbcf0ca..02c5020c 100644 --- a/tests/SharpCompress.Test/Xz/XZStreamTests.cs +++ b/tests/SharpCompress.Test/Xz/XZStreamTests.cs @@ -4,7 +4,7 @@ using Xunit; namespace SharpCompress.Test.Xz; -public class XZStreamTests : XZTestsBase +public class XzStreamTests : XzTestsBase { [Fact] public void CanReadEmptyStream() diff --git a/tests/SharpCompress.Test/Xz/XZTestsBase.cs b/tests/SharpCompress.Test/Xz/XZTestsBase.cs index 0b88dc52..a4c3dcfb 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); diff --git a/tests/SharpCompress.Test/Zip/Zip64Tests.cs b/tests/SharpCompress.Test/Zip/Zip64Tests.cs index c4c4c987..a89b1128 100644 --- a/tests/SharpCompress.Test/Zip/Zip64Tests.cs +++ b/tests/SharpCompress.Test/Zip/Zip64Tests.cs @@ -25,27 +25,27 @@ public class Zip64Tests : WriterTests [Trait("format", "zip64")] public void Zip64_Single_Large_File() => // One single file, requires zip64 - RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: true, forward_only: false); + RunSingleTest(1, FOUR_GB_LIMIT, setZip64: true, forwardOnly: false); [Trait("format", "zip64")] public void Zip64_Two_Large_Files() => // One single file, requires zip64 - RunSingleTest(2, FOUR_GB_LIMIT, set_zip64: true, forward_only: false); + RunSingleTest(2, FOUR_GB_LIMIT, setZip64: true, forwardOnly: false); [Trait("format", "zip64")] public void Zip64_Two_Small_files() => // Multiple files, does not require zip64 - RunSingleTest(2, FOUR_GB_LIMIT / 2, set_zip64: false, forward_only: false); + RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: false, forwardOnly: 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, set_zip64: false, forward_only: true); + RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: false, forwardOnly: 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, set_zip64: true, forward_only: false); + RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: true, forwardOnly: false); [Trait("format", "zip64")] public void Zip64_Single_Large_File_Fail() @@ -53,7 +53,7 @@ public class Zip64Tests : WriterTests try { // One single file, should fail - RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: false, forward_only: false); + RunSingleTest(1, FOUR_GB_LIMIT, setZip64: false, forwardOnly: false); throw new InvalidOperationException("Test did not fail?"); } catch (NotSupportedException) { } @@ -65,7 +65,7 @@ public class Zip64Tests : WriterTests try { // One single file, should fail (fast) with zip64 - RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: true, forward_only: true); + RunSingleTest(1, FOUR_GB_LIMIT, setZip64: true, forwardOnly: true); throw new InvalidOperationException("Test did not fail?"); } catch (NotSupportedException) { } @@ -77,7 +77,7 @@ public class Zip64Tests : WriterTests try { // One single file, should fail once the write discovers the problem - RunSingleTest(1, FOUR_GB_LIMIT, set_zip64: false, forward_only: true); + RunSingleTest(1, FOUR_GB_LIMIT, setZip64: false, forwardOnly: true); throw new InvalidOperationException("Test did not fail?"); } catch (NotSupportedException) { } @@ -86,9 +86,9 @@ public class Zip64Tests : WriterTests public void RunSingleTest( long files, long filesize, - bool set_zip64, - bool forward_only, - long write_chunk_size = 1024 * 1024, + bool setZip64, + bool forwardOnly, + long writeChunkSize = 1024 * 1024, string filename = "zip64-test.zip" ) { @@ -101,7 +101,7 @@ public class Zip64Tests : WriterTests if (!File.Exists(filename)) { - CreateZipArchive(filename, files, filesize, write_chunk_size, set_zip64, forward_only); + CreateZipArchive(filename, files, filesize, writeChunkSize, setZip64, forwardOnly); } var resForward = ReadForwardOnly(filename); @@ -140,20 +140,20 @@ public class Zip64Tests : WriterTests long files, long filesize, long chunksize, - bool set_zip64, - bool forward_only + bool setZip64, + bool forwardOnly ) { var data = new byte[chunksize]; // Use deflate for speed - var opts = new ZipWriterOptions(CompressionType.Deflate) { UseZip64 = set_zip64 }; + var opts = new ZipWriterOptions(CompressionType.Deflate) { UseZip64 = setZip64 }; // 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 }; using var zip = File.OpenWrite(filename); - using var st = forward_only ? (Stream)new ForwardOnlyStream(zip) : zip; + using var st = forwardOnly ? (Stream)new ForwardOnlyStream(zip) : zip; using var zipWriter = (ZipWriter)WriterFactory.Open(st, ArchiveType.Zip, opts); for (var i = 0; i < files; i++) { From 94d1503c64c1101b91dc83dc3dbd3d21cea4ca27 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 08:57:16 +0000 Subject: [PATCH 0045/1333] more clean up --- .../Filters/BranchExecTests.cs | 56 +++++++++---------- .../Mocks/FlushOnDisposeStream.cs | 20 +++---- .../Mocks/ForwardOnlyStream.cs | 10 +--- tests/SharpCompress.Test/Mocks/TestStream.cs | 36 +++++------- .../SharpCompress.Test/Rar/RarArchiveTests.cs | 48 +++++++--------- .../SharpCompress.Test/Rar/RarReaderTests.cs | 25 ++++----- .../Streams/LzmaStreamTests.cs | 8 +-- tests/SharpCompress.Test/TestBase.cs | 24 ++++---- .../Xz/Filters/Lzma2Tests.cs | 6 +- tests/SharpCompress.Test/Xz/XZHeaderTests.cs | 2 +- tests/SharpCompress.Test/Xz/XZIndexTests.cs | 21 +------ tests/SharpCompress.Test/Xz/XZTestsBase.cs | 12 ++-- 12 files changed, 111 insertions(+), 157 deletions(-) diff --git a/tests/SharpCompress.Test/Filters/BranchExecTests.cs b/tests/SharpCompress.Test/Filters/BranchExecTests.cs index 00d724b9..ca9686a4 100644 --- a/tests/SharpCompress.Test/Filters/BranchExecTests.cs +++ b/tests/SharpCompress.Test/Filters/BranchExecTests.cs @@ -13,7 +13,7 @@ namespace SharpCompress.Test.Filters; public class BranchExecTests { private static byte[] X86ResultData { get; } = - { + [ 0x12, 0x00, 0x00, @@ -91,11 +91,11 @@ public class BranchExecTests 0x00, 0x00, 0x1C, - 0x00, - }; + 0x00 + ]; private static byte[] X86Data { get; } = - { + [ 0x12, 0x00, 0x00, @@ -173,11 +173,11 @@ public class BranchExecTests 0x00, 0x00, 0x1C, - 0x00, - }; + 0x00 + ]; private static byte[] PpcResultData { get; } = - { + [ 0xF8, 0x6B, 0x2E, @@ -274,10 +274,10 @@ public class BranchExecTests 0xB2, 0xD4, 0xED - }; + ]; private static byte[] PpcData { get; } = - { + [ 0xF8, 0x6B, 0x2E, @@ -374,10 +374,10 @@ public class BranchExecTests 0xB2, 0xD4, 0xED - }; + ]; private static byte[] ArmResultData { get; } = - { + [ 0x7C, 0xFC, 0x0A, @@ -474,10 +474,10 @@ public class BranchExecTests 0xC6, 0x8F, 0xE2 - }; + ]; private static byte[] ArmData { get; } = - { + [ 0x7C, 0xFC, 0x0A, @@ -574,10 +574,10 @@ public class BranchExecTests 0xC6, 0x8F, 0xE2 - }; + ]; private static byte[] ArmtResultData { get; } = - { + [ 0x95, 0x23, 0xB6, @@ -690,10 +690,10 @@ public class BranchExecTests 0xED, 0x11, 0x0F - }; + ]; private static byte[] ArmtData { get; } = - { + [ 0x95, 0x23, 0xB6, @@ -806,10 +806,10 @@ public class BranchExecTests 0xED, 0x11, 0x0F - }; + ]; private static byte[] Ia64ResultData { get; } = - { + [ 0x4D, 0xF8, 0xF2, @@ -906,10 +906,10 @@ public class BranchExecTests 0x72, 0xD5, 0x0D - }; + ]; private static byte[] Ia64Data { get; } = - { + [ 0x4D, 0xF8, 0xF2, @@ -1006,10 +1006,10 @@ public class BranchExecTests 0x72, 0xD5, 0x0D - }; + ]; private static byte[] SparcResultData { get; } = - { + [ 0x78, 0x2E, 0x73, @@ -1087,11 +1087,11 @@ public class BranchExecTests 0x91, 0x00, 0x10, - 0x00, - }; + 0x00 + ]; private static byte[] SparcData { get; } = - { + [ 0x78, 0x2E, 0x73, @@ -1169,8 +1169,8 @@ public class BranchExecTests 0x91, 0x00, 0x10, - 0x00, - }; + 0x00 + ]; private void CompareBuffer(byte[] testBuffer, byte[] targetBuffer) => Assert.Equal(testBuffer, targetBuffer); diff --git a/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs index ab9b7c78..56cd0161 100644 --- a/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs +++ b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs @@ -7,30 +7,26 @@ 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, IDisposable +public class FlushOnDisposeStream(Stream innerStream) : Stream { - private Stream _inner; - - public FlushOnDisposeStream(Stream innerStream) => _inner = innerStream; - - public override bool CanRead => _inner.CanRead; + public override bool CanRead => innerStream.CanRead; public override bool CanSeek => false; public override bool CanWrite => false; - public override long Length => _inner.Length; + public override long Length => innerStream.Length; public override long Position { - get => _inner.Position; - set => _inner.Position = value; + get => innerStream.Position; + set => innerStream.Position = value; } public override void Flush() { } public override int Read(byte[] buffer, int offset, int count) => - _inner.Read(buffer, offset, count); + innerStream.Read(buffer, offset, count); public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException(); @@ -44,8 +40,8 @@ public class FlushOnDisposeStream : Stream, IDisposable { if (disposing) { - _inner.Flush(); - _inner.Close(); + innerStream.Flush(); + innerStream.Close(); } base.Dispose(disposing); diff --git a/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs b/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs index bdaac761..180b8416 100644 --- a/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs +++ b/tests/SharpCompress.Test/Mocks/ForwardOnlyStream.cs @@ -3,21 +3,17 @@ using System.IO; namespace SharpCompress.Test.Mocks; -public class ForwardOnlyStream : Stream +public class ForwardOnlyStream(Stream stream) : Stream { - private readonly Stream _stream; - public bool IsDisposed { get; private set; } - public ForwardOnlyStream(Stream stream) => _stream = stream; - protected override void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { - _stream.Dispose(); + stream.Dispose(); IsDisposed = true; base.Dispose(disposing); } @@ -40,7 +36,7 @@ public class ForwardOnlyStream : Stream } public override int Read(byte[] buffer, int offset, int count) => - _stream.Read(buffer, offset, count); + stream.Read(buffer, offset, count); public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); diff --git a/tests/SharpCompress.Test/Mocks/TestStream.cs b/tests/SharpCompress.Test/Mocks/TestStream.cs index daa39fc2..da7d65cc 100644 --- a/tests/SharpCompress.Test/Mocks/TestStream.cs +++ b/tests/SharpCompress.Test/Mocks/TestStream.cs @@ -2,53 +2,43 @@ namespace SharpCompress.Test.Mocks; -public class TestStream : Stream +public class TestStream(Stream stream, bool read, bool write, bool seek) : 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) - { - _stream = stream; - CanRead = read; - CanWrite = write; - CanSeek = seek; - } - protected override void Dispose(bool disposing) { base.Dispose(disposing); - _stream.Dispose(); + stream.Dispose(); IsDisposed = true; } - public override bool CanRead { get; } + public override bool CanRead { get; } = read; - public override bool CanSeek { get; } + public override bool CanSeek { get; } = seek; - public override bool CanWrite { get; } + public override bool CanWrite { get; } = write; - public override void Flush() => _stream.Flush(); + public override void Flush() => stream.Flush(); - public override long Length => _stream.Length; + public override long Length => stream.Length; public override long Position { - get => _stream.Position; - set => _stream.Position = value; + get => stream.Position; + set => stream.Position = value; } public override int Read(byte[] buffer, int offset, int count) => - _stream.Read(buffer, offset, count); + stream.Read(buffer, offset, count); - public override long Seek(long offset, SeekOrigin origin) => _stream.Seek(offset, origin); + public override long Seek(long offset, SeekOrigin origin) => stream.Seek(offset, origin); - public override void SetLength(long value) => _stream.SetLength(value); + public override void SetLength(long value) => stream.SetLength(value); public override void Write(byte[] buffer, int offset, int count) => - _stream.Write(buffer, offset, count); + stream.Write(buffer, offset, count); } diff --git a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs index 513ba277..373af692 100644 --- a/tests/SharpCompress.Test/Rar/RarArchiveTests.cs +++ b/tests/SharpCompress.Test/Rar/RarArchiveTests.cs @@ -229,30 +229,28 @@ 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 ); @@ -274,15 +272,14 @@ 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 ); @@ -344,8 +341,7 @@ public class RarArchiveTests : ArchiveTests [Fact] public void Rar2_Multi_ArchiveStreamRead() => DoRar_Multi_ArchiveStreamRead( - new[] - { + [ "Rar2.multi.rar", "Rar2.multi.r00", "Rar2.multi.r01", @@ -353,7 +349,7 @@ public class RarArchiveTests : ArchiveTests "Rar2.multi.r03", "Rar2.multi.r04", "Rar2.multi.r05" - }, + ], false ); @@ -467,8 +463,7 @@ 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", @@ -476,7 +471,7 @@ public class RarArchiveTests : ArchiveTests "Rar4.multi.part05.rar", "Rar4.multi.part06.rar", "Rar4.multi.part07.rar" - }, + ], false ); @@ -485,15 +480,14 @@ 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 @@ -520,15 +514,14 @@ public class RarArchiveTests : ArchiveTests public void Rar4_Split_ArchiveStreamFirstFileRead() => ArchiveStreamMultiRead( null, - new[] - { - "Rar4.split.001", + [ + "Rar4.split.001" //"Rar4.split.002", //"Rar4.split.003", //"Rar4.split.004", //"Rar4.split.005", //"Rar4.split.006" - } + ] ); //open with ArchiveFactory.Open and stream @@ -561,12 +554,11 @@ public class RarArchiveTests : ArchiveTests [Fact] public void Rar4_Multi_ArchiveOpenEntryVolumeIndexTest() => ArchiveOpenEntryVolumeIndexTest( - 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 - }, + [ + [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 + ], null, "Rar4.multi.part01.rar", "Rar4.multi.part02.rar", diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index 981bd8ee..e2b100f6 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -13,29 +13,27 @@ 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) @@ -62,15 +60,14 @@ 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) => @@ -99,29 +96,27 @@ 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) diff --git a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs index 492a96fd..2eea6607 100644 --- a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs +++ b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs @@ -20,7 +20,7 @@ public class LzmaStreamTests } private static byte[] LzmaData { get; } = - { + [ 0x5D, 0x00, 0x20, @@ -175,13 +175,13 @@ public class LzmaStreamTests 0x76, 0x03, 0x90 - }; + ]; /// /// The decoded data for . /// private static byte[] LzmaResultData { get; } = - { + [ 0x01, 0x00, 0xFD, @@ -510,7 +510,7 @@ public class LzmaStreamTests 0x00, 0x00, 0x00 - }; + ]; [Fact] public void TestLzmaBuffer() diff --git a/tests/SharpCompress.Test/TestBase.cs b/tests/SharpCompress.Test/TestBase.cs index 3ad1fe79..ad39b2d7 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 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; + 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; - public TestBase() + protected 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()); - CompareFilesByTimeAndAttribut(orig.Single(), extracted[orig.Key].Single()); + CompareFilesByTimeAndAttribute(orig.Single(), extracted[orig.Key].Single()); } } /// /// Verifies the files by extension also check modified time and attributes. /// - protected void VerifyFilesByExtensionEx() + private 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()); - CompareFilesByTimeAndAttribut(orig.Single(), extracted[orig.Key].Single()); + CompareFilesByTimeAndAttribute(orig.Single(), extracted[orig.Key].Single()); } } @@ -194,7 +194,7 @@ public class TestBase : IDisposable } } - protected void CompareFilesByTimeAndAttribut(string file1, string file2) + private void CompareFilesByTimeAndAttribute(string file1, string file2) { var fi1 = new FileInfo(file1); var fi2 = new FileInfo(file2); diff --git a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs index c5b34f93..e77bc2f8 100644 --- a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs @@ -31,7 +31,7 @@ public class Lzma2Tests : XzTestsBase [InlineData(40, (uint)(1024 * 1024 * 1024 - 1) * 4 + 3)] public void CalculatesDictionarySize(byte inByte, uint dicSize) { - _filter.Init(new[] { inByte }); + _filter.Init([inByte]); Assert.Equal(_filter.DictionarySize, dicSize); } @@ -39,7 +39,7 @@ public class Lzma2Tests : XzTestsBase public void CalculatesDictionarySizeError() { uint temp; - _filter.Init(new byte[] { 41 }); + _filter.Init([41]); var ex = Assert.Throws(() => { temp = _filter.DictionarySize; @@ -59,7 +59,7 @@ public class Lzma2Tests : XzTestsBase [Fact] public void ReservedBytesThrow() { - var ex = Assert.Throws(() => _filter.Init(new byte[] { 0xC0 })); + var ex = Assert.Throws(() => _filter.Init([0xC0])); Assert.Equal("Reserved bits used in LZMA properties", ex.Message); } } diff --git a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs index ba684c2d..8815b7a9 100644 --- a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs +++ b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs @@ -40,7 +40,7 @@ public class XzHeaderTests : XzTestsBase public void BadVersionIfCrcOkButStreamFlagUnknown() { var bytes = (byte[])Compressed.Clone(); - byte[] streamFlags = { 0x00, 0xF4 }; + byte[] streamFlags = [0x00, 0xF4]; var crc = Crc32.Compute(streamFlags).ToLittleEndianBytes(); streamFlags.CopyTo(bytes, 6); crc.CopyTo(bytes, 8); diff --git a/tests/SharpCompress.Test/Xz/XZIndexTests.cs b/tests/SharpCompress.Test/Xz/XZIndexTests.cs index 341e8a42..b00b9d1a 100644 --- a/tests/SharpCompress.Test/Xz/XZIndexTests.cs +++ b/tests/SharpCompress.Test/Xz/XZIndexTests.cs @@ -15,7 +15,7 @@ public class XzIndexTests : XzTestsBase [Fact] public void RecordsStreamStartOnInit() { - using Stream badStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 }); + 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); @@ -24,7 +24,7 @@ public class XzIndexTests : XzTestsBase [Fact] public void ThrowsIfHasNoIndexMarker() { - using Stream badStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5 }); + 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()); @@ -71,22 +71,7 @@ public class XzIndexTests : XzTestsBase { // Index with 3-byte padding. using Stream badStream = new MemoryStream( - new byte[] - { - 0x00, - 0x01, - 0x10, - 0x80, - 0x01, - 0x00, - 0x00, - 0x00, - 0xB1, - 0x01, - 0xD9, - 0xC9, - 0xFF - } + [0x00, 0x01, 0x10, 0x80, 0x01, 0x00, 0x00, 0x00, 0xB1, 0x01, 0xD9, 0xC9, 0xFF] ); var br = new BinaryReader(badStream); var index = new XZIndex(br, false); diff --git a/tests/SharpCompress.Test/Xz/XZTestsBase.cs b/tests/SharpCompress.Test/Xz/XZTestsBase.cs index a4c3dcfb..a679934e 100644 --- a/tests/SharpCompress.Test/Xz/XZTestsBase.cs +++ b/tests/SharpCompress.Test/Xz/XZTestsBase.cs @@ -29,7 +29,7 @@ public abstract class XzTestsBase : IDisposable protected Stream CompressedEmptyStream { get; } = new MemoryStream(CompressedEmpty); protected static byte[] CompressedEmpty { get; } = - { + [ 0xfd, 0x37, 0x7a, @@ -62,7 +62,7 @@ public abstract class XzTestsBase : IDisposable 0x01, 0x59, 0x5a - }; + ]; protected static byte[] OriginalEmptyBytes => Encoding.ASCII.GetBytes(OriginalEmpty); @@ -71,7 +71,7 @@ public abstract class XzTestsBase : IDisposable protected Stream CompressedStream { get; } = new MemoryStream(Compressed); protected static byte[] Compressed { get; } = - { + [ 0xfd, 0x37, 0x7a, @@ -452,7 +452,7 @@ public abstract class XzTestsBase : IDisposable 0x04, 0x59, 0x5a - }; + ]; protected static byte[] OriginalBytes => Encoding.ASCII.GetBytes(Original); protected static string Original { get; } = @@ -479,7 +479,7 @@ public abstract class XzTestsBase : IDisposable protected Stream CompressedIndexedStream { get; } = new MemoryStream(CompressedIndexed); protected static byte[] CompressedIndexed { get; } = - { + [ 0xfd, 0x37, 0x7a, @@ -1120,7 +1120,7 @@ public abstract class XzTestsBase : IDisposable 0x01, 0x59, 0x5a - }; + ]; protected static byte[] OriginalIndexedBytes => Encoding.ASCII.GetBytes(OriginalIndexed); From 198a0673a2f11953ce5ad024340ca8d66ad60f32 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 09:00:44 +0000 Subject: [PATCH 0046/1333] more clean up --- .../Archives/AbstractWritableArchive.cs | 6 +- .../Archives/GZip/GZipArchive.cs | 2 +- src/SharpCompress/Archives/Rar/RarArchive.cs | 7 +- src/SharpCompress/Archives/Tar/TarArchive.cs | 2 +- src/SharpCompress/Archives/Zip/ZipArchive.cs | 2 +- src/SharpCompress/Common/OptionsBase.cs | 2 +- .../Common/Rar/Headers/ArchiveCryptHeader.cs | 2 +- .../Common/Rar/RarCryptoBinaryReader.cs | 2 +- .../Common/Rar/RarCryptoWrapper.cs | 2 +- .../Common/SevenZip/ArchiveDatabase.cs | 14 +-- .../Common/SevenZip/ArchiveReader.cs | 6 +- src/SharpCompress/Common/SevenZip/CFolder.cs | 8 +- .../Common/SevenZip/CMethodId.cs | 8 +- .../Common/Tar/Headers/TarHeader.cs | 2 +- .../Zip/PkwareTraditionalEncryptionData.cs | 2 +- .../Compressors/BZip2/CBZip2InputStream.cs | 2 +- .../Compressors/BZip2/CBZip2OutputStream.cs | 2 +- .../Compressors/Deflate/DeflateManager.cs | 6 +- .../Compressors/Deflate/DeflateStream.cs | 4 +- .../Compressors/Deflate/GZipStream.cs | 18 ++-- .../Compressors/Deflate/Inflate.cs | 4 +- .../Compressors/Deflate64/DeflateInput.cs | 2 +- .../Compressors/Deflate64/HuffmanTree.cs | 6 +- src/SharpCompress/Compressors/LZMA/Log.cs | 2 +- .../Compressors/LZMA/LzmaDecoder.cs | 16 ++-- .../Compressors/LZMA/LzmaEncoder.cs | 18 ++-- .../Compressors/LZMA/LzmaStream.cs | 4 +- .../Compressors/PPMd/H/ModelPPM.cs | 22 ++--- .../Compressors/PPMd/H/PPMContext.cs | 10 +-- .../Compressors/PPMd/I1/MemoryNode.cs | 14 +-- .../Compressors/PPMd/I1/Pointer.cs | 8 +- .../Compressors/PPMd/I1/PpmContext.cs | 36 ++++---- .../Compressors/PPMd/I1/PpmState.cs | 16 ++-- .../Compressors/Rar/UnpackV1/Unpack.cs | 10 +-- .../Compressors/Rar/UnpackV1/Unpack20.cs | 10 +-- .../Compressors/Rar/UnpackV2017/unpack_hpp.cs | 12 +-- src/SharpCompress/Compressors/Rar/VM/RarVM.cs | 14 +-- .../Compressors/Rar/VM/VMPreparedProgram.cs | 8 +- src/SharpCompress/Compressors/Xz/XZBlock.cs | 2 +- src/SharpCompress/Compressors/Xz/XZIndex.cs | 2 +- src/SharpCompress/Factories/Factory.cs | 2 +- src/SharpCompress/IO/BufferedSubStream.cs | 39 ++++----- src/SharpCompress/IO/DataDescriptorStream.cs | 44 +++++----- src/SharpCompress/IO/ListeningStream.cs | 14 +-- src/SharpCompress/IO/ReadOnlySubStream.cs | 4 +- src/SharpCompress/IO/RewindableStream.cs | 86 +++++++++---------- src/SharpCompress/Lazy.cs | 27 ------ src/SharpCompress/LazyReadOnlyCollection.cs | 2 +- src/SharpCompress/Readers/AbstractReader.cs | 2 +- src/SharpCompress/Readers/Rar/RarReader.cs | 6 +- src/SharpCompress/Utility.cs | 3 +- src/SharpCompress/Writers/WriterOptions.cs | 2 +- src/SharpCompress/Writers/Zip/ZipWriter.cs | 4 +- 53 files changed, 254 insertions(+), 296 deletions(-) delete mode 100644 src/SharpCompress/Lazy.cs diff --git a/src/SharpCompress/Archives/AbstractWritableArchive.cs b/src/SharpCompress/Archives/AbstractWritableArchive.cs index 30083ec7..84ca0b3f 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -31,10 +31,10 @@ public abstract class AbstractWritableArchive } } - private readonly List newEntries = new List(); - private readonly List removedEntries = new List(); + private readonly List newEntries = new(); + private readonly List removedEntries = new(); - private readonly List modifiedEntries = new List(); + private readonly List modifiedEntries = new(); private bool hasModifications; private bool pauseRebuilding; diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index fb2f7691..70924b04 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -94,7 +94,7 @@ public class GZipArchive : AbstractWritableArchive ); } - public static GZipArchive Create() => new GZipArchive(); + public static GZipArchive Create() => new(); /// /// Constructor with a SourceStream able to handle FileInfo and Streams. diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 5d1883f5..56177e02 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -13,10 +14,8 @@ namespace SharpCompress.Archives.Rar; public class RarArchive : AbstractArchive { - internal Lazy UnpackV2017 { get; } = - new Lazy(() => new Compressors.Rar.UnpackV2017.Unpack()); - internal Lazy UnpackV1 { get; } = - new Lazy(() => new Compressors.Rar.UnpackV1.Unpack()); + internal Lazy UnpackV2017 { get; } = new(() => new Compressors.Rar.UnpackV2017.Unpack()); + internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); /// /// Constructor with a SourceStream able to handle FileInfo and Streams. diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index 43184b66..70ac2413 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -195,7 +195,7 @@ public class TarArchive : AbstractWritableArchive } } - public static TarArchive Create() => new TarArchive(); + public static TarArchive Create() => new(); protected override TarArchiveEntry CreateEntryInternal( string filePath, diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index 14e4a93e..87e9ac25 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -294,7 +294,7 @@ public class ZipArchive : AbstractWritableArchive bool closeStream ) => new ZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream); - public static ZipArchive Create() => new ZipArchive(); + public static ZipArchive Create() => new(); protected override IReader CreateReaderForSolidExtraction() { diff --git a/src/SharpCompress/Common/OptionsBase.cs b/src/SharpCompress/Common/OptionsBase.cs index 61a6cb55..8d1cbd1c 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 ArchiveEncoding(); + public ArchiveEncoding ArchiveEncoding { get; set; } = new(); } diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs index 529b85cc..07b58b40 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs @@ -12,7 +12,7 @@ internal class ArchiveCryptHeader : RarHeader public ArchiveCryptHeader(RarHeader header, RarCrcBinaryReader reader) : base(header, reader, HeaderType.Crypt) { } - public Rar5CryptoInfo CryptInfo = new Rar5CryptoInfo(); + public Rar5CryptoInfo CryptInfo = new(); protected override void ReadFinish(MarkingBinaryReader reader) { diff --git a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs index 982821c3..82db8b35 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs @@ -10,7 +10,7 @@ namespace SharpCompress.Common.Rar; internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader { private BlockTransformer _rijndael; - private readonly Queue _data = new Queue(); + private readonly Queue _data = new(); private long _readCount; public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey) diff --git a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index e3403ecd..8cae331a 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -9,7 +9,7 @@ internal sealed class RarCryptoWrapper : Stream { private readonly Stream _actualStream; private BlockTransformer _rijndael; - private readonly Queue _data = new Queue(); + private readonly Queue _data = new(); public RarCryptoWrapper(Stream actualStream, byte[] salt, ICryptKey key) { diff --git a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs index 5e42494a..ee6f6d08 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 List(); - internal List _packCrCs = new List(); - internal List _folders = new List(); + internal List _packSizes = new(); + internal List _packCrCs = new(); + internal List _folders = new(); internal List _numUnpackStreamsVector; - internal List _files = new List(); + internal List _files = new(); - internal List _packStreamStartPositions = new List(); - internal List _folderStartFileIndex = new List(); - internal List _fileIndexToFolderIndexMap = new List(); + internal List _packStreamStartPositions = new(); + internal List _folderStartFileIndex = new(); + internal List _fileIndexToFolderIndexMap = new(); internal IPasswordProvider PasswordProvider { get; } diff --git a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs index c1376ad9..3e506e0e 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 Stack(); + internal Stack _readerStack = new(); internal DataReader _currentReader; internal long _streamOrigin; internal long _streamEnding; internal byte[] _header; - private readonly Dictionary _cachedStreams = new Dictionary(); + private readonly Dictionary _cachedStreams = new(); 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 List(); + internal List _extractStatuses = new(); internal CExtractFolderInfo(int fileIndex, int folderIndex) { diff --git a/src/SharpCompress/Common/SevenZip/CFolder.cs b/src/SharpCompress/Common/SevenZip/CFolder.cs index 9d3516b1..8b0123da 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 List(); - internal List _bindPairs = new List(); - internal List _packStreams = new List(); + internal List _coders = new(); + internal List _bindPairs = new(); + internal List _packStreams = new(); internal int _firstPackStreamId; - internal List _unpackSizes = new List(); + internal List _unpackSizes = new(); 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 6dce5773..8494aad5 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 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 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 readonly ulong _id; diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 0e379e6b..a59b74f6 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -9,7 +9,7 @@ namespace SharpCompress.Common.Tar.Headers; internal sealed class TarHeader { - internal static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + internal static readonly DateTime EPOCH = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public TarHeader(ArchiveEncoding archiveEncoding) => ArchiveEncoding = archiveEncoding; diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs index d6c4e96d..b5d4b0fb 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 CRC32(); + private static readonly CRC32 CRC32 = new(); private readonly uint[] _keys = { 0x12345678, 0x23456789, 0x34567890 }; private readonly ArchiveEncoding _archiveEncoding; diff --git a/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs b/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs index e03a5096..a541a04d 100644 --- a/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs +++ b/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs @@ -87,7 +87,7 @@ internal class CBZip2InputStream : Stream private int bsBuff; private int bsLive; - private readonly CRC mCrc = new CRC(); + private readonly CRC mCrc = new(); 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 a975ffbd..bf01c2c3 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 CRC(); + private readonly CRC mCrc = new(); 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 06cf0005..1e51fc92 100644 --- a/src/SharpCompress/Compressors/Deflate/DeflateManager.cs +++ b/src/SharpCompress/Compressors/Deflate/DeflateManager.cs @@ -342,9 +342,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 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 + 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 // number of codes at each bit length for an optimal tree private readonly short[] bl_count = new short[InternalConstants.MAX_BITS + 1]; diff --git a/src/SharpCompress/Compressors/Deflate/DeflateStream.cs b/src/SharpCompress/Compressors/Deflate/DeflateStream.cs index 05003d7f..13d73570 100644 --- a/src/SharpCompress/Compressors/Deflate/DeflateStream.cs +++ b/src/SharpCompress/Compressors/Deflate/DeflateStream.cs @@ -366,9 +366,9 @@ public class DeflateStream : Stream #endregion public MemoryStream InputBuffer => - new MemoryStream( + new( _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 c547df14..6bebbbc3 100644 --- a/src/SharpCompress/Compressors/Deflate/GZipStream.cs +++ b/src/SharpCompress/Compressors/Deflate/GZipStream.cs @@ -35,15 +35,15 @@ namespace SharpCompress.Compressors.Deflate; public class GZipStream : Stream { - internal static readonly DateTime UNIX_EPOCH = new DateTime( - 1970, - 1, - 1, - 0, - 0, - 0, - DateTimeKind.Utc - ); + internal static readonly DateTime UNIX_EPOCH = new( + 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 37227b3d..d768548b 100644 --- a/src/SharpCompress/Compressors/Deflate/Inflate.cs +++ b/src/SharpCompress/Compressors/Deflate/Inflate.cs @@ -105,11 +105,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 InflateCodes(); // if CODES, current state + internal InflateCodes codes = new(); // 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 InfTree(); + internal InfTree inftree = new(); 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/Deflate64/DeflateInput.cs b/src/SharpCompress/Compressors/Deflate64/DeflateInput.cs index 6a12df3b..304a2a78 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 InputState(Count, StartIndex); + internal InputState DumpState() => new(Count, StartIndex); internal void RestoreState(InputState state) { diff --git a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs index 051b613e..e37802bb 100644 --- a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs +++ b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs @@ -42,11 +42,9 @@ internal sealed class HuffmanTree private readonly int _tableMask; // huffman tree for static block - public static HuffmanTree StaticLiteralLengthTree { get; } = - new HuffmanTree(GetStaticLiteralTreeLength()); + public static HuffmanTree StaticLiteralLengthTree { get; } = new(GetStaticLiteralTreeLength()); - public static HuffmanTree StaticDistanceTree { get; } = - new HuffmanTree(GetStaticDistanceTreeLength()); + public static HuffmanTree StaticDistanceTree { get; } = new(GetStaticDistanceTreeLength()); public HuffmanTree(byte[] codeLengths) { diff --git a/src/SharpCompress/Compressors/LZMA/Log.cs b/src/SharpCompress/Compressors/LZMA/Log.cs index e954e259..1431966c 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 Stack(); + private static readonly Stack INDENT = new(); 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 b460e1be..1b2fdc81 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 BitDecoder(); - private BitDecoder _choice2 = new BitDecoder(); + private BitDecoder _choice = new(); + private BitDecoder _choice2 = new(); 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 BitTreeDecoder(Base.K_NUM_HIGH_LEN_BITS); + private BitTreeDecoder _highCoder = new(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 BitTreeDecoder(Base.K_NUM_ALIGN_BITS); + private BitTreeDecoder _posAlignDecoder = new(Base.K_NUM_ALIGN_BITS); - private readonly LenDecoder _lenDecoder = new LenDecoder(); - private readonly LenDecoder _repLenDecoder = new LenDecoder(); + private readonly LenDecoder _lenDecoder = new(); + private readonly LenDecoder _repLenDecoder = new(); - private readonly LiteralDecoder _literalDecoder = new LiteralDecoder(); + private readonly LiteralDecoder _literalDecoder = new(); private int _dictionarySize; private uint _posStateMask; - private Base.State _state = new Base.State(); + private Base.State _state = new(); private uint _rep0, _rep1, _rep2, diff --git a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs index 7a231289..509e54c8 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 Base.State(); + private Base.State _state = new(); 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 BitEncoder(); - private BitEncoder _choice2 = new BitEncoder(); + private BitEncoder _choice = new(); + private BitEncoder _choice2 = new(); 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 BitTreeEncoder(Base.K_NUM_HIGH_LEN_BITS); + private BitTreeEncoder _highCoder = new(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 RangeCoder.Encoder(); + private readonly RangeCoder.Encoder _rangeEncoder = new(); 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 BitTreeEncoder(Base.K_NUM_ALIGN_BITS); + private BitTreeEncoder _posAlignEncoder = new(Base.K_NUM_ALIGN_BITS); - private readonly LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); - private readonly LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); + private readonly LenPriceTableEncoder _lenEncoder = new(); + private readonly LenPriceTableEncoder _repMatchLenEncoder = new(); - private readonly LiteralEncoder _literalEncoder = new LiteralEncoder(); + private readonly LiteralEncoder _literalEncoder = new(); private readonly uint[] _matchDistances = new uint[(Base.K_MATCH_MAX_LEN * 2) + 2]; diff --git a/src/SharpCompress/Compressors/LZMA/LzmaStream.cs b/src/SharpCompress/Compressors/LZMA/LzmaStream.cs index 8e7d4adc..043cbbad 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 OutWindow(); - private readonly RangeCoder.Decoder _rangeDecoder = new RangeCoder.Decoder(); + private readonly OutWindow _outWindow = new(); + private readonly RangeCoder.Decoder _rangeDecoder = new(); private Decoder _decoder; private long _position; diff --git a/src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs b/src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs index 3b2d22ba..d4e91921 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 SubAllocator(); + public SubAllocator SubAlloc { get; } = new(); 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 State(null); + private readonly State _tempState1 = new(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 State(null); + private readonly State _tempState2 = new(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 State(null); + private readonly State _tempState3 = new(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 State(null); + private readonly State _tempState4 = new(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 StateRef(); + private readonly StateRef _tempStateRef1 = new(); //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 StateRef(); + private readonly StateRef _tempStateRef2 = new(); //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 PpmContext(null); + private readonly PpmContext _tempPpmContext1 = new(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 PpmContext(null); + private readonly PpmContext _tempPpmContext2 = new(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 PpmContext(null); + private readonly PpmContext _tempPpmContext3 = new(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 PpmContext(null); + private readonly PpmContext _tempPpmContext4 = new(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 ab00615d..e4f98c71 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 State(null); + private readonly State _tempState1 = new(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 State(null); + private readonly State _tempState2 = new(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 State(null); + private readonly State _tempState3 = new(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 State(null); + private readonly State _tempState4 = new(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 State(null); + private readonly State _tempState5 = new(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/MemoryNode.cs b/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs index 5e978c5c..76d53951 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 MemoryNode(0, null); + public static readonly MemoryNode ZERO = new(0, null); public const int SIZE = 12; /// @@ -64,13 +64,13 @@ internal struct MemoryNode public MemoryNode Next { get => - new MemoryNode( + new( _memory[_address + 4] - | (((uint)_memory[_address + 5]) << 8) - | (((uint)_memory[_address + 6]) << 16) - | (((uint)_memory[_address + 7]) << 24), + | (((uint)_memory[_address + 5]) << 8) + | (((uint)_memory[_address + 6]) << 16) + | (((uint)_memory[_address + 7]) << 24), _memory - ); + ); set { _memory[_address + 4] = (byte)value._address; @@ -150,7 +150,7 @@ internal struct MemoryNode /// /// public static implicit operator MemoryNode(Pointer pointer) => - new MemoryNode(pointer._address, pointer._memory); + new(pointer._address, pointer._memory); /// /// Allow pointer-like addition on a memory node. diff --git a/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs b/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs index 72c557ba..da7cdc2e 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 Pointer(0, null); + public static readonly Pointer ZERO = new(0, null); public const int SIZE = 1; /// @@ -69,7 +69,7 @@ internal struct Pointer /// /// public static implicit operator Pointer(MemoryNode memoryNode) => - new Pointer(memoryNode._address, memoryNode._memory); + new(memoryNode._address, memoryNode._memory); /// /// Allow a to be implicitly converted to a . @@ -77,7 +77,7 @@ internal struct Pointer /// /// public static implicit operator Pointer(Model.PpmContext context) => - new Pointer(context._address, context._memory); + new(context._address, context._memory); /// /// Allow a to be implicitly converted to a . @@ -85,7 +85,7 @@ internal struct Pointer /// /// public static implicit operator Pointer(PpmState state) => - new Pointer(state._address, state._memory); + new(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 a37d278d..e27b6cd1 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 PpmContext(0, null); + public static readonly PpmContext ZERO = new(0, null); public const int SIZE = 12; /// @@ -70,13 +70,13 @@ internal partial class Model public PpmState Statistics { get => - new PpmState( + new( _memory[_address + 4] - | (((uint)_memory[_address + 5]) << 8) - | (((uint)_memory[_address + 6]) << 16) - | (((uint)_memory[_address + 7]) << 24), + | (((uint)_memory[_address + 5]) << 8) + | (((uint)_memory[_address + 6]) << 16) + | (((uint)_memory[_address + 7]) << 24), _memory - ); + ); set { _memory[_address + 4] = (byte)value._address; @@ -92,13 +92,13 @@ internal partial class Model public PpmContext Suffix { get => - new PpmContext( + new( _memory[_address + 8] - | (((uint)_memory[_address + 9]) << 8) - | (((uint)_memory[_address + 10]) << 16) - | (((uint)_memory[_address + 11]) << 24), + | (((uint)_memory[_address + 9]) << 8) + | (((uint)_memory[_address + 10]) << 16) + | (((uint)_memory[_address + 11]) << 24), _memory - ); + ); set { _memory[_address + 8] = (byte)value._address; @@ -133,7 +133,7 @@ internal partial class Model /// /// /// - public PpmState FirstState => new PpmState(_address + 2, _memory); + public PpmState FirstState => new(_address + 2, _memory); /// /// Gets or sets the symbol of the first PPM state. This is provided for convenience. The same @@ -164,13 +164,13 @@ internal partial class Model public PpmContext FirstStateSuccessor { get => - new PpmContext( + new( _memory[_address + 4] - | (((uint)_memory[_address + 5]) << 8) - | (((uint)_memory[_address + 6]) << 16) - | (((uint)_memory[_address + 7]) << 24), + | (((uint)_memory[_address + 5]) << 8) + | (((uint)_memory[_address + 6]) << 16) + | (((uint)_memory[_address + 7]) << 24), _memory - ); + ); set { _memory[_address + 4] = (byte)value._address; @@ -186,7 +186,7 @@ internal partial class Model /// /// public static implicit operator PpmContext(Pointer pointer) => - new PpmContext(pointer._address, pointer._memory); + new(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 757afd00..d1187ee9 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 PpmState(0, null); + public static readonly PpmState ZERO = new(0, null); public const int SIZE = 6; /// @@ -55,13 +55,13 @@ internal struct PpmState public Model.PpmContext Successor { get => - new Model.PpmContext( + new( _memory[_address + 2] - | (((uint)_memory[_address + 3]) << 8) - | (((uint)_memory[_address + 4]) << 16) - | (((uint)_memory[_address + 5]) << 24), + | (((uint)_memory[_address + 3]) << 8) + | (((uint)_memory[_address + 4]) << 16) + | (((uint)_memory[_address + 5]) << 24), _memory - ); + ); set { _memory[_address + 2] = (byte)value._address; @@ -77,7 +77,7 @@ internal struct PpmState /// /// /// - public PpmState this[int offset] => new PpmState((uint)(_address + (offset * SIZE)), _memory); + public PpmState this[int offset] => new((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 PpmState(pointer._address, pointer._memory); + new(pointer._address, pointer._memory); /// /// Allow pointer-like addition on a PPM state. diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs index 2ca62d6b..e6d4153d 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 ModelPpm(); + private readonly ModelPpm ppm = new(); - private readonly RarVM rarVM = new RarVM(); + private readonly RarVM rarVM = new(); // Filters code, one entry per filter - private readonly List filters = new List(); + private readonly List filters = new(); // Filters stack, several entrances of same filter are possible - private readonly List prgStack = new List(); + private readonly List prgStack = new(); // 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 List(); + private readonly List oldFilterLengths = new(); private int lastFilter; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.cs index 15b980da..3a5d008d 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 LitDecode(); + private readonly LitDecode LD = new(); - private readonly DistDecode DD = new DistDecode(); + private readonly DistDecode DD = new(); - private readonly LowDistDecode LDD = new LowDistDecode(); + private readonly LowDistDecode LDD = new(); - private readonly RepDecode RD = new RepDecode(); + private readonly RepDecode RD = new(); - private readonly BitDecode BD = new BitDecode(); + private readonly BitDecode BD = new(); private static readonly int[] LDecode = { diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs index 4f77fc07..3bba4c94 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/unpack_hpp.cs @@ -269,7 +269,7 @@ internal partial class Unpack private byte[] FilterDstMemory = Array.Empty(); // Filters code, one entry per filter. - private readonly List Filters = new List(); + private readonly List Filters = new(); private readonly uint[] OldDist = new uint[4]; private uint OldDistPtr; @@ -297,7 +297,7 @@ internal partial class Unpack private byte[] Window; - private readonly FragmentedWindow FragWindow = new FragmentedWindow(); + private readonly FragmentedWindow FragWindow = new(); private bool Fragmented; private int64 DestUnpSize; @@ -393,18 +393,18 @@ 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 BitInput(true); + private readonly BitInput VMCodeInp = new(true); // Filters code, one entry per filter. - private readonly List Filters30 = new List(); + private readonly List Filters30 = new(); // Filters stack, several entrances of same filter are possible. - private readonly List PrgStack = new List(); + private readonly List PrgStack = new(); // 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 List(); + private readonly List OldFilterLengths = new(); /*#if RarV2017_RAR_SMP // More than 8 threads are unlikely to provide a noticeable gain diff --git a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs index 48b25c5c..185b24d4 100644 --- a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs +++ b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs @@ -1131,13 +1131,13 @@ internal sealed class RarVM : BitInput { VMStandardFilterSignature[] stdList = { - 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) + 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) }; var CodeCRC = RarCRC.CheckCrc(0xffffffff, code, 0, code.Length) ^ 0xffffffff; for (var i = 0; i < stdList.Length; i++) diff --git a/src/SharpCompress/Compressors/Rar/VM/VMPreparedProgram.cs b/src/SharpCompress/Compressors/Rar/VM/VMPreparedProgram.cs index c0006e09..f1f9e0aa 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 List(); - internal List AltCommands = new List(); + internal List Commands = new(); + internal List AltCommands = new(); public int CommandCount { get; set; } - internal List GlobalData = new List(); - internal List StaticData = new List(); + internal List GlobalData = new(); + internal List StaticData = new(); // static data contained in DB operators internal int[] InitR = new int[7]; diff --git a/src/SharpCompress/Compressors/Xz/XZBlock.cs b/src/SharpCompress/Compressors/Xz/XZBlock.cs index ea907609..ddd7eaf3 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 Stack(); + public Stack Filters { get; private set; } = new(); 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 631f27b2..ddfd7c99 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 List(); + public List Records { get; } = new(); private readonly bool _indexMarkerAlreadyVerified; diff --git a/src/SharpCompress/Factories/Factory.cs b/src/SharpCompress/Factories/Factory.cs index 7ec68508..baef3b85 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 HashSet(); + private static readonly HashSet _factories = new(); /// /// Gets the collection of registered . diff --git a/src/SharpCompress/IO/BufferedSubStream.cs b/src/SharpCompress/IO/BufferedSubStream.cs index 0b98f9d0..0658a7b6 100644 --- a/src/SharpCompress/IO/BufferedSubStream.cs +++ b/src/SharpCompress/IO/BufferedSubStream.cs @@ -3,22 +3,13 @@ using System.IO; namespace SharpCompress.IO; -internal class BufferedSubStream : NonDisposingStream +internal class BufferedSubStream(Stream stream, long origin, long bytesToRead) : NonDisposingStream(stream, throwOnDispose: false) { - private long position; - private int cacheOffset; - private int cacheLength; - private readonly byte[] cache; + private int _cacheOffset; + private int _cacheLength; + private readonly byte[] _cache = new byte[32 << 10]; - 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; } + private long BytesLeftToRead { get; set; } = bytesToRead; public override bool CanRead => true; @@ -45,22 +36,22 @@ internal class BufferedSubStream : NonDisposingStream if (count > 0) { - if (cacheLength == 0) + if (_cacheLength == 0) { - cacheOffset = 0; - Stream.Position = position; - cacheLength = Stream.Read(cache, 0, cache.Length); - position += cacheLength; + _cacheOffset = 0; + Stream.Position = origin; + _cacheLength = Stream.Read(_cache, 0, _cache.Length); + origin += _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 45708338..1802556c 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 _search_position; + private int _searchPosition; 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; - _search_position = 0; + _searchPosition = 0; _done = false; } @@ -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 compressed_size = br.ReadUInt32(); - var uncompressed_size = br.ReadUInt32(); - var uncompressed_64bit = br.ReadInt64(); + var compressedSize = br.ReadUInt32(); + var uncompressedSize = br.ReadUInt32(); + var uncompressed64Bit = br.ReadInt64(); - stream.Position -= DataDescriptorSize; + stream.Position -= _dataDescriptorSize; - var test_64bit = ((long)uncompressed_size << 32) | compressed_size; + var test64Bit = ((long)uncompressedSize << 32) | compressedSize; - if (test_64bit == size && test_64bit == uncompressed_64bit) + if (test64Bit == size && test64Bit == uncompressed64Bit) { return true; } - if (compressed_size == size && compressed_size == uncompressed_size) + if (compressedSize == size && compressedSize == uncompressedSize) { return true; } @@ -92,20 +92,20 @@ public class DataDescriptorStream : Stream for (var i = 0; i < read; i++) { - if (buffer[offset + i] == DataDescriptorMarker[_search_position]) + if (buffer[offset + i] == _dataDescriptorMarker[_searchPosition]) { - _search_position++; + _searchPosition++; - if (_search_position == 4) + if (_searchPosition == 4) { - _search_position = 0; + _searchPosition = 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 { - _search_position = 0; + _searchPosition = 0; } } - if (_search_position > 0) + if (_searchPosition > 0) { - read -= _search_position; - _stream.Position -= _search_position; - _search_position = 0; + read -= _searchPosition; + _stream.Position -= _searchPosition; + _searchPosition = 0; } return read; diff --git a/src/SharpCompress/IO/ListeningStream.cs b/src/SharpCompress/IO/ListeningStream.cs index a1bf715b..0acf1056 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 55c5b575..cd39335e 100644 --- a/src/SharpCompress/IO/ReadOnlySubStream.cs +++ b/src/SharpCompress/IO/ReadOnlySubStream.cs @@ -72,8 +72,8 @@ internal class ReadOnlySubStream : NonDisposingStream #if !NETFRAMEWORK && !NETSTANDARD2_0 public override int Read(Span buffer) { - var slice_len = BytesLeftToRead < buffer.Length ? BytesLeftToRead : buffer.Length; - var read = Stream.Read(buffer.Slice(0, (int)slice_len)); + var sliceLen = BytesLeftToRead < buffer.Length ? BytesLeftToRead : buffer.Length; + var read = Stream.Read(buffer.Slice(0, (int)sliceLen)); if (read > 0) { BytesLeftToRead -= read; diff --git a/src/SharpCompress/IO/RewindableStream.cs b/src/SharpCompress/IO/RewindableStream.cs index ff7fe3d0..c7febd1d 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 MemoryStream(); - private bool isRewound; - private bool isDisposed; + private readonly Stream _stream; + private MemoryStream _bufferStream = new(); + 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 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/Lazy.cs b/src/SharpCompress/Lazy.cs deleted file mode 100644 index 7a6abd55..00000000 --- a/src/SharpCompress/Lazy.cs +++ /dev/null @@ -1,27 +0,0 @@ -#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 8f5ee834..cc9cb3fd 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 List(); + private readonly List backing = new(); private readonly IEnumerator source; private bool fullyLoaded; diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 285f0f84..4520b134 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -191,7 +191,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// Retains a reference to the entry stream, so we can check whether it completed later. /// protected EntryStream CreateEntryStream(Stream decompressed) => - new EntryStream(this, decompressed); + new(this, decompressed); protected virtual EntryStream GetEntryStream() => CreateEntryStream(Entry.Parts.First().GetCompressedStream()); diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index ac346262..d5306ac4 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -14,10 +14,8 @@ namespace SharpCompress.Readers.Rar; public abstract class RarReader : AbstractReader { private RarVolume? volume; - internal Lazy UnpackV2017 { get; } = - new Lazy(() => new Compressors.Rar.UnpackV2017.Unpack()); - internal Lazy UnpackV1 { get; } = - new Lazy(() => new Compressors.Rar.UnpackV1.Unpack()); + internal Lazy UnpackV2017 { get; } = new(() => new Compressors.Rar.UnpackV2017.Unpack()); + internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); internal RarReader(ReaderOptions options) : base(options, ArchiveType.Rar) { } diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 9471c3e1..f7e0b17d 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -9,8 +9,7 @@ namespace SharpCompress; [CLSCompliant(false)] public static class Utility { - public static ReadOnlyCollection ToReadOnly(this ICollection items) => - new ReadOnlyCollection(items); + public static ReadOnlyCollection ToReadOnly(this ICollection items) => new(items); /// /// Performs an unsigned bitwise right shift with the specified number diff --git a/src/SharpCompress/Writers/WriterOptions.cs b/src/SharpCompress/Writers/WriterOptions.cs index 9d323c2b..e71f86f6 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 WriterOptions(compressionType); + new(compressionType); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index e1bb53e9..f446102a 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 List(); + private readonly List entries = new(); private readonly string zipComment; private long streamPosition; private PpmdProperties? ppmdProps; @@ -324,7 +324,7 @@ public class ZipWriter : AbstractWriter internal class ZipWritingStream : Stream { - private readonly CRC32 crc = new CRC32(); + private readonly CRC32 crc = new(); private readonly ZipCentralDirectoryEntry entry; private readonly Stream originalStream; private readonly Stream writeStream; From 95975a4c33662b602c8bc0a291a0db2353611c65 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 09:07:21 +0000 Subject: [PATCH 0047/1333] even more clean up --- src/SharpCompress/Archives/Rar/RarArchive.cs | 3 +- .../Common/PasswordProtectedException.cs | 12 ----- src/SharpCompress/Common/Rar/CryptKey3.cs | 5 +- .../Common/Rar/Headers/ArchiveCryptHeader.cs | 4 +- .../Common/Rar/Rar5CryptoInfo.cs | 4 +- .../Common/Rar/RarCryptoBinaryReader.cs | 15 ++---- .../Common/Rar/RarCryptoWrapper.cs | 6 +-- .../Common/Zip/StreamingZipHeaderFactory.cs | 5 +- src/SharpCompress/Common/Zip/ZipEntry.cs | 51 ++++--------------- .../Compressors/Deflate/DeflateManager.cs | 21 +++----- .../Compressors/Deflate/DeflateStream.cs | 6 +-- .../Compressors/Deflate/GZipStream.cs | 10 +--- .../Compressors/Filters/BranchExecFilter.cs | 5 +- .../Compressors/PPMd/I1/MemoryNode.cs | 8 +-- .../Compressors/PPMd/I1/Pointer.cs | 3 +- .../Compressors/PPMd/I1/PpmContext.cs | 24 ++++----- .../Compressors/PPMd/I1/PpmState.cs | 8 +-- .../Compressors/Shrink/HwUnshrink.cs | 6 +-- src/SharpCompress/Crypto/BlockTransformer.cs | 17 +------ src/SharpCompress/Crypto/Crc32Stream.cs | 42 ++++++--------- src/SharpCompress/Crypto/CryptoException.cs | 14 ----- .../Crypto/DataLengthException.cs | 24 --------- src/SharpCompress/Crypto/IBlockCipher.cs | 33 ------------ src/SharpCompress/Crypto/ICipherParameters.cs | 3 -- src/SharpCompress/Crypto/KeyParameter.cs | 39 -------------- src/SharpCompress/IO/BufferedSubStream.cs | 3 +- src/SharpCompress/Readers/AbstractReader.cs | 3 +- src/SharpCompress/Readers/Rar/RarReader.cs | 3 +- src/SharpCompress/Readers/Tar/TarReader.cs | 34 +++---------- src/SharpCompress/Writers/Zip/ZipWriter.cs | 36 ++++--------- 30 files changed, 95 insertions(+), 352 deletions(-) delete mode 100644 src/SharpCompress/Common/PasswordProtectedException.cs delete mode 100644 src/SharpCompress/Crypto/CryptoException.cs delete mode 100644 src/SharpCompress/Crypto/DataLengthException.cs delete mode 100644 src/SharpCompress/Crypto/IBlockCipher.cs delete mode 100644 src/SharpCompress/Crypto/ICipherParameters.cs delete mode 100644 src/SharpCompress/Crypto/KeyParameter.cs diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 56177e02..b6472407 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -14,7 +14,8 @@ namespace SharpCompress.Archives.Rar; public class RarArchive : AbstractArchive { - internal Lazy UnpackV2017 { get; } = new(() => new Compressors.Rar.UnpackV2017.Unpack()); + internal Lazy UnpackV2017 { get; } = + new(() => new Compressors.Rar.UnpackV2017.Unpack()); internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); /// diff --git a/src/SharpCompress/Common/PasswordProtectedException.cs b/src/SharpCompress/Common/PasswordProtectedException.cs deleted file mode 100644 index 9ebe3d65..00000000 --- a/src/SharpCompress/Common/PasswordProtectedException.cs +++ /dev/null @@ -1,12 +0,0 @@ -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 index 254c692f..93e451b1 100644 --- a/src/SharpCompress/Common/Rar/CryptKey3.cs +++ b/src/SharpCompress/Common/Rar/CryptKey3.cs @@ -12,10 +12,7 @@ internal class CryptKey3 : ICryptKey private string _password; - public CryptKey3(string password) - { - _password = password ?? ""; - } + public CryptKey3(string password) => _password = password ?? ""; public ICryptoTransform Transformer(byte[] salt) { diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs index 07b58b40..5aa29d49 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs @@ -14,8 +14,6 @@ internal class ArchiveCryptHeader : RarHeader public Rar5CryptoInfo CryptInfo = new(); - protected override void ReadFinish(MarkingBinaryReader reader) - { + protected override void ReadFinish(MarkingBinaryReader reader) => CryptInfo = new Rar5CryptoInfo(reader, false); - } } diff --git a/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs b/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs index 28053a3d..7b8edff9 100644 --- a/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs +++ b/src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs @@ -42,10 +42,8 @@ internal class Rar5CryptoInfo } } - public void ReadInitV(MarkingBinaryReader reader) - { + public void ReadInitV(MarkingBinaryReader reader) => InitV = reader.ReadBytes(EncryptionConstV5.SIZE_INITV); - } public bool UsePswCheck = false; diff --git a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs index 82db8b35..6e44286b 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoBinaryReader.cs @@ -22,10 +22,7 @@ internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader } public RarCryptoBinaryReader(Stream stream, ICryptKey cryptKey, byte[] salt) - : base(stream) - { - _rijndael = new BlockTransformer(cryptKey.Transformer(salt)); - } + : base(stream) => _rijndael = new BlockTransformer(cryptKey.Transformer(salt)); // track read count ourselves rather than using the underlying stream since we buffer public override long CurrentReadByteCount @@ -39,15 +36,9 @@ internal sealed class RarCryptoBinaryReader : RarCrcBinaryReader public override void Mark() => _readCount = 0; - public override byte ReadByte() - { - return ReadAndDecryptBytes(1)[0]; - } + public override byte ReadByte() => ReadAndDecryptBytes(1)[0]; - public override byte[] ReadBytes(int count) - { - return ReadAndDecryptBytes(count); - } + public override byte[] ReadBytes(int count) => ReadAndDecryptBytes(count); private byte[] ReadAndDecryptBytes(int count) { diff --git a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index 8cae331a..a9798609 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -23,10 +23,8 @@ internal sealed class RarCryptoWrapper : Stream public override void SetLength(long value) => throw new NotSupportedException(); - public override int Read(byte[] buffer, int offset, int count) - { - return ReadAndDecrypt(buffer, offset, count); - } + public override int Read(byte[] buffer, int offset, int count) => + ReadAndDecrypt(buffer, offset, count); public int ReadAndDecrypt(byte[] buffer, int offset, int count) { diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 34dd8798..68817d27 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -15,10 +15,7 @@ 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) { diff --git a/src/SharpCompress/Common/Zip/ZipEntry.cs b/src/SharpCompress/Common/Zip/ZipEntry.cs index 61e1b6af..80e33360 100644 --- a/src/SharpCompress/Common/Zip/ZipEntry.cs +++ b/src/SharpCompress/Common/Zip/ZipEntry.cs @@ -22,47 +22,18 @@ public class ZipEntry : Entry } } - public override CompressionType CompressionType - { - get + public override CompressionType CompressionType => + _filePart.Header.CompressionMethod switch { - 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; - } - case ZipCompressionMethod.Shrink: - { - return CompressionType.Shrink; - } - default: - { - return CompressionType.Unknown; - } - } - } - } + 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 + }; public override long Crc => _filePart.Header.Crc; diff --git a/src/SharpCompress/Compressors/Deflate/DeflateManager.cs b/src/SharpCompress/Compressors/Deflate/DeflateManager.cs index 1e51fc92..cccd0237 100644 --- a/src/SharpCompress/Compressors/Deflate/DeflateManager.cs +++ b/src/SharpCompress/Compressors/Deflate/DeflateManager.cs @@ -1787,21 +1787,14 @@ internal sealed partial class DeflateManager return status == BUSY_STATE ? ZlibConstants.Z_DATA_ERROR : ZlibConstants.Z_OK; } - private void SetDeflater() - { - switch (config.Flavor) + private void SetDeflater() => + DeflateFunction = config.Flavor switch { - case DeflateFlavor.Store: - DeflateFunction = DeflateNone; - break; - case DeflateFlavor.Fast: - DeflateFunction = DeflateFast; - break; - case DeflateFlavor.Slow: - DeflateFunction = DeflateSlow; - break; - } - } + DeflateFlavor.Store => DeflateNone, + DeflateFlavor.Fast => DeflateFast, + DeflateFlavor.Slow => DeflateSlow, + _ => DeflateFunction + }; internal int SetParams(CompressionLevel level, CompressionStrategy strategy) { diff --git a/src/SharpCompress/Compressors/Deflate/DeflateStream.cs b/src/SharpCompress/Compressors/Deflate/DeflateStream.cs index 13d73570..5566e817 100644 --- a/src/SharpCompress/Compressors/Deflate/DeflateStream.cs +++ b/src/SharpCompress/Compressors/Deflate/DeflateStream.cs @@ -366,9 +366,5 @@ public class DeflateStream : Stream #endregion public MemoryStream InputBuffer => - new( - _baseStream._z.InputBuffer, - _baseStream._z.NextIn, - _baseStream._z.AvailableBytesIn - ); + new(_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 6bebbbc3..0f7beca8 100644 --- a/src/SharpCompress/Compressors/Deflate/GZipStream.cs +++ b/src/SharpCompress/Compressors/Deflate/GZipStream.cs @@ -35,15 +35,7 @@ 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(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private string? _comment; private string? _fileName; diff --git a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs index f70d6c11..d198cf8f 100644 --- a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs +++ b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs @@ -24,10 +24,7 @@ public sealed class BranchExecFilter } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool X86TestByte(byte b) - { - return b == 0x00 || b == 0xFF; - } + private static bool X86TestByte(byte b) => 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). diff --git a/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs b/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs index 76d53951..c8b411d8 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/MemoryNode.cs @@ -66,11 +66,11 @@ internal struct MemoryNode get => new( _memory[_address + 4] - | (((uint)_memory[_address + 5]) << 8) - | (((uint)_memory[_address + 6]) << 16) - | (((uint)_memory[_address + 7]) << 24), + | (((uint)_memory[_address + 5]) << 8) + | (((uint)_memory[_address + 6]) << 16) + | (((uint)_memory[_address + 7]) << 24), _memory - ); + ); set { _memory[_address + 4] = (byte)value._address; diff --git a/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs b/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs index da7cdc2e..d1a89545 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/Pointer.cs @@ -84,8 +84,7 @@ internal struct Pointer /// /// /// - public static implicit operator Pointer(PpmState state) => - new(state._address, state._memory); + public static implicit operator Pointer(PpmState state) => new(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 e27b6cd1..701039c2 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/PpmContext.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/PpmContext.cs @@ -72,11 +72,11 @@ internal partial class Model get => new( _memory[_address + 4] - | (((uint)_memory[_address + 5]) << 8) - | (((uint)_memory[_address + 6]) << 16) - | (((uint)_memory[_address + 7]) << 24), + | (((uint)_memory[_address + 5]) << 8) + | (((uint)_memory[_address + 6]) << 16) + | (((uint)_memory[_address + 7]) << 24), _memory - ); + ); set { _memory[_address + 4] = (byte)value._address; @@ -94,11 +94,11 @@ internal partial class Model get => new( _memory[_address + 8] - | (((uint)_memory[_address + 9]) << 8) - | (((uint)_memory[_address + 10]) << 16) - | (((uint)_memory[_address + 11]) << 24), + | (((uint)_memory[_address + 9]) << 8) + | (((uint)_memory[_address + 10]) << 16) + | (((uint)_memory[_address + 11]) << 24), _memory - ); + ); set { _memory[_address + 8] = (byte)value._address; @@ -166,11 +166,11 @@ internal partial class Model get => new( _memory[_address + 4] - | (((uint)_memory[_address + 5]) << 8) - | (((uint)_memory[_address + 6]) << 16) - | (((uint)_memory[_address + 7]) << 24), + | (((uint)_memory[_address + 5]) << 8) + | (((uint)_memory[_address + 6]) << 16) + | (((uint)_memory[_address + 7]) << 24), _memory - ); + ); set { _memory[_address + 4] = (byte)value._address; diff --git a/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs b/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs index d1187ee9..02e79a34 100644 --- a/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs +++ b/src/SharpCompress/Compressors/PPMd/I1/PpmState.cs @@ -57,11 +57,11 @@ internal struct PpmState get => new( _memory[_address + 2] - | (((uint)_memory[_address + 3]) << 8) - | (((uint)_memory[_address + 4]) << 16) - | (((uint)_memory[_address + 5]) << 24), + | (((uint)_memory[_address + 3]) << 8) + | (((uint)_memory[_address + 4]) << 16) + | (((uint)_memory[_address + 5]) << 24), _memory - ); + ); set { _memory[_address + 2] = (byte)value._address; diff --git a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs index 3eb10e6b..6ad5ab7c 100644 --- a/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs +++ b/src/SharpCompress/Compressors/Shrink/HwUnshrink.cs @@ -414,11 +414,9 @@ namespace SharpCompress.Compressors.Shrink q.nextIdx = 0; } - private static ushort CodeQueueNext(ref CodeQueue q) - { + private static ushort CodeQueueNext(ref CodeQueue q) => //assert(q.nextIdx < q.codes.Length); - return q.codes[q.nextIdx]; - } + q.codes[q.nextIdx]; private static ushort CodeQueueRemoveNext(ref CodeQueue q) { diff --git a/src/SharpCompress/Crypto/BlockTransformer.cs b/src/SharpCompress/Crypto/BlockTransformer.cs index bcb937d0..ed9ead44 100644 --- a/src/SharpCompress/Crypto/BlockTransformer.cs +++ b/src/SharpCompress/Crypto/BlockTransformer.cs @@ -5,25 +5,12 @@ using System.Security.Cryptography; namespace SharpCompress.Crypto; -internal class BlockTransformer : IDisposable +internal class BlockTransformer(ICryptoTransform transformer) : IDisposable { - private ICryptoTransform _transform; - - public BlockTransformer(ICryptoTransform transformer) - { - _transform = transformer; - } - public byte[] ProcessBlock(ReadOnlySpan cipherText) { var decryptedBytes = new byte[cipherText.Length]; - var bytes = _transform.TransformBlock( - cipherText.ToArray(), - 0, - cipherText.Length, - decryptedBytes, - 0 - ); + transformer.TransformBlock(cipherText.ToArray(), 0, cipherText.Length, decryptedBytes, 0); return decryptedBytes; } diff --git a/src/SharpCompress/Crypto/Crc32Stream.cs b/src/SharpCompress/Crypto/Crc32Stream.cs index 7f0af6ca..5f5ccd87 100644 --- a/src/SharpCompress/Crypto/Crc32Stream.cs +++ b/src/SharpCompress/Crypto/Crc32Stream.cs @@ -6,27 +6,17 @@ using System.IO; namespace SharpCompress.Crypto; [CLSCompliant(false)] -public sealed class Crc32Stream : Stream +public sealed class Crc32Stream(Stream stream, uint polynomial, uint seed) : Stream { - public const uint DefaultPolynomial = 0xedb88320u; - public const uint DefaultSeed = 0xffffffffu; + public const uint DEFAULT_POLYNOMIAL = 0xedb88320u; + public const uint DEFAULT_SEED = 0xffffffffu; - private static uint[] defaultTable; + private static uint[] _defaultTable; - private readonly uint[] table; - private uint hash; - - private readonly Stream stream; + private readonly uint[] _table = InitializeTable(polynomial); public Crc32Stream(Stream stream) - : this(stream, DefaultPolynomial, DefaultSeed) { } - - public Crc32Stream(Stream stream, uint polynomial, uint seed) - { - this.stream = stream; - table = InitializeTable(polynomial); - hash = seed; - } + : this(stream, DEFAULT_POLYNOMIAL, DEFAULT_SEED) { } public Stream WrappedStream => stream; @@ -45,20 +35,20 @@ public sealed class Crc32Stream : Stream { stream.Write(buffer); - hash = CalculateCrc(table, hash, buffer); + seed = CalculateCrc(_table, seed, buffer); } #endif public override void Write(byte[] buffer, int offset, int count) { stream.Write(buffer, offset, count); - hash = CalculateCrc(table, hash, buffer.AsSpan(offset, count)); + seed = CalculateCrc(_table, seed, buffer.AsSpan(offset, count)); } public override void WriteByte(byte value) { stream.WriteByte(value); - hash = CalculateCrc(table, hash, value); + seed = CalculateCrc(_table, seed, value); } public override bool CanRead => stream.CanRead; @@ -71,21 +61,21 @@ public sealed class Crc32Stream : Stream set => throw new NotSupportedException(); } - public uint Crc => ~hash; + public uint Crc => ~seed; - public static uint Compute(byte[] buffer) => Compute(DefaultSeed, buffer); + public static uint Compute(byte[] buffer) => Compute(DEFAULT_SEED, buffer); public static uint Compute(uint seed, byte[] buffer) => - Compute(DefaultPolynomial, seed, buffer); + Compute(DEFAULT_POLYNOMIAL, 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 == DefaultPolynomial && defaultTable != null) + if (polynomial == DEFAULT_POLYNOMIAL && _defaultTable != null) { - return defaultTable; + return _defaultTable; } var createTable = new uint[256]; @@ -107,9 +97,9 @@ public sealed class Crc32Stream : Stream createTable[i] = entry; } - if (polynomial == DefaultPolynomial) + if (polynomial == DEFAULT_POLYNOMIAL) { - defaultTable = createTable; + _defaultTable = createTable; } return createTable; diff --git a/src/SharpCompress/Crypto/CryptoException.cs b/src/SharpCompress/Crypto/CryptoException.cs deleted file mode 100644 index 234fd5e5..00000000 --- a/src/SharpCompress/Crypto/CryptoException.cs +++ /dev/null @@ -1,14 +0,0 @@ -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 deleted file mode 100644 index 828c1a8f..00000000 --- a/src/SharpCompress/Crypto/DataLengthException.cs +++ /dev/null @@ -1,24 +0,0 @@ -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 deleted file mode 100644 index 50eb5fb3..00000000 --- a/src/SharpCompress/Crypto/IBlockCipher.cs +++ /dev/null @@ -1,33 +0,0 @@ -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 deleted file mode 100644 index 9934637a..00000000 --- a/src/SharpCompress/Crypto/ICipherParameters.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace SharpCompress.Crypto; - -public interface ICipherParameters { } diff --git a/src/SharpCompress/Crypto/KeyParameter.cs b/src/SharpCompress/Crypto/KeyParameter.cs deleted file mode 100644 index fce334f9..00000000 --- a/src/SharpCompress/Crypto/KeyParameter.cs +++ /dev/null @@ -1,39 +0,0 @@ -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/IO/BufferedSubStream.cs b/src/SharpCompress/IO/BufferedSubStream.cs index 0658a7b6..243d1ca9 100644 --- a/src/SharpCompress/IO/BufferedSubStream.cs +++ b/src/SharpCompress/IO/BufferedSubStream.cs @@ -3,7 +3,8 @@ using System.IO; namespace SharpCompress.IO; -internal class BufferedSubStream(Stream stream, long origin, long bytesToRead) : NonDisposingStream(stream, throwOnDispose: false) +internal class BufferedSubStream(Stream stream, long origin, long bytesToRead) + : NonDisposingStream(stream, throwOnDispose: false) { private int _cacheOffset; private int _cacheLength; diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 4520b134..53069414 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -190,8 +190,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// /// 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(this, decompressed); protected virtual EntryStream GetEntryStream() => CreateEntryStream(Entry.Parts.First().GetCompressedStream()); diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index d5306ac4..a46d2852 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -14,7 +14,8 @@ namespace SharpCompress.Readers.Rar; public abstract class RarReader : AbstractReader { private RarVolume? volume; - internal Lazy UnpackV2017 { get; } = new(() => new Compressors.Rar.UnpackV2017.Unpack()); + internal Lazy UnpackV2017 { get; } = + new(() => new Compressors.Rar.UnpackV2017.Unpack()); internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); internal RarReader(ReaderOptions options) diff --git a/src/SharpCompress/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index d029376c..55ef132f 100644 --- a/src/SharpCompress/Readers/Tar/TarReader.cs +++ b/src/SharpCompress/Readers/Tar/TarReader.cs @@ -30,33 +30,15 @@ public class TarReader : AbstractReader protected override Stream RequestInitialStream() { var stream = base.RequestInitialStream(); - switch (compressionType) + return compressionType switch { - 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); - } - } + 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.None => stream, + _ => throw new NotSupportedException("Invalid compression type: " + compressionType) + }; } #region Open diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index f446102a..9dc094e2 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -61,34 +61,16 @@ public class ZipWriter : AbstractWriter base.Dispose(isDisposing); } - private static ZipCompressionMethod ToZipCompressionMethod(CompressionType compressionType) - { - switch (compressionType) + private static ZipCompressionMethod ToZipCompressionMethod(CompressionType compressionType) => + compressionType switch { - 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); - } - } + 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) + }; public override void Write(string entryPath, Stream source, DateTime? modificationTime) => Write( From 4afc7ae2e4b1461c510ea33fa5043446a6cbdd8a Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 14 Mar 2024 13:07:40 +0000 Subject: [PATCH 0048/1333] use complete namespace --- tests/SharpCompress.Test/Tar/TarReaderTests.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index a1667d7d..56ea72ed 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -6,11 +6,6 @@ using SharpCompress.Readers; using SharpCompress.Readers.Tar; using SharpCompress.Test.Mocks; using Xunit; -#if !NETFRAMEWORK -using System.Runtime.InteropServices; -using Mono.Unix; -#endif - namespace SharpCompress.Test.Tar; @@ -189,7 +184,9 @@ public class TarReaderTests : ReaderTests [Fact] public void Tar_GZip_With_Symlink_Entries() { - var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + 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") ); @@ -210,7 +207,7 @@ public class TarReaderTests : ReaderTests { if (!isWindows) { - var link = new UnixSymbolicLinkInfo(sourcePath); + var link = new Mono.Unix.UnixSymbolicLinkInfo(sourcePath); if (File.Exists(sourcePath)) { link.Delete(); // equivalent to ln -s -f @@ -225,7 +222,7 @@ public class TarReaderTests : ReaderTests if (reader.Entry.LinkTarget != null) { var path = Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key); - var link = new UnixSymbolicLinkInfo(path); + var link = new Mono.Unix.UnixSymbolicLinkInfo(path); if (link.HasContents) { // need to convert the link to an absolute path for comparison From b6340f14584b5f6fdaf6547c4e1d3a7bf0da9b47 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 14 Mar 2024 11:31:22 -0400 Subject: [PATCH 0049/1333] rar5 improve memory usage use ArrayPool for stream buffer use stackalloc for methods on file decompression code path --- src/SharpCompress/BufferPool.cs | 33 ++++++++++++++++++ .../Compressors/Rar/RarStream.cs | 34 +++++++++++++------ .../Compressors/Rar/UnpackV2017/Unpack.cs | 8 ++--- .../Rar/UnpackV2017/Unpack.unpack20_cpp.cs | 11 +++--- .../Rar/UnpackV2017/Unpack.unpack50_cpp.cs | 12 +++---- .../Rar/UnpackV2017/Unpack.unpack_cpp.cs | 6 ++-- 6 files changed, 74 insertions(+), 30 deletions(-) create mode 100644 src/SharpCompress/BufferPool.cs diff --git a/src/SharpCompress/BufferPool.cs b/src/SharpCompress/BufferPool.cs new file mode 100644 index 00000000..b11dbe6f --- /dev/null +++ b/src/SharpCompress/BufferPool.cs @@ -0,0 +1,33 @@ +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/Compressors/Rar/RarStream.cs b/src/SharpCompress/Compressors/Rar/RarStream.cs index cebc81a1..bf5d3209 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 = new byte[65536]; + private byte[] tmpBuffer = BufferPool.Rent(65536); private int tmpOffset; private int tmpCount; @@ -40,6 +40,11 @@ internal class RarStream : Stream { if (!isDisposed) { + if (disposing) + { + BufferPool.Return(this.tmpBuffer); + this.tmpBuffer = null; + } isDisposed = true; base.Dispose(disposing); readStream.Dispose(); @@ -118,16 +123,7 @@ internal class RarStream : Stream } if (count > 0) { - 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; - } + EnsureBufferCapacity(count); Buffer.BlockCopy(buffer, offset, tmpBuffer, tmpCount, count); tmpCount += count; tmpOffset = 0; @@ -138,4 +134,20 @@ 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/UnpackV2017/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs index 450b4694..22fdc746 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using SharpCompress.Common.Rar.Headers; #if !Rar2017_64bit @@ -67,15 +67,15 @@ internal partial class Unpack : IRarUnpack private void UnstoreFile() { - var b = new byte[0x10000]; + Span b = stackalloc byte[(int)Math.Min(0x10000, DestUnpSize)]; do { - var n = readStream.Read(b, 0, (int)Math.Min(b.Length, DestUnpSize)); + var n = readStream.Read(b); if (n == 0) { break; } - writeStream.Write(b, 0, n); + writeStream.Write(b.Slice(0, n)); DestUnpSize -= n; } while (!Suspended); } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs index 397fd334..51dbff0b 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_cpp.cs @@ -373,8 +373,8 @@ internal partial class Unpack private bool ReadTables20() { - var BitLength = new byte[BC20]; - var Table = new byte[MC20 * 4]; + Span BitLength = stackalloc byte[checked((int)BC20)]; + Span Table = stackalloc byte[checked((int)MC20 * 4)]; if (Inp.InAddr > ReadTop - 25) { if (!UnpReadBuf()) @@ -410,13 +410,13 @@ internal partial class Unpack TableSize = NC20 + DC20 + RC20; } - for (uint I = 0; I < BC20; I++) + for (int I = 0; I < checked((int)BC20); I++) { BitLength[I] = (byte)(Inp.getbits() >> 12); Inp.addbits(4); } MakeDecodeTables(BitLength, 0, BlockTables.BD, BC20); - for (uint I = 0; I < TableSize; ) + for (int I = 0; I < checked((int)TableSize); ) { if (Inp.InAddr > ReadTop - 5) { @@ -487,8 +487,7 @@ internal partial class Unpack MakeDecodeTables(Table, (int)NC20, BlockTables.DD, DC20); MakeDecodeTables(Table, (int)(NC20 + DC20), BlockTables.RD, RC20); } - //x memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20)); - Array.Copy(Table, UnpOldTable20, UnpOldTable20.Length); + Table.CopyTo(this.UnpOldTable20); 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 82294e27..62567888 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System; using static SharpCompress.Compressors.Rar.UnpackV2017.PackDef; @@ -752,8 +752,8 @@ internal partial class Unpack } } - var BitLength = new byte[BC]; - for (uint I = 0; I < BC; I++) + Span BitLength = stackalloc byte[checked((int)BC)]; + for (int I = 0; I < BC; I++) { uint Length = (byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); @@ -784,9 +784,9 @@ internal partial class Unpack MakeDecodeTables(BitLength, 0, Tables.BD, BC); - var Table = new byte[HUFF_TABLE_SIZE]; - const uint TableSize = HUFF_TABLE_SIZE; - for (uint I = 0; I < TableSize; ) + Span Table = stackalloc byte[checked((int)HUFF_TABLE_SIZE)]; + const int TableSize = checked((int)HUFF_TABLE_SIZE); + for (int 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 38c21c9f..9c6cbeb0 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp.cs @@ -259,7 +259,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(byte[] LengthTable, int offset, DecodeTable Dec, uint Size) + private void MakeDecodeTables(Span LengthTable, int offset, DecodeTable Dec, uint Size) { // Size of alphabet and DecodePos array. Dec.MaxNum = Size; @@ -269,7 +269,7 @@ internal sealed partial class Unpack : BitInput //memset(LengthCount,0,sizeof(LengthCount)); for (size_t I = 0; I < Size; I++) { - LengthCount[LengthTable[offset + I] & 0xf]++; + LengthCount[LengthTable[checked((int)(offset + I))] & 0xf]++; } // We must not calculate the number of zero length codes. @@ -318,7 +318,7 @@ internal sealed partial class Unpack : BitInput for (uint I = 0; I < Size; I++) { // Get the current bit length. - var _CurBitLength = (byte)(LengthTable[offset + I] & 0xf); + var _CurBitLength = (byte)(LengthTable[checked((int)(offset + I))] & 0xf); if (_CurBitLength != 0) { From 6a824429d041725b5aeb41bfa6eb4eb23815e8c0 Mon Sep 17 00:00:00 2001 From: btomblinson Date: Sat, 16 Mar 2024 22:52:36 -0600 Subject: [PATCH 0050/1333] #809 Add README.md to csproj for NuGet --- src/SharpCompress/SharpCompress.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 318b5de8..5a9fa3e5 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -24,6 +24,7 @@ true latest true + README.md @@ -41,4 +42,7 @@ + + + From 02301ecf6d0f07a8a52912ee2bdbbff5d14d7ef1 Mon Sep 17 00:00:00 2001 From: Twan van Dongen Date: Sun, 24 Mar 2024 16:23:25 +0100 Subject: [PATCH 0051/1333] Support added for TAR LZW compression (Unix 'compress' resulting in .Z files) --- src/SharpCompress/Common/CompressionType.cs | 3 +- .../Compressors/Lzw/LzwConstants.cs | 65 ++ .../Compressors/Lzw/LzwStream.cs | 597 ++++++++++++++++++ src/SharpCompress/Factories/TarFactory.cs | 14 + src/SharpCompress/Readers/Tar/TarReader.cs | 4 +- src/SharpCompress/SharpCompress.csproj | 5 +- .../SharpCompress.Test/Tar/TarReaderTests.cs | 3 + tests/TestArchives/Archives/Tar.tar.Z | Bin 0 -> 90939 bytes 8 files changed, 688 insertions(+), 3 deletions(-) create mode 100644 src/SharpCompress/Compressors/Lzw/LzwConstants.cs create mode 100644 src/SharpCompress/Compressors/Lzw/LzwStream.cs create mode 100644 tests/TestArchives/Archives/Tar.tar.Z diff --git a/src/SharpCompress/Common/CompressionType.cs b/src/SharpCompress/Common/CompressionType.cs index b26e5a95..20f166c4 100644 --- a/src/SharpCompress/Common/CompressionType.cs +++ b/src/SharpCompress/Common/CompressionType.cs @@ -15,5 +15,6 @@ public enum CompressionType Xz, Unknown, Deflate64, - Shrink + Shrink, + Lzw } diff --git a/src/SharpCompress/Compressors/Lzw/LzwConstants.cs b/src/SharpCompress/Compressors/Lzw/LzwConstants.cs new file mode 100644 index 00000000..0325adbb --- /dev/null +++ b/src/SharpCompress/Compressors/Lzw/LzwConstants.cs @@ -0,0 +1,65 @@ +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 new file mode 100644 index 00000000..488ba1aa --- /dev/null +++ b/src/SharpCompress/Compressors/Lzw/LzwStream.cs @@ -0,0 +1,597 @@ +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/Factories/TarFactory.cs b/src/SharpCompress/Factories/TarFactory.cs index 54c24c02..715a05d2 100644 --- a/src/SharpCompress/Factories/TarFactory.cs +++ b/src/SharpCompress/Factories/TarFactory.cs @@ -6,6 +6,7 @@ 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; @@ -160,6 +161,19 @@ 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/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index 55ef132f..528e9cf4 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; @@ -10,6 +10,7 @@ using SharpCompress.Compressors.BZip2; using SharpCompress.Compressors.Deflate; using SharpCompress.Compressors.LZMA; using SharpCompress.Compressors.Xz; +using SharpCompress.Compressors.Lzw; using SharpCompress.IO; namespace SharpCompress.Readers.Tar; @@ -36,6 +37,7 @@ public class TarReader : AbstractReader 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) }; diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 5a9fa3e5..dec8a386 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -26,6 +26,9 @@ true README.md + + + @@ -43,6 +46,6 @@ - + diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index 56ea72ed..1ee4ae8d 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -40,6 +40,9 @@ public class TarReaderTests : ReaderTests } } + [Fact] + public void Tar_Z_Reader() => Read("Tar.tar.Z", CompressionType.Lzw); + [Fact] public void Tar_BZip2_Reader() => Read("Tar.tar.bz2", CompressionType.BZip2); diff --git a/tests/TestArchives/Archives/Tar.tar.Z b/tests/TestArchives/Archives/Tar.tar.Z new file mode 100644 index 0000000000000000000000000000000000000000..0eb90fb16643b08402e4a17e408aa2fe4e916a15 GIT binary patch literal 90939 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%0AMyXv3ME#v_|j$A5suTeg0BXD*L9X;&_r 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 A!T Date: Sun, 24 Mar 2024 16:29:29 +0100 Subject: [PATCH 0052/1333] CSharpier reformat missed --- src/SharpCompress/Readers/Tar/TarReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/Readers/Tar/TarReader.cs b/src/SharpCompress/Readers/Tar/TarReader.cs index 528e9cf4..a686dc11 100644 --- a/src/SharpCompress/Readers/Tar/TarReader.cs +++ b/src/SharpCompress/Readers/Tar/TarReader.cs @@ -9,8 +9,8 @@ using SharpCompress.Compressors; using SharpCompress.Compressors.BZip2; using SharpCompress.Compressors.Deflate; using SharpCompress.Compressors.LZMA; -using SharpCompress.Compressors.Xz; using SharpCompress.Compressors.Lzw; +using SharpCompress.Compressors.Xz; using SharpCompress.IO; namespace SharpCompress.Readers.Tar; From 09f2410170475edf1d37e1471b59c39b08b88964 Mon Sep 17 00:00:00 2001 From: klimatr26 Date: Fri, 5 Apr 2024 15:00:43 -0500 Subject: [PATCH 0053/1333] Add support for 7z ARM64 and RISCV filters --- .../Compressors/Filters/BCJFilterARM64.cs | 62 ++++++ .../Compressors/Filters/BCJFilterRISCV.cs | 204 ++++++++++++++++++ .../Compressors/LZMA/Registry.cs | 6 + .../SevenZip/SevenZipArchiveTests.cs | 6 + tests/TestArchives/Archives/7Zip.ARM64.7z | Bin 0 -> 59222 bytes tests/TestArchives/Archives/7Zip.Filters.7z | Bin 66213 -> 66536 bytes tests/TestArchives/Archives/7Zip.RISCV.7z | Bin 0 -> 59143 bytes 7 files changed, 278 insertions(+) create mode 100644 src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs create mode 100644 src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs create mode 100644 tests/TestArchives/Archives/7Zip.ARM64.7z create mode 100644 tests/TestArchives/Archives/7Zip.RISCV.7z diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs new file mode 100644 index 00000000..2797760c --- /dev/null +++ b/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs @@ -0,0 +1,62 @@ +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/BCJFilterRISCV.cs b/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs new file mode 100644 index 00000000..31996989 --- /dev/null +++ b/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs @@ -0,0 +1,204 @@ +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/LZMA/Registry.cs b/src/SharpCompress/Compressors/LZMA/Registry.cs index f4cfde4b..eb3e3bdd 100644 --- a/src/SharpCompress/Compressors/LZMA/Registry.cs +++ b/src/SharpCompress/Compressors/LZMA/Registry.cs @@ -25,6 +25,8 @@ 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; @@ -66,6 +68,10 @@ 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/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs index 226ba4d8..a0c9d8c9 100644 --- a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs +++ b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs @@ -162,6 +162,12 @@ 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"); diff --git a/tests/TestArchives/Archives/7Zip.ARM64.7z b/tests/TestArchives/Archives/7Zip.ARM64.7z new file mode 100644 index 0000000000000000000000000000000000000000..2e9d629370b0dc934f31ec7c4c9bce4d19c36887 GIT binary patch literal 59222 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 literal 0 HcmV?d00001 diff --git a/tests/TestArchives/Archives/7Zip.Filters.7z b/tests/TestArchives/Archives/7Zip.Filters.7z index ea15f3b2be5ff5957f1f19884be9ed32957f1cf9..d066779b32fff23c2150cfd850133c7e07ad5799 100644 GIT binary patch literal 66536 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

&^DSVlVP+# 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 GPyhfyiIvJ7Ld8y8 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

3Vvl2m#uglAK3a@%lw%N`t} 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 diff --git a/tests/TestArchives/Archives/7Zip.RISCV.7z b/tests/TestArchives/Archives/7Zip.RISCV.7z new file mode 100644 index 0000000000000000000000000000000000000000..b65c517b5700dc92d9030d16761fef0060e739ca GIT binary patch literal 59143 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�dtPab|s?w+rvC_wDwv`cjie{U+*sLi%d_=2od( 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�iz^eKVoYt{C`W`{fT?iVXn;8yDH6$#Ne91*0J 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 Date: Mon, 8 Apr 2024 09:50:37 +0100 Subject: [PATCH 0054/1333] formatting --- .../Compressors/Filters/BCJFilterARM64.cs | 7 +-- .../Compressors/Filters/BCJFilterRISCV.cs | 46 +++++++++++-------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs b/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs index 2797760c..24f5ab17 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterARM64.cs @@ -19,7 +19,9 @@ internal class BCJFilterARM64 : Filter for (i = offset; i <= end; i += 4) { uint pc = (uint)(_pos + i - offset); - uint instr = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan(buffer, i, 4)); + uint instr = BinaryPrimitives.ReadUInt32LittleEndian( + new ReadOnlySpan(buffer, i, 4) + ); if ((instr >> 26) == 0x25) { @@ -35,8 +37,7 @@ internal class BCJFilterARM64 : Filter } else if ((instr & 0x9F000000) == 0x90000000) { - uint src = ((instr >> 29) & 3) - | ((instr >> 3) & 0x001FFFFC); + uint src = ((instr >> 29) & 3) | ((instr >> 3) & 0x001FFFFC); if (((src + 0x00020000) & 0x001C0000) != 0) continue; diff --git a/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs b/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs index 31996989..67d9cb52 100644 --- a/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs +++ b/src/SharpCompress/Compressors/Filters/BCJFilterRISCV.cs @@ -33,21 +33,17 @@ internal class BCJFilterRISCV : Filter uint b3 = buffer[i + 3]; uint pc = (uint)(_pos + i); - uint addr = ((b1 & 0xF0) << 13) - | (b2 << 9) - | (b3 << 1); + uint addr = ((b1 & 0xF0) << 13) | (b2 << 9) | (b3 << 1); addr -= pc; - buffer[i + 1] = (byte)((b1 & 0x0F) - | ((addr >> 8) & 0xF0)); + buffer[i + 1] = (byte)((b1 & 0x0F) | ((addr >> 8) & 0xF0)); - buffer[i + 2] = (byte)(((addr >> 16) & 0x0F) - | ((addr >> 7) & 0x10) - | ((addr << 4) & 0xE0)); + buffer[i + 2] = (byte)( + ((addr >> 16) & 0x0F) | ((addr >> 7) & 0x10) | ((addr << 4) & 0xE0) + ); - buffer[i + 3] = (byte)(((addr >> 4) & 0x7F) - | ((addr >> 13) & 0x80)); + buffer[i + 3] = (byte)(((addr >> 4) & 0x7F) | ((addr >> 13) & 0x80)); i += 4 - 2; } @@ -60,7 +56,9 @@ internal class BCJFilterRISCV : Filter if ((inst & 0xE80) != 0) { - inst2 = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan(buffer, i + 4, 4)); + inst2 = BinaryPrimitives.ReadUInt32LittleEndian( + new ReadOnlySpan(buffer, i + 4, 4) + ); if (((((inst) << 8) ^ (inst2)) & 0xF8003) != 3) { i += 6 - 2; @@ -81,14 +79,15 @@ internal class BCJFilterRISCV : Filter continue; } - uint addr = BinaryPrimitives.ReadUInt32BigEndian(new ReadOnlySpan(buffer, i + 4, 4)); + 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); + 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); @@ -123,7 +122,8 @@ internal class BCJFilterRISCV : Filter uint b3 = buffer[i + 3]; uint pc = (uint)(_pos + i); - uint addr = ((b1 & 0xF0) << 8) + uint addr = + ((b1 & 0xF0) << 8) | ((b2 & 0x0F) << 16) | ((b2 & 0x10) << 7) | ((b2 & 0xE0) >> 4) @@ -132,8 +132,7 @@ internal class BCJFilterRISCV : Filter addr += pc; - buffer[i + 1] = (byte)((b1 & 0x0F) - | ((addr >> 13) & 0xF0)); + buffer[i + 1] = (byte)((b1 & 0x0F) | ((addr >> 13) & 0xF0)); buffer[i + 2] = (byte)(addr >> 9); @@ -149,7 +148,9 @@ internal class BCJFilterRISCV : Filter if ((inst & 0xE80) != 0) { - uint inst2 = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan(buffer, i + 4, 4)); + uint inst2 = BinaryPrimitives.ReadUInt32LittleEndian( + new ReadOnlySpan(buffer, i + 4, 4) + ); if (((((inst) << 8) ^ (inst2)) & 0xF8003) != 3) { i += 6 - 2; @@ -173,14 +174,19 @@ internal class BCJFilterRISCV : Filter continue; } - uint fake_addr = BinaryPrimitives.ReadUInt32LittleEndian(new ReadOnlySpan(buffer, i + 4, 4)); + 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); + BinaryPrimitives.WriteUInt32LittleEndian( + new Span(buffer, i + 4, 4), + fake_inst2 + ); } i += 8 - 2; } From bf74dd887a5a16f4e2787ae1e0eedd6c558ac9b8 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 9 Apr 2024 08:19:23 +0100 Subject: [PATCH 0055/1333] Fix tar corruption when sizes mismatch --- src/SharpCompress/Utility.cs | 15 ++++++++++++++- src/SharpCompress/Writers/Tar/TarWriter.cs | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index f7e0b17d..18ea1505 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -269,8 +269,9 @@ public static class Utility return sTime.AddSeconds(unixtime); } - public static long TransferTo(this Stream source, Stream destination) + public static long TransferTo(this Stream source, Stream destination, Int64? size = null) { + Int64 realSize = size ?? source.Length; var array = GetTransferByteArray(); try { @@ -279,6 +280,18 @@ public static class Utility { total += count; destination.Write(array, 0, count); + if (total + count > realSize) + { + int bytesToWrite = (int)(realSize - total); + destination.Write(array, 0, (int)bytesToWrite); + total = realSize; + break; + } + else + { + total += count; + destination.Write(array, 0, count); + } } return total; } diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 2427db37..53ce0ea2 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -91,7 +91,7 @@ public class TarWriter : AbstractWriter header.Size = realSize; header.Write(OutputStream); - size = source.TransferTo(OutputStream); + size = source.TransferTo(OutputStream, realSize); PadTo512(size.Value); } From 2321d9dbee9982da5d9240cd8bf787a576dd2bf9 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 9 Apr 2024 08:56:15 +0100 Subject: [PATCH 0056/1333] fix patch --- src/SharpCompress/Utility.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 18ea1505..18b83cd3 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -269,28 +269,24 @@ public static class Utility return sTime.AddSeconds(unixtime); } - public static long TransferTo(this Stream source, Stream destination, Int64? size = null) + public static long TransferTo(this Stream source, Stream destination, long? size = null) { - Int64 realSize = size ?? source.Length; var array = GetTransferByteArray(); try { long total = 0; while (ReadTransferBlock(source, array, out var count)) { - total += count; - destination.Write(array, 0, count); - if (total + count > realSize) + if (size is not null && total + count > size) { - int bytesToWrite = (int)(realSize - total); - destination.Write(array, 0, (int)bytesToWrite); - total = realSize; - break; + var bytesToWrite = (int)(size - total); + destination.Write(array, 0, bytesToWrite); + total += bytesToWrite; } else { - total += count; destination.Write(array, 0, count); + total += count; } } return total; From fdfaa8ab454bb8c4ea40f3b0ccf0d5dffce36a19 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 9 Apr 2024 15:35:15 +0100 Subject: [PATCH 0057/1333] add max transfer size to tar --- src/SharpCompress/Utility.cs | 46 +++++++++++++++++----- src/SharpCompress/Writers/Tar/TarWriter.cs | 8 +++- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 18b83cd3..c252f325 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -269,7 +269,7 @@ public static class Utility return sTime.AddSeconds(unixtime); } - public static long TransferTo(this Stream source, Stream destination, long? size = null) + public static long TransferTo(this Stream source, Stream destination) { var array = GetTransferByteArray(); try @@ -277,16 +277,32 @@ public static class Utility long total = 0; while (ReadTransferBlock(source, array, out var count)) { - if (size is not null && total + count > size) + destination.Write(array, 0, count); + total += count; + } + return total; + } + finally + { + ArrayPool.Shared.Return(array); + } + } + + public static long TransferTo(this Stream source, Stream destination, int size) + { + var array = GetTransferByteArray(); + try + { + long total = 0; + var remaining = size; + while (ReadTransferBlock(source, array, remaining, out var count)) + { + destination.Write(array, 0, count); + total += count; + remaining -= count; + if (remaining - count < 0) { - var bytesToWrite = (int)(size - total); - destination.Write(array, 0, bytesToWrite); - total += bytesToWrite; - } - else - { - destination.Write(array, 0, count); - total += count; + break; } } return total; @@ -327,6 +343,16 @@ 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/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 53ce0ea2..177a4051 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -91,7 +91,13 @@ public class TarWriter : AbstractWriter header.Size = realSize; header.Write(OutputStream); - size = source.TransferTo(OutputStream, realSize); + if (realSize >= int.MaxValue) + { + throw new NotSupportedException( + "TarWriter does not support writing files larger than 2GB." + ); + } + size = source.TransferTo(OutputStream, (int)realSize); PadTo512(size.Value); } From eab97a3f8b651a1b76860bce8081c58f79607465 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 10 Apr 2024 08:53:20 +0100 Subject: [PATCH 0058/1333] calculate remaining afterwards --- src/SharpCompress/Utility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index c252f325..857ecc8c 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -299,11 +299,11 @@ public static class Utility { destination.Write(array, 0, count); total += count; - remaining -= count; if (remaining - count < 0) { break; } + remaining -= count; } return total; } From cb223217c12321ec0b66cb1270b50f7f65c9347c Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 10 Apr 2024 16:12:01 +0100 Subject: [PATCH 0059/1333] actually, transfer block is different than overall transfer --- SharpCompress.sln.DotSettings | 5 +++++ src/SharpCompress/Utility.cs | 11 ++++++++--- src/SharpCompress/Writers/Tar/TarWriter.cs | 9 +-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/SharpCompress.sln.DotSettings b/SharpCompress.sln.DotSettings index 248b4c35..4ff50910 100644 --- a/SharpCompress.sln.DotSettings +++ b/SharpCompress.sln.DotSettings @@ -79,6 +79,10 @@ <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" /> @@ -127,6 +131,7 @@ 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/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 857ecc8c..5d8c1e27 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -288,14 +288,19 @@ public static class Utility } } - public static long TransferTo(this Stream source, Stream destination, int size) + public static long TransferTo(this Stream source, Stream destination, long maxLength) { var array = GetTransferByteArray(); try { long total = 0; - var remaining = size; - while (ReadTransferBlock(source, array, remaining, out var count)) + var remaining = maxLength; + var maxReadSize = array.Length; + if (remaining < maxLength) + { + maxReadSize = (int)remaining; + } + while (ReadTransferBlock(source, array, maxReadSize, out var count)) { destination.Write(array, 0, count); total += count; diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 177a4051..90242857 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -90,14 +90,7 @@ public class TarWriter : AbstractWriter header.Name = NormalizeFilename(filename); header.Size = realSize; header.Write(OutputStream); - - if (realSize >= int.MaxValue) - { - throw new NotSupportedException( - "TarWriter does not support writing files larger than 2GB." - ); - } - size = source.TransferTo(OutputStream, (int)realSize); + size = source.TransferTo(OutputStream, realSize); PadTo512(size.Value); } From 373637e6a7f617a6b03acc6a1b9a791efea5c122 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 11 Apr 2024 09:05:45 +0100 Subject: [PATCH 0060/1333] more logic fixes --- src/SharpCompress/Utility.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 5d8c1e27..bcecafb4 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -291,12 +291,12 @@ public static class Utility 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; - var maxReadSize = array.Length; - if (remaining < maxLength) + if (remaining < maxReadSize) { maxReadSize = (int)remaining; } @@ -309,6 +309,10 @@ public static class Utility break; } remaining -= count; + if (remaining < maxReadSize) + { + maxReadSize = (int)remaining; + } } return total; } From 4b9c814bfce9db8c8cc4190d51403f6597f72edd Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 11 Apr 2024 15:46:43 +0100 Subject: [PATCH 0061/1333] remove .netstandard 2.0 and clean up --- .editorconfig | 25 +++++++++++++------ README.md | 2 +- SharpCompress.sln | 1 + build/build.csproj | 4 +-- src/SharpCompress/Algorithms/Adler32.cs | 2 +- .../Common/Zip/WinzipAesEncryptionData.cs | 2 +- .../Compressors/BZip2/BZip2Stream.cs | 2 +- .../Compressors/LZMA/AesDecoderStream.cs | 23 ----------------- .../Compressors/LZMA/LZipStream.cs | 2 +- src/SharpCompress/Crypto/Crc32Stream.cs | 2 +- src/SharpCompress/IO/NonDisposingStream.cs | 2 +- src/SharpCompress/IO/ReadOnlySubStream.cs | 2 +- .../Polyfills/StreamExtensions.cs | 2 +- .../Polyfills/StringExtensions.cs | 2 +- src/SharpCompress/SharpCompress.csproj | 13 +++------- .../SharpCompress.Test.csproj | 6 ++--- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 2 +- 17 files changed, 38 insertions(+), 56 deletions(-) diff --git a/.editorconfig b/.editorconfig index 1903a97c..eab3d428 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 = warning +dotnet_analyzer_diagnostic.severity = silent ########################################## # File Header (Uncomment to support file headers) @@ -269,6 +269,8 @@ 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 @@ -286,6 +288,7 @@ 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 @@ -303,13 +306,12 @@ dotnet_diagnostic.CS1998.severity = error dotnet_diagnostic.CS8602.severity = error dotnet_diagnostic.CS8604.severity = error dotnet_diagnostic.CS8618.severity = error -dotnet_diagnostic.CS0618.severity = error +dotnet_diagnostic.CS0618.severity = suggestion 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 @@ -318,7 +320,7 @@ dotnet_diagnostic.MVC1000.severity = suggestion dotnet_diagnostic.RZ10012.severity = error dotnet_diagnostic.IDE0004.severity = error # redundant cast -dotnet_diagnostic.IDE0005.severity = error +dotnet_diagnostic.IDE0005.severity = suggestion dotnet_diagnostic.IDE0007.severity = error # Use var dotnet_diagnostic.IDE0011.severity = error # Use braces on if statements dotnet_diagnostic.IDE0010.severity = silent # populate switch @@ -329,7 +331,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 +dotnet_diagnostic.IDE0028.severity = silent # expression body for accessors dotnet_diagnostic.IDE0032.severity = suggestion # Use auto property dotnet_diagnostic.IDE0033.severity = error # prefer tuple name dotnet_diagnostic.IDE0037.severity = suggestion # simplify anonymous type @@ -337,7 +339,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 # paratemeter name +dotnet_diagnostic.IDE0047.severity = suggestion # parameter name dotnet_diagnostic.IDE0051.severity = error # unused field dotnet_diagnostic.IDE0052.severity = error # unused member dotnet_diagnostic.IDE0053.severity = suggestion # lambda not needed @@ -351,11 +353,20 @@ 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 = error # namespace folder structure +dotnet_diagnostic.IDE0130.severity = suggestion # 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/README.md b/README.md index 8eb4c10d..2a707028 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # SharpCompress -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. +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. The major feature is support for non-seekable streams so large files can be processed on the fly (i.e. download stream). diff --git a/SharpCompress.sln b/SharpCompress.sln index 71ec294e..34e23bfd 100644 --- a/SharpCompress.sln +++ b/SharpCompress.sln @@ -17,6 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{CDB425 ProjectSection(SolutionItems) = preProject Directory.Build.props = Directory.Build.props global.json = global.json + .editorconfig = .editorconfig EndProjectSection EndProject Global diff --git a/build/build.csproj b/build/build.csproj index 7b478cf3..27c0a257 100644 --- a/build/build.csproj +++ b/build/build.csproj @@ -6,9 +6,9 @@ - + - + diff --git a/src/SharpCompress/Algorithms/Adler32.cs b/src/SharpCompress/Algorithms/Adler32.cs index 10dbfc4d..51d5f53d 100644 --- a/src/SharpCompress/Algorithms/Adler32.cs +++ b/src/SharpCompress/Algorithms/Adler32.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK +#if !NETSTANDARD2_1 && !NETFRAMEWORK #define SUPPORTS_RUNTIME_INTRINSICS #define SUPPORTS_HOTPATH #endif diff --git a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs index 0b692035..adffaaea 100644 --- a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs @@ -48,7 +48,7 @@ internal class WinzipAesEncryptionData private void Initialize() { -#if NETFRAMEWORK || NETSTANDARD2_0 +#if NETFRAMEWORK var rfc2898 = new Rfc2898DeriveBytes(_password, _salt, RFC2898_ITERATIONS); #else var rfc2898 = new Rfc2898DeriveBytes( diff --git a/src/SharpCompress/Compressors/BZip2/BZip2Stream.cs b/src/SharpCompress/Compressors/BZip2/BZip2Stream.cs index feea12d1..e5614096 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 public override int Read(Span buffer) => stream.Read(buffer); diff --git a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs index 8e884c97..48e8ef34 100644 --- a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs +++ b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs @@ -207,28 +207,6 @@ internal sealed class AesDecoderStream : DecoderStream2 } else { -#if NETSTANDARD2_0 - using var sha = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); - var counter = new byte[8]; - var 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 (var 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; @@ -251,7 +229,6 @@ internal sealed class AesDecoderStream : DecoderStream2 sha.TransformFinalBlock(counter, 0, 0); return sha.Hash; -#endif } } diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.cs index 4b63a621..0e620dcf 100644 --- a/src/SharpCompress/Compressors/LZMA/LZipStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LZipStream.cs @@ -125,7 +125,7 @@ public sealed class LZipStream : Stream public override void SetLength(long value) => throw new NotImplementedException(); -#if !NETFRAMEWORK && !NETSTANDARD2_0 +#if !NETFRAMEWORK public override int Read(Span buffer) => _stream.Read(buffer); diff --git a/src/SharpCompress/Crypto/Crc32Stream.cs b/src/SharpCompress/Crypto/Crc32Stream.cs index 5f5ccd87..137131a3 100644 --- a/src/SharpCompress/Crypto/Crc32Stream.cs +++ b/src/SharpCompress/Crypto/Crc32Stream.cs @@ -29,7 +29,7 @@ public sealed class Crc32Stream(Stream stream, uint polynomial, uint seed) : Str public override void SetLength(long value) => throw new NotSupportedException(); -#if !NETFRAMEWORK && !NETSTANDARD2_0 +#if !NETFRAMEWORK public override void Write(ReadOnlySpan buffer) { diff --git a/src/SharpCompress/IO/NonDisposingStream.cs b/src/SharpCompress/IO/NonDisposingStream.cs index 334296d7..6d9e4174 100644 --- a/src/SharpCompress/IO/NonDisposingStream.cs +++ b/src/SharpCompress/IO/NonDisposingStream.cs @@ -63,7 +63,7 @@ public class NonDisposingStream : Stream public override void Write(byte[] buffer, int offset, int count) => Stream.Write(buffer, offset, count); -#if !NETFRAMEWORK && !NETSTANDARD2_0 +#if !NETFRAMEWORK public override int Read(Span buffer) => Stream.Read(buffer); diff --git a/src/SharpCompress/IO/ReadOnlySubStream.cs b/src/SharpCompress/IO/ReadOnlySubStream.cs index cd39335e..301e27ca 100644 --- a/src/SharpCompress/IO/ReadOnlySubStream.cs +++ b/src/SharpCompress/IO/ReadOnlySubStream.cs @@ -69,7 +69,7 @@ internal class ReadOnlySubStream : NonDisposingStream return value; } -#if !NETFRAMEWORK && !NETSTANDARD2_0 +#if !NETFRAMEWORK public override int Read(Span buffer) { var sliceLen = BytesLeftToRead < buffer.Length ? BytesLeftToRead : buffer.Length; diff --git a/src/SharpCompress/Polyfills/StreamExtensions.cs b/src/SharpCompress/Polyfills/StreamExtensions.cs index ab118a4f..360d041d 100644 --- a/src/SharpCompress/Polyfills/StreamExtensions.cs +++ b/src/SharpCompress/Polyfills/StreamExtensions.cs @@ -1,4 +1,4 @@ -#if NETFRAMEWORK || NETSTANDARD2_0 +#if NETFRAMEWORK using System; using System.Buffers; diff --git a/src/SharpCompress/Polyfills/StringExtensions.cs b/src/SharpCompress/Polyfills/StringExtensions.cs index 57d1e1bc..1cd22b8a 100644 --- a/src/SharpCompress/Polyfills/StringExtensions.cs +++ b/src/SharpCompress/Polyfills/StringExtensions.cs @@ -1,4 +1,4 @@ -#if NETFRAMEWORK || NETSTANDARD2_0 +#if NETFRAMEWORK namespace SharpCompress; diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index dec8a386..65904deb 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -6,7 +6,7 @@ 0.36.0 0.36.0 Adam Hathcock - net462;netstandard2.0;netstandard2.1;net6.0;net7.0;net8.0 + net462;netstandard2.1;net6.0;net8.0 SharpCompress ../../SharpCompress.snk true @@ -17,7 +17,7 @@ Copyright (c) 2014 Adam Hathcock false false - 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. + SharpCompress is a compression library for 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. true true snupkg @@ -26,21 +26,14 @@ true README.md - - - - + - - - - diff --git a/tests/SharpCompress.Test/SharpCompress.Test.csproj b/tests/SharpCompress.Test/SharpCompress.Test.csproj index e1f75276..8b10a738 100644 --- a/tests/SharpCompress.Test/SharpCompress.Test.csproj +++ b/tests/SharpCompress.Test/SharpCompress.Test.csproj @@ -9,12 +9,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index 1948b26a..68fe4e26 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -646,7 +646,7 @@ public class ZipArchiveTests : ArchiveTests Assert.Equal(199, len1); -#if !NETFRAMEWORK && !NETSTANDARD2_0 +#if !NETFRAMEWORK var len2 = 0; var buffer2 = new byte[firstEntry.Size + 256]; From 11153084e2196a34e20739ad619a17be1fd54524 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 11 Apr 2024 15:47:39 +0100 Subject: [PATCH 0062/1333] update csharpier --- .config/dotnet-tools.json | 2 +- src/SharpCompress/Archives/Zip/ZipArchive.cs | 1 - .../Common/Rar/Headers/FileHeader.cs | 6 ---- .../Common/Rar/Headers/RarHeaderFactory.cs | 6 ---- src/SharpCompress/Common/Rar/RarVolume.cs | 4 --- .../Common/Tar/TarHeaderFactory.cs | 2 -- .../Rar/UnpackV2017/Unpack.unpack50_cpp.cs | 2 -- src/SharpCompress/Compressors/Rar/VM/RarVM.cs | 28 ------------------- src/SharpCompress/Readers/Zip/ZipReader.cs | 1 - src/SharpCompress/Writers/Tar/TarWriter.cs | 3 -- 10 files changed, 1 insertion(+), 54 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index a4713c52..a13daa35 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "csharpier": { - "version": "0.27.3", + "version": "0.28.0", "commands": [ "dotnet-csharpier" ] diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index 87e9ac25..88e3335e 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -231,7 +231,6 @@ public class ZipArchive : AbstractWritableArchive switch (h.ZipHeaderType) { case ZipHeaderType.DirectoryEntry: - { var deh = (DirectoryEntryHeader)h; Stream s; diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index 86b56055..eea8293d 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -121,7 +121,6 @@ internal class FileHeader : RarHeader switch (type) { case FHEXTRA_CRYPT: // file encryption - { Rar5CryptoInfo = new Rar5CryptoInfo(reader, true); @@ -132,7 +131,6 @@ internal class FileHeader : RarHeader } break; case FHEXTRA_HASH: - { const uint FHEXTRA_HASH_BLAKE2 = 0x0; // const uint HASH_BLAKE2 = 0x03; @@ -146,7 +144,6 @@ internal class FileHeader : RarHeader } break; case FHEXTRA_HTIME: // file time - { var flags = reader.ReadRarVIntUInt16(); var isWindowsTime = (flags & 1) == 0; @@ -171,7 +168,6 @@ internal class FileHeader : RarHeader // } // break; case FHEXTRA_REDIR: // file system redirection - { RedirType = reader.ReadRarVIntByte(); RedirFlags = reader.ReadRarVIntByte(); @@ -284,7 +280,6 @@ internal class FileHeader : RarHeader switch (HeaderCode) { case HeaderCodeV.RAR4_FILE_HEADER: - { if (HasFlag(FileFlagsV4.UNICODE)) { @@ -311,7 +306,6 @@ internal class FileHeader : RarHeader } break; case HeaderCodeV.RAR4_NEW_SUB_HEADER: - { var datasize = HeaderSize - newLhdSize - nameSize; if (HasFlag(FileFlagsV4.SALT)) diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index e38cb629..74d68fc7 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -98,13 +98,11 @@ public class RarHeaderFactory switch (StreamingMode) { case StreamingMode.Seekable: - { reader.BaseStream.Position += ph.DataSize; } break; case StreamingMode.Streaming: - { reader.BaseStream.Skip(ph.DataSize); } @@ -146,14 +144,12 @@ 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) @@ -204,14 +200,12 @@ 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/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index da42ff24..2f497a04 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -39,19 +39,16 @@ 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) @@ -63,7 +60,6 @@ public abstract class RarVolume : Volume } break; case HeaderType.Service: - { var fh = (FileHeader)header; if (fh.FileName == "CMT") diff --git a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs index 85eec5b4..13813353 100644 --- a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs +++ b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs @@ -28,7 +28,6 @@ internal static class TarHeaderFactory switch (mode) { case StreamingMode.Seekable: - { header.DataStartPosition = reader.BaseStream.Position; @@ -37,7 +36,6 @@ internal static class TarHeaderFactory } break; case StreamingMode.Streaming: - { header.PackedStream = new TarReadOnlySubStream(stream, header.Size); } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs index 62567888..143e3d31 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs @@ -530,7 +530,6 @@ internal partial class Unpack { case FILTER_E8: case FILTER_E8E9: - { var FileOffset = (uint)WrittenFileSize; @@ -569,7 +568,6 @@ 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" diff --git a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs index 185b24d4..f758b8a4 100644 --- a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs +++ b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs @@ -228,7 +228,6 @@ 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); @@ -247,7 +246,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_CMPB: - { var value1 = (VMFlags)GetValue(true, Mem, op1); var result = value1 - GetValue(true, Mem, op2); @@ -265,7 +263,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_CMPD: - { var value1 = (VMFlags)GetValue(false, Mem, op1); var result = value1 - GetValue(false, Mem, op2); @@ -283,7 +280,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_ADD: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var result = (int)( @@ -351,7 +347,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SUB: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var result = (int)( @@ -411,7 +406,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_INC: - { var result = (int)(GetValue(cmd.IsByteMode, Mem, op1) & (0xFFffFFffL + 1L)); if (cmd.IsByteMode) @@ -440,7 +434,6 @@ 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); @@ -463,7 +456,6 @@ internal sealed class RarVM : BitInput continue; case VMCommands.VM_XOR: - { var result = GetValue(cmd.IsByteMode, Mem, op1) ^ GetValue(cmd.IsByteMode, Mem, op2); @@ -475,7 +467,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_AND: - { var result = GetValue(cmd.IsByteMode, Mem, op1) & GetValue(cmd.IsByteMode, Mem, op2); @@ -487,7 +478,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_OR: - { var result = GetValue(cmd.IsByteMode, Mem, op1) | GetValue(cmd.IsByteMode, Mem, op2); @@ -499,7 +489,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_TEST: - { var result = GetValue(cmd.IsByteMode, Mem, op1) & GetValue(cmd.IsByteMode, Mem, op2); @@ -578,7 +567,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SHL: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -596,7 +584,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SHR: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -610,7 +597,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SAR: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -624,7 +610,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_NEG: - { var result = -GetValue(cmd.IsByteMode, Mem, op1); flags = (VMFlags)( @@ -645,7 +630,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_PUSHA: - { for (int i = 0, SP = R[7] - 4; i < regCount; i++, SP -= 4) { @@ -656,7 +640,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_POPA: - { for (int i = 0, SP = R[7]; i < regCount; i++, SP += 4) { @@ -684,7 +667,6 @@ 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)); @@ -693,7 +675,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_MUL: - { var result = (int)( ( @@ -707,7 +688,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_DIV: - { var divider = GetValue(cmd.IsByteMode, Mem, op2); if (divider != 0) @@ -719,7 +699,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_ADC: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var FC = (int)(flags & VMFlags.VM_FC); @@ -749,7 +728,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SBB: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var FC = (int)(flags & VMFlags.VM_FC); @@ -1156,7 +1134,6 @@ internal sealed class RarVM : BitInput { case VMStandardFilters.VMSF_E8: case VMStandardFilters.VMSF_E8E9: - { var dataSize = R[4]; long fileOffset = R[6] & unchecked((int)0xFFffFFff); @@ -1211,7 +1188,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_ITANIUM: - { var dataSize = R[4]; long fileOffset = R[6] & unchecked((int)0xFFffFFff); @@ -1269,7 +1245,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_DELTA: - { var dataSize = R[4] & unchecked((int)0xFFffFFff); var channels = R[0] & unchecked((int)0xFFffFFff); @@ -1300,7 +1275,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_RGB: - { // byte *SrcData=Mem,*DestData=SrcData+DataSize; int dataSize = R[4], @@ -1366,7 +1340,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_AUDIO: - { int dataSize = R[4], channels = R[0]; @@ -1497,7 +1470,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_UPCASE: - { int dataSize = R[4], srcPos = 0, diff --git a/src/SharpCompress/Readers/Zip/ZipReader.cs b/src/SharpCompress/Readers/Zip/ZipReader.cs index b00690f0..cda3f3f8 100644 --- a/src/SharpCompress/Readers/Zip/ZipReader.cs +++ b/src/SharpCompress/Readers/Zip/ZipReader.cs @@ -69,7 +69,6 @@ public class ZipReader : AbstractReader switch (h.ZipHeaderType) { case ZipHeaderType.LocalEntry: - { yield return new ZipEntry( new StreamingZipFilePart((LocalEntryHeader)h, stream) diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 90242857..a1581da9 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -32,19 +32,16 @@ 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); } From 2af744b474a38fe069c21d3206ff41b43f1cf6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20W=C4=99glarz?= Date: Mon, 15 Apr 2024 04:28:15 +0200 Subject: [PATCH 0063/1333] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8eb4c10d..c1295636 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The major feature is support for non-seekable streams so large files can be proc 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%20Documentation-RobiniaDocs-43bc00?logo=readme&logoColor=white)](https://www.robiniadocs.com/d/sharpcompress/api/SharpCompress.html) +[![Static Badge](https://img.shields.io/badge/API%20Docs-DNDocs-190088?logo=readme&logoColor=white)](https://dndocs.com/d/sharpcompress/api/index.html) ## Need Help? From e96366f4895dbb13fcc8b2fb40d945bd27ef4bfc Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 18 Apr 2024 13:24:03 +0100 Subject: [PATCH 0064/1333] Entry can be null and remove other ! usages --- .../Archives/AbstractWritableArchive.cs | 4 ++++ src/SharpCompress/Archives/GZip/GZipArchive.cs | 2 +- .../Archives/IArchiveEntryExtensions.cs | 6 +----- src/SharpCompress/Archives/IArchiveExtensions.cs | 3 +-- src/SharpCompress/Common/Entry.cs | 8 ++++---- src/SharpCompress/Common/ExtractionMethods.cs | 4 ++-- src/SharpCompress/Common/FilePart.cs | 2 +- src/SharpCompress/Common/GZip/GZipEntry.cs | 2 +- src/SharpCompress/Common/GZip/GZipFilePart.cs | 2 +- src/SharpCompress/Common/IEntry.cs | 2 +- src/SharpCompress/Common/IVolume.cs | 2 +- src/SharpCompress/Common/Rar/RarCryptoWrapper.cs | 4 ++-- .../Common/SevenZip/ArchiveDatabase.cs | 2 +- src/SharpCompress/Common/Volume.cs | 2 +- src/SharpCompress/IO/SourceStream.cs | 16 ++++++++-------- src/SharpCompress/Readers/AbstractReader.cs | 4 ++-- src/SharpCompress/Readers/Rar/RarReader.cs | 6 ++++-- src/SharpCompress/Utility.cs | 16 ++++++++++++++++ .../SharpCompress.Test/GZip/GZipArchiveTests.cs | 5 +++-- tests/SharpCompress.Test/Rar/RarReaderTests.cs | 6 +++--- tests/SharpCompress.Test/TestBase.cs | 4 ++-- tests/SharpCompress.Test/Zip/ZipArchiveTests.cs | 2 +- 22 files changed, 61 insertions(+), 43 deletions(-) diff --git a/src/SharpCompress/Archives/AbstractWritableArchive.cs b/src/SharpCompress/Archives/AbstractWritableArchive.cs index 84ca0b3f..ef272d9b 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -120,6 +120,10 @@ 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/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index 70924b04..88247222 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -184,7 +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, entryStream, entry.LastModifiedTime); + writer.Write(entry.Key.NotNull("Entry Key is null"), entryStream, entry.LastModifiedTime); } } diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index 0992f152..3d1daa1a 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -17,15 +17,11 @@ public static class IArchiveEntryExtensions streamListener.EnsureEntriesLoaded(); streamListener.FireEntryExtractionBegin(archiveEntry); streamListener.FireFilePartExtractionBegin( - archiveEntry.Key, + archiveEntry.Key ?? "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 56ea0d9f..382c3ddf 100644 --- a/src/SharpCompress/Archives/IArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveExtensions.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; -using System.Threading.Tasks; using SharpCompress.Common; namespace SharpCompress.Archives; @@ -59,7 +58,7 @@ public static class IArchiveExtensions } // Create each directory - var path = Path.Combine(destination, entry.Key); + var path = Path.Combine(destination, entry.Key.NotNull("Entry Key is null")); if (Path.GetDirectoryName(path) is { } directory && seenDirectories.Add(path)) { Directory.CreateDirectory(directory); diff --git a/src/SharpCompress/Common/Entry.cs b/src/SharpCompress/Common/Entry.cs index 85219a43..6209b3de 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; + public override string ToString() => Key ?? "Entry"; internal abstract IEnumerable Parts { get; } diff --git a/src/SharpCompress/Common/ExtractionMethods.cs b/src/SharpCompress/Common/ExtractionMethods.cs index a470637a..4a24ad9e 100644 --- a/src/SharpCompress/Common/ExtractionMethods.cs +++ b/src/SharpCompress/Common/ExtractionMethods.cs @@ -36,10 +36,10 @@ internal static class ExtractionMethods options ??= new ExtractionOptions() { Overwrite = true }; - var file = Path.GetFileName(entry.Key); + var file = Path.GetFileName(entry.Key.NotNull("Entry Key is null")).NotNull("File is null"); if (options.ExtractFullPath) { - var folder = Path.GetDirectoryName(entry.Key)!; + var folder = Path.GetDirectoryName(entry.Key.NotNull("Entry Key is null")).NotNull("Directory is null"); var destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder)); if (!Directory.Exists(destdir)) diff --git a/src/SharpCompress/Common/FilePart.cs b/src/SharpCompress/Common/FilePart.cs index 3c286d54..23b8b400 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 bb9a22da..bd341d24 100644 --- a/src/SharpCompress/Common/GZip/GZipEntry.cs +++ b/src/SharpCompress/Common/GZip/GZipEntry.cs @@ -14,7 +14,7 @@ public class GZipEntry : Entry public override long Crc => _filePart.Crc ?? 0; - public override string Key => _filePart.FilePartName; + public override string? Key => _filePart.FilePartName; public override string? LinkTarget => null; diff --git a/src/SharpCompress/Common/GZip/GZipFilePart.cs b/src/SharpCompress/Common/GZip/GZipFilePart.cs index fbf4ee45..4a1c9515 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/IEntry.cs b/src/SharpCompress/Common/IEntry.cs index df1fa603..56e1db81 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 abbc0406..aed35fd0 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/Rar/RarCryptoWrapper.cs b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs index a9798609..5500af8d 100644 --- a/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs +++ b/src/SharpCompress/Common/Rar/RarCryptoWrapper.cs @@ -70,11 +70,11 @@ internal sealed class RarCryptoWrapper : Stream protected override void Dispose(bool disposing) { - if (_rijndael != null) + if (disposing) { _rijndael.Dispose(); - _rijndael = null!; } + base.Dispose(disposing); } } diff --git a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs index ee6f6d08..4bac08ad 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveDatabase.cs @@ -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/Volume.cs b/src/SharpCompress/Common/Volume.cs index 1f259257..a29dab75 100644 --- a/src/SharpCompress/Common/Volume.cs +++ b/src/SharpCompress/Common/Volume.cs @@ -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/IO/SourceStream.cs b/src/SharpCompress/IO/SourceStream.cs index 26ce0af1..46c0a3f6 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(_streams.Count); + var f = _getFilePart.NotNull("GetFilePart is null")(_streams.Count); if (f == null) { _stream = _streams.Count - 1; @@ -90,7 +90,7 @@ public class SourceStream : Stream } else { - var s = _getStreamPart(_streams.Count); + var s = _getStreamPart.NotNull("GetStreamPart is null")(_streams.Count); if (s == null) { _stream = _streams.Count - 1; diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 53069414..a0d982f1 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -35,7 +35,7 @@ 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 @@ -109,7 +109,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti return entriesForCurrentReadStream.MoveNext(); } - protected virtual Stream RequestInitialStream() => Volume.Stream; + protected virtual Stream RequestInitialStream() => Volume.NotNull("Volume isn't loaded.").Stream; internal virtual bool NextEntryForCurrentStream() => entriesForCurrentReadStream!.MoveNext(); diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index a46d2852..f092699d 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -19,11 +19,13 @@ public abstract class RarReader : AbstractReader internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); internal RarReader(ReaderOptions options) - : base(options, ArchiveType.Rar) { } + : base(options, ArchiveType.Rar) + { + } 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 diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index bcecafb4..74f6037a 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -9,6 +9,22 @@ namespace SharpCompress; [CLSCompliant(false)] public static class Utility { + public static T NotNull(this T? item, string message) where T : class + { + if (item is null) + { + throw new InvalidOperationException(message); + } + return item; + } + public static T NotNull(this T? item) where T : class + { + if (item is null) + { + throw new InvalidOperationException("Item is null"); + } + return item; + } public static ReadOnlyCollection ToReadOnly(this ICollection items) => new(items); /// diff --git a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs index 5b497d9f..80a9a9a1 100644 --- a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs @@ -19,7 +19,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)); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar")); @@ -41,7 +41,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)); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar")); @@ -94,6 +94,7 @@ public class GZipArchiveTests : ArchiveTests using (var entryStream = archiveEntry.OpenEntryStream()) { var result = TarArchive.IsTarFile(entryStream); + Assert.True(result); } Assert.Equal(size, tarStream.Length); using (var entryStream = archiveEntry.OpenEntryStream()) diff --git a/tests/SharpCompress.Test/Rar/RarReaderTests.cs b/tests/SharpCompress.Test/Rar/RarReaderTests.cs index e2b100f6..6ba605a5 100644 --- a/tests/SharpCompress.Test/Rar/RarReaderTests.cs +++ b/tests/SharpCompress.Test/Rar/RarReaderTests.cs @@ -209,7 +209,7 @@ public class RarReaderTests : ReaderTests { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); using var entryStream = reader.OpenEntryStream(); - var file = Path.GetFileName(reader.Entry.Key); + var file = Path.GetFileName(reader.Entry.Key).NotNull(); var folder = Path.GetDirectoryName(reader.Entry.Key) ?? throw new ArgumentNullException(); @@ -293,7 +293,7 @@ public class RarReaderTests : ReaderTests using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true }); while (reader.MoveToNextEntry()) { - if (reader.Entry.Key.Contains("jpg")) + if (reader.Entry.Key.NotNull().Contains("jpg")) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( @@ -316,7 +316,7 @@ public class RarReaderTests : ReaderTests using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true }); while (reader.MoveToNextEntry()) { - if (reader.Entry.Key.Contains("jpg")) + if (reader.Entry.Key.NotNull().Contains("jpg")) { Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType); reader.WriteEntryToDirectory( diff --git a/tests/SharpCompress.Test/TestBase.cs b/tests/SharpCompress.Test/TestBase.cs index ad39b2d7..184e6442 100644 --- a/tests/SharpCompress.Test/TestBase.cs +++ b/tests/SharpCompress.Test/TestBase.cs @@ -216,8 +216,8 @@ public class TestBase : IDisposable while (archive1.MoveToNextEntry()) { Assert.True(archive2.MoveToNextEntry()); - archive1Entries.Add(archive1.Entry.Key); - archive2Entries.Add(archive2.Entry.Key); + archive1Entries.Add(archive1.Entry.Key.NotNull()); + archive2Entries.Add(archive2.Entry.Key.NotNull()); } Assert.False(archive2.MoveToNextEntry()); } diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index 1948b26a..afbe7c9e 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -258,7 +258,7 @@ public class ZipArchiveTests : ArchiveTests ); Assert.Null( ((IArchive)vfs).Entries.FirstOrDefault(v => - v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); } From fb55624f5f74108a629d62ceacfcf58b6f7dbaec Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 18 Apr 2024 14:25:10 +0100 Subject: [PATCH 0065/1333] add more null handling --- src/SharpCompress/Archives/AbstractArchive.cs | 5 +- .../Archives/GZip/GZipArchiveEntry.cs | 2 +- .../Archives/GZip/GZipWritableArchiveEntry.cs | 4 +- src/SharpCompress/Archives/Rar/RarArchive.cs | 11 +++-- .../Archives/SevenZip/SevenZipArchive.cs | 46 ++++++++----------- src/SharpCompress/Archives/Tar/TarArchive.cs | 7 ++- .../Archives/Tar/TarArchiveEntry.cs | 2 +- .../Archives/Tar/TarWritableArchiveEntry.cs | 2 - src/SharpCompress/Archives/Zip/ZipArchive.cs | 24 +++++----- src/SharpCompress/Common/GZip/GZipEntry.cs | 14 +++--- src/SharpCompress/Common/GZip/GZipVolume.cs | 2 +- src/SharpCompress/Common/Rar/RarEntry.cs | 2 +- .../Common/SevenZip/SevenZipEntry.cs | 2 +- .../Common/Tar/Headers/TarHeader.cs | 18 ++++---- src/SharpCompress/Common/Tar/TarEntry.cs | 26 +++++------ src/SharpCompress/Common/Tar/TarFilePart.cs | 8 ++-- src/SharpCompress/Common/Volume.cs | 6 +-- .../Common/Zip/Headers/ZipFileEntry.cs | 16 +++---- .../Common/Zip/StreamingZipFilePart.cs | 2 +- .../Common/Zip/StreamingZipHeaderFactory.cs | 4 ++ src/SharpCompress/Common/Zip/ZipEntry.cs | 29 ++++++------ src/SharpCompress/Common/Zip/ZipFilePart.cs | 2 +- src/SharpCompress/Utility.cs | 17 +++++++ src/SharpCompress/Writers/AbstractWriter.cs | 20 ++++---- src/SharpCompress/Writers/GZip/GZipWriter.cs | 16 +++---- src/SharpCompress/Writers/Tar/TarWriter.cs | 2 +- src/SharpCompress/Writers/Zip/ZipWriter.cs | 6 +-- .../SevenZip/SevenZipArchiveTests.cs | 2 +- .../SharpCompress.Test/Tar/TarArchiveTests.cs | 2 +- .../SharpCompress.Test/Tar/TarReaderTests.cs | 8 ++-- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 10 ++-- 31 files changed, 157 insertions(+), 160 deletions(-) diff --git a/src/SharpCompress/Archives/AbstractArchive.cs b/src/SharpCompress/Archives/AbstractArchive.cs index cfac55f2..3975a0d4 100644 --- a/src/SharpCompress/Archives/AbstractArchive.cs +++ b/src/SharpCompress/Archives/AbstractArchive.cs @@ -24,7 +24,7 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra protected ReaderOptions ReaderOptions { get; } private bool disposed; - protected SourceStream SrcStream; + protected SourceStream? SrcStream; internal AbstractArchive(ArchiveType type, SourceStream srcStream) { @@ -35,15 +35,14 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra 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()); } -#nullable enable public ArchiveType Type { get; } diff --git a/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs b/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs index be872e80..459d042d 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 27dfc2bf..90f6f16f 100644 --- a/src/SharpCompress/Archives/GZip/GZipWritableArchiveEntry.cs +++ b/src/SharpCompress/Archives/GZip/GZipWritableArchiveEntry.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.IO; @@ -32,7 +30,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/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index b6472407..b6a7c02b 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -31,14 +31,15 @@ public class RarArchive : AbstractArchive protected override IEnumerable LoadVolumes(SourceStream srcStream) { - SrcStream.LoadAllParts(); //request all streams - var streams = SrcStream.Streams.ToArray(); + var sourceStream = SrcStream.NotNull("SourceStream is null"); + sourceStream .LoadAllParts(); //request all streams + var streams = sourceStream.Streams.ToArray(); var idx = 0; if (streams.Length > 1 && IsRarFile(streams[1], ReaderOptions)) //test part 2 - true = multipart not split { - SrcStream.IsVolumes = true; + sourceStream.IsVolumes = true; streams[1].Position = 0; - SrcStream.Position = 0; + sourceStream.Position = 0; return srcStream.Streams.Select(a => new StreamRarArchiveVolume( a, @@ -48,7 +49,7 @@ public class RarArchive : AbstractArchive } else //split mode or single file { - return new StreamRarArchiveVolume(SrcStream, ReaderOptions, idx++).AsEnumerable(); + return new StreamRarArchiveVolume(sourceStream, ReaderOptions, idx++).AsEnumerable(); } } diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index 7577b43d..b41f4cf6 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.IO; @@ -14,14 +12,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()); @@ -32,7 +30,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( @@ -51,7 +49,7 @@ public class SevenZipArchive : AbstractArchive public static SevenZipArchive Open( IEnumerable fileInfos, - ReaderOptions readerOptions = null + ReaderOptions? readerOptions = null ) { fileInfos.CheckNotNull(nameof(fileInfos)); @@ -72,7 +70,7 @@ public class SevenZipArchive : AbstractArchive public static SevenZipArchive Open( IEnumerable streams, - ReaderOptions readerOptions = null + ReaderOptions? readerOptions = null ) { streams.CheckNotNull(nameof(streams)); @@ -91,7 +89,7 @@ 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( @@ -103,13 +101,12 @@ public class SevenZipArchive : AbstractArchive /// - /// internal SevenZipArchive(SourceStream srcStream) : base(ArchiveType.SevenZip, srcStream) { } protected override IEnumerable LoadVolumes(SourceStream srcStream) { - SrcStream.LoadAllParts(); //request all streams + SrcStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams var idx = 0; return new SevenZipVolume(srcStream, ReaderOptions, idx++).AsEnumerable(); //simple single volume or split, multivolume not supported } @@ -133,6 +130,10 @@ public class SevenZipArchive : AbstractArchive volumes ) { + if (database is null) + { + return Enumerable.Empty(); + } var stream = volumes.Single().Stream; LoadFactory(stream); var entries = new SevenZipArchiveEntry[database._files.Count]; @@ -196,21 +197,14 @@ public class SevenZipArchive : AbstractArchive Entries.Where(x => !x.IsDirectory).GroupBy(x => x.FilePart.Folder).Count() > 1; - public override long TotalSize - { - get - { - var i = Entries.Count; - return database._packSizes.Aggregate(0L, (total, packSize) => total + packSize); - } - } + public override long TotalSize => database?._packSizes.Aggregate(0L, (total, packSize) => total + packSize) ?? 0; private sealed class SevenZipReader : AbstractReader { private readonly SevenZipArchive archive; - private CFolder currentFolder; - private Stream currentStream; - private CFileItem currentItem; + private CFolder? currentFolder; + private Stream? currentStream; + private CFileItem? currentItem; internal SevenZipReader(ReaderOptions readerOptions, SevenZipArchive archive) : base(readerOptions, ArchiveType.SevenZip) => this.archive = archive; @@ -236,7 +230,7 @@ public class SevenZipArchive : AbstractArchive - CreateEntryStream(new ReadOnlySubStream(currentStream, currentItem.Size)); + CreateEntryStream(new ReadOnlySubStream(currentStream.NotNull("currentStream is not null"), currentItem?.Size ?? 0)); } 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.NotNull(); } } diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index 70ac2413..d1f8cc1d 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; @@ -125,7 +125,7 @@ public class TarArchive : AbstractWritableArchive protected override IEnumerable LoadVolumes(SourceStream srcStream) { - SrcStream.LoadAllParts(); //request all streams + SrcStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams var idx = 0; return new TarVolume(srcStream, ReaderOptions, idx++).AsEnumerable(); //simple single volume or split, multivolume not supported } @@ -134,7 +134,6 @@ public class TarArchive : AbstractWritableArchive /// Constructor with a SourceStream able to handle FileInfo and Streams. /// /// - /// internal TarArchive(SourceStream srcStream) : base(ArchiveType.Tar, srcStream) { } @@ -225,7 +224,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, entryStream, entry.LastModifiedTime, entry.Size); + writer.Write(entry.Key.NotNull("Entry Key is null"), entryStream, entry.LastModifiedTime, entry.Size); } } diff --git a/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs b/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs index 2da84d71..d04c4ef8 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 0bbea709..32be7d9b 100644 --- a/src/SharpCompress/Archives/Tar/TarWritableArchiveEntry.cs +++ b/src/SharpCompress/Archives/Tar/TarWritableArchiveEntry.cs @@ -1,5 +1,3 @@ -#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 87e9ac25..2d243d42 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -16,10 +16,7 @@ namespace SharpCompress.Archives.Zip; public class ZipArchive : AbstractWritableArchive { -#nullable disable - private readonly SeekableZipHeaderFactory headerFactory; - -#nullable enable + private readonly SeekableZipHeaderFactory? headerFactory; /// /// Gets or sets the compression level applied to files added to the archive, @@ -191,10 +188,11 @@ public class ZipArchive : AbstractWritableArchive protected override IEnumerable LoadVolumes(SourceStream srcStream) { - SrcStream.LoadAllParts(); //request all streams - SrcStream.Position = 0; + var stream = SrcStream.NotNull("SrcStream is null"); + stream.LoadAllParts(); //request all streams + stream.Position = 0; - var streams = SrcStream.Streams.ToList(); + var streams = stream.Streams.ToList(); var idx = 0; if (streams.Count > 1) //test part 2 - true = multipart not split { @@ -203,7 +201,7 @@ public class ZipArchive : AbstractWritableArchive streams[1].Position -= 4; if (isZip) { - SrcStream.IsVolumes = true; + stream.IsVolumes = true; var tmp = streams[0]; //arcs as zip, z01 ... swap the zip the end streams.RemoveAt(0); @@ -215,7 +213,7 @@ public class ZipArchive : AbstractWritableArchive } //split mode or single file - return new ZipVolume(SrcStream, ReaderOptions, idx++).AsEnumerable(); + return new ZipVolume(stream, ReaderOptions, idx++).AsEnumerable(); } internal ZipArchive() @@ -224,7 +222,7 @@ public class ZipArchive : AbstractWritableArchive protected override IEnumerable LoadEntries(IEnumerable volumes) { var vols = volumes.ToArray(); - foreach (var h in headerFactory.ReadSeekableHeader(vols.Last().Stream)) + foreach (var h in headerFactory.NotNull().ReadSeekableHeader(vols.Last().Stream)) { if (h != null) { @@ -254,14 +252,14 @@ public class ZipArchive : AbstractWritableArchive yield return new ZipArchiveEntry( this, - new SeekableZipFilePart(headerFactory, deh, s) + new SeekableZipFilePart(headerFactory.NotNull(), deh, s) ); } break; case ZipHeaderType.DirectoryEnd: { var bytes = ((DirectoryEndHeader)h).Comment ?? Array.Empty(); - volumes.Last().Comment = ReaderOptions.ArchiveEncoding.Decode(bytes); + vols.Last().Comment = ReaderOptions.ArchiveEncoding.Decode(bytes); yield break; } } @@ -282,7 +280,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, entryStream, entry.LastModifiedTime); + writer.Write(entry.Key.NotNull("Entry Key is null"), entryStream, entry.LastModifiedTime); } } diff --git a/src/SharpCompress/Common/GZip/GZipEntry.cs b/src/SharpCompress/Common/GZip/GZipEntry.cs index bd341d24..9a551d07 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.AsEnumerable(); + internal override IEnumerable Parts => _filePart.Empty(); internal static IEnumerable GetEntries(Stream stream, OptionsBase options) { diff --git a/src/SharpCompress/Common/GZip/GZipVolume.cs b/src/SharpCompress/Common/GZip/GZipVolume.cs index 0dd9b8d9..9cfdb82d 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 = 0) + 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/Rar/RarEntry.cs b/src/SharpCompress/Common/Rar/RarEntry.cs index 30de1037..a064c2f8 100644 --- a/src/SharpCompress/Common/Rar/RarEntry.cs +++ b/src/SharpCompress/Common/Rar/RarEntry.cs @@ -25,7 +25,7 @@ public abstract class RarEntry : Entry /// /// 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; diff --git a/src/SharpCompress/Common/SevenZip/SevenZipEntry.cs b/src/SharpCompress/Common/SevenZip/SevenZipEntry.cs index 66170ba8..fbcb3d00 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/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index a59b74f6..94fdaf92 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Buffers.Binary; using System.IO; @@ -13,8 +11,8 @@ internal sealed class TarHeader 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; } @@ -22,7 +20,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; @@ -36,7 +34,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); + var nameByteCount = ArchiveEncoding.GetEncoding().GetByteCount(Name.NotNull("Name is null")); if (nameByteCount > 100) { // Set mock filename and filetype to indicate the next block is the actual name of the file @@ -46,7 +44,7 @@ internal sealed class TarHeader } else { - WriteStringBytes(ArchiveEncoding.Encode(Name), buffer, 100); + WriteStringBytes(ArchiveEncoding.Encode(Name.NotNull("Name is null")), buffer, 100); WriteOctalBytes(Size, buffer, 124, 12); var time = (long)(LastModifiedTime.ToUniversalTime() - EPOCH).TotalSeconds; WriteOctalBytes(time, buffer, 136, 12); @@ -77,7 +75,7 @@ internal sealed class TarHeader // // and then infinite recursion is occured in WriteLongFilenameHeader because truncated.Length is 102. Name = ArchiveEncoding.Decode( - ArchiveEncoding.Encode(Name), + ArchiveEncoding.Encode(Name.NotNull("Name is null")), 0, 100 - ArchiveEncoding.GetEncoding().GetMaxByteCount(1) ); @@ -87,7 +85,7 @@ internal sealed class TarHeader private void WriteLongFilenameHeader(Stream output) { - var nameBytes = ArchiveEncoding.Encode(Name); + var nameBytes = ArchiveEncoding.Encode(Name.NotNull("Name is null")); output.Write(nameBytes, 0, nameBytes.Length); // pad to multiple of BlockSize bytes, and make sure a terminating null is added @@ -323,5 +321,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 59743070..ae49e1fc 100644 --- a/src/SharpCompress/Common/Tar/TarEntry.cs +++ b/src/SharpCompress/Common/Tar/TarEntry.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using System.IO; @@ -10,9 +8,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; @@ -22,15 +20,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; + public override long CompressedSize => _filePart?.Header.Size ?? 0; - public override long Size => _filePart.Header.Size; + public override long Size => _filePart?.Header.Size ?? 0; - public override DateTime? LastModifiedTime => _filePart.Header.LastModifiedTime; + public override DateTime? LastModifiedTime => _filePart?.Header.LastModifiedTime; public override DateTime? CreatedTime => null; @@ -40,17 +38,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; + public long Mode => _filePart?.Header.Mode ?? 0; - public long UserID => _filePart.Header.UserId; + public long UserID => _filePart?.Header.UserId ?? 0; - public long GroupId => _filePart.Header.GroupId; + public long GroupId => _filePart?.Header.GroupId ?? 0; - internal override IEnumerable Parts => _filePart.AsEnumerable(); + internal override IEnumerable Parts => _filePart.Empty(); internal static IEnumerable GetEntries( StreamingMode mode, diff --git a/src/SharpCompress/Common/Tar/TarFilePart.cs b/src/SharpCompress/Common/Tar/TarFilePart.cs index bfd2fe29..88c525aa 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,7 +16,7 @@ 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() { @@ -25,7 +25,7 @@ internal sealed class TarFilePart : FilePart _seekableStream.Position = Header.DataStartPosition!.Value; return new TarReadOnlySubStream(_seekableStream, Header.Size); } - return Header.PackedStream; + return Header.PackedStream.NotNull(); } internal override Stream? GetRawStream() => null; diff --git a/src/SharpCompress/Common/Volume.cs b/src/SharpCompress/Common/Volume.cs index a29dab75..7be161ec 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; - if (readerOptions.LeaveStreamOpen) + ReaderOptions = readerOptions ?? new ReaderOptions(); + if (ReaderOptions.LeaveStreamOpen) { stream = NonDisposingStream.Create(stream); } diff --git a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs index edba3ebe..0570bf6d 100644 --- a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs +++ b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Buffers.Binary; using System.Collections.Generic; @@ -20,21 +18,21 @@ internal abstract class ZipFileEntry : ZipHeader { get { - if (Name.EndsWith('/')) + if (Name?.EndsWith('/') ?? false) { return true; } //.NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers - return CompressedSize == 0 && UncompressedSize == 0 && Name.EndsWith('\\'); + return CompressedSize == 0 && UncompressedSize == 0 && (Name?.EndsWith('\\') ?? false); } } - 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; } @@ -48,7 +46,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) { @@ -65,7 +63,7 @@ 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. @@ -119,7 +117,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/StreamingZipFilePart.cs b/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs index 1cd1f61f..97e44b6b 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; + protected override Stream CreateBaseStream() => Header.PackedStream.NotNull(); internal override Stream GetCompressedStream() { diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 68817d27..c0af5408 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -42,6 +42,10 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory ) ) { + if (_lastEntryHeader.Part is null) + { + continue; + } reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation( ref rewindableStream ); diff --git a/src/SharpCompress/Common/Zip/ZipEntry.cs b/src/SharpCompress/Common/Zip/ZipEntry.cs index 80e33360..66d19dcc 100644 --- a/src/SharpCompress/Common/Zip/ZipEntry.cs +++ b/src/SharpCompress/Common/Zip/ZipEntry.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using SharpCompress.Common.Zip.Headers; @@ -8,22 +6,23 @@ 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 ); - } } public override CompressionType CompressionType => - _filePart.Header.CompressionMethod switch + _filePart?.Header.CompressionMethod switch { ZipCompressionMethod.BZip2 => CompressionType.BZip2, ZipCompressionMethod.Deflate => CompressionType.Deflate, @@ -35,15 +34,15 @@ public class ZipEntry : Entry _ => CompressionType.Unknown }; - public override long Crc => _filePart.Header.Crc; + 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; + public override string? LinkTarget => null; - public override long CompressedSize => _filePart.Header.CompressedSize; + public override long CompressedSize => _filePart?.Header.CompressedSize ?? 0; - public override long Size => _filePart.Header.UncompressedSize; + public override long Size => _filePart?.Header.UncompressedSize ?? 0; public override DateTime? LastModifiedTime { get; } @@ -54,11 +53,11 @@ public class ZipEntry : Entry public override DateTime? ArchivedTime => null; public override bool IsEncrypted => - FlagUtility.HasFlag(_filePart.Header.Flags, HeaderFlags.Encrypted); + FlagUtility.HasFlag(_filePart?.Header.Flags ?? HeaderFlags.None, HeaderFlags.Encrypted); - public override bool IsDirectory => _filePart.Header.IsDirectory; + public override bool IsDirectory => _filePart?.Header.IsDirectory ?? false; public override bool IsSplitAfter => false; - internal override IEnumerable Parts => _filePart.AsEnumerable(); + internal override IEnumerable Parts => _filePart.Empty(); } diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index f8a0e8a8..e8516150 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -29,7 +29,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() { diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 74f6037a..1dbff914 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -2,6 +2,7 @@ using System; using System.Buffers; using System.Collections.Generic; using System.IO; +using System.Linq; using SharpCompress.Readers; namespace SharpCompress; @@ -25,6 +26,22 @@ public static class Utility } return item; } + public static IEnumerable Empty(this IEnumerable? item) where T : class + { + if (item is null) + { + return Enumerable.Empty(); + } + return item; + } + public static IEnumerable Empty(this T? item) where T : class + { + if (item is null) + { + return Enumerable.Empty(); + } + return item.AsEnumerable(); + } public static ReadOnlyCollection ToReadOnly(this ICollection items) => new(items); /// diff --git a/src/SharpCompress/Writers/AbstractWriter.cs b/src/SharpCompress/Writers/AbstractWriter.cs index 209c49f7..1820c986 100644 --- a/src/SharpCompress/Writers/AbstractWriter.cs +++ b/src/SharpCompress/Writers/AbstractWriter.cs @@ -1,28 +1,24 @@ -#nullable disable - -using System; +using System; using System.IO; using SharpCompress.Common; namespace SharpCompress.Writers; -public abstract class AbstractWriter : IWriter +#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 { private bool _isDisposed; - protected AbstractWriter(ArchiveType type, WriterOptions writerOptions) - { - WriterType = type; - WriterOptions = writerOptions; - } + //always initializes the stream - protected void InitalizeStream(Stream stream) => OutputStream = stream; + protected void InitializeStream(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; } + public ArchiveType WriterType { get; } = type; - protected WriterOptions WriterOptions { get; } + protected WriterOptions WriterOptions { get; } = writerOptions; 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 5c990a7d..a94a7238 100644 --- a/src/SharpCompress/Writers/GZip/GZipWriter.cs +++ b/src/SharpCompress/Writers/GZip/GZipWriter.cs @@ -18,14 +18,14 @@ public sealed class GZipWriter : AbstractWriter { destination = NonDisposingStream.Create(destination); } - InitalizeStream( - new GZipStream( - destination, - CompressionMode.Compress, - options?.CompressionLevel ?? CompressionLevel.Default, - WriterOptions.ArchiveEncoding.GetEncoding() - ) - ); + InitializeStream( + new GZipStream( + destination, + CompressionMode.Compress, + options?.CompressionLevel ?? CompressionLevel.Default, + WriterOptions.ArchiveEncoding.GetEncoding() + ) + ); } protected override void Dispose(bool isDisposing) diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 90242857..3826b4bb 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -56,7 +56,7 @@ public class TarWriter : AbstractWriter ); } } - InitalizeStream(destination); + InitializeStream(destination); } public override void Write(string filename, Stream source, DateTime? modificationTime) => diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index 9dc094e2..440b210d 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -42,14 +42,14 @@ public class ZipWriter : AbstractWriter { destination = NonDisposingStream.Create(destination); } - InitalizeStream(destination); + InitializeStream(destination); } private PpmdProperties PpmdProperties => ppmdProps ??= new PpmdProperties(); protected override void Dispose(bool isDisposing) { - if (isDisposing) + if (isDisposing && OutputStream is not null) { ulong size = 0; foreach (var entry in entries) @@ -114,7 +114,7 @@ public class ZipWriter : AbstractWriter streamPosition += headersize; return new ZipWritingStream( this, - OutputStream, + OutputStream.NotNull(), entry, compression, options.DeflateCompressionLevel ?? compressionLevel diff --git a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs index a0c9d8c9..32d978a2 100644 --- a/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs +++ b/tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs @@ -182,7 +182,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)); + entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull())); var size = entry.Size; var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "7Zip.Tar.tar")); diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index 1ee6b783..bbf96c00 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -195,7 +195,7 @@ public class TarArchiveTests : ArchiveTests using (var archive = TarArchive.Open(unmodified)) { var entry = archive.Entries.Single(x => - x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ); archive.RemoveEntry(entry); archive.SaveTo(scratchPath, CompressionType.None); diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index 1ee4ae8d..bb10db98 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -79,7 +79,7 @@ public class TarReaderTests : ReaderTests { Directory.CreateDirectory(destdir); } - var destinationFileName = Path.Combine(destdir, file); + var destinationFileName = Path.Combine(destdir, file.NotNull()); using var fs = File.OpenWrite(destinationFileName); entryStream.TransferTo(fs); @@ -105,7 +105,7 @@ public class TarReaderTests : ReaderTests { if (!reader.Entry.IsDirectory) { - filePaths.Add(reader.Entry.Key); + filePaths.Add(reader.Entry.Key.NotNull("Entry Key is null")); } } } @@ -135,7 +135,7 @@ public class TarReaderTests : ReaderTests Assert.Equal(CompressionType.BZip2, reader.Entry.CompressionType); using var entryStream = reader.OpenEntryStream(); entryStream.SkipEntry(); - names.Add(reader.Entry.Key); + names.Add(reader.Entry.Key.NotNull()); } } Assert.Equal(3, names.Count); @@ -224,7 +224,7 @@ public class TarReaderTests : ReaderTests { if (reader.Entry.LinkTarget != null) { - var path = Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key); + var path = Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key.NotNull()); var link = new Mono.Unix.UnixSymbolicLinkInfo(path); if (link.HasContents) { diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index afbe7c9e..b6e46d4a 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -193,7 +193,7 @@ public class ZipArchiveTests : ArchiveTests using (var archive = ZipArchive.Open(unmodified)) { var entry = archive.Entries.Single(x => - x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ); archive.RemoveEntry(entry); @@ -249,11 +249,11 @@ public class ZipArchiveTests : ArchiveTests var 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.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)); + var e = vfs.Entries.First(v => v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase)); vfs.RemoveEntry(e); Assert.Null( vfs.Entries.FirstOrDefault(v => - v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); Assert.Null( @@ -394,12 +394,12 @@ public class ZipArchiveTests : ArchiveTests archive.AddAllFromDirectory(SCRATCH_FILES_PATH); archive.RemoveEntry( archive.Entries.Single(x => - x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); Assert.Null( archive.Entries.FirstOrDefault(x => - x.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + x.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ) ); } From b550df20380c3b9cd8f81b685255d8ce10e26ba5 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 22 Apr 2024 14:17:08 +0100 Subject: [PATCH 0066/1333] get rid of more ! and update csharpier --- .config/dotnet-tools.json | 2 +- src/SharpCompress/Archives/AbstractArchive.cs | 1 - .../Archives/GZip/GZipArchive.cs | 6 +- src/SharpCompress/Archives/Rar/RarArchive.cs | 2 +- .../Archives/SevenZip/SevenZipArchive.cs | 10 ++- src/SharpCompress/Archives/Tar/TarArchive.cs | 7 ++- src/SharpCompress/Archives/Zip/ZipArchive.cs | 9 ++- src/SharpCompress/Common/ExtractionMethods.cs | 3 +- .../Common/Rar/Headers/FileHeader.cs | 6 -- .../Common/Rar/Headers/RarHeaderFactory.cs | 6 -- src/SharpCompress/Common/Rar/RarVolume.cs | 4 -- .../Common/SevenZip/SevenZipFilePart.cs | 9 +-- .../Common/Tar/Headers/TarHeader.cs | 4 +- src/SharpCompress/Common/Tar/TarFilePart.cs | 2 +- .../Common/Tar/TarHeaderFactory.cs | 2 - .../Common/Zip/SeekableZipFilePart.cs | 8 +-- src/SharpCompress/Common/Zip/ZipEntry.cs | 10 +-- .../Common/Zip/ZipHeaderFactory.cs | 8 ++- .../Compressors/LZMA/LZipStream.cs | 8 +-- .../Rar/UnpackV2017/Unpack.unpack50_cpp.cs | 2 - src/SharpCompress/Compressors/Rar/VM/RarVM.cs | 28 --------- src/SharpCompress/NotNullExtensions.cs | 63 +++++++++++++++++++ src/SharpCompress/Readers/AbstractReader.cs | 44 ++++++------- src/SharpCompress/Readers/Rar/RarReader.cs | 4 +- src/SharpCompress/Readers/Zip/ZipReader.cs | 1 - src/SharpCompress/Utility.cs | 33 ---------- src/SharpCompress/Writers/GZip/GZipWriter.cs | 14 ++--- src/SharpCompress/Writers/Tar/TarWriter.cs | 3 - src/SharpCompress/Writers/Zip/ZipWriter.cs | 13 ++-- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 4 +- 30 files changed, 163 insertions(+), 153 deletions(-) create mode 100644 src/SharpCompress/NotNullExtensions.cs diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index a4713c52..00b1a064 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "csharpier": { - "version": "0.27.3", + "version": "0.28.1", "commands": [ "dotnet-csharpier" ] diff --git a/src/SharpCompress/Archives/AbstractArchive.cs b/src/SharpCompress/Archives/AbstractArchive.cs index 3975a0d4..a757dd47 100644 --- a/src/SharpCompress/Archives/AbstractArchive.cs +++ b/src/SharpCompress/Archives/AbstractArchive.cs @@ -43,7 +43,6 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra lazyEntries = new LazyReadOnlyCollection(Enumerable.Empty()); } - public ArchiveType Type { get; } void IArchiveExtractionListener.FireEntryExtractionBegin(IArchiveEntry entry) => diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index 88247222..976bd70f 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -184,7 +184,11 @@ 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.NotNull("Entry Key is null"), + entryStream, + entry.LastModifiedTime + ); } } diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index b6a7c02b..0e28529a 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -32,7 +32,7 @@ public class RarArchive : AbstractArchive protected override IEnumerable LoadVolumes(SourceStream srcStream) { var sourceStream = SrcStream.NotNull("SourceStream is null"); - sourceStream .LoadAllParts(); //request all streams + sourceStream.LoadAllParts(); //request all streams var streams = sourceStream.Streams.ToArray(); var idx = 0; if (streams.Length > 1 && IsRarFile(streams[1], ReaderOptions)) //test part 2 - true = multipart not split diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index b41f4cf6..b3120b1b 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -197,7 +197,8 @@ 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 => + database?._packSizes.Aggregate(0L, (total, packSize) => total + packSize) ?? 0; private sealed class SevenZipReader : AbstractReader { @@ -245,7 +246,12 @@ public class SevenZipArchive : AbstractArchive - CreateEntryStream(new ReadOnlySubStream(currentStream.NotNull("currentStream is not null"), currentItem?.Size ?? 0)); + CreateEntryStream( + new ReadOnlySubStream( + currentStream.NotNull("currentStream is not null"), + currentItem?.Size ?? 0 + ) + ); } private class PasswordProvider : IPasswordProvider diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index d1f8cc1d..c3c58534 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -224,7 +224,12 @@ 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.NotNull("Entry Key is null"), + entryStream, + entry.LastModifiedTime, + entry.Size + ); } } diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index 2d243d42..18e0e233 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -194,7 +194,7 @@ public class ZipArchive : AbstractWritableArchive var streams = stream.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); @@ -229,7 +229,6 @@ public class ZipArchive : AbstractWritableArchive switch (h.ZipHeaderType) { case ZipHeaderType.DirectoryEntry: - { var deh = (DirectoryEntryHeader)h; Stream s; @@ -280,7 +279,11 @@ 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.NotNull("Entry Key is null"), + entryStream, + entry.LastModifiedTime + ); } } diff --git a/src/SharpCompress/Common/ExtractionMethods.cs b/src/SharpCompress/Common/ExtractionMethods.cs index 4a24ad9e..27d41648 100644 --- a/src/SharpCompress/Common/ExtractionMethods.cs +++ b/src/SharpCompress/Common/ExtractionMethods.cs @@ -39,7 +39,8 @@ internal static class ExtractionMethods var file = Path.GetFileName(entry.Key.NotNull("Entry Key is null")).NotNull("File is null"); if (options.ExtractFullPath) { - var folder = Path.GetDirectoryName(entry.Key.NotNull("Entry Key is null")).NotNull("Directory is null"); + var folder = Path.GetDirectoryName(entry.Key.NotNull("Entry Key is null")) + .NotNull("Directory is null"); var destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder)); if (!Directory.Exists(destdir)) diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index 86b56055..eea8293d 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -121,7 +121,6 @@ internal class FileHeader : RarHeader switch (type) { case FHEXTRA_CRYPT: // file encryption - { Rar5CryptoInfo = new Rar5CryptoInfo(reader, true); @@ -132,7 +131,6 @@ internal class FileHeader : RarHeader } break; case FHEXTRA_HASH: - { const uint FHEXTRA_HASH_BLAKE2 = 0x0; // const uint HASH_BLAKE2 = 0x03; @@ -146,7 +144,6 @@ internal class FileHeader : RarHeader } break; case FHEXTRA_HTIME: // file time - { var flags = reader.ReadRarVIntUInt16(); var isWindowsTime = (flags & 1) == 0; @@ -171,7 +168,6 @@ internal class FileHeader : RarHeader // } // break; case FHEXTRA_REDIR: // file system redirection - { RedirType = reader.ReadRarVIntByte(); RedirFlags = reader.ReadRarVIntByte(); @@ -284,7 +280,6 @@ internal class FileHeader : RarHeader switch (HeaderCode) { case HeaderCodeV.RAR4_FILE_HEADER: - { if (HasFlag(FileFlagsV4.UNICODE)) { @@ -311,7 +306,6 @@ internal class FileHeader : RarHeader } break; case HeaderCodeV.RAR4_NEW_SUB_HEADER: - { var datasize = HeaderSize - newLhdSize - nameSize; if (HasFlag(FileFlagsV4.SALT)) diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index e38cb629..74d68fc7 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -98,13 +98,11 @@ public class RarHeaderFactory switch (StreamingMode) { case StreamingMode.Seekable: - { reader.BaseStream.Position += ph.DataSize; } break; case StreamingMode.Streaming: - { reader.BaseStream.Skip(ph.DataSize); } @@ -146,14 +144,12 @@ 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) @@ -204,14 +200,12 @@ 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/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index da42ff24..2f497a04 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -39,19 +39,16 @@ 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) @@ -63,7 +60,6 @@ public abstract class RarVolume : Volume } break; case HeaderType.Service: - { var fh = (FileHeader)header; if (fh.FileName == "CMT") diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index aad191c9..6365676d 100644 --- a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs +++ b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs @@ -76,9 +76,11 @@ internal class SevenZipFilePart : FilePart internal CompressionType GetCompression() { if (Header.IsDir) + { return CompressionType.None; + } - var coder = Folder!._coders.First(); + var coder = Folder.NotNull()._coders.First(); switch (coder._methodId._id) { case K_LZMA: @@ -100,7 +102,6 @@ internal class SevenZipFilePart : FilePart } internal bool IsEncrypted => - Header.IsDir - ? false - : Folder!._coders.FindIndex(c => c._methodId._id == CMethodId.K_AES_ID) != -1; + !Header.IsDir + && 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 94fdaf92..68a72e8a 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -34,7 +34,9 @@ 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.NotNull("Name is null")); if (nameByteCount > 100) { // Set mock filename and filetype to indicate the next block is the actual name of the file diff --git a/src/SharpCompress/Common/Tar/TarFilePart.cs b/src/SharpCompress/Common/Tar/TarFilePart.cs index 88c525aa..06516114 100644 --- a/src/SharpCompress/Common/Tar/TarFilePart.cs +++ b/src/SharpCompress/Common/Tar/TarFilePart.cs @@ -22,7 +22,7 @@ internal sealed class TarFilePart : FilePart { if (_seekableStream != null) { - _seekableStream.Position = Header.DataStartPosition!.Value; + _seekableStream.Position = Header.DataStartPosition ?? 0; return new TarReadOnlySubStream(_seekableStream, Header.Size); } return Header.PackedStream.NotNull(); diff --git a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs index 85eec5b4..13813353 100644 --- a/src/SharpCompress/Common/Tar/TarHeaderFactory.cs +++ b/src/SharpCompress/Common/Tar/TarHeaderFactory.cs @@ -28,7 +28,6 @@ internal static class TarHeaderFactory switch (mode) { case StreamingMode.Seekable: - { header.DataStartPosition = reader.BaseStream.Position; @@ -37,7 +36,6 @@ internal static class TarHeaderFactory } break; case StreamingMode.Streaming: - { header.PackedStream = new TarReadOnlySubStream(stream, header.Size); } diff --git a/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs b/src/SharpCompress/Common/Zip/SeekableZipFilePart.cs index 63fdc933..e37008e5 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!.Value; + BaseStream.Position = Header.DataStartPosition.NotNull(); if ( (Header.CompressedSize == 0) && FlagUtility.HasFlag(Header.Flags, HeaderFlags.UsePostDataDescriptor) - && (_directoryEntryHeader?.HasData == true) - && (_directoryEntryHeader?.CompressedSize != 0) + && _directoryEntryHeader.HasData + && (_directoryEntryHeader.CompressedSize != 0) ) { - return new ReadOnlySubStream(BaseStream, _directoryEntryHeader!.CompressedSize); + return new ReadOnlySubStream(BaseStream, _directoryEntryHeader.CompressedSize); } return BaseStream; diff --git a/src/SharpCompress/Common/Zip/ZipEntry.cs b/src/SharpCompress/Common/Zip/ZipEntry.cs index 66d19dcc..c2cecf39 100644 --- a/src/SharpCompress/Common/Zip/ZipEntry.cs +++ b/src/SharpCompress/Common/Zip/ZipEntry.cs @@ -14,11 +14,11 @@ public class ZipEntry : Entry { 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 => diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 628cbb20..40fe178f 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -55,7 +55,13 @@ internal class ZipHeaderFactory } case POST_DATA_DESCRIPTOR: { - if (FlagUtility.HasFlag(_lastEntryHeader!.Flags, HeaderFlags.UsePostDataDescriptor)) + if ( + FlagUtility.HasFlag( + _lastEntryHeader.NotNull().Flags, + HeaderFlags.UsePostDataDescriptor + ) + && _lastEntryHeader != null + ) { _lastEntryHeader.Crc = reader.ReadUInt32(); _lastEntryHeader.CompressedSize = zip64 diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.cs index 4b63a621..5e987214 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!.Count; + var compressedCount = _countingWritableSubStream.NotNull().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/Rar/UnpackV2017/Unpack.unpack50_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs index 62567888..143e3d31 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs @@ -530,7 +530,6 @@ internal partial class Unpack { case FILTER_E8: case FILTER_E8E9: - { var FileOffset = (uint)WrittenFileSize; @@ -569,7 +568,6 @@ 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" diff --git a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs index 185b24d4..f758b8a4 100644 --- a/src/SharpCompress/Compressors/Rar/VM/RarVM.cs +++ b/src/SharpCompress/Compressors/Rar/VM/RarVM.cs @@ -228,7 +228,6 @@ 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); @@ -247,7 +246,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_CMPB: - { var value1 = (VMFlags)GetValue(true, Mem, op1); var result = value1 - GetValue(true, Mem, op2); @@ -265,7 +263,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_CMPD: - { var value1 = (VMFlags)GetValue(false, Mem, op1); var result = value1 - GetValue(false, Mem, op2); @@ -283,7 +280,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_ADD: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var result = (int)( @@ -351,7 +347,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SUB: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var result = (int)( @@ -411,7 +406,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_INC: - { var result = (int)(GetValue(cmd.IsByteMode, Mem, op1) & (0xFFffFFffL + 1L)); if (cmd.IsByteMode) @@ -440,7 +434,6 @@ 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); @@ -463,7 +456,6 @@ internal sealed class RarVM : BitInput continue; case VMCommands.VM_XOR: - { var result = GetValue(cmd.IsByteMode, Mem, op1) ^ GetValue(cmd.IsByteMode, Mem, op2); @@ -475,7 +467,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_AND: - { var result = GetValue(cmd.IsByteMode, Mem, op1) & GetValue(cmd.IsByteMode, Mem, op2); @@ -487,7 +478,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_OR: - { var result = GetValue(cmd.IsByteMode, Mem, op1) | GetValue(cmd.IsByteMode, Mem, op2); @@ -499,7 +489,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_TEST: - { var result = GetValue(cmd.IsByteMode, Mem, op1) & GetValue(cmd.IsByteMode, Mem, op2); @@ -578,7 +567,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SHL: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -596,7 +584,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SHR: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -610,7 +597,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SAR: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var value2 = GetValue(cmd.IsByteMode, Mem, op2); @@ -624,7 +610,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_NEG: - { var result = -GetValue(cmd.IsByteMode, Mem, op1); flags = (VMFlags)( @@ -645,7 +630,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_PUSHA: - { for (int i = 0, SP = R[7] - 4; i < regCount; i++, SP -= 4) { @@ -656,7 +640,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_POPA: - { for (int i = 0, SP = R[7]; i < regCount; i++, SP += 4) { @@ -684,7 +667,6 @@ 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)); @@ -693,7 +675,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_MUL: - { var result = (int)( ( @@ -707,7 +688,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_DIV: - { var divider = GetValue(cmd.IsByteMode, Mem, op2); if (divider != 0) @@ -719,7 +699,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_ADC: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var FC = (int)(flags & VMFlags.VM_FC); @@ -749,7 +728,6 @@ internal sealed class RarVM : BitInput break; case VMCommands.VM_SBB: - { var value1 = GetValue(cmd.IsByteMode, Mem, op1); var FC = (int)(flags & VMFlags.VM_FC); @@ -1156,7 +1134,6 @@ internal sealed class RarVM : BitInput { case VMStandardFilters.VMSF_E8: case VMStandardFilters.VMSF_E8E9: - { var dataSize = R[4]; long fileOffset = R[6] & unchecked((int)0xFFffFFff); @@ -1211,7 +1188,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_ITANIUM: - { var dataSize = R[4]; long fileOffset = R[6] & unchecked((int)0xFFffFFff); @@ -1269,7 +1245,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_DELTA: - { var dataSize = R[4] & unchecked((int)0xFFffFFff); var channels = R[0] & unchecked((int)0xFFffFFff); @@ -1300,7 +1275,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_RGB: - { // byte *SrcData=Mem,*DestData=SrcData+DataSize; int dataSize = R[4], @@ -1366,7 +1340,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_AUDIO: - { int dataSize = R[4], channels = R[0]; @@ -1497,7 +1470,6 @@ internal sealed class RarVM : BitInput break; case VMStandardFilters.VMSF_UPCASE: - { int dataSize = R[4], srcPos = 0, diff --git a/src/SharpCompress/NotNullExtensions.cs b/src/SharpCompress/NotNullExtensions.cs new file mode 100644 index 00000000..d2ba87a3 --- /dev/null +++ b/src/SharpCompress/NotNullExtensions.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +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 a0d982f1..b36acd53 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; @@ -40,13 +40,13 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// /// Current file entry /// - public TEntry Entry => entriesForCurrentReadStream!.Current; + public TEntry Entry => _entriesForCurrentReadStream.NotNull().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,7 +69,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti public bool MoveToNextEntry() { - if (completed) + if (_completed) { return false; } @@ -77,27 +77,27 @@ public abstract class AbstractReader : IReader, IReaderExtracti { throw new ReaderCancelledException("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,13 +105,15 @@ 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.NotNull("Volume isn't loaded.").Stream; - internal virtual bool NextEntryForCurrentStream() => entriesForCurrentReadStream!.MoveNext(); + internal virtual bool NextEntryForCurrentStream() => + _entriesForCurrentReadStream.NotNull().MoveNext(); protected abstract IEnumerable GetEntries(Stream stream); @@ -149,7 +151,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."); } @@ -166,7 +168,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti } Write(writableStream); - wroteCurrentEntry = true; + _wroteCurrentEntry = true; } internal void Write(Stream writeStream) @@ -178,12 +180,12 @@ 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; } diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index f092699d..daba2bfd 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -19,9 +19,7 @@ public abstract class RarReader : AbstractReader internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); internal RarReader(ReaderOptions options) - : base(options, ArchiveType.Rar) - { - } + : base(options, ArchiveType.Rar) { } internal abstract void ValidateArchive(RarVolume archive); diff --git a/src/SharpCompress/Readers/Zip/ZipReader.cs b/src/SharpCompress/Readers/Zip/ZipReader.cs index b00690f0..cda3f3f8 100644 --- a/src/SharpCompress/Readers/Zip/ZipReader.cs +++ b/src/SharpCompress/Readers/Zip/ZipReader.cs @@ -69,7 +69,6 @@ public class ZipReader : AbstractReader switch (h.ZipHeaderType) { case ZipHeaderType.LocalEntry: - { yield return new ZipEntry( new StreamingZipFilePart((LocalEntryHeader)h, stream) diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 1dbff914..bcecafb4 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -2,7 +2,6 @@ using System; using System.Buffers; using System.Collections.Generic; using System.IO; -using System.Linq; using SharpCompress.Readers; namespace SharpCompress; @@ -10,38 +9,6 @@ namespace SharpCompress; [CLSCompliant(false)] public static class Utility { - public static T NotNull(this T? item, string message) where T : class - { - if (item is null) - { - throw new InvalidOperationException(message); - } - return item; - } - public static T NotNull(this T? item) where T : class - { - if (item is null) - { - throw new InvalidOperationException("Item is null"); - } - return item; - } - public static IEnumerable Empty(this IEnumerable? item) where T : class - { - if (item is null) - { - return Enumerable.Empty(); - } - return item; - } - public static IEnumerable Empty(this T? item) where T : class - { - if (item is null) - { - return Enumerable.Empty(); - } - return item.AsEnumerable(); - } public static ReadOnlyCollection ToReadOnly(this ICollection items) => new(items); /// diff --git a/src/SharpCompress/Writers/GZip/GZipWriter.cs b/src/SharpCompress/Writers/GZip/GZipWriter.cs index a94a7238..f30fdb55 100644 --- a/src/SharpCompress/Writers/GZip/GZipWriter.cs +++ b/src/SharpCompress/Writers/GZip/GZipWriter.cs @@ -19,13 +19,13 @@ public sealed class GZipWriter : AbstractWriter destination = NonDisposingStream.Create(destination); } InitializeStream( - new GZipStream( - destination, - CompressionMode.Compress, - options?.CompressionLevel ?? CompressionLevel.Default, - WriterOptions.ArchiveEncoding.GetEncoding() - ) - ); + new GZipStream( + destination, + CompressionMode.Compress, + options?.CompressionLevel ?? CompressionLevel.Default, + WriterOptions.ArchiveEncoding.GetEncoding() + ) + ); } protected override void Dispose(bool isDisposing) diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 3826b4bb..a3e572f1 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -32,19 +32,16 @@ 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); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index 440b210d..1fb66a2b 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -419,13 +419,14 @@ public class ZipWriter : AbstractWriter return; } + var countingCount = counting?.Count ?? 0; entry.Crc = (uint)crc.Crc32Result; - entry.Compressed = counting!.Count; + entry.Compressed = countingCount; entry.Decompressed = decompressed; var zip64 = entry.Compressed >= uint.MaxValue || entry.Decompressed >= uint.MaxValue; - var compressedvalue = zip64 ? uint.MaxValue : (uint)counting.Count; + var compressedvalue = zip64 ? uint.MaxValue : (uint)countingCount; var decompressedvalue = zip64 ? uint.MaxValue : (uint)entry.Decompressed; if (originalStream.CanSeek) @@ -433,7 +434,7 @@ public class ZipWriter : AbstractWriter originalStream.Position = (long)(entry.HeaderOffset + 6); originalStream.WriteByte(0); - if (counting.Count == 0 && entry.Decompressed == 0) + if (countingCount == 0 && entry.Decompressed == 0) { // set compression to STORED for zero byte files (no compression data) originalStream.Position = (long)(entry.HeaderOffset + 8); @@ -520,11 +521,12 @@ 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) - || (counting!.Count + (uint)count) > uint.MaxValue + || (countingCount + (uint)count) > uint.MaxValue ) { throw new NotSupportedException( @@ -539,8 +541,9 @@ public class ZipWriter : AbstractWriter if (entry.Zip64HeaderOffset == 0) { + var countingCount = counting?.Count ?? 0; // Post-check, this is accurate - if ((decompressed > uint.MaxValue) || counting!.Count > uint.MaxValue) + if ((decompressed > uint.MaxValue) || countingCount > uint.MaxValue) { // We have written the data, so the archive is now broken // Throwing the exception here, allows us to avoid diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index b6e46d4a..2e12b1ff 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -249,7 +249,9 @@ public class ZipArchiveTests : ArchiveTests var 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)); + var e = vfs.Entries.First(v => + v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase) + ); vfs.RemoveEntry(e); Assert.Null( vfs.Entries.FirstOrDefault(v => From 7963233702a07af04d7d93f2616699290e019ade Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 22 Apr 2024 14:18:41 +0100 Subject: [PATCH 0067/1333] add missing usings --- src/SharpCompress/NotNullExtensions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SharpCompress/NotNullExtensions.cs b/src/SharpCompress/NotNullExtensions.cs index d2ba87a3..88e95c41 100644 --- a/src/SharpCompress/NotNullExtensions.cs +++ b/src/SharpCompress/NotNullExtensions.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Runtime.CompilerServices; namespace SharpCompress; From f24bfdf945c6f16885a89bd83196e51efa8f3e9d Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 22 Apr 2024 14:57:08 +0100 Subject: [PATCH 0068/1333] fix tests --- src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs | 6 +++--- src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs | 7 ++++--- .../Compressors/LZMA/Utilites/IPasswordProvider.cs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index b3120b1b..3f419541 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -130,12 +130,12 @@ public class SevenZipArchive : AbstractArchive volumes ) { + var stream = volumes.Single().Stream; + LoadFactory(stream); if (database is null) { return Enumerable.Empty(); } - var stream = volumes.Single().Stream; - LoadFactory(stream); var entries = new SevenZipArchiveEntry[database._files.Count]; for (var i = 0; i < database._files.Count; i++) { @@ -260,6 +260,6 @@ public class SevenZipArchive : AbstractArchive _password = password; - public string CryptoGetTextPassword() => _password.NotNull(); + public string? CryptoGetTextPassword() => _password; } } diff --git a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs index 8e884c97..ecec4f29 100644 --- a/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs +++ b/src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs @@ -20,7 +20,8 @@ internal sealed class AesDecoderStream : DecoderStream2 public AesDecoderStream(Stream input, byte[] info, IPasswordProvider pass, long limit) { - if (pass.CryptoGetTextPassword() == null) + var password = pass.CryptoGetTextPassword(); + if (password == null) { throw new SharpCompress.Common.CryptographicException( "Encrypted 7Zip archive has no password specified." @@ -37,8 +38,8 @@ internal sealed class AesDecoderStream : DecoderStream2 Init(info, out var numCyclesPower, out var salt, out var seed); - var password = Encoding.Unicode.GetBytes(pass.CryptoGetTextPassword()); - var key = InitKey(numCyclesPower, salt, password); + var passwordBytes = Encoding.Unicode.GetBytes(password); + var key = InitKey(numCyclesPower, salt, passwordBytes); if (key == null) { throw new InvalidOperationException("Initialized with null key"); diff --git a/src/SharpCompress/Compressors/LZMA/Utilites/IPasswordProvider.cs b/src/SharpCompress/Compressors/LZMA/Utilites/IPasswordProvider.cs index 2f0eb904..d7d787d2 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(); } From 99e2c8c90d44d59681a0004645ca147fe4c820ba Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 22 Apr 2024 15:10:22 +0100 Subject: [PATCH 0069/1333] more clean up --- src/SharpCompress/Archives/AbstractArchive.cs | 46 +++++++------ .../Archives/AbstractWritableArchive.cs | 4 +- .../Archives/GZip/GZipArchive.cs | 13 ++-- src/SharpCompress/Archives/Rar/RarArchive.cs | 20 +++--- .../Archives/SevenZip/SevenZipArchive.cs | 65 +++++++++---------- src/SharpCompress/Archives/Tar/TarArchive.cs | 15 ++--- src/SharpCompress/Archives/Zip/ZipArchive.cs | 13 ++-- 7 files changed, 83 insertions(+), 93 deletions(-) diff --git a/src/SharpCompress/Archives/AbstractArchive.cs b/src/SharpCompress/Archives/AbstractArchive.cs index a757dd47..df54d781 100644 --- a/src/SharpCompress/Archives/AbstractArchive.cs +++ b/src/SharpCompress/Archives/AbstractArchive.cs @@ -12,35 +12,33 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra where TEntry : IArchiveEntry where TVolume : IVolume { - private readonly LazyReadOnlyCollection lazyVolumes; - private readonly LazyReadOnlyCollection lazyEntries; + private readonly LazyReadOnlyCollection _lazyVolumes; + private readonly LazyReadOnlyCollection _lazyEntries; + private bool _disposed; + private readonly SourceStream? _sourceStream; public event EventHandler>? EntryExtractionBegin; public event EventHandler>? EntryExtractionEnd; public event EventHandler? CompressedBytesRead; public event EventHandler? FilePartExtractionBegin; - protected ReaderOptions ReaderOptions { get; } - private bool disposed; - protected SourceStream? SrcStream; - - internal AbstractArchive(ArchiveType type, SourceStream srcStream) + internal AbstractArchive(ArchiveType type, SourceStream sourceStream) { Type = type; - ReaderOptions = srcStream.ReaderOptions; - SrcStream = srcStream; - lazyVolumes = new LazyReadOnlyCollection(LoadVolumes(SrcStream)); - lazyEntries = new LazyReadOnlyCollection(LoadEntries(Volumes)); + ReaderOptions = sourceStream.ReaderOptions; + _sourceStream = sourceStream; + _lazyVolumes = new LazyReadOnlyCollection(LoadVolumes(_sourceStream)); + _lazyEntries = new LazyReadOnlyCollection(LoadEntries(Volumes)); } 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()); } public ArchiveType Type { get; } @@ -63,12 +61,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. @@ -82,29 +80,29 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra public virtual long TotalUncompressSize => Entries.Aggregate(0L, (total, cf) => total + cf.Size); - protected abstract IEnumerable LoadVolumes(SourceStream srcStream); + protected abstract IEnumerable LoadVolumes(SourceStream sourceStream); 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()); - SrcStream?.Dispose(); + _lazyVolumes.ForEach(v => v.Dispose()); + _lazyEntries.GetLoaded().Cast().ForEach(x => x.Close()); + _sourceStream?.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 ef272d9b..614489fe 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -41,8 +41,8 @@ public abstract class AbstractWritableArchive internal AbstractWritableArchive(ArchiveType type) : base(type) { } - internal AbstractWritableArchive(ArchiveType type, SourceStream srcStream) - : base(type, srcStream) { } + internal AbstractWritableArchive(ArchiveType type, SourceStream sourceStream) + : base(type, sourceStream) { } public override ICollection Entries { diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index 976bd70f..541e6d87 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -99,16 +99,15 @@ public class GZipArchive : AbstractWritableArchive /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - /// - internal GZipArchive(SourceStream srcStream) - : base(ArchiveType.Tar, srcStream) { } + /// + private GZipArchive(SourceStream sourceStream) + : base(ArchiveType.Tar, sourceStream) { } - protected override IEnumerable LoadVolumes(SourceStream srcStream) + protected override IEnumerable LoadVolumes(SourceStream sourceStream) { - srcStream.LoadAllParts(); + sourceStream.LoadAllParts(); var idx = 0; - return srcStream.Streams.Select(a => new GZipVolume(a, ReaderOptions, idx++)); + return sourceStream.Streams.Select(a => new GZipVolume(a, ReaderOptions, idx++)); } public static bool IsGZipFile(string filePath) => IsGZipFile(new FileInfo(filePath)); diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 0e28529a..a771dbec 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -21,35 +21,31 @@ public class RarArchive : AbstractArchive /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - /// - internal RarArchive(SourceStream srcStream) - : base(ArchiveType.Rar, srcStream) { } + /// + private RarArchive(SourceStream sourceStream) + : base(ArchiveType.Rar, sourceStream) { } protected override IEnumerable LoadEntries(IEnumerable volumes) => RarArchiveEntryFactory.GetEntries(this, volumes, ReaderOptions); - protected override IEnumerable LoadVolumes(SourceStream srcStream) + protected override IEnumerable LoadVolumes(SourceStream sourceStream) { - var sourceStream = SrcStream.NotNull("SourceStream is null"); sourceStream.LoadAllParts(); //request all streams var streams = sourceStream.Streams.ToArray(); - var idx = 0; if (streams.Length > 1 && IsRarFile(streams[1], ReaderOptions)) //test part 2 - true = multipart not split { sourceStream.IsVolumes = true; streams[1].Position = 0; sourceStream.Position = 0; - return srcStream.Streams.Select(a => new StreamRarArchiveVolume( + return sourceStream.Streams.Select(a => new StreamRarArchiveVolume( a, - ReaderOptions, - idx++ + ReaderOptions )); } else //split mode or single file { - return new StreamRarArchiveVolume(sourceStream, ReaderOptions, idx++).AsEnumerable(); + return new StreamRarArchiveVolume(sourceStream, ReaderOptions).AsEnumerable(); } } @@ -109,7 +105,7 @@ public class RarArchive : AbstractArchive public static RarArchive Open(Stream stream, ReaderOptions? options = null) { stream.CheckNotNull(nameof(stream)); - return new RarArchive(new SourceStream(stream, i => null, options ?? new ReaderOptions())); + return new RarArchive(new SourceStream(stream, _ => null, options ?? new ReaderOptions())); } /// diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index 3f419541..ee165982 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -12,7 +12,7 @@ namespace SharpCompress.Archives.SevenZip; public class SevenZipArchive : AbstractArchive { - private ArchiveDatabase? database; + private ArchiveDatabase? _database; /// /// Constructor expects a filepath to an existing file. @@ -93,22 +93,21 @@ public class SevenZipArchive : AbstractArchive null, readerOptions ?? new ReaderOptions()) + new SourceStream(stream, _ => null, readerOptions ?? new ReaderOptions()) ); } /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - internal SevenZipArchive(SourceStream srcStream) - : base(ArchiveType.SevenZip, srcStream) { } + /// + private SevenZipArchive(SourceStream sourceStream) + : base(ArchiveType.SevenZip, sourceStream) { } - protected override IEnumerable LoadVolumes(SourceStream srcStream) + protected override IEnumerable LoadVolumes(SourceStream sourceStream) { - SrcStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams - var idx = 0; - return new SevenZipVolume(srcStream, ReaderOptions, idx++).AsEnumerable(); //simple single volume or split, multivolume not supported + sourceStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams + return new SevenZipVolume(sourceStream, ReaderOptions, 0).AsEnumerable(); //simple single volume or split, multivolume not supported } public static bool IsSevenZipFile(string filePath) => IsSevenZipFile(new FileInfo(filePath)); @@ -132,17 +131,17 @@ public class SevenZipArchive : AbstractArchive(); } - var entries = new SevenZipArchiveEntry[database._files.Count]; - for (var i = 0; i < database._files.Count; i++) + 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)) @@ -160,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() => @@ -198,23 +197,23 @@ public class SevenZipArchive : AbstractArchive !x.IsDirectory).GroupBy(x => x.FilePart.Folder).Count() > 1; public override long TotalSize => - database?._packSizes.Aggregate(0L, (total, packSize) => total + packSize) ?? 0; + _database?._packSizes.Aggregate(0L, (total, packSize) => total + packSize) ?? 0; 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)) { @@ -224,22 +223,22 @@ 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; } } @@ -248,8 +247,8 @@ public class SevenZipArchive : AbstractArchive CreateEntryStream( new ReadOnlySubStream( - currentStream.NotNull("currentStream is not null"), - currentItem?.Size ?? 0 + _currentStream.NotNull("currentStream is not null"), + _currentItem?.Size ?? 0 ) ); } diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index c3c58534..74a3c87c 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -123,21 +123,20 @@ public class TarArchive : AbstractWritableArchive return false; } - protected override IEnumerable LoadVolumes(SourceStream srcStream) + protected override IEnumerable LoadVolumes(SourceStream sourceStream) { - SrcStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams - var idx = 0; - return new TarVolume(srcStream, ReaderOptions, idx++).AsEnumerable(); //simple single volume or split, multivolume not supported + sourceStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams + return new TarVolume(sourceStream, ReaderOptions, 0).AsEnumerable(); //simple single volume or split, multivolume not supported } /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// - internal TarArchive(SourceStream srcStream) - : base(ArchiveType.Tar, srcStream) { } + /// + private TarArchive(SourceStream sourceStream) + : base(ArchiveType.Tar, sourceStream) { } - internal TarArchive() + private TarArchive() : base(ArchiveType.Tar) { } protected override IEnumerable LoadEntries(IEnumerable volumes) diff --git a/src/SharpCompress/Archives/Zip/ZipArchive.cs b/src/SharpCompress/Archives/Zip/ZipArchive.cs index 18e0e233..85130f70 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchive.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchive.cs @@ -27,13 +27,13 @@ public class ZipArchive : AbstractWritableArchive /// /// Constructor with a SourceStream able to handle FileInfo and Streams. /// - /// + /// /// - internal ZipArchive(SourceStream srcStream) - : base(ArchiveType.Zip, srcStream) => + internal ZipArchive(SourceStream sourceStream) + : base(ArchiveType.Zip, sourceStream) => headerFactory = new SeekableZipHeaderFactory( - srcStream.ReaderOptions.Password, - srcStream.ReaderOptions.ArchiveEncoding + sourceStream.ReaderOptions.Password, + sourceStream.ReaderOptions.ArchiveEncoding ); /// @@ -186,9 +186,8 @@ public class ZipArchive : AbstractWritableArchive } } - protected override IEnumerable LoadVolumes(SourceStream srcStream) + protected override IEnumerable LoadVolumes(SourceStream stream) { - var stream = SrcStream.NotNull("SrcStream is null"); stream.LoadAllParts(); //request all streams stream.Position = 0; From 7ebdc85ad2ec1fa97e904dfea15b096329cbc490 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 22 Apr 2024 15:17:24 +0100 Subject: [PATCH 0070/1333] more null clean up --- .../Archives/Rar/SeekableFilePart.cs | 20 +++++++++---------- src/SharpCompress/Common/ArchiveEncoding.cs | 6 ++++-- src/SharpCompress/Common/Tar/TarEntry.cs | 8 ++++---- .../Zip/PkwareTraditionalEncryptionData.cs | 2 +- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/SharpCompress/Archives/Rar/SeekableFilePart.cs b/src/SharpCompress/Archives/Rar/SeekableFilePart.cs index 13048d4c..97822d90 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,27 @@ internal class SeekableFilePart : RarFilePart ) : base(mh, fh, index) { - this.stream = stream; - this.password = password; + _stream = stream; + _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); + var cryptKey = new CryptKey3(_password!); + return new RarCryptoWrapper(_stream, FileHeader.R4Salt, cryptKey); } if (FileHeader.Rar5CryptoInfo != null) { - var cryptKey = new CryptKey5(password!, FileHeader.Rar5CryptoInfo); - return new RarCryptoWrapper(stream, FileHeader.Rar5CryptoInfo.Salt, cryptKey); + 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/Common/ArchiveEncoding.cs b/src/SharpCompress/Common/ArchiveEncoding.cs index f66044d3..3701a93b 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,6 +50,8 @@ 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/Tar/TarEntry.cs b/src/SharpCompress/Common/Tar/TarEntry.cs index ae49e1fc..2597b837 100644 --- a/src/SharpCompress/Common/Tar/TarEntry.cs +++ b/src/SharpCompress/Common/Tar/TarEntry.cs @@ -57,17 +57,17 @@ public class TarEntry : Entry ArchiveEncoding archiveEncoding ) { - foreach (var h in TarHeaderFactory.ReadHeader(mode, stream, archiveEncoding)) + foreach (var header in TarHeaderFactory.ReadHeader(mode, stream, archiveEncoding)) { - if (h != null) + if (header != null) { if (mode == StreamingMode.Seekable) { - yield return new TarEntry(new TarFilePart(h, stream), compressionType); + yield return new TarEntry(new TarFilePart(header, stream), compressionType); } else { - yield return new TarEntry(new TarFilePart(h, null), compressionType); + yield return new TarEntry(new TarFilePart(header, null), compressionType); } } else diff --git a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs index b5d4b0fb..7b517857 100644 --- a/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/PkwareTraditionalEncryptionData.cs @@ -103,7 +103,7 @@ internal class PkwareTraditionalEncryptionData internal byte[] StringToByteArray(string value) { - var a = _archiveEncoding.Password.GetBytes(value); + var a = _archiveEncoding.GetPasswordEncoding().GetBytes(value); return a; } From c73ca21b4d580a7dde427bd06817050aa936693e Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Mon, 22 Apr 2024 15:19:05 +0100 Subject: [PATCH 0071/1333] fmt --- src/SharpCompress/Archives/Rar/RarArchive.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index a771dbec..156397ed 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -38,10 +38,7 @@ public class RarArchive : AbstractArchive streams[1].Position = 0; sourceStream.Position = 0; - return sourceStream.Streams.Select(a => new StreamRarArchiveVolume( - a, - ReaderOptions - )); + return sourceStream.Streams.Select(a => new StreamRarArchiveVolume(a, ReaderOptions)); } else //split mode or single file { From 23dd041e2e584ee7dd5f25962f0148c2577d96d5 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 08:52:10 +0100 Subject: [PATCH 0072/1333] fix some tests --- src/SharpCompress/Archives/Rar/RarArchive.cs | 4 ++-- src/SharpCompress/Archives/Rar/StreamRarArchiveVolume.cs | 2 +- src/SharpCompress/Archives/Tar/TarArchive.cs | 2 +- tests/SharpCompress.Test/ArchiveTests.cs | 4 +--- tests/SharpCompress.Test/OperatingSystemExtensions.cs | 8 ++++++++ tests/SharpCompress.Test/ReaderTests.cs | 4 +--- 6 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 tests/SharpCompress.Test/OperatingSystemExtensions.cs diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 156397ed..45663185 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -38,11 +38,11 @@ public class RarArchive : AbstractArchive streams[1].Position = 0; sourceStream.Position = 0; - return sourceStream.Streams.Select(a => new StreamRarArchiveVolume(a, ReaderOptions)); + return sourceStream.Streams.Select(a => new StreamRarArchiveVolume(a, ReaderOptions, 1)); } else //split mode or single file { - return new StreamRarArchiveVolume(sourceStream, ReaderOptions).AsEnumerable(); + return new StreamRarArchiveVolume(sourceStream, ReaderOptions, 1).AsEnumerable(); } } diff --git a/src/SharpCompress/Archives/Rar/StreamRarArchiveVolume.cs b/src/SharpCompress/Archives/Rar/StreamRarArchiveVolume.cs index 3eb5095c..60cbab9a 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 = 0) + internal StreamRarArchiveVolume(Stream stream, ReaderOptions options, int index) : base(StreamingMode.Seekable, stream, options, index) { } internal override IEnumerable ReadFileParts() => GetVolumeFileParts(); diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index 74a3c87c..3b9a45ed 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -126,7 +126,7 @@ public class TarArchive : AbstractWritableArchive protected override IEnumerable LoadVolumes(SourceStream sourceStream) { sourceStream.NotNull("SourceStream is null").LoadAllParts(); //request all streams - return new TarVolume(sourceStream, ReaderOptions, 0).AsEnumerable(); //simple single volume or split, multivolume not supported + return new TarVolume(sourceStream, ReaderOptions, 1).AsEnumerable(); //simple single volume or split, multivolume not supported } /// diff --git a/tests/SharpCompress.Test/ArchiveTests.cs b/tests/SharpCompress.Test/ArchiveTests.cs index 41135e7d..7d94b29d 100644 --- a/tests/SharpCompress.Test/ArchiveTests.cs +++ b/tests/SharpCompress.Test/ArchiveTests.cs @@ -240,12 +240,10 @@ public class ArchiveTests : ReaderTests ReaderOptions? readerOptions = null ) { -#if !NETFRAMEWORK - if (!OperatingSystem.IsWindows()) + if (!Environment.OSVersion.IsWindows()) { fileOrder = fileOrder.Replace('\\', '/'); } -#endif var expected = new Stack(fileOrder.Split(' ')); testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); using var archive = ArchiveFactory.Open(testArchive, readerOptions); diff --git a/tests/SharpCompress.Test/OperatingSystemExtensions.cs b/tests/SharpCompress.Test/OperatingSystemExtensions.cs new file mode 100644 index 00000000..96fbd6d4 --- /dev/null +++ b/tests/SharpCompress.Test/OperatingSystemExtensions.cs @@ -0,0 +1,8 @@ +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/ReaderTests.cs b/tests/SharpCompress.Test/ReaderTests.cs index b62dd4d2..7ea1d7b7 100644 --- a/tests/SharpCompress.Test/ReaderTests.cs +++ b/tests/SharpCompress.Test/ReaderTests.cs @@ -77,12 +77,10 @@ public abstract class ReaderTests : TestBase ReaderOptions? options = null ) { -#if !NETFRAMEWORK - if (!OperatingSystem.IsWindows()) + if (!Environment.OSVersion.IsWindows()) { fileOrder = fileOrder.Replace('\\', '/'); } -#endif var expected = new Stack(fileOrder.Split(' ')); testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive); From b94e75fabeaea175d139e71183d6ed085b248bbc Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 09:06:49 +0100 Subject: [PATCH 0073/1333] try to fix more tests --- src/SharpCompress/Archives/GZip/GZipArchive.cs | 5 ++--- .../Archives/Rar/FileInfoRarArchiveVolume.cs | 2 +- src/SharpCompress/Archives/Rar/RarArchive.cs | 4 ++-- src/SharpCompress/Common/GZip/GZipVolume.cs | 2 +- src/SharpCompress/Common/Rar/RarVolume.cs | 17 +++++++---------- src/SharpCompress/Readers/GZip/GZipReader.cs | 4 ++-- .../Readers/Rar/MultiVolumeRarReader.cs | 2 +- src/SharpCompress/Readers/Rar/RarReader.cs | 8 ++++---- .../Readers/Rar/RarReaderVolume.cs | 2 +- .../Readers/Rar/SingleVolumeRarReader.cs | 2 +- 10 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index 541e6d87..cec2f640 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -90,7 +90,7 @@ public class GZipArchive : AbstractWritableArchive { stream.CheckNotNull(nameof(stream)); return new GZipArchive( - new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions()) + new SourceStream(stream, _ => null, readerOptions ?? new ReaderOptions()) ); } @@ -106,8 +106,7 @@ public class GZipArchive : AbstractWritableArchive protected override IEnumerable LoadVolumes(SourceStream sourceStream) { sourceStream.LoadAllParts(); - var idx = 0; - return sourceStream.Streams.Select(a => new GZipVolume(a, ReaderOptions, idx++)); + return sourceStream.Streams.Select(a => new GZipVolume(a, ReaderOptions, 0)); } public static bool IsGZipFile(string filePath) => IsGZipFile(new FileInfo(filePath)); diff --git a/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs b/src/SharpCompress/Archives/Rar/FileInfoRarArchiveVolume.cs index 3e576db3..6d9b44fd 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 = 0) + internal FileInfoRarArchiveVolume(FileInfo fileInfo, ReaderOptions options, int index) : 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 45663185..2afd20be 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -38,11 +38,11 @@ public class RarArchive : AbstractArchive streams[1].Position = 0; sourceStream.Position = 0; - return sourceStream.Streams.Select(a => new StreamRarArchiveVolume(a, ReaderOptions, 1)); + return sourceStream.Streams.Select(a => new StreamRarArchiveVolume(a, ReaderOptions, 0)); } else //split mode or single file { - return new StreamRarArchiveVolume(sourceStream, ReaderOptions, 1).AsEnumerable(); + return new StreamRarArchiveVolume(sourceStream, ReaderOptions, 0).AsEnumerable(); } } diff --git a/src/SharpCompress/Common/GZip/GZipVolume.cs b/src/SharpCompress/Common/GZip/GZipVolume.cs index 9cfdb82d..600ba8e3 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 = 0) + public GZipVolume(Stream stream, ReaderOptions? options, int index) : base(stream, options, index) { } public GZipVolume(FileInfo fileInfo, ReaderOptions options) diff --git a/src/SharpCompress/Common/Rar/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index 2f497a04..f3d55393 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -15,17 +15,14 @@ namespace SharpCompress.Common.Rar; public abstract class RarVolume : Volume { private readonly RarHeaderFactory _headerFactory; - internal int _maxCompressionAlgorithm; + private int _maxCompressionAlgorithm; - internal RarVolume(StreamingMode mode, Stream stream, ReaderOptions options, int index = 0) + internal RarVolume(StreamingMode mode, Stream stream, ReaderOptions options, int index) : base(stream, options, index) => _headerFactory = new RarHeaderFactory(mode, options); -#nullable disable - internal ArchiveHeader ArchiveHeader { get; private set; } + private ArchiveHeader? ArchiveHeader { get; set; } -#nullable enable - - internal StreamingMode Mode => _headerFactory.StreamingMode; + private StreamingMode Mode => _headerFactory.StreamingMode; internal abstract IEnumerable ReadFileParts(); @@ -101,7 +98,7 @@ public abstract class RarVolume : Volume get { EnsureArchiveHeaderLoaded(); - return ArchiveHeader.IsFirstVolume; + return ArchiveHeader?.IsFirstVolume ?? false; } } @@ -113,7 +110,7 @@ public abstract class RarVolume : Volume get { EnsureArchiveHeaderLoaded(); - return ArchiveHeader.IsVolume; + return ArchiveHeader?.IsVolume ?? false; } } @@ -126,7 +123,7 @@ public abstract class RarVolume : Volume get { EnsureArchiveHeaderLoaded(); - return ArchiveHeader.IsSolid; + return ArchiveHeader?.IsSolid ?? false; } } diff --git a/src/SharpCompress/Readers/GZip/GZipReader.cs b/src/SharpCompress/Readers/GZip/GZipReader.cs index 27394cc7..73bc4a9d 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 { - internal GZipReader(Stream stream, ReaderOptions options) - : base(options, ArchiveType.GZip) => Volume = new GZipVolume(stream, options); + private GZipReader(Stream stream, ReaderOptions options) + : base(options, ArchiveType.GZip) => Volume = new GZipVolume(stream, options, 0); public override GZipVolume Volume { get; } diff --git a/src/SharpCompress/Readers/Rar/MultiVolumeRarReader.cs b/src/SharpCompress/Readers/Rar/MultiVolumeRarReader.cs index 76899e0c..556ca9f5 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(); - internal override void ValidateArchive(RarVolume archive) { } + protected 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 daba2bfd..2398cfac 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -14,14 +14,14 @@ namespace SharpCompress.Readers.Rar; public abstract class RarReader : AbstractReader { private RarVolume? volume; - internal Lazy UnpackV2017 { get; } = + private Lazy UnpackV2017 { get; } = new(() => new Compressors.Rar.UnpackV2017.Unpack()); - internal Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); + private Lazy UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack()); internal RarReader(ReaderOptions options) : base(options, ArchiveType.Rar) { } - internal abstract void ValidateArchive(RarVolume archive); + protected abstract void ValidateArchive(RarVolume archive); public override RarVolume? Volume => volume; @@ -51,7 +51,7 @@ public abstract class RarReader : AbstractReader protected override IEnumerable GetEntries(Stream stream) { - volume = new RarReaderVolume(stream, Options); + volume = new RarReaderVolume(stream, Options, 0); foreach (var fp in volume.ReadFileParts()) { ValidateArchive(volume); diff --git a/src/SharpCompress/Readers/Rar/RarReaderVolume.cs b/src/SharpCompress/Readers/Rar/RarReaderVolume.cs index 85beb897..d614260a 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 = 0) + internal RarReaderVolume(Stream stream, ReaderOptions options, int index) : 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 768aa115..165c92f7 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; - internal override void ValidateArchive(RarVolume archive) + protected override void ValidateArchive(RarVolume archive) { if (archive.IsMultiVolume) { From 9622853b8dee0feda48916871f4994fce62365f7 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 09:16:05 +0100 Subject: [PATCH 0074/1333] fix and fmt --- src/SharpCompress/Archives/Rar/RarArchive.cs | 14 +++++++++----- .../OperatingSystemExtensions.cs | 5 ++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/SharpCompress/Archives/Rar/RarArchive.cs b/src/SharpCompress/Archives/Rar/RarArchive.cs index 2afd20be..a05ad417 100644 --- a/src/SharpCompress/Archives/Rar/RarArchive.cs +++ b/src/SharpCompress/Archives/Rar/RarArchive.cs @@ -32,18 +32,22 @@ public class RarArchive : AbstractArchive { sourceStream.LoadAllParts(); //request all streams var streams = sourceStream.Streams.ToArray(); + var i = 0; if (streams.Length > 1 && IsRarFile(streams[1], ReaderOptions)) //test part 2 - true = multipart not split { sourceStream.IsVolumes = true; streams[1].Position = 0; sourceStream.Position = 0; - return sourceStream.Streams.Select(a => new StreamRarArchiveVolume(a, ReaderOptions, 0)); - } - else //split mode or single file - { - return new StreamRarArchiveVolume(sourceStream, ReaderOptions, 0).AsEnumerable(); + return sourceStream.Streams.Select(a => new StreamRarArchiveVolume( + a, + ReaderOptions, + i++ + )); } + + //split mode or single file + return new StreamRarArchiveVolume(sourceStream, ReaderOptions, i++).AsEnumerable(); } protected override IReader CreateReaderForSolidExtraction() diff --git a/tests/SharpCompress.Test/OperatingSystemExtensions.cs b/tests/SharpCompress.Test/OperatingSystemExtensions.cs index 96fbd6d4..c8ca768e 100644 --- a/tests/SharpCompress.Test/OperatingSystemExtensions.cs +++ b/tests/SharpCompress.Test/OperatingSystemExtensions.cs @@ -4,5 +4,8 @@ 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; + public static bool IsWindows(this OperatingSystem os) => + os.Platform == PlatformID.Win32NT + || os.Platform == PlatformID.Win32Windows + || os.Platform == PlatformID.Win32S; } From 095b5f702cfa7a1a7f0c621293a72284c4467363 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 09:20:20 +0100 Subject: [PATCH 0075/1333] get rid of another null! --- .../Common/SevenZip/SevenZipFilePart.cs | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index 6365676d..fe221b53 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) { - return null!; + throw new InvalidOperationException("File does not have a stream."); } var folderStream = _database.GetFolderStream(_stream, Folder!, _database.PasswordProvider); @@ -73,7 +73,7 @@ internal class SevenZipFilePart : FilePart private const uint K_PPMD = 0x030401; private const uint K_B_ZIP2 = 0x040202; - internal CompressionType GetCompression() + private CompressionType GetCompression() { if (Header.IsDir) { @@ -81,24 +81,13 @@ internal class SevenZipFilePart : FilePart } var coder = Folder.NotNull()._coders.First(); - switch (coder._methodId._id) + return coder._methodId._id switch { - 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(); - } + K_LZMA or K_LZMA2 => CompressionType.LZMA, + K_PPMD => CompressionType.PPMd, + K_B_ZIP2 => CompressionType.BZip2, + _ => throw new NotImplementedException() + }; } internal bool IsEncrypted => From 745fe1eb9fad5c8ca77c677f3886e2e9172564fa Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 09:28:33 +0100 Subject: [PATCH 0076/1333] references --- tests/SharpCompress.Test/SharpCompress.Test.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/SharpCompress.Test/SharpCompress.Test.csproj b/tests/SharpCompress.Test/SharpCompress.Test.csproj index 8b10a738..a358af80 100644 --- a/tests/SharpCompress.Test/SharpCompress.Test.csproj +++ b/tests/SharpCompress.Test/SharpCompress.Test.csproj @@ -10,11 +10,11 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + From 9d24e0a4b860ab9f08a87a75eef759883ca2341e Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 09:37:25 +0100 Subject: [PATCH 0077/1333] set package locks and central management --- Directory.Build.props | 2 + Directory.Packages.props | 17 + NuGet.config | 9 + SharpCompress.sln | 2 + build/build.csproj | 6 +- build/packages.lock.json | 25 ++ src/SharpCompress/SharpCompress.csproj | 10 +- src/SharpCompress/packages.lock.json | 244 +++++++++++ .../SharpCompress.Test.csproj | 15 +- tests/SharpCompress.Test/packages.lock.json | 408 ++++++++++++++++++ 10 files changed, 721 insertions(+), 17 deletions(-) create mode 100644 Directory.Packages.props create mode 100644 NuGet.config create mode 100644 build/packages.lock.json create mode 100644 src/SharpCompress/packages.lock.json create mode 100644 tests/SharpCompress.Test/packages.lock.json diff --git a/Directory.Build.props b/Directory.Build.props index 4b343bf8..b3d0b595 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -10,5 +10,7 @@ true False False + true + true diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 00000000..6bc10b2c --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 00000000..48259210 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/SharpCompress.sln b/SharpCompress.sln index 34e23bfd..ab4995b1 100644 --- a/SharpCompress.sln +++ b/SharpCompress.sln @@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{CDB425 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/build/build.csproj b/build/build.csproj index 27c0a257..8e837d3a 100644 --- a/build/build.csproj +++ b/build/build.csproj @@ -6,9 +6,9 @@ - - - + + + diff --git a/build/packages.lock.json b/build/packages.lock.json new file mode 100644 index 00000000..52565140 --- /dev/null +++ b/build/packages.lock.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "dependencies": { + "net7.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/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 65904deb..261e03da 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -28,15 +28,15 @@ - - + + - + - - + + diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json new file mode 100644 index 00000000..f6eef2d5 --- /dev/null +++ b/src/SharpCompress/packages.lock.json @@ -0,0 +1,244 @@ +{ + "version": 2, + "dependencies": { + ".NETFramework,Version=v4.6.2": { + "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.7.6, )", + "resolved": "0.7.6", + "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "5.0.0", + "System.Memory": "4.5.5" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "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.1": { + "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.7.6, )", + "resolved": "0.7.6", + "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "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.NET.ILLink.Analyzers": { + "type": "Direct", + "requested": "[7.0.100-1.23211.1, )", + "resolved": "7.0.100-1.23211.1", + "contentHash": "0GvbEgDGcUQA9KuWcQU1WwYHXt1tBzNr1Nls/M57rM7NA/AndFwCaCEoJpJkmxRY7xLlPDBnmGp8h5+FNqUngg==" + }, + "Microsoft.NET.ILLink.Tasks": { + "type": "Direct", + "requested": "[7.0.100-1.23211.1, )", + "resolved": "7.0.100-1.23211.1", + "contentHash": "tvG8XZYLjT0o3WicCyKBZysVWo1jC9HdCFmNRmddx3WbAz0UCsd0qKZqpiEo99VLA8Re+FzWK51OcRldQPbt2Q==" + }, + "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.7.6, )", + "resolved": "0.7.6", + "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==" + }, + "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.2, )", + "resolved": "8.0.2", + "contentHash": "hKTrehpfVzOhAz0mreaTAZgbz0DrMEbWq4n3hAo8Ks6WdxdqQhNPvzOqn9VygKuWf1bmxPdraqzTaXriO/sn0A==" + }, + "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.7.6, )", + "resolved": "0.7.6", + "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==" + }, + "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/SharpCompress.Test.csproj b/tests/SharpCompress.Test/SharpCompress.Test.csproj index a358af80..3bfeaa3e 100644 --- a/tests/SharpCompress.Test/SharpCompress.Test.csproj +++ b/tests/SharpCompress.Test/SharpCompress.Test.csproj @@ -8,16 +8,13 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + + + - + diff --git a/tests/SharpCompress.Test/packages.lock.json b/tests/SharpCompress.Test/packages.lock.json new file mode 100644 index 00000000..a7d04fce --- /dev/null +++ b/tests/SharpCompress.Test/packages.lock.json @@ -0,0 +1,408 @@ +{ + "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.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" + }, + "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.SourceLink.Common": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" + }, + "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.SourceLink.GitHub": "[8.0.0, )", + "System.Memory": "[4.5.5, )", + "System.Text.Encoding.CodePages": "[8.0.0, )", + "ZstdSharp.Port": "[0.7.6, )" + } + }, + "Microsoft.SourceLink.GitHub": { + "type": "CentralTransitive", + "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": "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.7.6, )", + "resolved": "0.7.6", + "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "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.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.9.0", + "contentHash": "RGD37ZSrratfScYXm7M0HjvxMxZyWZL4jm+XgMZbkIY1UPgjUpbNA/t+WTGj/rC/0Hm9A3IrH3ywbKZkOCnoZA==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" + }, + "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": { + "Microsoft.SourceLink.GitHub": "[8.0.0, )", + "ZstdSharp.Port": "[0.7.6, )" + } + }, + "Microsoft.SourceLink.GitHub": { + "type": "CentralTransitive", + "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": "CentralTransitive", + "requested": "[0.7.6, )", + "resolved": "0.7.6", + "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==" + } + } + } +} \ No newline at end of file From d84720230880be569af3b83e4f9b84d7d4462141 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 09:59:30 +0100 Subject: [PATCH 0078/1333] add back net standard 2.0 --- src/SharpCompress/Algorithms/Adler32.cs | 2 +- .../Common/Zip/WinzipAesEncryptionData.cs | 61 +++++------- .../Compressors/BZip2/BZip2Stream.cs | 2 +- .../Compressors/LZMA/LZipStream.cs | 2 +- src/SharpCompress/Crypto/Crc32Stream.cs | 2 +- src/SharpCompress/IO/NonDisposingStream.cs | 2 +- src/SharpCompress/IO/ReadOnlySubStream.cs | 2 +- .../Polyfills/StreamExtensions.cs | 2 +- .../Polyfills/StringExtensions.cs | 2 +- src/SharpCompress/SharpCompress.csproj | 8 +- src/SharpCompress/packages.lock.json | 98 +++++++++++++++++++ 11 files changed, 134 insertions(+), 49 deletions(-) diff --git a/src/SharpCompress/Algorithms/Adler32.cs b/src/SharpCompress/Algorithms/Adler32.cs index 51d5f53d..10dbfc4d 100644 --- a/src/SharpCompress/Algorithms/Adler32.cs +++ b/src/SharpCompress/Algorithms/Adler32.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -#if !NETSTANDARD2_1 && !NETFRAMEWORK +#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK #define SUPPORTS_RUNTIME_INTRINSICS #define SUPPORTS_HOTPATH #endif diff --git a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs index adffaaea..31322019 100644 --- a/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs +++ b/src/SharpCompress/Common/Zip/WinzipAesEncryptionData.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Buffers.Binary; using System.Security.Cryptography; @@ -10,12 +8,7 @@ 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, @@ -25,10 +18,28 @@ internal class WinzipAesEncryptionData ) { _keySize = keySize; - _salt = salt; - _passwordVerifyValue = passwordVerifyValue; - _password = password; - Initialize(); + +#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"); + } } internal byte[] IvBytes { get; set; } @@ -45,32 +56,4 @@ internal class WinzipAesEncryptionData WinzipAesKeySize.KeySize256 => 32, _ => throw new InvalidOperationException(), }; - - private void Initialize() - { -#if NETFRAMEWORK - 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); - _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/Compressors/BZip2/BZip2Stream.cs b/src/SharpCompress/Compressors/BZip2/BZip2Stream.cs index e5614096..2c00ea71 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 +#if !NETFRAMEWORK&& !NETSTANDARD2_0 public override int Read(Span buffer) => stream.Read(buffer); diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.cs index 9a6a5efd..5e987214 100644 --- a/src/SharpCompress/Compressors/LZMA/LZipStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LZipStream.cs @@ -125,7 +125,7 @@ public sealed class LZipStream : Stream public override void SetLength(long value) => throw new NotImplementedException(); -#if !NETFRAMEWORK +#if !NETFRAMEWORK && !NETSTANDARD2_0 public override int Read(Span buffer) => _stream.Read(buffer); diff --git a/src/SharpCompress/Crypto/Crc32Stream.cs b/src/SharpCompress/Crypto/Crc32Stream.cs index 137131a3..5f5ccd87 100644 --- a/src/SharpCompress/Crypto/Crc32Stream.cs +++ b/src/SharpCompress/Crypto/Crc32Stream.cs @@ -29,7 +29,7 @@ public sealed class Crc32Stream(Stream stream, uint polynomial, uint seed) : Str public override void SetLength(long value) => throw new NotSupportedException(); -#if !NETFRAMEWORK +#if !NETFRAMEWORK && !NETSTANDARD2_0 public override void Write(ReadOnlySpan buffer) { diff --git a/src/SharpCompress/IO/NonDisposingStream.cs b/src/SharpCompress/IO/NonDisposingStream.cs index 6d9e4174..334296d7 100644 --- a/src/SharpCompress/IO/NonDisposingStream.cs +++ b/src/SharpCompress/IO/NonDisposingStream.cs @@ -63,7 +63,7 @@ public class NonDisposingStream : Stream public override void Write(byte[] buffer, int offset, int count) => Stream.Write(buffer, offset, count); -#if !NETFRAMEWORK +#if !NETFRAMEWORK && !NETSTANDARD2_0 public override int Read(Span buffer) => Stream.Read(buffer); diff --git a/src/SharpCompress/IO/ReadOnlySubStream.cs b/src/SharpCompress/IO/ReadOnlySubStream.cs index 301e27ca..cd39335e 100644 --- a/src/SharpCompress/IO/ReadOnlySubStream.cs +++ b/src/SharpCompress/IO/ReadOnlySubStream.cs @@ -69,7 +69,7 @@ internal class ReadOnlySubStream : NonDisposingStream return value; } -#if !NETFRAMEWORK +#if !NETFRAMEWORK && !NETSTANDARD2_0 public override int Read(Span buffer) { var sliceLen = BytesLeftToRead < buffer.Length ? BytesLeftToRead : buffer.Length; diff --git a/src/SharpCompress/Polyfills/StreamExtensions.cs b/src/SharpCompress/Polyfills/StreamExtensions.cs index 360d041d..ab118a4f 100644 --- a/src/SharpCompress/Polyfills/StreamExtensions.cs +++ b/src/SharpCompress/Polyfills/StreamExtensions.cs @@ -1,4 +1,4 @@ -#if NETFRAMEWORK +#if NETFRAMEWORK || NETSTANDARD2_0 using System; using System.Buffers; diff --git a/src/SharpCompress/Polyfills/StringExtensions.cs b/src/SharpCompress/Polyfills/StringExtensions.cs index 1cd22b8a..57d1e1bc 100644 --- a/src/SharpCompress/Polyfills/StringExtensions.cs +++ b/src/SharpCompress/Polyfills/StringExtensions.cs @@ -1,4 +1,4 @@ -#if NETFRAMEWORK +#if NETFRAMEWORK || NETSTANDARD2_0 namespace SharpCompress; diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 261e03da..12faab61 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -6,7 +6,7 @@ 0.36.0 0.36.0 Adam Hathcock - net462;netstandard2.1;net6.0;net8.0 + net462;netstandard2.0;netstandard2.1;net6.0;net8.0 SharpCompress ../../SharpCompress.snk true @@ -17,7 +17,7 @@ Copyright (c) 2014 Adam Hathcock false false - SharpCompress is a compression library for 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/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. true true snupkg @@ -34,6 +34,10 @@ + + + + diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json index f6eef2d5..e6e0a13d 100644 --- a/src/SharpCompress/packages.lock.json +++ b/src/SharpCompress/packages.lock.json @@ -99,6 +99,104 @@ } } }, + ".NETStandard,Version=v2.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" + } + }, + "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.7.6, )", + "resolved": "0.7.6", + "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "5.0.0", + "System.Memory": "4.5.5" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", + "dependencies": { + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "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.SourceLink.GitHub": { "type": "Direct", From b203d165f5392cce0df4dcadc9ab3daf5cad9451 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 10:25:32 +0100 Subject: [PATCH 0079/1333] Mark for 0.37.0 --- src/SharpCompress/SharpCompress.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 12faab61..a21d1726 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -2,9 +2,9 @@ SharpCompress - Pure C# Decompression/Compression en-US - 0.36.0 - 0.36.0 - 0.36.0 + 0.37.0 + 0.37.0 + 0.37.0 Adam Hathcock net462;netstandard2.0;netstandard2.1;net6.0;net8.0 SharpCompress From 8cb621ebed2557916840049c652ccccdbd31a37a Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 14:47:40 +0100 Subject: [PATCH 0080/1333] Add SharpCompressException and use it or children in most places --- src/SharpCompress/Archives/AbstractArchive.cs | 2 +- .../Archives/AbstractWritableArchive.cs | 2 +- .../Archives/GZip/GZipArchive.cs | 4 +- src/SharpCompress/Common/ArchiveException.cs | 9 ---- .../Common/CryptographicException.cs | 9 ---- .../Common/ExtractionException.cs | 12 ----- .../Common/IncompleteArchiveException.cs | 7 --- .../Common/InvalidFormatException.cs | 12 ----- .../Common/MultiVolumeExtractionException.cs | 12 ----- .../MultipartStreamRequiredException.cs | 7 --- .../Common/ReaderCancelledException.cs | 12 ----- .../Common/SevenZip/ArchiveReader.cs | 10 ++-- .../Common/SevenZip/SevenZipFilePart.cs | 4 +- .../Common/SharpCompressException.cs | 52 +++++++++++++++++++ .../Common/Tar/Headers/TarHeader.cs | 2 +- src/SharpCompress/Compressors/Deflate/Zlib.cs | 3 +- .../Compressors/Deflate64/Deflate64Stream.cs | 3 +- .../Compressors/Deflate64/HuffmanTree.cs | 7 +-- .../Compressors/Deflate64/InflaterManaged.cs | 27 +++++----- .../Compressors/Filters/BranchExecFilter.cs | 3 +- .../Compressors/LZMA/DecoderStream.cs | 7 +-- .../Compressors/LZMA/LZipStream.cs | 29 ++++------- .../Compressors/LZMA/LzmaEncoder.cs | 3 +- .../Compressors/Xz/Filters/ArmFilter.cs | 7 +-- .../Compressors/Xz/Filters/ArmThumbFilter.cs | 7 +-- .../Compressors/Xz/Filters/BlockFilter.cs | 3 +- .../Compressors/Xz/Filters/IA64Filter.cs | 7 +-- .../Compressors/Xz/Filters/Lzma2Filter.cs | 5 +- .../Compressors/Xz/Filters/PowerPCFilter.cs | 7 +-- .../Compressors/Xz/Filters/SparcFilter.cs | 7 +-- .../Compressors/Xz/Filters/X86Filter.cs | 7 +-- .../Compressors/Xz/MultiByteIntegers.cs | 5 +- src/SharpCompress/Compressors/Xz/XZBlock.cs | 13 ++--- src/SharpCompress/Compressors/Xz/XZFooter.cs | 5 +- src/SharpCompress/Compressors/Xz/XZHeader.cs | 7 +-- src/SharpCompress/Compressors/Xz/XZIndex.cs | 5 +- .../Compressors/Xz/XZReadOnlyStream.cs | 3 +- src/SharpCompress/Compressors/Xz/XZStream.cs | 3 +- src/SharpCompress/IO/MarkingBinaryReader.cs | 3 +- src/SharpCompress/Readers/ReaderFactory.cs | 7 +-- .../SharpCompress.Test/Xz/Filters/BCJTests.cs | 15 +++--- .../Xz/Filters/Lzma2Tests.cs | 5 +- tests/SharpCompress.Test/Xz/XZBlockTests.cs | 2 +- tests/SharpCompress.Test/Xz/XZHeaderTests.cs | 7 +-- tests/SharpCompress.Test/Xz/XZIndexTests.cs | 3 +- 45 files changed, 180 insertions(+), 191 deletions(-) delete mode 100644 src/SharpCompress/Common/ArchiveException.cs delete mode 100644 src/SharpCompress/Common/CryptographicException.cs delete mode 100644 src/SharpCompress/Common/ExtractionException.cs delete mode 100644 src/SharpCompress/Common/IncompleteArchiveException.cs delete mode 100644 src/SharpCompress/Common/InvalidFormatException.cs delete mode 100644 src/SharpCompress/Common/MultiVolumeExtractionException.cs delete mode 100644 src/SharpCompress/Common/MultipartStreamRequiredException.cs delete mode 100644 src/SharpCompress/Common/ReaderCancelledException.cs create mode 100644 src/SharpCompress/Common/SharpCompressException.cs diff --git a/src/SharpCompress/Archives/AbstractArchive.cs b/src/SharpCompress/Archives/AbstractArchive.cs index df54d781..bf7fb9ed 100644 --- a/src/SharpCompress/Archives/AbstractArchive.cs +++ b/src/SharpCompress/Archives/AbstractArchive.cs @@ -53,7 +53,7 @@ public abstract class AbstractArchive : IArchive, IArchiveExtra { if (!stream.CanSeek || !stream.CanRead) { - throw new ArgumentException("Archive streams must be Readable and Seekable"); + throw new ArchiveException("Archive streams must be Readable and Seekable"); } return stream; } diff --git a/src/SharpCompress/Archives/AbstractWritableArchive.cs b/src/SharpCompress/Archives/AbstractWritableArchive.cs index 614489fe..082b9631 100644 --- a/src/SharpCompress/Archives/AbstractWritableArchive.cs +++ b/src/SharpCompress/Archives/AbstractWritableArchive.cs @@ -151,7 +151,7 @@ public abstract class AbstractWritableArchive { if (!source.CanRead || !source.CanSeek) { - throw new ArgumentException( + throw new ArchiveException( "Streams must be readable and seekable to use the Writing Archive API" ); } diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index cec2f640..7a33a10a 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -162,7 +162,7 @@ public class GZipArchive : AbstractWritableArchive { if (Entries.Any()) { - throw new InvalidOperationException("Only one entry is allowed in a GZip Archive"); + throw new InvalidFormatException("Only one entry is allowed in a GZip Archive"); } return new GZipWritableArchiveEntry(this, source, filePath, size, modified, closeStream); } @@ -176,7 +176,7 @@ public class GZipArchive : AbstractWritableArchive { if (Entries.Count > 1) { - throw new InvalidOperationException("Only one entry is allowed in a GZip Archive"); + throw new InvalidFormatException("Only one entry is allowed in a GZip Archive"); } using var writer = new GZipWriter(stream, new GZipWriterOptions(options)); foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory)) diff --git a/src/SharpCompress/Common/ArchiveException.cs b/src/SharpCompress/Common/ArchiveException.cs deleted file mode 100644 index 507d5fd8..00000000 --- a/src/SharpCompress/Common/ArchiveException.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace SharpCompress.Common; - -public class ArchiveException : Exception -{ - public ArchiveException(string message) - : base(message) { } -} diff --git a/src/SharpCompress/Common/CryptographicException.cs b/src/SharpCompress/Common/CryptographicException.cs deleted file mode 100644 index 6127524a..00000000 --- a/src/SharpCompress/Common/CryptographicException.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace SharpCompress.Common; - -public class CryptographicException : Exception -{ - public CryptographicException(string message) - : base(message) { } -} diff --git a/src/SharpCompress/Common/ExtractionException.cs b/src/SharpCompress/Common/ExtractionException.cs deleted file mode 100644 index 4bc4f00c..00000000 --- a/src/SharpCompress/Common/ExtractionException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace SharpCompress.Common; - -public class ExtractionException : Exception -{ - public ExtractionException(string message) - : base(message) { } - - public ExtractionException(string message, Exception inner) - : base(message, inner) { } -} diff --git a/src/SharpCompress/Common/IncompleteArchiveException.cs b/src/SharpCompress/Common/IncompleteArchiveException.cs deleted file mode 100644 index a033001a..00000000 --- a/src/SharpCompress/Common/IncompleteArchiveException.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace SharpCompress.Common; - -public class IncompleteArchiveException : ArchiveException -{ - public IncompleteArchiveException(string message) - : base(message) { } -} diff --git a/src/SharpCompress/Common/InvalidFormatException.cs b/src/SharpCompress/Common/InvalidFormatException.cs deleted file mode 100644 index 8f14df14..00000000 --- a/src/SharpCompress/Common/InvalidFormatException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace SharpCompress.Common; - -public class InvalidFormatException : ExtractionException -{ - public InvalidFormatException(string message) - : base(message) { } - - public InvalidFormatException(string message, Exception inner) - : base(message, inner) { } -} diff --git a/src/SharpCompress/Common/MultiVolumeExtractionException.cs b/src/SharpCompress/Common/MultiVolumeExtractionException.cs deleted file mode 100644 index 764ac808..00000000 --- a/src/SharpCompress/Common/MultiVolumeExtractionException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace SharpCompress.Common; - -public class MultiVolumeExtractionException : ExtractionException -{ - public MultiVolumeExtractionException(string message) - : base(message) { } - - public MultiVolumeExtractionException(string message, Exception inner) - : base(message, inner) { } -} diff --git a/src/SharpCompress/Common/MultipartStreamRequiredException.cs b/src/SharpCompress/Common/MultipartStreamRequiredException.cs deleted file mode 100644 index 33a842d9..00000000 --- a/src/SharpCompress/Common/MultipartStreamRequiredException.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace SharpCompress.Common; - -public class MultipartStreamRequiredException : ExtractionException -{ - public MultipartStreamRequiredException(string message) - : base(message) { } -} 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/ArchiveReader.cs b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs index 3e506e0e..45eb702f 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs @@ -784,7 +784,7 @@ internal class ArchiveReader ); break; default: - throw new InvalidOperationException(); + throw new InvalidFormatException(); } } } @@ -843,7 +843,7 @@ internal class ArchiveReader outStream.ReadExact(data, 0, data.Length); if (outStream.ReadByte() >= 0) { - throw new InvalidOperationException("Decoded stream is longer than expected."); + throw new InvalidFormatException("Decoded stream is longer than expected."); } dataVector.Add(data); @@ -854,9 +854,9 @@ internal class ArchiveReader != folder._unpackCrc ) { - throw new InvalidOperationException( - "Decoded stream does not match expected CRC." - ); + throw new InvalidFormatException( + "Decoded stream does not match expected CRC." + ); } } } diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index fe221b53..ac355828 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."); + throw new InvalidFormatException("File does not have a stream."); } var folderStream = _database.GetFolderStream(_stream, Folder!, _database.PasswordProvider); @@ -86,7 +86,7 @@ internal class SevenZipFilePart : FilePart K_LZMA or K_LZMA2 => CompressionType.LZMA, K_PPMD => CompressionType.PPMd, K_B_ZIP2 => CompressionType.BZip2, - _ => throw new NotImplementedException() + _ => throw new InvalidFormatException() }; } diff --git a/src/SharpCompress/Common/SharpCompressException.cs b/src/SharpCompress/Common/SharpCompressException.cs new file mode 100644 index 00000000..7c68863d --- /dev/null +++ b/src/SharpCompress/Common/SharpCompressException.cs @@ -0,0 +1,52 @@ +using System; + +namespace SharpCompress.Common; + +public class SharpCompressException : ApplicationException +{ + public SharpCompressException() + { } + public SharpCompressException(string message) + : base(message) { } + + public SharpCompressException(string message, Exception inner) + : base(message, inner) { } +} + + + +public class ArchiveException(string message) : SharpCompressException(message); + +public class IncompleteArchiveException(string message) : ArchiveException(message); + + +public class CryptographicException(string message) : SharpCompressException(message); + +public class ReaderCancelledException(string message) : SharpCompressException(message); + +public class ExtractionException : SharpCompressException +{ + public ExtractionException() + { } + public ExtractionException(string message) + : base(message) { } + + public ExtractionException(string message, Exception inner) + : base(message, inner) { } +} + +public class MultipartStreamRequiredException(string message) : ExtractionException(message); + +public class MultiVolumeExtractionException(string message) : ExtractionException(message); + +public class InvalidFormatException : ExtractionException +{ + public InvalidFormatException() + { } + public InvalidFormatException(string message) + : base(message) { } + + public InvalidFormatException(string message, Exception inner) + : base(message, inner) { } +} + diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 68a72e8a..8f87a028 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -188,7 +188,7 @@ internal sealed class TarHeader if (buffer.Length != 0 && buffer.Length < BLOCK_SIZE) { - throw new InvalidOperationException("Buffer is invalid size"); + throw new InvalidFormatException("Buffer is invalid size"); } return buffer; } diff --git a/src/SharpCompress/Compressors/Deflate/Zlib.cs b/src/SharpCompress/Compressors/Deflate/Zlib.cs index 6fbeb4d9..b395029e 100644 --- a/src/SharpCompress/Compressors/Deflate/Zlib.cs +++ b/src/SharpCompress/Compressors/Deflate/Zlib.cs @@ -64,6 +64,7 @@ using System; using System.IO; +using SharpCompress.Common; namespace SharpCompress.Compressors.Deflate; @@ -177,7 +178,7 @@ public enum CompressionStrategy /// /// A general purpose exception class for exceptions in the Zlib library. /// -public class ZlibException : Exception +public class ZlibException : SharpCompressException { /// /// The ZlibException class captures exception information generated diff --git a/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs b/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs index da4117b9..e6a3fdfd 100644 --- a/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs +++ b/src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs @@ -8,6 +8,7 @@ using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; +using SharpCompress.Common; using SharpCompress.Common.Zip; namespace SharpCompress.Compressors.Deflate64; @@ -151,7 +152,7 @@ public sealed class Deflate64Stream : Stream { // The stream is either malicious or poorly implemented and returned a number of // bytes larger than the buffer supplied to it. - throw new InvalidDataException("Deflate64: invalid data"); + throw new InvalidFormatException("Deflate64: invalid data"); } _inflater.SetInput(_buffer, 0, bytes); diff --git a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs index e37802bb..4c9e7e8b 100644 --- a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs +++ b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.IO; +using SharpCompress.Common; namespace SharpCompress.Compressors.Deflate64; @@ -192,7 +193,7 @@ internal sealed class HuffmanTree var increment = 1 << len; if (start >= increment) { - throw new InvalidDataException("Deflate64: invalid Huffman data"); + throw new InvalidFormatException("Deflate64: invalid Huffman data"); } // Note the bits in the table are reverted. @@ -234,7 +235,7 @@ internal sealed class HuffmanTree if (value > 0) { // prevent an IndexOutOfRangeException from array[index] - throw new InvalidDataException("Deflate64: invalid Huffman data"); + throw new InvalidFormatException("Deflate64: invalid Huffman data"); } Debug.Assert( @@ -307,7 +308,7 @@ internal sealed class HuffmanTree // huffman code lengths must be at least 1 bit long if (codeLength <= 0) { - throw new InvalidDataException("Deflate64: invalid Huffman data"); + throw new InvalidFormatException("Deflate64: invalid Huffman data"); } // diff --git a/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs b/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs index 4e11854f..2e4d8377 100644 --- a/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs +++ b/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs @@ -31,6 +31,7 @@ using System; using System.Diagnostics; using System.IO; +using SharpCompress.Compressors.Deflate; namespace SharpCompress.Compressors.Deflate64; @@ -385,7 +386,7 @@ internal sealed class InflaterManaged } else { - throw new InvalidDataException("Deflate64: unknown block type"); + throw new ZlibException("Deflate64: unknown block type"); } } @@ -411,7 +412,7 @@ internal sealed class InflaterManaged } else { - throw new InvalidDataException("Deflate64: unknown block type"); + throw new ZlibException("Deflate64: unknown block type"); } // @@ -473,7 +474,7 @@ internal sealed class InflaterManaged // make sure complement matches if ((ushort)_blockLength != (ushort)(~blockLengthComplement)) { - throw new InvalidDataException("Deflate64: invalid block length"); + throw new ZlibException("Deflate64: invalid block length"); } } @@ -507,7 +508,7 @@ internal sealed class InflaterManaged default: Debug. /*Fail*/ Assert(false, "check why we are here!"); - throw new InvalidDataException("Deflate64: unknown state"); + throw new ZlibException("Deflate64: unknown state"); } } } @@ -569,7 +570,7 @@ internal sealed class InflaterManaged { if (symbol < 0 || symbol >= S_EXTRA_LENGTH_BITS.Length) { - throw new InvalidDataException("Deflate64: invalid data"); + throw new ZlibException("Deflate64: invalid data"); } _extraBits = S_EXTRA_LENGTH_BITS[symbol]; Debug.Assert(_extraBits != 0, "We handle other cases separately!"); @@ -591,7 +592,7 @@ internal sealed class InflaterManaged if (_length < 0 || _length >= S_LENGTH_BASE.Length) { - throw new InvalidDataException("Deflate64: invalid data"); + throw new ZlibException("Deflate64: invalid data"); } _length = S_LENGTH_BASE[_length] + bits; } @@ -649,7 +650,7 @@ internal sealed class InflaterManaged default: Debug. /*Fail*/ Assert(false, "check why we are here!"); - throw new InvalidDataException("Deflate64: unknown state"); + throw new ZlibException("Deflate64: unknown state"); } } @@ -781,7 +782,7 @@ internal sealed class InflaterManaged if (_loopCounter == 0) { // can't have "prev code" on first code - throw new InvalidDataException(); + throw new ZlibException(); } var previousCode = _codeList[_loopCounter - 1]; @@ -789,7 +790,7 @@ internal sealed class InflaterManaged if (_loopCounter + repeatCount > _codeArraySize) { - throw new InvalidDataException(); + throw new ZlibException(); } for (var j = 0; j < repeatCount; j++) @@ -809,7 +810,7 @@ internal sealed class InflaterManaged if (_loopCounter + repeatCount > _codeArraySize) { - throw new InvalidDataException(); + throw new ZlibException(); } for (var j = 0; j < repeatCount; j++) @@ -830,7 +831,7 @@ internal sealed class InflaterManaged if (_loopCounter + repeatCount > _codeArraySize) { - throw new InvalidDataException(); + throw new ZlibException(); } for (var j = 0; j < repeatCount; j++) @@ -846,7 +847,7 @@ internal sealed class InflaterManaged default: Debug. /*Fail*/ Assert(false, "check why we are here!"); - throw new InvalidDataException("Deflate64: unknown state"); + throw new ZlibException("Deflate64: unknown state"); } var literalTreeCodeLength = new byte[HuffmanTree.MAX_LITERAL_TREE_ELEMENTS]; @@ -865,7 +866,7 @@ internal sealed class InflaterManaged // Make sure there is an end-of-block code, otherwise how could we ever end? if (literalTreeCodeLength[HuffmanTree.END_OF_BLOCK_CODE] == 0) { - throw new InvalidDataException(); + throw new ZlibException(); } _literalLengthTree = new HuffmanTree(literalTreeCodeLength); diff --git a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs index d198cf8f..7f887720 100644 --- a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs +++ b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs @@ -7,6 +7,7 @@ using System; using System.IO; using System.Runtime.CompilerServices; +using SharpCompress.Common; namespace SharpCompress.Compressors.Filters; @@ -244,7 +245,7 @@ public sealed class BranchExecFilter long size = data.Length; if (size < 16) { - throw new InvalidDataException("Unexpected data size"); + throw new InvalidFormatException("Unexpected data size"); } size -= 16; diff --git a/src/SharpCompress/Compressors/LZMA/DecoderStream.cs b/src/SharpCompress/Compressors/LZMA/DecoderStream.cs index a3dbf37f..b54d89e3 100644 --- a/src/SharpCompress/Compressors/LZMA/DecoderStream.cs +++ b/src/SharpCompress/Compressors/LZMA/DecoderStream.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using SharpCompress.Common; using SharpCompress.Common.SevenZip; using SharpCompress.Compressors.LZMA.Utilites; using SharpCompress.IO; @@ -46,7 +47,7 @@ internal static class DecoderStreamHelper } } - throw new InvalidOperationException("Could not link output stream to coder."); + throw new InvalidFormatException("Could not link output stream to coder."); } private static void FindPrimaryOutStreamIndex( @@ -75,7 +76,7 @@ internal static class DecoderStreamHelper { if (foundPrimaryOutStream) { - throw new NotSupportedException("Multiple output streams."); + throw new InvalidFormatException("Multiple output streams."); } foundPrimaryOutStream = true; @@ -87,7 +88,7 @@ internal static class DecoderStreamHelper if (!foundPrimaryOutStream) { - throw new NotSupportedException("No output stream."); + throw new InvalidFormatException("No output stream."); } } diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.cs index 5e987214..b7c69150 100644 --- a/src/SharpCompress/Compressors/LZMA/LZipStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LZipStream.cs @@ -1,6 +1,7 @@ using System; using System.Buffers.Binary; using System.IO; +using SharpCompress.Common; using SharpCompress.Crypto; using SharpCompress.IO; @@ -32,7 +33,7 @@ public sealed class LZipStream : Stream var dSize = ValidateAndReadSize(stream); if (dSize == 0) { - throw new IOException("Not an LZip stream"); + throw new InvalidFormatException("Not an LZip stream"); } var properties = GetProperties(dSize); _stream = new LzmaStream(properties, stream); @@ -167,11 +168,6 @@ public sealed class LZipStream : Stream /// public static int ValidateAndReadSize(Stream stream) { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } - // Read the header Span header = stackalloc byte[6]; var n = stream.Read(header); @@ -198,34 +194,27 @@ public sealed class LZipStream : Stream return (1 << basePower) - (subtractionNumerator * (1 << (basePower - 4))); } - private static readonly byte[] headerBytes = new byte[6] - { + private static readonly byte[] headerBytes = + [ (byte)'L', (byte)'Z', (byte)'I', (byte)'P', 1, 113 - }; + ]; - public static void WriteHeaderSize(Stream stream) - { - if (stream is null) - { - throw new ArgumentNullException(nameof(stream)); - } + public static void WriteHeaderSize(Stream stream) => // hard coding the dictionary size encoding stream.Write(headerBytes, 0, 6); - } /// /// Creates a byte array to communicate the parameters and dictionary size to LzmaStream. /// private static byte[] GetProperties(int dictionarySize) => - new byte[] - { - // Parameters as per http://www.nongnu.org/lzip/manual/lzip_manual.html#Stream-format + [ + // Parameters as per http://www.nongnu.org/lzip/manual/lzip_manual.html#Stream-format // but encoded as a single byte in the format LzmaStream expects. // literal_context_bits = 3 // literal_pos_state_bits = 0 @@ -236,5 +225,5 @@ public sealed class LZipStream : Stream (byte)((dictionarySize >> 8) & 0xff), (byte)((dictionarySize >> 16) & 0xff), (byte)((dictionarySize >> 24) & 0xff) - }; + ]; } diff --git a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs index 509e54c8..0c2a91dc 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs @@ -2,6 +2,7 @@ using System; using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.LZMA.LZ; using SharpCompress.Compressors.LZMA.RangeCoder; @@ -1611,7 +1612,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { if (_nowPos64 > 0) { - throw new InvalidOperationException(); + throw new InvalidFormatException(); } _trainSize = (uint)trainStream.Length; if (_trainSize > 0) diff --git a/src/SharpCompress/Compressors/Xz/Filters/ArmFilter.cs b/src/SharpCompress/Compressors/Xz/Filters/ArmFilter.cs index af1e99d3..cff95778 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/ArmFilter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/ArmFilter.cs @@ -5,6 +5,7 @@ */ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Filters; namespace SharpCompress.Compressors.Xz.Filters; @@ -25,19 +26,19 @@ public class ArmFilter : BlockFilter { if (properties.Length != 0 && properties.Length != 4) { - throw new InvalidDataException("ARM properties unexpected length"); + throw new InvalidFormatException("ARM properties unexpected length"); } if (properties.Length == 4) { // Even XZ doesn't support it. - throw new InvalidDataException("ARM properties offset is not supported"); + throw new InvalidFormatException("ARM properties offset is not supported"); //_offset = BitConverter.ToUInt32(properties, 0); // //if (_offset % (UInt32)BranchExec.Alignment.ARCH_ARM_ALIGNMENT != 0) //{ - // throw new InvalidDataException("Filter offset does not match alignment"); + // throw new InvalidFormatException("Filter offset does not match alignment"); //} } } diff --git a/src/SharpCompress/Compressors/Xz/Filters/ArmThumbFilter.cs b/src/SharpCompress/Compressors/Xz/Filters/ArmThumbFilter.cs index f3ec7b1b..1bcfcdc9 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/ArmThumbFilter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/ArmThumbFilter.cs @@ -5,6 +5,7 @@ */ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Filters; namespace SharpCompress.Compressors.Xz.Filters; @@ -25,19 +26,19 @@ public class ArmThumbFilter : BlockFilter { if (properties.Length != 0 && properties.Length != 4) { - throw new InvalidDataException("ARM Thumb properties unexpected length"); + throw new InvalidFormatException("ARM Thumb properties unexpected length"); } if (properties.Length == 4) { // Even XZ doesn't support it. - throw new InvalidDataException("ARM Thumb properties offset is not supported"); + throw new InvalidFormatException("ARM Thumb properties offset is not supported"); //_offset = BitConverter.ToUInt32(properties, 0); // //if (_offset % (UInt32)BranchExec.Alignment.ARCH_ARMTHUMB_ALIGNMENT != 0) //{ - // throw new InvalidDataException("Filter offset does not match alignment"); + // throw new InvalidFormatException("Filter offset does not match alignment"); //} } } diff --git a/src/SharpCompress/Compressors/Xz/Filters/BlockFilter.cs b/src/SharpCompress/Compressors/Xz/Filters/BlockFilter.cs index 936a3a0d..a7e3482a 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/BlockFilter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/BlockFilter.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using SharpCompress.Common; namespace SharpCompress.Compressors.Xz.Filters; @@ -50,7 +51,7 @@ public abstract class BlockFilter : ReadOnlyStream var sizeOfProperties = reader.ReadXZInteger(); if (sizeOfProperties > int.MaxValue) { - throw new InvalidDataException("Block filter information too large"); + throw new InvalidFormatException("Block filter information too large"); } var properties = reader.ReadBytes((int)sizeOfProperties); diff --git a/src/SharpCompress/Compressors/Xz/Filters/IA64Filter.cs b/src/SharpCompress/Compressors/Xz/Filters/IA64Filter.cs index dc04c71b..14f8cdad 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/IA64Filter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/IA64Filter.cs @@ -5,6 +5,7 @@ */ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Filters; namespace SharpCompress.Compressors.Xz.Filters; @@ -25,19 +26,19 @@ public class IA64Filter : BlockFilter { if (properties.Length != 0 && properties.Length != 4) { - throw new InvalidDataException("IA64 properties unexpected length"); + throw new InvalidFormatException("IA64 properties unexpected length"); } if (properties.Length == 4) { // Even XZ doesn't support it. - throw new InvalidDataException("IA64 properties offset is not supported"); + throw new InvalidFormatException("IA64 properties offset is not supported"); //_offset = BitConverter.ToUInt32(properties, 0); // //if (_offset % (UInt32)BranchExec.Alignment.ARCH_IA64_ALIGNMENT != 0) //{ - // throw new InvalidDataException("Filter offset does not match alignment"); + // throw new InvalidFormatException("Filter offset does not match alignment"); //} } } diff --git a/src/SharpCompress/Compressors/Xz/Filters/Lzma2Filter.cs b/src/SharpCompress/Compressors/Xz/Filters/Lzma2Filter.cs index bed59b76..ea078c9d 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/Lzma2Filter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/Lzma2Filter.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.LZMA; namespace SharpCompress.Compressors.Xz.Filters; @@ -35,14 +36,14 @@ public class Lzma2Filter : BlockFilter { if (properties.Length != 1) { - throw new InvalidDataException("LZMA properties unexpected length"); + throw new InvalidFormatException("LZMA properties unexpected length"); } _dictionarySize = (byte)(properties[0] & 0x3F); var reserved = properties[0] & 0xC0; if (reserved != 0) { - throw new InvalidDataException("Reserved bits used in LZMA properties"); + throw new InvalidFormatException("Reserved bits used in LZMA properties"); } } diff --git a/src/SharpCompress/Compressors/Xz/Filters/PowerPCFilter.cs b/src/SharpCompress/Compressors/Xz/Filters/PowerPCFilter.cs index 7a03a3fe..b171fa6c 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/PowerPCFilter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/PowerPCFilter.cs @@ -5,6 +5,7 @@ */ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Filters; namespace SharpCompress.Compressors.Xz.Filters; @@ -25,19 +26,19 @@ public class PowerPCFilter : BlockFilter { if (properties.Length != 0 && properties.Length != 4) { - throw new InvalidDataException("PPC properties unexpected length"); + throw new InvalidFormatException("PPC properties unexpected length"); } if (properties.Length == 4) { // Even XZ doesn't support it. - throw new InvalidDataException("PPC properties offset is not supported"); + throw new InvalidFormatException("PPC properties offset is not supported"); //_offset = BitConverter.ToUInt32(properties, 0); // //if (_offset % (UInt32)BranchExec.Alignment.ARCH_PowerPC_ALIGNMENT != 0) //{ - // throw new InvalidDataException("Filter offset does not match alignment"); + // throw new InvalidFormatException("Filter offset does not match alignment"); //} } } diff --git a/src/SharpCompress/Compressors/Xz/Filters/SparcFilter.cs b/src/SharpCompress/Compressors/Xz/Filters/SparcFilter.cs index 9b74d344..8b3a4532 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/SparcFilter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/SparcFilter.cs @@ -5,6 +5,7 @@ */ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Filters; namespace SharpCompress.Compressors.Xz.Filters; @@ -25,19 +26,19 @@ public class SparcFilter : BlockFilter { if (properties.Length != 0 && properties.Length != 4) { - throw new InvalidDataException("SPARC properties unexpected length"); + throw new InvalidFormatException("SPARC properties unexpected length"); } if (properties.Length == 4) { // Even XZ doesn't support it. - throw new InvalidDataException("SPARC properties offset is not supported"); + throw new InvalidFormatException("SPARC properties offset is not supported"); //_offset = BitConverter.ToUInt32(properties, 0); // //if (_offset % (UInt32)BranchExec.Alignment.ARCH_SPARC_ALIGNMENT != 0) //{ - // throw new InvalidDataException("Filter offset does not match alignment"); + // throw new InvalidFormatException("Filter offset does not match alignment"); //} } } diff --git a/src/SharpCompress/Compressors/Xz/Filters/X86Filter.cs b/src/SharpCompress/Compressors/Xz/Filters/X86Filter.cs index 74dbfb1d..fd8ef42a 100644 --- a/src/SharpCompress/Compressors/Xz/Filters/X86Filter.cs +++ b/src/SharpCompress/Compressors/Xz/Filters/X86Filter.cs @@ -5,6 +5,7 @@ */ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Filters; namespace SharpCompress.Compressors.Xz.Filters; @@ -27,19 +28,19 @@ public class X86Filter : BlockFilter { if (properties.Length != 0 && properties.Length != 4) { - throw new InvalidDataException("X86 properties unexpected length"); + throw new InvalidFormatException("X86 properties unexpected length"); } if (properties.Length == 4) { // Even XZ doesn't support it. - throw new InvalidDataException("X86 properties offset is not supported"); + throw new InvalidFormatException("X86 properties offset is not supported"); //_offset = BitConverter.ToUInt32(properties, 0); // //if (_offset % (UInt32)BranchExec.Alignment.ARCH_x86_ALIGNMENT != 0) //{ - // throw new InvalidDataException("Filter offset does not match alignment"); + // throw new InvalidFormatException("Filter offset does not match alignment"); //} } } diff --git a/src/SharpCompress/Compressors/Xz/MultiByteIntegers.cs b/src/SharpCompress/Compressors/Xz/MultiByteIntegers.cs index a38505da..8a0d81a3 100644 --- a/src/SharpCompress/Compressors/Xz/MultiByteIntegers.cs +++ b/src/SharpCompress/Compressors/Xz/MultiByteIntegers.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using SharpCompress.Common; namespace SharpCompress.Compressors.Xz; @@ -25,13 +26,13 @@ internal static class MultiByteIntegers { if (++i >= MaxBytes) { - throw new InvalidDataException(); + throw new InvalidFormatException(); } LastByte = reader.ReadByte(); if (LastByte == 0) { - throw new InvalidDataException(); + throw new InvalidFormatException(); } Output |= ((ulong)(LastByte & 0x7F)) << (i * 7); diff --git a/src/SharpCompress/Compressors/Xz/XZBlock.cs b/src/SharpCompress/Compressors/Xz/XZBlock.cs index ddd7eaf3..34ce2333 100644 --- a/src/SharpCompress/Compressors/Xz/XZBlock.cs +++ b/src/SharpCompress/Compressors/Xz/XZBlock.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using SharpCompress.Common; using SharpCompress.Compressors.Xz.Filters; namespace SharpCompress.Compressors.Xz; @@ -80,7 +81,7 @@ public sealed class XZBlock : XZReadOnlyStream BaseStream.Read(paddingBytes, 0, paddingBytes.Length); if (paddingBytes.Any(b => b != 0)) { - throw new InvalidDataException("Padding bytes were non-null"); + throw new InvalidFormatException("Padding bytes were non-null"); } } _paddingSkipped = true; @@ -145,7 +146,7 @@ public sealed class XZBlock : XZReadOnlyStream var calcCrc = Crc32.Compute(blockHeaderWithoutCrc); if (crc != calcCrc) { - throw new InvalidDataException("Block header corrupt"); + throw new InvalidFormatException("Block header corrupt"); } return blockHeaderWithoutCrc; @@ -159,7 +160,7 @@ public sealed class XZBlock : XZReadOnlyStream if (reserved != 0) { - throw new InvalidDataException( + throw new InvalidFormatException( "Reserved bytes used, perhaps an unknown XZ implementation" ); } @@ -189,7 +190,7 @@ public sealed class XZBlock : XZReadOnlyStream || (i + 1 < _numFilters && !filter.AllowAsNonLast) ) { - throw new InvalidDataException("Block Filters in bad order"); + throw new InvalidFormatException("Block Filters in bad order"); } if (filter.ChangesDataSize && i + 1 < _numFilters) @@ -202,7 +203,7 @@ public sealed class XZBlock : XZReadOnlyStream } if (nonLastSizeChangers > 2) { - throw new InvalidDataException( + throw new InvalidFormatException( "More than two non-last block filters cannot change stream size" ); } @@ -212,7 +213,7 @@ public sealed class XZBlock : XZReadOnlyStream var blockHeaderPadding = reader.ReadBytes(blockHeaderPaddingSize); if (!blockHeaderPadding.All(b => b == 0)) { - throw new InvalidDataException("Block header contains unknown fields"); + throw new InvalidFormatException("Block header contains unknown fields"); } } } diff --git a/src/SharpCompress/Compressors/Xz/XZFooter.cs b/src/SharpCompress/Compressors/Xz/XZFooter.cs index 9751fc2b..9b2dd6e2 100644 --- a/src/SharpCompress/Compressors/Xz/XZFooter.cs +++ b/src/SharpCompress/Compressors/Xz/XZFooter.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using SharpCompress.Common; using SharpCompress.IO; namespace SharpCompress.Compressors.Xz; @@ -35,7 +36,7 @@ public class XZFooter var myCrc = Crc32.Compute(footerBytes); if (crc != myCrc) { - throw new InvalidDataException("Footer corrupt"); + throw new InvalidFormatException("Footer corrupt"); } using (var stream = new MemoryStream(footerBytes)) @@ -47,7 +48,7 @@ public class XZFooter var magBy = _reader.ReadBytes(2); if (!magBy.AsSpan().SequenceEqual(_magicBytes)) { - throw new InvalidDataException("Magic footer missing"); + throw new InvalidFormatException("Magic footer missing"); } } } diff --git a/src/SharpCompress/Compressors/Xz/XZHeader.cs b/src/SharpCompress/Compressors/Xz/XZHeader.cs index a5ed8c4a..1dfe296a 100644 --- a/src/SharpCompress/Compressors/Xz/XZHeader.cs +++ b/src/SharpCompress/Compressors/Xz/XZHeader.cs @@ -1,6 +1,7 @@ using System.IO; using System.Linq; using System.Text; +using SharpCompress.Common; using SharpCompress.IO; namespace SharpCompress.Compressors.Xz; @@ -37,14 +38,14 @@ public class XZHeader var calcCrc = Crc32.Compute(streamFlags); if (crc != calcCrc) { - throw new InvalidDataException("Stream header corrupt"); + throw new InvalidFormatException("Stream header corrupt"); } BlockCheckType = (CheckType)(streamFlags[1] & 0x0F); var futureUse = (byte)(streamFlags[1] & 0xF0); if (futureUse != 0 || streamFlags[0] != 0) { - throw new InvalidDataException("Unknown XZ Stream Version"); + throw new InvalidFormatException("Unknown XZ Stream Version"); } } @@ -52,7 +53,7 @@ public class XZHeader { if (!header.SequenceEqual(MagicHeader)) { - throw new InvalidDataException("Invalid XZ Stream"); + throw new InvalidFormatException("Invalid XZ Stream"); } } } diff --git a/src/SharpCompress/Compressors/Xz/XZIndex.cs b/src/SharpCompress/Compressors/Xz/XZIndex.cs index ddfd7c99..386c15da 100644 --- a/src/SharpCompress/Compressors/Xz/XZIndex.cs +++ b/src/SharpCompress/Compressors/Xz/XZIndex.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using SharpCompress.Common; using SharpCompress.IO; namespace SharpCompress.Compressors.Xz; @@ -59,7 +60,7 @@ public class XZIndex var marker = _reader.ReadByte(); if (marker != 0) { - throw new InvalidDataException("Not an index block"); + throw new InvalidFormatException("Not an index block"); } } @@ -71,7 +72,7 @@ public class XZIndex var paddingBytes = _reader.ReadBytes(4 - bytes); if (paddingBytes.Any(b => b != 0)) { - throw new InvalidDataException("Padding bytes were non-null"); + throw new InvalidFormatException("Padding bytes were non-null"); } } } diff --git a/src/SharpCompress/Compressors/Xz/XZReadOnlyStream.cs b/src/SharpCompress/Compressors/Xz/XZReadOnlyStream.cs index 4c1aa02b..fd947cc9 100644 --- a/src/SharpCompress/Compressors/Xz/XZReadOnlyStream.cs +++ b/src/SharpCompress/Compressors/Xz/XZReadOnlyStream.cs @@ -1,4 +1,5 @@ using System.IO; +using SharpCompress.Common; namespace SharpCompress.Compressors.Xz; @@ -9,7 +10,7 @@ public abstract class XZReadOnlyStream : ReadOnlyStream BaseStream = stream; if (!BaseStream.CanRead) { - throw new InvalidDataException("Must be able to read from stream"); + throw new InvalidFormatException("Must be able to read from stream"); } } } diff --git a/src/SharpCompress/Compressors/Xz/XZStream.cs b/src/SharpCompress/Compressors/Xz/XZStream.cs index 26d3dcb2..eff08a1e 100644 --- a/src/SharpCompress/Compressors/Xz/XZStream.cs +++ b/src/SharpCompress/Compressors/Xz/XZStream.cs @@ -2,6 +2,7 @@ using System; using System.IO; +using SharpCompress.Common; namespace SharpCompress.Compressors.Xz; @@ -33,7 +34,7 @@ public sealed class XZStream : XZReadOnlyStream case CheckType.SHA256: throw new NotImplementedException(); default: - throw new NotSupportedException("Check Type unknown to this version of decoder."); + throw new InvalidFormatException("Check Type unknown to this version of decoder."); } } diff --git a/src/SharpCompress/IO/MarkingBinaryReader.cs b/src/SharpCompress/IO/MarkingBinaryReader.cs index 424b9e08..be26df86 100644 --- a/src/SharpCompress/IO/MarkingBinaryReader.cs +++ b/src/SharpCompress/IO/MarkingBinaryReader.cs @@ -1,6 +1,7 @@ using System; using System.Buffers.Binary; using System.IO; +using SharpCompress.Common; namespace SharpCompress.IO; @@ -44,7 +45,7 @@ internal class MarkingBinaryReader : BinaryReader var bytes = base.ReadBytes(count); if (bytes.Length != count) { - throw new EndOfStreamException( + throw new InvalidFormatException( string.Format( "Could not read the requested amount of bytes. End of stream reached. Requested: {0} Read: {1}", count, diff --git a/src/SharpCompress/Readers/ReaderFactory.cs b/src/SharpCompress/Readers/ReaderFactory.cs index a079c235..2cb4865f 100644 --- a/src/SharpCompress/Readers/ReaderFactory.cs +++ b/src/SharpCompress/Readers/ReaderFactory.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using SharpCompress.Common; using SharpCompress.IO; namespace SharpCompress.Readers; @@ -29,8 +30,8 @@ public static class ReaderFactory } } - throw new InvalidOperationException( - "Cannot determine compressed stream type. Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ" - ); + throw new InvalidFormatException( + "Cannot determine compressed stream type. Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ" + ); } } diff --git a/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs b/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs index bc16789d..9dbdf348 100644 --- a/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs @@ -4,6 +4,7 @@ */ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Xz.Filters; using Xunit; @@ -66,23 +67,23 @@ public class BcjTests : XzTestsBase [InlineData(new byte[] { 0, 0, 0, 0, 0 })] public void OnlyAcceptsOneByte(byte[] bytes) { - InvalidDataException ex; - ex = Assert.Throws(() => _armFilter.Init(bytes)); + InvalidFormatException ex; + 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..133332c9 100644 --- a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Xz.Filters; using Xunit; @@ -52,14 +53,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([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..f2ac9b68 100644 --- a/tests/SharpCompress.Test/Xz/XZBlockTests.cs +++ b/tests/SharpCompress.Test/Xz/XZBlockTests.cs @@ -43,7 +43,7 @@ public class XzBlockTests : XzTestsBase using Stream badCrcStream = new MemoryStream(bytes); Rewind(badCrcStream); var xzBlock = new XZBlock(badCrcStream, CheckType.CRC64, 8); - var ex = Assert.Throws(() => + var ex = Assert.Throws(() => { ReadBytes(xzBlock, 1); }); diff --git a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs index 8815b7a9..c8f3ac5e 100644 --- a/tests/SharpCompress.Test/Xz/XZHeaderTests.cs +++ b/tests/SharpCompress.Test/Xz/XZHeaderTests.cs @@ -1,4 +1,5 @@ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Xz; using Xunit; @@ -14,7 +15,7 @@ public class XzHeaderTests : XzTestsBase using Stream badMagicNumberStream = new MemoryStream(bytes); var br = new BinaryReader(badMagicNumberStream); var header = new XZHeader(br); - var ex = Assert.Throws(() => + var ex = Assert.Throws(() => { header.Process(); }); @@ -29,7 +30,7 @@ public class XzHeaderTests : XzTestsBase using Stream badCrcStream = new MemoryStream(bytes); var br = new BinaryReader(badCrcStream); var header = new XZHeader(br); - var ex = Assert.Throws(() => + var ex = Assert.Throws(() => { header.Process(); }); @@ -47,7 +48,7 @@ public class XzHeaderTests : XzTestsBase using Stream badFlagStream = new MemoryStream(bytes); var br = new BinaryReader(badFlagStream); var header = new XZHeader(br); - var ex = Assert.Throws(() => + var ex = Assert.Throws(() => { header.Process(); }); diff --git a/tests/SharpCompress.Test/Xz/XZIndexTests.cs b/tests/SharpCompress.Test/Xz/XZIndexTests.cs index b00b9d1a..5e1b55a8 100644 --- a/tests/SharpCompress.Test/Xz/XZIndexTests.cs +++ b/tests/SharpCompress.Test/Xz/XZIndexTests.cs @@ -1,4 +1,5 @@ using System.IO; +using SharpCompress.Common; using SharpCompress.Compressors.Xz; using Xunit; @@ -27,7 +28,7 @@ public class XzIndexTests : XzTestsBase 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()); + Assert.Throws(() => index.Process()); } [Fact] From a283d99e1b833ea2ea8181779593fe17d021fbd3 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 14:48:33 +0100 Subject: [PATCH 0081/1333] compiles --- tests/SharpCompress.Test/Xz/XZBlockTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/SharpCompress.Test/Xz/XZBlockTests.cs b/tests/SharpCompress.Test/Xz/XZBlockTests.cs index f2ac9b68..0d6c7d9a 100644 --- a/tests/SharpCompress.Test/Xz/XZBlockTests.cs +++ b/tests/SharpCompress.Test/Xz/XZBlockTests.cs @@ -1,5 +1,6 @@ using System.IO; using System.Text; +using SharpCompress.Common; using SharpCompress.Compressors.Xz; using Xunit; From e31238d12134b8efa75046f9090cad56b0717709 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 14:48:50 +0100 Subject: [PATCH 0082/1333] fmt --- .../Common/SevenZip/ArchiveReader.cs | 4 ++-- .../Common/SharpCompressException.cs | 16 ++++++---------- src/SharpCompress/Compressors/LZMA/LZipStream.cs | 7 +++---- src/SharpCompress/Readers/ReaderFactory.cs | 4 ++-- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs index 45eb702f..96488124 100644 --- a/src/SharpCompress/Common/SevenZip/ArchiveReader.cs +++ b/src/SharpCompress/Common/SevenZip/ArchiveReader.cs @@ -855,8 +855,8 @@ internal class ArchiveReader ) { throw new InvalidFormatException( - "Decoded stream does not match expected CRC." - ); + "Decoded stream does not match expected CRC." + ); } } } diff --git a/src/SharpCompress/Common/SharpCompressException.cs b/src/SharpCompress/Common/SharpCompressException.cs index 7c68863d..78e8b9e3 100644 --- a/src/SharpCompress/Common/SharpCompressException.cs +++ b/src/SharpCompress/Common/SharpCompressException.cs @@ -4,8 +4,8 @@ namespace SharpCompress.Common; public class SharpCompressException : ApplicationException { - public SharpCompressException() - { } + public SharpCompressException() { } + public SharpCompressException(string message) : base(message) { } @@ -13,21 +13,18 @@ public class SharpCompressException : ApplicationException : base(message, inner) { } } - - public class ArchiveException(string message) : SharpCompressException(message); public class IncompleteArchiveException(string message) : ArchiveException(message); - public class CryptographicException(string message) : SharpCompressException(message); public class ReaderCancelledException(string message) : SharpCompressException(message); public class ExtractionException : SharpCompressException { - public ExtractionException() - { } + public ExtractionException() { } + public ExtractionException(string message) : base(message) { } @@ -41,12 +38,11 @@ public class MultiVolumeExtractionException(string message) : ExtractionExceptio public class InvalidFormatException : ExtractionException { - public InvalidFormatException() - { } + public InvalidFormatException() { } + public InvalidFormatException(string message) : base(message) { } public InvalidFormatException(string message, Exception inner) : base(message, inner) { } } - diff --git a/src/SharpCompress/Compressors/LZMA/LZipStream.cs b/src/SharpCompress/Compressors/LZMA/LZipStream.cs index b7c69150..5bb35a75 100644 --- a/src/SharpCompress/Compressors/LZMA/LZipStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LZipStream.cs @@ -205,7 +205,6 @@ public sealed class LZipStream : Stream ]; public static void WriteHeaderSize(Stream stream) => - // hard coding the dictionary size encoding stream.Write(headerBytes, 0, 6); @@ -213,8 +212,8 @@ public sealed class LZipStream : Stream /// Creates a byte array to communicate the parameters and dictionary size to LzmaStream. /// private static byte[] GetProperties(int dictionarySize) => - [ - // Parameters as per http://www.nongnu.org/lzip/manual/lzip_manual.html#Stream-format + [ + // Parameters as per http://www.nongnu.org/lzip/manual/lzip_manual.html#Stream-format // but encoded as a single byte in the format LzmaStream expects. // literal_context_bits = 3 // literal_pos_state_bits = 0 @@ -225,5 +224,5 @@ public sealed class LZipStream : Stream (byte)((dictionarySize >> 8) & 0xff), (byte)((dictionarySize >> 16) & 0xff), (byte)((dictionarySize >> 24) & 0xff) - ]; + ]; } diff --git a/src/SharpCompress/Readers/ReaderFactory.cs b/src/SharpCompress/Readers/ReaderFactory.cs index 2cb4865f..d56e30c1 100644 --- a/src/SharpCompress/Readers/ReaderFactory.cs +++ b/src/SharpCompress/Readers/ReaderFactory.cs @@ -31,7 +31,7 @@ public static class ReaderFactory } throw new InvalidFormatException( - "Cannot determine compressed stream type. Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ" - ); + "Cannot determine compressed stream type. Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ" + ); } } From e4d5b56951e66a1e7d3bbe95b74eb64e329e8595 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 15:08:32 +0100 Subject: [PATCH 0083/1333] fix more nulls and tests --- .../Archives/GZip/GZipArchiveEntry.cs | 2 +- .../Archives/Rar/RarArchiveEntry.cs | 2 +- .../Archives/Tar/TarArchiveEntry.cs | 2 +- .../Archives/Zip/ZipArchiveEntry.cs | 2 +- src/SharpCompress/Common/FilePart.cs | 2 +- src/SharpCompress/Common/Rar/CryptKey5.cs | 2 +- .../Common/Rar/Headers/ArchiveCryptHeader.cs | 3 -- .../Common/Rar/Headers/FileHeader.cs | 49 +++++++++++-------- .../Common/Rar/Headers/RarHeader.cs | 3 +- .../Common/Rar/Headers/RarHeaderFactory.cs | 8 ++- src/SharpCompress/Common/Rar/RarEntry.cs | 4 +- src/SharpCompress/Common/Rar/RarVolume.cs | 2 +- .../Common/SevenZip/SevenZipFilePart.cs | 1 - .../Common/Zip/StreamingZipFilePart.cs | 1 - src/SharpCompress/Compressors/Deflate/Zlib.cs | 1 - .../Compressors/Deflate64/HuffmanTree.cs | 1 - .../Compressors/Deflate64/InflaterManaged.cs | 1 - .../Compressors/Filters/BranchExecFilter.cs | 1 - .../Compressors/Filters/DeltaFilter.cs | 1 - .../Compressors/Rar/RarBLAKE2spStream.cs | 3 +- .../Rar/UnpackV2017/Unpack.unpack50_cpp.cs | 1 - .../Compressors/Shrink/BitStream.cs | 6 --- .../Compressors/Shrink/ShrinkStream.cs | 4 -- src/SharpCompress/IO/DataDescriptorStream.cs | 1 - src/SharpCompress/NotNullExtensions.cs | 7 ++- src/SharpCompress/Readers/AbstractReader.cs | 2 +- .../Readers/Rar/NonSeekableStreamFilePart.cs | 2 +- src/SharpCompress/Readers/Rar/RarReader.cs | 2 +- src/SharpCompress/Readers/ReaderFactory.cs | 1 - .../GZip/GZipArchiveTests.cs | 4 +- .../SharpCompress.Test/Xz/Filters/BCJTests.cs | 1 - .../Xz/Filters/Lzma2Tests.cs | 1 - 32 files changed, 54 insertions(+), 69 deletions(-) diff --git a/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs b/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs index 459d042d..f00e889c 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchiveEntry.cs @@ -17,7 +17,7 @@ public class GZipArchiveEntry : GZipEntry, IArchiveEntry { part.GetRawStream().Position = part.EntryStartPosition; } - return Parts.Single().GetCompressedStream(); + return Parts.Single().GetCompressedStream().NotNull(); } #region IArchiveEntry Members diff --git a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs index fa59b295..262d7cbe 100644 --- a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs +++ b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs @@ -42,7 +42,7 @@ public class RarArchiveEntry : RarEntry, IArchiveEntry { CheckIncomplete(); return BitConverter.ToUInt32( - parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc, + parts.Select(fp => fp.FileHeader).Single(fh => !fh.IsSplitAfter).FileCrc.NotNull(), 0 ); } diff --git a/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs b/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs index d04c4ef8..770a7109 100644 --- a/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs +++ b/src/SharpCompress/Archives/Tar/TarArchiveEntry.cs @@ -10,7 +10,7 @@ public class TarArchiveEntry : TarEntry, IArchiveEntry internal TarArchiveEntry(TarArchive archive, TarFilePart? part, CompressionType compressionType) : base(part, compressionType) => Archive = archive; - public virtual Stream OpenEntryStream() => Parts.Single().GetCompressedStream(); + public virtual Stream OpenEntryStream() => Parts.Single().GetCompressedStream().NotNull(); #region IArchiveEntry Members diff --git a/src/SharpCompress/Archives/Zip/ZipArchiveEntry.cs b/src/SharpCompress/Archives/Zip/ZipArchiveEntry.cs index a94ed2c6..f13faee7 100644 --- a/src/SharpCompress/Archives/Zip/ZipArchiveEntry.cs +++ b/src/SharpCompress/Archives/Zip/ZipArchiveEntry.cs @@ -9,7 +9,7 @@ public class ZipArchiveEntry : ZipEntry, IArchiveEntry internal ZipArchiveEntry(ZipArchive archive, SeekableZipFilePart? part) : base(part) => Archive = archive; - public virtual Stream OpenEntryStream() => Parts.Single().GetCompressedStream(); + public virtual Stream OpenEntryStream() => Parts.Single().GetCompressedStream().NotNull(); #region IArchiveEntry Members diff --git a/src/SharpCompress/Common/FilePart.cs b/src/SharpCompress/Common/FilePart.cs index 23b8b400..54e3c9f9 100644 --- a/src/SharpCompress/Common/FilePart.cs +++ b/src/SharpCompress/Common/FilePart.cs @@ -11,7 +11,7 @@ public abstract class FilePart internal abstract string? FilePartName { get; } public int Index { get; set; } - internal abstract Stream GetCompressedStream(); + internal abstract Stream? GetCompressedStream(); internal abstract Stream? GetRawStream(); internal bool Skipped { get; set; } } diff --git a/src/SharpCompress/Common/Rar/CryptKey5.cs b/src/SharpCompress/Common/Rar/CryptKey5.cs index 0b802691..90778c5a 100644 --- a/src/SharpCompress/Common/Rar/CryptKey5.cs +++ b/src/SharpCompress/Common/Rar/CryptKey5.cs @@ -17,7 +17,7 @@ internal class CryptKey5 : ICryptKey private byte[] _pswCheck = { }; private byte[] _hashKey = { }; - public CryptKey5(string password, Rar5CryptoInfo rar5CryptoInfo) + public CryptKey5(string? password, Rar5CryptoInfo rar5CryptoInfo) { _password = password ?? ""; _cryptoInfo = rar5CryptoInfo; diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs index 5aa29d49..f819b478 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs @@ -1,8 +1,5 @@ #nullable disable -using System; -using System.Security.Cryptography; -using SharpCompress.Common.Rar.Headers; using SharpCompress.IO; namespace SharpCompress.Common.Rar.Headers; diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index eea8293d..d1bf7b8a 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -1,9 +1,6 @@ -#nullable disable - using System; using System.IO; using System.Linq; -using System.Security.Cryptography; using System.Text; using SharpCompress.IO; #if !Rar2017_64bit @@ -18,7 +15,7 @@ namespace SharpCompress.Common.Rar.Headers; internal class FileHeader : RarHeader { - private byte[] _hash; + private byte[]? _hash; public FileHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) : base(header, reader, headerType) { } @@ -319,6 +316,10 @@ internal class FileHeader : RarHeader if (NewSubHeaderType.SUBHEAD_TYPE_RR.Equals(fileNameBytes)) { + if (SubData is null) + { + throw new InvalidFormatException(); + } RecoverySectors = SubData[8] + (SubData[9] << 8) @@ -340,12 +341,16 @@ internal class FileHeader : RarHeader if (RemainingHeaderBytes(reader) >= 2) { var extendedFlags = reader.ReadUInt16(); - FileLastModifiedTime = ProcessExtendedTimeV4( - extendedFlags, - FileLastModifiedTime, - reader, - 0 - ); + if (FileLastModifiedTime is not null) + { + FileLastModifiedTime = ProcessExtendedTimeV4( + extendedFlags, + FileLastModifiedTime, + reader, + 0 + ); + } + FileCreatedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 1); FileLastAccessedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 2); FileArchivedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 3); @@ -377,7 +382,7 @@ internal class FileHeader : RarHeader var dosTime = reader.ReadUInt32(); time = Utility.DosDateToDateTime(dosTime); } - if ((rmode & 4) == 0) + if ((rmode & 4) == 0 && time is not null) { time = time.Value.AddSeconds(1); } @@ -390,7 +395,11 @@ internal class FileHeader : RarHeader } //10^-7 to 10^-3 - return time.Value.AddMilliseconds(nanosecondHundreds * Math.Pow(10, -4)); + if (time is not null) + { + return time.Value.AddMilliseconds(nanosecondHundreds * Math.Pow(10, -4)); + } + return null; } private static string ConvertPathV4(string path) @@ -406,13 +415,13 @@ internal class FileHeader : RarHeader return path; } - public override string ToString() => FileName; + public override string ToString() => FileName ?? "FileHeader"; private ushort Flags { get; set; } private bool HasFlag(ushort flag) => (Flags & flag) == flag; - internal byte[] FileCrc + internal byte[]? FileCrc { get => _hash; private set => _hash = value; @@ -441,22 +450,22 @@ internal class FileHeader : RarHeader public bool IsRedir => RedirType != 0; public byte RedirFlags { get; private set; } public bool IsRedirDirectory => (RedirFlags & RedirFlagV5.DIRECTORY) != 0; - public string RedirTargetName { get; private set; } + 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; } + 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; } internal long UncompressedSize { get; private set; } - internal string FileName { get; private set; } - internal byte[] SubData { get; private set; } + internal string? FileName { get; private set; } + internal byte[]? SubData { get; private set; } internal int RecoverySectors { get; private set; } internal long DataStartPosition { get; set; } - public Stream PackedStream { get; set; } + public Stream? PackedStream { get; set; } public bool IsSplitBefore => IsRar5 ? HasHeaderFlag(HeaderFlagsV5.SPLIT_BEFORE) : HasFlag(FileFlagsV4.SPLIT_BEFORE); diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs index 0d8648e8..2ae1b9f3 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using SharpCompress.IO; namespace SharpCompress.Common.Rar.Headers; @@ -21,7 +20,7 @@ internal class RarHeader : IRarHeader { return new RarHeader(reader, isRar5, archiveEncoding); } - catch (EndOfStreamException) + catch (InvalidFormatException) { return null; } diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index 74d68fc7..a702c4d1 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; @@ -160,10 +158,10 @@ public class RarHeaderFactory { fh.PackedStream = new RarCryptoWrapper( ms, - fh.R4Salt is null ? fh.Rar5CryptoInfo.Salt : fh.R4Salt, + fh.R4Salt is null ? fh.Rar5CryptoInfo.NotNull().Salt : fh.R4Salt, fh.R4Salt is null - ? new CryptKey5(Options.Password!, fh.Rar5CryptoInfo) - : new CryptKey3(Options.Password!) + ? new CryptKey5(Options.Password, fh.Rar5CryptoInfo.NotNull()) + : new CryptKey3(Options.Password) ); } } diff --git a/src/SharpCompress/Common/Rar/RarEntry.cs b/src/SharpCompress/Common/Rar/RarEntry.cs index a064c2f8..c76c72b6 100644 --- a/src/SharpCompress/Common/Rar/RarEntry.cs +++ b/src/SharpCompress/Common/Rar/RarEntry.cs @@ -20,7 +20,7 @@ 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 => BitConverter.ToUInt32(FileHeader.FileCrc.NotNull(), 0); /// /// The path of the file internal to the Rar Archive. @@ -68,7 +68,7 @@ public abstract class RarEntry : Entry public bool IsRedir => FileHeader.IsRedir; - public string RedirTargetName => FileHeader.RedirTargetName; + public string? RedirTargetName => FileHeader.RedirTargetName; public override string ToString() => string.Format( diff --git a/src/SharpCompress/Common/Rar/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index f3d55393..274ac0a2 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -63,7 +63,7 @@ public abstract class RarVolume : Volume { var part = CreateFilePart(lastMarkHeader!, fh); var buffer = new byte[fh.CompressedSize]; - part.GetCompressedStream().Read(buffer, 0, buffer.Length); + part.GetCompressedStream().NotNull().Read(buffer, 0, buffer.Length); Comment = Encoding.UTF8.GetString(buffer, 0, buffer.Length - 1); } } diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index ac355828..31c4a24b 100644 --- a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs +++ b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using SharpCompress.IO; diff --git a/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs b/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs index 97e44b6b..a3fa3caa 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipFilePart.cs @@ -1,5 +1,4 @@ using System.IO; -using System.Net.Sockets; using SharpCompress.Common.Zip.Headers; using SharpCompress.Compressors.Deflate; using SharpCompress.IO; diff --git a/src/SharpCompress/Compressors/Deflate/Zlib.cs b/src/SharpCompress/Compressors/Deflate/Zlib.cs index b395029e..1358e01b 100644 --- a/src/SharpCompress/Compressors/Deflate/Zlib.cs +++ b/src/SharpCompress/Compressors/Deflate/Zlib.cs @@ -62,7 +62,6 @@ // // ----------------------------------------------------------------------- -using System; using System.IO; using SharpCompress.Common; diff --git a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs index 4c9e7e8b..aac88b05 100644 --- a/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs +++ b/src/SharpCompress/Compressors/Deflate64/HuffmanTree.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; -using System.IO; using SharpCompress.Common; namespace SharpCompress.Compressors.Deflate64; diff --git a/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs b/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs index 2e4d8377..101188db 100644 --- a/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs +++ b/src/SharpCompress/Compressors/Deflate64/InflaterManaged.cs @@ -30,7 +30,6 @@ using System; using System.Diagnostics; -using System.IO; using SharpCompress.Compressors.Deflate; namespace SharpCompress.Compressors.Deflate64; diff --git a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs index 7f887720..df95c838 100644 --- a/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs +++ b/src/SharpCompress/Compressors/Filters/BranchExecFilter.cs @@ -5,7 +5,6 @@ */ using System; -using System.IO; using System.Runtime.CompilerServices; using SharpCompress.Common; diff --git a/src/SharpCompress/Compressors/Filters/DeltaFilter.cs b/src/SharpCompress/Compressors/Filters/DeltaFilter.cs index 85ec9b15..a6954116 100644 --- a/src/SharpCompress/Compressors/Filters/DeltaFilter.cs +++ b/src/SharpCompress/Compressors/Filters/DeltaFilter.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace SharpCompress.Compressors.Filters diff --git a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs index 7c897176..cf93cffb 100644 --- a/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using SharpCompress.Common; using SharpCompress.Common.Rar.Headers; @@ -93,7 +92,7 @@ internal class RarBLAKE2spStream : RarStream { this.readStream = readStream; disableCRCCheck = fileHeader.IsEncrypted; - _hash = fileHeader.FileCrc; + _hash = fileHeader.FileCrc.NotNull(); _blake2sp = new BLAKE2SP(); ResetCrc(); } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs index 143e3d31..2ba0d80c 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack50_cpp.cs @@ -3,7 +3,6 @@ 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 diff --git a/src/SharpCompress/Compressors/Shrink/BitStream.cs b/src/SharpCompress/Compressors/Shrink/BitStream.cs index 949ee6c3..9dc534e0 100644 --- a/src/SharpCompress/Compressors/Shrink/BitStream.cs +++ b/src/SharpCompress/Compressors/Shrink/BitStream.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace SharpCompress.Compressors.Shrink { internal class BitStream diff --git a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs index 65b2eb37..258f2c42 100644 --- a/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs +++ b/src/SharpCompress/Compressors/Shrink/ShrinkStream.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace SharpCompress.Compressors.Shrink; diff --git a/src/SharpCompress/IO/DataDescriptorStream.cs b/src/SharpCompress/IO/DataDescriptorStream.cs index 1802556c..801f9fa7 100644 --- a/src/SharpCompress/IO/DataDescriptorStream.cs +++ b/src/SharpCompress/IO/DataDescriptorStream.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.CompilerServices; namespace SharpCompress.IO; diff --git a/src/SharpCompress/NotNullExtensions.cs b/src/SharpCompress/NotNullExtensions.cs index 88e95c41..c8ae4762 100644 --- a/src/SharpCompress/NotNullExtensions.cs +++ b/src/SharpCompress/NotNullExtensions.cs @@ -8,9 +8,10 @@ namespace SharpCompress; public static class NotNullExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Empty(this IEnumerable? source) => source ?? Enumerable.Empty(); - + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Empty(this T? source) { if (source is null) @@ -21,6 +22,7 @@ public static class NotNullExtensions } #if NETFRAMEWORK || NETSTANDARD +[MethodImpl(MethodImplOptions.AggressiveInlining)] public static T NotNull(this T? obj, string? message = null) where T : class { @@ -31,6 +33,7 @@ public static class NotNullExtensions return obj; } +[MethodImpl(MethodImplOptions.AggressiveInlining)] public static T NotNull(this T? obj, string? message = null) where T : struct { @@ -42,6 +45,7 @@ public static class NotNullExtensions } #else + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T NotNull( [NotNull] this T? obj, [CallerArgumentExpression(nameof(obj))] string? paramName = null @@ -52,6 +56,7 @@ public static class NotNullExtensions return obj; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T NotNull( [NotNull] this T? obj, [CallerArgumentExpression(nameof(obj))] string? paramName = null diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index b36acd53..c99c3966 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -192,7 +192,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// /// 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(this, decompressed.NotNull()); protected virtual EntryStream GetEntryStream() => CreateEntryStream(Entry.Parts.First().GetCompressedStream()); diff --git a/src/SharpCompress/Readers/Rar/NonSeekableStreamFilePart.cs b/src/SharpCompress/Readers/Rar/NonSeekableStreamFilePart.cs index 3a43e60c..94ee6bf2 100644 --- a/src/SharpCompress/Readers/Rar/NonSeekableStreamFilePart.cs +++ b/src/SharpCompress/Readers/Rar/NonSeekableStreamFilePart.cs @@ -9,7 +9,7 @@ internal class NonSeekableStreamFilePart : RarFilePart internal NonSeekableStreamFilePart(MarkHeader mh, FileHeader fh, int index = 0) : base(mh, fh, index) { } - internal override Stream GetCompressedStream() => FileHeader.PackedStream; + internal override Stream? GetCompressedStream() => FileHeader.PackedStream; internal override Stream? GetRawStream() => FileHeader.PackedStream; diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index 2398cfac..245001e3 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -78,7 +78,7 @@ public abstract class RarReader : AbstractReader return CreateEntryStream(new RarCrcStream(UnpackV1.Value, Entry.FileHeader, stream)); } - if (Entry.FileHeader.FileCrc.Length > 5) + if (Entry.FileHeader.FileCrc?.Length > 5) { return CreateEntryStream( new RarBLAKE2spStream(UnpackV2017.Value, Entry.FileHeader, stream) diff --git a/src/SharpCompress/Readers/ReaderFactory.cs b/src/SharpCompress/Readers/ReaderFactory.cs index d56e30c1..de085d92 100644 --- a/src/SharpCompress/Readers/ReaderFactory.cs +++ b/src/SharpCompress/Readers/ReaderFactory.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using SharpCompress.Common; diff --git a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs index 80a9a9a1..56b5cd2b 100644 --- a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs @@ -1,9 +1,9 @@ -using System; 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; @@ -62,7 +62,7 @@ public class GZipArchiveTests : ArchiveTests var jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg"); using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")); using var archive = GZipArchive.Open(stream); - Assert.Throws(() => archive.AddEntry("jpg\\test.jpg", jpg)); + Assert.Throws(() => archive.AddEntry("jpg\\test.jpg", jpg)); archive.SaveTo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz")); } diff --git a/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs b/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs index 9dbdf348..a53565b7 100644 --- a/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/BCJTests.cs @@ -3,7 +3,6 @@ * */ -using System.IO; using SharpCompress.Common; using SharpCompress.Compressors.Xz.Filters; using Xunit; diff --git a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs index 133332c9..12db0746 100644 --- a/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs +++ b/tests/SharpCompress.Test/Xz/Filters/Lzma2Tests.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using SharpCompress.Common; using SharpCompress.Compressors.Xz.Filters; using Xunit; From 5d9c99508dd9406c738de01a1ae15d329de6ff6e Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Tue, 23 Apr 2024 15:08:50 +0100 Subject: [PATCH 0084/1333] fmt --- src/SharpCompress/Common/Rar/Headers/FileHeader.cs | 10 +++++----- .../Common/Rar/Headers/RarHeaderFactory.cs | 9 +++++++-- src/SharpCompress/NotNullExtensions.cs | 5 +++-- src/SharpCompress/Readers/AbstractReader.cs | 3 ++- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index d1bf7b8a..0aa9fc0d 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -344,11 +344,11 @@ internal class FileHeader : RarHeader if (FileLastModifiedTime is not null) { FileLastModifiedTime = ProcessExtendedTimeV4( - extendedFlags, - FileLastModifiedTime, - reader, - 0 - ); + extendedFlags, + FileLastModifiedTime, + reader, + 0 + ); } FileCreatedTime = ProcessExtendedTimeV4(extendedFlags, null, reader, 1); diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index a702c4d1..902e595f 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -158,9 +158,14 @@ public class RarHeaderFactory { fh.PackedStream = new RarCryptoWrapper( ms, - fh.R4Salt is null ? fh.Rar5CryptoInfo.NotNull().Salt : fh.R4Salt, fh.R4Salt is null - ? new CryptKey5(Options.Password, fh.Rar5CryptoInfo.NotNull()) + ? fh.Rar5CryptoInfo.NotNull().Salt + : fh.R4Salt, + fh.R4Salt is null + ? new CryptKey5( + Options.Password, + fh.Rar5CryptoInfo.NotNull() + ) : new CryptKey3(Options.Password) ); } diff --git a/src/SharpCompress/NotNullExtensions.cs b/src/SharpCompress/NotNullExtensions.cs index c8ae4762..956a4fde 100644 --- a/src/SharpCompress/NotNullExtensions.cs +++ b/src/SharpCompress/NotNullExtensions.cs @@ -11,6 +11,7 @@ public static class NotNullExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Empty(this IEnumerable? source) => source ?? Enumerable.Empty(); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IEnumerable Empty(this T? source) { @@ -22,7 +23,7 @@ public static class NotNullExtensions } #if NETFRAMEWORK || NETSTANDARD -[MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T NotNull(this T? obj, string? message = null) where T : class { @@ -33,7 +34,7 @@ public static class NotNullExtensions return obj; } -[MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T NotNull(this T? obj, string? message = null) where T : struct { diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index c99c3966..da6279a9 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -192,7 +192,8 @@ public abstract class AbstractReader : IReader, IReaderExtracti /// /// Retains a reference to the entry stream, so we can check whether it completed later. /// - protected EntryStream CreateEntryStream(Stream? decompressed) => new(this, decompressed.NotNull()); + protected EntryStream CreateEntryStream(Stream? decompressed) => + new(this, decompressed.NotNull()); protected virtual EntryStream GetEntryStream() => CreateEntryStream(Entry.Parts.First().GetCompressedStream()); From dbbc7c81321e7e3e20f5d610a005f8dfbadd1e65 Mon Sep 17 00:00:00 2001 From: blokyk Date: Wed, 24 Apr 2024 03:13:13 +0200 Subject: [PATCH 0085/1333] fix(tar): prevent infinite loop when reading corrupted archive --- src/SharpCompress/Archives/Tar/TarArchive.cs | 2 ++ tests/SharpCompress.Test/Tar/TarReaderTests.cs | 15 +++++++++++++++ tests/TestArchives/Archives/TarCorrupted.tar | Bin 0 -> 962560 bytes 3 files changed, 17 insertions(+) create mode 100644 tests/TestArchives/Archives/TarCorrupted.tar diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index 3b9a45ed..de37df89 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -189,6 +189,8 @@ public class TarArchive : AbstractWritableArchive CompressionType.None ); } + } else { + throw new IncompleteArchiveException("Failed to read TAR header"); } } } diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index bb10db98..3b6a6a88 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -183,6 +183,21 @@ public class TarReaderTests : ReaderTests 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()); + } + #if !NETFRAMEWORK [Fact] public void Tar_GZip_With_Symlink_Entries() diff --git a/tests/TestArchives/Archives/TarCorrupted.tar b/tests/TestArchives/Archives/TarCorrupted.tar new file mode 100644 index 0000000000000000000000000000000000000000..a21c4fe53e7631fdf5fe59d82b6d550219c7072f GIT binary patch literal 962560 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 z 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

RN{If#mGH|ESCi0^!6payx|;su5_W~K#)v})iQ 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 literal 0 HcmV?d00001 From 9483856439950fe8c5dcecebdc97be3bbeb6cb15 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Wed, 24 Apr 2024 09:17:42 +0100 Subject: [PATCH 0086/1333] fmt --- src/SharpCompress/Archives/Tar/TarArchive.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/Archives/Tar/TarArchive.cs b/src/SharpCompress/Archives/Tar/TarArchive.cs index de37df89..fdf8cd42 100644 --- a/src/SharpCompress/Archives/Tar/TarArchive.cs +++ b/src/SharpCompress/Archives/Tar/TarArchive.cs @@ -189,7 +189,9 @@ public class TarArchive : AbstractWritableArchive CompressionType.None ); } - } else { + } + else + { throw new IncompleteArchiveException("Failed to read TAR header"); } } From 49ce17b7598466e7bb56200461dfbfe91c175f52 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Thu, 25 Apr 2024 08:35:52 +0100 Subject: [PATCH 0087/1333] update zstdsharp.port and net8 is only trimmable --- Directory.Packages.props | 5 +- src/SharpCompress/SharpCompress.csproj | 11 ++- src/SharpCompress/packages.lock.json | 82 ++++++++++----------- tests/SharpCompress.Test/packages.lock.json | 34 +++++---- 4 files changed, 68 insertions(+), 64 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 6bc10b2c..59eb5567 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,6 +3,7 @@ + @@ -12,6 +13,6 @@ - + - + \ No newline at end of file diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index a21d1726..39b19e0e 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -21,24 +21,29 @@ true true snupkg - true latest true README.md - + + true + + - + + + + diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json index e6e0a13d..d2ca0eec 100644 --- a/src/SharpCompress/packages.lock.json +++ b/src/SharpCompress/packages.lock.json @@ -2,6 +2,15 @@ "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, )", @@ -44,22 +53,14 @@ }, "ZstdSharp.Port": { "type": "Direct", - "requested": "[0.7.6, )", - "resolved": "0.7.6", - "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "requested": "[0.8.0, )", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "5.0.0", "System.Memory": "4.5.5" } }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", "resolved": "8.0.0", @@ -100,6 +101,15 @@ } }, ".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, )", @@ -142,22 +152,14 @@ }, "ZstdSharp.Port": { "type": "Direct", - "requested": "[0.7.6, )", - "resolved": "0.7.6", - "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "requested": "[0.8.0, )", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "5.0.0", "System.Memory": "4.5.5" } }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", "resolved": "8.0.0", @@ -198,6 +200,12 @@ } }, ".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, )", @@ -220,9 +228,9 @@ }, "ZstdSharp.Port": { "type": "Direct", - "requested": "[0.7.6, )", - "resolved": "0.7.6", - "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "requested": "[0.8.0, )", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", "dependencies": { "System.Runtime.CompilerServices.Unsafe": "6.0.0" } @@ -265,18 +273,6 @@ } }, "net6.0": { - "Microsoft.NET.ILLink.Analyzers": { - "type": "Direct", - "requested": "[7.0.100-1.23211.1, )", - "resolved": "7.0.100-1.23211.1", - "contentHash": "0GvbEgDGcUQA9KuWcQU1WwYHXt1tBzNr1Nls/M57rM7NA/AndFwCaCEoJpJkmxRY7xLlPDBnmGp8h5+FNqUngg==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[7.0.100-1.23211.1, )", - "resolved": "7.0.100-1.23211.1", - "contentHash": "tvG8XZYLjT0o3WicCyKBZysVWo1jC9HdCFmNRmddx3WbAz0UCsd0qKZqpiEo99VLA8Re+FzWK51OcRldQPbt2Q==" - }, "Microsoft.SourceLink.GitHub": { "type": "Direct", "requested": "[8.0.0, )", @@ -289,9 +285,9 @@ }, "ZstdSharp.Port": { "type": "Direct", - "requested": "[0.7.6, )", - "resolved": "0.7.6", - "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==" + "requested": "[0.8.0, )", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==" }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", @@ -323,9 +319,9 @@ }, "ZstdSharp.Port": { "type": "Direct", - "requested": "[0.7.6, )", - "resolved": "0.7.6", - "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==" + "requested": "[0.8.0, )", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==" }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", diff --git a/tests/SharpCompress.Test/packages.lock.json b/tests/SharpCompress.Test/packages.lock.json index a7d04fce..4ef26a3c 100644 --- a/tests/SharpCompress.Test/packages.lock.json +++ b/tests/SharpCompress.Test/packages.lock.json @@ -59,14 +59,6 @@ "xunit.extensibility.execution": "2.4.0" } }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", "resolved": "8.0.0", @@ -179,10 +171,20 @@ "sharpcompress": { "type": "Project", "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "[8.0.0, )", "Microsoft.SourceLink.GitHub": "[8.0.0, )", "System.Memory": "[4.5.5, )", "System.Text.Encoding.CodePages": "[8.0.0, )", - "ZstdSharp.Port": "[0.7.6, )" + "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" } }, "Microsoft.SourceLink.GitHub": { @@ -218,9 +220,9 @@ }, "ZstdSharp.Port": { "type": "CentralTransitive", - "requested": "[0.7.6, )", - "resolved": "0.7.6", - "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==", + "requested": "[0.8.0, )", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "5.0.0", "System.Memory": "4.5.5" @@ -384,7 +386,7 @@ "type": "Project", "dependencies": { "Microsoft.SourceLink.GitHub": "[8.0.0, )", - "ZstdSharp.Port": "[0.7.6, )" + "ZstdSharp.Port": "[0.8.0, )" } }, "Microsoft.SourceLink.GitHub": { @@ -399,9 +401,9 @@ }, "ZstdSharp.Port": { "type": "CentralTransitive", - "requested": "[0.7.6, )", - "resolved": "0.7.6", - "contentHash": "opRgjMeBTNpZQyJaZOWCHGGpQ+d9T2Eg3q8JPeBj65srJBf1F3JidO2h7sYkK2s0Mcga+skrqypQY39CF8kcfA==" + "requested": "[0.8.0, )", + "resolved": "0.8.0", + "contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==" } } } From 1393629bc5db0b806c7033a062670a5bb7a4ae80 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Sat, 27 Apr 2024 06:15:29 +0100 Subject: [PATCH 0088/1333] Mark sourcelink as PrivateAssets="All" --- Directory.Packages.props | 4 ++-- src/SharpCompress/packages.lock.json | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 59eb5567..af422ec8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ - + @@ -15,4 +15,4 @@ - \ No newline at end of file + diff --git a/src/SharpCompress/packages.lock.json b/src/SharpCompress/packages.lock.json index d2ca0eec..b06d9c98 100644 --- a/src/SharpCompress/packages.lock.json +++ b/src/SharpCompress/packages.lock.json @@ -303,9 +303,9 @@ "net8.0": { "Microsoft.NET.ILLink.Tasks": { "type": "Direct", - "requested": "[8.0.2, )", - "resolved": "8.0.2", - "contentHash": "hKTrehpfVzOhAz0mreaTAZgbz0DrMEbWq4n3hAo8Ks6WdxdqQhNPvzOqn9VygKuWf1bmxPdraqzTaXriO/sn0A==" + "requested": "[8.0.4, )", + "resolved": "8.0.4", + "contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw==" }, "Microsoft.SourceLink.GitHub": { "type": "Direct", From c635f008990cce07ec86514a69470b97bd42f295 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Sat, 27 Apr 2024 09:12:17 +0100 Subject: [PATCH 0089/1333] mark as 0.37.1 --- src/SharpCompress/SharpCompress.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index 39b19e0e..fd6ab0a6 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -2,9 +2,9 @@ SharpCompress - Pure C# Decompression/Compression en-US - 0.37.0 - 0.37.0 - 0.37.0 + 0.37.1 + 0.37.1 + 0.37.1 Adam Hathcock net462;netstandard2.0;netstandard2.1;net6.0;net8.0 SharpCompress From 446852c7d0796e7ce375ebf136a05bbda47ee237 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Sat, 27 Apr 2024 09:34:05 +0100 Subject: [PATCH 0090/1333] really fix source link and central usage --- Directory.Packages.props | 2 +- build/build.csproj | 2 +- build/packages.lock.json | 4 +- src/SharpCompress/SharpCompress.csproj | 4 +- tests/SharpCompress.Test/packages.lock.json | 42 --------------------- 5 files changed, 7 insertions(+), 47 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index af422ec8..e128f52f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ - + diff --git a/build/build.csproj b/build/build.csproj index 8e837d3a..e0dffc7f 100644 --- a/build/build.csproj +++ b/build/build.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net8.0 diff --git a/build/packages.lock.json b/build/packages.lock.json index 52565140..8a8fa2c0 100644 --- a/build/packages.lock.json +++ b/build/packages.lock.json @@ -1,7 +1,7 @@ { - "version": 1, + "version": 2, "dependencies": { - "net7.0": { + "net8.0": { "Bullseye": { "type": "Direct", "requested": "[5.0.0, )", diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index fd6ab0a6..ceb80a08 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -30,7 +30,9 @@ true - + + all + diff --git a/tests/SharpCompress.Test/packages.lock.json b/tests/SharpCompress.Test/packages.lock.json index 4ef26a3c..baeef64f 100644 --- a/tests/SharpCompress.Test/packages.lock.json +++ b/tests/SharpCompress.Test/packages.lock.json @@ -59,11 +59,6 @@ "xunit.extensibility.execution": "2.4.0" } }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, "Microsoft.CodeCoverage": { "type": "Transitive", "resolved": "17.9.0", @@ -74,11 +69,6 @@ "resolved": "1.0.3", "contentHash": "IzAV30z22ESCeQfxP29oVf4qEo8fBGXLXSU6oacv/9Iqe6PzgHDKCaWfwMBak7bSJQM0F5boXWoZS+kChztRIQ==" }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, "Microsoft.TestPlatform.ObjectModel": { "type": "Transitive", "resolved": "17.9.0", @@ -172,7 +162,6 @@ "type": "Project", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "[8.0.0, )", - "Microsoft.SourceLink.GitHub": "[8.0.0, )", "System.Memory": "[4.5.5, )", "System.Text.Encoding.CodePages": "[8.0.0, )", "ZstdSharp.Port": "[0.8.0, )" @@ -187,16 +176,6 @@ "System.Threading.Tasks.Extensions": "4.5.4" } }, - "Microsoft.SourceLink.GitHub": { - "type": "CentralTransitive", - "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": "CentralTransitive", "requested": "[4.5.5, )", @@ -282,21 +261,11 @@ "xunit.extensibility.execution": "2.4.0" } }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" - }, "Microsoft.CodeCoverage": { "type": "Transitive", "resolved": "17.9.0", "contentHash": "RGD37ZSrratfScYXm7M0HjvxMxZyWZL4jm+XgMZbkIY1UPgjUpbNA/t+WTGj/rC/0Hm9A3IrH3ywbKZkOCnoZA==" }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" - }, "Microsoft.TestPlatform.ObjectModel": { "type": "Transitive", "resolved": "17.9.0", @@ -385,20 +354,9 @@ "sharpcompress": { "type": "Project", "dependencies": { - "Microsoft.SourceLink.GitHub": "[8.0.0, )", "ZstdSharp.Port": "[0.8.0, )" } }, - "Microsoft.SourceLink.GitHub": { - "type": "CentralTransitive", - "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": "CentralTransitive", "requested": "[0.8.0, )", From 6fc4b045fde70c42df738d203c453082354e9558 Mon Sep 17 00:00:00 2001 From: Adam Hathcock Date: Sat, 27 Apr 2024 09:34:32 +0100 Subject: [PATCH 0091/1333] mark for 0.37.2 --- src/SharpCompress/SharpCompress.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/SharpCompress.csproj b/src/SharpCompress/SharpCompress.csproj index ceb80a08..cbceba12 100644 --- a/src/SharpCompress/SharpCompress.csproj +++ b/src/SharpCompress/SharpCompress.csproj @@ -2,9 +2,9 @@ SharpCompress - Pure C# Decompression/Compression en-US - 0.37.1 - 0.37.1 - 0.37.1 + 0.37.2 + 0.37.2 + 0.37.2 Adam Hathcock net462;netstandard2.0;netstandard2.1;net6.0;net8.0 SharpCompress From a9601ef8482ca9c9241adea67af16d503bb8202f Mon Sep 17 00:00:00 2001 From: Daniel Nash Date: Mon, 3 Jun 2024 12:41:11 -0400 Subject: [PATCH 0092/1333] Tar: Add processing for the LongLink header type Fixes #846 --- .../Common/Tar/Headers/TarHeader.cs | 72 ++++++++++++------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 68a72e8a..e9aa343c 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -101,57 +101,79 @@ internal sealed class TarHeader internal bool Read(BinaryReader reader) { - var buffer = ReadBlock(reader); - if (buffer.Length == 0) - { - return false; - } + string? longName = null; + string? longLinkName = null; + var hasLongValue = true; + byte[] buffer; + EntryType entryType; - // for symlinks, additionally read the linkname - if (ReadEntryType(buffer) == EntryType.SymLink) + do { - LinkName = ArchiveEncoding.Decode(buffer, 157, 100).TrimNulls(); - } - - if (ReadEntryType(buffer) == EntryType.LongName) - { - Name = ReadLongName(reader, buffer); buffer = ReadBlock(reader); - } - else - { - Name = ArchiveEncoding.Decode(buffer, 0, 100).TrimNulls(); - } - EntryType = ReadEntryType(buffer); + 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(); + } + Mode = ReadAsciiInt64Base8(buffer, 100, 7); - if (EntryType == EntryType.Directory) + + if (entryType == EntryType.Directory) { Mode |= 0b1_000_000_000; } UserId = ReadAsciiInt64Base8oldGnu(buffer, 108, 7); GroupId = ReadAsciiInt64Base8oldGnu(buffer, 116, 7); - var unixTimeStamp = ReadAsciiInt64Base8(buffer, 136, 11); - LastModifiedTime = EPOCH.AddSeconds(unixTimeStamp).ToLocalTime(); + 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); - namePrefix = namePrefix.TrimNulls(); + var namePrefix = ArchiveEncoding.Decode(buffer, 345, 157).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; } From 525b309d37d920c606eeae279a9ed3101ef19904 Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:33:32 +0200 Subject: [PATCH 0093/1333] Add failing test --- tests/SharpCompress.Test/GZip/GZipArchiveTests.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs index 80a9a9a1..a8e215f7 100644 --- a/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs +++ b/tests/SharpCompress.Test/GZip/GZipArchiveTests.cs @@ -4,6 +4,7 @@ using System.Linq; using SharpCompress.Archives; using SharpCompress.Archives.GZip; using SharpCompress.Archives.Tar; +using SharpCompress.Common; using Xunit; namespace SharpCompress.Test.GZip; @@ -106,7 +107,7 @@ public class GZipArchiveTests : ArchiveTests } [Fact] - public void TestGzCrcWithMostSignificaltBitNotNegative() + public void TestGzCrcWithMostSignificantBitNotNegative() { using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")); using var archive = GZipArchive.Open(stream); @@ -116,4 +117,12 @@ 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); + } } From 49f5ceaa9b548040779caa21e6cbb485dd1e2747 Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:34:06 +0200 Subject: [PATCH 0094/1333] Fix GZipArchive getting Type set to ArchiveType.Tar --- src/SharpCompress/Archives/GZip/GZipArchive.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/Archives/GZip/GZipArchive.cs b/src/SharpCompress/Archives/GZip/GZipArchive.cs index cec2f640..ea46e8d0 100644 --- a/src/SharpCompress/Archives/GZip/GZipArchive.cs +++ b/src/SharpCompress/Archives/GZip/GZipArchive.cs @@ -101,7 +101,7 @@ public class GZipArchive : AbstractWritableArchive ///

/// private GZipArchive(SourceStream sourceStream) - : base(ArchiveType.Tar, sourceStream) { } + : base(ArchiveType.GZip, sourceStream) { } protected override IEnumerable LoadVolumes(SourceStream sourceStream) { From 5c1149aa8b470826c70d154c0285d8d79e1b0e8e Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Sat, 8 Jun 2024 17:22:20 +0200 Subject: [PATCH 0095/1333] #844 --- src/SharpCompress/Common/Rar/RarVolume.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/SharpCompress/Common/Rar/RarVolume.cs b/src/SharpCompress/Common/Rar/RarVolume.cs index f3d55393..d05e16c2 100644 --- a/src/SharpCompress/Common/Rar/RarVolume.cs +++ b/src/SharpCompress/Common/Rar/RarVolume.cs @@ -61,9 +61,8 @@ public abstract class RarVolume : Volume var fh = (FileHeader)header; if (fh.FileName == "CMT") { - var part = CreateFilePart(lastMarkHeader!, fh); var buffer = new byte[fh.CompressedSize]; - part.GetCompressedStream().Read(buffer, 0, buffer.Length); + fh.PackedStream.Read(buffer, 0, buffer.Length); Comment = Encoding.UTF8.GetString(buffer, 0, buffer.Length - 1); } } From 33dd519f5630c54425e06b8264995eb5ad6d5682 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Sat, 8 Jun 2024 18:26:12 +0200 Subject: [PATCH 0096/1333] Throw exception when bzip2 is corrupt --- .../Compressors/BZip2/CBZip2InputStream.cs | 9 +++++--- .../BZip2/BZip2ReaderTests.cs | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 tests/SharpCompress.Test/BZip2/BZip2ReaderTests.cs diff --git a/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs b/src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs index a541a04d..a467942f 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,14 +42,17 @@ internal class CBZip2InputStream : Stream private static void Cadvise() { //System.out.Println("CRC Error"); - //throw new CCoruptionError(); + throw new InvalidOperationException("BZip2 error"); } private static void BadBGLengths() => Cadvise(); private static void BitStreamEOF() => Cadvise(); - private static void CompressedStreamEOF() => Cadvise(); + private static void CompressedStreamEOF() + { + throw new InvalidOperationException("BZip2 compressed file ends unexpectedly"); + } private void MakeMaps() { diff --git a/tests/SharpCompress.Test/BZip2/BZip2ReaderTests.cs b/tests/SharpCompress.Test/BZip2/BZip2ReaderTests.cs new file mode 100644 index 00000000..e0fa0583 --- /dev/null +++ b/tests/SharpCompress.Test/BZip2/BZip2ReaderTests.cs @@ -0,0 +1,21 @@ +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)); + } +} From b7b78edaa311ad25409092d1168e25f4a99799d1 Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Sat, 22 Jun 2024 00:09:25 -0500 Subject: [PATCH 0097/1333] Fixed extractions after first ZIP64 entry is read from stream --- .../Common/Zip/StreamingZipHeaderFactory.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index c0af5408..c165211e 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -49,7 +49,17 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory 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 lastModifiedTime = reader.ReadUInt16(); + var lastModifiedDate = reader.ReadUInt16(); + var crc = reader.ReadUInt32(); if (crc == POST_DATA_DESCRIPTOR) { @@ -62,7 +72,6 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory var uncompressed_size = reader.ReadUInt32(); // Check if we have header or 64bit DataDescriptor - headerBytes = reader.ReadUInt32(); var test_header = !(headerBytes == 0x04034b50 || headerBytes == 0x02014b50); var test_64bit = ((long)uncompressed_size << 32) | compressed_size; @@ -80,6 +89,9 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory 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 From eee518b7fad11f04b1bc8c0938f27e622ae7b14d Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Sun, 23 Jun 2024 22:29:33 -0500 Subject: [PATCH 0098/1333] Reworked ZIP64 handling to separate block The last commit made in this branch messed up some ZIP reading and caused a bunch of tests to fail. These changes branch off ZIP64 logic into its own block so that data is read correctly for 64 and non-64 entries. --- .../Common/Zip/StreamingZipHeaderFactory.cs | 52 ++++++++++++++++--- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index c165211e..6e786560 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -34,13 +34,7 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory ZipHeader? header; var reader = new BinaryReader(rewindableStream); uint headerBytes = 0; - if ( - _lastEntryHeader != null - && ( - FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) - || _lastEntryHeader.IsZip64 - ) - ) + if (_lastEntryHeader != null && FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)) { if (_lastEntryHeader.Part is null) { @@ -52,15 +46,57 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null; + 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 + headerBytes = reader.ReadUInt32(); + 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; + } + } + 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 lastModifiedTime = reader.ReadUInt16(); var lastModifiedDate = reader.ReadUInt16(); + var lastModifiedTime = reader.ReadUInt16(); var crc = reader.ReadUInt32(); + if (crc == POST_DATA_DESCRIPTOR) { crc = reader.ReadUInt32(); From 9bc0a1d7c7fac9457abc6721a672dbc82bced811 Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Sun, 23 Jun 2024 22:30:34 -0500 Subject: [PATCH 0099/1333] Null reference checking Reorders this null reference check to avoid throwing a null reference exception. --- src/SharpCompress/Common/Zip/ZipHeaderFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 40fe178f..4c7c6a93 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -56,11 +56,11 @@ internal class ZipHeaderFactory case POST_DATA_DESCRIPTOR: { if ( + _lastEntryHeader != null && FlagUtility.HasFlag( _lastEntryHeader.NotNull().Flags, HeaderFlags.UsePostDataDescriptor ) - && _lastEntryHeader != null ) { _lastEntryHeader.Crc = reader.ReadUInt32(); From b89de6caadc4c044737a7bc1ec5239729c15e899 Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Mon, 24 Jun 2024 17:19:53 -0500 Subject: [PATCH 0100/1333] Fix formatting --- .../Common/Zip/StreamingZipHeaderFactory.cs | 9 +++++++-- src/SharpCompress/Common/Zip/ZipHeaderFactory.cs | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 6e786560..508dfd1a 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -34,7 +34,10 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory ZipHeader? header; var reader = new BinaryReader(rewindableStream); uint headerBytes = 0; - if (_lastEntryHeader != null && FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)) + if ( + _lastEntryHeader != null + && FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) + ) { if (_lastEntryHeader.Part is null) { @@ -83,7 +86,9 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory if (_lastEntryHeader.Part is null) continue; - reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation(ref rewindableStream); + reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation( + ref rewindableStream + ); var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null; diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 4c7c6a93..45869ff6 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -56,8 +56,8 @@ internal class ZipHeaderFactory case POST_DATA_DESCRIPTOR: { if ( - _lastEntryHeader != null && - FlagUtility.HasFlag( + _lastEntryHeader != null + && FlagUtility.HasFlag( _lastEntryHeader.NotNull().Flags, HeaderFlags.UsePostDataDescriptor ) From 061273be227e6846638b564f92046ec9c7b942f1 Mon Sep 17 00:00:00 2001 From: GordonJ Date: Tue, 25 Jun 2024 11:35:11 -0500 Subject: [PATCH 0101/1333] Added Export and (un)Reduce to sharpCompress --- src/SharpCompress/Common/CompressionType.cs | 7 +- .../Common/Zip/ZipCompressionMethod.cs | 5 + src/SharpCompress/Common/Zip/ZipEntry.cs | 5 + src/SharpCompress/Common/Zip/ZipFilePart.cs | 27 + .../Compressors/Explode/ExplodeStream.cs | 746 ++++++++++++++++++ .../Compressors/Explode/HuftTree.cs | 269 +++++++ .../Compressors/Reduce/ReduceStream.cs | 249 ++++++ 7 files changed, 1307 insertions(+), 1 deletion(-) create mode 100644 src/SharpCompress/Compressors/Explode/ExplodeStream.cs create mode 100644 src/SharpCompress/Compressors/Explode/HuftTree.cs create mode 100644 src/SharpCompress/Compressors/Reduce/ReduceStream.cs diff --git a/src/SharpCompress/Common/CompressionType.cs b/src/SharpCompress/Common/CompressionType.cs index 20f166c4..927c1e7a 100644 --- a/src/SharpCompress/Common/CompressionType.cs +++ b/src/SharpCompress/Common/CompressionType.cs @@ -16,5 +16,10 @@ public enum CompressionType Unknown, Deflate64, Shrink, - Lzw + Lzw, + Reduce1, + Reduce2, + Reduce3, + Reduce4, + Explode } diff --git a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs index a98ed667..b4147eee 100644 --- a/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs +++ b/src/SharpCompress/Common/Zip/ZipCompressionMethod.cs @@ -4,6 +4,11 @@ internal enum ZipCompressionMethod { None = 0, Shrink = 1, + Reduce1 = 2, + Reduce2 = 3, + Reduce3 = 4, + Reduce4 = 5, + Explode = 6, Deflate = 8, Deflate64 = 9, BZip2 = 12, diff --git a/src/SharpCompress/Common/Zip/ZipEntry.cs b/src/SharpCompress/Common/Zip/ZipEntry.cs index c2cecf39..2700e005 100644 --- a/src/SharpCompress/Common/Zip/ZipEntry.cs +++ b/src/SharpCompress/Common/Zip/ZipEntry.cs @@ -31,6 +31,11 @@ public class ZipEntry : Entry ZipCompressionMethod.PPMd => CompressionType.PPMd, ZipCompressionMethod.None => CompressionType.None, ZipCompressionMethod.Shrink => CompressionType.Shrink, + ZipCompressionMethod.Reduce1 => CompressionType.Reduce1, + ZipCompressionMethod.Reduce2 => CompressionType.Reduce2, + ZipCompressionMethod.Reduce3 => CompressionType.Reduce3, + ZipCompressionMethod.Reduce4 => CompressionType.Reduce4, + ZipCompressionMethod.Explode => CompressionType.Explode, _ => CompressionType.Unknown }; diff --git a/src/SharpCompress/Common/Zip/ZipFilePart.cs b/src/SharpCompress/Common/Zip/ZipFilePart.cs index e8516150..5d0a69c3 100644 --- a/src/SharpCompress/Common/Zip/ZipFilePart.cs +++ b/src/SharpCompress/Common/Zip/ZipFilePart.cs @@ -11,6 +11,8 @@ using SharpCompress.Compressors.LZMA; using SharpCompress.Compressors.PPMd; using SharpCompress.Compressors.Shrink; using SharpCompress.Compressors.Xz; +using SharpCompress.Compressors.Reduce; +using SharpCompress.Compressors.Explode; using SharpCompress.IO; using ZstdSharp; @@ -89,6 +91,27 @@ internal abstract class ZipFilePart : FilePart Header.UncompressedSize ); } + case ZipCompressionMethod.Reduce1: + { + return new ReduceStream(stream, Header.CompressedSize, Header.UncompressedSize, 1); + } + case ZipCompressionMethod.Reduce2: + { + return new ReduceStream(stream, Header.CompressedSize, Header.UncompressedSize, 2); + } + case ZipCompressionMethod.Reduce3: + { + return new ReduceStream(stream, Header.CompressedSize, Header.UncompressedSize, 3); + } + case ZipCompressionMethod.Reduce4: + { + return new ReduceStream(stream, Header.CompressedSize, Header.UncompressedSize, 4); + } + case ZipCompressionMethod.Explode: + { + return new ExplodeStream(stream, Header.CompressedSize, Header.UncompressedSize, Header.Flags); + } + case ZipCompressionMethod.Deflate: { return new DeflateStream(stream, CompressionMode.Decompress); @@ -203,6 +226,10 @@ internal abstract class ZipFilePart : FilePart { case ZipCompressionMethod.None: case ZipCompressionMethod.Shrink: + case ZipCompressionMethod.Reduce1: + case ZipCompressionMethod.Reduce2: + case ZipCompressionMethod.Reduce3: + case ZipCompressionMethod.Reduce4: case ZipCompressionMethod.Deflate: case ZipCompressionMethod.Deflate64: case ZipCompressionMethod.BZip2: diff --git a/src/SharpCompress/Compressors/Explode/ExplodeStream.cs b/src/SharpCompress/Compressors/Explode/ExplodeStream.cs new file mode 100644 index 00000000..a68353ce --- /dev/null +++ b/src/SharpCompress/Compressors/Explode/ExplodeStream.cs @@ -0,0 +1,746 @@ +using System; +using System.IO; +using SharpCompress.Common.Zip.Headers; + +namespace SharpCompress.Compressors.Explode; + +public class ExplodeStream : Stream +{ + private const int INVALID_CODE = 99; + private const int WSIZE = 64 * 1024; + + private readonly long unCompressedSize; + private readonly int compressedSize; + private readonly HeaderFlags generalPurposeBitFlag; + private readonly Stream inStream; + + private huftNode[]? hufLiteralCodeTable; /* literal code table */ + private huftNode[] hufLengthCodeTable = []; /* length code table */ + private huftNode[] hufDistanceCodeTable = []; /* distance code table */ + + private int bitsForLiteralCodeTable; + private int bitsForLengthCodeTable; + private int bitsForDistanceCodeTable; + private int numOfUncodedLowerDistanceBits; /* number of uncoded lower distance bits */ + + private ulong bitBuffer; + private int bitBufferCount; + + private readonly byte[] windowsBuffer; + private uint maskForLiteralCodeTable; + private uint maskForLengthCodeTable; + private uint maskForDistanceCodeTable; + private uint maskForDistanceLowBits; + private long outBytesCount; + + private int windowIndex; + private int distance; + private int length; + + internal ExplodeStream( + Stream inStr, + long compressedSize, + long uncompressedSize, + HeaderFlags generalPurposeBitFlag + ) + { + inStream = inStr; + this.compressedSize = (int)compressedSize; + unCompressedSize = (long)uncompressedSize; + this.generalPurposeBitFlag = generalPurposeBitFlag; + explode_SetTables(); + + windowsBuffer = new byte[WSIZE]; + explode_var_init(); + } + + public override void Flush() + { + throw new NotImplementedException(); + } + + 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(); + } + + public override bool CanRead => true; + public override bool CanSeek => false; + public override bool CanWrite => false; + public override long Length => unCompressedSize; + public override long Position + { + get => outBytesCount; + set { } + } + + static uint[] mask_bits = new uint[] + { + 0x0000, + 0x0001, + 0x0003, + 0x0007, + 0x000f, + 0x001f, + 0x003f, + 0x007f, + 0x00ff, + 0x01ff, + 0x03ff, + 0x07ff, + 0x0fff, + 0x1fff, + 0x3fff, + 0x7fff, + 0xffff + }; + + /* Tables for length and distance */ + static int[] cplen2 = new int[] + { + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65 + }; + + static int[] cplen3 = new int[] + { + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66 + }; + + static int[] extra = new int[] + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8 + }; + + static int[] cpdist4 = new int[] + { + 1, + 65, + 129, + 193, + 257, + 321, + 385, + 449, + 513, + 577, + 641, + 705, + 769, + 833, + 897, + 961, + 1025, + 1089, + 1153, + 1217, + 1281, + 1345, + 1409, + 1473, + 1537, + 1601, + 1665, + 1729, + 1793, + 1857, + 1921, + 1985, + 2049, + 2113, + 2177, + 2241, + 2305, + 2369, + 2433, + 2497, + 2561, + 2625, + 2689, + 2753, + 2817, + 2881, + 2945, + 3009, + 3073, + 3137, + 3201, + 3265, + 3329, + 3393, + 3457, + 3521, + 3585, + 3649, + 3713, + 3777, + 3841, + 3905, + 3969, + 4033 + }; + + static int[] cpdist8 = new int[] + { + 1, + 129, + 257, + 385, + 513, + 641, + 769, + 897, + 1025, + 1153, + 1281, + 1409, + 1537, + 1665, + 1793, + 1921, + 2049, + 2177, + 2305, + 2433, + 2561, + 2689, + 2817, + 2945, + 3073, + 3201, + 3329, + 3457, + 3585, + 3713, + 3841, + 3969, + 4097, + 4225, + 4353, + 4481, + 4609, + 4737, + 4865, + 4993, + 5121, + 5249, + 5377, + 5505, + 5633, + 5761, + 5889, + 6017, + 6145, + 6273, + 6401, + 6529, + 6657, + 6785, + 6913, + 7041, + 7169, + 7297, + 7425, + 7553, + 7681, + 7809, + 7937, + 8065 + }; + + private int get_tree(int[] arrBitLengths, int numberExpected) + /* Get the bit lengths for a code representation from the compressed + stream. If get_tree() returns 4, then there is an error in the data. + Otherwise zero is returned. */ + { + /* get bit lengths */ + int inIndex = inStream.ReadByte() + 1; /* length/count pairs to read */ + int outIndex = 0; /* next code */ + do + { + int nextByte = inStream.ReadByte(); + int bitLengthOfCodes = (nextByte & 0xf) + 1; /* bits in code (1..16) */ + int numOfCodes = ((nextByte & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */ + if (outIndex + numOfCodes > numberExpected) + return 4; /* don't overflow arrBitLengths[] */ + do + { + arrBitLengths[outIndex++] = bitLengthOfCodes; + } while ((--numOfCodes) != 0); + } while ((--inIndex) != 0); + + return outIndex != numberExpected ? 4 : 0; /* should have read numberExpected of them */ + } + + private int explode_SetTables() + { + int returnCode; /* return codes */ + int[] arrBitLengthsForCodes = new int[256]; /* bit lengths for codes */ + + bitsForLiteralCodeTable = 0; /* bits for tb */ + bitsForLengthCodeTable = 7; + bitsForDistanceCodeTable = (compressedSize) > 200000 ? 8 : 7; + + if ((generalPurposeBitFlag & HeaderFlags.Bit2) != 0) + /* With literal tree--minimum match length is 3 */ + { + bitsForLiteralCodeTable = 9; /* base table size for literals */ + if ((returnCode = get_tree(arrBitLengthsForCodes, 256)) != 0) + return returnCode; + + if ( + ( + returnCode = HuftTree.huftbuid( + arrBitLengthsForCodes, + 256, + 256, + [], + [], + out hufLiteralCodeTable, + ref bitsForLiteralCodeTable + ) + ) != 0 + ) + return returnCode; + + if ((returnCode = get_tree(arrBitLengthsForCodes, 64)) != 0) + return returnCode; + + if ( + ( + returnCode = HuftTree.huftbuid( + arrBitLengthsForCodes, + 64, + 0, + cplen3, + extra, + out hufLengthCodeTable, + ref bitsForLengthCodeTable + ) + ) != 0 + ) + return returnCode; + } + else + /* No literal tree--minimum match length is 2 */ + { + if ((returnCode = get_tree(arrBitLengthsForCodes, 64)) != 0) + return returnCode; + + hufLiteralCodeTable = null; + + if ( + ( + returnCode = HuftTree.huftbuid( + arrBitLengthsForCodes, + 64, + 0, + cplen2, + extra, + out hufLengthCodeTable, + ref bitsForLengthCodeTable + ) + ) != 0 + ) + return returnCode; + } + + if ((returnCode = get_tree(arrBitLengthsForCodes, 64)) != 0) + return (int)returnCode; + + if ((generalPurposeBitFlag & HeaderFlags.Bit1) != 0) /* true if 8K */ + { + numOfUncodedLowerDistanceBits = 7; + returnCode = HuftTree.huftbuid( + arrBitLengthsForCodes, + 64, + 0, + cpdist8, + extra, + out hufDistanceCodeTable, + ref bitsForDistanceCodeTable + ); + } + else /* else 4K */ + { + numOfUncodedLowerDistanceBits = 6; + returnCode = HuftTree.huftbuid( + arrBitLengthsForCodes, + 64, + 0, + cpdist4, + extra, + out hufDistanceCodeTable, + ref bitsForDistanceCodeTable + ); + } + + return returnCode; + } + + private void NeedBits(int numberOfBits) + { + while (bitBufferCount < (numberOfBits)) + { + bitBuffer |= (uint)inStream.ReadByte() << bitBufferCount; + bitBufferCount += 8; + } + } + + private void DumpBits(int numberOfBits) + { + bitBuffer >>= numberOfBits; + bitBufferCount -= numberOfBits; + } + + int DecodeHuft(huftNode[] htab, int bits, uint mask, out huftNode huftPointer, out int e) + { + NeedBits(bits); + + int tabOffset = (int)(~bitBuffer & mask); + huftPointer = htab[tabOffset]; + + while (true) + { + DumpBits(huftPointer.NumberOfBitsUsed); + e = huftPointer.NumberOfExtraBits; + if (e <= 32) + break; + if (e == INVALID_CODE) + return 1; + + e &= 31; + NeedBits(e); + + tabOffset = (int)(~bitBuffer & mask_bits[e]); + huftPointer = huftPointer.ChildNodes[tabOffset]; + } + + return 0; + } + + private void explode_var_init() + { + /* explode the coded data */ + bitBuffer = 0; + bitBufferCount = 0; + maskForLiteralCodeTable = mask_bits[bitsForLiteralCodeTable]; //only used in explode_lit + maskForLengthCodeTable = mask_bits[bitsForLengthCodeTable]; + maskForDistanceCodeTable = mask_bits[bitsForDistanceCodeTable]; + maskForDistanceLowBits = mask_bits[numOfUncodedLowerDistanceBits]; + outBytesCount = 0; + + windowIndex = 0; /* initialize bit buffer, window */ + } + + public override int Read(byte[] buffer, int offset, int count) + { + int countIndex = 0; + while (countIndex < count && outBytesCount < unCompressedSize) /* do until unCompressedSize bytes uncompressed */ + { + if (length == 0) + { + NeedBits(1); + bool literal = (bitBuffer & 1) == 1; + DumpBits(1); + + huftNode huftPointer; + if (literal) /* then literal--decode it */ + { + byte nextByte; + if (hufLiteralCodeTable != null) + { + /* get coded literal */ + if ( + DecodeHuft( + hufLiteralCodeTable, + bitsForLiteralCodeTable, + maskForLiteralCodeTable, + out huftPointer, + out _ + ) != 0 + ) + throw new Exception("Error decoding literal value"); + + nextByte = (byte)huftPointer.Value; + } + else + { + NeedBits(8); + nextByte = (byte)bitBuffer; + DumpBits(8); + } + + buffer[offset + (countIndex++)] = nextByte; + windowsBuffer[windowIndex++] = nextByte; + outBytesCount++; + + if (windowIndex == WSIZE) + windowIndex = 0; + + continue; + } + + NeedBits(numOfUncodedLowerDistanceBits); /* get distance low bits */ + distance = (int)(bitBuffer & maskForDistanceLowBits); + DumpBits(numOfUncodedLowerDistanceBits); + + /* get coded distance high bits */ + if ( + DecodeHuft( + hufDistanceCodeTable, + bitsForDistanceCodeTable, + maskForDistanceCodeTable, + out huftPointer, + out _ + ) != 0 + ) + throw new Exception("Error decoding distance high bits"); + + distance = windowIndex - (distance + huftPointer.Value); /* construct offset */ + + /* get coded length */ + if ( + DecodeHuft( + hufLengthCodeTable, + bitsForLengthCodeTable, + maskForLengthCodeTable, + out huftPointer, + out int extraBitLength + ) != 0 + ) + throw new Exception("Error decoding coded length"); + + length = huftPointer.Value; + + if (extraBitLength != 0) /* get length extra bits */ + { + NeedBits(8); + length += (int)(bitBuffer & 0xff); + DumpBits(8); + } + + if (length > (unCompressedSize - outBytesCount)) + length = (int)(unCompressedSize - outBytesCount); + + distance &= WSIZE - 1; + } + + while (length != 0 && countIndex < count) + { + byte nextByte = windowsBuffer[distance++]; + buffer[offset + (countIndex++)] = nextByte; + windowsBuffer[windowIndex++] = nextByte; + outBytesCount++; + + if (distance == WSIZE) + distance = 0; + + if (windowIndex == WSIZE) + windowIndex = 0; + + length--; + } + } + + return countIndex; + } +} diff --git a/src/SharpCompress/Compressors/Explode/HuftTree.cs b/src/SharpCompress/Compressors/Explode/HuftTree.cs new file mode 100644 index 00000000..caa1a141 --- /dev/null +++ b/src/SharpCompress/Compressors/Explode/HuftTree.cs @@ -0,0 +1,269 @@ +/* + * This code has been converted to C# based on the original huft_tree code found in + * inflate.c -- by Mark Adler version c17e, 30 Mar 2007 + */ + +namespace SharpCompress.Compressors.Explode; + +public class huftNode +{ + public int NumberOfExtraBits; /* number of extra bits or operation */ + public int NumberOfBitsUsed; /* number of bits in this code or subcode */ + public int Value; /* literal, length base, or distance base */ + public huftNode[] ChildNodes = []; /* next level of table */ +} + +public static class HuftTree +{ + private const int INVALID_CODE = 99; + + /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ + private const int BMAX = 16; /* maximum bit length of any code (16 for explode) */ + private const int N_MAX = 288; /* maximum number of codes in any set */ + + public static int huftbuid( + int[] arrBitLengthForCodes, + int numberOfCodes, + int numberOfSimpleValueCodes, + int[] arrBaseValuesForNonSimpleCodes, + int[] arrExtraBitsForNonSimpleCodes, + out huftNode[] outHufTable, + ref int outBitsForTable + ) + /* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. + The code with value 256 is special, and the tables are constructed + so that no bits beyond that code are fetched when that code is + decoded. */ + { + outHufTable = []; + + /* Generate counts for each bit length */ + int lengthOfEOBcode = numberOfCodes > 256 ? arrBitLengthForCodes[256] : BMAX; /* set length of EOB code, if any */ + + int[] arrBitLengthCount = new int[BMAX + 1]; + for (int i = 0; i < BMAX + 1; i++) + arrBitLengthCount[i] = 0; + + int pIndex = 0; + int counterCurrentCode = numberOfCodes; + do + { + arrBitLengthCount[arrBitLengthForCodes[pIndex]]++; + pIndex++; /* assume all entries <= BMAX */ + } while ((--counterCurrentCode) != 0); + + if (arrBitLengthCount[0] == numberOfCodes) /* null input--all zero length codes */ + { + return 0; + } + + /* Find minimum and maximum length, bound *outBitsForTable by those */ + int counter; + for (counter = 1; counter <= BMAX; counter++) + if (arrBitLengthCount[counter] != 0) + break; + + int numberOfBitsInCurrentCode = counter; /* minimum code length */ + if (outBitsForTable < counter) + outBitsForTable = counter; + + for (counterCurrentCode = BMAX; counterCurrentCode != 0; counterCurrentCode--) + if (arrBitLengthCount[counterCurrentCode] != 0) + break; + + int maximumCodeLength = counterCurrentCode; /* maximum code length */ + if (outBitsForTable > counterCurrentCode) + outBitsForTable = counterCurrentCode; + + /* Adjust last length count to fill out codes, if needed */ + int numberOfDummyCodesAdded; + for ( + numberOfDummyCodesAdded = 1 << counter; + counter < counterCurrentCode; + counter++, numberOfDummyCodesAdded <<= 1 + ) + if ((numberOfDummyCodesAdded -= arrBitLengthCount[counter]) < 0) + return 2; /* bad input: more codes than bits */ + + if ((numberOfDummyCodesAdded -= arrBitLengthCount[counterCurrentCode]) < 0) + return 2; + + arrBitLengthCount[counterCurrentCode] += numberOfDummyCodesAdded; + + /* Generate starting offsets into the value table for each length */ + int[] bitOffset = new int[BMAX + 1]; + bitOffset[1] = 0; + counter = 0; + pIndex = 1; + int xIndex = 2; + while ((--counterCurrentCode) != 0) + { /* note that i == g from above */ + bitOffset[xIndex++] = (counter += arrBitLengthCount[pIndex++]); + } + + /* Make a table of values in order of bit lengths */ + int[] arrValuesInOrderOfBitLength = new int[N_MAX]; + for (int i = 0; i < N_MAX; i++) + arrValuesInOrderOfBitLength[i] = 0; + + pIndex = 0; + counterCurrentCode = 0; + do + { + if ((counter = arrBitLengthForCodes[pIndex++]) != 0) + arrValuesInOrderOfBitLength[bitOffset[counter]++] = counterCurrentCode; + } while (++counterCurrentCode < numberOfCodes); + + numberOfCodes = bitOffset[maximumCodeLength]; /* set numberOfCodes to length of v */ + + /* Generate the Huffman codes and for each, make the table entries */ + bitOffset[0] = counterCurrentCode = 0; /* first Huffman code is zero */ + pIndex = 0; /* grab values in bit order */ + int tableLevel = -1; /* no tables yet--level -1 */ + int bitsBeforeThisTable = 0; + int[] arrLX = new int[BMAX + 1]; + int stackOfBitsPerTable = 1; /* stack of bits per table */ + arrLX[stackOfBitsPerTable - 1] = 0; /* no bits decoded yet */ + + huftNode[][] arrHufTableStack = new huftNode[BMAX][]; + huftNode[] pointerToCurrentTable = []; + int numberOfEntriesInCurrentTable = 0; + + bool first = true; + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; numberOfBitsInCurrentCode <= maximumCodeLength; numberOfBitsInCurrentCode++) + { + int counterForCodes = arrBitLengthCount[numberOfBitsInCurrentCode]; + while ((counterForCodes--) != 0) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while ( + numberOfBitsInCurrentCode + > bitsBeforeThisTable + arrLX[stackOfBitsPerTable + tableLevel] + ) + { + bitsBeforeThisTable += arrLX[stackOfBitsPerTable + (tableLevel++)]; /* add bits already decoded */ + + /* compute minimum size table less than or equal to *outBitsForTable bits */ + numberOfEntriesInCurrentTable = + (numberOfEntriesInCurrentTable = maximumCodeLength - bitsBeforeThisTable) + > outBitsForTable + ? outBitsForTable + : numberOfEntriesInCurrentTable; /* upper limit */ + int fBitCounter1 = + 1 << (counter = numberOfBitsInCurrentCode - bitsBeforeThisTable); + if (fBitCounter1 > counterForCodes + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + fBitCounter1 -= counterForCodes + 1; /* deduct codes from patterns left */ + xIndex = numberOfBitsInCurrentCode; + while (++counter < numberOfEntriesInCurrentTable) /* try smaller tables up to z bits */ + { + if ((fBitCounter1 <<= 1) <= arrBitLengthCount[++xIndex]) + break; /* enough codes to use up j bits */ + fBitCounter1 -= arrBitLengthCount[xIndex]; /* else deduct codes from patterns */ + } + } + if ( + bitsBeforeThisTable + counter > lengthOfEOBcode + && bitsBeforeThisTable < lengthOfEOBcode + ) + counter = lengthOfEOBcode - bitsBeforeThisTable; /* make EOB code end at table */ + + numberOfEntriesInCurrentTable = 1 << counter; /* table entries for j-bit table */ + arrLX[stackOfBitsPerTable + tableLevel] = counter; /* set table size in stack */ + + /* allocate and link in new table */ + pointerToCurrentTable = new huftNode[numberOfEntriesInCurrentTable]; + + // set the pointer, pointed to by *outHufTable to the second huft in pointertoCurrentTable + if (first) + { + outHufTable = pointerToCurrentTable; /* link to list for huft_free() */ + first = false; + } + + arrHufTableStack[tableLevel] = pointerToCurrentTable; /* table starts after link */ + + /* connect to last table, if there is one */ + if (tableLevel != 0) + { + bitOffset[tableLevel] = counterCurrentCode; /* save pattern for backing up */ + + huftNode vHuft = new huftNode + { + NumberOfBitsUsed = arrLX[stackOfBitsPerTable + tableLevel - 1], /* bits to dump before this table */ + NumberOfExtraBits = 32 + counter, /* bits in this table */ + ChildNodes = pointerToCurrentTable /* pointer to this table */ + }; + + counter = + (counterCurrentCode & ((1 << bitsBeforeThisTable) - 1)) + >> (bitsBeforeThisTable - arrLX[stackOfBitsPerTable + tableLevel - 1]); + arrHufTableStack[tableLevel - 1][counter] = vHuft; /* connect to last table */ + } + } + + /* set up table entry in r */ + huftNode vHuft1 = new huftNode + { + NumberOfBitsUsed = numberOfBitsInCurrentCode - bitsBeforeThisTable + }; + + if (pIndex >= numberOfCodes) + vHuft1.NumberOfExtraBits = INVALID_CODE; /* out of values--invalid code */ + else if (arrValuesInOrderOfBitLength[pIndex] < numberOfSimpleValueCodes) + { + vHuft1.NumberOfExtraBits = ( + arrValuesInOrderOfBitLength[pIndex] < 256 ? 32 : 31 + ); /* 256 is end-of-block code */ + vHuft1.Value = arrValuesInOrderOfBitLength[pIndex++]; /* simple code is just the value */ + } + else + { + vHuft1.NumberOfExtraBits = arrExtraBitsForNonSimpleCodes[ + arrValuesInOrderOfBitLength[pIndex] - numberOfSimpleValueCodes + ]; /* non-simple--look up in lists */ + vHuft1.Value = arrBaseValuesForNonSimpleCodes[ + arrValuesInOrderOfBitLength[pIndex++] - numberOfSimpleValueCodes + ]; + } + + /* fill code-like entries with r */ + int fBitCounter2 = 1 << (numberOfBitsInCurrentCode - bitsBeforeThisTable); + for ( + counter = counterCurrentCode >> bitsBeforeThisTable; + counter < numberOfEntriesInCurrentTable; + counter += fBitCounter2 + ) + pointerToCurrentTable[counter] = vHuft1; + + /* backwards increment the k-bit code i */ + for ( + counter = 1 << (numberOfBitsInCurrentCode - 1); + (counterCurrentCode & counter) != 0; + counter >>= 1 + ) + counterCurrentCode ^= counter; + counterCurrentCode ^= counter; + + /* backup over finished tables */ + while ( + (counterCurrentCode & ((1 << bitsBeforeThisTable) - 1)) != bitOffset[tableLevel] + ) + bitsBeforeThisTable -= arrLX[stackOfBitsPerTable + (--tableLevel)]; + } + } + + /* return actual size of base table */ + outBitsForTable = arrLX[stackOfBitsPerTable]; + + /* Return true (1) if we were given an incomplete table */ + return (numberOfDummyCodesAdded != 0 && maximumCodeLength != 1) ? 1 : 0; + } +} diff --git a/src/SharpCompress/Compressors/Reduce/ReduceStream.cs b/src/SharpCompress/Compressors/Reduce/ReduceStream.cs new file mode 100644 index 00000000..2ebc20ab --- /dev/null +++ b/src/SharpCompress/Compressors/Reduce/ReduceStream.cs @@ -0,0 +1,249 @@ +using System; +using System.IO; + +namespace SharpCompress.Compressors.Reduce; + +public class ReduceStream : Stream +{ + private readonly long unCompressedSize; + private readonly long compressedSize; + private readonly Stream inStream; + + private long inByteCount; + private const int EOF = 1234; + + private readonly int factor; + private readonly int distanceMask; + private readonly int lengthMask; + + private long outBytesCount; + + private readonly byte[] windowsBuffer; + private int windowIndex; + private int length; + private int distance; + + public ReduceStream(Stream inStr, long compsize, long unCompSize, int factor) + { + inStream = inStr; + compressedSize = compsize; + unCompressedSize = unCompSize; + inByteCount = 0; + outBytesCount = 0; + + this.factor = factor; + distanceMask = (int)mask_bits[factor] << 8; + lengthMask = 0xff >> factor; + + windowIndex = 0; + length = 0; + distance = 0; + + windowsBuffer = new byte[WSIZE]; + + outByte = 0; + + LoadBitLengthTable(); + LoadNextByteTable(); + } + + public override void Flush() + { + throw new NotImplementedException(); + } + + 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(); + } + + public override bool CanRead => true; + public override bool CanSeek => false; + public override bool CanWrite => false; + public override long Length => unCompressedSize; + public override long Position + { + get => outBytesCount; + set { } + } + + private const int RunLengthCode = 144; + private const int WSIZE = 0x4000; + + private readonly uint[] mask_bits = new uint[] + { + 0x0000, + 0x0001, + 0x0003, + 0x0007, + 0x000f, + 0x001f, + 0x003f, + 0x007f, + 0x00ff, + 0x01ff, + 0x03ff, + 0x07ff, + 0x0fff, + 0x1fff, + 0x3fff, + 0x7fff, + 0xffff + }; + + private int bitBufferCount; + private ulong bitBuffer; + + private int NEXTBYTE() + { + if (inByteCount == compressedSize) + return EOF; + inByteCount++; + return inStream.ReadByte(); + } + + private void READBITS(int nbits, out byte zdest) + { + if (nbits > bitBufferCount) + { + int temp; + while (bitBufferCount <= 8 * (int)(4 - 1) && (temp = NEXTBYTE()) != EOF) + { + bitBuffer |= (ulong)temp << bitBufferCount; + bitBufferCount += 8; + } + } + zdest = (byte)(bitBuffer & (ulong)mask_bits[nbits]); + bitBuffer >>= nbits; + bitBufferCount -= nbits; + } + + private byte[] bitCountTable = []; + + private void LoadBitLengthTable() + { + byte[] bitPos = { 0, 2, 4, 8, 16, 32, 64, 128, 255 }; + bitCountTable = new byte[256]; + + for (byte i = 1; i <= 8; i++) + { + int vMin = bitPos[i - 1] + 1; + int vMax = bitPos[i]; + for (int j = vMin; j <= vMax; j++) + { + bitCountTable[j] = i; + } + } + } + + private byte[][] nextByteTable = []; + + private void LoadNextByteTable() + { + nextByteTable = new byte[256][]; + for (int x = 255; x >= 0; x--) + { + READBITS(6, out byte Slen); + nextByteTable[x] = new byte[Slen]; + for (int i = 0; i < Slen; i++) + { + READBITS(8, out nextByteTable[x][i]); + } + } + } + + private byte outByte; + + private byte GetNextByte() + { + if (nextByteTable[outByte].Length == 0) + { + READBITS(8, out outByte); + return outByte; + } + READBITS(1, out byte nextBit); + if (nextBit == 1) + { + READBITS(8, out outByte); + return outByte; + } + READBITS(bitCountTable[nextByteTable[outByte].Length], out byte nextByteIndex); + outByte = nextByteTable[outByte][nextByteIndex]; + return outByte; + } + + public override int Read(byte[] buffer, int offset, int count) + { + int countIndex = 0; + while (countIndex < count && outBytesCount < unCompressedSize) + { + if (length == 0) + { + byte nextByte = GetNextByte(); + if (nextByte != RunLengthCode) + { + buffer[offset + (countIndex++)] = nextByte; + windowsBuffer[windowIndex++] = nextByte; + outBytesCount++; + if (windowIndex == WSIZE) + windowIndex = 0; + + continue; + } + + nextByte = GetNextByte(); + if (nextByte == 0) + { + buffer[offset + (countIndex++)] = RunLengthCode; + windowsBuffer[windowIndex++] = RunLengthCode; + outBytesCount++; + if (windowIndex == WSIZE) + windowIndex = 0; + + continue; + } + + int lengthDistanceByte = nextByte; + length = lengthDistanceByte & lengthMask; + if (length == lengthMask) + { + length += GetNextByte(); + } + length += 3; + + int distanceHighByte = (lengthDistanceByte << factor) & distanceMask; + distance = windowIndex - (distanceHighByte + GetNextByte() + 1); + + distance &= WSIZE - 1; + } + + while (length != 0 && countIndex < count) + { + byte nextByte = windowsBuffer[distance++]; + buffer[offset + (countIndex++)] = nextByte; + windowsBuffer[windowIndex++] = nextByte; + outBytesCount++; + + if (distance == WSIZE) + distance = 0; + + if (windowIndex == WSIZE) + windowIndex = 0; + + length--; + } + } + + return countIndex; + } +} From 471a3f63fe34343923d6c14c163eede84e1e5b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zavark=C3=B3=20G=C3=A1bor?= Date: Sun, 7 Jul 2024 00:14:00 +0200 Subject: [PATCH 0102/1333] return Stream.Null when 7z entry has no stream --- src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs b/src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs index fe221b53..2788f41a 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 Stream.Null; } var folderStream = _database.GetFolderStream(_stream, Folder!, _database.PasswordProvider); From e42d953f47e2339c03e663cdff5015d61873dcea Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Wed, 10 Jul 2024 19:53:32 +0200 Subject: [PATCH 0103/1333] Check crc on tar header --- .../Common/Tar/Headers/TarHeader.cs | 7 +++++++ tests/SharpCompress.Test/Tar/TarArchiveTests.cs | 11 +++++++++-- tests/TestArchives/Archives/false.positive.tar | Bin 0 -> 1024 bytes 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/TestArchives/Archives/false.positive.tar diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index e9aa343c..510d38a0 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -134,6 +134,13 @@ internal sealed class TarHeader hasLongValue = false; } while (hasLongValue); + var crc = ReadAsciiInt64Base8(buffer, 148, 7); + + if (crc != RecalculateChecksum(buffer)) + { + return false; + } + Name = longName ?? ArchiveEncoding.Decode(buffer, 0, 100).TrimNulls(); EntryType = entryType; Size = ReadSize(buffer); diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index bbf96c00..6a8f3294 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -217,8 +217,7 @@ public class TarArchiveTests : ArchiveTests { 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); + Assert.Throws(() => ArchiveFactory.Open(stream)); } [Theory] @@ -287,4 +286,12 @@ public class TarArchiveTests : ArchiveTests Assert.Equal(2, numberOfEntries); } + + [Fact] + public void Tar_Detect_Test() + { + var isTar = TarArchive.IsTarFile(Path.Combine(TEST_ARCHIVES_PATH, "false.positive.tar")); + + Assert.False(isTar); + } } diff --git a/tests/TestArchives/Archives/false.positive.tar b/tests/TestArchives/Archives/false.positive.tar new file mode 100644 index 0000000000000000000000000000000000000000..db91a2ff2657cb03d7538bb306d0b9816837fb6a GIT binary patch literal 1024 zcmdmZ+NXyB2)IE65X`MMWncu-s$d=img#Z90vk52w literal 0 HcmV?d00001 From 6b88f82656d3fdecd84181f4b098b97632887df4 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Thu, 11 Jul 2024 19:52:33 +0200 Subject: [PATCH 0104/1333] Handle special case, empty file --- .../Common/Tar/Headers/TarHeader.cs | 42 +++++++++++++++++-- .../SharpCompress.Test/Tar/TarArchiveTests.cs | 3 +- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 510d38a0..9231833d 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -2,6 +2,7 @@ using System; using System.Buffers.Binary; using System.IO; using System.Text; +using ZstdSharp.Unsafe; namespace SharpCompress.Common.Tar.Headers; @@ -134,9 +135,8 @@ internal sealed class TarHeader hasLongValue = false; } while (hasLongValue); - var crc = ReadAsciiInt64Base8(buffer, 148, 7); - - if (crc != RecalculateChecksum(buffer)) + // Check header checksum + if (!checkChecksum(buffer)) { return false; } @@ -318,6 +318,42 @@ internal sealed class TarHeader (byte)' ' }; + internal static bool checkChecksum(byte[] buf) + { + const int eightSpacesChksum = 256; + var buffer = new Span(buf).Slice(0, 512); + int posix_sum = eightSpacesChksum; + int sun_sum = eightSpacesChksum; + + foreach (byte b in buffer) + { + posix_sum += b; + sun_sum += unchecked((sbyte)b); + } + + // Special case, empty file header + if (posix_sum == eightSpacesChksum) + { + return true; + } + + // Remove current checksum from calculation + foreach (byte b in buffer.Slice(148, 8)) + { + posix_sum -= b; + sun_sum -= unchecked((sbyte)b); + } + + // Read and compare checksum for header + var crc = ReadAsciiInt64Base8(buf, 148, 7); + if (crc != posix_sum && crc != sun_sum) + { + return false; + } + + return true; + } + internal static int RecalculateChecksum(byte[] buf) { // Set default value for checksum. That is 8 spaces. diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index 6a8f3294..1024e945 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -217,7 +217,8 @@ public class TarArchiveTests : ArchiveTests { var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.Empty.tar"); using Stream stream = File.OpenRead(archiveFullPath); - Assert.Throws(() => ArchiveFactory.Open(stream)); + using var archive = ArchiveFactory.Open(stream); + Assert.True(archive.Type == ArchiveType.Tar); } [Theory] From 9515350f52a40cb54627c029a4fc7b6fe7ffc939 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Thu, 11 Jul 2024 19:56:46 +0200 Subject: [PATCH 0105/1333] Remove using directive --- src/SharpCompress/Common/Tar/Headers/TarHeader.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 9231833d..72c83612 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -2,7 +2,6 @@ using System; using System.Buffers.Binary; using System.IO; using System.Text; -using ZstdSharp.Unsafe; namespace SharpCompress.Common.Tar.Headers; From 188a426ddea1979ab0400c248056ab97dedb36fe Mon Sep 17 00:00:00 2001 From: Alex Prabhat Bara <50404684+alexprabhat99@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:20:04 +0530 Subject: [PATCH 0106/1333] fix for missing empty directories when using ExtractToDirectory --- src/SharpCompress/Archives/IArchiveExtensions.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/Archives/IArchiveExtensions.cs b/src/SharpCompress/Archives/IArchiveExtensions.cs index 382c3ddf..b47f3394 100644 --- a/src/SharpCompress/Archives/IArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveExtensions.cs @@ -54,14 +54,23 @@ public static class IArchiveExtensions var entry = entries.Entry; if (entry.IsDirectory) { + var dirPath = Path.Combine(destination, entry.Key.NotNull("Entry Key is null")); + if (Path.GetDirectoryName(dirPath + "/") is { } emptyDirectory && seenDirectories.Add(dirPath)) + { + Directory.CreateDirectory(emptyDirectory); + } continue; } - // Create each directory + // Create each directory if not already created var path = Path.Combine(destination, entry.Key.NotNull("Entry Key is null")); - if (Path.GetDirectoryName(path) is { } directory && seenDirectories.Add(path)) + if (Path.GetDirectoryName(path) is { } directory) { - Directory.CreateDirectory(directory); + if (!Directory.Exists(directory) && !seenDirectories.Contains(directory)) + { + Directory.CreateDirectory(directory); + seenDirectories.Add(directory); + } } // Write file From 004e0941d572da081d9542d181aa25188babee4e Mon Sep 17 00:00:00 2001 From: Alex Prabhat Bara <50404684+alexprabhat99@users.noreply.github.com> Date: Tue, 16 Jul 2024 20:12:01 +0530 Subject: [PATCH 0107/1333] code formatted using csharpier --- src/SharpCompress/Archives/IArchiveExtensions.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/Archives/IArchiveExtensions.cs b/src/SharpCompress/Archives/IArchiveExtensions.cs index b47f3394..4cba5463 100644 --- a/src/SharpCompress/Archives/IArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveExtensions.cs @@ -55,7 +55,10 @@ public static class IArchiveExtensions if (entry.IsDirectory) { var dirPath = Path.Combine(destination, entry.Key.NotNull("Entry Key is null")); - if (Path.GetDirectoryName(dirPath + "/") is { } emptyDirectory && seenDirectories.Add(dirPath)) + if ( + Path.GetDirectoryName(dirPath + "/") is { } emptyDirectory + && seenDirectories.Add(dirPath) + ) { Directory.CreateDirectory(emptyDirectory); } From 3545693999a601872f343b1e8530fc9b7263e644 Mon Sep 17 00:00:00 2001 From: GordonJ Date: Tue, 23 Jul 2024 14:05:07 -0500 Subject: [PATCH 0108/1333] Added Tests and supporting Files. --- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 51 +++++++++++++++--- tests/TestArchives/Archives/Zip.implode.zip | Bin 0 -> 63534 bytes tests/TestArchives/Archives/Zip.reduce1.zip | Bin 0 -> 67014 bytes tests/TestArchives/Archives/Zip.reduce2.zip | Bin 0 -> 66505 bytes tests/TestArchives/Archives/Zip.reduce3.zip | Bin 0 -> 66364 bytes tests/TestArchives/Archives/Zip.reduce4.zip | Bin 0 -> 66161 bytes 6 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 tests/TestArchives/Archives/Zip.implode.zip create mode 100644 tests/TestArchives/Archives/Zip.reduce1.zip create mode 100644 tests/TestArchives/Archives/Zip.reduce2.zip create mode 100644 tests/TestArchives/Archives/Zip.reduce3.zip create mode 100644 tests/TestArchives/Archives/Zip.reduce4.zip diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index 494e02c9..dfeecadd 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -16,14 +16,7 @@ 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"); @@ -183,6 +176,48 @@ public class ZipArchiveTests : ArchiveTests [Fact] public void Zip_Zip64_ArchiveFileRead() => ArchiveFileRead("Zip.zip64.zip"); + [Fact] + public void Zip_Shrink_ArchiveStreamRead() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + ArchiveStreamRead("Zip.shrink.zip"); + } + [Fact] + public void Zip_Implode_ArchiveStreamRead() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + ArchiveStreamRead("Zip.implode.zip"); + } + [Fact] + public void Zip_Reduce1_ArchiveStreamRead() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + ArchiveStreamRead("Zip.reduce1.zip"); + } + [Fact] + public void Zip_Reduce2_ArchiveStreamRead() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + ArchiveStreamRead("Zip.reduce2.zip"); + } + [Fact] + public void Zip_Reduce3_ArchiveStreamRead() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + ArchiveStreamRead("Zip.reduce3.zip"); + } + [Fact] + public void Zip_Reduce4_ArchiveStreamRead() + { + UseExtensionInsteadOfNameToVerify = true; + UseCaseInsensitiveToVerify = true; + ArchiveStreamRead("Zip.reduce4.zip"); + } [Fact] public void Zip_Random_Write_Remove() { diff --git a/tests/TestArchives/Archives/Zip.implode.zip b/tests/TestArchives/Archives/Zip.implode.zip new file mode 100644 index 0000000000000000000000000000000000000000..bd4354f0d04063d4e06fdc908d7d618eaab4eb5c GIT binary patch literal 63534 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