Migrate some MSZIP pieces to Models

This commit is contained in:
Matt Nadareski
2022-12-15 23:51:12 -08:00
parent e0e16292eb
commit fedf76e534
9 changed files with 743 additions and 736 deletions

View File

@@ -30,6 +30,29 @@ namespace BurnOutSharp.Models.MicrosoftCabinet
TYPE_LZX = 0x0003,
}
public enum DeflateCompressionType : byte
{
/// <summary>
/// no compression
/// </summary>
NoCompression = 0b00,
/// <summary>
/// Compressed with fixed Huffman codes
/// </summary>
FixedHuffman = 0b01,
/// <summary>
/// Compressed with dynamic Huffman codes
/// </summary>
DynamicHuffman = 0b10,
/// <summary>
/// Reserved (error)
/// </summary>
Reserved = 0b11,
}
[Flags]
public enum FileAttributes : ushort
{

View File

@@ -0,0 +1,8 @@
namespace BurnOutSharp.Models.MicrosoftCabinet
{
/// <summary>
/// Empty interface defining block types
/// </summary>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public interface IMSZIPBlockData { }
}

View File

@@ -0,0 +1,31 @@
namespace BurnOutSharp.Models.MicrosoftCabinet
{
/// <summary>
/// Each MSZIP block MUST consist of a 2-byte MSZIP signature and one or more RFC 1951 blocks. The
/// 2-byte MSZIP signature MUST consist of the bytes 0x43 and 0x4B. The MSZIP signature MUST be
/// the first 2 bytes in the MSZIP block.The MSZIP signature is shown in the following packet diagram.
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-MCI/%5bMS-MCI%5d.pdf"/>
public class MSZIPBlock
{
/// <summary>
/// 'CK'
/// </summary>
public ushort Signature;
/// <summary>
/// Each MSZIP block is the result of a single deflate compression operation, as defined in [RFC1951].
/// The compressor that performs the compression operation MUST generate one or more RFC 1951
/// blocks, as defined in [RFC1951]. The number, deflation mode, and type of RFC 1951 blocks in each
/// MSZIP block is determined by the compressor, as defined in [RFC1951]. The last RFC 1951 block in
/// each MSZIP block MUST be marked as the "end" of the stream(1), as defined by [RFC1951]
/// section 3.2.3. Decoding trees MUST be discarded after each RFC 1951 block, but the history buffer
/// MUST be maintained.Each MSZIP block MUST represent no more than 32 KB of uncompressed data.
///
/// The maximum compressed size of each MSZIP block is 32 KB + 12 bytes. This enables the MSZIP
/// block to contain 32 KB of data split between two noncompressed RFC 1951 blocks, each of which
/// has a value of BTYPE = 00.
/// </summary>
public byte[] Data;
}
}

View File

@@ -0,0 +1,19 @@
namespace BurnOutSharp.Models.MicrosoftCabinet
{
/// <summary>
/// Base class for compressed blocks
/// </summary>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public abstract class MSZIPCompressedBlock : IMSZIPBlockData
{
/// <summary>
/// Huffman code lengths for the literal / length alphabet
/// </summary>
public abstract int[] LiteralLengths { get; set; }
/// <summary>
/// Huffman distance codes for the literal / length alphabet
/// </summary>
public abstract int[] DistanceCodes { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
namespace BurnOutSharp.Models.MicrosoftCabinet
{
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class MSZIPDeflateBlock
{
/// <summary>
/// Set if and only if this is the last block of the data set.
/// </summary>
/// <remarks>Bit 0</remarks>
public bool BFINAL { get; set; }
/// <summary>
/// Specifies how the data are compressed
/// </summary>
/// <remarks>Bits 1-2</remarks>
public DeflateCompressionType BTYPE { get; set; }
/// <summary>
/// Block data as defined by the compression type
/// </summary>
public IMSZIPBlockData BlockData { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
namespace BurnOutSharp.Models.MicrosoftCabinet
{
/// <summary>
/// Compression with dynamic Huffman codes (BTYPE=10)
/// </summary>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class MSZIPDynamicHuffmanCompressedBlock : MSZIPCompressedBlock
{
/// <inheritdoc/>
public override int[] LiteralLengths { get; set; }
/// <inheritdoc/>
public override int[] DistanceCodes { get; set; }
}
}

View File

@@ -0,0 +1,90 @@
using System;
namespace BurnOutSharp.Models.MicrosoftCabinet
{
/// <summary>
/// Compression with fixed Huffman codes (BTYPE=01)
/// </summary>
/// <see href="https://interoperability.blob.core.windows.net/files/MS-MCI/%5bMS-MCI%5d.pdf"/>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class MSZIPFixedHuffmanCompressedBlock : MSZIPCompressedBlock
{
#region Properties
/// <inheritdoc/>
public override int[] LiteralLengths
{
get
{
// If we have cached lengths, use those
if (_literalLengths != null)
return _literalLengths;
// Otherwise, build it from scratch
_literalLengths = new int[288];
// Literal Value 0 - 143, 8 bits
for (int i = 0; i < 144; i++)
_literalLengths[i] = 8;
// Literal Value 144 - 255, 9 bits
for (int i = 144; i < 256; i++)
_literalLengths[i] = 9;
// Literal Value 256 - 279, 7 bits
for (int i = 256; i < 280; i++)
_literalLengths[i] = 7;
// Literal Value 280 - 287, 8 bits
for (int i = 280; i < 288; i++)
_literalLengths[i] = 8;
return _literalLengths;
}
set
{
throw new FieldAccessException();
}
}
/// <inheritdoc/>
public override int[] DistanceCodes
{
get
{
// If we have cached distances, use those
if (_distanceCodes != null)
return _distanceCodes;
// Otherwise, build it from scratch
_distanceCodes = new int[32];
// Fixed length, 5 bits
for (int i = 0; i < 32; i++)
_distanceCodes[i] = 5;
return _distanceCodes;
}
set
{
throw new FieldAccessException();
}
}
#endregion
#region Instance Variables
/// <summary>
/// Huffman code lengths for the literal / length alphabet
/// </summary>
private int[] _literalLengths = null;
/// <summary>
/// Huffman distance codes for the literal / length alphabet
/// </summary>
private int[] _distanceCodes = null;
#endregion
}
}

View File

@@ -0,0 +1,26 @@
namespace BurnOutSharp.Models.MicrosoftCabinet
{
/// <summary>
/// Non-compressed blocks (BTYPE=00)
/// </summary>
/// <see href="https://www.rfc-editor.org/rfc/rfc1951"/>
public class MSZIPNonCompressedBlock : IMSZIPBlockData
{
/// <summary>
/// The number of data bytes in the block
/// </summary>
/// <remarks>Bytes 0-1</remarks>
public ushort LEN;
/// <summary>
/// The one's complement of LEN
/// </summary>
/// <remarks>Bytes 2-3</remarks>
public ushort NLEN;
/// <summary>
/// <see cref="LEN"/> bytes of literal data
/// </summary>
public byte[] Data;
}
}

File diff suppressed because it is too large Load Diff