using Google.FlatBuffers; using System.Data.SQLite; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using SCHALE.Common.Crypto.XXHash; using SCHALE.Common.FlatData; using System.Reflection; using System.Text; using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; namespace SCHALE.Common.Crypto { public static class TableService { /// /// General password gen by file name, encode to base64 for zips password /// /// /// /// public static byte[] CreatePassword(string key, int length = 20) { byte[] password = GC.AllocateUninitializedArray((int)Math.Round((decimal)(length / 4 * 3))); using var xxhash = XXHash32.Create(); xxhash.ComputeHash(Encoding.UTF8.GetBytes(key)); var mt = new MersenneTwister((int)xxhash.HashUInt32); int i = 0; while (i < password.Length) { Array.Copy(BitConverter.GetBytes(mt.Next()), 0, password, i, Math.Min(4, password.Length - i)); i += 4; } return password; } #if DEBUG public static List GetExcelList(Type type, string exceldbDir, string schema) { var excelList = new List(); using (var dbConnection = new SQLiteConnection($"Data Source = {exceldbDir}")) { dbConnection.Open(); var command = dbConnection.CreateCommand(); command.CommandText = $"SELECT Bytes FROM {schema}"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { excelList.Add(type.GetMethod($"GetRootAs{type.Name}", BindingFlags.Static | BindingFlags.Public, [typeof(ByteBuffer)])! .Invoke(null, [new ByteBuffer((byte[])reader[0])])); } } } return excelList; } public static void DumpExcelDB(string exceldbDir, string destDir) { Directory.CreateDirectory(destDir); using (var dbConnection = new SQLiteConnection($"Data Source = {exceldbDir}")) { dbConnection.Open(); string query = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';"; using (var command = new SQLiteCommand(query, dbConnection)) using (var reader = command.ExecuteReader()) { while (reader.Read()) { string dbSchemaName = reader.GetString(0); string excelName = dbSchemaName.Replace("DBSchema", "Excel"); var type = Assembly.GetAssembly(typeof(AcademyFavorScheduleExcelTable))!.GetTypes().Where(t => t.IsAssignableTo(typeof(IFlatbufferObject)) && (t.Name.Equals(excelName))).FirstOrDefault(); var list = GetExcelList(type, exceldbDir, dbSchemaName); File.WriteAllText(Path.Join(destDir, $"{type.Name}.json"), JsonConvert.SerializeObject(list, Formatting.Indented, new StringEnumConverter())); Console.WriteLine($"Dumped {type.Name} from {dbSchemaName} successfully"); } } } } public static void DumpExcels(string bytesDir, string destDir) { Directory.CreateDirectory(destDir); foreach (var type in Assembly.GetAssembly(typeof(AcademyFavorScheduleExcelTable))!.GetTypes().Where(t => t.IsAssignableTo(typeof(IFlatbufferObject)) && t.Name.EndsWith("ExcelTable"))) { var bytesFilePath = Path.Join(bytesDir, $"{type.Name}.bytes"); if (!File.Exists(bytesFilePath)) { Console.WriteLine($"bytes files for {type.Name} not found. skipping..."); continue; } var bytes = File.ReadAllBytes(bytesFilePath); TableEncryptionService.XOR(type.Name, bytes); var inst = type.GetMethod($"GetRootAs{type.Name}", BindingFlags.Static | BindingFlags.Public, [typeof(ByteBuffer)])!.Invoke(null, [new ByteBuffer(bytes)]); var obj = type.GetMethod("UnPack", BindingFlags.Instance | BindingFlags.Public)!.Invoke(inst, null); File.WriteAllText(Path.Join(destDir, $"{type.Name}.json"), JsonConvert.SerializeObject(obj, Formatting.Indented, new StringEnumConverter())); Console.WriteLine($"Dumped {type.Name} successfully"); } } #endif } }