Compare commits

...

76 Commits

Author SHA1 Message Date
Adam Hathcock
6f3124a84f Mark for 0.39 2025-01-16 08:30:21 +00:00
Adam Hathcock
59eb5bd9c4 Merge pull request #888 from adamhathcock/updates
Update to support net48, net481, netstandard2.0, net6 and net8
2025-01-16 08:19:50 +00:00
Adam Hathcock
ad2b6bb4f7 Merge branch 'master' into updates 2025-01-16 08:17:25 +00:00
Adam Hathcock
51d64ee10e Merge pull request #889 from majorro/internal-helpers
Make helper classes internal
2025-01-16 08:15:02 +00:00
majorro
1159efc6cc formatting 2025-01-15 21:43:10 +03:00
Adam Hathcock
3cfb76a56f Add back net48 and net481 support 2025-01-15 16:35:05 +00:00
majorro
7a1ad6688a make helpers internal 2025-01-15 04:46:22 +03:00
majorro
4f4af6e3fd make test friend assembly 2025-01-15 04:46:07 +03:00
majorro
2736b79097 signed test assembly 2025-01-15 04:43:16 +03:00
Adam Hathcock
8da2ffa433 Update dependencies 2025-01-14 09:12:03 +00:00
Adam Hathcock
5bf3d6dc32 update csharpier 2025-01-14 09:07:40 +00:00
Adam Hathcock
30d4380afe update csproj 2025-01-14 09:06:03 +00:00
Adam Hathcock
c8b5aad482 Update to support only netstandard2.0, net6 and net8 2025-01-14 09:04:39 +00:00
Adam Hathcock
fa1d440947 Merge pull request #887 from majorro/improve-rar-memory-usage
Improve rar memory usage
2025-01-14 08:58:18 +00:00
Adam Hathcock
a89fc3a276 formatting 2025-01-14 08:55:09 +00:00
majorro
3875f62453 deps fix 2025-01-14 00:36:26 +03:00
majorro
23e1447ab6 stackalloc addvmcode 2025-01-13 23:31:33 +03:00
majorro
91364c6a7c stackalloc readtables 2025-01-13 23:28:26 +03:00
majorro
a070493fba window null checks 2025-01-13 23:26:49 +03:00
majorro
ca0a6ab72c rollback ILLink.Tasks downgrade 2025-01-12 16:38:30 +03:00
majorro
10e0562a82 stackalloc rar unpackv1 2025-01-12 16:02:49 +03:00
majorro
44998a2a2b pooled window for rar unpackv1 2025-01-12 16:01:59 +03:00
majorro
f8e033e560 add explicit System.Buffers, remove redundant code 2025-01-12 15:36:53 +03:00
Adam Hathcock
5842da84af Merge pull request #878 from Morilli/fix-xzblock-padding
Fix XZBlock padding calculation when its stream's starting position % 4 != 0
2024-12-20 08:50:46 +00:00
Adam Hathcock
10cc270170 Merge branch 'master' into fix-xzblock-padding 2024-12-20 08:47:40 +00:00
Morilli
f51bdd56aa expose Position getter in ForwardOnlyStream 2024-12-19 20:41:00 +01:00
Adam Hathcock
7f79c49f93 Merge pull request #884 from YoshiRulz/exports-unclutter
Exports unclutter
2024-12-19 14:06:48 +00:00
YoshiRulz
e4920255f0 Replace ReadOnlyCollection with the one in the BCL
I changed the param type of the helper, but the stronger constraint
didn't seem to matter in practice
2024-12-19 22:11:16 +10:00
YoshiRulz
f8e8273d39 Move utility classes to new namespace 2024-12-19 22:11:16 +10:00
Adam Hathcock
ceddab98d1 Merge pull request #877 from StarkDirewolf/master
Fixed bug in zip time header flags
2024-11-01 14:07:24 +00:00
Robb Pryde
0faa176791 Sharpier styling 2024-10-31 17:35:47 +00:00
Morilli
9b0e0ee536 Fix padding calculation when initial position % 4 != 0 2024-10-29 02:57:26 +01:00
Morilli
881d2756db Add failing test 2024-10-29 02:57:25 +01:00
Robb Pryde
ab5af40999 Fixed bug in zip time header flags, and failing to parse it no longer throws an exception. 2024-10-26 01:22:07 +01:00
Adam Hathcock
6aeef8dcf9 Merge pull request #876 from Morilli/fix-isarchive-stream-seek
Restore stream position in ArchiveFactory.IsArchive
2024-10-24 08:28:52 +01:00
Morilli
5d62196dde Restore stream position in ArchiveFactory.IsArchive 2024-10-23 17:01:55 +02:00
Adam Hathcock
7fe27ac310 Mark for 0.38 2024-09-02 09:09:57 +01:00
Adam Hathcock
1e300349ce Merge pull request #868 from kikaragyozov/patch-1
Fix small typo in USAGE.md
2024-09-02 07:43:30 +01:00
Kiril Karagyozov
6b01a7b08e Fix small typo in USAGE.md 2024-08-29 12:11:19 +03:00
Adam Hathcock
34d948df18 Merge pull request #866 from TwanVanDongen/master
Added shrink, reduce and implode to FORMATS
2024-08-22 16:07:23 +01:00
Twan
27091c4f1d Update FORMATS.md 2024-08-21 19:09:14 +02:00
Twan
970a3d7f2a Update FORMATS.md 2024-08-21 19:08:40 +02:00
Twan
2bedbbfc54 Update FORMATS.md 2024-08-21 19:06:14 +02:00
Adam Hathcock
8de33f0db3 Merge pull request #864 from adamhathcock/update-csproj
Update csproj to get green marks and update deps
2024-08-12 16:08:28 +01:00
Adam Hathcock
df4eab67dc Update csproj to get green marks and update deps 2024-08-08 08:41:51 +01:00
Adam Hathcock
2d13bc0046 Merge pull request #860 from lostmsu/7zSFX
Added support for 7zip SFX archives
2024-08-06 08:54:12 +01:00
Victor Nova
704a0cb35d added support for 7zip SFX archives by handling ReaderOptions.LookForHeader 2024-08-05 23:11:15 -07:00
Adam Hathcock
06a983e445 Merge pull request #859 from DineshSolanki/#858-fix-invalid-character-in-filename
Fix #858 - Replaces invalid filename characters
2024-07-30 08:22:01 +01:00
Dinesh Solanki
2d10df8b87 Fix #858 - Replaces invalid filename characters
Added a method to replace invalid characters in file names with underscores during file extraction. This prevents errors related to invalid file names.
2024-07-26 00:16:44 +05:30
Adam Hathcock
baf66db9dc format 2024-07-24 08:31:44 +01:00
GordonJ
3545693999 Added Tests and supporting Files. 2024-07-23 14:05:07 -05:00
gjefferyes
84fb99c2c8 Merge branch 'adamhathcock:master' into master 2024-07-23 13:58:48 -05:00
Adam Hathcock
21e2983ae1 Merge pull request #857 from alexprabhat99/master
Fix for missing empty directories when using ExtractToDirectory
2024-07-18 08:34:20 +01:00
Alex Prabhat Bara
004e0941d5 code formatted using csharpier 2024-07-16 20:12:01 +05:30
Alex Prabhat Bara
188a426dde fix for missing empty directories when using ExtractToDirectory 2024-07-16 16:20:04 +05:30
Adam Hathcock
6fcfae8bfe Merge pull request #855 from Erior/feature/Check-tar-crc-on-header
Check crc on tar header
2024-07-12 08:35:27 +01:00
Lars Vahlenberg
9515350f52 Remove using directive 2024-07-11 19:56:46 +02:00
Lars Vahlenberg
6b88f82656 Handle special case, empty file 2024-07-11 19:52:33 +02:00
Lars Vahlenberg
e42d953f47 Check crc on tar header 2024-07-10 19:53:32 +02:00
gjefferyes
9c257faf26 Merge branch 'master' into master 2024-06-26 06:28:55 -05:00
Adam Hathcock
d18cad6d76 Merge pull request #852 from LANCommander/fix-post-zip64-entry-subsequent-extractions
Fixed extractions after first ZIP64 entry is read from stream
2024-06-26 08:31:58 +01:00
GordonJ
061273be22 Added Export and (un)Reduce to sharpCompress 2024-06-25 11:35:11 -05:00
Pat Hartl
b89de6caad Fix formatting 2024-06-24 17:19:53 -05:00
Pat Hartl
9bc0a1d7c7 Null reference checking
Reorders this null reference check to avoid throwing a null reference exception.
2024-06-23 22:30:34 -05:00
Pat Hartl
eee518b7fa 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.
2024-06-23 22:29:33 -05:00
Pat Hartl
b7b78edaa3 Fixed extractions after first ZIP64 entry is read from stream 2024-06-22 00:09:25 -05:00
Adam Hathcock
3eaac68ab4 Merge pull request #850 from Erior/feature/Issue-842
Issue 842
2024-06-18 13:45:53 +01:00
Adam Hathcock
a7672190e9 Merge branch 'master' into feature/Issue-842 2024-06-18 13:43:22 +01:00
Adam Hathcock
4e4e89b6eb Merge pull request #849 from Erior/develop
Fix for issue #844
2024-06-18 13:41:52 +01:00
Lars Vahlenberg
33dd519f56 Throw exception when bzip2 is corrupt 2024-06-08 18:26:12 +02:00
Lars Vahlenberg
5c1149aa8b #844 2024-06-08 17:22:20 +02:00
Adam Hathcock
9061e92af6 Merge pull request #848 from Morilli/fix-gzip-archivetype
Fix gzip archives having a `Type` of `ArchiveType.Tar` instead of `ArchiveType.Gzip`
2024-06-06 08:21:14 +01:00
Morilli
49f5ceaa9b Fix GZipArchive getting Type set to ArchiveType.Tar 2024-06-04 10:34:06 +02:00
Morilli
525b309d37 Add failing test 2024-06-04 10:33:32 +02:00
Adam Hathcock
bdb3a787fc Merge pull request #847 from DannyBoyk/846_tar_longlinkname
Tar: Add processing for the LongLink header type
2024-06-04 08:47:57 +01:00
Daniel Nash
a9601ef848 Tar: Add processing for the LongLink header type
Fixes #846
2024-06-03 12:54:19 -04:00
126 changed files with 2423 additions and 673 deletions

View File

@@ -3,10 +3,11 @@
"isRoot": true,
"tools": {
"csharpier": {
"version": "0.28.1",
"version": "0.30.6",
"commands": [
"dotnet-csharpier"
]
],
"rollForward": false
}
}
}

View File

@@ -1,18 +1,19 @@
<Project>
<ItemGroup>
<PackageVersion Include="Bullseye" Version="5.0.0" />
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="FluentAssertions" Version="7.0.0" />
<PackageVersion Include="Glob" Version="1.1.9" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageVersion Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageVersion Include="SimpleExec" Version="12.0.0" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
<PackageVersion Include="System.Buffers" Version="4.6.0" />
<PackageVersion Include="System.Memory" Version="4.6.0" />
<PackageVersion Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageVersion Include="xunit" Version="2.7.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.8" />
<PackageVersion Include="xunit.SkippableFact" Version="1.4.13" />
<PackageVersion Include="ZstdSharp.Port" Version="0.8.0" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.1" />
<PackageVersion Include="xunit.SkippableFact" Version="1.5.23" />
<PackageVersion Include="ZstdSharp.Port" Version="0.8.4" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
</ItemGroup>
</Project>

View File

@@ -11,7 +11,7 @@
| Archive Format | Compression Format(s) | Compress/Decompress | Archive API | Reader API | Writer API |
| ---------------------- | ------------------------------------------------- | ------------------- | --------------- | ---------- | ------------- |
| Rar | Rar | Decompress (1) | RarArchive | RarReader | N/A |
| Zip (2) | None, DEFLATE, Deflate64, BZip2, LZMA/LZMA2, PPMd | Both | ZipArchive | ZipReader | ZipWriter |
| Zip (2) | None, Shrink, Reduce, Implode, DEFLATE, Deflate64, BZip2, LZMA/LZMA2, PPMd | Both | ZipArchive | ZipReader | ZipWriter |
| Tar | None | Both | TarArchive | TarReader | TarWriter (3) |
| Tar.GZip | DEFLATE | Both | TarArchive | TarReader | TarWriter (3) |
| Tar.BZip2 | BZip2 | Both | TarArchive | TarReader | TarWriter (3) |

View File

@@ -27,7 +27,7 @@ To deal with the "correct" rules as well as the expectations of users, I've deci
To be explicit though, consider always using the overloads that use `ReaderOptions` or `WriterOptions` and explicitly set `LeaveStreamOpen` the way you want.
If using Compression Stream classes directly and you don't want the wrapped stream to be closed. Use the `NonDisposingStream` as a wrapped to prevent the stream being disposed. The change in 0.21 simplified a lot even though the usage is a bit more convoluted.
If using Compression Stream classes directly and you don't want the wrapped stream to be closed. Use the `NonDisposingStream` as a wrapper to prevent the stream being disposed. The change in 0.21 simplified a lot even though the usage is a bit more convoluted.
## Samples

View File

@@ -14,11 +14,31 @@
"resolved": "1.1.9",
"contentHash": "AfK5+ECWYTP7G3AAdnU8IfVj+QpGjrh9GC2mpdcJzCvtQ4pnerAGwHsxJ9D4/RnhDUz2DSzd951O/lQjQby2Sw=="
},
"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"
}
},
"SimpleExec": {
"type": "Direct",
"requested": "[12.0.0, )",
"resolved": "12.0.0",
"contentHash": "ptxlWtxC8vM6Y6e3h9ZTxBBkOWnWrm/Sa1HT+2i1xcXY3Hx2hmKDZP5RShPf8Xr9D+ivlrXNy57ktzyH8kyt+Q=="
},
"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=="
}
}
}

View File

@@ -141,7 +141,7 @@ internal static class Adler32 // From https://github.com/SixLabors/ImageSharp/bl
4,
3,
2,
1 // tap2
1, // tap2
};
#endif

View File

@@ -189,9 +189,10 @@ public static class ArchiveFactory
foreach (var factory in Factory.Factories)
{
var isArchive = factory.IsArchive(stream);
stream.Position = startPosition;
if (factory.IsArchive(stream, null))
if (isArchive)
{
type = factory.KnownArchiveType;
return true;
@@ -239,4 +240,6 @@ public static class ArchiveFactory
}
}
}
public static IArchiveFactory AutoFactory { get; } = new AutoArchiveFactory();
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common;
using SharpCompress.Readers;
namespace SharpCompress.Archives;
class AutoArchiveFactory : IArchiveFactory
{
public string Name => nameof(AutoArchiveFactory);
public ArchiveType? KnownArchiveType => null;
public IEnumerable<string> GetSupportedExtensions() => throw new NotSupportedException();
public bool IsArchive(Stream stream, string? password = null) =>
throw new NotSupportedException();
public FileInfo? GetFilePart(int index, FileInfo part1) => throw new NotSupportedException();
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(stream, readerOptions);
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(fileInfo, readerOptions);
}

View File

@@ -101,7 +101,7 @@ public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
/// </summary>
/// <param name="sourceStream"></param>
private GZipArchive(SourceStream sourceStream)
: base(ArchiveType.Tar, sourceStream) { }
: base(ArchiveType.GZip, sourceStream) { }
protected override IEnumerable<GZipVolume> LoadVolumes(SourceStream sourceStream)
{

View File

@@ -54,14 +54,26 @@ 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

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using SharpCompress.Common.Rar;

View File

@@ -14,6 +14,7 @@ namespace SharpCompress.Archives.Rar;
public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
{
private bool _disposed;
internal Lazy<IRarUnpack> UnpackV2017 { get; } =
new(() => new Compressors.Rar.UnpackV2017.Unpack());
internal Lazy<IRarUnpack> UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack());
@@ -25,6 +26,20 @@ public class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>
private RarArchive(SourceStream sourceStream)
: base(ArchiveType.Rar, sourceStream) { }
public override void Dispose()
{
if (!_disposed)
{
if (UnpackV1.IsValueCreated && UnpackV1.Value is IDisposable unpackV1)
{
unpackV1.Dispose();
}
_disposed = true;
base.Dispose();
}
}
protected override IEnumerable<RarArchiveEntry> LoadEntries(IEnumerable<RarVolume> volumes) =>
RarArchiveEntryFactory.GetEntries(this, volumes, ReaderOptions);

View File

@@ -163,7 +163,7 @@ public class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVol
{
stream.Position = 0;
var reader = new ArchiveReader();
reader.Open(stream);
reader.Open(stream, lookForHeader: ReaderOptions.LookForHeader);
_database = reader.ReadDatabase(new PasswordProvider(ReaderOptions.Password));
}
}

View File

@@ -1,3 +1,7 @@
using System;
using System.Runtime.CompilerServices;
[assembly: CLSCompliant(true)]
[assembly: InternalsVisibleTo(
"SharpCompress.Test,PublicKey=0024000004800000940000000602000000240000525341310004000001000100158bebf1433f76dffc356733c138babea7a47536c65ed8009b16372c6f4edbb20554db74a62687f56b97c20a6ce8c4b123280279e33c894e7b3aa93ab3c573656fde4db576cfe07dba09619ead26375b25d2c4a8e43f7be257d712b0dd2eb546f67adb09281338618a58ac834fc038dd7e2740a7ab3591826252e4f4516306dc"
)]

View File

@@ -1,33 +0,0 @@
using System.Buffers;
namespace SharpCompress;
internal static class BufferPool
{
/// <summary>
/// gets a buffer from the pool
/// </summary>
/// <param name="bufferSize">size of the buffer</param>
/// <returns>the buffer</returns>
public static byte[] Rent(int bufferSize)
{
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
return ArrayPool<byte>.Shared.Rent(bufferSize);
#else
return new byte[bufferSize];
#endif
}
/// <summary>
/// returns a buffer to the pool
/// </summary>
/// <param name="buffer">the buffer to return</param>
public static void Return(byte[] buffer)
{
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
ArrayPool<byte>.Shared.Return(buffer);
#else
// no-op
#endif
}
}

View File

@@ -6,5 +6,5 @@ public enum ArchiveType
Zip,
Tar,
SevenZip,
GZip
GZip,
}

View File

@@ -16,5 +16,10 @@ public enum CompressionType
Unknown,
Deflate64,
Shrink,
Lzw
Lzw,
Reduce1,
Reduce2,
Reduce3,
Reduce4,
Explode,
}

View File

@@ -37,6 +37,7 @@ internal static class ExtractionMethods
options ??= new ExtractionOptions() { Overwrite = true };
var file = Path.GetFileName(entry.Key.NotNull("Entry Key is null")).NotNull("File is null");
file = Utility.ReplaceInvalidFileNameChars(file);
if (options.ExtractFullPath)
{
var folder = Path.GetDirectoryName(entry.Key.NotNull("Entry Key is null"))

View File

@@ -13,7 +13,7 @@ public enum HeaderType : byte
Sign,
NewSub,
EndArchive,
Crypt
Crypt,
}
internal static class HeaderCodeV

View File

@@ -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);
}
}

View File

@@ -1220,23 +1220,46 @@ internal class ArchiveReader
#region Public Methods
public void Open(Stream stream)
public void Open(Stream stream, bool lookForHeader)
{
Close();
_streamOrigin = stream.Position;
_streamEnding = stream.Length;
// TODO: Check Signature!
_header = new byte[0x20];
for (var offset = 0; offset < 0x20; )
var canScan = lookForHeader ? 0x80000 - 20 : 0;
while (true)
{
var delta = stream.Read(_header, offset, 0x20 - offset);
if (delta == 0)
// TODO: Check Signature!
_header = new byte[0x20];
for (var offset = 0; offset < 0x20; )
{
throw new EndOfStreamException();
var delta = stream.Read(_header, offset, 0x20 - offset);
if (delta == 0)
{
throw new EndOfStreamException();
}
offset += delta;
}
offset += delta;
if (
!lookForHeader
|| _header
.AsSpan(0, length: 6)
.SequenceEqual<byte>([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C])
)
{
break;
}
if (canScan == 0)
{
throw new InvalidFormatException("Unable to find 7z signature");
}
canScan--;
stream.Position = ++_streamOrigin;
}
_stream = stream;

View File

@@ -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 NotImplementedException(),
};
}

View File

@@ -14,5 +14,5 @@ internal enum EntryType : byte
LongName = (byte)'L',
SparseFile = (byte)'S',
VolumeHeader = (byte)'V',
GlobalExtendedHeader = (byte)'g'
GlobalExtendedHeader = (byte)'g',
}

View File

@@ -101,57 +101,85 @@ internal sealed class TarHeader
internal bool Read(BinaryReader reader)
{
var buffer = ReadBlock(reader);
if (buffer.Length == 0)
string? longName = null;
string? longLinkName = null;
var hasLongValue = true;
byte[] buffer;
EntryType entryType;
do
{
buffer = ReadBlock(reader);
if (buffer.Length == 0)
{
return false;
}
entryType = ReadEntryType(buffer);
// LongName and LongLink headers can follow each other and need
// to apply to the header that follows them.
if (entryType == EntryType.LongName)
{
longName = ReadLongName(reader, buffer);
continue;
}
else if (entryType == EntryType.LongLink)
{
longLinkName = ReadLongName(reader, buffer);
continue;
}
hasLongValue = false;
} while (hasLongValue);
// Check header checksum
if (!checkChecksum(buffer))
{
return false;
}
// for symlinks, additionally read the linkname
if (ReadEntryType(buffer) == EntryType.SymLink)
{
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);
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;
}
@@ -286,9 +314,45 @@ internal sealed class TarHeader
(byte)' ',
(byte)' ',
(byte)' ',
(byte)' '
(byte)' ',
};
internal static bool checkChecksum(byte[] buf)
{
const int eightSpacesChksum = 256;
var buffer = new Span<byte>(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.

View File

@@ -13,5 +13,5 @@ internal enum HeaderFlags : ushort
EnhancedDeflate = 16,
//Bit 11: Language encoding flag
Efs = 2048
Efs = 2048,
}

View File

@@ -14,7 +14,7 @@ internal enum ExtraDataType : ushort
// -Info-ZIP Unicode Path Extra Field
UnicodePathExtraField = 0x7075,
Zip64ExtendedInformationExtraField = 0x0001,
UnixTimeExtraField = 0x5455
UnixTimeExtraField = 0x5455,
}
internal class ExtraData
@@ -166,10 +166,10 @@ internal sealed class UnixTimeExtraField : ExtraData
return Tuple.Create<DateTime?, DateTime?, DateTime?>(null, null, null);
}
var flags = DataBytes[0];
var isModifiedTimeSpecified = (flags & 0x01) == 1;
var isLastAccessTimeSpecified = (flags & 0x02) == 1;
var isCreationTimeSpecified = (flags & 0x04) == 1;
var flags = (RecordedTimeFlag)DataBytes[0];
var isModifiedTimeSpecified = flags.HasFlag(RecordedTimeFlag.LastModified);
var isLastAccessTimeSpecified = flags.HasFlag(RecordedTimeFlag.LastAccessed);
var isCreationTimeSpecified = flags.HasFlag(RecordedTimeFlag.Created);
var currentIndex = 1;
DateTime? modifiedTime = null;
DateTime? lastAccessTime = null;
@@ -189,7 +189,7 @@ internal sealed class UnixTimeExtraField : ExtraData
{
if (currentIndex + 4 > DataBytes.Length)
{
throw new ArchiveException("Invalid UnicodeExtraTime field");
return Tuple.Create<DateTime?, DateTime?, DateTime?>(null, null, null);
}
var lastAccessEpochTime = BinaryPrimitives.ReadInt32LittleEndian(
@@ -206,7 +206,7 @@ internal sealed class UnixTimeExtraField : ExtraData
{
if (currentIndex + 4 > DataBytes.Length)
{
throw new ArchiveException("Invalid UnicodeExtraTime field");
return Tuple.Create<DateTime?, DateTime?, DateTime?>(null, null, null);
}
var creationTimeEpochTime = BinaryPrimitives.ReadInt32LittleEndian(
@@ -222,6 +222,15 @@ internal sealed class UnixTimeExtraField : ExtraData
return Tuple.Create(modifiedTime, lastAccessTime, creationTime);
}
}
[Flags]
private enum RecordedTimeFlag
{
None = 0,
LastModified = 1,
LastAccessed = 2,
Created = 4,
}
}
internal static class LocalEntryHeaderExtraFactory
@@ -229,11 +238,14 @@ internal static class LocalEntryHeaderExtraFactory
internal static ExtraData Create(ExtraDataType type, ushort length, byte[] extraData) =>
type switch
{
ExtraDataType.UnicodePathExtraField
=> new ExtraUnicodePathExtraField(type, length, extraData),
ExtraDataType.Zip64ExtendedInformationExtraField
=> new Zip64ExtendedInformationExtraField(type, length, extraData),
ExtraDataType.UnicodePathExtraField => new ExtraUnicodePathExtraField(
type,
length,
extraData
),
ExtraDataType.Zip64ExtendedInformationExtraField =>
new Zip64ExtendedInformationExtraField(type, length, extraData),
ExtraDataType.UnixTimeExtraField => new UnixTimeExtraField(type, length, extraData),
_ => new ExtraData(type, length, extraData)
_ => new ExtraData(type, length, extraData),
};
}

View File

@@ -8,5 +8,5 @@ internal enum ZipHeaderType
DirectoryEnd,
Split,
Zip64DirectoryEnd,
Zip64DirectoryEndLocator
Zip64DirectoryEndLocator,
}

View File

@@ -6,7 +6,7 @@ namespace SharpCompress.Common.Zip;
internal enum CryptoMode
{
Encrypt,
Decrypt
Decrypt,
}
internal class PkwareTraditionalCryptoStream : Stream

View File

@@ -36,10 +36,7 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory
uint headerBytes = 0;
if (
_lastEntryHeader != null
&& (
FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)
|| _lastEntryHeader.IsZip64
)
&& FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)
)
{
if (_lastEntryHeader.Part is null)
@@ -49,7 +46,9 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory
reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation(
ref rewindableStream
);
var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null;
var crc = reader.ReadUInt32();
if (crc == POST_DATA_DESCRIPTOR)
{
@@ -82,6 +81,60 @@ internal class StreamingZipHeaderFactory : ZipHeaderFactory
_lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize;
}
}
else if (_lastEntryHeader != null && _lastEntryHeader.IsZip64)
{
if (_lastEntryHeader.Part is null)
continue;
reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation(
ref rewindableStream
);
var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null;
headerBytes = reader.ReadUInt32();
var version = reader.ReadUInt16();
var flags = (HeaderFlags)reader.ReadUInt16();
var compressionMethod = (ZipCompressionMethod)reader.ReadUInt16();
var lastModifiedDate = reader.ReadUInt16();
var lastModifiedTime = reader.ReadUInt16();
var crc = reader.ReadUInt32();
if (crc == POST_DATA_DESCRIPTOR)
{
crc = reader.ReadUInt32();
}
_lastEntryHeader.Crc = crc;
// The DataDescriptor can be either 64bit or 32bit
var compressed_size = reader.ReadUInt32();
var uncompressed_size = reader.ReadUInt32();
// Check if we have header or 64bit DataDescriptor
var test_header = !(headerBytes == 0x04034b50 || headerBytes == 0x02014b50);
var test_64bit = ((long)uncompressed_size << 32) | compressed_size;
if (test_64bit == _lastEntryHeader.CompressedSize && test_header)
{
_lastEntryHeader.UncompressedSize =
((long)reader.ReadUInt32() << 32) | headerBytes;
headerBytes = reader.ReadUInt32();
}
else
{
_lastEntryHeader.UncompressedSize = uncompressed_size;
}
if (pos.HasValue)
{
_lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize;
// 4 = First 4 bytes of the entry header (i.e. 50 4B 03 04)
rewindableStream.Position = pos.Value + 4;
}
}
else
{
headerBytes = reader.ReadUInt32();

View File

@@ -4,5 +4,5 @@ internal enum WinzipAesKeySize
{
KeySize128 = 1,
KeySize192 = 2,
KeySize256 = 3
KeySize256 = 3,
}

View File

@@ -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,
@@ -11,5 +16,5 @@ internal enum ZipCompressionMethod
ZStd = 93,
Xz = 95,
PPMd = 98,
WinzipAes = 0x63 //http://www.winzip.com/aes_info.htm
WinzipAes = 0x63, //http://www.winzip.com/aes_info.htm
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SharpCompress.Common.Zip.Headers;
namespace SharpCompress.Common.Zip;
@@ -15,10 +16,19 @@ public class ZipEntry : Entry
return;
}
_filePart = filePart;
LastModifiedTime = Utility.DosDateToDateTime(
filePart.Header.LastModifiedDate,
filePart.Header.LastModifiedTime
);
var times =
filePart.Header.Extra.FirstOrDefault(header =>
header.GetType() == typeof(UnixTimeExtraField)
) as UnixTimeExtraField;
LastAccessedTime = times?.UnicodeTimes.Item2;
CreatedTime = times?.UnicodeTimes.Item3;
}
public override CompressionType CompressionType =>
@@ -31,7 +41,12 @@ public class ZipEntry : Entry
ZipCompressionMethod.PPMd => CompressionType.PPMd,
ZipCompressionMethod.None => CompressionType.None,
ZipCompressionMethod.Shrink => CompressionType.Shrink,
_ => CompressionType.Unknown
ZipCompressionMethod.Reduce1 => CompressionType.Reduce1,
ZipCompressionMethod.Reduce2 => CompressionType.Reduce2,
ZipCompressionMethod.Reduce3 => CompressionType.Reduce3,
ZipCompressionMethod.Reduce4 => CompressionType.Reduce4,
ZipCompressionMethod.Explode => CompressionType.Explode,
_ => CompressionType.Unknown,
};
public override long Crc => _filePart?.Header.Crc ?? 0;
@@ -46,9 +61,17 @@ public class ZipEntry : Entry
public override DateTime? LastModifiedTime { get; }
public override DateTime? CreatedTime => null;
/// <inheritdoc/>
/// <remarks>
/// The returned time is UTC, not local.
/// </remarks>
public override DateTime? CreatedTime { get; }
public override DateTime? LastAccessedTime => null;
/// <inheritdoc/>
/// <remarks>
/// The returned time is UTC, not local.
/// </remarks>
public override DateTime? LastAccessedTime { get; }
public override DateTime? ArchivedTime => null;

View File

@@ -7,8 +7,10 @@ using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Compressors.Deflate64;
using SharpCompress.Compressors.Explode;
using SharpCompress.Compressors.LZMA;
using SharpCompress.Compressors.PPMd;
using SharpCompress.Compressors.Reduce;
using SharpCompress.Compressors.Shrink;
using SharpCompress.Compressors.Xz;
using SharpCompress.IO;
@@ -89,6 +91,32 @@ 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 +231,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:

View File

@@ -56,11 +56,11 @@ internal class ZipHeaderFactory
case POST_DATA_DESCRIPTOR:
{
if (
FlagUtility.HasFlag(
_lastEntryHeader != null
&& FlagUtility.HasFlag(
_lastEntryHeader.NotNull().Flags,
HeaderFlags.UsePostDataDescriptor
)
&& _lastEntryHeader != null
)
{
_lastEntryHeader.Crc = reader.ReadUInt32();

View File

@@ -555,6 +555,6 @@ internal class BZip2Constants
858,
364,
936,
638
638,
};
}

View File

@@ -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()
{

View File

@@ -1829,7 +1829,7 @@ internal sealed class CBZip2OutputStream : Stream
88573,
265720,
797161,
2391484
2391484,
};
private void AllocateCompressStructures()

View File

@@ -288,7 +288,7 @@ internal class CRC
unchecked((int)0xbcb4666d),
unchecked((int)0xb8757bda),
unchecked((int)0xb5365d03),
unchecked((int)0xb1f740b4)
unchecked((int)0xb1f740b4),
};
public CRC() => InitialiseCRC();

View File

@@ -3,5 +3,5 @@ namespace SharpCompress.Compressors;
public enum CompressionMode
{
Compress = 0,
Decompress = 1
Decompress = 1,
}

View File

@@ -106,7 +106,7 @@ internal sealed partial class DeflateManager
5,
5,
5,
0
0,
};
// extra bits for each distance code
@@ -141,7 +141,7 @@ internal sealed partial class DeflateManager
12,
12,
13,
13
13,
};
internal enum BlockState
@@ -149,14 +149,14 @@ internal sealed partial class DeflateManager
NeedMore = 0, // block not completed, need more input or more output
BlockDone, // block flush performed
FinishStarted, // finish started, need only more output at next deflate
FinishDone // finish done, accept no more input or output
FinishDone, // finish done, accept no more input or output
}
internal enum DeflateFlavor
{
Store,
Fast,
Slow
Slow,
}
private const int MEM_LEVEL_MAX = 9;
@@ -214,7 +214,7 @@ internal sealed partial class DeflateManager
new Config(8, 16, 128, 128, DeflateFlavor.Slow),
new Config(8, 32, 128, 256, DeflateFlavor.Slow),
new Config(32, 128, 258, 1024, DeflateFlavor.Slow),
new Config(32, 258, 258, 4096, DeflateFlavor.Slow)
new Config(32, 258, 258, 4096, DeflateFlavor.Slow),
};
private static readonly Config[] Table;
@@ -233,7 +233,7 @@ internal sealed partial class DeflateManager
"insufficient memory",
"buffer error",
"incompatible version",
""
"",
};
// preset dictionary flag in zlib header
@@ -1793,7 +1793,7 @@ internal sealed partial class DeflateManager
DeflateFlavor.Store => DeflateNone,
DeflateFlavor.Fast => DeflateFast,
DeflateFlavor.Slow => DeflateSlow,
_ => DeflateFunction
_ => DeflateFunction,
};
internal int SetParams(CompressionLevel level, CompressionStrategy strategy)

View File

@@ -39,5 +39,5 @@ public enum FlushType
Full,
/// <summary>Signals the end of the compression/decompression stream.</summary>
Finish
Finish,
}

View File

@@ -1615,7 +1615,7 @@ internal sealed class InfTree
79,
0,
9,
255
255,
};
//UPGRADE_NOTE: Final was removed from the declaration of 'fixed_td'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
@@ -1716,7 +1716,7 @@ internal sealed class InfTree
193,
192,
5,
24577
24577,
};
// Tables for deflate from PKZIP's appnote.txt.
@@ -1753,7 +1753,7 @@ internal sealed class InfTree
227,
258,
0,
0
0,
};
// see note #13 above about 258
@@ -1790,7 +1790,7 @@ internal sealed class InfTree
5,
0,
112,
112
112,
};
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdist'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
@@ -1825,7 +1825,7 @@ internal sealed class InfTree
8193,
12289,
16385,
24577
24577,
};
//UPGRADE_NOTE: Final was removed from the declaration of 'cpdext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
@@ -1860,7 +1860,7 @@ internal sealed class InfTree
12,
12,
13,
13
13,
};
// If BMAX needs to be larger than 16, then h and x[] should be uLong.

View File

@@ -93,7 +93,7 @@ internal sealed class InflateBlocks
2,
14,
1,
15
15,
};
internal ZlibCodec _codec; // pointer back to this zlib stream
@@ -815,7 +815,7 @@ internal sealed class InflateBlocks
CODES = 6, // processing fixed or dynamic block
DRY = 7, // output remaining window bytes
DONE = 8, // finished last block, done
BAD = 9 // ot a data error--stuck here
BAD = 9, // ot a data error--stuck here
}
#endregion
@@ -842,7 +842,7 @@ internal static class InternalInflateConstants
0x00001fff,
0x00003fff,
0x00007fff,
0x0000ffff
0x0000ffff,
};
}
@@ -2054,7 +2054,7 @@ internal sealed class InflateManager
CHECK2 = 10, // two check bytes to go
CHECK1 = 11, // one check byte to go
DONE = 12, // finished check, done
BAD = 13 // got an error--stay here
BAD = 13, // got an error--stay here
}
#endregion

View File

@@ -95,7 +95,7 @@ internal sealed partial class DeflateManager
2,
14,
1,
15
15,
};
// The lengths of the bit length codes are sent in order of decreasing
@@ -618,7 +618,7 @@ internal sealed partial class DeflateManager
29,
29,
29,
29
29,
};
internal static readonly sbyte[] LengthCode =
@@ -878,7 +878,7 @@ internal sealed partial class DeflateManager
27,
27,
27,
28
28,
};
internal static readonly int[] LengthBase =
@@ -911,7 +911,7 @@ internal sealed partial class DeflateManager
160,
192,
224,
0
0,
};
internal static readonly int[] DistanceBase =
@@ -945,7 +945,7 @@ internal sealed partial class DeflateManager
8192,
12288,
16384,
24576
24576,
};
internal short[] dyn_tree; // the dynamic tree

View File

@@ -143,7 +143,7 @@ public enum CompressionLevel
/// <summary>
/// A synonym for BestCompression.
/// </summary>
Level9 = BestCompression
Level9 = BestCompression,
}
/// <summary>
@@ -171,7 +171,7 @@ public enum CompressionStrategy
/// Using <c>HuffmanOnly</c> will force the compressor to do Huffman encoding only, with no
/// string matching.
/// </summary>
HuffmanOnly = 2
HuffmanOnly = 2,
}
/// <summary>
@@ -859,7 +859,7 @@ internal sealed class StaticTree
99,
8,
227,
8
8,
};
internal static readonly short[] distTreeCodes =
@@ -923,7 +923,7 @@ internal sealed class StaticTree
7,
5,
23,
5
5,
};
// extra bits for each bit length code
@@ -947,7 +947,7 @@ internal sealed class StaticTree
0,
2,
3,
7
7,
};
internal static readonly StaticTree Literals;

View File

@@ -39,7 +39,7 @@ internal enum ZlibStreamFlavor
{
ZLIB = 1950,
DEFLATE = 1951,
GZIP = 1952
GZIP = 1952,
}
internal class ZlibBaseStream : Stream
@@ -655,6 +655,6 @@ internal class ZlibBaseStream : Stream
{
Writer,
Reader,
Undefined
Undefined,
}
}

View File

@@ -8,5 +8,5 @@ internal enum BlockType
{
Uncompressed = 0,
Static = 1,
Dynamic = 2
Dynamic = 2,
}

View File

@@ -111,7 +111,7 @@ internal static class FastEncoderStatics
0x7e,
0x7c,
0x1f,
0x3f
0x3f,
};
internal static ReadOnlySpan<byte> B_FINAL_FAST_ENCODER_TREE_STRUCTURE_DATA =>
@@ -214,7 +214,7 @@ internal static class FastEncoderStatics
0x7e,
0x7c,
0x1f,
0x3f
0x3f,
};
// Output a currentMatch with length matchLen (>= MIN_MATCH) and displacement matchPos
@@ -762,7 +762,7 @@ internal static class FastEncoderStatics
0x0039e7f1,
0x003be7f1,
0x003de7f1,
0x000047eb
0x000047eb,
};
internal static readonly uint[] FAST_ENCODER_DISTANCE_CODE_INFO =
@@ -798,7 +798,7 @@ internal static class FastEncoderStatics
0x000007d5,
0x000017d5,
0x00000000,
0x00000100
0x00000100,
};
internal static readonly uint[] BIT_MASK =
@@ -818,7 +818,7 @@ internal static class FastEncoderStatics
4095,
8191,
16383,
32767
32767,
};
internal static readonly byte[] EXTRA_LENGTH_BITS =
{
@@ -850,7 +850,7 @@ internal static class FastEncoderStatics
5,
5,
5,
0
0,
};
internal static readonly byte[] EXTRA_DISTANCE_BITS =
{
@@ -885,7 +885,7 @@ internal static class FastEncoderStatics
13,
13,
0,
0
0,
};
internal const int NUM_CHARS = 256;
internal const int NUM_LENGTH_BASE_CODES = 29;

View File

@@ -70,7 +70,7 @@ internal sealed class InflaterManaged
5,
5,
5,
16
16,
};
// The base length for length code 257 - 285.
@@ -105,7 +105,7 @@ internal sealed class InflaterManaged
163,
195,
227,
3
3,
};
// The base distance for distance code 0 - 31
@@ -143,7 +143,7 @@ internal sealed class InflaterManaged
16385,
24577,
32769,
49153
49153,
};
// code lengths for code length alphabet is stored in following order
@@ -184,7 +184,7 @@ internal sealed class InflaterManaged
0x07,
0x17,
0x0f,
0x1f
0x1f,
};
private readonly OutputWindow _output;

View File

@@ -37,5 +37,5 @@ internal enum InflaterState
ReadingFooter = 22,
VerifyingFooter = 23,
Done = 24 // Finished
Done = 24, // Finished
}

View File

@@ -8,5 +8,5 @@ internal enum MatchState
{
HasSymbol = 1,
HasMatch = 2,
HasSymbolAndMatch = 3
HasSymbolAndMatch = 3,
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -13,7 +13,7 @@ internal class BCJFilter : Filter
true,
false,
false,
false
false,
};
private static readonly int[] MASK_TO_BIT_NUMBER = { 0, 1, 2, 2, 3, 3, 3, 3 };

View File

@@ -39,7 +39,7 @@ internal class BCJFilterIA64 : Filter
4,
4,
0,
0
0,
};
public BCJFilterIA64(bool isEncoder, Stream baseStream)

View File

@@ -147,7 +147,7 @@ internal enum CoderPropId
/// <summary>
/// Specifies mode with end marker.
/// </summary>
EndMarker
EndMarker,
}
internal interface ISetCoderProperties

View File

@@ -205,7 +205,7 @@ public sealed class LZipStream : Stream
(byte)'I',
(byte)'P',
1,
113
113,
};
public static void WriteHeaderSize(Stream stream)
@@ -235,6 +235,6 @@ public sealed class LZipStream : Stream
(byte)(dictionarySize & 0xff),
(byte)((dictionarySize >> 8) & 0xff),
(byte)((dictionarySize >> 16) & 0xff),
(byte)((dictionarySize >> 24) & 0xff)
(byte)((dictionarySize >> 24) & 0xff),
};
}

View File

@@ -12,7 +12,7 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
private enum EMatchFinderType
{
Bt2,
Bt4
Bt4,
}
private const uint K_IFINITY_PRICE = 0xFFFFFFF;

View File

@@ -38,7 +38,7 @@ public class LzmaEncoderProperties
CoderPropId.Algorithm,
CoderPropId.NumFastBytes,
CoderPropId.MatchFinder,
CoderPropId.EndMarker
CoderPropId.EndMarker,
};
_properties = new object[]
{
@@ -49,7 +49,7 @@ public class LzmaEncoderProperties
algorithm,
numFastBytes,
mf,
eos
eos,
};
}
}

View File

@@ -132,7 +132,7 @@ internal class ModelPpm
0x64A1,
0x5ABC,
0x6632,
0x6051
0x6051,
};
// Temp fields

View File

@@ -59,7 +59,7 @@ internal partial class Model
0x64A1,
0x5ABC,
0x6632,
0x6051
0x6051,
};
private static ReadOnlySpan<byte> EXPONENTIAL_ESCAPES =>

View File

@@ -24,5 +24,5 @@ internal enum ModelRestorationMethod
/// <summary>
/// Freeze the context tree (in some cases may result in poor compression).
/// </summary>
Freeze = 2
Freeze = 2,
}

View File

@@ -4,5 +4,5 @@ public enum PpmdVersion
{
H,
H7Z,
I1
I1,
}

View File

@@ -28,7 +28,7 @@ internal class RarBLAKE2spStream : RarStream
0x510E527FU,
0x9B05688CU,
0x1F83D9ABU,
0x5BE0CD19U
0x5BE0CD19U,
};
static readonly byte[][] k_BLAKE2S_Sigma =

View File

@@ -9,7 +9,7 @@ internal static class RarCRC
public static uint CheckCrc(uint startCrc, byte b) =>
(crcTab[((int)startCrc ^ b) & 0xff] ^ (startCrc >> 8));
public static uint CheckCrc(uint startCrc, byte[] data, int offset, int count)
public static uint CheckCrc(uint startCrc, ReadOnlySpan<byte> data, int offset, int count)
{
var size = Math.Min(data.Length - offset, count);

View File

@@ -1,6 +1,7 @@
#nullable disable
using System;
using System.Buffers;
using System.IO;
using SharpCompress.Common.Rar.Headers;
@@ -14,7 +15,7 @@ internal class RarStream : Stream
private bool fetch;
private byte[] tmpBuffer = BufferPool.Rent(65536);
private byte[] tmpBuffer = ArrayPool<byte>.Shared.Rent(65536);
private int tmpOffset;
private int tmpCount;
@@ -42,7 +43,7 @@ internal class RarStream : Stream
{
if (disposing)
{
BufferPool.Return(this.tmpBuffer);
ArrayPool<byte>.Shared.Return(this.tmpBuffer);
this.tmpBuffer = null;
}
isDisposed = true;
@@ -143,11 +144,11 @@ internal class RarStream : Stream
this.tmpBuffer.Length * 2 > this.tmpCount + count
? this.tmpBuffer.Length * 2
: this.tmpCount + count;
var newBuffer = BufferPool.Rent(newLength);
var newBuffer = ArrayPool<byte>.Shared.Rent(newLength);
Buffer.BlockCopy(this.tmpBuffer, 0, newBuffer, 0, this.tmpCount);
var oldBuffer = this.tmpBuffer;
this.tmpBuffer = newBuffer;
BufferPool.Return(oldBuffer);
ArrayPool<byte>.Shared.Return(oldBuffer);
}
}
}

View File

@@ -10,5 +10,5 @@ internal enum CodeType
CODE_STARTFILE,
CODE_ENDFILE,
CODE_VM,
CODE_VMDATA
CODE_VMDATA,
}

View File

@@ -12,5 +12,5 @@ internal enum FilterType : byte
FILTER_RGB,
FILTER_ITANIUM,
FILTER_PPM,
FILTER_NONE
FILTER_NONE,
}

View File

@@ -3,5 +3,5 @@ namespace SharpCompress.Compressors.Rar.UnpackV1.PPM;
internal enum BlockTypes
{
BLOCK_LZ = 0,
BLOCK_PPM = 1
BLOCK_PPM = 1,
}

View File

@@ -1,6 +1,7 @@
#nullable disable
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common;
@@ -12,14 +13,28 @@ using SharpCompress.Compressors.Rar.VM;
namespace SharpCompress.Compressors.Rar.UnpackV1;
internal sealed partial class Unpack : BitInput, IRarUnpack
internal sealed partial class Unpack : BitInput, IRarUnpack, IDisposable
{
private readonly BitInput Inp;
private bool disposed;
public Unpack() =>
// to ease in porting Unpack50.cs
Inp = this;
public void Dispose()
{
if (!disposed)
{
if (!externalWindow)
{
ArrayPool<byte>.Shared.Return(window);
window = null;
}
disposed = true;
}
}
public bool FileExtracted { get; private set; }
public long DestSize
@@ -74,7 +89,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private BlockTypes unpBlockType;
//private bool externalWindow;
private bool externalWindow;
private long writtenFileSize;
@@ -104,22 +119,21 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
2,
14,
0,
12
12,
};
private FileHeader fileHeader;
private void Init(byte[] window)
{
if (window is null)
if (this.window is null && window is null)
{
this.window = new byte[PackDef.MAXWINSIZE];
this.window = ArrayPool<byte>.Shared.Rent(PackDef.MAXWINSIZE);
}
else
else if (window is not null)
{
this.window = window;
//externalWindow = true;
externalWindow = true;
}
inAddr = 0;
UnpInitData(false);
@@ -175,31 +189,24 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private void UnstoreFile()
{
var buffer = new byte[0x10000];
while (true)
Span<byte> buffer = stackalloc byte[(int)Math.Min(0x10000, destUnpSize)];
do
{
var code = readStream.Read(buffer, 0, (int)Math.Min(buffer.Length, destUnpSize));
var code = readStream.Read(buffer);
if (code == 0 || code == -1)
{
break;
}
code = code < destUnpSize ? code : (int)destUnpSize;
writeStream.Write(buffer, 0, code);
if (destUnpSize >= 0)
{
destUnpSize -= code;
}
if (suspended)
{
return;
}
}
writeStream.Write(buffer.Slice(0, code));
destUnpSize -= code;
} while (!suspended && destUnpSize > 0);
}
private void Unpack29(bool solid)
{
var DDecode = new int[PackDef.DC];
var DBits = new byte[PackDef.DC];
Span<int> DDecode = stackalloc int[PackDef.DC];
Span<byte> DBits = stackalloc byte[PackDef.DC];
int Bits;
@@ -859,9 +866,9 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private bool ReadTables()
{
var bitLength = new byte[PackDef.BC];
Span<byte> bitLength = stackalloc byte[PackDef.BC];
Span<byte> table = stackalloc byte[PackDef.HUFF_TABLE_SIZE];
var table = new byte[PackDef.HUFF_TABLE_SIZE];
if (inAddr > readTop - 25)
{
if (!unpReadBuf())
@@ -989,7 +996,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
// memcpy(unpOldTable,table,sizeof(unpOldTable));
Buffer.BlockCopy(table, 0, unpOldTable, 0, unpOldTable.Length);
table.CopyTo(unpOldTable);
return (true);
}
@@ -1190,7 +1197,7 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
{
return (false);
}
var VMCode = new byte[VMCodeSize];
Span<byte> VMCode = stackalloc byte[VMCodeSize];
for (var I = 0; I < VMCodeSize; I++)
{
if (Inp.Overflow(3))

View File

@@ -88,7 +88,7 @@ internal partial class Unpack
0xf000,
0xf200,
0xf200,
0xffff
0xffff,
};
private static readonly int[] PosL1 = { 0, 0, 0, 2, 3, 5, 7, 11, 16, 20, 24, 32, 32 };
@@ -106,7 +106,7 @@ internal partial class Unpack
0xf000,
0xf200,
0xf240,
0xffff
0xffff,
};
private static readonly int[] PosL2 = { 0, 0, 0, 0, 5, 7, 9, 13, 18, 22, 26, 34, 36 };
@@ -123,7 +123,7 @@ internal partial class Unpack
0xf200,
0xf200,
0xf200,
0xffff
0xffff,
};
private static readonly int[] PosHf0 = { 0, 0, 0, 0, 0, 8, 16, 24, 33, 33, 33, 33, 33 };
@@ -139,7 +139,7 @@ internal partial class Unpack
0xf200,
0xf200,
0xf7e0,
0xffff
0xffff,
};
private static readonly int[] PosHf1 = { 0, 0, 0, 0, 0, 0, 4, 44, 60, 76, 80, 80, 127 };
@@ -155,7 +155,7 @@ internal partial class Unpack
0xfa00,
0xffff,
0xffff,
0xffff
0xffff,
};
private static readonly int[] PosHf2 = { 0, 0, 0, 0, 0, 0, 2, 7, 53, 117, 233, 0, 0 };
@@ -170,7 +170,7 @@ internal partial class Unpack
0xfe80,
0xffff,
0xffff,
0xffff
0xffff,
};
private static readonly int[] PosHf3 = { 0, 0, 0, 0, 0, 0, 0, 2, 16, 218, 251, 0, 0 };
@@ -199,7 +199,7 @@ internal partial class Unpack
0x90,
0x98,
0x9c,
0xb0
0xb0,
};
private static readonly int[] ShortLen2 = { 2, 3, 3, 3, 4, 4, 5, 6, 6, 4, 4, 5, 6, 6, 4, 0 };
@@ -220,7 +220,7 @@ internal partial class Unpack
0x90,
0x98,
0x9c,
0xb0
0xb0,
};
private void unpack15(bool solid)

View File

@@ -64,7 +64,7 @@ internal partial class Unpack
128,
160,
192,
224
224,
};
private static ReadOnlySpan<byte> LBits =>
@@ -97,7 +97,7 @@ internal partial class Unpack
5,
5,
5,
5
5,
};
private static readonly int[] DDecode =
@@ -149,7 +149,7 @@ internal partial class Unpack
786432,
851968,
917504,
983040
983040,
};
private static readonly int[] DBits =
@@ -201,7 +201,7 @@ internal partial class Unpack
16,
16,
16,
16
16,
};
private static readonly int[] SDDecode = { 0, 4, 8, 16, 32, 64, 128, 192 };
@@ -391,8 +391,8 @@ internal partial class Unpack
private bool ReadTables20()
{
var BitLength = new byte[PackDef.BC20];
var Table = new byte[PackDef.MC20 * 4];
Span<byte> BitLength = stackalloc byte[PackDef.BC20];
Span<byte> Table = stackalloc byte[PackDef.MC20 * 4];
int TableSize,
N,
I;

View File

@@ -181,7 +181,12 @@ internal static class UnpackUtility
return (dec.DecodeNum[N]);
}
internal static void makeDecodeTables(byte[] lenTab, int offset, Decode.Decode dec, int size)
internal static void makeDecodeTables(
Span<byte> lenTab,
int offset,
Decode.Decode dec,
int size
)
{
Span<int> lenCount = stackalloc int[16];
Span<int> tmpPos = stackalloc int[16];

View File

@@ -19,7 +19,7 @@ internal partial class Unpack
0xf000,
0xf200,
0xf200,
0xffff
0xffff,
};
private static readonly uint[] PosL1 = { 0, 0, 0, 2, 3, 5, 7, 11, 16, 20, 24, 32, 32 };
@@ -37,7 +37,7 @@ internal partial class Unpack
0xf000,
0xf200,
0xf240,
0xffff
0xffff,
};
private static readonly uint[] PosL2 = { 0, 0, 0, 0, 5, 7, 9, 13, 18, 22, 26, 34, 36 };
@@ -54,7 +54,7 @@ internal partial class Unpack
0xf200,
0xf200,
0xf200,
0xffff
0xffff,
};
private static readonly uint[] PosHf0 = { 0, 0, 0, 0, 0, 8, 16, 24, 33, 33, 33, 33, 33 };
@@ -70,7 +70,7 @@ internal partial class Unpack
0xf200,
0xf200,
0xf7e0,
0xffff
0xffff,
};
private static readonly uint[] PosHf1 = { 0, 0, 0, 0, 0, 0, 4, 44, 60, 76, 80, 80, 127 };
@@ -86,7 +86,7 @@ internal partial class Unpack
0xfa00,
0xffff,
0xffff,
0xffff
0xffff,
};
private static readonly uint[] PosHf2 = { 0, 0, 0, 0, 0, 0, 2, 7, 53, 117, 233, 0, 0 };
@@ -101,7 +101,7 @@ internal partial class Unpack
0xfe80,
0xffff,
0xffff,
0xffff
0xffff,
};
private static readonly uint[] PosHf3 = { 0, 0, 0, 0, 0, 0, 0, 2, 16, 218, 251, 0, 0 };
@@ -225,7 +225,7 @@ internal partial class Unpack
6,
6,
4,
0
0,
};
public static readonly uint[] ShortXor1 =
{
@@ -243,7 +243,7 @@ internal partial class Unpack
0x90,
0x98,
0x9c,
0xb0
0xb0,
};
public static readonly uint[] ShortLen2 =
{
@@ -262,7 +262,7 @@ internal partial class Unpack
6,
6,
4,
0
0,
};
public static readonly uint[] ShortXor2 =
{
@@ -280,7 +280,7 @@ internal partial class Unpack
0x90,
0x98,
0x9c,
0xb0
0xb0,
};
}

View File

@@ -53,7 +53,7 @@ internal partial class Unpack
128,
160,
192,
224
224,
};
public static readonly byte[] LBits =
{
@@ -84,7 +84,7 @@ internal partial class Unpack
5,
5,
5,
5
5,
};
public static readonly uint[] DDecode =
{
@@ -135,7 +135,7 @@ internal partial class Unpack
786432,
851968,
917504,
983040
983040,
};
public static readonly byte[] DBits =
{
@@ -186,7 +186,7 @@ internal partial class Unpack
16,
16,
16,
16
16,
};
public static readonly byte[] SDDecode = { 0, 4, 8, 16, 32, 64, 128, 192 };
public static readonly byte[] SDBits = { 2, 2, 3, 4, 5, 6, 6, 6 };

View File

@@ -776,14 +776,14 @@ internal sealed class RarVM : BitInput
}
}
public void prepare(byte[] code, int codeSize, VMPreparedProgram prg)
public void prepare(ReadOnlySpan<byte> code, int codeSize, VMPreparedProgram prg)
{
InitBitInput();
var cpLength = Math.Min(MAX_SIZE, codeSize);
// memcpy(inBuf,Code,Min(CodeSize,BitInput::MAX_SIZE));
Buffer.BlockCopy(code, 0, InBuf, 0, cpLength);
code.Slice(0, cpLength).CopyTo(InBuf);
byte xorSum = 0;
for (var i = 1; i < codeSize; i++)
{
@@ -1105,7 +1105,7 @@ internal sealed class RarVM : BitInput
}
}
private VMStandardFilters IsStandardFilter(byte[] code, int codeSize)
private VMStandardFilters IsStandardFilter(ReadOnlySpan<byte> code, int codeSize)
{
VMStandardFilterSignature[] stdList =
{
@@ -1115,7 +1115,7 @@ internal sealed class RarVM : BitInput
new(29, 0x0e06077d, VMStandardFilters.VMSF_DELTA),
new(149, 0x1c2c5dc8, VMStandardFilters.VMSF_RGB),
new(216, 0xbc85e701, VMStandardFilters.VMSF_AUDIO),
new(40, 0x46b9c560, VMStandardFilters.VMSF_UPCASE)
new(40, 0x46b9c560, VMStandardFilters.VMSF_UPCASE),
};
var CodeCRC = RarCRC.CheckCrc(0xffffffff, code, 0, code.Length) ^ 0xffffffff;
for (var i = 0; i < stdList.Length; i++)

View File

@@ -53,6 +53,6 @@ internal class VMCmdFlags
VMCF_OP2 | VMCF_BYTEMODE,
VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS,
VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS,
VMCF_OP0
VMCF_OP0,
};
}

View File

@@ -66,5 +66,5 @@ internal enum VMCommands
VM_NEGB = 52,
VM_NEGD = 53,
VM_STANDARD = 54
VM_STANDARD = 54,
}

View File

@@ -5,5 +5,5 @@ internal enum VMFlags
None = 0,
VM_FC = 1,
VM_FZ = 2,
VM_FS = 80000000
VM_FS = 80000000,
}

View File

@@ -5,5 +5,5 @@ internal enum VMOpType
VM_OPREG = 0,
VM_OPINT = 1,
VM_OPREGMEM = 2,
VM_OPNONE = 3
VM_OPNONE = 3,
}

View File

@@ -9,5 +9,5 @@ internal enum VMStandardFilters
VMSF_RGB = 4,
VMSF_AUDIO = 5,
VMSF_DELTA = 6,
VMSF_UPCASE = 7
VMSF_UPCASE = 7,
}

View File

@@ -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;
}
}

View File

@@ -32,7 +32,7 @@ namespace SharpCompress.Compressors.Shrink
8191U,
16383U,
(uint)short.MaxValue,
(uint)ushort.MaxValue
(uint)ushort.MaxValue,
};
public BitStream(byte[] src, int srcLen)

View File

@@ -387,7 +387,7 @@ namespace SharpCompress.Compressors.Shrink
{
Ok,
Full,
Error
Error,
}
private struct CodeQueue

View File

@@ -5,5 +5,5 @@ public enum CheckType : byte
NONE = 0x00,
CRC32 = 0x01,
CRC64 = 0x04,
SHA256 = 0x0A
SHA256 = 0x0A,
}

View File

@@ -15,20 +15,19 @@ public abstract class BlockFilter : ReadOnlyStream
ArchArmFilter = 0x07,
ArchArmThumbFilter = 0x08,
ArchSparcFilter = 0x09,
Lzma2 = 0x21
Lzma2 = 0x21,
}
private static readonly Dictionary<FilterTypes, Func<BlockFilter>> FILTER_MAP =
new()
{
{ FilterTypes.ArchX86Filter, () => new X86Filter() },
{ FilterTypes.ArchPowerPcFilter, () => new PowerPCFilter() },
{ FilterTypes.ArchIa64Filter, () => new IA64Filter() },
{ FilterTypes.ArchArmFilter, () => new ArmFilter() },
{ FilterTypes.ArchArmThumbFilter, () => new ArmThumbFilter() },
{ FilterTypes.ArchSparcFilter, () => new SparcFilter() },
{ FilterTypes.Lzma2, () => new Lzma2Filter() }
};
private static readonly Dictionary<FilterTypes, Func<BlockFilter>> FILTER_MAP = new()
{
{ FilterTypes.ArchX86Filter, () => new X86Filter() },
{ FilterTypes.ArchPowerPcFilter, () => new PowerPCFilter() },
{ FilterTypes.ArchIa64Filter, () => new IA64Filter() },
{ FilterTypes.ArchArmFilter, () => new ArmFilter() },
{ FilterTypes.ArchArmThumbFilter, () => new ArmThumbFilter() },
{ FilterTypes.ArchSparcFilter, () => new SparcFilter() },
{ FilterTypes.Lzma2, () => new Lzma2Filter() },
};
public abstract bool AllowAsLast { get; }
public abstract bool AllowAsNonLast { get; }

View File

@@ -25,13 +25,14 @@ public sealed class XZBlock : XZReadOnlyStream
private bool _endOfStream;
private bool _paddingSkipped;
private bool _crcChecked;
private ulong _bytesRead;
private readonly long _startPosition;
public XZBlock(Stream stream, CheckType checkType, int checkSize)
: base(stream)
{
_checkType = checkType;
_checkSize = checkSize;
_startPosition = stream.Position;
}
public override int Read(byte[] buffer, int offset, int count)
@@ -67,13 +68,12 @@ public sealed class XZBlock : XZReadOnlyStream
CheckCrc();
}
_bytesRead += (ulong)bytesRead;
return bytesRead;
}
private void SkipPadding()
{
var bytes = (int)(BaseStream.Position % 4);
var bytes = (BaseStream.Position - _startPosition) % 4;
if (bytes > 0)
{
var paddingBytes = new byte[4 - bytes];

View File

@@ -3,5 +3,5 @@ namespace SharpCompress.IO;
public enum StreamingMode
{
Streaming,
Seekable
Seekable,
}

View File

@@ -4,7 +4,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
namespace SharpCompress;
namespace SharpCompress.Helpers;
internal sealed class LazyReadOnlyCollection<T> : ICollection<T>
{

View File

@@ -4,9 +4,9 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
namespace SharpCompress;
namespace SharpCompress.Helpers;
public static class NotNullExtensions
internal static class NotNullExtensions
{
public static IEnumerable<T> Empty<T>(this IEnumerable<T>? source) =>
source ?? Enumerable.Empty<T>();

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace SharpCompress;
public class ReadOnlyCollection<T> : ICollection<T>
{
private readonly ICollection<T> collection;
public ReadOnlyCollection(ICollection<T> collection) => this.collection = collection;
public void Add(T item) => throw new NotSupportedException();
public void Clear() => throw new NotSupportedException();
public bool Contains(T item) => collection.Contains(item);
public void CopyTo(T[] array, int arrayIndex) => collection.CopyTo(array, arrayIndex);
public int Count => collection.Count;
public bool IsReadOnly => true;
public bool Remove(T item) => throw new NotSupportedException();
public IEnumerator<T> GetEnumerator() => collection.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => throw new NotSupportedException();
}

View File

@@ -44,7 +44,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti
#region IDisposable Members
public void Dispose()
public virtual void Dispose()
{
_entriesForCurrentReadStream?.Dispose();
Volume?.Dispose();

View File

@@ -13,6 +13,7 @@ namespace SharpCompress.Readers.Rar;
/// </summary>
public abstract class RarReader : AbstractReader<RarReaderEntry, RarVolume>
{
private bool _disposed;
private RarVolume? volume;
private Lazy<IRarUnpack> UnpackV2017 { get; } =
new(() => new Compressors.Rar.UnpackV2017.Unpack());
@@ -21,6 +22,20 @@ public abstract class RarReader : AbstractReader<RarReaderEntry, RarVolume>
internal RarReader(ReaderOptions options)
: base(options, ArchiveType.Rar) { }
public override void Dispose()
{
if (!_disposed)
{
if (UnpackV1.IsValueCreated && UnpackV1.Value is IDisposable unpackV1)
{
unpackV1.Dispose();
}
_disposed = true;
base.Dispose();
}
}
protected abstract void ValidateArchive(RarVolume archive);
public override RarVolume? Volume => volume;

View File

@@ -39,7 +39,7 @@ public class TarReader : AbstractReader<TarEntry, TarVolume>
CompressionType.Xz => new XZStream(stream),
CompressionType.Lzw => new LzwStream(stream),
CompressionType.None => stream,
_ => throw new NotSupportedException("Invalid compression type: " + compressionType)
_ => throw new NotSupportedException("Invalid compression type: " + compressionType),
};
}

View File

@@ -2,11 +2,11 @@
<PropertyGroup>
<AssemblyTitle>SharpCompress - Pure C# Decompression/Compression</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>0.37.2</VersionPrefix>
<AssemblyVersion>0.37.2</AssemblyVersion>
<FileVersion>0.37.2</FileVersion>
<VersionPrefix>0.39.0</VersionPrefix>
<AssemblyVersion>0.39.0</AssemblyVersion>
<FileVersion>0.39.0</FileVersion>
<Authors>Adam Hathcock</Authors>
<TargetFrameworks>net462;netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net48;net481;netstandard2.0;net6.0;net8.0</TargetFrameworks>
<AssemblyName>SharpCompress</AssemblyName>
<AssemblyOriginatorKeyFile>../../SharpCompress.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
@@ -14,41 +14,32 @@
<PackageTags>rar;unrar;zip;unzip;bzip2;gzip;tar;7zip;lzip;xz</PackageTags>
<PackageProjectUrl>https://github.com/adamhathcock/sharpcompress</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Copyright>Copyright (c) 2014 Adam Hathcock</Copyright>
<Copyright>Copyright (c) 2025 Adam Hathcock</Copyright>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Description>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.</Description>
<Description>SharpCompress is a compression library for NET Standard 2.0/NET 4.8/NET 4.8.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.</Description>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageReadmeFile>README.md</PackageReadmeFile>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Buffers" />
<PackageReference Include="ZstdSharp.Port" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="System.Text.Encoding.CodePages" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="System.Text.Encoding.CodePages" />
<PackageReference Include="System.Memory" />
</ItemGroup>
<ItemGroup Condition=" '$(VersionlessImplicitFrameworkDefine)' == 'NETFRAMEWORK' ">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="System.Text.Encoding.CodePages" />
<PackageReference Include="System.Memory" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>

View File

@@ -1,15 +1,17 @@
global using SharpCompress.Helpers;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using SharpCompress.Readers;
namespace SharpCompress;
namespace SharpCompress.Helpers;
[CLSCompliant(false)]
public static class Utility
internal static class Utility
{
public static ReadOnlyCollection<T> ToReadOnly<T>(this ICollection<T> items) => new(items);
public static ReadOnlyCollection<T> ToReadOnly<T>(this IList<T> items) => new(items);
/// <summary>
/// Performs an unsigned bitwise right shift with the specified number
@@ -434,4 +436,17 @@ public static class Utility
buffer[offset + 2] = (byte)(number >> 8);
buffer[offset + 3] = (byte)number;
}
public static string ReplaceInvalidFileNameChars(string fileName)
{
var invalidChars = new HashSet<char>(Path.GetInvalidFileNameChars());
var sb = new StringBuilder(fileName.Length);
foreach (var c in fileName)
{
var newChar = invalidChars.Contains(c) ? '_' : c;
sb.Append(newChar);
}
return sb.ToString();
}
}

View File

@@ -69,7 +69,7 @@ public class ZipWriter : AbstractWriter
CompressionType.BZip2 => ZipCompressionMethod.BZip2,
CompressionType.LZMA => ZipCompressionMethod.LZMA,
CompressionType.PPMd => ZipCompressionMethod.PPMd,
_ => throw new InvalidFormatException("Invalid compression method: " + compressionType)
_ => throw new InvalidFormatException("Invalid compression method: " + compressionType),
};
public override void Write(string entryPath, Stream source, DateTime? modificationTime) =>
@@ -100,7 +100,7 @@ public class ZipWriter : AbstractWriter
)
{
Comment = options.EntryComment,
ModificationTime = options.ModificationDateTime
ModificationTime = options.ModificationDateTime,
};
// Use the archive default setting for zip64 and allow overrides

View File

@@ -1,25 +1,7 @@
{
"version": 2,
"dependencies": {
".NETFramework,Version=v4.6.2": {
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net462": "1.0.3"
}
},
".NETFramework,Version=v4.8": {
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
@@ -30,35 +12,21 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"System.Memory": {
"System.Buffers": {
"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"
}
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
},
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.0, )",
"resolved": "0.8.0",
"contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==",
"requested": "[0.8.4, )",
"resolved": "0.8.4",
"contentHash": "eieSXq3kakCUXbgdxkKaRqWS6hF0KBJcqok9LlDCs60GOyrynLvPOcQ0pRw7shdPF7lh/VepJ9cP9n9HHc759g==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
"System.Memory": "4.5.5"
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"Microsoft.Build.Tasks.Git": {
@@ -66,21 +34,11 @@
"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",
@@ -98,6 +56,117 @@
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "CentralTransitive",
"requested": "[8.0.0, )",
"resolved": "5.0.0",
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"System.Memory": {
"type": "CentralTransitive",
"requested": "[4.6.0, )",
"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"
}
}
},
".NETFramework,Version=v4.8.1": {
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
"resolved": "1.0.3",
"contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net481": "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.Buffers": {
"type": "Direct",
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
},
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.4, )",
"resolved": "0.8.4",
"contentHash": "eieSXq3kakCUXbgdxkKaRqWS6hF0KBJcqok9LlDCs60GOyrynLvPOcQ0pRw7shdPF7lh/VepJ9cP9n9HHc759g==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.NETFramework.ReferenceAssemblies.net481": {
"type": "Transitive",
"resolved": "1.0.3",
"contentHash": "Vv/20vgHS7VglVOVh8J3Iz/MA+VYKVRp9f7r2qiKBMuzviTOmocG70yq0Q8T5OTmCONkEAIJwETD1zhEfLkAXQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"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"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "CentralTransitive",
"requested": "[8.0.0, )",
"resolved": "5.0.0",
"contentHash": "W8DPQjkMScOMTtJbPwmPyj9c3zYSFGawDW3jwlBOOsnY+EzZFLgNQ/UMkK35JmkNOVPdCyPr2Tw7Vv9N+KA3ZQ==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"System.Memory": {
"type": "CentralTransitive",
"requested": "[4.6.0, )",
"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"
}
}
},
".NETStandard,Version=v2.0": {
@@ -129,15 +198,21 @@
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
"System.Buffers": {
"type": "Direct",
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
},
"System.Memory": {
"type": "Direct",
"requested": "[4.5.5, )",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.4.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
"System.Buffers": "4.6.0",
"System.Numerics.Vectors": "4.6.0",
"System.Runtime.CompilerServices.Unsafe": "6.1.0"
}
},
"System.Text.Encoding.CodePages": {
@@ -152,12 +227,13 @@
},
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.0, )",
"resolved": "0.8.0",
"contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==",
"requested": "[0.8.4, )",
"resolved": "0.8.4",
"contentHash": "eieSXq3kakCUXbgdxkKaRqWS6hF0KBJcqok9LlDCs60GOyrynLvPOcQ0pRw7shdPF7lh/VepJ9cP9n9HHc759g==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "5.0.0",
"System.Memory": "4.5.5"
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"Microsoft.Build.Tasks.Git": {
@@ -175,20 +251,15 @@
"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=="
"resolved": "4.6.0",
"contentHash": "t+SoieZsRuEyiw/J+qXUbolyO219tKQQI0+2/YI+Qv7YdGValA6WiuokrNKqjrTNsy5ABWU11bdKOzUdheteXg=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
"resolved": "6.1.0",
"contentHash": "5o/HZxx6RVqYlhKSq8/zronDkALJZUT2Vz0hx43f0gwe8mwlM0y2nYlqdBwLMzr262Bwvpikeb/yEwkAa5PADg=="
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
@@ -199,79 +270,6 @@
}
}
},
".NETStandard,Version=v2.1": {
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "8.0.0",
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"System.Text.Encoding.CodePages": {
"type": "Direct",
"requested": "[8.0.0, )",
"resolved": "8.0.0",
"contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==",
"dependencies": {
"System.Memory": "4.5.5",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.0, )",
"resolved": "0.8.0",
"contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw=="
},
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
},
"System.Memory": {
"type": "CentralTransitive",
"requested": "[4.5.5, )",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.4.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.3"
}
}
},
"net6.0": {
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
@@ -283,11 +281,17 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"System.Buffers": {
"type": "Direct",
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
},
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.0, )",
"resolved": "0.8.0",
"contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA=="
"requested": "[0.8.4, )",
"resolved": "0.8.4",
"contentHash": "eieSXq3kakCUXbgdxkKaRqWS6hF0KBJcqok9LlDCs60GOyrynLvPOcQ0pRw7shdPF7lh/VepJ9cP9n9HHc759g=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
@@ -303,9 +307,9 @@
"net8.0": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.4, )",
"resolved": "8.0.4",
"contentHash": "PZb5nfQ+U19nhnmnR9T1jw+LTmozhuG2eeuzuW5A7DqxD/UXW2ucjmNJqnqOuh8rdPzM3MQXoF8AfFCedJdCUw=="
"requested": "[8.0.12, )",
"resolved": "8.0.12",
"contentHash": "FV4HnQ3JI15PHnJ5PGTbz+rYvrih42oLi/7UMIshNwCwUZhTq13UzrggtXk4ygrcMcN+4jsS6hhshx2p/Zd0ig=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
@@ -317,11 +321,17 @@
"Microsoft.SourceLink.Common": "8.0.0"
}
},
"System.Buffers": {
"type": "Direct",
"requested": "[4.6.0, )",
"resolved": "4.6.0",
"contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA=="
},
"ZstdSharp.Port": {
"type": "Direct",
"requested": "[0.8.0, )",
"resolved": "0.8.0",
"contentHash": "Z62eNBIu8E8YtbqlMy57tK3dV1+m2b9NhPeaYovB5exmLKvrGCqOhJTzrEUH5VyUWU6vwX3c1XHJGhW5HVs8dA=="
"requested": "[0.8.4, )",
"resolved": "0.8.4",
"contentHash": "eieSXq3kakCUXbgdxkKaRqWS6hF0KBJcqok9LlDCs60GOyrynLvPOcQ0pRw7shdPF7lh/VepJ9cP9n9HHc759g=="
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",

View File

@@ -73,27 +73,45 @@ public class ArchiveTests : ReaderTests
}
}
protected void ArchiveStreamRead(string testArchive, ReaderOptions? readerOptions = null)
protected void ArchiveStreamRead(string testArchive, ReaderOptions? readerOptions = null) =>
ArchiveStreamRead(ArchiveFactory.AutoFactory, testArchive, readerOptions);
protected void ArchiveStreamRead(
IArchiveFactory archiveFactory,
string testArchive,
ReaderOptions? readerOptions = null
)
{
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
ArchiveStreamRead(readerOptions, testArchive);
ArchiveStreamRead(archiveFactory, readerOptions, testArchive);
}
protected void ArchiveStreamRead(
ReaderOptions? readerOptions = null,
params string[] testArchives
) => ArchiveStreamRead(ArchiveFactory.AutoFactory, readerOptions, testArchives);
protected void ArchiveStreamRead(
IArchiveFactory archiveFactory,
ReaderOptions? readerOptions = null,
params string[] testArchives
) =>
ArchiveStreamRead(
archiveFactory,
readerOptions,
testArchives.Select(x => Path.Combine(TEST_ARCHIVES_PATH, x))
);
protected void ArchiveStreamRead(ReaderOptions? readerOptions, IEnumerable<string> testArchives)
protected void ArchiveStreamRead(
IArchiveFactory archiveFactory,
ReaderOptions? readerOptions,
IEnumerable<string> testArchives
)
{
foreach (var path in testArchives)
{
using (var stream = NonDisposingStream.Create(File.OpenRead(path), true))
using (var archive = ArchiveFactory.Open(stream, readerOptions))
using (var archive = archiveFactory.Open(stream, readerOptions))
{
try
{
@@ -218,10 +236,14 @@ public class ArchiveTests : ReaderTests
}
}
protected void ArchiveFileRead(string testArchive, ReaderOptions? readerOptions = null)
protected void ArchiveFileRead(
IArchiveFactory archiveFactory,
string testArchive,
ReaderOptions? readerOptions = null
)
{
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
using (var archive = ArchiveFactory.Open(testArchive, readerOptions))
using (var archive = archiveFactory.Open(new FileInfo(testArchive), readerOptions))
{
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
@@ -234,6 +256,9 @@ public class ArchiveTests : ReaderTests
VerifyFiles();
}
protected void ArchiveFileRead(string testArchive, ReaderOptions? readerOptions = null) =>
ArchiveFileRead(ArchiveFactory.AutoFactory, testArchive, readerOptions);
protected void ArchiveFileSkip(
string testArchive,
string fileOrder,
@@ -270,7 +295,7 @@ public class ArchiveTests : ReaderTests
ExtractFullPath = true,
Overwrite = true,
PreserveAttributes = true,
PreserveFileTime = true
PreserveFileTime = true,
}
);
}

View File

@@ -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));
}
}

Some files were not shown because too many files have changed in this diff Show More