2016-10-24 12:58:57 -07:00
|
|
|
|
using System;
|
2016-09-02 13:59:25 -07:00
|
|
|
|
using System.Collections.Generic;
|
2016-09-02 14:26:15 -07:00
|
|
|
|
using System.Diagnostics;
|
2016-09-08 17:42:53 -07:00
|
|
|
|
using System.Linq;
|
2016-09-02 13:59:25 -07:00
|
|
|
|
using System.Xml;
|
2016-10-24 12:58:57 -07:00
|
|
|
|
using Mono.Data.Sqlite;
|
|
|
|
|
|
|
2017-10-06 00:52:26 -07:00
|
|
|
|
using SabreTools.Library;
|
2017-05-04 02:41:11 -07:00
|
|
|
|
using SabreTools.Library.Data;
|
|
|
|
|
|
using SabreTools.Library.Dats;
|
|
|
|
|
|
using SabreTools.Library.Tools;
|
2016-09-02 13:59:25 -07:00
|
|
|
|
|
2016-10-28 21:49:29 -07:00
|
|
|
|
#if MONO
|
2016-10-27 11:35:17 -07:00
|
|
|
|
using System.IO;
|
|
|
|
|
|
#else
|
2016-10-26 22:10:47 -07:00
|
|
|
|
using Alphaleonis.Win32.Filesystem;
|
|
|
|
|
|
|
|
|
|
|
|
using SearchOption = System.IO.SearchOption;
|
|
|
|
|
|
using StreamWriter = System.IO.StreamWriter;
|
2016-10-30 21:15:33 -07:00
|
|
|
|
#endif
|
2016-10-26 22:10:47 -07:00
|
|
|
|
|
2017-02-02 15:08:21 -08:00
|
|
|
|
namespace RombaSharp
|
2016-09-02 13:59:25 -07:00
|
|
|
|
{
|
|
|
|
|
|
public partial class RombaSharp
|
|
|
|
|
|
{
|
|
|
|
|
|
#region Helper methods
|
|
|
|
|
|
|
2016-10-17 11:04:07 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Display the statistics in the database
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private static void DisplayDBStats()
|
|
|
|
|
|
{
|
|
|
|
|
|
SqliteConnection dbc = new SqliteConnection(_connectionString);
|
|
|
|
|
|
dbc.Open();
|
|
|
|
|
|
|
|
|
|
|
|
// Total number of CRCs
|
|
|
|
|
|
string query = "SELECT COUNT(*) FROM crc";
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand(query, dbc);
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.User("Total CRCs: {0}", (long)slc.ExecuteScalar());
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
|
|
|
|
|
// Total number of MD5s
|
|
|
|
|
|
query = "SELECT COUNT(*) FROM md5";
|
|
|
|
|
|
slc = new SqliteCommand(query, dbc);
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.User("Total MD5s: {0}", (long)slc.ExecuteScalar());
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
|
|
|
|
|
// Total number of SHA1s
|
|
|
|
|
|
query = "SELECT COUNT(*) FROM sha1";
|
|
|
|
|
|
slc = new SqliteCommand(query, dbc);
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.User("Total SHA1s: {0}", (long)slc.ExecuteScalar());
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
|
|
|
|
|
// Total number of DATs
|
|
|
|
|
|
query = "SELECT COUNT(*) FROM dat";
|
|
|
|
|
|
slc = new SqliteCommand(query, dbc);
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.User("Total DATs: {0}", (long)slc.ExecuteScalar());
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
dbc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Display the current memory usage of the application
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private static void DisplayMemoryStats()
|
|
|
|
|
|
{
|
|
|
|
|
|
Process proc = Process.GetCurrentProcess();
|
|
|
|
|
|
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.User("Current Nonpaged Memory: {0}", Style.GetBytesReadable(proc.NonpagedSystemMemorySize64));
|
|
|
|
|
|
Globals.Logger.User("Current Paged Memory: {0}", Style.GetBytesReadable(proc.PagedMemorySize64));
|
|
|
|
|
|
Globals.Logger.User("Peak Paged Memory: {0}", Style.GetBytesReadable(proc.PeakPagedMemorySize64));
|
|
|
|
|
|
Globals.Logger.User("Peak Virtual Memory: {0}", Style.GetBytesReadable(proc.PeakVirtualMemorySize64));
|
|
|
|
|
|
Globals.Logger.User("Peak Working Memory: {0}", Style.GetBytesReadable(proc.PeakWorkingSet64));
|
|
|
|
|
|
Globals.Logger.User("Private Memory: {0}", Style.GetBytesReadable(proc.PrivateMemorySize64));
|
|
|
|
|
|
Globals.Logger.User("Virtual Memory: {0}", Style.GetBytesReadable(proc.VirtualMemorySize64));
|
|
|
|
|
|
Globals.Logger.User("Working Memory: {0}", Style.GetBytesReadable(proc.WorkingSet64));
|
|
|
|
|
|
Globals.Logger.User("Total Processor Time: {0}", proc.TotalProcessorTime);
|
|
|
|
|
|
Globals.Logger.User("User Processor Time: {0}", proc.UserProcessorTime);
|
2016-10-17 11:04:07 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Export the current database to CSV
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <remarks>REDO</remarks>
|
|
|
|
|
|
private static void ExportDatabase()
|
|
|
|
|
|
{
|
|
|
|
|
|
SqliteConnection dbc = new SqliteConnection(_connectionString);
|
|
|
|
|
|
dbc.Open();
|
2017-03-15 20:07:28 -07:00
|
|
|
|
StreamWriter sw = new StreamWriter(FileTools.TryCreate("export.csv"));
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
2017-01-27 16:53:29 -08:00
|
|
|
|
sw.WriteLine("\"ID\",\"Size\",\"CRC\",\"MD5\",\"SHA-1\",\"In Depot\",\"DAT Hash\"");
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
|
|
|
|
|
string query = "SELECT dats.id, size, crc, md5, sha1, indepot, hash FROM data JOIN dats ON data.id=dats.id";
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand(query, dbc);
|
|
|
|
|
|
SqliteDataReader sldr = slc.ExecuteReader();
|
|
|
|
|
|
|
|
|
|
|
|
if (sldr.HasRows)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (sldr.Read())
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
string line = "\"" + sldr.GetInt32(0) + "\","
|
|
|
|
|
|
+ "\"" + sldr.GetInt64(1) + "\","
|
|
|
|
|
|
+ "\"" + sldr.GetString(2) + "\","
|
|
|
|
|
|
+ "\"" + sldr.GetString(3) + "\","
|
|
|
|
|
|
+ "\"" + sldr.GetString(4) + "\","
|
|
|
|
|
|
+ "\"" + sldr.GetInt32(5) + "\","
|
|
|
|
|
|
+ "\"" + sldr.GetString(6) + "\"";
|
2016-10-17 11:04:07 -07:00
|
|
|
|
sw.WriteLine(line);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sldr.Dispose();
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
sw.Dispose();
|
|
|
|
|
|
dbc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Gets all valid DATs that match in the DAT root
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="inputs">List of input strings to check for, presumably file names</param>
|
|
|
|
|
|
/// <returns>Dictionary of hash/full path for each of the valid DATs</returns>
|
|
|
|
|
|
private static Dictionary<string, string> GetValidDats(List<string> inputs)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Get a dictionary of filenames that actually exist in the DATRoot, logging which ones are not
|
|
|
|
|
|
List<string> datRootDats = Directory.EnumerateFiles(_dats, "*", SearchOption.AllDirectories).ToList();
|
|
|
|
|
|
List<string> lowerCaseDats = datRootDats.ConvertAll(i => Path.GetFileName(i).ToLowerInvariant());
|
|
|
|
|
|
Dictionary<string, string> foundDats = new Dictionary<string, string>();
|
|
|
|
|
|
foreach (string input in inputs)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (lowerCaseDats.Contains(input.ToLowerInvariant()))
|
|
|
|
|
|
{
|
|
|
|
|
|
string fullpath = Path.GetFullPath(datRootDats[lowerCaseDats.IndexOf(input.ToLowerInvariant())]);
|
2017-03-01 21:26:27 -08:00
|
|
|
|
string sha1 = FileTools.GetFileInfo(fullpath).SHA1;
|
2016-10-17 11:04:07 -07:00
|
|
|
|
foundDats.Add(sha1, fullpath);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.Warning("The file '{0}' could not be found in the DAT root", input);
|
2016-10-17 11:04:07 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return foundDats;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-09-02 13:59:25 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Initialize the Romba application from XML config
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private static void InitializeConfiguration()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Get default values if they're not written
|
|
|
|
|
|
int workers = 4,
|
|
|
|
|
|
verbosity = 1,
|
|
|
|
|
|
cores = 4,
|
|
|
|
|
|
port = 4003;
|
|
|
|
|
|
string logdir = "logs",
|
|
|
|
|
|
tmpdir = "tmp",
|
|
|
|
|
|
webdir = "web",
|
|
|
|
|
|
baddir = "bad",
|
|
|
|
|
|
dats = "dats",
|
|
|
|
|
|
db = "db",
|
2017-01-27 16:53:29 -08:00
|
|
|
|
connectionString = "";
|
2016-09-02 13:59:25 -07:00
|
|
|
|
Dictionary<string, Tuple<long, bool>> depots = new Dictionary<string, Tuple<long, bool>>();
|
|
|
|
|
|
|
|
|
|
|
|
// Get the XML text reader for the configuration file, if possible
|
2017-03-01 21:26:27 -08:00
|
|
|
|
XmlReader xtr = FileTools.GetXmlTextReader(_config);
|
2016-09-02 13:59:25 -07:00
|
|
|
|
|
|
|
|
|
|
// Now parse the XML file for settings
|
|
|
|
|
|
if (xtr != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
xtr.MoveToContent();
|
|
|
|
|
|
while (!xtr.EOF)
|
|
|
|
|
|
{
|
|
|
|
|
|
// We only want elements
|
|
|
|
|
|
if (xtr.NodeType != XmlNodeType.Element)
|
|
|
|
|
|
{
|
|
|
|
|
|
xtr.Read();
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (xtr.Name)
|
|
|
|
|
|
{
|
|
|
|
|
|
case "workers":
|
|
|
|
|
|
workers = xtr.ReadElementContentAsInt();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "logdir":
|
|
|
|
|
|
logdir = xtr.ReadElementContentAsString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "tmpdir":
|
|
|
|
|
|
tmpdir = xtr.ReadElementContentAsString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "webdir":
|
|
|
|
|
|
webdir = xtr.ReadElementContentAsString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "baddir":
|
|
|
|
|
|
baddir = xtr.ReadElementContentAsString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "verbosity":
|
|
|
|
|
|
verbosity = xtr.ReadElementContentAsInt();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "cores":
|
|
|
|
|
|
cores = xtr.ReadElementContentAsInt();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "dats":
|
|
|
|
|
|
dats = xtr.ReadElementContentAsString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "db":
|
|
|
|
|
|
db = xtr.ReadElementContentAsString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "depot":
|
|
|
|
|
|
XmlReader subreader = xtr.ReadSubtree();
|
|
|
|
|
|
if (subreader != null)
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
string root = "";
|
2016-09-02 13:59:25 -07:00
|
|
|
|
long maxsize = -1;
|
|
|
|
|
|
bool online = true;
|
|
|
|
|
|
|
|
|
|
|
|
while (!subreader.EOF)
|
|
|
|
|
|
{
|
|
|
|
|
|
// We only want elements
|
|
|
|
|
|
if (subreader.NodeType != XmlNodeType.Element)
|
|
|
|
|
|
{
|
|
|
|
|
|
subreader.Read();
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (subreader.Name)
|
|
|
|
|
|
{
|
|
|
|
|
|
case "root":
|
|
|
|
|
|
root = subreader.ReadElementContentAsString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "maxsize":
|
|
|
|
|
|
maxsize = subreader.ReadElementContentAsLong();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "online":
|
|
|
|
|
|
online = subreader.ReadElementContentAsBoolean();
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
subreader.Read();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
depots.Add(root, new Tuple<long, bool>(maxsize, online));
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
// Ignore add errors
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
xtr.Skip();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case "port":
|
|
|
|
|
|
port = xtr.ReadElementContentAsInt();
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
xtr.Read();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Now validate the values given
|
|
|
|
|
|
if (workers < 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
workers = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (workers > 8)
|
|
|
|
|
|
{
|
|
|
|
|
|
workers = 8;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Directory.Exists(logdir))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(logdir);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Directory.Exists(tmpdir))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(tmpdir);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Directory.Exists(webdir))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(webdir);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Directory.Exists(baddir))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(baddir);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (verbosity < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
verbosity = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (verbosity > 3)
|
|
|
|
|
|
{
|
|
|
|
|
|
verbosity = 3;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (cores < 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
cores = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (cores > 16)
|
|
|
|
|
|
{
|
|
|
|
|
|
cores = 16;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Directory.Exists(dats))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(dats);
|
|
|
|
|
|
}
|
|
|
|
|
|
db = Path.GetFileNameWithoutExtension(db) + ".sqlite";
|
2016-09-02 14:31:17 -07:00
|
|
|
|
connectionString = "Data Source=" + db + ";Version = 3;";
|
2016-09-02 13:59:25 -07:00
|
|
|
|
foreach (string key in depots.Keys)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Directory.Exists(key))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(key);
|
|
|
|
|
|
File.CreateText(Path.Combine(key, ".romba_size"));
|
|
|
|
|
|
File.CreateText(Path.Combine(key, ".romba_size.backup"));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!File.Exists(Path.Combine(key, ".romba_size")))
|
|
|
|
|
|
{
|
|
|
|
|
|
File.CreateText(Path.Combine(key, ".romba_size"));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!File.Exists(Path.Combine(key, ".romba_size.backup")))
|
|
|
|
|
|
{
|
|
|
|
|
|
File.CreateText(Path.Combine(key, ".romba_size.backup"));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (port < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
port = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (port > 65535)
|
|
|
|
|
|
{
|
|
|
|
|
|
port = 65535;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Finally set all of the fields
|
2017-07-13 17:03:38 -07:00
|
|
|
|
Globals.MaxThreads = workers;
|
2016-09-02 13:59:25 -07:00
|
|
|
|
_logdir = logdir;
|
|
|
|
|
|
_tmpdir = tmpdir;
|
|
|
|
|
|
_webdir = webdir;
|
|
|
|
|
|
_baddir = baddir;
|
|
|
|
|
|
_verbosity = verbosity;
|
|
|
|
|
|
_cores = cores;
|
|
|
|
|
|
_dats = dats;
|
|
|
|
|
|
_db = db;
|
|
|
|
|
|
_connectionString = connectionString;
|
|
|
|
|
|
_depots = depots;
|
|
|
|
|
|
_port = port;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-09-02 14:08:34 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Moves DAT index entries for orphaned DATs to backup folder
|
|
|
|
|
|
/// </summary>
|
2017-02-02 22:06:20 -08:00
|
|
|
|
/// <param name="logOnly">Only write out actions to log</param>
|
|
|
|
|
|
private static void PurgeBackup(bool logOnly)
|
2016-09-02 14:08:34 -07:00
|
|
|
|
{
|
2017-03-01 21:26:27 -08:00
|
|
|
|
Globals.Logger.User("This feature is not yet implemented: purge-backup");
|
2016-09-02 14:08:34 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Deletes DAT index entries for orphaned DATs
|
|
|
|
|
|
/// </summary>
|
2017-02-02 22:06:20 -08:00
|
|
|
|
/// <param name="logOnly">Only write out actions to log</param>
|
|
|
|
|
|
private static void PurgeDelete(bool logOnly)
|
2016-09-02 14:08:34 -07:00
|
|
|
|
{
|
2017-03-01 21:26:27 -08:00
|
|
|
|
Globals.Logger.User("This feature is not yet implemented: purge-delete");
|
2016-09-02 14:08:34 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-09-02 13:59:25 -07:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Populate or refresh the database information
|
|
|
|
|
|
/// </summary>
|
2016-10-14 14:04:15 -07:00
|
|
|
|
/// <remarks>This has no link between Dat and file at all...</remarks>
|
2016-09-02 13:59:25 -07:00
|
|
|
|
private static void RefreshDatabase()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Make sure the db is set
|
|
|
|
|
|
if (String.IsNullOrEmpty(_db))
|
|
|
|
|
|
{
|
|
|
|
|
|
_db = "db.sqlite";
|
|
|
|
|
|
_connectionString = "Data Source=" + _db + ";Version = 3;";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure the file exists
|
|
|
|
|
|
if (!File.Exists(_db))
|
|
|
|
|
|
{
|
2016-09-22 21:04:41 -07:00
|
|
|
|
DatabaseTools.EnsureDatabase(_dbSchema, _db, _connectionString);
|
2016-09-02 13:59:25 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure the dats dir is set
|
|
|
|
|
|
if (String.IsNullOrEmpty(_dats))
|
|
|
|
|
|
{
|
|
|
|
|
|
_dats = "dats";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure the folder exists
|
|
|
|
|
|
if (!Directory.Exists(_dats))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(_dats);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-10-19 10:47:23 -07:00
|
|
|
|
// First get a list of SHA-1's from the input DATs
|
|
|
|
|
|
DatFile datroot = new DatFile { Type = "SuperDAT", };
|
2017-03-17 15:48:49 -07:00
|
|
|
|
// TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually
|
2017-05-04 02:33:16 -07:00
|
|
|
|
datroot.PopulateFromDir(_dats, Hash.DeepHashes, false, false, false, SkipFileType.None, false, false, _tmpdir, false, null);
|
2017-08-29 11:46:01 -07:00
|
|
|
|
datroot.BucketBy(SortedBy.SHA1, DedupeType.None);
|
2016-10-19 10:47:23 -07:00
|
|
|
|
|
2016-09-02 13:59:25 -07:00
|
|
|
|
// Create a List of dat hashes in the database (SHA-1)
|
|
|
|
|
|
List<string> databaseDats = new List<string>();
|
2016-10-19 10:47:23 -07:00
|
|
|
|
List<string> unneeded = new List<string>();
|
2016-09-02 13:59:25 -07:00
|
|
|
|
|
2016-09-22 15:59:03 -07:00
|
|
|
|
SqliteConnection dbc = new SqliteConnection(_connectionString);
|
2016-10-10 13:14:35 -07:00
|
|
|
|
dbc.Open();
|
|
|
|
|
|
|
|
|
|
|
|
// Populate the List from the database
|
2017-10-06 00:52:26 -07:00
|
|
|
|
InternalStopwatch watch = new InternalStopwatch("Populating the list of existing DATs");
|
2016-10-10 13:45:41 -07:00
|
|
|
|
|
2016-10-14 14:04:15 -07:00
|
|
|
|
string query = "SELECT DISTINCT hash FROM dat";
|
2016-09-22 15:59:03 -07:00
|
|
|
|
SqliteCommand slc = new SqliteCommand(query, dbc);
|
|
|
|
|
|
SqliteDataReader sldr = slc.ExecuteReader();
|
|
|
|
|
|
if (sldr.HasRows)
|
2016-09-02 13:59:25 -07:00
|
|
|
|
{
|
2016-09-22 15:59:03 -07:00
|
|
|
|
sldr.Read();
|
|
|
|
|
|
string hash = sldr.GetString(0);
|
2017-09-25 12:56:45 -07:00
|
|
|
|
if (datroot.Contains(hash))
|
2016-09-02 13:59:25 -07:00
|
|
|
|
{
|
2017-09-25 12:21:52 -07:00
|
|
|
|
datroot.Remove(hash);
|
2016-09-22 15:59:03 -07:00
|
|
|
|
databaseDats.Add(hash);
|
2016-09-02 13:59:25 -07:00
|
|
|
|
}
|
2016-10-19 10:47:23 -07:00
|
|
|
|
else if (!databaseDats.Contains(hash))
|
|
|
|
|
|
{
|
|
|
|
|
|
unneeded.Add(hash);
|
|
|
|
|
|
}
|
2016-09-22 15:59:03 -07:00
|
|
|
|
}
|
2017-08-29 11:46:01 -07:00
|
|
|
|
datroot.BucketBy(SortedBy.Game, DedupeType.None, norename: true);
|
2016-10-19 10:47:23 -07:00
|
|
|
|
|
2017-10-06 00:52:26 -07:00
|
|
|
|
watch.Stop();
|
2016-09-02 13:59:25 -07:00
|
|
|
|
|
2016-09-22 15:59:03 -07:00
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
sldr.Dispose();
|
2016-09-02 13:59:25 -07:00
|
|
|
|
|
2016-10-19 10:47:23 -07:00
|
|
|
|
// Loop through the Dictionary and add all data
|
2017-10-06 00:52:26 -07:00
|
|
|
|
watch.Start("Adding new DAT information");
|
2016-11-08 15:50:27 -08:00
|
|
|
|
foreach (string key in datroot.Keys)
|
2016-09-22 15:59:03 -07:00
|
|
|
|
{
|
2016-11-08 15:29:52 -08:00
|
|
|
|
foreach (Rom value in datroot[key])
|
2016-09-22 15:59:03 -07:00
|
|
|
|
{
|
2016-10-19 10:47:23 -07:00
|
|
|
|
AddDatToDatabase(value, dbc);
|
2016-09-22 15:59:03 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-10-06 00:52:26 -07:00
|
|
|
|
watch.Stop();
|
2016-10-19 10:47:23 -07:00
|
|
|
|
|
|
|
|
|
|
// Now loop through and remove all references to old Dats
|
2017-10-06 00:52:26 -07:00
|
|
|
|
watch.Start("Removing unmatched DAT information");
|
2016-10-10 13:45:41 -07:00
|
|
|
|
|
2016-10-19 10:47:23 -07:00
|
|
|
|
foreach (string dathash in unneeded)
|
2016-09-22 15:59:03 -07:00
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
query = "DELETE FROM dats WHERE hash=\"" + dathash + "\"";
|
2016-10-19 10:47:23 -07:00
|
|
|
|
slc = new SqliteCommand(query, dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
slc.Dispose();
|
|
|
|
|
|
}
|
2017-10-06 00:52:26 -07:00
|
|
|
|
|
|
|
|
|
|
watch.Stop();
|
2016-10-19 10:47:23 -07:00
|
|
|
|
|
|
|
|
|
|
dbc.Dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void AddDatToDatabase(Rom dat, SqliteConnection dbc)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Get the dat full path
|
2017-01-27 16:53:29 -08:00
|
|
|
|
string fullpath = Path.Combine(_dats, (dat.Machine.Name == "dats" ? "" : dat.Machine.Name), dat.Name);
|
2016-09-02 13:59:25 -07:00
|
|
|
|
|
2016-10-19 10:47:23 -07:00
|
|
|
|
// Parse the Dat if possible
|
2017-03-01 21:26:27 -08:00
|
|
|
|
Globals.Logger.User("Adding from '" + dat.Name + "'");
|
2016-10-19 10:47:23 -07:00
|
|
|
|
DatFile tempdat = new DatFile();
|
2017-03-01 21:26:27 -08:00
|
|
|
|
tempdat.Parse(fullpath, 0, 0);
|
2016-10-19 10:47:23 -07:00
|
|
|
|
|
|
|
|
|
|
// If the Dat wasn't empty, add the information
|
|
|
|
|
|
SqliteCommand slc = new SqliteCommand();
|
2016-11-08 15:29:52 -08:00
|
|
|
|
if (tempdat.Count != 0)
|
2016-10-19 10:47:23 -07:00
|
|
|
|
{
|
|
|
|
|
|
string crcquery = "INSERT OR IGNORE INTO crc (crc) VALUES";
|
|
|
|
|
|
string md5query = "INSERT OR IGNORE INTO md5 (md5) VALUES";
|
|
|
|
|
|
string sha1query = "INSERT OR IGNORE INTO sha1 (sha1) VALUES";
|
|
|
|
|
|
string crcsha1query = "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES";
|
|
|
|
|
|
string md5sha1query = "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES";
|
|
|
|
|
|
|
|
|
|
|
|
// Loop through the parsed entries
|
2016-11-08 15:50:27 -08:00
|
|
|
|
foreach (string romkey in tempdat.Keys)
|
2016-09-22 15:59:03 -07:00
|
|
|
|
{
|
2016-11-08 15:50:27 -08:00
|
|
|
|
foreach (DatItem datItem in tempdat[romkey])
|
2016-09-02 13:59:25 -07:00
|
|
|
|
{
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.Verbose("Checking and adding file '{0}'", datItem.Name);
|
2016-10-19 10:47:23 -07:00
|
|
|
|
|
|
|
|
|
|
if (datItem.Type == ItemType.Rom)
|
2016-09-02 13:59:25 -07:00
|
|
|
|
{
|
2016-10-19 10:47:23 -07:00
|
|
|
|
Rom rom = (Rom)datItem;
|
2016-10-10 13:42:52 -07:00
|
|
|
|
|
2016-10-14 14:04:15 -07:00
|
|
|
|
if (!String.IsNullOrEmpty(rom.CRC))
|
2016-09-02 13:59:25 -07:00
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
crcquery += " (\"" + rom.CRC + "\"),";
|
2016-09-22 15:59:03 -07:00
|
|
|
|
}
|
2016-10-14 14:04:15 -07:00
|
|
|
|
if (!String.IsNullOrEmpty(rom.MD5))
|
2016-09-22 15:59:03 -07:00
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
md5query += " (\"" + rom.MD5 + "\"),";
|
2016-10-14 14:04:15 -07:00
|
|
|
|
}
|
|
|
|
|
|
if (!String.IsNullOrEmpty(rom.SHA1))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
sha1query += " (\"" + rom.SHA1 + "\"),";
|
2016-10-17 11:13:43 -07:00
|
|
|
|
|
|
|
|
|
|
if (!String.IsNullOrEmpty(rom.CRC))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
crcsha1query += " (\"" + rom.CRC + "\", \"" + rom.SHA1 + "\"),";
|
2016-10-17 11:13:43 -07:00
|
|
|
|
}
|
|
|
|
|
|
if (!String.IsNullOrEmpty(rom.MD5))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
md5sha1query += " (\"" + rom.MD5 + "\", \"" + rom.SHA1 + "\"),";
|
2016-10-17 11:13:43 -07:00
|
|
|
|
}
|
2016-09-02 13:59:25 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-10-19 10:47:23 -07:00
|
|
|
|
else if (datItem.Type == ItemType.Disk)
|
|
|
|
|
|
{
|
|
|
|
|
|
Disk disk = (Disk)datItem;
|
2016-10-14 14:04:15 -07:00
|
|
|
|
|
2016-10-19 10:47:23 -07:00
|
|
|
|
if (!String.IsNullOrEmpty(disk.MD5))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
md5query += " (\"" + disk.MD5 + "\"),";
|
2016-10-19 10:47:23 -07:00
|
|
|
|
}
|
|
|
|
|
|
if (!String.IsNullOrEmpty(disk.SHA1))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
sha1query += " (\"" + disk.SHA1 + "\"),";
|
2016-10-19 10:47:23 -07:00
|
|
|
|
|
|
|
|
|
|
if (!String.IsNullOrEmpty(disk.MD5))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
md5sha1query += " (\"" + disk.MD5 + "\", \"" + disk.SHA1 + "\"),";
|
2016-10-19 10:47:23 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-10-14 14:04:15 -07:00
|
|
|
|
}
|
2016-09-02 13:59:25 -07:00
|
|
|
|
}
|
2016-10-10 13:45:41 -07:00
|
|
|
|
|
2016-10-19 10:47:23 -07:00
|
|
|
|
// Now run the queries after fixing them
|
|
|
|
|
|
if (crcquery != "INSERT OR IGNORE INTO crc (crc) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(crcquery.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (md5query != "INSERT OR IGNORE INTO md5 (md5) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(md5query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sha1query != "INSERT OR IGNORE INTO sha1 (sha1) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(sha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (crcsha1query != "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(crcsha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (md5sha1query != "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(md5sha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
2016-09-02 13:59:25 -07:00
|
|
|
|
}
|
2016-10-10 10:51:19 -07:00
|
|
|
|
|
2017-01-27 16:53:29 -08:00
|
|
|
|
string datquery = "INSERT OR IGNORE INTO dat (hash) VALUES (\"" + dat.SHA1 + "\")";
|
2016-10-19 10:47:23 -07:00
|
|
|
|
slc = new SqliteCommand(datquery, dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
slc.Dispose();
|
2016-09-02 13:59:25 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-09-08 17:42:53 -07:00
|
|
|
|
/// <summary>
|
2016-10-17 11:04:07 -07:00
|
|
|
|
/// Rescan a particular depot path into the database
|
2016-09-08 17:42:53 -07:00
|
|
|
|
/// </summary>
|
2016-10-17 11:04:07 -07:00
|
|
|
|
/// <param name="depotname">Path to the depot to be rescanned</param>
|
|
|
|
|
|
private static void Rescan(string depotname)
|
2016-09-08 17:42:53 -07:00
|
|
|
|
{
|
2016-10-17 11:04:07 -07:00
|
|
|
|
// Check that it's a valid depot first
|
|
|
|
|
|
if (!_depots.ContainsKey(depotname))
|
2016-09-08 17:42:53 -07:00
|
|
|
|
{
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.User("'{0}' is not a recognized depot. Please add it to your configuration file and try again", depotname);
|
2016-10-17 11:04:07 -07:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Then check that the depot is online
|
|
|
|
|
|
if (!Directory.Exists(depotname))
|
|
|
|
|
|
{
|
2017-08-26 14:11:10 -07:00
|
|
|
|
Globals.Logger.User("'{0}' does not appear to be online. Please check its status and try again", depotname);
|
2016-10-17 11:04:07 -07:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Open the database connection
|
|
|
|
|
|
SqliteConnection dbc = new SqliteConnection(_connectionString);
|
|
|
|
|
|
dbc.Open();
|
|
|
|
|
|
|
|
|
|
|
|
// If we have it, then check for all hashes that are in that depot
|
|
|
|
|
|
List<string> hashes = new List<string>();
|
2017-01-27 16:53:29 -08:00
|
|
|
|
string query = "SELECT sha1 FROM sha1 WHERE depot=\"" + depotname + "\"";
|
2016-10-17 11:04:07 -07:00
|
|
|
|
SqliteCommand slc = new SqliteCommand(query, dbc);
|
|
|
|
|
|
SqliteDataReader sldr = slc.ExecuteReader();
|
|
|
|
|
|
if (sldr.HasRows)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (sldr.Read())
|
2016-09-08 17:42:53 -07:00
|
|
|
|
{
|
2016-10-17 11:04:07 -07:00
|
|
|
|
hashes.Add(sldr.GetString(0));
|
2016-09-08 17:42:53 -07:00
|
|
|
|
}
|
2016-10-17 11:04:07 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Now rescan the depot itself
|
|
|
|
|
|
DatFile depot = new DatFile();
|
2017-03-17 15:48:49 -07:00
|
|
|
|
// TODO: All instances of Hash.DeepHashes should be made into 0x0 eventually
|
2017-05-04 02:33:16 -07:00
|
|
|
|
depot.PopulateFromDir(depotname, Hash.DeepHashes, false, false, true, SkipFileType.None, false, false, _tmpdir, false, null);
|
2017-08-29 11:46:01 -07:00
|
|
|
|
depot.BucketBy(SortedBy.SHA1, DedupeType.None);
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
2016-10-17 11:13:43 -07:00
|
|
|
|
// Set the base queries to use
|
|
|
|
|
|
string crcquery = "INSERT OR IGNORE INTO crc (crc) VALUES";
|
|
|
|
|
|
string md5query = "INSERT OR IGNORE INTO md5 (md5) VALUES";
|
|
|
|
|
|
string sha1query = "INSERT OR IGNORE INTO sha1 (sha1, depot) VALUES";
|
|
|
|
|
|
string crcsha1query = "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES";
|
|
|
|
|
|
string md5sha1query = "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES";
|
|
|
|
|
|
|
2016-10-17 11:04:07 -07:00
|
|
|
|
// Once we have both, check for any new files
|
|
|
|
|
|
List<string> dupehashes = new List<string>();
|
2016-11-08 15:50:27 -08:00
|
|
|
|
List<string> keys = depot.Keys.ToList();
|
2016-10-17 11:04:07 -07:00
|
|
|
|
foreach (string key in keys)
|
|
|
|
|
|
{
|
2016-11-08 15:50:27 -08:00
|
|
|
|
List<DatItem> roms = depot[key];
|
2016-10-17 11:04:07 -07:00
|
|
|
|
foreach (Rom rom in roms)
|
2016-09-08 17:42:53 -07:00
|
|
|
|
{
|
2016-10-17 11:04:07 -07:00
|
|
|
|
if (hashes.Contains(rom.SHA1))
|
|
|
|
|
|
{
|
|
|
|
|
|
dupehashes.Add(rom.SHA1);
|
|
|
|
|
|
hashes.Remove(rom.SHA1);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!dupehashes.Contains(rom.SHA1))
|
|
|
|
|
|
{
|
2016-10-17 11:13:43 -07:00
|
|
|
|
if (!String.IsNullOrEmpty(rom.CRC))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
crcquery += " (\"" + rom.CRC + "\"),";
|
2016-10-17 11:13:43 -07:00
|
|
|
|
}
|
|
|
|
|
|
if (!String.IsNullOrEmpty(rom.MD5))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
md5query += " (\"" + rom.MD5 + "\"),";
|
2016-10-17 11:13:43 -07:00
|
|
|
|
}
|
|
|
|
|
|
if (!String.IsNullOrEmpty(rom.SHA1))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
sha1query += " (\"" + rom.SHA1 + "\", \"" + depotname + "\"),";
|
2016-10-17 11:04:07 -07:00
|
|
|
|
|
2016-10-17 11:13:43 -07:00
|
|
|
|
if (!String.IsNullOrEmpty(rom.CRC))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
crcsha1query += " (\"" + rom.CRC + "\", \"" + rom.SHA1 + "\"),";
|
2016-10-17 11:13:43 -07:00
|
|
|
|
}
|
|
|
|
|
|
if (!String.IsNullOrEmpty(rom.MD5))
|
|
|
|
|
|
{
|
2017-01-27 16:53:29 -08:00
|
|
|
|
md5sha1query += " (\"" + rom.MD5 + "\", \"" + rom.SHA1 + "\"),";
|
2016-10-17 11:13:43 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2016-10-17 11:04:07 -07:00
|
|
|
|
}
|
2016-09-08 17:42:53 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-10-17 11:13:43 -07:00
|
|
|
|
// Now run the queries after fixing them
|
|
|
|
|
|
if (crcquery != "INSERT OR IGNORE INTO crc (crc) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(crcquery.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (md5query != "INSERT OR IGNORE INTO md5 (md5) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(md5query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sha1query != "INSERT OR IGNORE INTO sha1 (sha1, depot) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(sha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (crcsha1query != "INSERT OR IGNORE INTO crcsha1 (crc, sha1) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(crcsha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (md5sha1query != "INSERT OR IGNORE INTO md5sha1 (md5, sha1) VALUES")
|
|
|
|
|
|
{
|
|
|
|
|
|
slc = new SqliteCommand(md5sha1query.TrimEnd(','), dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-10-17 11:24:31 -07:00
|
|
|
|
// Now that we've added the information, we get to remove all of the hashes that we want to
|
|
|
|
|
|
query = @"DELETE FROM sha1
|
|
|
|
|
|
JOIN crcsha1
|
|
|
|
|
|
ON sha1.sha1=crcsha1.sha1
|
|
|
|
|
|
JOIN md5sha1
|
|
|
|
|
|
ON sha1.sha1=md5sha1.sha1
|
|
|
|
|
|
JOIN crc
|
|
|
|
|
|
ON crcsha1.crc=crc.crc
|
|
|
|
|
|
JOIN md5
|
|
|
|
|
|
ON md5sha1.md5=md5.md5
|
2017-01-27 16:53:29 -08:00
|
|
|
|
WHERE sha1.sha1 IN (""" + String.Join("\",\"", hashes) + "\")";
|
2016-10-17 11:24:31 -07:00
|
|
|
|
slc = new SqliteCommand(query, dbc);
|
|
|
|
|
|
slc.ExecuteNonQuery();
|
|
|
|
|
|
|
2016-10-17 11:04:07 -07:00
|
|
|
|
// Dispose of the database connection
|
2016-10-17 11:24:31 -07:00
|
|
|
|
slc.Dispose();
|
2016-10-17 11:04:07 -07:00
|
|
|
|
dbc.Dispose();
|
2016-09-08 17:42:53 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-09-02 13:59:25 -07:00
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|