diff --git a/Test/FileTypes.cs b/SabreTools.Serialization/Wrappers/WrapperFactory.cs similarity index 64% rename from Test/FileTypes.cs rename to SabreTools.Serialization/Wrappers/WrapperFactory.cs index 66cb8aaf..619130d5 100644 --- a/Test/FileTypes.cs +++ b/SabreTools.Serialization/Wrappers/WrapperFactory.cs @@ -1,65 +1,175 @@ using System; +using System.IO; +using SabreTools.IO.Extensions; using SabreTools.Matching; +using SabreTools.Serialization.Interfaces; -namespace Test +namespace SabreTools.Serialization.Wrappers { - internal static class FileTypes + public static class WrapperFactory { + /// + /// Create an instance of a wrapper based on file type + /// + public static IWrapper? CreateWrapper(WrapperType fileType, Stream? data) + { + switch (fileType) + { + case WrapperType.AACSMediaKeyBlock: return AACSMediaKeyBlock.Create(data); + case WrapperType.BDPlusSVM: return BDPlusSVM.Create(data); + case WrapperType.BFPK: return BFPK.Create(data); + case WrapperType.BSP: return BSP.Create(data); + //case SupportedFileType.BZip2: return BZip2.Create(data); + case WrapperType.CFB: return CFB.Create(data); + case WrapperType.CIA: return CIA.Create(data); + case WrapperType.Executable: return CreateExecutableWrapper(data); + case WrapperType.GCF: return GCF.Create(data); + //case SupportedFileType.GZIP: return GZIP.Create(data); + //case SupportedFileType.IniFile: return IniFile.Create(data); + //case SupportedFileType.InstallShieldArchiveV3: return InstallShieldArchiveV3.Create(data); + case WrapperType.InstallShieldCAB: return InstallShieldCabinet.Create(data); + //case SupportedFileType.LDSCRYPT: return LDSCRYPT.Create(data); + case WrapperType.MicrosoftCAB: return MicrosoftCabinet.Create(data); + //case SupportedFileType.MicrosoftLZ: return MicrosoftLZ.Create(data); + case WrapperType.MoPaQ: return MoPaQ.Create(data); + case WrapperType.N3DS: return N3DS.Create(data); + case WrapperType.NCF: return NCF.Create(data); + case WrapperType.Nitro: return Nitro.Create(data); + case WrapperType.PAK: return PAK.Create(data); + case WrapperType.PFF: return PFF.Create(data); + //case SupportedFileType.PIC: return PIC.Create(data); + //case SupportedFileType.PKZIP: return PKZIP.Create(data); + case WrapperType.PlayJAudioFile: return PlayJAudioFile.Create(data); + //case SupportedFileType.PlayJPlaylist: return PlayJPlaylist.Create(data); + case WrapperType.Quantum: return Quantum.Create(data); + //case SupportedFileType.RAR: return RAR.Create(data); + //case SupportedFileType.RealArcadeInstaller: return RealArcadeInstaller.Create(data); + //case SupportedFileType.RealArcadeMezzanine: return RealArcadeMezzanine.Create(data); + //case SupportedFileType.SevenZip: return SevenZip.Create(data); + //case SupportedFileType.SFFS: return SFFS.Create(data); + case WrapperType.SGA: return SGA.Create(data); + //case SupportedFileType.TapeArchive: return TapeArchive.Create(data); + //case SupportedFileType.Textfile: return Textfile.Create(data); + case WrapperType.VBSP: return VBSP.Create(data); + case WrapperType.VPK: return VPK.Create(data); + case WrapperType.WAD: return WAD.Create(data); + //case SupportedFileType.XZ: return XZ.Create(data); + case WrapperType.XZP: return XZP.Create(data); + default: return null; + } + } + + /// + /// Create an instance of a wrapper based on the executable type + /// + /// Stream data to parse + /// IWrapper representing the executable, null on error + public static IWrapper? CreateExecutableWrapper(Stream? stream) + { + // If we have no stream + if (stream == null) + return null; + + // Try to get an MS-DOS wrapper first + var wrapper = MSDOS.Create(stream); + if (wrapper == null || !(wrapper is MSDOS msdos)) + return null; + + // Check for a valid new executable address + if (msdos.Model.Header?.NewExeHeaderAddr == null || msdos.Model.Header.NewExeHeaderAddr >= stream.Length) + return wrapper; + + // Try to read the executable info + stream.Seek(msdos.Model.Header.NewExeHeaderAddr, SeekOrigin.Begin); + var magic = stream.ReadBytes(4); + + // If we didn't get valid data at the offset + if (magic == null) + { + return wrapper; + } + + // New Executable + else if (magic.StartsWith(Models.NewExecutable.Constants.SignatureBytes)) + { + stream.Seek(0, SeekOrigin.Begin); + return NewExecutable.Create(stream); + } + + // Linear Executable + else if (magic.StartsWith(Models.LinearExecutable.Constants.LESignatureBytes) + || magic.StartsWith(Models.LinearExecutable.Constants.LXSignatureBytes)) + { + stream.Seek(0, SeekOrigin.Begin); + return LinearExecutable.Create(stream); + } + + // Portable Executable + else if (magic.StartsWith(Models.PortableExecutable.Constants.SignatureBytes)) + { + stream.Seek(0, SeekOrigin.Begin); + return PortableExecutable.Create(stream); + } + + // Everything else fails + return null; + } + /// /// Get the supported file type for a magic string /// /// Recommend sending in 16 bytes to check - public static SupportedFileType GetFileType(byte[] magic) + public static WrapperType GetFileType(byte[] magic) { // If we have an invalid magic byte array if (magic == null || magic.Length == 0) - return SupportedFileType.UNKNOWN; + return WrapperType.UNKNOWN; // TODO: For all modelled types, use the constants instead of hardcoded values here #region AACSMediaKeyBlock // Block starting with verify media key record if (magic.StartsWith(new byte?[] { 0x81, 0x00, 0x00, 0x14 })) - return SupportedFileType.AACSMediaKeyBlock; + return WrapperType.AACSMediaKeyBlock; // Block starting with type and version record if (magic.StartsWith(new byte?[] { 0x10, 0x00, 0x00, 0x0C })) - return SupportedFileType.AACSMediaKeyBlock; + return WrapperType.AACSMediaKeyBlock; #endregion #region BDPlusSVM if (magic.StartsWith(new byte?[] { 0x42, 0x44, 0x53, 0x56, 0x4D, 0x5F, 0x43, 0x43 })) - return SupportedFileType.BDPlusSVM; + return WrapperType.BDPlusSVM; #endregion #region BFPK if (magic.StartsWith(new byte?[] { 0x42, 0x46, 0x50, 0x4b })) - return SupportedFileType.BFPK; + return WrapperType.BFPK; #endregion #region BSP if (magic.StartsWith(new byte?[] { 0x1e, 0x00, 0x00, 0x00 })) - return SupportedFileType.BSP; + return WrapperType.BSP; #endregion #region BZip2 if (magic.StartsWith(new byte?[] { 0x42, 0x52, 0x68 })) - return SupportedFileType.BZip2; + return WrapperType.BZip2; #endregion #region CFB if (magic.StartsWith(new byte?[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 })) - return SupportedFileType.CFB; + return WrapperType.CFB; #endregion @@ -73,10 +183,10 @@ namespace Test // DOS MZ executable file format (and descendants) if (magic.StartsWith(new byte?[] { 0x4d, 0x5a })) - return SupportedFileType.Executable; + return WrapperType.Executable; /* - // None of the following are supported in scans yet + // None of the following are supported yet // Executable and Linkable Format if (magic.StartsWith(new byte?[] { 0x7f, 0x45, 0x4c, 0x46 })) @@ -108,14 +218,14 @@ namespace Test #region GCF if (magic.StartsWith(new byte?[] { 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 })) - return SupportedFileType.GCF; + return WrapperType.GCF; #endregion #region GZIP if (magic.StartsWith(new byte?[] { 0x1f, 0x8b })) - return SupportedFileType.GZIP; + return WrapperType.GZIP; #endregion @@ -128,45 +238,45 @@ namespace Test #region InstallShieldArchiveV3 if (magic.StartsWith(new byte?[] { 0x13, 0x5D, 0x65, 0x8C })) - return SupportedFileType.InstallShieldArchiveV3; + return WrapperType.InstallShieldArchiveV3; #endregion #region InstallShieldCAB if (magic.StartsWith(new byte?[] { 0x49, 0x53, 0x63 })) - return SupportedFileType.InstallShieldCAB; + return WrapperType.InstallShieldCAB; #endregion #region LDSCRYPT if (magic.StartsWith(new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 })) - return SupportedFileType.LDSCRYPT; + return WrapperType.LDSCRYPT; #endregion #region MicrosoftCAB if (magic.StartsWith(new byte?[] { 0x4d, 0x53, 0x43, 0x46 })) - return SupportedFileType.MicrosoftCAB; + return WrapperType.MicrosoftCAB; #endregion #region MicrosoftLZ if (magic.StartsWith(new byte?[] { 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33 })) - return SupportedFileType.MicrosoftLZ; + return WrapperType.MicrosoftLZ; #endregion #region MPQ if (magic.StartsWith(new byte?[] { 0x4d, 0x50, 0x51, 0x1a })) - return SupportedFileType.MPQ; + return WrapperType.MoPaQ; if (magic.StartsWith(new byte?[] { 0x4d, 0x50, 0x51, 0x1b })) - return SupportedFileType.MPQ; + return WrapperType.MoPaQ; #endregion @@ -179,7 +289,7 @@ namespace Test #region NCF if (magic.StartsWith(new byte?[] { 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 })) - return SupportedFileType.NCF; + return WrapperType.NCF; #endregion @@ -192,7 +302,7 @@ namespace Test #region PAK if (magic.StartsWith(new byte?[] { 0x50, 0x41, 0x43, 0x4B })) - return SupportedFileType.PAK; + return WrapperType.PAK; #endregion @@ -200,15 +310,15 @@ namespace Test // Version 2 if (magic.StartsWith(new byte?[] { 0x14, 0x00, 0x00, 0x00, 0x50, 0x46, 0x46, 0x32 })) - return SupportedFileType.PFF; + return WrapperType.PFF; // Version 3 if (magic.StartsWith(new byte?[] { 0x14, 0x00, 0x00, 0x00, 0x50, 0x46, 0x46, 0x33 })) - return SupportedFileType.PFF; + return WrapperType.PFF; // Version 4 if (magic.StartsWith(new byte?[] { 0x14, 0x00, 0x00, 0x00, 0x50, 0x46, 0x46, 0x34 })) - return SupportedFileType.PFF; + return WrapperType.PFF; #endregion @@ -216,19 +326,19 @@ namespace Test // PKZIP (Unknown) if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x00, 0x00 })) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // PKZIP if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x03, 0x04 })) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // PKZIP (Empty Archive) if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x05, 0x06 })) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // PKZIP (Spanned Archive) if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x07, 0x08 })) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; #endregion @@ -236,14 +346,14 @@ namespace Test // https://www.iana.org/assignments/media-types/audio/vnd.everad.plj if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B })) - return SupportedFileType.PLJ; + return WrapperType.PlayJAudioFile; #endregion #region Quantum if (magic.StartsWith(new byte?[] { 0x44, 0x53 })) - return SupportedFileType.Quantum; + return WrapperType.Quantum; #endregion @@ -251,11 +361,11 @@ namespace Test // RAR archive version 1.50 onwards if (magic.StartsWith(new byte?[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 })) - return SupportedFileType.RAR; + return WrapperType.RAR; // RAR archive version 5.0 onwards if (magic.StartsWith(new byte?[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 })) - return SupportedFileType.RAR; + return WrapperType.RAR; #endregion @@ -264,19 +374,19 @@ namespace Test // RASGI2.0 // Found in the ".rgs files in IA item "Nova_RealArcadeCD_USA". if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 })) - return SupportedFileType.RealArcadeInstaller; + return WrapperType.RealArcadeInstaller; // XZip2.0 // Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA". if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 })) - return SupportedFileType.RealArcadeMezzanine; + return WrapperType.RealArcadeMezzanine; #endregion #region SevenZip if (magic.StartsWith(new byte?[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c })) - return SupportedFileType.SevenZip; + return WrapperType.SevenZip; #endregion @@ -284,24 +394,24 @@ namespace Test // Found in Redump entry 81756, confirmed to be "StarForce Filesystem" by PiD. if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53 })) - return SupportedFileType.SFFS; + return WrapperType.SFFS; #endregion #region SGA if (magic.StartsWith(new byte?[] { 0x5F, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45 })) - return SupportedFileType.SGA; + return WrapperType.SGA; #endregion #region TapeArchive if (magic.StartsWith(new byte?[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 })) - return SupportedFileType.TapeArchive; + return WrapperType.TapeArchive; if (magic.StartsWith(new byte?[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 })) - return SupportedFileType.TapeArchive; + return WrapperType.TapeArchive; #endregion @@ -311,83 +421,83 @@ namespace Test // HTML if (magic.StartsWith(new byte?[] { 0x3c, 0x68, 0x74, 0x6d, 0x6c })) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // HTML and XML if (magic.StartsWith(new byte?[] { 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45 })) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // InstallShield Compiled Rules if (magic.StartsWith(new byte?[] { 0x61, 0x4C, 0x75, 0x5A })) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Microsoft Office File (old) if (magic.StartsWith(new byte?[] { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 })) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Rich Text File if (magic.StartsWith(new byte?[] { 0x7b, 0x5c, 0x72, 0x74, 0x66, 0x31 })) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Windows Help File if (magic.StartsWith(new byte?[] { 0x3F, 0x5F, 0x03, 0x00 })) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // XML // " /// Get the supported file type for an extension /// /// This is less accurate than a magic string match - public static SupportedFileType GetFileType(string extension) + public static WrapperType GetFileType(string extension) { // If we have an invalid extension if (string.IsNullOrEmpty(extension)) - return SupportedFileType.UNKNOWN; + return WrapperType.UNKNOWN; // Normalize the extension extension = extension.TrimStart('.').Trim(); @@ -401,14 +511,14 @@ namespace Test // HD-DVD if (extension.Equals("aacs", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.AACSMediaKeyBlock; + return WrapperType.AACSMediaKeyBlock; #endregion #region BDPlusSVM if (extension.Equals("svm", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.BDPlusSVM; + return WrapperType.BDPlusSVM; #endregion @@ -429,7 +539,7 @@ namespace Test #region BZip2 if (extension.Equals("bz2", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.BZip2; + return WrapperType.BZip2; #endregion @@ -437,30 +547,30 @@ namespace Test // Installer package if (extension.Equals("msi", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.CFB; + return WrapperType.CFB; // Merge module else if (extension.Equals("msm", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.CFB; + return WrapperType.CFB; // Patch Package else if (extension.Equals("msp", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.CFB; + return WrapperType.CFB; // Transform else if (extension.Equals("mst", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.CFB; + return WrapperType.CFB; // Patch Creation Properties else if (extension.Equals("pcp", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.CFB; + return WrapperType.CFB; #endregion #region CIA if (extension.Equals("cia", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.CIA; + return WrapperType.CIA; #endregion @@ -468,39 +578,39 @@ namespace Test // DOS MZ executable file format (and descendants) if (extension.Equals("exe", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Executable; + return WrapperType.Executable; // DOS MZ library file format (and descendants) if (extension.Equals("dll", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Executable; + return WrapperType.Executable; #endregion #region GCF if (extension.Equals("gcf", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.GCF; + return WrapperType.GCF; #endregion #region GZIP if (extension.Equals("gz", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.GZIP; + return WrapperType.GZIP; #endregion #region IniFile if (extension.Equals("ini", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.IniFile; + return WrapperType.IniFile; #endregion #region InstallShieldArchiveV3 if (extension.Equals("z", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.InstallShieldArchiveV3; + return WrapperType.InstallShieldArchiveV3; #endregion @@ -521,7 +631,7 @@ namespace Test #region MPQ if (extension.Equals("mpq", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.MPQ; + return WrapperType.MoPaQ; #endregion @@ -529,7 +639,7 @@ namespace Test // 3DS cart image if (extension.Equals("3ds", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.N3DS; + return WrapperType.N3DS; // CIA package -- Not currently supported // else if (extension.Equals("cia", StringComparison.OrdinalIgnoreCase)) @@ -540,7 +650,7 @@ namespace Test #region NCF if (extension.Equals("ncf", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.NCF; + return WrapperType.NCF; #endregion @@ -548,19 +658,19 @@ namespace Test // DS cart image if (extension.Equals("nds", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Nitro; + return WrapperType.Nitro; // DS development cart image else if (extension.Equals("srl", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Nitro; + return WrapperType.Nitro; // DSi cart image else if (extension.Equals("dsi", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Nitro; + return WrapperType.Nitro; // iQue DS cart image else if (extension.Equals("ids", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Nitro; + return WrapperType.Nitro; #endregion @@ -576,7 +686,7 @@ namespace Test #region PFF if (extension.Equals("pff", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PFF; + return WrapperType.PFF; #endregion @@ -584,87 +694,87 @@ namespace Test // PKZIP if (extension.Equals("zip", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Android package if (extension.Equals("apk", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Java archive if (extension.Equals("jar", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Google Earth saved working session file if (extension.Equals("kmz", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // KWord document if (extension.Equals("kwd", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Microsoft Office Open XML Format (OOXML) Document if (extension.Equals("docx", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Microsoft Office Open XML Format (OOXML) Presentation if (extension.Equals("pptx", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Microsoft Office Open XML Format (OOXML) Spreadsheet if (extension.Equals("xlsx", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // OpenDocument text document if (extension.Equals("odt", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // OpenDocument presentation if (extension.Equals("odp", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // OpenDocument text document template if (extension.Equals("ott", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Microsoft Open XML paper specification file if (extension.Equals("oxps", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // OpenOffice spreadsheet if (extension.Equals("sxc", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // OpenOffice drawing if (extension.Equals("sxd", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // OpenOffice presentation if (extension.Equals("sxi", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // OpenOffice word processing if (extension.Equals("sxw", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // StarOffice spreadsheet if (extension.Equals("sxc", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Windows Media compressed skin file if (extension.Equals("wmz", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // Mozilla Browser Archive if (extension.Equals("xpi", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // XML paper specification file if (extension.Equals("xps", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; // eXact Packager Models if (extension.Equals("xpt", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PKZIP; + return WrapperType.PKZIP; #endregion @@ -672,14 +782,14 @@ namespace Test // https://www.iana.org/assignments/media-types/audio/vnd.everad.plj if (extension.Equals("plj", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.PLJ; + return WrapperType.PlayJAudioFile; #endregion #region Quantum if (extension.Equals("q", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Quantum; + return WrapperType.Quantum; // Both PAK and Quantum share one extension // if (extension.Equals("pak", StringComparison.OrdinalIgnoreCase)) @@ -690,28 +800,28 @@ namespace Test #region RAR if (extension.Equals("rar", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.RAR; + return WrapperType.RAR; #endregion #region SevenZip if (extension.Equals("7z", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.SevenZip; + return WrapperType.SevenZip; #endregion #region SGA if (extension.Equals("sga", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.SGA; + return WrapperType.SGA; #endregion #region TapeArchive if (extension.Equals("tar", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.SevenZip; + return WrapperType.SevenZip; #endregion @@ -719,51 +829,51 @@ namespace Test // "Description in Zip" if (extension.Equals("diz", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Generic textfile (no header) if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // HTML if (extension.Equals("htm", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; if (extension.Equals("html", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // InstallShield Script if (extension.Equals("ins", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Microsoft Office File (old) if (extension.Equals("doc", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Property list if (extension.Equals("plist", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Rich Text File if (extension.Equals("rtf", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Setup information if (extension.Equals("inf", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // Windows Help File if (extension.Equals("hlp", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // WZC if (extension.Equals("wzc", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; // XML if (extension.Equals("xml", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.Textfile; + return WrapperType.Textfile; + - #endregion @@ -794,19 +904,19 @@ namespace Test #region XZ if (extension.Equals("xz", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.XZ; + return WrapperType.XZ; #endregion #region XZP if (extension.Equals("xzp", StringComparison.OrdinalIgnoreCase)) - return SupportedFileType.XZP; + return WrapperType.XZP; #endregion // We couldn't find a supported match - return SupportedFileType.UNKNOWN; + return WrapperType.UNKNOWN; } } -} \ No newline at end of file +} diff --git a/Test/SupportedFileType.cs b/SabreTools.Serialization/Wrappers/WrapperType.cs similarity index 69% rename from Test/SupportedFileType.cs rename to SabreTools.Serialization/Wrappers/WrapperType.cs index 038e09a2..c852e17b 100644 --- a/Test/SupportedFileType.cs +++ b/SabreTools.Serialization/Wrappers/WrapperType.cs @@ -1,9 +1,9 @@ -namespace Test +namespace SabreTools.Serialization.Wrappers { /// - /// Subset of file types that are supported by the library + /// Represents each of the IWrapper implementations /// - internal enum SupportedFileType + public enum WrapperType { /// /// Unknown or unsupported @@ -33,6 +33,7 @@ namespace Test /// /// bzip2 archive /// + /// Currently has no IWrapper implementation BZip2, /// @@ -48,6 +49,7 @@ namespace Test /// /// Executable or library /// + /// Includes MZ, NE, LE/LX, and PE Executable, /// @@ -58,16 +60,19 @@ namespace Test /// /// gzip archive /// + /// Currently has no IWrapper implementation GZIP, /// /// Key-value pair INI file /// + /// Currently has no IWrapper implementation IniFile, /// /// InstallShield archive v3 /// + /// Currently has no IWrapper implementation InstallShieldArchiveV3, /// @@ -78,6 +83,7 @@ namespace Test /// /// Link Data Security encrypted file /// + /// Currently has no IWrapper implementation LDSCRYPT, /// @@ -88,12 +94,13 @@ namespace Test /// /// Microsoft LZ-compressed file /// + /// Currently has no IWrapper implementation MicrosoftLZ, /// /// MPQ game data archive /// - MPQ, + MoPaQ, /// /// Nintendo 3DS cart image @@ -120,15 +127,28 @@ namespace Test /// PFF, + /// + /// PIC data object + /// + /// Currently has no detection method + PIC, + /// /// PKWARE ZIP archive and derivatives /// + /// Currently has no IWrapper implementation PKZIP, /// /// PlayJ audio file /// - PLJ, + PlayJAudioFile, + + /// + /// PlayJ playlist file + /// + /// Currently has no detection method/remarks> + PlayJPlaylist, /// /// Quantum archive @@ -138,26 +158,31 @@ namespace Test /// /// RAR archive /// + /// Currently has no IWrapper implementation RAR, /// /// RealArcade Installer /// + /// Currently has no IWrapper implementation RealArcadeInstaller, /// /// RealArcade Mezzanine /// + /// Currently has no IWrapper implementation RealArcadeMezzanine, /// /// 7-zip archive /// + /// Currently has no IWrapper implementation SevenZip, /// /// StarForce FileSystem file /// + /// Currently has no IWrapper implementation SFFS, /// @@ -168,11 +193,13 @@ namespace Test /// /// Tape archive /// + /// Currently has no IWrapper implementation TapeArchive, /// /// Various generic textfile formats /// + /// Currently has no IWrapper implementation Textfile, /// @@ -193,6 +220,7 @@ namespace Test /// /// xz archive /// + /// Currently has no IWrapper implementation XZ, /// diff --git a/Test/Options.cs b/Test/Options.cs index 1678ca31..2a96d5e5 100644 --- a/Test/Options.cs +++ b/Test/Options.cs @@ -104,7 +104,7 @@ namespace Test /// public static void DisplayHelp() { - Console.WriteLine("SabreTools.Printing Test Program"); + Console.WriteLine("SabreTools.Serialization Test Program"); Console.WriteLine(); Console.WriteLine("test.exe file|directory ..."); Console.WriteLine(); diff --git a/Test/Program.cs b/Test/Program.cs index af607446..19cc9546 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -2,6 +2,7 @@ using System.IO; using SabreTools.IO.Extensions; using SabreTools.Serialization; +using SabreTools.Serialization.Wrappers; namespace Test { @@ -80,11 +81,11 @@ namespace Test stream.Seek(0, SeekOrigin.Begin); // Get the file type - SupportedFileType ft = FileTypes.GetFileType(magic ?? []); - if (ft == SupportedFileType.UNKNOWN) + WrapperType ft = WrapperFactory.GetFileType(magic ?? []); + if (ft == WrapperType.UNKNOWN) { string extension = Path.GetExtension(file).TrimStart('.'); - ft = FileTypes.GetFileType(extension); + ft = WrapperFactory.GetFileType(extension); } // Print out the file format diff --git a/Test/WrapperFactory.cs b/Test/WrapperFactory.cs deleted file mode 100644 index 7b4855ee..00000000 --- a/Test/WrapperFactory.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.IO; -using SabreTools.IO.Extensions; -using SabreTools.Matching; -using SabreTools.Serialization.Interfaces; -using SabreTools.Serialization.Wrappers; - -namespace Test -{ - internal static class WrapperFactory - { - /// - /// Create an instance of a wrapper based on file type - /// - public static IWrapper? CreateWrapper(SupportedFileType fileType, Stream? data) - { - switch (fileType) - { - case SupportedFileType.AACSMediaKeyBlock: return AACSMediaKeyBlock.Create(data); - case SupportedFileType.BDPlusSVM: return BDPlusSVM.Create(data); - case SupportedFileType.BFPK: return BFPK.Create(data); - case SupportedFileType.BSP: return BSP.Create(data); - //case SupportedFileType.BZip2: return BZip2.Create(data); - case SupportedFileType.CFB: return CFB.Create(data); - case SupportedFileType.CIA: return CIA.Create(data); - case SupportedFileType.Executable: return CreateExecutableWrapper(data); - case SupportedFileType.GCF: return GCF.Create(data); - //case SupportedFileType.GZIP: return GZIP.Create(data); - //case SupportedFileType.IniFile: return IniFile.Create(data); - //case SupportedFileType.InstallShieldArchiveV3: return InstallShieldArchiveV3.Create(data); - case SupportedFileType.InstallShieldCAB: return InstallShieldCabinet.Create(data); - //case SupportedFileType.LDSCRYPT: return LDSCRYPT.Create(data); - case SupportedFileType.MicrosoftCAB: return MicrosoftCabinet.Create(data); - //case SupportedFileType.MicrosoftLZ: return MicrosoftLZ.Create(data); - case SupportedFileType.MPQ: return MoPaQ.Create(data); - case SupportedFileType.N3DS: return N3DS.Create(data); - case SupportedFileType.NCF: return NCF.Create(data); - case SupportedFileType.Nitro: return Nitro.Create(data); - case SupportedFileType.PAK: return PAK.Create(data); - case SupportedFileType.PFF: return PFF.Create(data); - //case SupportedFileType.PIC: return PIC.Create(data); - //case SupportedFileType.PKZIP: return PKZIP.Create(data); - case SupportedFileType.PLJ: return PlayJAudioFile.Create(data); - //case SupportedFileType.PLJPlaylist: return PlayJPlaylist.Create(data); - case SupportedFileType.Quantum: return Quantum.Create(data); - //case SupportedFileType.RAR: return RAR.Create(data); - //case SupportedFileType.SevenZip: return SevenZip.Create(data); - //case SupportedFileType.SFFS: return SFFS.Create(data); - case SupportedFileType.SGA: return SGA.Create(data); - //case SupportedFileType.TapeArchive: return TapeArchive.Create(data); - //case SupportedFileType.Textfile: return Textfile.Create(data); - case SupportedFileType.VBSP: return VBSP.Create(data); - case SupportedFileType.VPK: return VPK.Create(data); - case SupportedFileType.WAD: return WAD.Create(data); - //case SupportedFileType.XZ: return XZ.Create(data); - case SupportedFileType.XZP: return XZP.Create(data); - default: return null; - } - } - - /// - /// Create an instance of a wrapper based on the executable type - /// - /// Stream data to parse - /// IWrapper representing the executable, null on error - public static IWrapper? CreateExecutableWrapper(Stream? stream) - { - // If we have no stream - if (stream == null) - return null; - - // Try to get an MS-DOS wrapper first - var wrapper = MSDOS.Create(stream); - if (wrapper == null || !(wrapper is MSDOS msdos)) - return null; - - // Check for a valid new executable address - if (msdos.Model.Header?.NewExeHeaderAddr == null || msdos.Model.Header.NewExeHeaderAddr >= stream.Length) - return wrapper; - - // Try to read the executable info - stream.Seek(msdos.Model.Header.NewExeHeaderAddr, SeekOrigin.Begin); - var magic = stream.ReadBytes(4); - - // If we didn't get valid data at the offset - if (magic == null) - { - return wrapper; - } - - // New Executable - else if (magic.StartsWith(SabreTools.Models.NewExecutable.Constants.SignatureBytes)) - { - stream.Seek(0, SeekOrigin.Begin); - return NewExecutable.Create(stream); - } - - // Linear Executable - else if (magic.StartsWith(SabreTools.Models.LinearExecutable.Constants.LESignatureBytes) - || magic.StartsWith(SabreTools.Models.LinearExecutable.Constants.LXSignatureBytes)) - { - stream.Seek(0, SeekOrigin.Begin); - return LinearExecutable.Create(stream); - } - - // Portable Executable - else if (magic.StartsWith(SabreTools.Models.PortableExecutable.Constants.SignatureBytes)) - { - stream.Seek(0, SeekOrigin.Begin); - return PortableExecutable.Create(stream); - } - - // Everything else fails - return null; - } - } -}