1- using System . IO ;
1+ using System ;
2+ using System . IO ;
23using BinaryObjectScanner . Interfaces ;
34#if ( NET40_OR_GREATER || NETCOREAPP ) && WIN
45using LibMSPackN ;
6+ #else
7+ using SabreTools . Models . MicrosoftCabinet ;
58#endif
69
710namespace BinaryObjectScanner . FileType
@@ -27,9 +30,111 @@ public bool Extract(string file, string outDir, bool includeDebug)
2730 public bool Extract ( Stream ? stream , string file , string outDir , bool includeDebug )
2831 {
2932#if NET20 || NET35 || ! WIN
30- // Not supported for old .NET due to feature requirements
31- // Not supported in non-Windows builds due to DLL requirements
32- return false ;
33+ try
34+ {
35+ if ( ! File . Exists ( file ) )
36+ return false ;
37+
38+ // Create the wrapper
39+ var cabArchive = SabreTools . Serialization . Wrappers . MicrosoftCabinet . Create ( stream ) ;
40+ if ( cabArchive ? . Model ? . Folders == null || cabArchive . Model . Folders . Length == 0 )
41+ return false ;
42+
43+ // Loop through the folders
44+ for ( int f = 0 ; f < cabArchive ! . Model . Folders . Length ; f ++ )
45+ {
46+ // Ensure data blocks
47+ var folder = cabArchive . Model . Folders [ f ] ;
48+ if ( folder ? . DataBlocks == null || folder . DataBlocks . Length == 0 )
49+ continue ;
50+
51+ // Loop through the data blocks
52+ var ms = new MemoryStream ( ) ;
53+ foreach ( var db in folder . DataBlocks )
54+ {
55+ if ( db ? . CompressedData == null )
56+ continue ;
57+
58+ // Uncompressed data
59+ if ( ( folder . CompressionType & CompressionType . TYPE_NONE ) != 0 )
60+ {
61+ ms . Write ( db . CompressedData ) ;
62+ ms . Flush ( ) ;
63+ }
64+
65+ // MS-ZIP
66+ else if ( ( folder . CompressionType & CompressionType . TYPE_MSZIP ) != 0 )
67+ {
68+ var decomp = SabreTools . Compression . MSZIP . Decompressor . Create ( ) ;
69+ decomp . CopyTo ( db . CompressedData , ms ) ;
70+ }
71+
72+ // Quantum
73+ else if ( ( folder . CompressionType & CompressionType . TYPE_QUANTUM ) != 0 )
74+ {
75+ uint windowBits = ( uint ) ( ( ( ushort ) folder . CompressionType >> 8 ) & 0x1f ) ;
76+ var decomp = SabreTools . Compression . Quantum . Decompressor . Create ( db . CompressedData , windowBits ) ;
77+ byte [ ] data = decomp . Process ( ) ;
78+ ms . Write ( data ) ;
79+ ms . Flush ( ) ;
80+ }
81+
82+ // LZX
83+ else if ( ( folder . CompressionType & CompressionType . TYPE_LZX ) != 0 )
84+ {
85+ // TODO: Unsupported
86+ continue ;
87+ }
88+
89+ // Unknown
90+ else
91+ {
92+ continue ;
93+ }
94+ }
95+
96+ // If no data was read
97+ if ( ms . Length == 0 )
98+ continue ;
99+
100+ // Ensure files
101+ if ( cabArchive ? . Model ? . Files == null || cabArchive . Model . Files . Length == 0 )
102+ continue ;
103+
104+ // Loop through the files
105+ foreach ( var compressedFile in cabArchive . Model . Files )
106+ {
107+ if ( compressedFile ? . Name == null || compressedFile . FolderIndex != ( FolderIndex ) f )
108+ continue ;
109+
110+ try
111+ {
112+ byte [ ] fileData = new byte [ compressedFile . FileSize ] ;
113+ Array . Copy ( ms . ToArray ( ) , compressedFile . FolderStartOffset , fileData , 0 , compressedFile . FileSize ) ;
114+
115+ string tempFile = Path . Combine ( outDir , compressedFile . Name ) ;
116+ var directoryName = Path . GetDirectoryName ( tempFile ) ;
117+ if ( directoryName != null && ! Directory . Exists ( directoryName ) )
118+ Directory . CreateDirectory ( directoryName ) ;
119+
120+ using var of = File . OpenWrite ( tempFile ) ;
121+ of . Write ( fileData ) ;
122+ of . Flush ( ) ;
123+ }
124+ catch ( Exception ex )
125+ {
126+ if ( includeDebug ) Console . WriteLine ( ex ) ;
127+ }
128+ }
129+ }
130+
131+ return true ;
132+ }
133+ catch ( Exception ex )
134+ {
135+ if ( includeDebug ) Console . WriteLine ( ex ) ;
136+ return false ;
137+ }
33138#else
34139 try
35140 {
@@ -49,17 +154,17 @@ public bool Extract(Stream? stream, string file, string outDir, bool includeDebu
49154
50155 compressedFile . ExtractTo ( tempFile ) ;
51156 }
52- catch ( System . Exception ex )
157+ catch ( Exception ex )
53158 {
54- if ( includeDebug ) System . Console . WriteLine ( ex ) ;
159+ if ( includeDebug ) Console . WriteLine ( ex ) ;
55160 }
56161 }
57162
58163 return true ;
59164 }
60- catch ( System . Exception ex )
165+ catch ( Exception ex )
61166 {
62- if ( includeDebug ) System . Console . WriteLine ( ex ) ;
167+ if ( includeDebug ) Console . WriteLine ( ex ) ;
63168 return false ;
64169 }
65170#endif
0 commit comments