Browse Source

Add md5 hashing for menus

ghorsington 4 years ago
parent
commit
e10f48dd75
1 changed files with 80 additions and 38 deletions
  1. 80 38
      COM3D2.CacheEditMenu/Hooks.cs

+ 80 - 38
COM3D2.CacheEditMenu/Hooks.cs

@@ -1,9 +1,14 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.IO;
+using System.Linq;
 using System.Reflection;
 using System.Reflection.Emit;
+using System.Security.Cryptography;
+using System.Text;
 using UnityEngine;
+using Debug = UnityEngine.Debug;
 
 namespace COM3D2.CacheEditMenu
 {
@@ -24,7 +29,7 @@ namespace COM3D2.CacheEditMenu
 
     public static class Hooks
     {
-        private const int CACHE_VERSION = 1011;
+        private const int CACHE_VERSION = 1020;
 
         private static readonly Dictionary<string, MenuInfo> infoCache = new Dictionary<string, MenuInfo>();
         private static BinaryWriter cacheWriter;
@@ -170,53 +175,84 @@ namespace COM3D2.CacheEditMenu
             return true;
         }
 
-        private static void Init()
+        private static byte[] HashMenus(string[] menuList)
         {
-            if (cacheWriter != null)
-                return;
-            var cacheDir = Path.Combine(Patcher.Patcher.SybarisPath, "EditMenuCache");
-            var cachePath = Path.Combine(cacheDir, "EditMenuCache.dat");
+            var md5 = MD5.Create();
 
-            var rebuildCache = false;
+            foreach (var s in menuList)
+            {
+                var buf = Encoding.Unicode.GetBytes(s);
+                md5.TransformBlock(buf, 0, buf.Length, null, 0);
+            }
 
-            Directory.CreateDirectory(cacheDir);
+            md5.TransformFinalBlock(new byte[0], 0, 0);
+
+            return md5.Hash;
+        }
 
-            if (File.Exists(cachePath))
-                using (var br = new BinaryReader(File.Open(cachePath, FileMode.Open, FileAccess.Read)))
+        private static bool ReadCache(string cachePath)
+        {
+            if (!File.Exists(cachePath)) 
+                return false;
+            using (var br = new BinaryReader(File.Open(cachePath, FileMode.Open, FileAccess.Read)))
+            {
+                try
                 {
-                    try
+                    var cacheVer = br.ReadInt32();
+
+                    if (cacheVer != CACHE_VERSION)
                     {
-                        int cacheVer = br.ReadInt32();
-                        int menuFilesCount = br.ReadInt32();
-                        int modMenuFilesCount = br.ReadInt32();
-                        
-                        if (cacheVer == CACHE_VERSION && 
-                            menuFilesCount == GameUty.MenuFiles.Length && 
-                            modMenuFilesCount == GameUty.ModOnlysMenuFiles.Length)
-                        {
-                            while (true)
-                            {
-                                var menuInfo = new MenuInfo();
-                                menuInfo.Deserialize(br);
-                                infoCache[menuInfo.key] = menuInfo;
-                            }
-                        }
-                        else
-                        {
-                            Debug.LogWarning("Outdated cache, rebuilding...");
-                            rebuildCache = true;
-                        }
+                        Debug.LogWarning("Old cache version, rebuilding...");
+                        return false;
                     }
-                    catch (FormatException e)
+
+                    var menuFilesHashSize = br.ReadInt32();
+                    var menuFilesHash = br.ReadBytes(menuFilesHashSize);
+                    if (!menuFilesHash.SequenceEqual(HashMenus(GameUty.MenuFiles)))
                     {
-                        Debug.Log($"Failed to deserialize cache because {e.Message}. Rebuilding the cache...");
-                        rebuildCache = true;
+                        Debug.LogWarning(".menu files changed, rebuilding cache...");
+                        return false;
                     }
-                    catch (EndOfStreamException)
+                            
+                    var modMenuFilesHashSize = br.ReadInt32();
+                    var modMenuFilesHash = br.ReadBytes(modMenuFilesHashSize);
+                    if (!modMenuFilesHash.SequenceEqual(HashMenus(GameUty.ModOnlysMenuFiles)))
                     {
-                        // End of file, no need to read more
+                        Debug.LogWarning("Mod .menu files changed, rebuilding cache...");
+                        return false;
+                    }
+                        
+                    while (true)
+                    {
+                        var menuInfo = new MenuInfo();
+                        menuInfo.Deserialize(br);
+                        infoCache[menuInfo.key] = menuInfo;
                     }
                 }
+                catch (FormatException e)
+                {
+                    Debug.Log($"Failed to deserialize cache because {e.Message}. Rebuilding the cache...");
+                    return false;
+                }
+                catch (EndOfStreamException)
+                {
+                    // End of file, no need to read more
+                }
+            }
+
+            return true;
+        }
+
+        private static void Init()
+        {
+            if (cacheWriter != null)
+                return;
+            var cacheDir = Path.Combine(Patcher.Patcher.SybarisPath, "EditMenuCache");
+            var cachePath = Path.Combine(cacheDir, "EditMenuCache.dat");
+
+            Directory.CreateDirectory(cacheDir);
+
+            var rebuildCache = !ReadCache(cachePath);
 
             var stream = rebuildCache ? File.Create(cachePath) : File.OpenWrite(cachePath);
             cacheWriter = new BinaryWriter(stream);
@@ -224,8 +260,14 @@ namespace COM3D2.CacheEditMenu
             if (rebuildCache)
             {
                 cacheWriter.Write(CACHE_VERSION);
-                cacheWriter.Write(GameUty.MenuFiles.Length);
-                cacheWriter.Write(GameUty.ModOnlysMenuFiles.Length);
+                var menuHash = HashMenus(GameUty.MenuFiles);
+                var modMenuHash = HashMenus(GameUty.ModOnlysMenuFiles);
+                
+                cacheWriter.Write(menuHash.Length);
+                cacheWriter.Write(menuHash);
+                
+                cacheWriter.Write(modMenuHash.Length);
+                cacheWriter.Write(modMenuHash);
                 
                 foreach (var keyValuePair in infoCache)
                     keyValuePair.Value.Serialize(cacheWriter);