2020-09-10 21:10:32 -07:00
using System ;
2021-07-18 09:44:23 -07:00
using System.Collections.Concurrent ;
2020-09-10 21:10:32 -07:00
using System.IO ;
2022-05-01 17:41:50 -07:00
using BurnOutSharp.Interfaces ;
2021-08-25 15:09:42 -07:00
using BurnOutSharp.Tools ;
2022-12-11 15:32:09 -08:00
#if NETSTANDARD2_0
2022-10-17 12:26:57 -07:00
using WixToolset.Dtf.Compression ;
2022-07-06 15:33:10 -07:00
using WixToolset.Dtf.Compression.Cab ;
2022-12-13 21:51:24 -08:00
#elif NET6_0_OR_GREATER
using LibMSPackSharp ;
using LibMSPackSharp.CABExtract ;
2022-12-11 15:32:09 -08:00
#endif
2020-09-10 21:10:32 -07:00
namespace BurnOutSharp.FileType
{
2022-12-08 21:32:52 -08:00
/// <summary>
/// Microsoft cabinet file
/// </summary>
/// <remarks>Specification available at <see href="http://download.microsoft.com/download/5/0/1/501ED102-E53F-4CE0-AA6B-B0F93629DDC6/Exchange/%5BMS-CAB%5D.pdf"/></remarks>
2022-12-13 21:51:24 -08:00
public partial class MicrosoftCAB : IScannable
2020-09-10 21:10:32 -07:00
{
2021-02-26 09:26:23 -08:00
/// <inheritdoc/>
2021-07-18 09:44:23 -07:00
public ConcurrentDictionary < string , ConcurrentQueue < string > > Scan ( Scanner scanner , string file )
2021-02-26 09:26:23 -08:00
{
if ( ! File . Exists ( file ) )
return null ;
using ( var fs = File . OpenRead ( file ) )
{
return Scan ( scanner , fs , file ) ;
}
}
/// <inheritdoc/>
2021-07-18 09:44:23 -07:00
public ConcurrentDictionary < string , ConcurrentQueue < string > > Scan ( Scanner scanner , Stream stream , string file )
2020-09-10 21:10:32 -07:00
{
2022-12-11 15:32:09 -08:00
#if NET6_0_OR_GREATER
2020-09-10 21:10:32 -07:00
// If the cab file itself fails
try
{
string tempPath = Path . Combine ( Path . GetTempPath ( ) , Guid . NewGuid ( ) . ToString ( ) ) ;
Directory . CreateDirectory ( tempPath ) ;
2022-12-13 21:51:24 -08:00
// Create the decompressor
var decompressor = Library . CreateCABDecompressor ( null ) ;
decompressor . Debug = scanner . IncludeDebug ;
2020-10-28 12:20:07 -07:00
2022-12-13 21:51:24 -08:00
// Open the cab file
var cabFile = decompressor . Open ( file ) ;
if ( cabFile = = null )
2022-05-15 20:58:27 -07:00
{
2022-12-13 21:51:24 -08:00
if ( scanner . IncludeDebug ) Console . WriteLine ( $"Error occurred opening of '{file}': {decompressor.Error}" ) ;
2022-07-07 11:24:21 -07:00
return null ;
}
2022-12-13 21:51:24 -08:00
// If we have a previous CAB and it exists, don't try scanning
string directory = Path . GetDirectoryName ( file ) ;
if ( ! string . IsNullOrWhiteSpace ( cabFile . PreviousCabinetName ) )
2022-07-07 11:24:21 -07:00
{
2022-12-13 21:51:24 -08:00
if ( File . Exists ( Path . Combine ( directory , cabFile . PreviousCabinetName ) ) )
2022-07-07 11:24:21 -07:00
return null ;
}
2022-12-13 21:51:24 -08:00
// If there are additional next CABs, add those
string fileName = Path . GetFileName ( file ) ;
CABExtract . LoadSpanningCabinets ( cabFile , fileName ) ;
2022-07-07 15:10:31 -07:00
2022-12-13 21:51:24 -08:00
// Loop through the found internal files
var sub = cabFile . Files ;
while ( sub ! = null )
2022-07-07 16:33:15 -07:00
{
2022-12-13 21:51:24 -08:00
// If an individual entry fails
try
2022-07-07 16:33:15 -07:00
{
2022-12-13 21:51:24 -08:00
// The trim here is for some very odd and stubborn files
string tempFile = Path . Combine ( tempPath , sub . Filename . TrimEnd ( '\0' , ' ' , '.' ) ) ;
Error error = decompressor . Extract ( sub , tempFile ) ;
if ( error ! = Error . MSPACK_ERR_OK )
2022-07-07 16:33:15 -07:00
{
2022-12-13 21:51:24 -08:00
if ( scanner . IncludeDebug ) Console . WriteLine ( $"Error occurred during extraction of '{sub.Filename}': {error}" ) ;
2022-07-07 16:33:15 -07:00
}
}
2022-12-13 21:51:24 -08:00
catch ( Exception ex )
2022-07-07 11:37:53 -07:00
{
2022-12-13 21:51:24 -08:00
if ( scanner . IncludeDebug ) Console . WriteLine ( ex ) ;
2022-07-07 11:37:53 -07:00
}
2022-12-13 21:51:24 -08:00
sub = sub . Next ;
2022-07-07 11:37:53 -07:00
}
2022-12-13 21:51:24 -08:00
// Destroy the decompressor
Library . DestroyCABDecompressor ( decompressor ) ;
2022-07-07 11:49:57 -07:00
2022-12-13 21:51:24 -08:00
// Collect and format all found protections
var protections = scanner . GetProtections ( tempPath ) ;
2022-07-07 11:49:57 -07:00
2022-12-13 21:51:24 -08:00
// If temp directory cleanup fails
try
2022-07-07 11:49:57 -07:00
{
2022-12-13 21:51:24 -08:00
Directory . Delete ( tempPath , true ) ;
2022-07-07 11:49:57 -07:00
}
2022-12-13 21:51:24 -08:00
catch ( Exception ex )
2022-07-07 11:15:35 -07:00
{
2022-12-13 21:51:24 -08:00
if ( scanner . IncludeDebug ) Console . WriteLine ( ex ) ;
2022-07-07 11:15:35 -07:00
}
2022-12-13 21:51:24 -08:00
// Remove temporary path references
Utilities . StripFromKeys ( protections , tempPath ) ;
2022-07-07 11:15:35 -07:00
2022-12-13 21:51:24 -08:00
return protections ;
2022-07-07 11:15:35 -07:00
}
2022-12-13 21:51:24 -08:00
catch ( Exception ex )
2022-07-07 12:02:25 -07:00
{
2022-12-13 21:51:24 -08:00
if ( scanner . IncludeDebug ) Console . WriteLine ( ex ) ;
2022-07-07 12:02:25 -07:00
}
2022-12-13 21:51:24 -08:00
return null ;
#else
// If the cab file itself fails
try
{
string tempPath = Path . Combine ( Path . GetTempPath ( ) , Guid . NewGuid ( ) . ToString ( ) ) ;
Directory . CreateDirectory ( tempPath ) ;
2022-07-07 12:02:25 -07:00
2022-12-13 21:51:24 -08:00
CabInfo cabInfo = new CabInfo ( file ) ;
cabInfo . Unpack ( tempPath ) ;
2022-07-07 12:02:25 -07:00
2022-12-13 21:51:24 -08:00
// Collect and format all found protections
var protections = scanner . GetProtections ( tempPath ) ;
2022-07-07 12:02:25 -07:00
2022-12-13 21:51:24 -08:00
// If temp directory cleanup fails
2022-07-07 12:02:25 -07:00
try
{
2022-12-13 21:51:24 -08:00
Directory . Delete ( tempPath , true ) ;
2022-07-07 12:02:25 -07:00
}
2022-12-13 21:51:24 -08:00
catch ( Exception ex )
2022-07-07 12:02:25 -07:00
{
2022-12-13 21:51:24 -08:00
if ( scanner . IncludeDebug ) Console . WriteLine ( ex ) ;
2022-07-07 12:02:25 -07:00
}
2022-07-07 10:39:41 -07:00
2022-12-13 21:51:24 -08:00
// Remove temporary path references
Utilities . StripFromKeys ( protections , tempPath ) ;
2022-07-07 13:27:13 -07:00
2022-12-13 21:51:24 -08:00
return protections ;
2022-07-07 13:27:13 -07:00
}
2022-12-13 21:51:24 -08:00
catch ( Exception ex )
2022-07-07 13:27:13 -07:00
{
2022-12-13 21:51:24 -08:00
if ( scanner . IncludeDebug ) Console . WriteLine ( ex ) ;
2022-07-07 13:27:13 -07:00
}
2022-12-13 21:51:24 -08:00
return null ;
#endif
2022-07-07 13:27:13 -07:00
}
2020-09-10 21:10:32 -07:00
}
}