Skip to content

Commit e221c08

Browse files
committed
Update to GTAHash
1 parent 9076a6b commit e221c08

1 file changed

Lines changed: 210 additions & 122 deletions

File tree

Program.cs

Lines changed: 210 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,254 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
24
using System.IO;
5+
using System.Linq;
36
using System.Net;
47
using System.Security.Cryptography;
5-
using System.Text.RegularExpressions;
8+
using System.Threading;
69

7-
namespace GTA5_MD5_Checker
10+
namespace GTAHash
811
{
912
class Program
1013
{
14+
static ConsoleColor goodColor = ConsoleColor.DarkGreen;
15+
static ConsoleColor badColor = ConsoleColor.DarkRed;
16+
static ConsoleColor unknownColor = ConsoleColor.DarkCyan;
17+
static int goodCount = 0, badCount = 0, unknownCount = 0;
18+
static List<string> fileList = new List<string>(), fileHashList = new List<string>();
19+
static List<string> hashQueue = new List<string>(), reportQueue = new List<string>(), writeQueue = new List<string>();
20+
static Stopwatch stopwatch = new Stopwatch();
21+
static WebClient client = new WebClient();
22+
static bool reporting = false, writing = false;
23+
static string hashFile = "hashes";
24+
static string action = "verify";
25+
1126
static void Main(string[] args)
1227
{
13-
ConsoleColor oldColor = Console.ForegroundColor;
14-
ConsoleColor oldBackColor = Console.BackgroundColor;
15-
WebClient client = new WebClient();
16-
int goodCount = 0;
17-
int idkCount = 0;
18-
int badCount = 0;
28+
if (args.Length > 0)
29+
if (args[0] == "write")
30+
{
31+
action = "write";
32+
if (File.Exists(hashFile))
33+
File.Delete(hashFile);
34+
}
35+
36+
// Show header
1937
showHeader();
20-
showDirectory();
21-
bool deleteFiles = areWeDeleting();
22-
string[] fileHashList = client.DownloadString("https://github.com/Scarsz/GTA5-MD5-Checker/raw/master/hashes").Split(new string[] { "\n", " " }, StringSplitOptions.None);
23-
// Change this for a different text color of the scanning process
24-
Console.ForegroundColor = ConsoleColor.White;
25-
foreach (string file in Directory.EnumerateFiles(".\\", "*.*", SearchOption.AllDirectories))
38+
39+
// Create threads
40+
Thread reporterThread = new Thread(new ThreadStart(reporter));
41+
Thread writerThread = new Thread(new ThreadStart(writer));
42+
Thread hashWorker1Thread = new Thread(new ThreadStart(hashWorker1));
43+
Thread hashWorker2Thread = new Thread(new ThreadStart(hashWorker2));
44+
Thread hashWorker3Thread = new Thread(new ThreadStart(hashWorker3));
45+
Thread hashWorker4Thread = new Thread(new ThreadStart(hashWorker4));
46+
47+
// Get file lists
48+
fileList = Directory.EnumerateFiles(".", "*", SearchOption.AllDirectories).ToList();
49+
fileHashList = client.DownloadString("https://github.com/Scarsz/GTA5-MD5-Checker/raw/master/hashes").Split(new string[] { "\n", " " }, StringSplitOptions.None).ToList();
50+
51+
// Clean file list
52+
// There has to be .ToList() on foreach loops where the list that's being looped is being modified inside of the foreach
53+
// .ToList() creates an instance of the list for foreach to loop on, unaffected by the modifications it's doing to the fileList list
54+
foreach (string file in fileList.ToList())
55+
{
56+
if (file == ".\\" + AppDomain.CurrentDomain.FriendlyName)
57+
fileList.Remove(fileList[fileList.IndexOf(file)]);
58+
if (file.Split('\\')[1] == "_CommonRedist")
59+
fileList.Remove(fileList[fileList.IndexOf(file)]);
60+
if (file.Split('\\')[1] == "Installers")
61+
fileList.Remove(fileList[fileList.IndexOf(file)]);
62+
if (file.Split('\\')[1] == "hashes")
63+
fileList.Remove(fileList[fileList.IndexOf(file)]);
64+
}
65+
66+
// Loop through each file to add it to the queue
67+
ConsoleColor oldColor = Console.BackgroundColor;
68+
Console.BackgroundColor = ConsoleColor.DarkMagenta;
69+
foreach (string file in fileList)
70+
{
71+
Console.WriteLine("Hash queue: Added file \"" + file + "\"");
72+
hashQueue.Add(file);
73+
}
74+
Console.BackgroundColor = oldColor;
75+
76+
// Add another line after the assigning messages to look nicer
77+
Console.WriteLine();
78+
79+
// Start stopwatch to time how long it takes to calculate all of the hashes
80+
stopwatch.Start();
81+
82+
// Start threads
83+
reporterThread.Start();
84+
writerThread.Start();
85+
hashWorker1Thread.Start();
86+
hashWorker2Thread.Start();
87+
hashWorker3Thread.Start();
88+
hashWorker4Thread.Start();
89+
90+
// Wait until all threads have did their work before continuing
91+
while (hashWorker1Thread.IsAlive || hashWorker2Thread.IsAlive || hashWorker3Thread.IsAlive || hashWorker4Thread.IsAlive || reporting || writing) { Thread.Sleep(100); }
92+
93+
// Abort the reporter thread because it won't receive any more reports
94+
reporterThread.Abort();
95+
// Abort the writer thread because it won't receive any more text
96+
writerThread.Abort();
97+
98+
// Stop the stopwatch
99+
stopwatch.Stop();
100+
101+
// Display information
102+
Console.WriteLine("\nCompleted in " + stopwatch.ElapsedMilliseconds / 1000 + " seconds");
103+
if (action == "verify")
104+
Console.WriteLine("Good files: {0}\nBad files: {1}\nUnknown files: {2}", goodCount, badCount, unknownCount);
105+
Console.ReadKey();
106+
}
107+
108+
static bool processWork(int threadId)
109+
{
110+
if (hashQueue.Count == 0)
111+
return false;
112+
113+
while (hashQueue.Count > 0)
26114
{
27-
// Crude way to exclude this exe from the search as well as _CommonRedist
28-
if (file != ".\\" + System.AppDomain.CurrentDomain.FriendlyName & file.Split('\\')[1] != "_CommonRedist")
115+
// Get the next available file to hash
116+
string file = hashQueue[0];
117+
118+
// Remove file from list so that another thread doesn't snag it
119+
hashQueue.RemoveAt(0);
120+
121+
// Calculate hash of file
122+
string fileHash = getHash(file);
123+
124+
// Do stuff with the file hash
125+
if (action == "verify")
29126
{
30-
int index = Array.IndexOf(fileHashList, file);
31-
int hashIndex = index + 1;
32-
if (index == -1)
33-
{
34-
// File list is either outdated or custom files were added
35-
Console.BackgroundColor = ConsoleColor.DarkCyan;
36-
Console.WriteLine(" " + file);
37-
idkCount++;
38-
}
127+
// Get index of file & hash in downloaded hash list
128+
int fileIndex = Array.IndexOf(fileHashList.ToArray(), file);
129+
int hashIndex = fileIndex + 1;
130+
131+
// If fileIndex == -1 the file is either custom or the downloaded file list is outdated
132+
if (fileIndex == -1)
133+
reportQueue.Add(file + " [Thread " + threadId + "]" + "|" + "unknown");
39134
else
40-
{
41-
// File was found in array
42-
if (getHash(file) == fileHashList[hashIndex])
43-
{
44-
// Match
45-
Console.BackgroundColor = ConsoleColor.DarkGreen;
46-
Console.WriteLine(" " + file);
47-
goodCount++;
48-
}
135+
if (fileHash == fileHashList[hashIndex])
136+
reportQueue.Add(file + " [Thread " + threadId + "]" + "|" + "good");
49137
else
50-
{
51-
// Not so match
52-
Console.BackgroundColor = ConsoleColor.Red;
53-
if (deleteFiles)
54-
{
55-
Console.WriteLine(" " + file + " [DELETED]");
56-
// We should be deleting the files so they can be downloaded later, let's do that
57-
File.Delete(file);
58-
}
59-
else
60-
{
61-
Console.WriteLine(" " + file);
62-
}
63-
badCount++;
64-
}
65-
}
138+
reportQueue.Add(file + " [Thread " + threadId + "]" + "|" + "bad");
139+
}
140+
else if (action == "write")
141+
{
142+
// If writing hashes send the hash to the file
143+
writeQueue.Add(file + "|" + fileHash + "|" + threadId);
66144
}
67145
}
68-
Console.BackgroundColor = oldBackColor;
69-
Console.ForegroundColor = ConsoleColor.White;
70-
Console.WriteLine("\nScan completed with " + goodCount + " good files, " + idkCount + " unknown files, and " + badCount + " bad files.");
71-
Console.ReadKey();
72-
Console.ForegroundColor = oldColor;
146+
147+
return true;
73148
}
74149

75-
static string getHash(string filepath)
150+
static void reporter()
76151
{
77-
using (var md5 = MD5.Create())
152+
while (true)
78153
{
79-
using (var stream = File.OpenRead(filepath))
154+
if (reportQueue.Count != 0)
80155
{
81-
string hash = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
82-
return hash;
156+
reporting = true;
157+
string info = reportQueue[0].Split('|')[0];
158+
string result = reportQueue[0].Split('|')[1];
159+
reportResult(info, result);
160+
reportQueue.RemoveAt(0);
83161
}
162+
else { reporting = false; Thread.Sleep(100); }
84163
}
85164
}
86-
static void showHeader()
165+
static void writer()
87166
{
88-
ConsoleColor oldColor = Console.ForegroundColor;
89-
Console.ForegroundColor = ConsoleColor.Green;
90-
Console.WriteLine("GTA5 PC MD5 Checker");
91-
Console.ForegroundColor = ConsoleColor.White;
92-
Console.WriteLine("v1 @ScarszRawr");
93-
Console.WriteLine();
94-
Console.ForegroundColor = ConsoleColor.DarkGreen;
95-
Console.WriteLine("████ File hash and expected hash matches");
96-
Console.ForegroundColor = ConsoleColor.DarkCyan;
97-
Console.WriteLine("████ Expected file hash unknown (custom file or out of date hash list)");
98-
Console.ForegroundColor = ConsoleColor.Red;
99-
Console.WriteLine("████ File hash and expected hash do not match");
100-
Console.WriteLine();
101-
102-
Console.ForegroundColor = oldColor;
167+
while (true)
168+
{
169+
if (writeQueue.Count != 0)
170+
{
171+
writing = true;
172+
string file = writeQueue[0].Split('|')[0];
173+
string fileHash = writeQueue[0].Split('|')[1];
174+
string thread = writeQueue[0].Split('|')[2];
175+
writeHash(file, fileHash, thread);
176+
writeQueue.RemoveAt(0);
177+
}
178+
else { writing = false; Thread.Sleep(100); }
179+
}
103180
}
104-
static void showDirectory()
181+
static void hashWorker1()
105182
{
106-
writeInfo("Scanning directory: ");
107-
Console.ForegroundColor = ConsoleColor.White;
108-
Console.WriteLine(Directory.GetCurrentDirectory() + "\n");
183+
//Boolean to know if thread exits normally
184+
bool hasExitedAfterWorkDone = processWork(1);
109185
}
110-
static void writeInfo(string message, bool newline = true)
186+
static void hashWorker2()
187+
{
188+
//Boolean to know if thread exits normally
189+
bool hasExitedAfterWorkDone = processWork(2);
190+
}
191+
static void hashWorker3()
192+
{
193+
//Boolean to know if thread exits normally
194+
bool hasExitedAfterWorkDone = processWork(3);
195+
}
196+
static void hashWorker4()
197+
{
198+
//Boolean to know if thread exits normally
199+
bool hasExitedAfterWorkDone = processWork(4);
200+
}
201+
202+
static void showHeader()
111203
{
112204
ConsoleColor oldColor = Console.ForegroundColor;
113205
Console.ForegroundColor = ConsoleColor.Green;
114-
if (newline)
115-
{
116-
Console.WriteLine(message);
117-
}
118-
else
119-
{
120-
Console.Write(message);
121-
}
206+
Console.WriteLine("GTAHash");
122207
Console.ForegroundColor = oldColor;
208+
Console.WriteLine("@ScarszRawr / github.com/Scarsz/GTAHash\n");
123209
}
124-
static string getResponse(string message)
210+
static string getHash(string filepath)
125211
{
126-
ConsoleColor oldColor = Console.ForegroundColor;
127-
writeInfo(message);
128-
Console.ForegroundColor = ConsoleColor.White;
129-
Console.Write("Response [\"y\"=yes \"n\"=no]: ");
130-
string response = Console.ReadKey().Key.ToString().ToLower();
131-
if (response == "y")
132-
{
133-
Console.WriteLine("\n");
134-
return response;
135-
}
136-
else if (response == "n")
137-
{
138-
Console.WriteLine("\n");
139-
return response;
140-
}
141-
else
212+
using (var md5 = MD5.Create())
142213
{
143-
Console.ForegroundColor = ConsoleColor.Red;
144-
Console.WriteLine("\nInvalid response \"" + response + "\", this was a very simple question.");
145-
Console.ForegroundColor = oldColor;
146-
Environment.Exit(1);
214+
using (var stream = File.OpenRead(filepath))
215+
{
216+
return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
217+
}
147218
}
148-
Console.WriteLine();
149-
Console.ForegroundColor = oldColor;
150-
return response;
151219
}
152-
static bool areWeDeleting()
220+
static void reportResult(string info, string result)
153221
{
154-
string deleteFiles = getResponse("Do you want to automatically delete files that do not match?");
155-
156-
if (deleteFiles == "y")
222+
Console.Title = "GTAHash | Hashed files: " + hashQueue.Count + "/" + fileList.Count;
223+
ConsoleColor oldColor = Console.BackgroundColor;
224+
switch (result)
157225
{
158-
return true;
159-
}
160-
else
161-
{
162-
return false;
226+
case "good":
227+
Console.BackgroundColor = goodColor;
228+
Console.WriteLine(" " + info);
229+
goodCount++;
230+
break;
231+
case "bad":
232+
Console.BackgroundColor = badColor;
233+
Console.WriteLine(" " + info);
234+
badCount++;
235+
break;
236+
case "unknown":
237+
Console.BackgroundColor = unknownColor;
238+
Console.WriteLine(" " + info);
239+
unknownCount++;
240+
break;
163241
}
242+
Console.BackgroundColor = oldColor;
243+
}
244+
static void writeHash(string file, string fileHash, string thread)
245+
{
246+
Console.Title = "GTAHash | Hashed files: " + writeQueue.Count + "/" + fileList.Count;
247+
Console.WriteLine("Thread " + thread + ": Writing hash \"" + fileHash + "\" of \"" + file + "\"");
248+
//if (!File.Exists(hashFile))
249+
// File.Create(hashFile);
250+
using (StreamWriter sw = File.AppendText(hashFile))
251+
sw.WriteLine(file + " " + fileHash);
164252
}
165253
}
166254
}

0 commit comments

Comments
 (0)