diff --git a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs index d4197b3f..60ece4ee 100644 --- a/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs +++ b/src/SharpCompress/Archives/Rar/RarArchiveEntry.cs @@ -64,10 +64,10 @@ namespace SharpCompress.Archives.Rar if (IsRarV3) { - return new RarStream(archive.UnpackV1.Value, archive.IsSolid, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast(), archive)); + return new RarStream(archive.UnpackV1.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast(), archive)); } - return new RarStream(archive.UnpackV2017.Value, archive.IsSolid, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast(), archive)); + return new RarStream(archive.UnpackV2017.Value, FileHeader, new MultiVolumeReadOnlyStream(Parts.Cast(), archive)); } public bool IsComplete diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index 55a13322..39b238ab 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -55,20 +55,24 @@ namespace SharpCompress.Common.Rar.Headers FileCrc = reader.ReadUInt32(); } - var us = reader.ReadRarVIntUInt16(); + var compressionInfo = reader.ReadRarVIntUInt16(); // Lower 6 bits (0x003f mask) contain the version of compression algorithm, resulting in possible 0 - 63 values. Current version is 0. // "+ 50" to not mix with old RAR format algorithms. For example, // we may need to use the compression algorithm 15 in the future, // but it was already used in RAR 1.5 and Unpack needs to distinguish // them. - CompressionAlgorithm = (byte)((us & 0x3f) + 50); + CompressionAlgorithm = (byte)((compressionInfo & 0x3f) + 50); + + // 7th bit (0x0040) defines the solid flag. If it is set, RAR continues to use the compression dictionary left after processing preceding files. + // It can be set only for file headers and is never set for service headers. + IsSolid = (compressionInfo & 0x40) == 0x40; // Bits 8 - 10 (0x0380 mask) define the compression method. Currently only values 0 - 5 are used. 0 means no compression. - CompressionMethod = (byte)((us >> 7) & 0x7); + CompressionMethod = (byte)((compressionInfo >> 7) & 0x7); // Bits 11 - 14 (0x3c00) define the minimum size of dictionary size required to extract data. Value 0 means 128 KB, 1 - 256 KB, ..., 14 - 2048 MB, 15 - 4096 MB. - WindowSize = IsDirectory ? 0 : ((size_t)0x20000) << ((us>>10) & 0xf); + WindowSize = IsDirectory ? 0 : ((size_t)0x20000) << ((compressionInfo>>10) & 0xf); HostOs = reader.ReadRarVIntByte(); @@ -205,6 +209,7 @@ namespace SharpCompress.Common.Rar.Headers private void ReadFromReaderV4(MarkingBinaryReader reader) { Flags = HeaderFlags; + IsSolid = HasFlag(FileFlagsV4.Solid); WindowSize = IsDirectory ? 0U : ((size_t)0x10000) << ((Flags & FileFlagsV4.WindowMask) >> 5); uint lowUncompressedSize = reader.ReadUInt32(); @@ -408,6 +413,8 @@ namespace SharpCompress.Common.Rar.Headers //case 29: // rar 3.x compression //case 50: // RAR 5.0 compression algorithm. internal byte CompressionAlgorithm { get; private set; } + + public bool IsSolid { get; private set; } // unused for UnpackV1 implementation (limitation) internal size_t WindowSize { get; private set; } diff --git a/src/SharpCompress/Compressors/Rar/IRarUnpack.cs b/src/SharpCompress/Compressors/Rar/IRarUnpack.cs index 887c590e..ecd70a47 100644 --- a/src/SharpCompress/Compressors/Rar/IRarUnpack.cs +++ b/src/SharpCompress/Compressors/Rar/IRarUnpack.cs @@ -5,8 +5,8 @@ namespace SharpCompress.Compressors.Rar { interface IRarUnpack { - void DoUnpack(bool isSolid, FileHeader fileHeader, Stream readStream, Stream writeStream); - void DoUnpack(bool isSolid); + void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream); + void DoUnpack(); // eg u/i pause/resume button bool Suspended { get; set; } diff --git a/src/SharpCompress/Compressors/Rar/RarCrcStream.cs b/src/SharpCompress/Compressors/Rar/RarCrcStream.cs index 2bf98579..df7d85ff 100644 --- a/src/SharpCompress/Compressors/Rar/RarCrcStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarCrcStream.cs @@ -9,8 +9,8 @@ namespace SharpCompress.Compressors.Rar private readonly MultiVolumeReadOnlyStream readStream; private uint currentCrc; - public RarCrcStream(IRarUnpack unpack, bool isSolid, FileHeader fileHeader, MultiVolumeReadOnlyStream readStream) - : base(unpack, isSolid, fileHeader, readStream) + public RarCrcStream(IRarUnpack unpack, FileHeader fileHeader, MultiVolumeReadOnlyStream readStream) + : base(unpack, fileHeader, readStream) { this.readStream = readStream; ResetCrc(); diff --git a/src/SharpCompress/Compressors/Rar/RarStream.cs b/src/SharpCompress/Compressors/Rar/RarStream.cs index 6da56697..08240859 100644 --- a/src/SharpCompress/Compressors/Rar/RarStream.cs +++ b/src/SharpCompress/Compressors/Rar/RarStream.cs @@ -9,7 +9,6 @@ namespace SharpCompress.Compressors.Rar private readonly IRarUnpack unpack; private readonly FileHeader fileHeader; private readonly Stream readStream; - private readonly bool isSolid; private bool fetch; @@ -23,14 +22,13 @@ namespace SharpCompress.Compressors.Rar private int outTotal; private bool isDisposed; - public RarStream(IRarUnpack unpack, bool isSolid, FileHeader fileHeader, Stream readStream) + public RarStream(IRarUnpack unpack, FileHeader fileHeader, Stream readStream) { - this.isSolid = isSolid; this.unpack = unpack; this.fileHeader = fileHeader; this.readStream = readStream; this.fetch = true; - unpack.DoUnpack(isSolid, fileHeader, readStream, this); + unpack.DoUnpack(fileHeader, readStream, this); this.fetch = false; } @@ -76,7 +74,7 @@ namespace SharpCompress.Compressors.Rar outOffset = offset; outCount = count; fetch = true; - unpack.DoUnpack(isSolid); + unpack.DoUnpack(); fetch = false; } return outTotal; diff --git a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs index dd3b52dc..90c09c6d 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs @@ -103,21 +103,21 @@ namespace SharpCompress.Compressors.Rar.UnpackV1 UnpInitData(false); } - public void DoUnpack(bool isSolid, FileHeader fileHeader, Stream readStream, Stream writeStream) + public void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream) { this.destUnpSize = fileHeader.UncompressedSize; this.fileHeader = fileHeader; this.readStream = readStream; this.writeStream = writeStream; - if (!isSolid) + if (!fileHeader.IsSolid) { Init(null); } this.suspended = false; - DoUnpack(isSolid); + DoUnpack(); } - public void DoUnpack(bool isSolid) + public void DoUnpack() { if (fileHeader.CompressionMethod == 0) { @@ -127,21 +127,21 @@ namespace SharpCompress.Compressors.Rar.UnpackV1 switch (fileHeader.CompressionAlgorithm) { case 15: // rar 1.5 compression - unpack15(isSolid); + unpack15(fileHeader.IsSolid); break; case 20: // rar 2.x compression case 26: // files larger than 2GB - unpack20(isSolid); + unpack20(fileHeader.IsSolid); break; case 29: // rar 3.x compression case 36: // alternative hash - Unpack29(isSolid); + Unpack29(fileHeader.IsSolid); break; case 50: // rar 5.x compression - Unpack5(isSolid); + Unpack5(fileHeader.IsSolid); break; default: diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs index 2d52da5b..e8bc8c36 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs @@ -37,7 +37,7 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017 this.writeStream.Write(buf, checked((int)offset), checked((int)count)); } - public void DoUnpack(bool isSolid, FileHeader fileHeader, Stream readStream, Stream writeStream) + public void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream) { // as of 12/2017 .NET limits array indexing to using a signed integer // MaxWinSize causes unpack to use a fragmented window when the file @@ -51,19 +51,19 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017 this.readStream = readStream; this.writeStream = writeStream; if (!fileHeader.IsStored) { - Init(fileHeader.WindowSize, isSolid); + Init(fileHeader.WindowSize, fileHeader.IsSolid); } Suspended = false; - DoUnpack(isSolid); + DoUnpack(); } - public void DoUnpack(bool isSolid) + public void DoUnpack() { if (this.fileHeader.IsStored) { UnstoreFile(); } else { - DoUnpack(this.fileHeader.CompressionAlgorithm, isSolid); + DoUnpack(this.fileHeader.CompressionAlgorithm, fileHeader.IsSolid); } } diff --git a/src/SharpCompress/Readers/Rar/RarReader.cs b/src/SharpCompress/Readers/Rar/RarReader.cs index 81f99d9b..05fe0daa 100644 --- a/src/SharpCompress/Readers/Rar/RarReader.cs +++ b/src/SharpCompress/Readers/Rar/RarReader.cs @@ -70,9 +70,9 @@ namespace SharpCompress.Readers.Rar var stream = new MultiVolumeReadOnlyStream(CreateFilePartEnumerableForCurrentEntry().Cast(), this); if (Entry.IsRarV3) { - return CreateEntryStream(new RarCrcStream(UnpackV1.Value, volume.IsSolidArchive, Entry.FileHeader, stream)); + return CreateEntryStream(new RarCrcStream(UnpackV1.Value, Entry.FileHeader, stream)); } - return CreateEntryStream(new RarCrcStream(UnpackV2017.Value, volume.IsSolidArchive, Entry.FileHeader, stream)); + return CreateEntryStream(new RarCrcStream(UnpackV2017.Value, Entry.FileHeader, stream)); } } }