22using System . IO ;
33using SabreTools . Data . Models . MicrosoftCabinet ;
44using SabreTools . IO . Compression . MSZIP ;
5+ using SabreTools . IO . Extensions ;
56
67namespace SabreTools . Serialization . Wrappers
78{
@@ -315,6 +316,8 @@ private static CompressionType GetCompressionType(CFFOLDER folder)
315316 if ( folder ? . DataBlocks == null || folder . DataBlocks . Length == 0 )
316317 return null ;
317318
319+ GetData ( folder ) ;
320+
318321 // Get all files for the folder
319322 var files = GetFiles ( folderIndex ) ;
320323 if ( files . Length == 0 )
@@ -335,7 +338,7 @@ private static CompressionType GetCompressionType(CFFOLDER folder)
335338 // Get all blocks from Prev
336339 if ( Prev ? . Header != null && Prev . Folders != null )
337340 {
338- int prevFolderIndex = Prev . FolderCount ;
341+ int prevFolderIndex = Prev . FolderCount - 1 ;
339342 var prevFolder = Prev . Folders [ prevFolderIndex - 1 ] ;
340343 prevBlocks = Prev . GetDataBlocks ( filename , prevFolder , prevFolderIndex , skipNext : true ) ?? [ ] ;
341344 }
@@ -360,6 +363,106 @@ private static CompressionType GetCompressionType(CFFOLDER folder)
360363 // Return all found blocks in order
361364 return [ .. prevBlocks , .. folder . DataBlocks , .. nextBlocks ] ;
362365 }
366+
367+ /// <summary>
368+ /// Loads in all the datablocks for the current folder.
369+ /// </summary>
370+ /// <param name="folder">The folder to have the datablocks loaded for</param>
371+ public void GetData ( CFFOLDER folder )
372+ {
373+ if ( folder . CabStartOffset <= 0 )
374+ return ;
375+
376+ uint offset = folder . CabStartOffset ;
377+ for ( int i = 0 ; i < folder . DataCount ; i ++ )
378+ {
379+ offset += 8 ;
380+
381+ if ( Header . DataReservedSize > 0 )
382+ {
383+ folder . DataBlocks [ i ] . ReservedData = ReadRangeFromSource ( offset , Header . DataReservedSize ) ;
384+ offset += Header . DataReservedSize ;
385+ }
386+
387+ if ( folder . DataBlocks [ i ] . CompressedSize > 0 )
388+ {
389+ folder . DataBlocks [ i ] . CompressedData = ReadRangeFromSource ( offset , folder . DataBlocks [ i ] . CompressedSize ) ;
390+ offset += folder . DataBlocks [ i ] . CompressedSize ;
391+ }
392+ }
393+
394+ }
395+
396+ /// <summary>
397+ /// Get all files for the current folder, plus connected spanned folders.
398+ /// </summary>
399+ /// <param name="folderIndex">Index of the folder in the cabinet</param>
400+ /// <param name="ignorePrev">True to ignore previous links, false otherwise</param>
401+ /// <returns>Array of all files for the folder</returns>
402+ private CFFILE [ ] GetSpannedFiles ( string ? filename , int folderIndex , bool ignorePrev = false , bool skipPrev = false , bool skipNext = false )
403+ {
404+ // Ignore invalid archives
405+ if ( Files . IsNullOrEmpty ( ) )
406+ return [ ] ;
407+
408+ // Get all files with a name and matching index
409+ var files = Array . FindAll ( Files , f =>
410+ {
411+ if ( string . IsNullOrEmpty ( f . Name ) )
412+ return false ;
413+
414+ // Ignore links to previous cabinets, if required
415+ if ( ignorePrev )
416+ {
417+ if ( f . FolderIndex == FolderIndex . CONTINUED_FROM_PREV )
418+ return false ;
419+ else if ( f . FolderIndex == FolderIndex . CONTINUED_PREV_AND_NEXT )
420+ return false ;
421+ }
422+
423+ int fileFolder = GetFolderIndex ( f ) ;
424+ return fileFolder == folderIndex ;
425+ } ) ;
426+
427+ // Check if the folder spans in either direction
428+ bool spanPrev = Array . Exists ( files , f => f . FolderIndex == FolderIndex . CONTINUED_FROM_PREV || f . FolderIndex == FolderIndex . CONTINUED_PREV_AND_NEXT ) ;
429+ bool spanNext = Array . Exists ( files , f => f . FolderIndex == FolderIndex . CONTINUED_TO_NEXT || f . FolderIndex == FolderIndex . CONTINUED_PREV_AND_NEXT ) ;
430+
431+ // If the folder spans backward and Prev is not being skipped
432+ CFFILE [ ] prevFiles = [ ] ;
433+ if ( ! skipPrev && spanPrev )
434+ {
435+ // Try to get Prev if it doesn't exist
436+ if ( Prev ? . Header == null )
437+ Prev = OpenPrevious ( filename ) ;
438+
439+ // Get all files from Prev
440+ if ( Prev ? . Header != null && Prev . Folders != null )
441+ {
442+ int prevFolderIndex = Prev . FolderCount - 1 ;
443+ prevFiles = Prev . GetSpannedFiles ( filename , prevFolderIndex , skipNext : true ) ?? [ ] ;
444+ }
445+ }
446+
447+ // If the folder spans forward and Next is not being skipped
448+ CFFILE [ ] nextFiles = [ ] ;
449+ if ( ! skipNext && spanNext )
450+ {
451+ // Try to get Next if it doesn't exist
452+ if ( Next ? . Header == null )
453+ Next = OpenNext ( filename ) ;
454+
455+ // Get all files from Prev
456+ if ( Next ? . Header != null && Next . Folders != null )
457+ {
458+ var nextFolder = Next . Folders [ 0 ] ;
459+ nextFiles = Next . GetSpannedFiles ( filename , 0 , skipPrev : true ) ?? [ ] ;
460+ }
461+ }
462+
463+ // Return all found files in order
464+ return [ .. prevFiles , .. files , .. nextFiles ] ;
465+ }
363466
364467 /// <summary>
365468 /// Get all files for the current folder index
0 commit comments