Skip to content

Commit 7994356

Browse files
committed
Keep tweaking extraction
1 parent b3321f9 commit 7994356

File tree

1 file changed

+40
-11
lines changed

1 file changed

+40
-11
lines changed

SabreTools.Serialization/Wrappers/MicrosoftCabinet.cs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ public MicrosoftCabinet(Cabinet? model, Stream? data)
118118
/// <param name="outDir">Path to the output directory</param>
119119
/// <param name="includeDebug">True to include debug data, false otherwise</param>
120120
/// <returns>Indicates if all files were able to be extracted</returns>
121-
public static bool ExtractAll(string filename, string outDir, bool includeDebug)
121+
/// <remarks>Will extract all items found in the set with forward-only reading</remarks>
122+
public static bool ExtractSet(string filename, string outDir, bool includeDebug)
122123
{
123124
// Get a wrapper for the set
124125
var current = OpenSet(filename);
@@ -144,13 +145,24 @@ public static bool ExtractAll(string filename, string outDir, bool includeDebug)
144145
return true;
145146
}
146147

148+
/// <summary>
149+
/// Extract a cabinet to an output directory, if possible
150+
/// </summary>
151+
/// <param name="filename">Filename for one cabinet in the set</param>
152+
/// <param name="outDir">Path to the output directory</param>
153+
/// <param name="includeDebug">True to include debug data, false otherwise</param>
154+
/// <returns>Indicates if all files were able to be extracted</returns>
155+
/// <remarks>Will read spanned folders but won't attempt to extract unrelated folders</remarks>
156+
public bool ExtractAll(string filename, string outDir, bool includeDebug)
157+
=> ExtractCabinet(filename, outDir, forwardOnly: false, includeDebug);
158+
147159
/// <summary>
148160
/// Extract a cabinet file to an output directory, if possible
149161
/// </summary>
150162
/// <param name="filename">Filename for one cabinet in the set</param>
151163
/// <param name="outDir">Path to the output directory</param>
152-
/// <param name="forwardOnly">Indicates if the cabinet set should only be read forward</param>
153164
/// <param name="includeDebug">True to include debug data, false otherwise</param>
165+
/// <param name="forwardOnly">Indicates if decompression should be done forward-only</param>
154166
/// <returns>Indicates if all files were able to be extracted</returns>
155167
private bool ExtractCabinet(string filename, string outDir, bool forwardOnly, bool includeDebug)
156168
{
@@ -183,9 +195,14 @@ private bool ExtractCabinet(string filename, string outDir, bool forwardOnly, bo
183195
/// <param name="outDir">Path to the output directory</param>
184196
/// <param name="folder">Folder containing the blocks to decompress</param>
185197
/// <param name="folderIndex">Index of the folder in the cabinet</param>
186-
/// <param name="forwardOnly">Indicates if the cabinet set should only be read forward</param>
198+
/// <param name="forwardOnly">Indicates if decompression should be done forward-only</param>
187199
/// <param name="includeDebug">True to include debug data, false otherwise</param>
188-
private void ExtractFolder(string filename, string outDir, CFFOLDER? folder, int folderIndex, bool forwardOnly, bool includeDebug)
200+
private void ExtractFolder(string filename,
201+
string outDir,
202+
CFFOLDER? folder,
203+
int folderIndex,
204+
bool forwardOnly,
205+
bool includeDebug)
189206
{
190207
// Decompress the blocks, if possible
191208
using var blockStream = DecompressBlocks(filename, folder, folderIndex, forwardOnly);
@@ -448,12 +465,14 @@ private int GetFolderIndex(CFFILE file)
448465
/// <param name="filename">Filename for one cabinet in the set</param>
449466
/// <param name="folder">Folder containing the blocks to decompress</param>
450467
/// <param name="folderIndex">Index of the folder in the cabinet</param>
451-
/// <param name="forwardOnly">Indicates if the cabinet set should only be read forward</param>
468+
/// <param name="forwardOnly">Indicates if decompression should be done forward-only</param>
452469
/// <returns>Stream representing the decompressed data on success, null otherwise</returns>
453470
public Stream? DecompressBlocks(string filename, CFFOLDER? folder, int folderIndex, bool forwardOnly)
454471
{
455472
// Ensure data blocks
456-
var dataBlocks = GetDataBlocks(filename, folder, folderIndex, skipPrev: forwardOnly, skipNext: false);
473+
var dataBlocks = forwardOnly
474+
? GetDataBlocksForward(filename, folder, folderIndex)
475+
: GetDataBlocks(filename, folder, folderIndex);
457476
if (dataBlocks == null || dataBlocks.Length == 0)
458477
return null;
459478

@@ -481,15 +500,15 @@ private int GetFolderIndex(CFFILE file)
481500

482501
// MS-ZIP
483502
case CompressionType.TYPE_MSZIP:
484-
long position = ms.Position;
503+
long preMsZipPosition = ms.Position;
485504
mszip.CopyTo(db.CompressedData, ms);
486-
long decompressedSize = ms.Position - position;
505+
long msZipDecompressedSize = ms.Position - preMsZipPosition;
487506

488507
// Pad to the correct size but throw a warning about this
489-
if (decompressedSize < db.UncompressedSize)
508+
if (msZipDecompressedSize < db.UncompressedSize)
490509
{
491-
Console.Error.WriteLine($"Data block {i} in folder {folderIndex} had mismatching sizes. Expected: {db.UncompressedSize}, Got: {decompressedSize}");
492-
byte[] padding = new byte[db.UncompressedSize - decompressedSize];
510+
Console.Error.WriteLine($"Data block {i} in folder {folderIndex} had mismatching sizes. Expected: {db.UncompressedSize}, Got: {msZipDecompressedSize}");
511+
byte[] padding = new byte[db.UncompressedSize - msZipDecompressedSize];
493512
ms.Write(padding, 0, padding.Length);
494513
}
495514

@@ -580,6 +599,16 @@ private static CompressionType GetCompressionType(CFFOLDER folder)
580599
return [.. prevBlocks, .. folder.DataBlocks, .. nextBlocks];
581600
}
582601

602+
/// <summary>
603+
/// Get the set of data blocks for a folder using forward reading only
604+
/// </summary>
605+
/// <param name="filename">Filename for one cabinet in the set</param>
606+
/// <param name="folder">Folder containing the blocks to decompress</param>
607+
/// <param name="folderIndex">Index of the folder in the cabinet</param>
608+
/// <returns>Array of data blocks on success, null otherwise</returns>
609+
private CFDATA[]? GetDataBlocksForward(string filename, CFFOLDER? folder, int folderIndex)
610+
=> GetDataBlocks(filename, folder, folderIndex, skipPrev: true, skipNext: false);
611+
583612
/// <summary>
584613
/// Get all files for the current folder index
585614
/// </summary>

0 commit comments

Comments
 (0)