Fix MS-ZIP, working

This commit is contained in:
Matt Nadareski
2024-12-11 07:31:03 -05:00
parent 0d942158a9
commit b6d9dcd77a
6 changed files with 57 additions and 71 deletions

View File

@@ -1649,13 +1649,21 @@ namespace SabreTools.Compression.Deflate
}
internal int SetDictionary(byte[] dictionary)
internal int SetDictionary(byte[] dictionary, bool check = true)
{
int length = dictionary.Length;
int index = 0;
if (dictionary == null || status != INIT_STATE)
throw new ZlibException("Stream error.");
if (check)
{
if (dictionary == null || status != INIT_STATE)
throw new ZlibException("Stream error.");
}
else
{
if (dictionary == null)
throw new ZlibException("Stream error.");
}
_codec._Adler32 = Adler.Adler32(_codec._Adler32, dictionary, 0, dictionary.Length);

View File

@@ -620,10 +620,11 @@ namespace SabreTools.Compression.Deflate
/// Set the dictionary to be used for either Inflation or Deflation.
/// </summary>
/// <param name="dictionary">The dictionary bytes to use.</param>
/// <param name="check">Determines if dictionary checks are run</param>
/// <returns>Z_OK if all goes well.</returns>
public int SetDictionary(byte[] dictionary)
public int SetDictionary(byte[] dictionary, bool check = true)
{
return _baseStream.SetDictionary(dictionary);
return _baseStream.SetDictionary(dictionary, check);
}
#endregion

View File

@@ -363,16 +363,20 @@ namespace SabreTools.Compression.Deflate
internal int SetDictionary(byte[] dictionary)
internal int SetDictionary(byte[] dictionary, bool check = true)
{
int index = 0;
int length = dictionary.Length;
if (mode != InflateManagerMode.DICT0)
throw new ZlibException("Stream error.");
if (Adler.Adler32(1, dictionary, 0, dictionary.Length) != _codec._Adler32)
if (check)
{
return ZlibConstants.Z_DATA_ERROR;
if (mode != InflateManagerMode.DICT0)
throw new ZlibException("Stream error.");
if (Adler.Adler32(1, dictionary, 0, dictionary.Length) != _codec._Adler32)
{
return ZlibConstants.Z_DATA_ERROR;
}
}
_codec._Adler32 = Adler.Adler32(0, null, 0, 0);

View File

@@ -624,10 +624,11 @@ namespace SabreTools.Compression.Deflate
/// Set the dictionary to be used for either Inflation or Deflation.
/// </summary>
/// <param name="dictionary">The dictionary bytes to use.</param>
/// <param name="check">Determines if dictionary checks are run</param>
/// <returns>Z_OK if all goes well.</returns>
public int SetDictionary(byte[] dictionary)
public int SetDictionary(byte[] dictionary, bool check = true)
{
return z.SetDictionary(dictionary);
return z.SetDictionary(dictionary, check);
}
}

View File

@@ -642,14 +642,15 @@ namespace SabreTools.Compression.Deflate
/// Set the dictionary to be used for either Inflation or Deflation.
/// </summary>
/// <param name="dictionary">The dictionary bytes to use.</param>
/// <param name="check">Determines if dictionary checks are run</param>
/// <returns>Z_OK if all goes well.</returns>
public int SetDictionary(byte[] dictionary)
public int SetDictionary(byte[] dictionary, bool check = true)
{
if (istate != null)
return istate.SetDictionary(dictionary);
return istate.SetDictionary(dictionary, check);
if (dstate != null)
return dstate.SetDictionary(dictionary);
return dstate.SetDictionary(dictionary, check);
throw new ZlibException("No Inflate or Deflate state!");
}

View File

@@ -1,6 +1,7 @@
using System;
using System.IO;
using SabreTools.IO.Extensions;
using SabreTools.Models.Compression.MSZIP;
namespace SabreTools.Compression.MSZIP
{
@@ -8,89 +9,59 @@ namespace SabreTools.Compression.MSZIP
public class Decompressor
{
/// <summary>
/// Source stream for the decompressor
/// Last uncompressed block data
/// </summary>
private readonly Stream _source;
private byte[]? _history = null;
#region Constructors
/// <summary>
/// Create a MS-ZIP decompressor
/// </summary>
private Decompressor(Stream source)
{
// Validate the inputs
if (source.Length == 0)
throw new ArgumentOutOfRangeException(nameof(source));
if (!source.CanRead)
throw new InvalidOperationException(nameof(source));
_source = source;
}
private Decompressor() { }
/// <summary>
/// Create a MS-ZIP decompressor
/// </summary>
public static Decompressor Create(byte[] source)
=> Create(new MemoryStream(source));
/// <summary>
/// Create a MS-ZIP decompressor
/// </summary>
public static Decompressor Create(Stream source)
{
// Create the decompressor
var decompressor = new Decompressor(source);
// Validate the header
var header = new Models.Compression.MSZIP.BlockHeader();
header.Signature = source.ReadUInt16();
if (header.Signature != 0x4B43)
throw new InvalidDataException(nameof(source));
// Return
return decompressor;
}
public static Decompressor Create() => new();
#endregion
/// <summary>
/// Decompress source data to an output stream
/// </summary>
public bool CopyTo(Stream dest)
public bool CopyTo(byte[] source, Stream dest)
=> CopyTo(new MemoryStream(source), dest);
/// <summary>
/// Decompress source data to an output stream
/// </summary>
public bool CopyTo(Stream source, Stream dest)
{
// Ignore unwritable streams
if (!dest.CanWrite)
return false;
byte[]? history = null;
while (true)
// Validate the header
var header = new BlockHeader();
header.Signature = source.ReadUInt16();
if (header.Signature != 0x4B43)
throw new InvalidDataException(nameof(source));
byte[] buffer = new byte[32 * 1024];
var blockStream = new Deflate.DeflateStream(source, Deflate.CompressionMode.Decompress);
if (_history != null)
blockStream.SetDictionary(_history, check: false);
int read = blockStream.Read(buffer, 0, buffer.Length);
if (read > 0)
{
byte[] buffer = new byte[32 * 1024];
var blockStream = new Deflate.DeflateStream(_source, Deflate.CompressionMode.Decompress);
if (history != null)
blockStream.SetDictionary(history);
int read = blockStream.Read(buffer, 0, buffer.Length);
if (read <= 0)
break;
// Write to output
dest.Write(buffer, 0, read);
// Save the history for rollover
history = new byte[read];
Array.Copy(buffer, history, read);
// Handle end of stream
if (_source.Position >= _source.Length)
break;
// Validate the header
var header = new Models.Compression.MSZIP.BlockHeader();
header.Signature = _source.ReadUInt16();
if (header.Signature != 0x4B43)
break;
_history = new byte[read];
Array.Copy(buffer, _history, read);
}
// Flush and return