Compare commits

...

187 Commits

Author SHA1 Message Date
Matt Nadareski
e1da5f192c Do not overread PKZIP extra fields on malformed (fixes #65) 2026-01-29 14:05:36 -05:00
Matt Nadareski
c15809dd72 Remove unused usings 2026-01-28 21:31:59 -05:00
HeroponRikiBestest
89a67d1bd2 Implement model, reader, wrapper for valve SKU sis files. (#62)
* Try again

* Fix import alphebetization

* Fixes.

* first part of first attempt at a model

* Reimplement Sku Sis parsing

* First round of fixes

* Make sure stream isn't closed

* Missed this newline
2026-01-28 21:30:08 -05:00
Matt Nadareski
c4c6709478 Make note of why only partial driverstatus 2026-01-28 09:55:07 -05:00
Matt Nadareski
5e1f6ac4b3 Partially hook up driverstatus for CMP 2026-01-28 09:52:35 -05:00
Matt Nadareski
8f8d86d0bb Clean up some formatting things 2026-01-27 12:03:01 -05:00
HeroponRikiBestest
ecca11e2f3 Flush before closing in microsoftcabinet.extraction (#61)
I had previously been under the assumption that closing always guaranteed a flush. I don't know of any issues that were being caused, but I should push this before i forget.
2026-01-25 21:41:35 -05:00
Matt Nadareski
527b09c6bc Add debug flag to interface definitions (fixes #60) 2026-01-25 20:07:59 -05:00
Matt Nadareski
69b6595434 Missed this one too 2026-01-25 19:48:07 -05:00
Matt Nadareski
59b918c75f Apparently didn't rename this 2026-01-25 19:46:39 -05:00
Matt Nadareski
344132b50a Add editorconfig, fix issues 2026-01-25 16:15:05 -05:00
Matt Nadareski
a35e58e9cc Fix some errant formatting 2026-01-25 15:08:37 -05:00
Matt Nadareski
4300d94858 Use newer "is not null" syntax 2026-01-25 14:32:49 -05:00
Matt Nadareski
ee85a84d8f Use newer "is null" syntax 2026-01-25 14:30:18 -05:00
Matt Nadareski
2959d82231 Formatting cleanup 2026-01-25 13:38:52 -05:00
HeroponRikiBestest
5dfe6aefb0 Convert Installshield Executable code to use proper reader/wrapper instead of living in PortableExecutable (#59)
* Figure out how to access OverlayAddress in wrapper or reader (ideally the latter) for a non-PE reader/wrapper

* Code works

* Remove TODOs

* First round of fixes.

* use constants

* remove comment
2026-01-25 13:36:17 -05:00
HeroponRikiBestest
7f7d0f84ef Re-enable stream extraction for MScab (#58)
* Re-enable extraction from stream

* Remove todo pre PR

* Properly support all situations, remove whitespace
2026-01-25 12:24:28 -05:00
Matt Nadareski
4bfaf36e24 Formatting cleanup 2026-01-24 21:43:08 -05:00
HeroponRikiBestest
695fc4b0af Change mscab extraction to use state handling, break into more helper methods (#57)
* Attempt 1

* Use private helper class

* Remove comment

* Add missing summaries

* Don't use create pattern

* Remove removed variable summary

* Reduce what needs to be passed in

* Further reduce what needs to be passed in

* These didn't get tabbed for some reason

* First round of fixes.

* Second round of changes

* Add a few comments.
2026-01-24 21:41:23 -05:00
Matt Nadareski
f16ed9742f Support WoD info CMP block type 2026-01-24 11:37:29 -05:00
Matt Nadareski
6bfe68b8cf Formatting and comment cleanup 2026-01-24 10:24:35 -05:00
HeroponRikiBestest
2e5c5b3c79 Extract Ms-cabs while reading instead of loading all datablocks into memory (#56)
* WIP

* WIP 2

* Todo: you're missing a read somehow and getting misaligned by two bytes? maybe properly implementing the buffer will magically fix it

* continued blocks my behated

* Pre-major-testing

* Forgot to add summaries

* Attempt to properly roll back. The state i wanted to roll back to wasn't in a commit before.

* Figured out the issue with the rolled back commit, this has to be a while loop because of 0 byte files. Reimplemented clean code.

* Comment so I don't forget why it's like this

* Skip unsupported compression types before opening filestream.

* Reenable non-start cab skipping

* TODO so i don't forget

* TODO so I don't forget

* iterate on continued block correctly.

* Handle incomplete extraction better

* Remove TODOs to ready for PR comments

* Missed one

* Some minor fixes before rewriting everything

* Next round of fixes.

* Next set of fixes

* Fix debug output
2026-01-24 10:08:18 -05:00
Matt Nadareski
2a6e193756 Formatting cleanup 2026-01-05 13:48:36 -05:00
HeroponRikiBestest
65a86d87f0 Fix mszip relying on exceptions (#52)
* Better fix

* initial

* Fixed

* Move function to proper location, clear memory better

* work so far

* more

* more work

* No more per file seeking

* Finished work for now.

* First round of fixes.

* Return if array is empty too
2026-01-05 13:45:20 -05:00
HeroponRikiBestest
d7131dfa4c fix naming (#53) 2025-12-04 11:10:46 -05:00
HeroponRikiBestest
a228b16314 Fix GCF extraction (#48) 2025-12-04 10:46:13 -05:00
Matt Nadareski
b8c9048ac6 Update GrindCore to 0.6.5 2025-12-02 19:35:20 -05:00
HeroponRikiBestest
0b54350d59 Explicitly handle password-protected archives rather than repeatedly throwing exceptions (#47)
* Explicitly handle password-protected archives rather than repeatedly throwing exceptions

* Fix logic error

* Continues

* Remove bool
2025-12-02 09:38:11 -05:00
Deterous
59eddb7129 Fix ISO9660 extraction of large files (#46)
* ExtentLength is uint

* Fix

* fix2

* fix3

* fix4

* Invert multi extent final extent logic
2025-12-02 07:31:31 -05:00
Matt Nadareski
1096232f9d Update GC libraries 2025-11-30 19:40:35 -05:00
Matt Nadareski
4b39ee8d00 Add CRC-16 and CRC-64 dat support 2025-11-29 10:11:05 -05:00
Matt Nadareski
27a9b12bbf Bump version 2025-11-25 07:45:09 -05:00
Matt Nadareski
11319c3341 Update GC.SharpCompress 2025-11-25 07:44:29 -05:00
Matt Nadareski
4de061e0d1 Bump version 2025-11-24 08:59:19 -05:00
Matt Nadareski
258e894c30 Update GC.SharpCompress 2025-11-23 19:59:28 -05:00
Matt Nadareski
8658eaf4e0 Format GHA definitions 2025-11-17 08:39:16 -05:00
Matt Nadareski
6d341abc75 Fix comment about CFB 2025-11-17 08:33:00 -05:00
Matt Nadareski
4821d63b4a Off-by-one spacing 2025-11-15 09:10:34 -05:00
Matt Nadareski
0617bf3170 Process all folders in all MS-CAB files in a set (fixes #43) 2025-11-15 09:00:28 -05:00
Matt Nadareski
425d13a2ac Fix inconsistencies in IS-CAB 2025-11-14 23:21:04 -05:00
Matt Nadareski
8a1e90f537 Reduce unnecessary casts 2025-11-14 21:33:55 -05:00
Matt Nadareski
ddc00948ed Remove red herring zlib code 2025-11-14 21:08:55 -05:00
Matt Nadareski
c96ee81f06 Simplify fixed statements 2025-11-14 20:36:46 -05:00
Matt Nadareski
f6201e2c35 In-depth cleanup with .NET 10 concepts 2025-11-14 14:06:43 -05:00
Matt Nadareski
d63fcfcf7f Minor formatting change to external code 2025-11-14 10:30:15 -05:00
Matt Nadareski
dcc50c4c23 Remove empty .gitmodules 2025-11-14 10:28:55 -05:00
Matt Nadareski
60e46e580d Cache more properties using the field keyword 2025-11-14 10:14:50 -05:00
Matt Nadareski
0638998773 Use auto-fields where possible 2025-11-14 09:48:00 -05:00
Matt Nadareski
ad3113987b Add support for .NET 10 2025-11-14 09:06:59 -05:00
Matt Nadareski
f2f0d0f2e7 Try to fix self-referencing MS-CAB 2025-11-13 14:07:46 -05:00
Matt Nadareski
f7fd2f6f65 Name some type parameters 2025-11-11 09:57:38 -05:00
Matt Nadareski
281c18e21d Bump version 2025-11-06 08:08:10 -05:00
Matt Nadareski
1a9c8b5392 Scaffolding for the future 2025-11-06 08:01:04 -05:00
Deterous
831a272f4b Final ISO9660 fix (#41)
* debug

* using

* Test fix

* Final fix
2025-11-05 20:26:42 -05:00
Matt Nadareski
f47e68b9ba Add Mode0 and Mode2 formless models 2025-11-05 09:49:32 -05:00
Matt Nadareski
eaabd2ee77 Add static readers for CD-ROM sector types 2025-11-05 09:37:56 -05:00
Matt Nadareski
a269edd6ea Missed one explicit type 2025-11-05 09:20:48 -05:00
Matt Nadareski
3bb501ce0c Separate out some helper methods 2025-11-05 09:14:37 -05:00
Deterous
d0006a4653 Custom ISO Stream for full CDROM support (#40)
* Implement custom ISO stream for CDROM support

* Delete old files

* Delete old test

* Leaner CDROM wrapper

* Fix custom stream

* WrapperBase using ISO stream

* Reset stream after deserializing

* Fix SeekOrigin

* Return to cached position

* CDROM Constants

* correct ns

* fix href
2025-11-05 08:20:34 -05:00
Matt Nadareski
c48a1394bc Be descriptive about types 2025-11-04 14:15:39 -05:00
Matt Nadareski
fcf7fcfd44 Be descriptive about types 2025-11-04 10:49:03 -05:00
Matt Nadareski
cca08e7103 Use consistent naming 2025-11-04 10:27:00 -05:00
Matt Nadareski
b908732f5c Fix logical block extension 2025-11-04 10:25:55 -05:00
Matt Nadareski
4ee4a6e85f Slight extension cleanup 2025-11-04 10:07:57 -05:00
Matt Nadareski
7990f11bab Remove unnecessary null checks 2025-11-04 09:54:24 -05:00
Matt Nadareski
427f7c9136 Remove unnecessary null checks 2025-11-04 09:46:03 -05:00
Matt Nadareski
f938f1593d Formatting update for readability 2025-11-04 09:15:12 -05:00
Matt Nadareski
480a1834ed Logic inversion and slight cleanup 2025-11-03 20:16:54 -05:00
Matt Nadareski
df5acc648c Minor cleanup 2025-11-03 10:31:30 -05:00
Matt Nadareski
10569e6aa1 Add tests for CDROM 2025-11-03 10:29:52 -05:00
Matt Nadareski
e5103b4830 Fix format comment for ExtractionTool 2025-11-03 09:27:57 -05:00
Matt Nadareski
513646fc53 Fix ExtractionTool publish 2025-11-03 09:03:45 -05:00
Matt Nadareski
27f723bf2f CascLibSharp isn't used and can be removed 2025-11-03 08:53:04 -05:00
Matt Nadareski
6511ecb5ad Merge pull request #39 from SabreTools/storm
Directly include StormLibSharp
2025-11-03 08:39:47 -05:00
Matt Nadareski
7bf6e6f344 Code cleanup and slight modernization 2025-11-03 08:36:12 -05:00
Matt Nadareski
d3e340ae39 Add and use MPQ filename constants 2025-11-02 23:21:29 -05:00
Matt Nadareski
22167a9617 Recursion isn't needed now 2025-11-02 22:27:02 -05:00
Matt Nadareski
48bea55133 Enable extraction on all .NET versions (not OSes) 2025-11-02 22:20:21 -05:00
Matt Nadareski
42239919e5 Enable StormLib for all .NET versions 2025-11-02 22:07:40 -05:00
Matt Nadareski
4840d9df6e Remove NoWarn and fix issues 2025-11-02 21:41:58 -05:00
Matt Nadareski
1378b87ea6 Directly include StormLibSharp code 2025-11-02 21:11:39 -05:00
Matt Nadareski
6b48164b97 Remove StormLibSharp as submodule 2025-11-02 21:07:51 -05:00
Matt Nadareski
50b09aa249 Automated cleanup 2025-11-02 19:28:16 -05:00
Deterous
ecbd147f6d CD-ROM (Volume Descriptor Set) support (#37)
* CD-ROM Wrapper

* Fix CDROMVolume Reader

* Fix SectorMode enum
2025-11-02 19:21:19 -05:00
HeroponRikiBestest
c13df79848 Fix extraction of recent MPF-zipped logs (#38)
* Fix extraction of recent MPF-zipped logs

* Use greater than or equal to

* corrected logic
2025-11-02 08:35:02 -05:00
Deterous
48bcc1de5b ISO9660: Skip interleaved files and other fixes (#35)
* Skip interleaved files

* Fix warning logic

* Refactor

* Fix extraction

* Multi extent

* review
2025-11-01 22:52:41 -04:00
Matt Nadareski
d082f5de25 Auto formatting cleanup 2025-10-31 21:07:13 -04:00
Deterous
c2321669b6 Support ISO9660 Extended Attribute Record (#34)
* Support ISO9660 Extended Attribute Record

* fix

* Fix

* Don't extract multi-extent files

* ReadUInt16LittleEndian

* debug

* Fix

* Skip EAR when extracting files

* Add comment about EAR

* Fix same-name extraction

* Safer directory parsing

* even safer

* return null

* more directory record checks

* not nullable nullable

* init system use

* valid records should pass

* review

* remove empty case
2025-10-31 21:04:45 -04:00
Matt Nadareski
e382635b85 Fix accidental recursion 2025-10-31 14:01:25 -04:00
Matt Nadareski
b4e02d7f8c Ensure default values in models when not optional 2025-10-31 13:59:28 -04:00
Matt Nadareski
0dc8a0b6c0 One missed explicit endian read 2025-10-31 09:36:28 -04:00
Matt Nadareski
171834986d Fix build from previous cleanup 2025-10-31 00:01:35 -04:00
Matt Nadareski
97af686b73 ZSTD model cleanup 2025-10-30 23:59:25 -04:00
Matt Nadareski
7d627ffc6f XZP model cleanup 2025-10-30 23:59:08 -04:00
Matt Nadareski
d924f25eb2 XZ model cleanup 2025-10-30 23:57:15 -04:00
Matt Nadareski
abd8ef3b1f Xbox model cleanup 2025-10-30 23:55:08 -04:00
Matt Nadareski
e9b8dba3a6 WiseInstaller model cleanup 2025-10-30 23:54:22 -04:00
Matt Nadareski
aaff7e7332 WAD3 model cleanup 2025-10-30 23:50:44 -04:00
Matt Nadareski
2fa00d1a16 VPK model cleanup 2025-10-30 23:48:26 -04:00
Matt Nadareski
8a2a2ecd12 TAR model cleanup 2025-10-30 23:45:14 -04:00
Matt Nadareski
98517bdd8c StarForce model cleanup 2025-10-30 23:43:06 -04:00
Matt Nadareski
dfe76f7e7e SpoonInstaller model cleanup 2025-10-30 23:41:40 -04:00
Matt Nadareski
a2e24b1f5f SGA model cleanup 2025-10-30 23:40:45 -04:00
Matt Nadareski
6a4e76e245 SevenZip model cleanup 2025-10-30 23:34:20 -04:00
Matt Nadareski
1ebec97e0e SecuROM model cleanup 2025-10-30 23:34:06 -04:00
Matt Nadareski
b9f03b02f0 RealArcade model cleanup 2025-10-30 23:31:19 -04:00
Matt Nadareski
2c06760778 RAR model cleanup 2025-10-30 23:31:01 -04:00
Matt Nadareski
3f0ee70b71 Quantum model cleanup 2025-10-30 23:30:45 -04:00
Matt Nadareski
05b34f158b PortableExecutable model cleanup 2025-10-30 23:29:24 -04:00
Matt Nadareski
e08db935b4 PlayStation4 model cleanup 2025-10-30 23:07:12 -04:00
Matt Nadareski
47da068bd3 PlayStation3 model cleanup 2025-10-30 23:06:46 -04:00
Matt Nadareski
9de669606d PlayJ model cleanup 2025-10-30 23:05:24 -04:00
Matt Nadareski
a02d50e61d PKZIP model cleanup 2025-10-30 23:01:55 -04:00
Matt Nadareski
069dab7fba PIC model cleanup 2025-10-30 22:58:02 -04:00
Matt Nadareski
d65edadbbb PFF model cleanup 2025-10-30 22:56:23 -04:00
Matt Nadareski
6307a51c0a PAK model cleanup 2025-10-30 22:54:37 -04:00
Matt Nadareski
d27c602bdf OLE model cleanup 2025-10-30 22:52:56 -04:00
Matt Nadareski
59fe9cb113 Nitro model cleanup 2025-10-30 22:51:16 -04:00
Matt Nadareski
b4b7ba75cb NewExecutable model cleanup 2025-10-30 22:47:17 -04:00
Matt Nadareski
d02e0c16c4 NCF model cleanup 2025-10-30 22:39:08 -04:00
Matt Nadareski
4aa0eb54b7 N3DS model cleanup 2025-10-30 22:36:21 -04:00
Matt Nadareski
c4f73abcb6 MSDOS model cleanup 2025-10-30 22:15:10 -04:00
Matt Nadareski
73dec51a4d MoPaQ model cleanup 2025-10-30 22:12:06 -04:00
Matt Nadareski
b7c3c094ae MicrosoftCabinet model cleanup 2025-10-30 22:07:29 -04:00
Matt Nadareski
97702ab3d5 LZ model cleanup 2025-10-30 22:03:22 -04:00
Matt Nadareski
a9b5fe706c LinearExecutable model cleanup 2025-10-30 22:00:42 -04:00
Matt Nadareski
198d48610c LDSCRYPT model cleanup 2025-10-30 21:55:01 -04:00
Matt Nadareski
c0e0344914 IRD model cleanup 2025-10-30 21:54:27 -04:00
Matt Nadareski
d49b2f1b60 InstallShieldExecutable model cleanup 2025-10-30 21:52:20 -04:00
Matt Nadareski
ec7172466b InstallShieldCabinet model cleanup 2025-10-30 21:51:15 -04:00
Matt Nadareski
d75a512ead InstallShieldArchiveV3 model cleanup 2025-10-30 21:43:38 -04:00
Matt Nadareski
af8b6906b6 GZIP model cleanup 2025-10-30 21:40:25 -04:00
Matt Nadareski
96bc301e6d GCF model cleanup 2025-10-30 21:38:17 -04:00
Matt Nadareski
c10749f34d DVD model cleanup 2025-10-30 21:32:21 -04:00
Matt Nadareski
0e4235c8ba Delphi model cleanup 2025-10-30 21:30:41 -04:00
Matt Nadareski
b2d31bb87e CueSheets model cleanup 2025-10-30 21:30:13 -04:00
Matt Nadareski
3ee88793da COFF model cleanup 2025-10-30 21:29:24 -04:00
Matt Nadareski
ad0f01c3ef CHD model cleanup 2025-10-30 21:27:37 -04:00
Matt Nadareski
63a96a7cf8 CFB model cleanup 2025-10-30 21:26:19 -04:00
Matt Nadareski
b8d8ca9a5c BZip2 model cleanup 2025-10-30 21:22:33 -04:00
Matt Nadareski
6b0fca31ae BSP model cleanup 2025-10-30 21:21:56 -04:00
Matt Nadareski
c147b12b10 Bitmap model cleanup 2025-10-30 20:58:03 -04:00
Matt Nadareski
7884b0b775 BFPK model cleanup 2025-10-30 20:57:35 -04:00
Matt Nadareski
9f3c263328 BDPlus model cleanup 2025-10-30 20:55:39 -04:00
Matt Nadareski
b830ce3d73 AdvancedInstaller model cleanup 2025-10-30 20:54:32 -04:00
Matt Nadareski
e8b7f33bf0 AACS model cleanup 2025-10-30 20:52:35 -04:00
Matt Nadareski
eae75c5943 Allow byte arrays to be non-null in most models 2025-10-30 20:44:16 -04:00
Matt Nadareski
c1f5ebcae1 Remove experiments 2025-10-30 19:50:03 -04:00
Matt Nadareski
acb8e98fe2 Add ImgBurn and UltraISO check extensions 2025-10-30 17:04:29 -04:00
Matt Nadareski
a24a92e97c Add unset reserved bytes extension 2025-10-30 16:22:05 -04:00
Matt Nadareski
f2d2fe97bb Override 2025-10-30 12:06:42 -04:00
Matt Nadareski
705252eec7 Unify Skeleton to ISO-9660 2025-10-30 12:03:13 -04:00
Matt Nadareski
69ae0456f0 Add skeleton printing and tests 2025-10-30 11:50:37 -04:00
Deterous
f07bd07cce Redumper skeleton support (#32)
* Skeleton support

* hide ISO extract

* Return true

* Don't inherit ISO9660

* fix

* fix2

* Skeleton
2025-10-30 11:46:45 -04:00
Matt Nadareski
9db2d2ca05 Reduce complexity of Zstd filename generation 2025-10-30 10:23:50 -04:00
Deterous
85248b0135 ISO 9660 Extraction (#31)
* ISO9660 Extraction

* Fix build

* Decode strings in Printer

* Double comment
2025-10-30 10:00:10 -04:00
Matt Nadareski
8663edc7df Fix unsynced ISO position 2025-10-30 08:20:46 -04:00
Matt Nadareski
b9cc9e40fd Changes based on a code sweep with unrelated issue 2025-10-30 07:51:08 -04:00
HeroponRikiBestest
5ce085ad2b Implement basic ZSTD detection and extraction. (#30)
* Implement basic ZSTD detection and extraction.

* Fix comment

* Remove newline

* Add newline

* Move section

* more newlines banished to the ether

* fix comment and name

* fix final i think
2025-10-29 22:01:23 -04:00
Matt Nadareski
d24f8a2fce Add ECMA link to models readme 2025-10-29 10:11:39 -04:00
Matt Nadareski
a73e830209 This extension is useful 2025-10-29 09:46:12 -04:00
Matt Nadareski
146fb42fd0 Replace remaining Seek with SeekIfPossible 2025-10-29 09:34:52 -04:00
Matt Nadareski
5b54ed719e Better integrate new printing model 2025-10-29 09:23:45 -04:00
Matt Nadareski
02d011228e IRD wrapper exists and should be used 2025-10-29 08:57:01 -04:00
Matt Nadareski
07adfd20a3 Add tests for ISO9660 2025-10-29 08:55:45 -04:00
Matt Nadareski
1d00abd6cc Make printing a wrapper extension 2025-10-29 08:53:14 -04:00
Deterous
36c2cc2f15 ISO 9660 support (#29)
* Begin defining ISO9660 models

* Fix initial models

* Improve ISO9660 models

* ISO9660 models

* Fix fields

* Nullable and enums

* Fix flags attribute

* Start ISO9660 Reader code

* semicolon

* Fix build

* Use EqualsExactly

* Fix build

* Update ISO9660.cs

* Update ISO9660.cs

* Move DirectoryRecordDateTime class

* ParseDirectoryRecordDateTime function

* ST refactoring

* fix return

* return array

* ISO9660 wrapper

* Initial printing code

* semicolon

* Fix

* orphan variable name

* fix null ref

* ISO9660 Printer

* Fix DirectoryRecord parsing

* fix

* test

* test

* Fix reader

* extractable ISO

* partial wrapper class

* namespace

* extension property

* path tables

* Cleanup

* rename directory

* fix

* fix

* typo

* fix2

* Fix

* Cleanup reader

* Count list property

* Parse Path Tables

* fix model name

* fix

* fix2

* fix3

* print path table records

* debug errors

* debug error

* debug

* undo debug

* Fix casting

* Validate path table locations

* print table numbers

* Printer cleanup

* fix printer

* printer++

* Print DecDateTime

* else if

* BootSystemUse

* Use Linq

* custom zero check

* fix

* Update ISO9660.cs

* Update ISO9660.cs

* Update ISO9660.cs

* Update ISO9660.cs

* fix

* debug

* debug2

* debug3

* debug4

* debug5

* debug6

* debug7

* debug8

* Array.TrueForAll

* Update ISO9660.cs

* fix

* cleanup

* typo

* Use BothInt numerics

* using SabreTools.Numerics

* Test nonnull

* nonnull bothint

* Print invalid BothInts

* Print directory record

* typo

* fix

* null check

* directory descriptors

* cleanup printer

* semicolon

* Fix

* flags never null

* more non nullable

* no null

* AppendLineBothEndian

* fix

* rename to Directory

* fix

* namespace

* full namespace

* fix

* cleanup

* Parse directories

* fix

* Fix

* Test parse directories

* PeekByteValue

* Revert CI changes

* Dummy extractor

* Review and fixes

* Fixes

* Final fix

* big endian directory search

* fix big endian changes

* Final fix
2025-10-29 08:46:08 -04:00
Matt Nadareski
27cf01ce84 Add printing cases for empty alongside null 2025-10-28 09:52:53 -04:00
Matt Nadareski
1e94163693 Add both-endian StringBuilder extensions
This has to use a new name for the both-endian handling because otherwise the implicit type handling will otherwise cause compilation errors.
2025-10-28 09:49:38 -04:00
Matt Nadareski
db1f94775b Convert some known Peek calls 2025-10-27 22:55:25 -04:00
Matt Nadareski
ce394eb4e9 Seek, if possible 2025-10-27 22:43:56 -04:00
Matt Nadareski
15109bed88 Update IO to 1.8.0 2025-10-27 22:15:54 -04:00
Matt Nadareski
8a18c8de34 Update rolling tag 2025-10-26 20:31:03 -04:00
HeroponRikiBestest
2f093a80c7 increase buffer size for isexe reading / writing based on deterous's … (#28)
* increase buffer size for isexe reading / writing based on deterous's input

* remove comment
2025-10-26 18:54:35 -04:00
Matt Nadareski
5df1af9c17 Minor cleanup and additions 2025-10-23 16:05:12 -04:00
HeroponRikiBestest
d5ab37a5a6 Add extraction for installshield executables. (#27)
* Add extractor for installshield executables.

* Add comment

* Fix intendation.

* Ensure PRs recursively pull

* Rebase

* Fix formatting for parsex

* newline before obj.name

* Changed while loop check to a position vs length check

* Specify type for chunkSize

* declare chunksize as a const int outside of the loop

* Open file writer with using

* Call fs.flush after every write.

* Improved chunk writing loop.

* Remove now-unecessary variable

* Properly handle extracting files of size greater than int32.

* Use long for overlay address

* create deserializer outside of loop.

* Move null check.

* Don't cache position.

---------

Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
2025-10-23 15:38:51 -04:00
Matt Nadareski
ed9ecf0da9 Ensure PRs recursively pull 2025-10-23 12:08:47 -04:00
Matt Nadareski
4fc17197ca Fix inverted logic of file only flag 2025-10-19 17:59:56 -04:00
Matt Nadareski
94a9cf0c3f Minor tweak to Wise debug statements 2025-10-17 09:56:04 -04:00
Matt Nadareski
1d9e12183f Bump version 2025-10-07 12:42:06 -04:00
Matt Nadareski
aaa8bbe709 This was inconsistent too 2025-10-07 11:25:35 -04:00
Matt Nadareski
805d1b9ad8 Not sure why this part was inconsistent 2025-10-07 11:21:39 -04:00
Matt Nadareski
d24d3e5adb Remove now-unused constants 2025-10-07 10:48:31 -04:00
Matt Nadareski
d3a7d552c3 Use main feature pattern with InfoPrint 2025-10-07 10:20:57 -04:00
Matt Nadareski
9f1c5e2bd2 Use main feature pattern with ExtractionTool 2025-10-07 10:04:19 -04:00
Matt Nadareski
1ec4ea8354 Update packages 2025-10-07 09:37:42 -04:00
Matt Nadareski
e4fab52489 Use CommandLine library for executables 2025-10-06 09:32:01 -04:00
1322 changed files with 17088 additions and 9595 deletions

167
.editorconfig Normal file
View File

@@ -0,0 +1,167 @@
# top-most EditorConfig file
root = true
# C# files
[*.cs]
# Indentation and spacing
charset = utf-8
indent_size = 4
indent_style = space
tab_width = 4
trim_trailing_whitespace = true
# New line preferences
end_of_line = lf
insert_final_newline = true
max_line_length = unset
# using directive preferences
csharp_using_directive_placement = outside_namespace
dotnet_diagnostic.IDE0005.severity = error
# Code-block preferences
csharp_style_namespace_declarations = block_scoped
csharp_style_prefer_method_group_conversion = true
csharp_style_prefer_top_level_statements = false
# Expression-level preferences
csharp_prefer_simple_default_expression = true
csharp_style_inlined_variable_declaration = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable
dotnet_diagnostic.IDE0001.severity = warning
dotnet_diagnostic.IDE0002.severity = warning
dotnet_diagnostic.IDE0004.severity = warning
dotnet_diagnostic.IDE0010.severity = error
dotnet_diagnostic.IDE0051.severity = warning
dotnet_diagnostic.IDE0052.severity = warning
dotnet_diagnostic.IDE0072.severity = warning
dotnet_diagnostic.IDE0080.severity = warning
dotnet_diagnostic.IDE0100.severity = error
dotnet_diagnostic.IDE0110.severity = error
dotnet_diagnostic.IDE0120.severity = warning
dotnet_diagnostic.IDE0121.severity = warning
dotnet_diagnostic.IDE0240.severity = error
dotnet_diagnostic.IDE0241.severity = error
dotnet_style_coalesce_expression = true
dotnet_style_namespace_match_folder = false
dotnet_style_null_propagation = true
dotnet_style_prefer_auto_properties = true
dotnet_style_prefer_collection_expression = when_types_loosely_match
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_style_prefer_compound_assignment = true
csharp_style_prefer_simple_property_accessors = true
dotnet_style_prefer_simplified_interpolation = true
dotnet_style_prefer_simplified_boolean_expressions = true
csharp_style_prefer_unbound_generic_type_in_nameof = true
# Field preferences
dotnet_diagnostic.IDE0044.severity = warning
dotnet_style_readonly_field = true
# Language keyword vs. framework types preferences
dotnet_diagnostic.IDE0049.severity = error
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# Modifier preferences
csharp_prefer_static_local_function = true
csharp_style_prefer_readonly_struct = true
dotnet_diagnostic.IDE0036.severity = warning
dotnet_diagnostic.IDE0040.severity = error
dotnet_diagnostic.IDE0380.severity = error
dotnet_style_require_accessibility_modifiers = always
# New-line preferences
dotnet_diagnostic.IDE2000.severity = warning
dotnet_diagnostic.IDE2002.severity = warning
dotnet_diagnostic.IDE2003.severity = warning
dotnet_diagnostic.IDE2004.severity = warning
dotnet_diagnostic.IDE2005.severity = warning
dotnet_diagnostic.IDE2006.severity = warning
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
dotnet_style_allow_multiple_blank_lines_experimental = false
dotnet_style_allow_statement_immediately_after_block_experimental = false
# Null-checking preferences
csharp_style_conditional_delegate_call = true
# Parameter preferences
dotnet_code_quality_unused_parameters = all
dotnet_diagnostic.IDE0280.severity = error
# Parentheses preferences
dotnet_diagnostic.IDE0047.severity = warning
dotnet_diagnostic.IDE0048.severity = warning
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = always_for_clarity
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
# Pattern-matching preferences
dotnet_diagnostic.IDE0019.severity = warning
dotnet_diagnostic.IDE0020.severity = warning
dotnet_diagnostic.IDE0038.severity = warning
dotnet_diagnostic.IDE0066.severity = none
dotnet_diagnostic.IDE0083.severity = warning
dotnet_diagnostic.IDE0260.severity = warning
csharp_style_pattern_matching_over_as_with_null_check = true
csharp_style_pattern_matching_over_is_with_cast_check = true
csharp_style_prefer_not_pattern = true
csharp_style_prefer_pattern_matching = true
# this. and Me. preferences
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false
# var preferences
csharp_style_var_for_built_in_types = false
csharp_style_var_when_type_is_apparent = true
# .NET formatting options
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = true
# C# formatting options
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = false
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false

View File

@@ -1,40 +1,48 @@
name: Build and Test
on:
push:
branches: [ "main" ]
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
9.0.x
- name: Run tests
run: dotnet test
- name: Run publish script
run: ./publish-nix.sh -d
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: "*.nupkg,*.snupkg,*.zip"
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Run tests
run: dotnet test
- name: Run publish script
run: ./publish-nix.sh -d
- name: Update rolling tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -f rolling
git push origin :refs/tags/rolling || true
git push origin rolling --force
- name: Upload to rolling
uses: ncipollo/release-action@v1.20.0
with:
allowUpdates: True
artifacts: "*.nupkg,*.snupkg,*.zip"
body: "Last built commit: ${{ github.sha }}"
name: "Rolling Release"
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

View File

@@ -3,21 +3,21 @@ name: Build PR
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
9.0.x
- name: Build
run: dotnet build
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Run tests
run: dotnet test
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Build
run: dotnet build
- name: Run tests
run: dotnet test

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "SabreTools.Serialization/_EXTERNAL/stormlibsharp"]
path = SabreTools.Serialization/_EXTERNAL/stormlibsharp
url = https://github.com/robpaveza/stormlibsharp.git

14
.vscode/launch.json vendored
View File

@@ -1,16 +1,16 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (ExtractionTool)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/ExtractionTool/bin/Debug/net9.0/ExtractionTool.dll",
"program": "${workspaceFolder}/ExtractionTool/bin/Debug/net10.0/ExtractionTool.dll",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
@@ -24,7 +24,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/InfoPrint/bin/Debug/net9.0/InfoPrint.dll",
"program": "${workspaceFolder}/InfoPrint/bin/Debug/net10.0/InfoPrint.dll",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
<OutputType>Exe</OutputType>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
@@ -10,7 +10,7 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>2.0.1</Version>
<Version>2.2.1</Version>
</PropertyGroup>
<!-- Support All Frameworks -->
@@ -20,20 +20,15 @@
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
</PropertyGroup>
<!-- These are needed for dealing with native Windows DLLs -->
<ItemGroup Condition="'$(RuntimeIdentifier)'=='win-x86'">
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x86\native\CascLib.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<TargetPath>CascLib.dll</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x86\native\StormLib.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
@@ -41,11 +36,6 @@
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)'=='win-x64'">
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x64\native\CascLib.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<TargetPath>CascLib.dll</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="..\SabreTools.Serialization\runtimes\win-x64\native\StormLib.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
@@ -58,8 +48,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.IO" Version="[1.7.5]" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.9" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
<PackageReference Include="SabreTools.IO" Version="[1.9.0]" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,340 @@
using System;
using System.IO;
using SabreTools.CommandLine;
using SabreTools.CommandLine.Inputs;
using SabreTools.IO.Extensions;
using SabreTools.Serialization;
using SabreTools.Serialization.Wrappers;
namespace ExtractionTool.Features
{
internal sealed class MainFeature : Feature
{
#region Feature Definition
public const string DisplayName = "main";
/// <remarks>Flags are unused</remarks>
private static readonly string[] _flags = [];
/// <remarks>Description is unused</remarks>
private const string _description = "";
#endregion
#region Inputs
private const string _debugName = "debug";
internal readonly FlagInput DebugInput = new(_debugName, ["-d", "--debug"], "Enable debug mode");
private const string _outputPathName = "output-path";
internal readonly StringInput OutputPathInput = new(_outputPathName, ["-o", "--outdir"], "Set output path for extraction (required)");
#endregion
#region Properties
/// <summary>
/// Enable debug output for relevant operations
/// </summary>
public bool Debug { get; private set; }
/// <summary>
/// Output path for archive extraction
/// </summary>
public string OutputPath { get; private set; } = string.Empty;
#endregion
public MainFeature()
: base(DisplayName, _flags, _description)
{
RequiresInputs = true;
Add(DebugInput);
Add(OutputPathInput);
}
/// <inheritdoc/>
public override bool Execute()
{
// Get the options from the arguments
Debug = GetBoolean(_debugName);
OutputPath = GetString(_outputPathName) ?? string.Empty;
// Validate the output path
if (!ValidateExtractionPath())
return false;
// Loop through the input paths
for (int i = 0; i < Inputs.Count; i++)
{
string arg = Inputs[i];
ExtractPath(arg);
}
return true;
}
/// <inheritdoc/>
public override bool VerifyInputs() => Inputs.Count > 0;
/// <summary>
/// Wrapper to extract data for a single path
/// </summary>
/// <param name="path">File or directory path</param>
private void ExtractPath(string path)
{
// Normalize by getting the full path
path = Path.GetFullPath(path);
Console.WriteLine($"Checking possible path: {path}");
// Check if the file or directory exists
if (File.Exists(path))
{
ExtractFile(path);
}
else if (Directory.Exists(path))
{
foreach (string file in path.SafeEnumerateFiles("*", SearchOption.AllDirectories))
{
ExtractFile(file);
}
}
else
{
Console.WriteLine($"{path} does not exist, skipping...");
}
}
/// <summary>
/// Print information for a single file, if possible
/// </summary>
/// <param name="path">File path</param>
private void ExtractFile(string file)
{
Console.WriteLine($"Attempting to extract all files from {file}");
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Get the extension for certain checks
string extension = Path.GetExtension(file).ToLower().TrimStart('.');
// Get the first 16 bytes for matching
byte[] magic = new byte[16];
try
{
int read = stream.Read(magic, 0, 16);
stream.SeekIfPossible(0, SeekOrigin.Begin);
}
catch (Exception ex)
{
if (Debug) Console.Error.WriteLine(ex);
return;
}
// Get the file type
WrapperType ft = WrapperFactory.GetFileType(magic, extension);
var wrapper = WrapperFactory.CreateWrapper(ft, stream);
// Create the output directory
Directory.CreateDirectory(OutputPath);
// Print the preamble
Console.WriteLine($"Attempting to extract from '{wrapper?.Description() ?? "UNKNOWN"}'");
Console.WriteLine();
switch (wrapper)
{
// 7-zip
case SevenZip sz:
sz.Extract(OutputPath, Debug);
break;
// BFPK archive
case BFPK bfpk:
bfpk.Extract(OutputPath, Debug);
break;
// BSP
case BSP bsp:
bsp.Extract(OutputPath, Debug);
break;
// bzip2
case BZip2 bzip2:
bzip2.Extract(OutputPath, Debug);
break;
// CD-ROM bin file
case CDROM cdrom:
cdrom.Extract(OutputPath, Debug);
break;
// CFB
case CFB cfb:
cfb.Extract(OutputPath, Debug);
break;
// GCF
case GCF gcf:
gcf.Extract(OutputPath, Debug);
break;
// gzip
case GZip gzip:
gzip.Extract(OutputPath, Debug);
break;
// InstallShield Archive V3 (Z)
case InstallShieldArchiveV3 isv3:
isv3.Extract(OutputPath, Debug);
break;
// IS-CAB archive
case InstallShieldCabinet iscab:
iscab.Extract(OutputPath, Debug);
break;
// ISO 9660 volume
case ISO9660 iso9660:
iso9660.Extract(OutputPath, Debug);
break;
// LZ-compressed file, KWAJ variant
case LZKWAJ kwaj:
kwaj.Extract(OutputPath, Debug);
break;
// LZ-compressed file, QBasic variant
case LZQBasic qbasic:
qbasic.Extract(OutputPath, Debug);
break;
// LZ-compressed file, SZDD variant
case LZSZDD szdd:
szdd.Extract(OutputPath, Debug);
break;
// Microsoft Cabinet archive
case MicrosoftCabinet mscab:
mscab.Extract(OutputPath, Debug);
break;
// MoPaQ (MPQ) archive
case MoPaQ mpq:
mpq.Extract(OutputPath, Debug);
break;
// New Executable
case NewExecutable nex:
nex.Extract(OutputPath, Debug);
break;
// PAK
case PAK pak:
pak.Extract(OutputPath, Debug);
break;
// PFF
case PFF pff:
pff.Extract(OutputPath, Debug);
break;
// PKZIP
case PKZIP pkzip:
pkzip.Extract(OutputPath, Debug);
break;
// Portable Executable
case PortableExecutable pex:
pex.Extract(OutputPath, Debug);
break;
// Quantum
case Quantum quantum:
quantum.Extract(OutputPath, Debug);
break;
// RAR
case RAR rar:
rar.Extract(OutputPath, Debug);
break;
// SGA
case SGA sga:
sga.Extract(OutputPath, Debug);
break;
// Tape Archive
case TapeArchive tar:
tar.Extract(OutputPath, Debug);
break;
// VBSP
case VBSP vbsp:
vbsp.Extract(OutputPath, Debug);
break;
// VPK
case VPK vpk:
vpk.Extract(OutputPath, Debug);
break;
// WAD3
case WAD3 wad:
wad.Extract(OutputPath, Debug);
break;
// xz
case XZ xz:
xz.Extract(OutputPath, Debug);
break;
// XZP
case XZP xzp:
xzp.Extract(OutputPath, Debug);
break;
// ZSTD
case ZSTD zstd:
zstd.Extract(OutputPath, Debug);
break;
// Everything else
default:
Console.WriteLine("Not a supported extractable file format, skipping...");
Console.WriteLine();
break;
}
}
/// <summary>
/// Validate the extraction path
/// </summary>
private bool ValidateExtractionPath()
{
// Null or empty output path
if (string.IsNullOrEmpty(OutputPath))
{
Console.WriteLine("Output directory required for extraction!");
Console.WriteLine();
return false;
}
// Malformed output path or invalid location
try
{
OutputPath = Path.GetFullPath(OutputPath);
Directory.CreateDirectory(OutputPath);
}
catch
{
Console.WriteLine("Output directory could not be created!");
Console.WriteLine();
return false;
}
return true;
}
}
}

View File

@@ -1,129 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace ExtractionTool
{
/// <summary>
/// Set of options for the test executable
/// </summary>
internal sealed class Options
{
#region Properties
/// <summary>
/// Enable debug output for relevant operations
/// </summary>
public bool Debug { get; private set; } = false;
/// <summary>
/// Set of input paths to use for operations
/// </summary>
public List<string> InputPaths { get; private set; } = [];
/// <summary>
/// Output path for archive extraction
/// </summary>
public string OutputPath { get; private set; } = string.Empty;
#endregion
/// <summary>
/// Parse commandline arguments into an Options object
/// </summary>
public static Options? ParseOptions(string[] args)
{
// If we have invalid arguments
if (args == null || args.Length == 0)
return null;
// Create an Options object
var options = new Options();
// Parse the options and paths
for (int index = 0; index < args.Length; index++)
{
string arg = args[index];
switch (arg)
{
case "-?":
case "-h":
case "--help":
return null;
case "-d":
case "--debug":
options.Debug = true;
break;
case "-o":
case "--outdir":
options.OutputPath = index + 1 < args.Length ? args[++index] : string.Empty;
break;
default:
options.InputPaths.Add(arg);
break;
}
}
// Validate we have any input paths to work on
if (options.InputPaths.Count == 0)
{
Console.WriteLine("At least one path is required!");
return null;
}
// Validate the output path
bool validPath = ValidateExtractionPath(options);
if (!validPath)
return null;
return options;
}
/// <summary>
/// Display help text
/// </summary>
public static void DisplayHelp()
{
Console.WriteLine("Extraction Tool");
Console.WriteLine();
Console.WriteLine("ExtractionTool.exe <options> file|directory ...");
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine("-?, -h, --help Display this help text and quit");
Console.WriteLine("-d, --debug Enable debug mode");
Console.WriteLine("-o, --outdir [PATH] Set output path for extraction (required)");
}
/// <summary>
/// Validate the extraction path
/// </summary>
private static bool ValidateExtractionPath(Options options)
{
// Null or empty output path
if (string.IsNullOrEmpty(options.OutputPath))
{
Console.WriteLine("Output directory required for extraction!");
Console.WriteLine();
return false;
}
// Malformed output path or invalid location
try
{
options.OutputPath = Path.GetFullPath(options.OutputPath);
Directory.CreateDirectory(options.OutputPath);
}
catch
{
Console.WriteLine("Output directory could not be created!");
Console.WriteLine();
return false;
}
return true;
}
}
}

View File

@@ -1,250 +1,79 @@
using System;
using System.IO;
using SabreTools.IO.Extensions;
using SabreTools.Serialization;
using SabreTools.Serialization.Wrappers;
using System.Collections.Generic;
using ExtractionTool.Features;
using SabreTools.CommandLine;
using SabreTools.CommandLine.Features;
namespace ExtractionTool
{
class Program
public static class Program
{
static void Main(string[] args)
public static void Main(string[] args)
{
#if NET462_OR_GREATER || NETCOREAPP
// Register the codepages
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
#endif
// Get the options from the arguments
var options = Options.ParseOptions(args);
// Create the command set
var mainFeature = new MainFeature();
var commandSet = CreateCommands(mainFeature);
// If we have an invalid state
if (options == null)
// If we have no args, show the help and quit
if (args is null || args.Length == 0)
{
Options.DisplayHelp();
commandSet.OutputAllHelp();
return;
}
// Loop through the input paths
foreach (string inputPath in options.InputPaths)
// Cache the first argument and starting index
string featureName = args[0];
// Try processing the standalone arguments
var topLevel = commandSet.GetTopLevel(featureName);
switch (topLevel)
{
ExtractPath(inputPath, options.OutputPath, options.Debug);
}
}
// Standalone Options
case Help help: help.ProcessArgs(args, 0, commandSet); return;
/// <summary>
/// Wrapper to extract data for a single path
/// </summary>
/// <param name="path">File or directory path</param>
/// <param name="outputDirectory">Output directory path</param>
/// <param name="includeDebug">Enable including debug information</param>
private static void ExtractPath(string path, string outputDirectory, bool includeDebug)
{
// Normalize by getting the full path
path = Path.GetFullPath(path);
Console.WriteLine($"Checking possible path: {path}");
// Check if the file or directory exists
if (File.Exists(path))
{
ExtractFile(path, outputDirectory, includeDebug);
}
else if (Directory.Exists(path))
{
foreach (string file in IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories))
{
ExtractFile(file, outputDirectory, includeDebug);
}
}
else
{
Console.WriteLine($"{path} does not exist, skipping...");
}
}
/// <summary>
/// Print information for a single file, if possible
/// </summary>
private static void ExtractFile(string file, string outputDirectory, bool includeDebug)
{
Console.WriteLine($"Attempting to extract all files from {file}");
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Get the extension for certain checks
string extension = Path.GetExtension(file).ToLower().TrimStart('.');
// Get the first 16 bytes for matching
byte[] magic = new byte[16];
try
{
int read = stream.Read(magic, 0, 16);
stream.Seek(0, SeekOrigin.Begin);
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return;
}
// Get the file type
WrapperType ft = WrapperFactory.GetFileType(magic, extension);
var wrapper = WrapperFactory.CreateWrapper(ft, stream);
// Create the output directory
Directory.CreateDirectory(outputDirectory);
// Print the preamble
Console.WriteLine($"Attempting to extract from '{wrapper?.Description() ?? "UNKNOWN"}'");
Console.WriteLine();
switch (wrapper)
{
// 7-zip
case SevenZip sz:
sz.Extract(outputDirectory, includeDebug);
break;
// BFPK archive
case BFPK bfpk:
bfpk.Extract(outputDirectory, includeDebug);
break;
// BSP
case BSP bsp:
bsp.Extract(outputDirectory, includeDebug);
break;
// bzip2
case BZip2 bzip2:
bzip2.Extract(outputDirectory, includeDebug);
break;
// CFB
case CFB cfb:
cfb.Extract(outputDirectory, includeDebug);
break;
// GCF
case GCF gcf:
gcf.Extract(outputDirectory, includeDebug);
break;
// gzip
case GZip gzip:
gzip.Extract(outputDirectory, includeDebug);
break;
// InstallShield Archive V3 (Z)
case InstallShieldArchiveV3 isv3:
isv3.Extract(outputDirectory, includeDebug);
break;
// IS-CAB archive
case InstallShieldCabinet iscab:
iscab.Extract(outputDirectory, includeDebug);
break;
// LZ-compressed file, KWAJ variant
case LZKWAJ kwaj:
kwaj.Extract(outputDirectory, includeDebug);
break;
// LZ-compressed file, QBasic variant
case LZQBasic qbasic:
qbasic.Extract(outputDirectory, includeDebug);
break;
// LZ-compressed file, SZDD variant
case LZSZDD szdd:
szdd.Extract(outputDirectory, includeDebug);
break;
// Microsoft Cabinet archive
case MicrosoftCabinet mscab:
mscab.Extract(outputDirectory, includeDebug);
break;
// MoPaQ (MPQ) archive
case MoPaQ mpq:
mpq.Extract(outputDirectory, includeDebug);
break;
// New Executable
case NewExecutable nex:
nex.Extract(outputDirectory, includeDebug);
break;
// PAK
case PAK pak:
pak.Extract(outputDirectory, includeDebug);
break;
// PFF
case PFF pff:
pff.Extract(outputDirectory, includeDebug);
break;
// PKZIP
case PKZIP pkzip:
pkzip.Extract(outputDirectory, includeDebug);
break;
// Portable Executable
case PortableExecutable pex:
pex.Extract(outputDirectory, includeDebug);
break;
// Quantum
case Quantum quantum:
quantum.Extract(outputDirectory, includeDebug);
break;
// RAR
case RAR rar:
rar.Extract(outputDirectory, includeDebug);
break;
// SGA
case SGA sga:
sga.Extract(outputDirectory, includeDebug);
break;
// Tape Archive
case TapeArchive tar:
tar.Extract(outputDirectory, includeDebug);
break;
// VBSP
case VBSP vbsp:
vbsp.Extract(outputDirectory, includeDebug);
break;
// VPK
case VPK vpk:
vpk.Extract(outputDirectory, includeDebug);
break;
// WAD3
case WAD3 wad:
wad.Extract(outputDirectory, includeDebug);
break;
// xz
case XZ xz:
xz.Extract(outputDirectory, includeDebug);
break;
// XZP
case XZP xzp:
xzp.Extract(outputDirectory, includeDebug);
break;
// Everything else
// Default Behavior
default:
Console.WriteLine("Not a supported extractable file format, skipping...");
Console.WriteLine();
if (!mainFeature.ProcessArgs(args, 0))
{
commandSet.OutputAllHelp();
return;
}
else if (!mainFeature.VerifyInputs())
{
Console.Error.WriteLine("At least one input is required");
commandSet.OutputAllHelp();
return;
}
mainFeature.Execute();
break;
}
}
/// <summary>
/// Create the command set for the program
/// </summary>
private static CommandSet CreateCommands(MainFeature mainFeature)
{
List<string> header = [
"Extraction Tool",
string.Empty,
"ExtractionTool <options> file|directory ...",
string.Empty,
];
var commandSet = new CommandSet(header);
commandSet.Add(new Help(["-?", "-h", "--help"]));
commandSet.Add(mainFeature.DebugInput);
commandSet.Add(mainFeature.OutputPathInput);
return commandSet;
}
}
}

View File

@@ -0,0 +1,280 @@
using System;
using System.IO;
using System.Text;
using SabreTools.CommandLine;
using SabreTools.CommandLine.Inputs;
using SabreTools.Hashing;
using SabreTools.IO.Extensions;
using SabreTools.Serialization;
using SabreTools.Serialization.Wrappers;
namespace InfoPrint.Features
{
internal sealed class MainFeature : Feature
{
#region Feature Definition
public const string DisplayName = "main";
/// <remarks>Flags are unused</remarks>
private static readonly string[] _flags = [];
/// <remarks>Description is unused</remarks>
private const string _description = "";
#endregion
#region Inputs
private const string _debugName = "debug";
internal readonly FlagInput DebugInput = new(_debugName, ["-d", "--debug"], "Enable debug mode");
private const string _fileOnlyName = "file-only";
internal readonly FlagInput FileOnlyInput = new(_fileOnlyName, ["-f", "--file"], "Print to file only");
private const string _hashName = "hash";
internal readonly FlagInput HashInput = new(_hashName, ["-c", "--hash"], "Output file hashes");
#if NETCOREAPP
private const string _jsonName = "json";
internal readonly FlagInput JsonInput = new(_jsonName, ["-j", "--json"], "Print info as JSON");
#endif
#endregion
/// <summary>
/// Enable debug output for relevant operations
/// </summary>
public bool Debug { get; private set; }
/// <summary>
/// Output information to file only, skip printing to console
/// </summary>
public bool FileOnly { get; private set; }
/// <summary>
/// Print external file hashes
/// </summary>
public bool Hash { get; private set; }
#if NETCOREAPP
/// <summary>
/// Enable JSON output
/// </summary>
public bool Json { get; private set; }
#endif
public MainFeature()
: base(DisplayName, _flags, _description)
{
RequiresInputs = true;
Add(DebugInput);
Add(HashInput);
Add(FileOnlyInput);
#if NETCOREAPP
Add(JsonInput);
#endif
}
/// <inheritdoc/>
public override bool Execute()
{
// Get the options from the arguments
Debug = GetBoolean(_debugName);
Hash = GetBoolean(_hashName);
FileOnly = GetBoolean(_fileOnlyName);
#if NETCOREAPP
Json = GetBoolean(_jsonName);
#endif
// Loop through the input paths
for (int i = 0; i < Inputs.Count; i++)
{
string arg = Inputs[i];
PrintPathInfo(arg);
}
return true;
}
/// <inheritdoc/>
public override bool VerifyInputs() => Inputs.Count > 0;
/// <summary>
/// Wrapper to print information for a single path
/// </summary>
/// <param name="path">File or directory path</param>
private void PrintPathInfo(string path)
{
Console.WriteLine($"Checking possible path: {path}");
// Check if the file or directory exists
if (File.Exists(path))
{
PrintFileInfo(path);
}
else if (Directory.Exists(path))
{
foreach (string file in path.SafeEnumerateFiles("*", SearchOption.AllDirectories))
{
PrintFileInfo(file);
}
}
else
{
Console.WriteLine($"{path} does not exist, skipping...");
}
}
/// <summary>
/// Print information for a single file, if possible
/// </summary>
/// <param name="file">File path</param>
private void PrintFileInfo(string file)
{
Console.WriteLine($"Attempting to print info for {file}");
// Get the base info output name
string filenameBase = $"info-{DateTime.Now:yyyy-MM-dd_HHmmss.ffff}";
// If we have the hash flag
if (Hash)
{
var hashBuilder = PrintHashInfo(file);
if (hashBuilder is not null)
{
// Create the output data
string hashData = hashBuilder.ToString();
// Write the output data
using var hsw = new StreamWriter(File.OpenWrite($"{filenameBase}.hashes"));
hsw.WriteLine(hashData);
hsw.Flush();
}
}
try
{
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Read the first 8 bytes
byte[] magic = stream.PeekBytes(8);
// Get the file type
string extension = Path.GetExtension(file).TrimStart('.');
WrapperType ft = WrapperFactory.GetFileType(magic ?? [], extension);
// Print out the file format
Console.WriteLine($"File format found: {ft}");
// Setup the wrapper to print
var wrapper = WrapperFactory.CreateWrapper(ft, stream);
// If we don't have a wrapper
if (wrapper is null)
{
Console.WriteLine($"Either {ft} is not supported or something went wrong during parsing!");
Console.WriteLine();
return;
}
#if NETCOREAPP
// If we have the JSON flag
if (Json)
{
// Create the output data
string serializedData = wrapper.ExportJSON();
// Write the output data
using var jsw = new StreamWriter(File.OpenWrite($"{filenameBase}.json"));
jsw.WriteLine(serializedData);
jsw.Flush();
}
#endif
// Create the output data
var builder = wrapper.ExportStringBuilder();
if (builder is null)
{
Console.WriteLine("No item information could be generated");
return;
}
// Only print to console if enabled
if (!FileOnly)
Console.WriteLine(builder);
using var sw = new StreamWriter(File.OpenWrite($"{filenameBase}.txt"));
sw.WriteLine(file);
sw.WriteLine();
sw.WriteLine(builder.ToString());
sw.Flush();
}
catch (Exception ex)
{
Console.WriteLine(Debug ? ex : "[Exception opening file, please try again]");
Console.WriteLine();
}
}
/// <summary>
/// Print hash information for a single file, if possible
/// </summary>
/// <param name="file">File path</param>
/// <returns>StringBuilder representing the hash information, if possible</returns>
private StringBuilder? PrintHashInfo(string file)
{
// Ignore missing files
if (!File.Exists(file))
return null;
Console.WriteLine($"Attempting to hash {file}, this may take a while...");
try
{
// Get all file hashes for flexibility
var hashes = HashTool.GetFileHashes(file);
if (hashes is null)
{
if (Debug) Console.WriteLine($"Hashes for {file} could not be retrieved");
return null;
}
// Output subset of available hashes
var builder = new StringBuilder();
if (hashes.TryGetValue(HashType.CRC16, out string? crc16) && crc16 is not null)
builder.AppendLine($"CRC-16 checksum: {crc16}");
if (hashes.TryGetValue(HashType.CRC32, out string? crc32) && crc32 is not null)
builder.AppendLine($"CRC-32 checksum: {crc32}");
if (hashes.TryGetValue(HashType.CRC64, out string? crc64) && crc64 is not null)
builder.AppendLine($"CRC-64 checksum: {crc64}");
if (hashes.TryGetValue(HashType.MD2, out string? md2) && md2 is not null)
builder.AppendLine($"MD2 hash: {md2}");
if (hashes.TryGetValue(HashType.MD4, out string? md4) && md4 is not null)
builder.AppendLine($"MD4 hash: {md4}");
if (hashes.TryGetValue(HashType.MD5, out string? md5) && md5 is not null)
builder.AppendLine($"MD5 hash: {md5}");
if (hashes.TryGetValue(HashType.RIPEMD128, out string? ripemd128) && ripemd128 is not null)
builder.AppendLine($"RIPEMD-128 hash: {ripemd128}");
if (hashes.TryGetValue(HashType.RIPEMD160, out string? ripemd160) && ripemd160 is not null)
builder.AppendLine($"RIPEMD-160 hash: {ripemd160}");
if (hashes.TryGetValue(HashType.SHA1, out string? sha1) && sha1 is not null)
builder.AppendLine($"SHA-1 hash: {sha1}");
if (hashes.TryGetValue(HashType.SHA256, out string? sha256) && sha256 is not null)
builder.AppendLine($"SHA-256 hash: {sha256}");
if (hashes.TryGetValue(HashType.SHA384, out string? sha384) && sha384 is not null)
builder.AppendLine($"SHA-384 hash: {sha384}");
if (hashes.TryGetValue(HashType.SHA512, out string? sha512) && sha512 is not null)
builder.AppendLine($"SHA-512 hash: {sha512}");
return builder;
}
catch (Exception ex)
{
Console.WriteLine(Debug ? ex : "[Exception opening file, please try again]");
return null;
}
}
}
}

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
<OutputType>Exe</OutputType>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
@@ -10,7 +10,7 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>2.0.1</Version>
<Version>2.2.1</Version>
</PropertyGroup>
<!-- Support All Frameworks -->
@@ -20,11 +20,11 @@
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
</PropertyGroup>
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
@@ -32,8 +32,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.IO" Version="[1.7.5]" />
<PackageReference Include="SabreTools.Hashing" Version="[1.5.0]" />
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
<PackageReference Include="SabreTools.Hashing" Version="[1.6.0]" />
<PackageReference Include="SabreTools.IO" Version="[1.9.0]" />
</ItemGroup>
</Project>

View File

@@ -1,141 +0,0 @@
using System;
using System.Collections.Generic;
namespace InfoPrint
{
/// <summary>
/// Set of options for the test executable
/// </summary>
internal sealed class Options
{
#region Properties
/// <summary>
/// Enable debug output for relevant operations
/// </summary>
public bool Debug { get; private set; } = false;
/// <summary>
/// Output information to file only, skip printing to console
/// </summary>
public bool FileOnly { get; private set; } = false;
/// <summary>
/// Print external file hashes
/// </summary>
public bool Hash { get; private set; } = false;
/// <summary>
/// Set of input paths to use for operations
/// </summary>
public List<string> InputPaths { get; private set; } = [];
#if NETCOREAPP
/// <summary>
/// Enable JSON output
/// </summary>
public bool Json { get; private set; } = false;
#endif
#endregion
/// <summary>
/// Parse commandline arguments into an Options object
/// </summary>
public static Options? ParseOptions(string[] args)
{
// If we have invalid arguments
if (args == null || args.Length == 0)
return null;
// Create an Options object
var options = new Options();
// Parse the features
int index = 0;
for (; index < args.Length; index++)
{
string arg = args[index];
bool featureFound = false;
switch (arg)
{
case "-?":
case "-h":
case "--help":
return null;
default:
break;
}
// If the flag wasn't a feature
if (!featureFound)
break;
}
// Parse the options and paths
for (; index < args.Length; index++)
{
string arg = args[index];
switch (arg)
{
case "-d":
case "--debug":
options.Debug = true;
break;
case "-c":
case "--hash":
options.Hash = true;
break;
case "-f":
case "--file":
options.FileOnly = true;
break;
case "-j":
case "--json":
#if NETCOREAPP
options.Json = true;
#else
Console.WriteLine("JSON output not available in .NET Framework");
#endif
break;
default:
options.InputPaths.Add(arg);
break;
}
}
// Validate we have any input paths to work on
if (options.InputPaths.Count == 0)
{
Console.WriteLine("At least one path is required!");
return null;
}
return options;
}
/// <summary>
/// Display help text
/// </summary>
public static void DisplayHelp()
{
Console.WriteLine("Information Printing Program");
Console.WriteLine();
Console.WriteLine("InfoPrint <options> file|directory ...");
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine("-?, -h, --help Display this help text and quit");
Console.WriteLine("-d, --debug Enable debug mode");
Console.WriteLine("-c, --hash Output file hashes");
Console.WriteLine("-f, --file Print to file only");
#if NETCOREAPP
Console.WriteLine("-j, --json Print info as JSON");
#endif
}
}
}

View File

@@ -1,10 +1,8 @@
using System;
using System.IO;
using System.Text;
using SabreTools.Hashing;
using SabreTools.IO.Extensions;
using SabreTools.Serialization;
using SabreTools.Serialization.Wrappers;
using System.Collections.Generic;
using InfoPrint.Features;
using SabreTools.CommandLine;
using SabreTools.CommandLine.Features;
namespace InfoPrint
{
@@ -12,199 +10,69 @@ namespace InfoPrint
{
public static void Main(string[] args)
{
// Get the options from the arguments
var options = Options.ParseOptions(args);
// Create the command set
var mainFeature = new MainFeature();
var commandSet = CreateCommands(mainFeature);
// If we have an invalid state
if (options == null)
// If we have no args, show the help and quit
if (args is null || args.Length == 0)
{
Options.DisplayHelp();
commandSet.OutputAllHelp();
return;
}
// Loop through the input paths
foreach (string inputPath in options.InputPaths)
// Cache the first argument and starting index
string featureName = args[0];
// Try processing the standalone arguments
var topLevel = commandSet.GetTopLevel(featureName);
switch (topLevel)
{
PrintPathInfo(inputPath, options);
// Standalone Options
case Help help: help.ProcessArgs(args, 0, commandSet); return;
// Default Behavior
default:
if (!mainFeature.ProcessArgs(args, 0))
{
commandSet.OutputAllHelp();
return;
}
else if (!mainFeature.VerifyInputs())
{
Console.Error.WriteLine("At least one input is required");
commandSet.OutputAllHelp();
return;
}
mainFeature.Execute();
break;
}
}
/// <summary>
/// Wrapper to print information for a single path
/// Create the command set for the program
/// </summary>
/// <param name="path">File or directory path</param>
/// <param name="options">User-defined options</param>
private static void PrintPathInfo(string path, Options options)
private static CommandSet CreateCommands(MainFeature mainFeature)
{
Console.WriteLine($"Checking possible path: {path}");
List<string> header = [
"Information Printing Program",
string.Empty,
"InfoPrint <options> file|directory ...",
string.Empty,
];
// Check if the file or directory exists
if (File.Exists(path))
{
PrintFileInfo(path, options);
}
else if (Directory.Exists(path))
{
foreach (string file in IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories))
{
PrintFileInfo(file, options);
}
}
else
{
Console.WriteLine($"{path} does not exist, skipping...");
}
}
/// <summary>
/// Print information for a single file, if possible
/// </summary>
/// <param name="file">File path</param>
/// <param name="options">User-defined options</param>
private static void PrintFileInfo(string file, Options options)
{
Console.WriteLine($"Attempting to print info for {file}");
// Get the base info output name
string filenameBase = $"info-{DateTime.Now:yyyy-MM-dd_HHmmss.ffff}";
// If we have the hash flag
if (options.Hash)
{
var hashBuilder = PrintHashInfo(file, options.Debug);
if (hashBuilder != null)
{
// Create the output data
string hashData = hashBuilder.ToString();
// Write the output data
using var hsw = new StreamWriter(File.OpenWrite($"{filenameBase}.hashes"));
hsw.WriteLine(hashData);
hsw.Flush();
}
}
try
{
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// Read the first 8 bytes
byte[]? magic = stream.ReadBytes(8);
stream.Seek(0, SeekOrigin.Begin);
// Get the file type
string extension = Path.GetExtension(file).TrimStart('.');
WrapperType ft = WrapperFactory.GetFileType(magic ?? [], extension);
// Print out the file format
Console.WriteLine($"File format found: {ft}");
// Setup the wrapper to print
var wrapper = WrapperFactory.CreateWrapper(ft, stream);
// If we don't have a wrapper
if (wrapper == null)
{
Console.WriteLine($"Either {ft} is not supported or something went wrong during parsing!");
Console.WriteLine();
return;
}
var commandSet = new CommandSet(header);
commandSet.Add(new Help(["-?", "-h", "--help"]));
commandSet.Add(mainFeature.DebugInput);
commandSet.Add(mainFeature.HashInput);
commandSet.Add(mainFeature.FileOnlyInput);
#if NETCOREAPP
// If we have the JSON flag
if (options.Json)
{
// Create the output data
string serializedData = wrapper.ExportJSON();
// Write the output data
using var jsw = new StreamWriter(File.OpenWrite($"{filenameBase}.json"));
jsw.WriteLine(serializedData);
jsw.Flush();
}
commandSet.Add(mainFeature.JsonInput);
#endif
// Create the output data
var builder = wrapper.ExportStringBuilder();
if (builder == null)
{
Console.WriteLine("No item information could be generated");
return;
}
// Only print to console if enabled
if (!options.FileOnly)
Console.WriteLine(builder);
using var sw = new StreamWriter(File.OpenWrite($"{filenameBase}.txt"));
sw.WriteLine(file);
sw.WriteLine();
sw.WriteLine(builder.ToString());
sw.Flush();
}
catch (Exception ex)
{
Console.WriteLine(options.Debug ? ex : "[Exception opening file, please try again]");
Console.WriteLine();
}
}
/// <summary>
/// Print hash information for a single file, if possible
/// </summary>
/// <param name="file">File path</param>
/// <param name="debug">Enable debug output</param>
/// <returns>StringBuilder representing the hash information, if possible</returns>
private static StringBuilder? PrintHashInfo(string file, bool debug)
{
// Ignore missing files
if (!File.Exists(file))
return null;
Console.WriteLine($"Attempting to hash {file}, this may take a while...");
try
{
// Get all file hashes for flexibility
var hashes = HashTool.GetFileHashes(file);
if (hashes == null)
{
if (debug) Console.WriteLine($"Hashes for {file} could not be retrieved");
return null;
}
// Output subset of available hashes
var builder = new StringBuilder();
if (hashes.TryGetValue(HashType.CRC16, out string? crc16) && crc16 != null)
builder.AppendLine($"CRC-16 checksum: {crc16}");
if (hashes.TryGetValue(HashType.CRC32, out string? crc32) && crc32 != null)
builder.AppendLine($"CRC-32 checksum: {crc32}");
if (hashes.TryGetValue(HashType.MD2, out string? md2) && md2 != null)
builder.AppendLine($"MD2 hash: {md2}");
if (hashes.TryGetValue(HashType.MD4, out string? md4) && md4 != null)
builder.AppendLine($"MD4 hash: {md4}");
if (hashes.TryGetValue(HashType.MD5, out string? md5) && md5 != null)
builder.AppendLine($"MD5 hash: {md5}");
if (hashes.TryGetValue(HashType.RIPEMD128, out string? ripemd128) && ripemd128 != null)
builder.AppendLine($"RIPEMD-128 hash: {ripemd128}");
if (hashes.TryGetValue(HashType.RIPEMD160, out string? ripemd160) && ripemd160 != null)
builder.AppendLine($"RIPEMD-160 hash: {ripemd160}");
if (hashes.TryGetValue(HashType.SHA1, out string? sha1) && sha1 != null)
builder.AppendLine($"SHA-1 hash: {sha1}");
if (hashes.TryGetValue(HashType.SHA256, out string? sha256) && sha256 != null)
builder.AppendLine($"SHA-256 hash: {sha256}");
if (hashes.TryGetValue(HashType.SHA384, out string? sha384) && sha384 != null)
builder.AppendLine($"SHA-384 hash: {sha384}");
if (hashes.TryGetValue(HashType.SHA512, out string? sha512) && sha512 != null)
builder.AppendLine($"SHA-512 hash: {sha512}");
return builder;
}
catch (Exception ex)
{
Console.WriteLine(debug ? ex : "[Exception opening file, please try again]");
return null;
}
return commandSet;
}
}
}

View File

@@ -9,7 +9,7 @@ Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTo
The following non-project libraries (or ports thereof) are used for file handling:
- [GrindCore.SharpCompress](https://github.com/Nanook/GrindCore.SharpCompress) - Common archive format extraction
- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MoPaQ extraction [Unused in .NET Framework 2.0/3.5/4.0 and non-Windows builds due to Windows-specific libraries]
- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MoPaQ extraction [Unused in non-Windows builds due to Windows-specific libraries]
The following projects have influenced this library:
@@ -30,7 +30,7 @@ For the latest WIP build here: [Rolling Release](https://github.com/SabreTools/S
InfoPrint <options> file|directory ...
Options:
-?, -h, --help Display this help text and quit
-?, -h, --help Display this help text
-d, --debug Enable debug mode
-c, --hash Output file hashes
-f, --file Print to file only
@@ -42,10 +42,10 @@ Options:
**ExtractionTool** is a reference implementation for the extraction features of the library, packaged as a standalone executable for all supported platforms. It will attempt to detect and extract many supported file types. See the table below for supported extraction functionality.
```text
ExtractionTool.exe <options> file|directory ...
ExtractionTool <options> file|directory ...
Options:
-?, -h, --help Display this help text and quit
-?, -h, --help Display this help text
-d, --debug Enable debug mode
-o, --outdir [PATH] Set output path for extraction (required)
```
@@ -55,7 +55,7 @@ Options:
| 7-zip archive | .NET Framework 4.6.2 and greater |
| BFPK custom archive format | |
| bzip2 archive | .NET Framework 4.6.2 and greater |
| Compound File Binary (CFB) | Only CFB common pieces extractable. .NET Framework 4.0 and greater |
| Compound File Binary (CFB) | Only CFB common pieces extractable |
| gzip archive | |
| Half-Life Game Cache File (GCF) | |
| Half-Life Level (BSP) | |
@@ -66,7 +66,7 @@ Options:
| InstallShield CAB | |
| Microsoft cabinet file | Does not support LZX or Quantum compression |
| Microsoft LZ-compressed files | KWAJ, QBasic, and SZDD variants |
| MoPaQ game data archive (MPQ) | Windows only. .NET Framework 4.5.2 and above |
| MoPaQ game data archive (MPQ) | Windows only |
| New Exectuable | Embedded archives and executables in the overlay and Wise installer |
| NovaLogic Game Archive Format (PFF) | |
| PKZIP and derived files (ZIP, etc.) | .NET Framework 4.6.2 and greater |
@@ -99,8 +99,8 @@ Below is a table representing the various non-conversion interfaces that are imp
| Interface Name | Purpose |
| --- | --- |
| `SabreTools.Data.Printers.IPrinter<TModel>` | Provides a formatted output for a `TModel` |
| `SabreTools.Serialization.Wrappers.IExtractable` | Marks a wrapper as able to be extracted |
| `SabreTools.Serialization.Wrappers.IPrintable` | Marks a wrapper as able to print model information |
| `SabreTools.Serialization.Wrappers.IWrapper` | Represents an item with a description and JSON serializable state, allowing for extensions |
| `SabreTools.Serialization.Wrappers.IWrapper<TModel>` | Wraps a model with source data, allowing for extensions |
@@ -114,7 +114,6 @@ Below is a table of all namespaces within the library and what they represent
| `SabreTools.Data.Extensions` | Extension methods related to models |
| `SabreTools.Data.Models` | Models representing different file and structure types |
| `SabreTools.Data.ObjectIdentifier` | Object Identifier (OID) parsing |
| `SabreTools.Data.Printers` | Export model information in a formatted manner |
| `SabreTools.Serialization.CrossModel` | Convert between models; mainly used for metadata files converting to and from a common, `Dictionary`-based model |
| `SabreTools.Serialization.Interfaces` | Interfaces used commonly throughout the library |
| `SabreTools.Serialization.Readers` | Convert from external sources to models |

View File

@@ -15,7 +15,7 @@ namespace SabreTools.Serialization.Test.CrossModel
Data.Models.ArchiveDotOrg.Files files = Build();
// Serialize to generic model
SabreTools.Data.Models.Metadata.MetadataFile? metadata = serializer.Serialize(files);
Data.Models.Metadata.MetadataFile? metadata = serializer.Serialize(files);
Assert.NotNull(metadata);
// Serialize back to original model
@@ -171,4 +171,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", file.Width);
}
}
}
}

View File

@@ -109,4 +109,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", row.FileIsAvailable);
}
}
}
}

View File

@@ -27,6 +27,7 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
[Fact]
@@ -51,6 +52,7 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
/// <summary>
@@ -97,7 +99,9 @@ namespace SabreTools.Serialization.Test.CrossModel
{
Name = "XXXXXX",
Size = "XXXXXX",
CRC16 = "XXXXXX",
CRC = "XXXXXX",
CRC64 = "XXXXXX",
MD2 = "XXXXXX",
MD4 = "XXXXXX",
MD5 = "XXXXXX",
@@ -207,6 +211,7 @@ namespace SabreTools.Serialization.Test.CrossModel
: new Data.Models.ClrMamePro.Machine();
gameBase.Name = "XXXXXX";
gameBase.Description = "XXXXXX";
gameBase.DriverStatus = "XXXXXX";
gameBase.Year = "XXXXXX";
gameBase.Manufacturer = "XXXXXX";
gameBase.Category = "XXXXXX";
@@ -227,10 +232,16 @@ namespace SabreTools.Serialization.Test.CrossModel
gameBase.DipSwitch = [dipswitch];
gameBase.Driver = driver;
var info = new Data.Models.ClrMamePro.Info
{
Source = ["XXXXXX"],
};
return new Data.Models.ClrMamePro.MetadataFile
{
ClrMamePro = cmp,
Game = [gameBase],
Info = info,
};
}
@@ -265,6 +276,7 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.NotNull(gb);
Assert.Equal("XXXXXX", gb.Name);
Assert.Equal("XXXXXX", gb.Description);
// Assert.Equal("XXXXXX", gb.DriverStatus); // TODO: Needs metadata mapping
Assert.Equal("XXXXXX", gb.Year);
Assert.Equal("XXXXXX", gb.Manufacturer);
Assert.Equal("XXXXXX", gb.Category);
@@ -350,7 +362,9 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.NotNull(rom);
Assert.Equal("XXXXXX", rom.Name);
Assert.Equal("XXXXXX", rom.Size);
Assert.Equal("XXXXXX", rom.CRC16);
Assert.Equal("XXXXXX", rom.CRC);
Assert.Equal("XXXXXX", rom.CRC64);
Assert.Equal("XXXXXX", rom.MD2);
Assert.Equal("XXXXXX", rom.MD4);
Assert.Equal("XXXXXX", rom.MD5);
@@ -497,5 +511,16 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", driver.PaletteSize);
Assert.Equal("XXXXXX", driver.Blit);
}
/// <summary>
/// Validate a ClrMamePro
/// </summary>
private static void Validate(Data.Models.ClrMamePro.Info? info)
{
Assert.NotNull(info);
Assert.NotNull(info.Source);
string source = Assert.Single(info.Source);
Assert.Equal("XXXXXX", source);
}
}
}
}

View File

@@ -108,4 +108,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", rom.Date);
}
}
}
}

View File

@@ -63,4 +63,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", row.Size);
}
}
}
}

View File

@@ -1,6 +1,6 @@
using SabreTools.Serialization.CrossModel;
using System;
using SabreTools.Hashing;
using SabreTools.Serialization.CrossModel;
using Xunit;
namespace SabreTools.Serialization.Test.CrossModel
@@ -219,6 +219,7 @@ namespace SabreTools.Serialization.Test.CrossModel
/// </summary>
private static Data.Models.Hashfile.Hashfile Build(HashType hashType)
{
#pragma warning disable IDE0072
return hashType switch
{
HashType.CRC32 => new Data.Models.Hashfile.Hashfile { SFV = [new Data.Models.Hashfile.SFV { File = "XXXXXX", Hash = "XXXXXX" }] },
@@ -230,8 +231,9 @@ namespace SabreTools.Serialization.Test.CrossModel
HashType.SHA384 => new Data.Models.Hashfile.Hashfile { SHA384 = [new Data.Models.Hashfile.SHA384 { Hash = "XXXXXX", File = "XXXXXX" }] },
HashType.SHA512 => new Data.Models.Hashfile.Hashfile { SHA512 = [new Data.Models.Hashfile.SHA512 { Hash = "XXXXXX", File = "XXXXXX" }] },
HashType.SpamSum => new Data.Models.Hashfile.Hashfile { SpamSum = [new Data.Models.Hashfile.SpamSum { Hash = "XXXXXX", File = "XXXXXX" }] },
_ => throw new ArgumentOutOfRangeException(),
_ => throw new ArgumentOutOfRangeException(nameof(hashType)),
};
#pragma warning restore IDE0072
}
/// <summary>
@@ -324,4 +326,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", spamsum.File);
}
}
}
}

View File

@@ -125,4 +125,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.True(row.NoGoodDumpKnown);
}
}
}
}

View File

@@ -876,4 +876,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", ramoption.Content);
}
}
}
}

View File

@@ -150,7 +150,9 @@ namespace SabreTools.Serialization.Test.CrossModel
{
Name = "XXXXXX",
Size = "XXXXXX",
CRC16 = "XXXXXX",
CRC = "XXXXXX",
CRC64 = "XXXXXX",
MD2 = "XXXXXX",
MD4 = "XXXXXX",
MD5 = "XXXXXX",
@@ -464,7 +466,9 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.NotNull(rom);
Assert.Equal("XXXXXX", rom.Name);
Assert.Equal("XXXXXX", rom.Size);
Assert.Equal("XXXXXX", rom.CRC16);
Assert.Equal("XXXXXX", rom.CRC);
Assert.Equal("XXXXXX", rom.CRC64);
Assert.Equal("XXXXXX", rom.MD2);
Assert.Equal("XXXXXX", rom.MD4);
Assert.Equal("XXXXXX", rom.MD5);
@@ -568,4 +572,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", softwarelist.Filter);
}
}
}
}

View File

@@ -870,4 +870,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", ramoption.Content);
}
}
}
}

View File

@@ -870,4 +870,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", ramoption.Content);
}
}
}
}

View File

@@ -448,4 +448,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", image.Height);
}
}
}
}

View File

@@ -82,7 +82,7 @@ namespace SabreTools.Serialization.Test.CrossModel
Original = original,
Rom = sccpluscart,
};
var software = new Data.Models.OpenMSX.Software
{
Title = "XXXXXX",
@@ -154,4 +154,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", rombase.Remark);
}
}
}
}

View File

@@ -151,4 +151,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", rom.MergeName);
}
}
}
}

View File

@@ -180,4 +180,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", row.Status);
}
}
}
}

View File

@@ -308,4 +308,4 @@ namespace SabreTools.Serialization.Test.CrossModel
Assert.Equal("XXXXXX", dipvalue.Default);
}
}
}
}

View File

@@ -3,6 +3,7 @@ using SabreTools.Data.Extensions;
using SabreTools.Data.Models.ASN1;
using Xunit;
#pragma warning disable IDE0230 // Use UTF-8 string literal
namespace SabreTools.Serialization.Test.Extensions
{
public class TypeLengthValueTests
@@ -31,7 +32,7 @@ namespace SabreTools.Serialization.Test.Extensions
public void Format_InvalidConstructed()
{
string expected = "Type: V_ASN1_OBJECT, V_ASN1_CONSTRUCTED, Length: 1, Value: [INVALID DATA TYPE]";
var tlv = new Data.Models.ASN1.TypeLengthValue { Type = ASN1Type.V_ASN1_OBJECT | ASN1Type.V_ASN1_CONSTRUCTED, Length = 1, Value = (object?)false };
var tlv = new Data.Models.ASN1.TypeLengthValue { Type = ASN1Type.V_ASN1_OBJECT | ASN1Type.V_ASN1_CONSTRUCTED, Length = 1, Value = false };
string actual = tlv.Format();
Assert.Equal(expected, actual);
}
@@ -50,7 +51,7 @@ namespace SabreTools.Serialization.Test.Extensions
public void Format_InvalidDataType()
{
string expected = "Type: V_ASN1_OBJECT, Length: 1, Value: [INVALID DATA TYPE]";
var tlv = new Data.Models.ASN1.TypeLengthValue { Type = ASN1Type.V_ASN1_OBJECT, Length = 1, Value = (object?)false };
var tlv = new Data.Models.ASN1.TypeLengthValue { Type = ASN1Type.V_ASN1_OBJECT, Length = 1, Value = false };
string actual = tlv.Format();
Assert.Equal(expected, actual);
}
@@ -210,4 +211,4 @@ namespace SabreTools.Serialization.Test.Extensions
#endregion
}
}
}

View File

@@ -15,7 +15,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
public void ASN1Notation_AlwaysNull()
{
ulong[]? values = null;
string? actual = Parser.ParseOIDToASN1Notation(values);
string? actual = Parser.ParseOIDToASN1Notation(values);
Assert.Null(actual);
}
@@ -27,7 +27,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
public void DotNotation_NullValues_Null()
{
ulong[]? values = null;
string? actual = Parser.ParseOIDToDotNotation(values);
string? actual = Parser.ParseOIDToDotNotation(values);
Assert.Null(actual);
}
@@ -35,7 +35,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
public void DotNotation_EmptyValues_Null()
{
ulong[]? values = [];
string? actual = Parser.ParseOIDToDotNotation(values);
string? actual = Parser.ParseOIDToDotNotation(values);
Assert.Null(actual);
}
@@ -44,7 +44,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
{
string expected = "0.1.2.3";
ulong[]? values = [0, 1, 2, 3];
string? actual = Parser.ParseOIDToDotNotation(values);
string? actual = Parser.ParseOIDToDotNotation(values);
Assert.Equal(expected, actual);
}
@@ -56,7 +56,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
public void ModifiedOIDIRI_NullValues_Null()
{
ulong[]? values = null;
string? actual = Parser.ParseOIDToModifiedOIDIRI(values);
string? actual = Parser.ParseOIDToModifiedOIDIRI(values);
Assert.Null(actual);
}
@@ -64,7 +64,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
public void ModifiedOIDIRI_EmptyValues_Null()
{
ulong[]? values = [];
string? actual = Parser.ParseOIDToModifiedOIDIRI(values);
string? actual = Parser.ParseOIDToModifiedOIDIRI(values);
Assert.Null(actual);
}
@@ -73,7 +73,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
{
string expected = "/ITU-T/[question]/2/3";
ulong[]? values = [0, 1, 2, 3];
string? actual = Parser.ParseOIDToModifiedOIDIRI(values);
string? actual = Parser.ParseOIDToModifiedOIDIRI(values);
Assert.Equal(expected, actual);
}
@@ -85,7 +85,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
public void OIDIRI_NullValues_Null()
{
ulong[]? values = null;
string? actual = Parser.ParseOIDToOIDIRINotation(values);
string? actual = Parser.ParseOIDToOIDIRINotation(values);
Assert.Null(actual);
}
@@ -93,7 +93,7 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
public void OIDIRI_EmptyValues_Null()
{
ulong[]? values = [];
string? actual = Parser.ParseOIDToOIDIRINotation(values);
string? actual = Parser.ParseOIDToOIDIRINotation(values);
Assert.Null(actual);
}
@@ -102,10 +102,10 @@ namespace SabreTools.Serialization.Test.ObjectIdentifier
{
string expected = "/ITU-T/1/2/3";
ulong[]? values = [0, 1, 2, 3];
string? actual = Parser.ParseOIDToOIDIRINotation(values);
string? actual = Parser.ParseOIDToOIDIRINotation(values);
Assert.Equal(expected, actual);
}
#endregion
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -149,4 +149,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -1,73 +1,73 @@
using System.IO;
using System.Linq;
using SabreTools.Serialization.Readers;
using Xunit;
namespace SabreTools.Serialization.Test.Readers
{
public class AppPkgHeaderTests
{
[Fact]
public void NullArray_Null()
{
byte[]? data = null;
int offset = 0;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void EmptyArray_Null()
{
byte[]? data = [];
int offset = 0;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void InvalidArray_Null()
{
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
int offset = 0;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void NullStream_Null()
{
Stream? data = null;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void EmptyStream_Null()
{
Stream? data = new MemoryStream([]);
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void InvalidStream_Null()
{
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
}
}
using System.IO;
using System.Linq;
using SabreTools.Serialization.Readers;
using Xunit;
namespace SabreTools.Serialization.Test.Readers
{
public class AppPkgHeaderTests
{
[Fact]
public void NullArray_Null()
{
byte[]? data = null;
int offset = 0;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void EmptyArray_Null()
{
byte[]? data = [];
int offset = 0;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void InvalidArray_Null()
{
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
int offset = 0;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void NullStream_Null()
{
Stream? data = null;
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void EmptyStream_Null()
{
Stream? data = new MemoryStream([]);
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void InvalidStream_Null()
{
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
var deserializer = new AppPkgHeader();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new ArchiveDotOrg();
var serializer = new SabreTools.Serialization.Writers.ArchiveDotOrg();
var serializer = new Serialization.Writers.ArchiveDotOrg();
// Build the data
Data.Models.ArchiveDotOrg.Files files = Build();
@@ -237,4 +237,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", file.Width);
}
}
}
}

View File

@@ -76,7 +76,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new AttractMode();
var serializer = new SabreTools.Serialization.Writers.AttractMode();
var serializer = new Serialization.Writers.AttractMode();
// Build the data
Data.Models.AttractMode.MetadataFile mf = Build();
@@ -101,7 +101,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new AttractMode();
var serializer = new SabreTools.Serialization.Writers.AttractMode();
var serializer = new Serialization.Writers.AttractMode();
// Build the data
Data.Models.AttractMode.MetadataFile mf = Build();
@@ -168,9 +168,9 @@ namespace SabreTools.Serialization.Test.Readers
{
Assert.NotNull(header);
if (longHeader)
Assert.True(SabreTools.Serialization.Writers.AttractMode.HeaderArrayWithRomname.SequenceEqual(header));
Assert.True(Serialization.Writers.AttractMode.HeaderArrayWithRomname.SequenceEqual(header));
else
Assert.True(SabreTools.Serialization.Writers.AttractMode.HeaderArrayWithoutRomname.SequenceEqual(header));
Assert.True(Serialization.Writers.AttractMode.HeaderArrayWithoutRomname.SequenceEqual(header));
}
/// <summary>
@@ -214,4 +214,4 @@ namespace SabreTools.Serialization.Test.Readers
}
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new ClrMamePro();
var serializer = new SabreTools.Serialization.Writers.ClrMamePro();
var serializer = new Serialization.Writers.ClrMamePro();
// Build the data
Data.Models.ClrMamePro.MetadataFile mf = Build(game: true);
@@ -93,6 +93,7 @@ namespace SabreTools.Serialization.Test.Readers
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
[Fact]
@@ -100,7 +101,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new ClrMamePro();
var serializer = new SabreTools.Serialization.Writers.ClrMamePro();
var serializer = new Serialization.Writers.ClrMamePro();
// Build the data
Data.Models.ClrMamePro.MetadataFile mf = Build(game: true);
@@ -118,6 +119,7 @@ namespace SabreTools.Serialization.Test.Readers
Assert.NotNull(newMf.Game);
var newGame = Assert.Single(newMf.Game);
Validate(newGame);
Validate(newMf.Info);
}
[Fact]
@@ -125,7 +127,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new ClrMamePro();
var serializer = new SabreTools.Serialization.Writers.ClrMamePro();
var serializer = new Serialization.Writers.ClrMamePro();
// Build the data
Data.Models.ClrMamePro.MetadataFile mf = Build(game: false);
@@ -150,7 +152,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new ClrMamePro();
var serializer = new SabreTools.Serialization.Writers.ClrMamePro();
var serializer = new Serialization.Writers.ClrMamePro();
// Build the data
Data.Models.ClrMamePro.MetadataFile mf = Build(game: false);
@@ -214,7 +216,9 @@ namespace SabreTools.Serialization.Test.Readers
{
Name = "XXXXXX",
Size = "XXXXXX",
CRC16 = "XXXXXX",
CRC = "XXXXXX",
CRC64 = "XXXXXX",
MD2 = "XXXXXX",
MD4 = "XXXXXX",
MD5 = "XXXXXX",
@@ -324,6 +328,7 @@ namespace SabreTools.Serialization.Test.Readers
: new Data.Models.ClrMamePro.Machine();
gameBase.Name = "XXXXXX";
gameBase.Description = "XXXXXX";
gameBase.DriverStatus = "XXXXXX";
gameBase.Year = "XXXXXX";
gameBase.Manufacturer = "XXXXXX";
gameBase.Category = "XXXXXX";
@@ -344,10 +349,16 @@ namespace SabreTools.Serialization.Test.Readers
gameBase.DipSwitch = [dipswitch];
gameBase.Driver = driver;
var info = new Data.Models.ClrMamePro.Info
{
Source = ["XXXXXX"],
};
return new Data.Models.ClrMamePro.MetadataFile
{
ClrMamePro = cmp,
Game = [gameBase],
Info = info,
};
}
@@ -382,6 +393,7 @@ namespace SabreTools.Serialization.Test.Readers
Assert.NotNull(gb);
Assert.Equal("XXXXXX", gb.Name);
Assert.Equal("XXXXXX", gb.Description);
// Assert.Equal("XXXXXX", gb.DriverStatus); // TODO: Needs metadata mapping
Assert.Equal("XXXXXX", gb.Year);
Assert.Equal("XXXXXX", gb.Manufacturer);
Assert.Equal("XXXXXX", gb.Category);
@@ -467,7 +479,9 @@ namespace SabreTools.Serialization.Test.Readers
Assert.NotNull(rom);
Assert.Equal("XXXXXX", rom.Name);
Assert.Equal("XXXXXX", rom.Size);
Assert.Equal("XXXXXX", rom.CRC16);
Assert.Equal("XXXXXX", rom.CRC);
Assert.Equal("XXXXXX", rom.CRC64);
Assert.Equal("XXXXXX", rom.MD2);
Assert.Equal("XXXXXX", rom.MD4);
Assert.Equal("XXXXXX", rom.MD5);
@@ -614,5 +628,16 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", driver.PaletteSize);
Assert.Equal("XXXXXX", driver.Blit);
}
/// <summary>
/// Validate a ClrMamePro
/// </summary>
private static void Validate(Data.Models.ClrMamePro.Info? info)
{
Assert.NotNull(info);
Assert.NotNull(info.Source);
string source = Assert.Single(info.Source);
Assert.Equal("XXXXXX", source);
}
}
}
}

View File

@@ -115,4 +115,4 @@ namespace SabreTools.Serialization.Test.Readers
#endregion
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new DosCenter();
var serializer = new SabreTools.Serialization.Writers.DosCenter();
var serializer = new Serialization.Writers.DosCenter();
// Build the data
Data.Models.DosCenter.MetadataFile mf = Build();
@@ -174,4 +174,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX XXXXXX", rom.Date);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new EverdriveSMDB();
var serializer = new SabreTools.Serialization.Writers.EverdriveSMDB();
var serializer = new Serialization.Writers.EverdriveSMDB();
// Build the data
Data.Models.EverdriveSMDB.MetadataFile mf = Build();
@@ -129,4 +129,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", row.Size);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -77,7 +77,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.CRC32);
@@ -101,7 +101,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.MD2);
@@ -125,7 +125,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.MD4);
@@ -149,7 +149,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.MD5);
@@ -173,7 +173,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.SHA1);
@@ -197,7 +197,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.SHA256);
@@ -221,7 +221,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.SHA384);
@@ -245,7 +245,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.SHA512);
@@ -269,7 +269,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Hashfile();
var serializer = new SabreTools.Serialization.Writers.Hashfile();
var serializer = new Serialization.Writers.Hashfile();
// Build the data
Data.Models.Hashfile.Hashfile hf = Build(HashType.SpamSum);
@@ -293,6 +293,7 @@ namespace SabreTools.Serialization.Test.Readers
/// </summary>
private static Data.Models.Hashfile.Hashfile Build(HashType hashType)
{
#pragma warning disable IDE0072
return hashType switch
{
HashType.CRC32 => new Data.Models.Hashfile.Hashfile { SFV = [new Data.Models.Hashfile.SFV { File = "XXXXXX", Hash = "XXXXXX" }] },
@@ -304,8 +305,9 @@ namespace SabreTools.Serialization.Test.Readers
HashType.SHA384 => new Data.Models.Hashfile.Hashfile { SHA384 = [new Data.Models.Hashfile.SHA384 { Hash = "XXXXXX", File = "XXXXXX" }] },
HashType.SHA512 => new Data.Models.Hashfile.Hashfile { SHA512 = [new Data.Models.Hashfile.SHA512 { Hash = "XXXXXX", File = "XXXXXX" }] },
HashType.SpamSum => new Data.Models.Hashfile.Hashfile { SpamSum = [new Data.Models.Hashfile.SpamSum { Hash = "XXXXXX", File = "XXXXXX" }] },
_ => throw new ArgumentOutOfRangeException(),
_ => throw new ArgumentOutOfRangeException(nameof(hashType)),
};
#pragma warning restore IDE0072
}
/// <summary>
@@ -398,4 +400,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", spamsum.File);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -0,0 +1,73 @@
using System.IO;
using System.Linq;
using SabreTools.Serialization.Readers;
using Xunit;
namespace SabreTools.Serialization.Test.Readers
{
public class ISO9660Tests
{
[Fact]
public void NullArray_Null()
{
byte[]? data = null;
int offset = 0;
var deserializer = new ISO9660();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void EmptyArray_Null()
{
byte[]? data = [];
int offset = 0;
var deserializer = new ISO9660();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void InvalidArray_Null()
{
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
int offset = 0;
var deserializer = new ISO9660();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void NullStream_Null()
{
Stream? data = null;
var deserializer = new ISO9660();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void EmptyStream_Null()
{
Stream? data = new MemoryStream([]);
var deserializer = new ISO9660();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void InvalidStream_Null()
{
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
var deserializer = new ISO9660();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -0,0 +1,73 @@
using System.IO;
using System.Linq;
using SabreTools.Serialization.Readers;
using Xunit;
namespace SabreTools.Serialization.Test.Readers
{
public class InstallShieldExecutableTests
{
[Fact]
public void NullArray_Null()
{
byte[]? data = null;
int offset = 0;
var deserializer = new InstallShieldExecutable();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void EmptyArray_Null()
{
byte[]? data = [];
int offset = 0;
var deserializer = new InstallShieldExecutable();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void InvalidArray_Null()
{
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
int offset = 0;
var deserializer = new InstallShieldExecutable();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void NullStream_Null()
{
Stream? data = null;
var deserializer = new InstallShieldExecutable();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void EmptyStream_Null()
{
Stream? data = new MemoryStream([]);
var deserializer = new InstallShieldExecutable();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void InvalidStream_Null()
{
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
var deserializer = new InstallShieldExecutable();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -6,7 +6,7 @@ using Xunit;
namespace SabreTools.Serialization.Test.Readers
{
public class LZQBasicTests
{
[Fact]
public void NullArray_Null()
@@ -71,4 +71,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Listrom();
var serializer = new SabreTools.Serialization.Writers.Listrom();
var serializer = new Serialization.Writers.Listrom();
// Build the data
Data.Models.Listrom.MetadataFile mf = Build();
@@ -264,4 +264,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.True(row.NoGoodDumpKnown);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Listxml();
var serializer = new SabreTools.Serialization.Writers.Listxml();
var serializer = new Serialization.Writers.Listxml();
// Build the data
Data.Models.Listxml.Mame mame = Build(game: true);
@@ -103,7 +103,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Listxml();
var serializer = new SabreTools.Serialization.Writers.Listxml();
var serializer = new Serialization.Writers.Listxml();
// Build the data
Data.Models.Listxml.Mame mame = Build(game: false);
@@ -943,4 +943,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", ramoption.Content);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Logiqx();
var serializer = new SabreTools.Serialization.Writers.Logiqx();
var serializer = new Serialization.Writers.Logiqx();
// Build the data
Data.Models.Logiqx.Datafile df = Build(game: true);
@@ -107,7 +107,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Logiqx();
var serializer = new SabreTools.Serialization.Writers.Logiqx();
var serializer = new Serialization.Writers.Logiqx();
// Build the data
Data.Models.Logiqx.Datafile df = Build(game: false);
@@ -215,7 +215,9 @@ namespace SabreTools.Serialization.Test.Readers
{
Name = "XXXXXX",
Size = "XXXXXX",
CRC16 = "XXXXXX",
CRC = "XXXXXX",
CRC64 = "XXXXXX",
MD2 = "XXXXXX",
MD4 = "XXXXXX",
MD5 = "XXXXXX",
@@ -618,4 +620,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", softwarelist.Filter);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new M1();
var serializer = new SabreTools.Serialization.Writers.M1();
var serializer = new Serialization.Writers.M1();
// Build the data
Data.Models.Listxml.M1 m1 = Build(game: true);
@@ -101,7 +101,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new M1();
var serializer = new SabreTools.Serialization.Writers.M1();
var serializer = new Serialization.Writers.M1();
// Build the data
Data.Models.Listxml.M1 m1 = Build(game: false);
@@ -937,4 +937,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", ramoption.Content);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Mess();
var serializer = new SabreTools.Serialization.Writers.Mess();
var serializer = new Serialization.Writers.Mess();
// Build the data
Data.Models.Listxml.Mess m1 = Build(game: true);
@@ -101,7 +101,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new Mess();
var serializer = new SabreTools.Serialization.Writers.Mess();
var serializer = new Serialization.Writers.Mess();
// Build the data
Data.Models.Listxml.Mess m1 = Build(game: false);
@@ -937,4 +937,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", ramoption.Content);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new OfflineList();
var serializer = new SabreTools.Serialization.Writers.OfflineList();
var serializer = new Serialization.Writers.OfflineList();
// Build the data
Data.Models.OfflineList.Dat dat = Build();
@@ -514,4 +514,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", image.Height);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new OpenMSX();
var serializer = new SabreTools.Serialization.Writers.OpenMSX();
var serializer = new Serialization.Writers.OpenMSX();
// Build the data
Data.Models.OpenMSX.SoftwareDb sdb = Build();
@@ -220,4 +220,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", rombase.Remark);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new RomCenter();
var serializer = new SabreTools.Serialization.Writers.RomCenter();
var serializer = new Serialization.Writers.RomCenter();
// Build the data
Data.Models.RomCenter.MetadataFile mf = Build();
@@ -217,4 +217,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", rom.MergeName);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -76,7 +76,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new SeparatedValue();
var serializer = new SabreTools.Serialization.Writers.SeparatedValue();
var serializer = new Serialization.Writers.SeparatedValue();
// Build the data
Data.Models.SeparatedValue.MetadataFile mf = Build();
@@ -104,7 +104,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new SeparatedValue();
var serializer = new SabreTools.Serialization.Writers.SeparatedValue();
var serializer = new Serialization.Writers.SeparatedValue();
// Build the data
Data.Models.SeparatedValue.MetadataFile mf = Build();
@@ -197,9 +197,9 @@ namespace SabreTools.Serialization.Test.Readers
{
Assert.NotNull(header);
if (longHeader)
Assert.True(SabreTools.Serialization.Writers.SeparatedValue.HeaderArrayExtended.SequenceEqual(header));
Assert.True(Serialization.Writers.SeparatedValue.HeaderArrayExtended.SequenceEqual(header));
else
Assert.True(SabreTools.Serialization.Writers.SeparatedValue.HeaderArrayStandard.SequenceEqual(header));
Assert.True(Serialization.Writers.SeparatedValue.HeaderArrayStandard.SequenceEqual(header));
}
/// <summary>
@@ -233,6 +233,7 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(row.SHA512);
Assert.Null(row.SpamSum);
}
Assert.Equal("XXXXXX", row.Status);
}
@@ -267,6 +268,7 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(row.SHA512);
Assert.Null(row.SpamSum);
}
Assert.NotNull(row.Status); Assert.Empty(row.Status);
}
@@ -302,7 +304,8 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(row.SHA512);
Assert.Null(row.SpamSum);
}
Assert.Equal("XXXXXX", row.Status);
}
}
}
}

View File

@@ -0,0 +1,73 @@
using System.IO;
using System.Linq;
using SabreTools.Serialization.Readers;
using Xunit;
namespace SabreTools.Serialization.Test.Readers
{
public class SkuSisTests
{
[Fact]
public void NullArray_Null()
{
byte[]? data = null;
int offset = 0;
var deserializer = new SkuSis();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void EmptyArray_Null()
{
byte[]? data = [];
int offset = 0;
var deserializer = new SkuSis();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void InvalidArray_Null()
{
byte[]? data = [.. Enumerable.Repeat<byte>(0xFF, 1024)];
int offset = 0;
var deserializer = new SkuSis();
var actual = deserializer.Deserialize(data, offset);
Assert.Null(actual);
}
[Fact]
public void NullStream_Null()
{
Stream? data = null;
var deserializer = new SkuSis();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void EmptyStream_Null()
{
Stream? data = new MemoryStream([]);
var deserializer = new SkuSis();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
[Fact]
public void InvalidStream_Null()
{
Stream? data = new MemoryStream([.. Enumerable.Repeat<byte>(0xFF, 1024)]);
var deserializer = new SkuSis();
var actual = deserializer.Deserialize(data);
Assert.Null(actual);
}
}
}

View File

@@ -75,7 +75,7 @@ namespace SabreTools.Serialization.Test.Readers
{
// Get the serializer and deserializer
var deserializer = new SoftwareList();
var serializer = new SabreTools.Serialization.Writers.SoftwareList();
var serializer = new Serialization.Writers.SoftwareList();
// Build the data
Data.Models.SoftwareList.SoftwareList sl = Build();
@@ -374,4 +374,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Equal("XXXXXX", dipvalue.Default);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -36,4 +36,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

View File

@@ -70,4 +70,4 @@ namespace SabreTools.Serialization.Test.Readers
Assert.Null(actual);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More