diff --git a/DATabase/DATabase.cs b/DATabase/DATabase.cs index cac43dce..75cdf3bd 100644 --- a/DATabase/DATabase.cs +++ b/DATabase/DATabase.cs @@ -15,7 +15,7 @@ namespace SabreTools private static Logger logger; private static string _dbName = "DATabase.sqlite"; private static string _connectionString = "Data Source=" + _dbName + ";Version = 3;"; - private static string _version = "0.2.0.0"; + private static string _version = "0.2.2.0"; private static string _header = @"+-----------------------------------------------------------------------------+ | DATabase " + _version + @" | diff --git a/Deheader/App.config b/Deheader/App.config index 88fa4027..48120d11 100644 --- a/Deheader/App.config +++ b/Deheader/App.config @@ -1,6 +1,29 @@ - + - - - + +
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Deheader/Headerer.cs b/Deheader/Headerer.cs index c61067d5..97bca827 100644 --- a/Deheader/Headerer.cs +++ b/Deheader/Headerer.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Data.SQLite; using System.IO; using System.Linq; +using System.Security.Cryptography; using System.Text.RegularExpressions; namespace SabreTools @@ -11,14 +13,17 @@ namespace SabreTools /// class Headerer { + private static string _version = "0.2.2.0"; + private static string _dbName = "Headerer.sqlite"; + private static string _connectionString = "Data Source=" + _dbName + ";Version = 3;"; private static Dictionary types; - private static bool save; private static string help = @"Deheader - Remove headers from roms ----------------------------------------- Usage: Deheader [option] [filename|dirname] Options: - -s Enable saving of the extracted header"; + -e Detect and remove mode + -r Restore header to file based on SHA-1"; /// /// Start deheader operation with supplied parameters @@ -34,6 +39,9 @@ Options: types.Add("nes", 16); types.Add("snes", 512); + // Ensure that the header database is set up + EnsureDatabase(_dbName, _connectionString); + if (args.Length == 0 || args.Length > 2) { Console.WriteLine(help); @@ -42,38 +50,73 @@ Options: // Get the filename (or foldername) string file = ""; + bool deheader = true; if (args.Length == 1) { file = args[0]; - save = false; } else { - file = args[1]; - save = true; - } - - - // If it's a single file, just check it - if (File.Exists(file)) - { - DetectRemoveHeader(file); - } - // If it's a directory, recursively check all - else if (Directory.Exists(file)) - { - foreach (string sub in Directory.GetFiles(file)) + + if (args[0] == "-e") { - if (sub != ".." && sub != ".") + deheader = true; + } + else if (args[0] == "-r") + { + deheader = false; + } + + file = args[1]; + } + + if (deheader) + { + // If it's a single file, just check it + if (File.Exists(file)) + { + DetectRemoveHeader(file); + } + // If it's a directory, recursively check all + else if (Directory.Exists(file)) + { + foreach (string sub in Directory.GetFiles(file)) { - DetectRemoveHeader(sub); + if (sub != ".." && sub != ".") + { + DetectRemoveHeader(sub); + } } } + // Else, show that help text + else + { + Console.WriteLine(help); + } } - // Else, show that help text else { - Console.WriteLine(help); + // If it's a single file, just check it + if (File.Exists(file)) + { + ReplaceHeader(file); + } + // If it's a directory, recursively check all + else if (Directory.Exists(file)) + { + foreach (string sub in Directory.GetFiles(file)) + { + if (sub != ".." && sub != ".") + { + ReplaceHeader(sub); + } + } + } + // Else, show that help text + else + { + Console.WriteLine(help); + } } } @@ -120,16 +163,11 @@ Options: Console.WriteLine("Deteched header type: " + type); int hs = types[type]; - // Write out the header if we're saving it - if (save) + // Save header as string in the database + string realhead = ""; + for (int i = 0; i < hs; i++) { - Console.WriteLine("Writing header to file: " + file + ".header"); - BinaryWriter bwh = new BinaryWriter(File.OpenWrite(file + ".header")); - for (int i = 0; i < hs; i++) - { - bwh.Write(hbin[i]); - } - bwh.Close(); + realhead += BitConverter.ToString(new byte[] { hbin[i] }); } // Get the bytes that aren't from the header from the extracted bit so they can be written before the rest of the file @@ -143,8 +181,133 @@ Options: bw.Write(br.ReadBytes((int)fi.Length - hs)); bw.Close(); Console.WriteLine("Unheadered file created!"); + + // Now add the information to the database if it's not already there + SHA1 sha1 = SHA1.Create(); + sha1.ComputeHash(File.ReadAllBytes(file + ".new")); + bool exists = false; + + string query = @"SELECT * FROM data WHERE sha1='" + BitConverter.ToString(sha1.Hash) + "'"; + using (SQLiteConnection dbc = new SQLiteConnection(_connectionString)) + { + dbc.Open(); + using (SQLiteCommand slc = new SQLiteCommand(query, dbc)) + { + using (SQLiteDataReader sldr = slc.ExecuteReader()) + { + exists = sldr.HasRows; + } + } + } + + if (!exists) + { + query = @"INSERT INTO data (sha1, header, type) VALUES ('" + + BitConverter.ToString(sha1.Hash) + "', " + + "'" + realhead + "', " + + "'" + type + "')"; + using (SQLiteConnection dbc = new SQLiteConnection(_connectionString)) + { + dbc.Open(); + using (SQLiteCommand slc = new SQLiteCommand(query, dbc)) + { + Console.WriteLine("Result of inserting header: " + slc.ExecuteNonQuery()); + } + } + } } br.Close(); } + + /// + /// Detect and replace header to the given file + /// + /// Name of the file to be parsed + private static void ReplaceHeader(string file) + { + // First, get the SHA-1 hash of the file + SHA1 sha1 = SHA1.Create(); + sha1.ComputeHash(File.ReadAllBytes(file)); + string hash = BitConverter.ToString(sha1.Hash); + + // Then try to pull the corresponding thing from the database + string header = ""; + + string query = @"SELECT header, type FROM data WHERE sha1='" + hash + "'"; + using (SQLiteConnection dbc = new SQLiteConnection(_connectionString)) + { + dbc.Open(); + using (SQLiteCommand slc = new SQLiteCommand(query, dbc)) + { + using (SQLiteDataReader sldr = slc.ExecuteReader()) + { + if (sldr.HasRows) + { + sldr.Read(); + Console.WriteLine("Found match with rom type " + sldr.GetString(1)); + header = sldr.GetString(0); + } + } + } + } + + // If the header isn't null, add it to the file. Otherwise tell the user + if (header == "") + { + Console.WriteLine("No matching header could be found!"); + return; + } + + Console.WriteLine("Creating reheadered file: " + file + ".new"); + BinaryWriter bw = new BinaryWriter(File.OpenWrite(file + ".new")); + + // Source: http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa + for (int i = 0; i < header.Length; i += 2) + { + bw.Write(Convert.ToByte(header.Substring(i, 2), 16)); + } + bw.Write(File.ReadAllBytes(file)); + bw.Close(); + Console.WriteLine("Reheadered file created!"); + } + + /// + /// Ensure that the databse exists and has the proper schema + /// + /// Name of the databse + /// Connection string for SQLite + public static void EnsureDatabase(string db, string connectionString) + { + // Make sure the file exists + if (!File.Exists(db)) + { + SQLiteConnection.CreateFile(db); + } + + // Connect to the file + SQLiteConnection dbc = new SQLiteConnection(connectionString); + dbc.Open(); + try + { + // Make sure the database has the correct schema + string query = @" +CREATE TABLE IF NOT EXISTS data ( + 'sha1' TEXT PRIMARY KEY NOT NULL, + 'header' TEXT NOT NULL, + 'type' TEXT NOT NULL +)"; + SQLiteCommand slc = new SQLiteCommand(query, dbc); + slc.ExecuteNonQuery(); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + finally + { + // Close and return the database connection + dbc.Close(); + } + } } } diff --git a/Deheader/Headerer.csproj b/Deheader/Headerer.csproj index cb0b3adc..bc37e97f 100644 --- a/Deheader/Headerer.csproj +++ b/Deheader/Headerer.csproj @@ -7,11 +7,13 @@ {66339C8A-F331-467C-B311-08A8F7284671} Exe Properties - Deheader - Deheader + Headerer + Headerer v4.5.2 512 true + + AnyCPU @@ -33,8 +35,29 @@ 4 + + ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll + True + + + ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll + True + + + + ..\packages\System.Data.SQLite.Core.1.0.99.0\lib\net451\System.Data.SQLite.dll + True + + + ..\packages\System.Data.SQLite.EF6.1.0.99.0\lib\net451\System.Data.SQLite.EF6.dll + True + + + ..\packages\System.Data.SQLite.Linq.1.0.99.0\lib\net451\System.Data.SQLite.Linq.dll + True + @@ -48,8 +71,16 @@ + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + +