Skip to content

Commit 78373dd

Browse files
committed
Split out MS-ZIP handling for cleaner code
1 parent fa74963 commit 78373dd

File tree

1 file changed

+48
-33
lines changed

1 file changed

+48
-33
lines changed

BinaryObjectScanner/FileType/MicrosoftCAB.cs

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -265,50 +265,65 @@ private static void ExtractFile(string outDir, Stream blockStream, CFFILE file,
265265
if (db?.CompressedData == null)
266266
continue;
267267

268-
switch (compressionType)
268+
// Get the uncompressed data block
269+
byte[] data = compressionType switch
269270
{
270-
// Uncompressed data
271-
case CompressionType.TYPE_NONE:
272-
ms.Write(db.CompressedData, 0, db.CompressedData.Length);
273-
ms.Flush();
274-
break;
275-
276-
// MS-ZIP
277-
case CompressionType.TYPE_MSZIP:
278-
long preMsZipPosition = ms.Position;
279-
mszip.CopyTo(db.CompressedData, ms);
280-
long msZipDecompressedSize = ms.Position - preMsZipPosition;
281-
282-
// Pad to the correct size but throw a warning about this
283-
if (msZipDecompressedSize < db.UncompressedSize)
284-
{
285-
Console.Error.WriteLine($"Data block {i} in folder {folderIndex} had mismatching sizes. Expected: {db.UncompressedSize}, Got: {msZipDecompressedSize}");
286-
byte[] padding = new byte[db.UncompressedSize - msZipDecompressedSize];
287-
ms.Write(padding, 0, padding.Length);
288-
}
289-
290-
break;
291-
292-
// Quantum
293-
case CompressionType.TYPE_QUANTUM:
294-
// TODO: Unsupported
295-
break;
296-
297-
// LZX
298-
case CompressionType.TYPE_LZX:
299-
// TODO: Unsupported
300-
break;
301-
}
271+
CompressionType.TYPE_NONE => db.CompressedData,
272+
CompressionType.TYPE_MSZIP => DecompressMSZIPBlock(folderIndex, mszip, i, db),
273+
274+
// TODO: Unsupported
275+
CompressionType.TYPE_QUANTUM => [],
276+
CompressionType.TYPE_LZX => [],
277+
278+
// Should be impossible
279+
_ => [],
280+
};
281+
282+
// Write the uncompressed data block
283+
ms.Write(data, 0, data.Length);
284+
ms.Flush();
302285
}
303286

304287
return ms;
305288
}
306289

290+
/// <summary>
291+
/// Decompress an MS-ZIP block using an existing decompressor
292+
/// </summary>
293+
/// <param name="folderIndex">Index of the folder in the cabinet</param>
294+
/// <param name="mszip">MS-ZIP decompressor with persistent state</param>
295+
/// <param name="blockIndex">Index of the block within the folder</param>
296+
/// <param name="block">Block data to be used for decompression</param>
297+
/// <returns>Byte array representing the decompressed data, empty on error</returns>
298+
/// TODO: Remove once Serialization is updated
299+
private static byte[] DecompressMSZIPBlock(int folderIndex, SabreTools.Compression.MSZIP.Decompressor mszip, int blockIndex, CFDATA block)
300+
{
301+
// Ignore invalid blocks
302+
if (block.CompressedData == null)
303+
return [];
304+
305+
// Decompress to a temporary stream
306+
using var stream = new MemoryStream();
307+
mszip.CopyTo(block.CompressedData, stream);
308+
309+
// Pad to the correct size but throw a warning about this
310+
if (stream.Length < block.UncompressedSize)
311+
{
312+
Console.Error.WriteLine($"Data block {blockIndex} in folder {folderIndex} had mismatching sizes. Expected: {block.UncompressedSize}, Got: {stream.Length}");
313+
byte[] padding = new byte[block.UncompressedSize - stream.Length];
314+
stream.Write(padding, 0, padding.Length);
315+
}
316+
317+
// Return the byte array data
318+
return stream.ToArray();
319+
}
320+
307321
/// <summary>
308322
/// Get the unmasked compression type for a folder
309323
/// </summary>
310324
/// <param name="folder">Folder to get the compression type for</param>
311325
/// <returns>Compression type on success, <see cref="ushort.MaxValue"/> on error</returns>
326+
/// TODO: Remove once Serialization is updated
312327
private static CompressionType GetCompressionType(CFFOLDER folder)
313328
{
314329
if ((folder!.CompressionType & CompressionType.MASK_TYPE) == CompressionType.TYPE_NONE)

0 commit comments

Comments
 (0)