diff --git a/src/SharpCompress/Common/Rar/Headers/AVHeader.cs b/src/SharpCompress/Common/Rar/Headers/AVHeader.cs index cd51d80b..fafab9df 100644 --- a/src/SharpCompress/Common/Rar/Headers/AVHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/AVHeader.cs @@ -4,13 +4,14 @@ namespace SharpCompress.Common.Rar.Headers; internal class AvHeader : RarHeader { - public AvHeader(RarHeader header, RarCrcBinaryReader reader) - : base(header, reader, HeaderType.Av) + public static AvHeader Create(RarHeader header, RarCrcBinaryReader reader) { - if (IsRar5) + var c = CreateChild(header, reader, HeaderType.Av); + if (c.IsRar5) { throw new InvalidFormatException("unexpected rar5 record"); } + return c; } protected override void ReadFinish(MarkingBinaryReader reader) diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs index f819b478..bbae6fe5 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.cs @@ -6,8 +6,8 @@ namespace SharpCompress.Common.Rar.Headers; internal class ArchiveCryptHeader : RarHeader { - public ArchiveCryptHeader(RarHeader header, RarCrcBinaryReader reader) - : base(header, reader, HeaderType.Crypt) { } + public static ArchiveCryptHeader Create(RarHeader header, RarCrcBinaryReader reader) => + CreateChild(header, reader, HeaderType.Crypt); public Rar5CryptoInfo CryptInfo = new(); diff --git a/src/SharpCompress/Common/Rar/Headers/ArchiveHeader.cs b/src/SharpCompress/Common/Rar/Headers/ArchiveHeader.cs index e8f344ad..602f7218 100644 --- a/src/SharpCompress/Common/Rar/Headers/ArchiveHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ArchiveHeader.cs @@ -4,9 +4,8 @@ namespace SharpCompress.Common.Rar.Headers; internal sealed class ArchiveHeader : RarHeader { - public ArchiveHeader(RarHeader header, RarCrcBinaryReader reader) - : base(header, reader, HeaderType.Archive) { } - + public static ArchiveHeader Create(RarHeader header, RarCrcBinaryReader reader) => + CreateChild(header, reader, HeaderType.Archive); protected override void ReadFinish(MarkingBinaryReader reader) { if (IsRar5) diff --git a/src/SharpCompress/Common/Rar/Headers/CommentHeader.cs b/src/SharpCompress/Common/Rar/Headers/CommentHeader.cs index 54abf9cc..14f0a799 100644 --- a/src/SharpCompress/Common/Rar/Headers/CommentHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/CommentHeader.cs @@ -4,13 +4,14 @@ namespace SharpCompress.Common.Rar.Headers; internal class CommentHeader : RarHeader { - protected CommentHeader(RarHeader header, RarCrcBinaryReader reader) - : base(header, reader, HeaderType.Comment) + public static CommentHeader Create(RarHeader header, RarCrcBinaryReader reader) { - if (IsRar5) + var c = CreateChild(header, reader, HeaderType.Comment); + if (c.IsRar5) { throw new InvalidFormatException("unexpected rar5 record"); } + return c; } protected override void ReadFinish(MarkingBinaryReader reader) diff --git a/src/SharpCompress/Common/Rar/Headers/EndArchiveHeader.cs b/src/SharpCompress/Common/Rar/Headers/EndArchiveHeader.cs index f5bc4523..a9b29cff 100644 --- a/src/SharpCompress/Common/Rar/Headers/EndArchiveHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/EndArchiveHeader.cs @@ -4,8 +4,8 @@ namespace SharpCompress.Common.Rar.Headers; internal class EndArchiveHeader : RarHeader { - public EndArchiveHeader(RarHeader header, RarCrcBinaryReader reader) - : base(header, reader, HeaderType.EndArchive) { } + public static EndArchiveHeader Create(RarHeader header, RarCrcBinaryReader reader) => + CreateChild(header, reader, HeaderType.EndArchive); protected override void ReadFinish(MarkingBinaryReader reader) { diff --git a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs index 0aa9fc0d..218055eb 100644 --- a/src/SharpCompress/Common/Rar/Headers/FileHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/FileHeader.cs @@ -17,8 +17,8 @@ internal class FileHeader : RarHeader { private byte[]? _hash; - public FileHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) - : base(header, reader, headerType) { } + public static FileHeader Create(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) => + CreateChild(header, reader, headerType); protected override void ReadFinish(MarkingBinaryReader reader) { diff --git a/src/SharpCompress/Common/Rar/Headers/ProtectHeader.cs b/src/SharpCompress/Common/Rar/Headers/ProtectHeader.cs index cf8db3c0..292c4a17 100644 --- a/src/SharpCompress/Common/Rar/Headers/ProtectHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/ProtectHeader.cs @@ -5,13 +5,14 @@ namespace SharpCompress.Common.Rar.Headers; // ProtectHeader is part of the Recovery Record feature internal sealed class ProtectHeader : RarHeader { - public ProtectHeader(RarHeader header, RarCrcBinaryReader reader) - : base(header, reader, HeaderType.Protect) + public static ProtectHeader Create(RarHeader header, RarCrcBinaryReader reader) { - if (IsRar5) + var c = CreateChild(header, reader, HeaderType.Protect); + if (c.IsRar5) { throw new InvalidFormatException("unexpected rar5 record"); } + return c; } protected override void ReadFinish(MarkingBinaryReader reader) diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs index 3ca76ab9..4a6ef88b 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeader.cs @@ -7,8 +7,13 @@ namespace SharpCompress.Common.Rar.Headers; // https://www.rarlab.com/technote.htm internal class RarHeader : IRarHeader { - private readonly HeaderType _headerType; - private readonly bool _isRar5; + private HeaderType _headerType; + private bool _isRar5; + + protected RarHeader() + { + ArchiveEncoding = new ArchiveEncoding(); + } internal static RarHeader? TryReadBase( RarCrcBinaryReader reader, @@ -18,7 +23,9 @@ internal class RarHeader : IRarHeader { try { - return new RarHeader(reader, isRar5, archiveEncoding); + var header = new RarHeader(); + header.Initialize(reader, isRar5, archiveEncoding); + return header; } catch (InvalidFormatException) { @@ -26,7 +33,7 @@ internal class RarHeader : IRarHeader } } - private RarHeader(RarCrcBinaryReader reader, bool isRar5, IArchiveEncoding archiveEncoding) + private void Initialize(RarCrcBinaryReader reader, bool isRar5, IArchiveEncoding archiveEncoding) { _headerType = HeaderType.Null; _isRar5 = isRar5; @@ -64,26 +71,31 @@ internal class RarHeader : IRarHeader } } - protected RarHeader(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) + internal static T CreateChild(RarHeader header, RarCrcBinaryReader reader, HeaderType headerType) + where T : RarHeader, new() { - _headerType = headerType; - _isRar5 = header.IsRar5; - HeaderCrc = header.HeaderCrc; - HeaderCode = header.HeaderCode; - HeaderFlags = header.HeaderFlags; - HeaderSize = header.HeaderSize; - ExtraSize = header.ExtraSize; - AdditionalDataSize = header.AdditionalDataSize; - ArchiveEncoding = header.ArchiveEncoding; - ReadFinish(reader); + var child = new T() + { + ArchiveEncoding = header.ArchiveEncoding + }; + child. _headerType = headerType; + child. _isRar5 = header.IsRar5; + child. HeaderCrc = header.HeaderCrc; + child. HeaderCode = header.HeaderCode; + child. HeaderFlags = header.HeaderFlags; + child.HeaderSize = header.HeaderSize; + child.ExtraSize = header.ExtraSize; + child. AdditionalDataSize = header.AdditionalDataSize; + child.ReadFinish(reader); - var n = RemainingHeaderBytes(reader); + var n = child.RemainingHeaderBytes(reader); if (n > 0) { reader.ReadBytes(n); } - VerifyHeaderCrc(reader.GetCrc32()); + child. VerifyHeaderCrc(reader.GetCrc32()); + return child; } protected int RemainingHeaderBytes(MarkingBinaryReader reader) => @@ -103,27 +115,27 @@ internal class RarHeader : IRarHeader public HeaderType HeaderType => _headerType; - protected bool IsRar5 => _isRar5; + internal bool IsRar5 => _isRar5; - protected uint HeaderCrc { get; } + protected uint HeaderCrc { get;private set; } - internal byte HeaderCode { get; } + internal byte HeaderCode { get;private set; } - protected ushort HeaderFlags { get; } + protected ushort HeaderFlags { get;private set; } protected bool HasHeaderFlag(ushort flag) => (HeaderFlags & flag) == flag; - protected int HeaderSize { get; } + protected int HeaderSize { get;private set; } - internal IArchiveEncoding ArchiveEncoding { get; } + internal IArchiveEncoding ArchiveEncoding { get; private set; } /// /// Extra header size. /// - protected uint ExtraSize { get; } + protected uint ExtraSize { get;private set; } /// /// Size of additional data (eg file contents) /// - protected long AdditionalDataSize { get; } + protected long AdditionalDataSize { get;private set; } } diff --git a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs index 902e595f..ecbf2f8f 100644 --- a/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs +++ b/src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.cs @@ -80,7 +80,7 @@ public class RarHeaderFactory case HeaderCodeV.RAR5_ARCHIVE_HEADER: case HeaderCodeV.RAR4_ARCHIVE_HEADER: { - var ah = new ArchiveHeader(header, reader); + var ah = ArchiveHeader.Create(header, reader); if (ah.IsEncrypted == true) { //!!! rar5 we don't know yet @@ -91,7 +91,7 @@ public class RarHeaderFactory case HeaderCodeV.RAR4_PROTECT_HEADER: { - var ph = new ProtectHeader(header, reader); + var ph = ProtectHeader.Create(header, reader); // skip the recovery record data, we do not use it. switch (StreamingMode) { @@ -116,7 +116,7 @@ public class RarHeaderFactory case HeaderCodeV.RAR5_SERVICE_HEADER: { - var fh = new FileHeader(header, reader, HeaderType.Service); + var fh = FileHeader.Create(header, reader, HeaderType.Service); if (fh.FileName == "CMT") { fh.PackedStream = new ReadOnlySubStream(reader.BaseStream, fh.CompressedSize); @@ -130,7 +130,7 @@ public class RarHeaderFactory case HeaderCodeV.RAR4_NEW_SUB_HEADER: { - var fh = new FileHeader(header, reader, HeaderType.NewSub); + var fh = FileHeader.Create(header, reader, HeaderType.NewSub); SkipData(fh, reader); return fh; } @@ -138,7 +138,7 @@ public class RarHeaderFactory case HeaderCodeV.RAR5_FILE_HEADER: case HeaderCodeV.RAR4_FILE_HEADER: { - var fh = new FileHeader(header, reader, HeaderType.File); + var fh = FileHeader.Create(header, reader, HeaderType.File); switch (StreamingMode) { case StreamingMode.Seekable: @@ -181,11 +181,11 @@ public class RarHeaderFactory case HeaderCodeV.RAR5_END_ARCHIVE_HEADER: case HeaderCodeV.RAR4_END_ARCHIVE_HEADER: { - return new EndArchiveHeader(header, reader); + return EndArchiveHeader.Create(header, reader); } case HeaderCodeV.RAR5_ARCHIVE_ENCRYPTION_HEADER: { - var cryptoHeader = new ArchiveCryptHeader(header, reader); + var cryptoHeader = ArchiveCryptHeader.Create(header, reader); IsEncrypted = true; _cryptInfo = cryptoHeader.CryptInfo; diff --git a/src/SharpCompress/Common/Rar/Headers/SignHeader.cs b/src/SharpCompress/Common/Rar/Headers/SignHeader.cs index 837ff3dc..18c2b91f 100644 --- a/src/SharpCompress/Common/Rar/Headers/SignHeader.cs +++ b/src/SharpCompress/Common/Rar/Headers/SignHeader.cs @@ -4,13 +4,14 @@ namespace SharpCompress.Common.Rar.Headers; internal class SignHeader : RarHeader { - protected SignHeader(RarHeader header, RarCrcBinaryReader reader) - : base(header, reader, HeaderType.Sign) + public static SignHeader Create(RarHeader header, RarCrcBinaryReader reader) { - if (IsRar5) - { - throw new InvalidFormatException("unexpected rar5 record"); - } + var c = CreateChild(header, reader, HeaderType.Sign); + if (c.IsRar5) + { + throw new InvalidFormatException("unexpected rar5 record"); + } + return c; } protected override void ReadFinish(MarkingBinaryReader reader)