Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Server Localization v1.1.5
ServerLocalization.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Data; using System.Diagnostics; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Xml.Serialization; using BepInEx; using BepInEx.Logging; using HarmonyLib; using fastJSON; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Server Localization")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Server Localization")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("88250b6d-b4c0-4b84-b61d-fb38502b6266")] [assembly: AssemblyFileVersion("1.1.5")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.5.0")] [module: UnverifiableCode] internal class Helper { public static void WatchFileChanges(string path, Action onChanged) { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); string directoryName = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); fileSystemWatcher.Path = directoryName; fileSystemWatcher.Filter = fileName; fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastWrite; fileSystemWatcher.Changed += delegate { onChanged?.Invoke(); }; fileSystemWatcher.Deleted += delegate { onChanged?.Invoke(); }; fileSystemWatcher.Created += delegate { onChanged?.Invoke(); }; fileSystemWatcher.Renamed += delegate { onChanged?.Invoke(); }; fileSystemWatcher.EnableRaisingEvents = true; } public static void WatchFolderChanges(string path, Action onChanged) { WatchFileChanges(Path.Combine(path, "*.*"), onChanged); } } internal class Log { private static Log _instance; private ManualLogSource _source; public static void CreateInstance(ManualLogSource source) { _instance = new Log { _source = source }; } private Log() { } public static void Info(object msg) { _instance._source.LogInfo((object)FormatMessage(msg)); } public static void Message(object msg) { _instance._source.LogMessage((object)FormatMessage(msg)); } public static void Debug(object msg) { _instance._source.LogDebug((object)FormatMessage(msg)); } public static void Warning(object msg) { _instance._source.LogWarning((object)FormatMessage(msg)); } public static void Error(object msg) { _instance._source.LogError((object)FormatMessage(msg)); } public static void Fatal(object msg) { _instance._source.LogFatal((object)FormatMessage(msg)); } private static string FormatMessage(object msg) { return $"[{DateTime.UtcNow}] {msg}"; } } namespace ServerLocalization { internal class LocalizationData : ISerializableParameter { private Dictionary<string, Dictionary<string, string>> _localizationData = new Dictionary<string, Dictionary<string, string>>(); private ZPackage _tempPkg = new ZPackage(); public void ClearAll() { _localizationData.Clear(); } public void Deserialize(ref ZPackage pkg) { Log.Debug($"Received server localization package. Size: {pkg.Size()}"); _localizationData.Clear(); _tempPkg = pkg.ReadCompressedPackage(); int num = _tempPkg.ReadInt(); for (int i = 0; i < num; i++) { int num2 = _tempPkg.ReadInt(); string key = _tempPkg.ReadString(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); _localizationData[key] = dictionary; for (int j = 0; j < num2; j++) { dictionary.Add(_tempPkg.ReadString(), _tempPkg.ReadString()); } } } public void Serialize(ref ZPackage pkg) { _tempPkg.Clear(); _tempPkg.Write(_localizationData.Count); foreach (KeyValuePair<string, Dictionary<string, string>> localizationDatum in _localizationData) { _tempPkg.Write(localizationDatum.Value.Count); _tempPkg.Write(localizationDatum.Key); foreach (KeyValuePair<string, string> item in localizationDatum.Value) { _tempPkg.Write(item.Key); _tempPkg.Write(item.Value); } } pkg.WriteCompressed(_tempPkg); Log.Debug($"Sent server localization package. Size: {pkg.Size()}"); } public void SetData(LocalizationData localizationData) { _localizationData = localizationData._localizationData; } public void AddLocalization(string language, Dictionary<string, string> keys) { if (!_localizationData.TryGetValue(language, out var value)) { value = new Dictionary<string, string>(); _localizationData.Add(language, value); } foreach (KeyValuePair<string, string> key in keys) { value[key.Key] = key.Value; } } public IReadOnlyCollection<string> GetLanguages() { return _localizationData.Keys; } public IReadOnlyDictionary<string, string> GetTranslations(string language) { if (!_localizationData.TryGetValue(language, out var value)) { return null; } return value; } public override string ToString() { int num = _localizationData.Sum((KeyValuePair<string, Dictionary<string, string>> language) => language.Value.Count); return $"Languages {_localizationData.Count}. Keys {num}"; } } [BepInPlugin("org.tristan.serverlocalization", "Server Localization", "1.1.5")] internal class Plugin : BaseUnityPlugin { [HarmonyPatch] private class Patches { private static bool _localizationInitialized; [HarmonyPostfix] [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static void ZNet_OnNewConnection(ZNet __instance, ZNetPeer peer) { if (!__instance.IsServer()) { peer.m_rpc.Register<LocalizationData>("ServerLocalization_LocalizationDataRpc", (Action<ZRpc, LocalizationData>)OnLocalizationDataReceived); } } [HarmonyPostfix] [HarmonyPatch(typeof(ZNet), "SendPeerInfo")] private static void ZNet_SendPeerInfo(ZNet __instance, ZRpc rpc) { if (__instance.IsServer()) { rpc.Invoke("ServerLocalization_LocalizationDataRpc", new object[1] { _localizationData }); } } [HarmonyPostfix] [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static void Localization_Initialize(Localization __instance) { SetupServerLocalization(__instance, __instance.GetSelectedLanguage()); _localizationInitialized = true; } [HarmonyPostfix] [HarmonyPatch(typeof(Localization), "SetupLanguage")] private static void Localization_SetupLanguage(Localization __instance, string language) { if (_localizationInitialized) { SetupServerLocalization(__instance, language); } } private static void OnLocalizationDataReceived(ZRpc arg1, LocalizationData localizationData) { _localizationData.SetData(localizationData); Log.Info($"Server localization received. {localizationData}"); Localization instance = Localization.instance; SetupServerLocalization(instance, instance.GetSelectedLanguage()); } private static void SetupServerLocalization(Localization localization, string language) { IReadOnlyCollection<string> languages = _localizationData.GetLanguages(); if (languages.Contains("English")) { AddTranslations(localization, "English"); } if (!string.Equals("English", language) && languages.Contains(language)) { AddTranslations(localization, language); } } private static void AddTranslations(Localization localization, string language) { IReadOnlyDictionary<string, string> translations = _localizationData.GetTranslations(language); Log.Info("Added server localization " + language); foreach (KeyValuePair<string, string> item in translations) { localization.AddWord(item.Key.TrimStart(new char[1] { '$' }), item.Value); Log.Debug("Added server localization key " + item.Key + "->" + item.Value); } } } private const string DefaultLanguage = "English"; public const string Guid = "org.tristan.serverlocalization"; public const string Name = "Server Localization"; public const string Version = "1.1.5"; private const string LocalizationDataRpc = "ServerLocalization_LocalizationDataRpc"; private static LocalizationData _localizationData = new LocalizationData(); private void Awake() { Log.CreateInstance(((BaseUnityPlugin)this).Logger); string directory = Path.Combine(Paths.ConfigPath, "ServerLocalization"); LoadLocalizationData(directory); Helper.WatchFolderChanges(directory, delegate { LoadLocalizationData(directory); }); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "org.tristan.serverlocalization"); } private void LoadLocalizationData(string directory) { if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } string[] files = Directory.GetFiles(directory, "*.json", SearchOption.AllDirectories); foreach (string text in files) { try { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string fileNameWithoutExtension2 = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(text)); Dictionary<string, string> keys = JSON.ToObject<Dictionary<string, string>>(File.ReadAllText(text)); _localizationData.AddLocalization(fileNameWithoutExtension2, keys); Log.Info("Loaded server localization " + fileNameWithoutExtension + ", language " + fileNameWithoutExtension2); } catch (Exception ex) { Log.Error("Cannot parse localization file " + text + ": " + ex.Message + "\n" + ex.StackTrace); } } } } } namespace fastJSON { internal class DynamicJson : DynamicObject, IEnumerable { private IDictionary<string, object> _dictionary { get; set; } private List<object> _list { get; set; } public DynamicJson(string json) { object obj = JSON.Parse(json); if (obj is IDictionary<string, object>) { _dictionary = (IDictionary<string, object>)obj; } else { _list = (List<object>)obj; } } private DynamicJson(object dictionary) { if (dictionary is IDictionary<string, object>) { _dictionary = (IDictionary<string, object>)dictionary; } } public override IEnumerable<string> GetDynamicMemberNames() { return _dictionary.Keys.ToList(); } public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { object obj = indexes[0]; if (obj is int) { result = _list[(int)obj]; } else { result = _dictionary[(string)obj]; } if (result is IDictionary<string, object>) { result = new DynamicJson(result as IDictionary<string, object>); } return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (!_dictionary.TryGetValue(binder.Name, out result) && !_dictionary.TryGetValue(binder.Name.ToLowerInvariant(), out result)) { return false; } if (result is IDictionary<string, object>) { result = new DynamicJson(result as IDictionary<string, object>); } else if (result is List<object>) { List<object> list = new List<object>(); foreach (object item in (List<object>)result) { if (item is IDictionary<string, object>) { list.Add(new DynamicJson(item as IDictionary<string, object>)); } else { list.Add(item); } } result = list; } return _dictionary.ContainsKey(binder.Name); } IEnumerator IEnumerable.GetEnumerator() { foreach (object item in _list) { yield return new DynamicJson(item as IDictionary<string, object>); } } } internal sealed class DatasetSchema { public List<string> Info; public string Name; } internal class DataMemberAttribute : Attribute { public string Name { get; set; } } internal static class Formatter { private static void AppendIndent(StringBuilder sb, int count, string indent) { while (count > 0) { sb.Append(indent); count--; } } public static string PrettyPrint(string input) { return PrettyPrint(input, new string(' ', JSON.Parameters.FormatterIndentSpaces)); } public static string PrettyPrint(string input, string spaces) { StringBuilder stringBuilder = new StringBuilder(); int num = 0; int length = input.Length; char[] array = input.ToCharArray(); for (int i = 0; i < length; i++) { char c = array[i]; if (c == '"') { bool flag = true; while (flag) { stringBuilder.Append(c); c = array[++i]; switch (c) { case '\\': stringBuilder.Append(c); c = array[++i]; break; case '"': flag = false; break; } } } switch (c) { case '[': case '{': stringBuilder.Append(c); stringBuilder.AppendLine(); AppendIndent(stringBuilder, ++num, spaces); break; case ']': case '}': stringBuilder.AppendLine(); AppendIndent(stringBuilder, --num, spaces); stringBuilder.Append(c); break; case ',': stringBuilder.Append(c); stringBuilder.AppendLine(); AppendIndent(stringBuilder, num, spaces); break; case ':': stringBuilder.Append(" : "); break; default: if (!char.IsWhiteSpace(c)) { stringBuilder.Append(c); } break; } } return stringBuilder.ToString(); } } internal class Helper { public static bool IsNullable(Type t) { if (!t.IsGenericType) { return false; } Type genericTypeDefinition = t.GetGenericTypeDefinition(); return genericTypeDefinition.Equals(typeof(Nullable<>)); } public static Type UnderlyingTypeOf(Type t) { return Reflection.Instance.GetGenericArguments(t)[0]; } public static DateTimeOffset CreateDateTimeOffset(int year, int month, int day, int hour, int min, int sec, int milli, int extraTicks, TimeSpan offset) { DateTimeOffset dateTimeOffset = new DateTimeOffset(year, month, day, hour, min, sec, milli, offset); if (extraTicks > 0) { return dateTimeOffset + TimeSpan.FromTicks(extraTicks); } return dateTimeOffset; } public static bool BoolConv(object v) { bool result = false; if (v is bool) { result = (bool)v; } else if (v is long) { result = (((long)v > 0) ? true : false); } else if (v is string) { string text = (string)v; switch (text.ToLowerInvariant()) { case "1": case "true": case "yes": case "on": result = true; break; } } return result; } public static long AutoConv(object value, JSONParameters param) { if (value is string) { if (param.AutoConvertStringToNumbers) { string text = (string)value; return CreateLong(text, 0, text.Length); } throw new Exception("AutoConvertStringToNumbers is disabled for converting string : " + value); } if (value is long) { return (long)value; } return Convert.ToInt64(value); } public unsafe static long CreateLong(string s, int index, int count) { long num = 0L; int num2 = 1; fixed (char* ptr = s) { char* ptr2 = ptr; ptr2 += index; if (*ptr2 == '-') { num2 = -1; ptr2++; count--; } if (*ptr2 == '+') { ptr2++; count--; } while (count > 0) { num = num * 10 + (*ptr2 - 48); ptr2++; count--; } } return num * num2; } public unsafe static long CreateLong(char[] s, int index, int count) { long num = 0L; int num2 = 1; fixed (char* ptr = s) { char* ptr2 = ptr; ptr2 += index; if (*ptr2 == '-') { num2 = -1; ptr2++; count--; } if (*ptr2 == '+') { ptr2++; count--; } while (count > 0) { num = num * 10 + (*ptr2 - 48); ptr2++; count--; } } return num * num2; } public unsafe static int CreateInteger(string s, int index, int count) { int num = 0; int num2 = 1; fixed (char* ptr = s) { char* ptr2 = ptr; ptr2 += index; if (*ptr2 == '-') { num2 = -1; ptr2++; count--; } if (*ptr2 == '+') { ptr2++; count--; } while (count > 0) { num = num * 10 + (*ptr2 - 48); ptr2++; count--; } } return num * num2; } public static object CreateEnum(Type pt, object v) { return Enum.Parse(pt, v.ToString(), ignoreCase: true); } public static Guid CreateGuid(string s) { if (s.Length > 30) { return new Guid(s); } return new Guid(Convert.FromBase64String(s)); } public static StringDictionary CreateSD(Dictionary<string, object> d) { StringDictionary stringDictionary = new StringDictionary(); foreach (KeyValuePair<string, object> item in d) { stringDictionary.Add(item.Key, (string)item.Value); } return stringDictionary; } public static NameValueCollection CreateNV(Dictionary<string, object> d) { NameValueCollection nameValueCollection = new NameValueCollection(); foreach (KeyValuePair<string, object> item in d) { nameValueCollection.Add(item.Key, (string)item.Value); } return nameValueCollection; } public static object CreateDateTimeOffset(string value) { int milli = 0; int extraTicks = 0; int num = 0; int num2 = 0; int year = CreateInteger(value, 0, 4); int month = CreateInteger(value, 5, 2); int day = CreateInteger(value, 8, 2); int hour = CreateInteger(value, 11, 2); int min = CreateInteger(value, 14, 2); int sec = CreateInteger(value, 17, 2); int num3 = 20; if (value.Length > 21 && value[19] == '.') { milli = CreateInteger(value, num3, 3); num3 = 23; if (value.Length > 25 && char.IsDigit(value[num3])) { extraTicks = CreateInteger(value, num3, 4); num3 = 27; } } if (value[num3] == 'Z') { return CreateDateTimeOffset(year, month, day, hour, min, sec, milli, extraTicks, TimeSpan.Zero); } if (value[num3] == ' ') { num3++; } num = CreateInteger(value, num3 + 1, 2); num2 = CreateInteger(value, num3 + 1 + 2 + 1, 2); if (value[num3] == '-') { num = -num; } return CreateDateTimeOffset(year, month, day, hour, min, sec, milli, extraTicks, new TimeSpan(num, num2, 0)); } public static DateTime CreateDateTime(string value, bool UseUTCDateTime) { if (value.Length < 19) { return DateTime.MinValue; } bool flag = false; int millisecond = 0; int year = CreateInteger(value, 0, 4); int month = CreateInteger(value, 5, 2); int day = CreateInteger(value, 8, 2); int hour = CreateInteger(value, 11, 2); int minute = CreateInteger(value, 14, 2); int second = CreateInteger(value, 17, 2); if (value.Length > 21 && value[19] == '.') { millisecond = CreateInteger(value, 20, 3); } if (value[value.Length - 1] == 'Z') { flag = true; } if (!UseUTCDateTime && !flag) { return new DateTime(year, month, day, hour, minute, second, millisecond); } return new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc).ToLocalTime(); } } internal sealed class JSONSerializer { private StringBuilder _output = new StringBuilder(); private int _before; private int _MAX_DEPTH = 20; private int _current_depth; private Dictionary<string, int> _globalTypes = new Dictionary<string, int>(); private Dictionary<object, int> _cirobj; private JSONParameters _params; private bool _useEscapedUnicode; private bool _TypesWritten; internal JSONSerializer(JSONParameters param) { if (param.OverrideObjectHashCodeChecking) { _cirobj = new Dictionary<object, int>(10, ReferenceEqualityComparer.Default); } else { _cirobj = new Dictionary<object, int>(); } _params = param; _useEscapedUnicode = _params.UseEscapedUnicode; _MAX_DEPTH = _params.SerializerMaxDepth; } internal string ConvertToJSON(object obj) { WriteValue(obj); if (_params.UsingGlobalTypes && _globalTypes != null && _globalTypes.Count > 0) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("\"$types\":{"); bool flag = false; foreach (KeyValuePair<string, int> globalType in _globalTypes) { if (flag) { stringBuilder.Append(','); } flag = true; stringBuilder.Append('"'); stringBuilder.Append(globalType.Key); stringBuilder.Append("\":\""); stringBuilder.Append(globalType.Value); stringBuilder.Append('"'); } stringBuilder.Append("},"); _output.Insert(_before, stringBuilder.ToString()); } return _output.ToString(); } private void WriteValue(object obj) { if (obj == null || obj is DBNull) { _output.Append("null"); } else if (obj is string || obj is char) { WriteString(obj.ToString()); } else if (obj is Guid) { WriteGuid((Guid)obj); } else if (obj is bool) { _output.Append(((bool)obj) ? "true" : "false"); } else if (obj is int || obj is long || obj is decimal || obj is byte || obj is short || obj is sbyte || obj is ushort || obj is uint || obj is ulong) { _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); } else if (obj is double || obj is double) { double d = (double)obj; if (double.IsNaN(d)) { _output.Append("\"NaN\""); } else if (double.IsInfinity(d)) { _output.Append('"'); _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); _output.Append('"'); } else { _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); } } else if (obj is float || obj is float) { float f = (float)obj; if (float.IsNaN(f)) { _output.Append("\"NaN\""); } else if (float.IsInfinity(f)) { _output.Append('"'); _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); _output.Append('"'); } else { _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); } } else if (obj is DateTime) { WriteDateTime((DateTime)obj); } else if (obj is DateTimeOffset) { WriteDateTimeOffset((DateTimeOffset)obj); } else if (obj is TimeSpan) { _output.Append(((TimeSpan)obj).Ticks); } else if (!_params.KVStyleStringDictionary && obj is IEnumerable<KeyValuePair<string, object>>) { WriteStringDictionary((IEnumerable<KeyValuePair<string, object>>)obj); } else if (!_params.KVStyleStringDictionary && obj is IDictionary && obj.GetType().IsGenericType && Reflection.Instance.GetGenericArguments(obj.GetType())[0] == typeof(string)) { WriteStringDictionary((IDictionary)obj); } else if (obj is IDictionary) { WriteDictionary((IDictionary)obj); } else if (obj is DataSet) { WriteDataset((DataSet)obj); } else if (obj is DataTable) { WriteDataTable((DataTable)obj); } else if (obj is byte[]) { WriteBytes((byte[])obj); } else if (obj is StringDictionary) { WriteSD((StringDictionary)obj); } else if (obj is NameValueCollection) { WriteNV((NameValueCollection)obj); } else if (obj is Array) { WriteArrayRanked((Array)obj); } else if (obj is IEnumerable) { WriteArray((IEnumerable)obj); } else if (obj is Enum) { WriteEnum((Enum)obj); } else if (Reflection.Instance.IsTypeRegistered(obj.GetType())) { WriteCustom(obj); } else { WriteObject(obj); } } private void WriteDateTimeOffset(DateTimeOffset d) { DateTime dt = (_params.UseUTCDateTime ? d.UtcDateTime : d.DateTime); write_date_value(dt); long num = dt.Ticks % 10000000; _output.Append('.'); _output.Append(num.ToString("0000000", NumberFormatInfo.InvariantInfo)); if (_params.UseUTCDateTime) { _output.Append('Z'); } else { if (d.Offset.Hours > 0) { _output.Append('+'); } else { _output.Append('-'); } _output.Append(d.Offset.Hours.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append(':'); _output.Append(d.Offset.Minutes.ToString("00", NumberFormatInfo.InvariantInfo)); } _output.Append('"'); } private void WriteNV(NameValueCollection nameValueCollection) { _output.Append('{'); bool flag = false; foreach (string item in nameValueCollection) { if (_params.SerializeNullValues || nameValueCollection[item] != null) { if (flag) { _output.Append(','); } if (_params.SerializeToLowerCaseNames) { WritePair(item.ToLowerInvariant(), nameValueCollection[item]); } else { WritePair(item, nameValueCollection[item]); } flag = true; } } _output.Append('}'); } private void WriteSD(StringDictionary stringDictionary) { _output.Append('{'); bool flag = false; foreach (DictionaryEntry item in stringDictionary) { if (_params.SerializeNullValues || item.Value != null) { if (flag) { _output.Append(','); } string text = (string)item.Key; if (_params.SerializeToLowerCaseNames) { WritePair(text.ToLowerInvariant(), item.Value); } else { WritePair(text, item.Value); } flag = true; } } _output.Append('}'); } private void WriteCustom(object obj) { Reflection.Instance._customSerializer.TryGetValue(obj.GetType(), out var value); WriteStringFast(value(obj)); } private void WriteEnum(Enum e) { if (_params.UseValuesOfEnums) { WriteValue(Convert.ToInt32(e)); } else { WriteStringFast(e.ToString()); } } private void WriteGuid(Guid g) { if (!_params.UseFastGuid) { WriteStringFast(g.ToString()); } else { WriteBytes(g.ToByteArray()); } } private void WriteBytes(byte[] bytes) { WriteStringFast(Convert.ToBase64String(bytes, 0, bytes.Length, Base64FormattingOptions.None)); } private void WriteDateTime(DateTime dateTime) { DateTime dt = dateTime; if (_params.UseUTCDateTime) { dt = dateTime.ToUniversalTime(); } write_date_value(dt); if (_params.DateTimeMilliseconds) { _output.Append('.'); _output.Append(dt.Millisecond.ToString("000", NumberFormatInfo.InvariantInfo)); } if (_params.UseUTCDateTime) { _output.Append('Z'); } _output.Append('"'); } private void write_date_value(DateTime dt) { _output.Append('"'); _output.Append(dt.Year.ToString("0000", NumberFormatInfo.InvariantInfo)); _output.Append('-'); _output.Append(dt.Month.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append('-'); _output.Append(dt.Day.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append('T'); _output.Append(dt.Hour.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append(':'); _output.Append(dt.Minute.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append(':'); _output.Append(dt.Second.ToString("00", NumberFormatInfo.InvariantInfo)); } private DatasetSchema GetSchema(DataTable ds) { if (ds == null) { return null; } DatasetSchema datasetSchema = new DatasetSchema(); datasetSchema.Info = new List<string>(); datasetSchema.Name = ds.TableName; foreach (DataColumn column in ds.Columns) { datasetSchema.Info.Add(ds.TableName); datasetSchema.Info.Add(column.ColumnName); if (_params.FullyQualifiedDataSetSchema) { datasetSchema.Info.Add(column.DataType.AssemblyQualifiedName); } else { datasetSchema.Info.Add(column.DataType.ToString()); } } return datasetSchema; } private DatasetSchema GetSchema(DataSet ds) { if (ds == null) { return null; } DatasetSchema datasetSchema = new DatasetSchema(); datasetSchema.Info = new List<string>(); datasetSchema.Name = ds.DataSetName; foreach (DataTable table in ds.Tables) { foreach (DataColumn column in table.Columns) { datasetSchema.Info.Add(table.TableName); datasetSchema.Info.Add(column.ColumnName); if (_params.FullyQualifiedDataSetSchema) { datasetSchema.Info.Add(column.DataType.AssemblyQualifiedName); } else { datasetSchema.Info.Add(column.DataType.ToString()); } } } return datasetSchema; } private string GetXmlSchema(DataTable dt) { using StringWriter writer = new StringWriter(); dt.WriteXmlSchema(writer); return dt.ToString(); } private void WriteDataset(DataSet ds) { _output.Append('{'); if (_params.UseExtensions) { WritePair("$schema", _params.UseOptimizedDatasetSchema ? ((object)GetSchema(ds)) : ((object)ds.GetXmlSchema())); _output.Append(','); } bool flag = false; foreach (DataTable table in ds.Tables) { if (flag) { _output.Append(','); } flag = true; WriteDataTableData(table); } _output.Append('}'); } private void WriteDataTableData(DataTable table) { _output.Append('"'); _output.Append(table.TableName); _output.Append("\":["); DataColumnCollection columns = table.Columns; bool flag = false; foreach (DataRow row in table.Rows) { if (flag) { _output.Append(','); } flag = true; _output.Append('['); bool flag2 = false; foreach (DataColumn item in columns) { if (flag2) { _output.Append(','); } WriteValue(row[item]); flag2 = true; } _output.Append(']'); } _output.Append(']'); } private void WriteDataTable(DataTable dt) { _output.Append('{'); if (_params.UseExtensions) { WritePair("$schema", _params.UseOptimizedDatasetSchema ? ((object)GetSchema(dt)) : ((object)GetXmlSchema(dt))); _output.Append(','); } WriteDataTableData(dt); _output.Append('}'); } private void WriteObject(object obj) { int value = 0; if (!_cirobj.TryGetValue(obj, out value)) { _cirobj.Add(obj, _cirobj.Count + 1); } else if (_current_depth > 0 && !_params.InlineCircularReferences) { _output.Append("{\"$i\":"); _output.Append(value.ToString()); _output.Append('}'); return; } if (!_params.UsingGlobalTypes) { _output.Append('{'); } else if (!_TypesWritten) { _output.Append('{'); _before = _output.Length; } else { _output.Append('{'); } _TypesWritten = true; _current_depth++; if (_current_depth > _MAX_DEPTH) { throw new Exception("Serializer encountered maximum depth of " + _MAX_DEPTH); } Dictionary<string, string> dictionary = new Dictionary<string, string>(); Type type = obj.GetType(); bool flag = false; if (_params.UseExtensions) { if (!_params.UsingGlobalTypes) { WritePairFast("$type", Reflection.Instance.GetTypeAssemblyName(type)); } else { int value2 = 0; string typeAssemblyName = Reflection.Instance.GetTypeAssemblyName(type); if (!_globalTypes.TryGetValue(typeAssemblyName, out value2)) { value2 = _globalTypes.Count + 1; _globalTypes.Add(typeAssemblyName, value2); } WritePairFast("$type", value2.ToString()); } flag = true; } Getters[] getters = Reflection.Instance.GetGetters(type, _params.IgnoreAttributes); int num = getters.Length; for (int i = 0; i < num; i++) { Getters getters2 = getters[i]; if (!_params.ShowReadOnlyProperties && getters2.ReadOnly) { continue; } object obj2 = getters2.Getter(obj); if (!_params.SerializeNullValues && (obj2 == null || obj2 is DBNull)) { continue; } if (flag) { _output.Append(','); } if (getters2.memberName != null) { WritePair(getters2.memberName, obj2); } else if (_params.SerializeToLowerCaseNames) { WritePair(getters2.lcName, obj2); } else { WritePair(getters2.Name, obj2); } if (obj2 != null && _params.UseExtensions) { Type type2 = obj2.GetType(); if (type2 == typeof(object)) { dictionary.Add(getters2.Name, type2.ToString()); } } flag = true; } if (dictionary.Count > 0 && _params.UseExtensions) { _output.Append(",\"$map\":"); WriteStringDictionary(dictionary); } _output.Append('}'); _current_depth--; } private void WritePairFast(string name, string value) { WriteStringFast(name); _output.Append(':'); WriteStringFast(value); } private void WritePair(string name, object value) { WriteString(name); _output.Append(':'); WriteValue(value); } private void WriteArray(IEnumerable array) { _output.Append('['); bool flag = false; foreach (object item in array) { if (flag) { _output.Append(','); } WriteValue(item); flag = true; } _output.Append(']'); } private void WriteArrayRanked(Array array) { if (array.Rank == 1) { WriteArray(array); return; } _output.Append('['); bool flag = false; foreach (object item in array) { if (flag) { _output.Append(','); } WriteValue(item); flag = true; } _output.Append(']'); } private void WriteStringDictionary(IDictionary dic) { _output.Append('{'); bool flag = false; foreach (DictionaryEntry item in dic) { if (_params.SerializeNullValues || item.Value != null) { if (flag) { _output.Append(','); } string text = (string)item.Key; if (_params.SerializeToLowerCaseNames) { WritePair(text.ToLowerInvariant(), item.Value); } else { WritePair(text, item.Value); } flag = true; } } _output.Append('}'); } private void WriteStringDictionary(IEnumerable<KeyValuePair<string, object>> dic) { _output.Append('{'); bool flag = false; foreach (KeyValuePair<string, object> item in dic) { if (_params.SerializeNullValues || item.Value != null) { if (flag) { _output.Append(','); } string key = item.Key; if (_params.SerializeToLowerCaseNames) { WritePair(key.ToLowerInvariant(), item.Value); } else { WritePair(key, item.Value); } flag = true; } } _output.Append('}'); } private void WriteDictionary(IDictionary dic) { _output.Append('['); bool flag = false; foreach (DictionaryEntry item in dic) { if (flag) { _output.Append(','); } _output.Append('{'); WritePair("k", item.Key); _output.Append(','); WritePair("v", item.Value); _output.Append('}'); flag = true; } _output.Append(']'); } private void WriteStringFast(string s) { _output.Append('"'); _output.Append(s); _output.Append('"'); } private void WriteString(string s) { _output.Append('"'); int num = -1; int length = s.Length; for (int i = 0; i < length; i++) { char c = s[i]; if (_useEscapedUnicode) { if (c >= ' ' && c < '\u0080' && c != '"' && c != '\\') { if (num == -1) { num = i; } continue; } } else if (c != '\t' && c != '\n' && c != '\r' && c != '"' && c != '\\' && c != 0) { if (num == -1) { num = i; } continue; } if (num != -1) { _output.Append(s, num, i - num); num = -1; } switch (c) { case '\t': _output.Append('\\').Append('t'); continue; case '\r': _output.Append('\\').Append('r'); continue; case '\n': _output.Append('\\').Append('n'); continue; case '"': case '\\': _output.Append('\\'); _output.Append(c); continue; case '\0': _output.Append("\\u0000"); continue; } if (_useEscapedUnicode) { _output.Append("\\u"); StringBuilder output = _output; int num2 = c; output.Append(num2.ToString("X4", NumberFormatInfo.InvariantInfo)); } else { _output.Append(c); } } if (num != -1) { _output.Append(s, num, s.Length - num); } _output.Append('"'); } } internal sealed class JSONParameters { public bool UseOptimizedDatasetSchema = true; public bool UseFastGuid = true; public bool SerializeNullValues = true; public bool UseUTCDateTime = true; public bool ShowReadOnlyProperties; public bool UsingGlobalTypes = true; [Obsolete("Not needed anymore and will always match")] public bool IgnoreCaseOnDeserialize; public bool EnableAnonymousTypes; public bool UseExtensions = true; public bool UseEscapedUnicode = true; public bool KVStyleStringDictionary; public bool UseValuesOfEnums; public List<Type> IgnoreAttributes = new List<Type> { typeof(XmlIgnoreAttribute), typeof(NonSerializedAttribute) }; public bool ParametricConstructorOverride; public bool DateTimeMilliseconds; public byte SerializerMaxDepth = 20; public bool InlineCircularReferences; public bool SerializeToLowerCaseNames; public byte FormatterIndentSpaces = 3; public bool AllowNonQuotedKeys; public bool AutoConvertStringToNumbers = true; public bool OverrideObjectHashCodeChecking; [Obsolete("Racist term removed, please use BadListTypeChecking")] public bool BlackListTypeChecking = true; public bool BadListTypeChecking = true; public bool FullyQualifiedDataSetSchema; public void FixValues() { if (!UseExtensions) { UsingGlobalTypes = false; InlineCircularReferences = true; } if (EnableAnonymousTypes) { ShowReadOnlyProperties = true; } } public JSONParameters MakeCopy() { return new JSONParameters { AllowNonQuotedKeys = AllowNonQuotedKeys, DateTimeMilliseconds = DateTimeMilliseconds, EnableAnonymousTypes = EnableAnonymousTypes, FormatterIndentSpaces = FormatterIndentSpaces, IgnoreAttributes = new List<Type>(IgnoreAttributes), InlineCircularReferences = InlineCircularReferences, KVStyleStringDictionary = KVStyleStringDictionary, ParametricConstructorOverride = ParametricConstructorOverride, SerializeNullValues = SerializeNullValues, SerializerMaxDepth = SerializerMaxDepth, SerializeToLowerCaseNames = SerializeToLowerCaseNames, ShowReadOnlyProperties = ShowReadOnlyProperties, UseEscapedUnicode = UseEscapedUnicode, UseExtensions = UseExtensions, UseFastGuid = UseFastGuid, UseOptimizedDatasetSchema = UseOptimizedDatasetSchema, UseUTCDateTime = UseUTCDateTime, UseValuesOfEnums = UseValuesOfEnums, UsingGlobalTypes = UsingGlobalTypes, AutoConvertStringToNumbers = AutoConvertStringToNumbers, OverrideObjectHashCodeChecking = OverrideObjectHashCodeChecking, FullyQualifiedDataSetSchema = FullyQualifiedDataSetSchema, BadListTypeChecking = BadListTypeChecking }; } } internal static class JSON { public static JSONParameters Parameters = new JSONParameters(); public static string ToNiceJSON(object obj) { string input = ToJSON(obj, Parameters); return Beautify(input); } public static string ToNiceJSON(object obj, JSONParameters param) { string input = ToJSON(obj, param); return Beautify(input, param.FormatterIndentSpaces); } public static string ToJSON(object obj) { return ToJSON(obj, Parameters); } public static string ToJSON(object obj, JSONParameters param) { param.FixValues(); param = param.MakeCopy(); Type c = null; if (obj == null) { return "null"; } if (obj.GetType().IsGenericType) { c = Reflection.Instance.GetGenericTypeDefinition(obj.GetType()); } if (typeof(IDictionary).IsAssignableFrom(c) || typeof(List<>).IsAssignableFrom(c)) { param.UsingGlobalTypes = false; } if (param.EnableAnonymousTypes) { param.UseExtensions = false; param.UsingGlobalTypes = false; } return new JSONSerializer(param).ConvertToJSON(obj); } public static object Parse(string json) { return new JsonParser(json, Parameters.AllowNonQuotedKeys).Decode(null); } public static dynamic ToDynamic(string json) { return new DynamicJson(json); } public static T ToObject<T>(string json) { return new deserializer(Parameters).ToObject<T>(json); } public static T ToObject<T>(string json, JSONParameters param) { return new deserializer(param).ToObject<T>(json); } public static object ToObject(string json) { return new deserializer(Parameters).ToObject(json, null); } public static object ToObject(string json, JSONParameters param) { return new deserializer(param).ToObject(json, null); } public static object ToObject(string json, Type type) { return new deserializer(Parameters).ToObject(json, type); } public static object ToObject(string json, Type type, JSONParameters par) { return new deserializer(par).ToObject(json, type); } public static object FillObject(object input, string json) { if (!(new JsonParser(json, Parameters.AllowNonQuotedKeys).Decode(input.GetType()) is Dictionary<string, object> d)) { return null; } return new deserializer(Parameters).ParseDictionary(d, null, input.GetType(), input); } public static object DeepCopy(object obj) { return new deserializer(Parameters).ToObject(ToJSON(obj)); } public static T DeepCopy<T>(T obj) { return new deserializer(Parameters).ToObject<T>(ToJSON(obj)); } public static string Beautify(string input) { string spaces = new string(' ', Parameters.FormatterIndentSpaces); return Formatter.PrettyPrint(input, spaces); } public static string Beautify(string input, byte spaces) { string spaces2 = new string(' ', spaces); return Formatter.PrettyPrint(input, spaces2); } public static void RegisterCustomType(Type type, Reflection.Serialize serializer, Reflection.Deserialize deserializer) { Reflection.Instance.RegisterCustomType(type, serializer, deserializer); } public static void ClearReflectionCache() { Reflection.Instance.ClearReflectionCache(); } } internal class deserializer { private JSONParameters _params; private bool _usingglobals; private Dictionary<object, int> _circobj; private Dictionary<int, object> _cirrev = new Dictionary<int, object>(); public deserializer(JSONParameters param) { if (param.OverrideObjectHashCodeChecking) { _circobj = new Dictionary<object, int>(10, ReferenceEqualityComparer.Default); } else { _circobj = new Dictionary<object, int>(); } param.FixValues(); _params = param.MakeCopy(); } public T ToObject<T>(string json) { Type typeFromHandle = typeof(T); object obj = ToObject(json, typeFromHandle); if (typeFromHandle.IsArray) { if ((obj as ICollection).Count == 0) { Type elementType = typeFromHandle.GetElementType(); object obj2 = Array.CreateInstance(elementType, 0); return (T)obj2; } return (T)obj; } return (T)obj; } public object ToObject(string json) { return ToObject(json, null); } public object ToObject(string json, Type type) { Type type2 = null; if (type != null && type.IsGenericType) { type2 = Reflection.Instance.GetGenericTypeDefinition(type); } _usingglobals = _params.UsingGlobalTypes; if (typeof(IDictionary).IsAssignableFrom(type2) || typeof(List<>).IsAssignableFrom(type2)) { _usingglobals = false; } object obj = new JsonParser(json, _params.AllowNonQuotedKeys).Decode(type); if (obj == null) { return null; } if (type != null) { if (type == typeof(DataSet)) { return CreateDataset(obj as Dictionary<string, object>, null); } if (type == typeof(DataTable)) { return CreateDataTable(obj as Dictionary<string, object>, null); } } if (obj is IDictionary) { if (type != null && typeof(Dictionary<, >).IsAssignableFrom(type2)) { return RootDictionary(obj, type); } return ParseDictionary(obj as Dictionary<string, object>, null, type, null); } if (obj is List<object>) { if (!(type != null)) { List<object> list = (List<object>)obj; if (list.Count > 0 && list[0].GetType() == typeof(Dictionary<string, object>)) { Dictionary<string, object> globaltypes = new Dictionary<string, object>(); List<object> list2 = new List<object>(); { foreach (object item in list) { list2.Add(ParseDictionary((Dictionary<string, object>)item, globaltypes, null, null)); } return list2; } } return list.ToArray(); } if (typeof(Dictionary<, >).IsAssignableFrom(type2)) { return RootDictionary(obj, type); } if (type2 == typeof(List<>)) { return RootList(obj, type); } if (type.IsArray) { return RootArray(obj, type); } if (type == typeof(Hashtable)) { return RootHashTable((List<object>)obj); } } else if (type != null && obj.GetType() != type) { return ChangeType(obj, type); } return obj; } private object RootHashTable(List<object> o) { Hashtable hashtable = new Hashtable(); foreach (Dictionary<string, object> item in o) { object obj = item["k"]; object obj2 = item["v"]; if (obj is Dictionary<string, object>) { obj = ParseDictionary((Dictionary<string, object>)obj, null, typeof(object), null); } if (obj2 is Dictionary<string, object>) { obj2 = ParseDictionary((Dictionary<string, object>)obj2, null, typeof(object), null); } hashtable.Add(obj, obj2); } return hashtable; } private object ChangeType(object value, Type conversionType) { if (conversionType == typeof(object)) { return value; } if (conversionType == typeof(int)) { if (!(value is string text)) { return (int)(long)value; } if (_params.AutoConvertStringToNumbers) { return Helper.CreateInteger(text, 0, text.Length); } throw new Exception("AutoConvertStringToNumbers is disabled for converting string : " + value); } if (conversionType == typeof(long)) { if (!(value is string text2)) { return (long)value; } if (_params.AutoConvertStringToNumbers) { return Helper.CreateLong(text2, 0, text2.Length); } throw new Exception("AutoConvertStringToNumbers is disabled for converting string : " + value); } if (conversionType == typeof(string)) { return (string)value; } if (conversionType.IsEnum) { return Helper.CreateEnum(conversionType, value); } if (conversionType == typeof(DateTime)) { return Helper.CreateDateTime((string)value, _params.UseUTCDateTime); } if (conversionType == typeof(DateTimeOffset)) { return Helper.CreateDateTimeOffset((string)value); } if (Reflection.Instance.IsTypeRegistered(conversionType)) { return Reflection.Instance.CreateCustom((string)value, conversionType); } if (Helper.IsNullable(conversionType)) { if (value == null) { return value; } conversionType = Helper.UnderlyingTypeOf(conversionType); } if (conversionType == typeof(Guid)) { return Helper.CreateGuid((string)value); } if (conversionType == typeof(byte[])) { return Convert.FromBase64String((string)value); } if (conversionType == typeof(TimeSpan)) { return new TimeSpan((long)value); } return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture); } private object RootList(object parse, Type type) { Type[] genericArguments = Reflection.Instance.GetGenericArguments(type); IList list = (IList)Reflection.Instance.FastCreateList(type, ((IList)parse).Count); DoParseList((IList)parse, genericArguments[0], list); return list; } private void DoParseList(IList parse, Type it, IList o) { Dictionary<string, object> globaltypes = new Dictionary<string, object>(); foreach (object item in parse) { _usingglobals = false; object obj = item; obj = ((!(item is Dictionary<string, object> d)) ? ChangeType(item, it) : ParseDictionary(d, globaltypes, it, null)); o.Add(obj); } } private object RootArray(object parse, Type type) { Type elementType = type.GetElementType(); IList list = (IList)Reflection.Instance.FastCreateInstance(typeof(List<>).MakeGenericType(elementType)); DoParseList((IList)parse, elementType, list); Array array = Array.CreateInstance(elementType, list.Count); list.CopyTo(array, 0); return array; } private object RootDictionary(object parse, Type type) { Type[] genericArguments = Reflection.Instance.GetGenericArguments(type); Type type2 = null; Type type3 = null; bool flag = false; if (genericArguments != null) { type2 = genericArguments[0]; type3 = genericArguments[1]; if (type3 != null) { flag = type3.Name.StartsWith("Dictionary"); } } Type elementType = type3.GetElementType(); if (parse is Dictionary<string, object>) { IDictionary dictionary = (IDictionary)Reflection.Instance.FastCreateInstance(type); { foreach (KeyValuePair<string, object> item in (Dictionary<string, object>)parse) { object key = ChangeType(item.Key, type2); object value = ((!flag) ? ((!(item.Value is Dictionary<string, object>)) ? ((type3.IsArray && type3 != typeof(byte[])) ? CreateArray((List<object>)item.Value, type3, elementType, null) : ((!(item.Value is IList)) ? ChangeType(item.Value, type3) : CreateGenericList((List<object>)item.Value, type3, type2, null))) : ParseDictionary(item.Value as Dictionary<string, object>, null, type3, null)) : RootDictionary(item.Value, type3)); dictionary.Add(key, value); } return dictionary; } } if (parse is List<object>) { return CreateDictionary(parse as List<object>, type, genericArguments, null); } return null; } internal object ParseDictionary(Dictionary<string, object> d, Dictionary<string, object> globaltypes, Type type, object input) { object value = ""; if (type == typeof(NameValueCollection)) { return Helper.CreateNV(d); } if (type == typeof(StringDictionary)) { return Helper.CreateSD(d); } if (d.TryGetValue("$i", out value)) { object value2 = null; _cirrev.TryGetValue((int)(long)value, out value2); return value2; } if (d.TryGetValue("$types", out value)) { _usingglobals = true; if (globaltypes == null) { globaltypes = new Dictionary<string, object>(); } foreach (KeyValuePair<string, object> item in (Dictionary<string, object>)value) { globaltypes.Add((string)item.Value, item.Key); } } if (globaltypes != null) { _usingglobals = true; } bool flag = d.TryGetValue("$type", out value); if (!flag && type == typeof(object)) { return d; } if (flag) { if (_usingglobals) { object value3 = ""; if (globaltypes != null && globaltypes.TryGetValue((string)value, out value3)) { value = value3; } } type = Reflection.Instance.GetTypeFromCache((string)value, _params.BadListTypeChecking); } if (type == null) { throw new Exception("Cannot determine type : " + value); } string fullName = type.FullName; object obj = input; if (obj == null) { obj = ((!_params.ParametricConstructorOverride) ? Reflection.Instance.FastCreateInstance(type) : FormatterServices.GetUninitializedObject(type)); } int value4 = 0; if (!_circobj.TryGetValue(obj, out value4)) { value4 = _circobj.Count + 1; _circobj.Add(obj, value4); _cirrev.Add(value4, obj); } Dictionary<string, myPropInfo> dictionary = Reflection.Instance.Getproperties(type, fullName, _params.ShowReadOnlyProperties); foreach (KeyValuePair<string, object> item2 in d) { string key = item2.Key; object value5 = item2.Value; string text = key; if (text == "$map") { ProcessMap(obj, dictionary, (Dictionary<string, object>)d[text]); } else { if ((!dictionary.TryGetValue(text, out var value6) && !dictionary.TryGetValue(text.ToLowerInvariant(), out value6)) || !value6.CanWrite) { continue; } object value7 = null; if (value5 != null) { switch (value6.Type) { case myPropInfoType.Int: value7 = (int)Helper.AutoConv(value5, _params); break; case myPropInfoType.Long: value7 = Helper.AutoConv(value5, _params); break; case myPropInfoType.String: value7 = value5.ToString(); break; case myPropInfoType.Bool: value7 = Helper.BoolConv(value5); break; case myPropInfoType.DateTime: value7 = Helper.CreateDateTime((string)value5, _params.UseUTCDateTime); break; case myPropInfoType.Enum: value7 = Helper.CreateEnum(value6.pt, value5); break; case myPropInfoType.Guid: value7 = Helper.CreateGuid((string)value5); break; case myPropInfoType.Array: if (!value6.IsValueType) { value7 = CreateArray((List<object>)value5, value6.pt, value6.bt, globaltypes); } break; case myPropInfoType.ByteArray: value7 = Convert.FromBase64String((string)value5); break; case myPropInfoType.DataSet: value7 = CreateDataset((Dictionary<string, object>)value5, globaltypes); break; case myPropInfoType.DataTable: value7 = CreateDataTable((Dictionary<string, object>)value5, globaltypes); break; case myPropInfoType.Dictionary: case myPropInfoType.Hashtable: value7 = CreateDictionary((List<object>)value5, value6.pt, value6.GenericTypes, globaltypes); break; case myPropInfoType.StringKeyDictionary: value7 = CreateStringKeyDictionary((Dictionary<string, object>)value5, value6.pt, value6.GenericTypes, globaltypes); break; case myPropInfoType.NameValue: value7 = Helper.CreateNV((Dictionary<string, object>)value5); break; case myPropInfoType.StringDictionary: value7 = Helper.CreateSD((Dictionary<string, object>)value5); break; case myPropInfoType.Custom: value7 = Reflection.Instance.CreateCustom((string)value5, value6.pt); break; default: value7 = ((value6.IsGenericType && !value6.IsValueType && value5 is List<object>) ? CreateGenericList((List<object>)value5, value6.pt, value6.bt, globaltypes) : (((value6.IsClass || value6.IsStruct || value6.IsInterface) && value5 is Dictionary<string, object>) ? ParseDictionary((Dictionary<string, object>)value5, globaltypes, value6.pt, null) : ((!(value5 is List<object>)) ? ((!value6.IsValueType) ? value5 : ChangeType(value5, value6.changeType)) : CreateArray((List<object>)value5, value6.pt, typeof(object), globaltypes)))); break; } } obj = value6.setter(obj, value7); } } return obj; } private static void ProcessMap(object obj, Dictionary<string, myPropInfo> props, Dictionary<string, object> dic) { foreach (KeyValuePair<string, object> item in dic) { myPropInfo myPropInfo2 = props[item.Key]; object obj2 = myPropInfo2.getter(obj); Type typeFromCache = Reflection.Instance.GetTypeFromCache((string)item.Value, badlistChecking: true); if (typeFromCache == typeof(Guid)) { myPropInfo2.setter(obj, Helper.CreateGuid((string)obj2)); } } } private object CreateArray(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes) { if (bt == null) { bt = typeof(object); } Array array = Array.CreateInstance(bt, data.Count); Type elementType = bt.GetElementType(); for (int i = 0; i < data.Count; i++) { object obj = data[i]; if (obj != null) { if (obj is IDictionary) { array.SetValue(ParseDictionary((Dictionary<string, object>)obj, globalTypes, bt, null), i); } else if (obj is ICollection) { array.SetValue(CreateArray((List<object>)obj, bt, elementType, globalTypes), i); } else { array.SetValue(ChangeType(obj, bt), i); } } } return array; } private object CreateGenericList(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes) { if (pt != typeof(object)) { IList list = (IList)Reflection.Instance.FastCreateList(pt, data.Count); Type type = Reflection.Instance.GetGenericArguments(pt)[0]; { foreach (object datum in data) { if (datum is IDictionary) { list.Add(ParseDictionary((Dictionary<string, object>)datum, globalTypes, type, null)); } else if (datum is List<object>) { if (bt.IsGenericType) { list.Add((List<object>)datum); } else { list.Add(((List<object>)datum).ToArray()); } } else { list.Add(ChangeType(datum, type)); } } return list; } } return data; } private object CreateStringKeyDictionary(Dictionary<string, object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes) { IDictionary dictionary = (IDictionary)Reflection.Instance.FastCreateInstance(pt); Type type = null; Type type2 = null; if (types != null) { type2 = types[1]; } Type bt = null; Type[] genericArguments = Reflection.Instance.GetGenericArguments(type2); if (genericArguments.Length != 0) { bt = genericArguments[0]; } type = type2.GetElementType(); foreach (KeyValuePair<string, object> item in reader) { string key = item.Key; object obj = null; obj = ((!(item.Value is Dictionary<string, object>)) ? ((types != null && type2.IsArray) ? ((!(item.Value is Array)) ? CreateArray((List<object>)item.Value, type2, type, globalTypes) : item.Value) : ((!(item.Value is IList)) ? ChangeType(item.Value, type2) : CreateGenericList((List<object>)item.Value, type2, bt, globalTypes))) : ParseDictionary((Dictionary<string, object>)item.Value, globalTypes, type2, null)); dictionary.Add(key, obj); } return dictionary; } private object CreateDictionary(List<object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes) { IDictionary dictionary = (IDictionary)Reflection.Instance.FastCreateInstance(pt); Type type = null; Type type2 = null; Type bt = null; if (types != null) { type = types[0]; type2 = types[1]; } Type bt2 = type2; if (type2 != null) { Type[] genericArguments = Reflection.Instance.GetGenericArguments(type2); if (genericArguments.Length != 0) { bt = genericArguments[0]; } bt2 = type2.GetElementType(); } bool flag = typeof(IDictionary).IsAssignableFrom(type2); foreach (Dictionary<string, object> item in reader) { object obj = item["k"]; object obj2 = item["v"]; obj = ((!(obj is Dictionary<string, object>)) ? ChangeType(obj, type) : ParseDictionary((Dictionary<string, object>)obj, globalTypes, type, null)); obj2 = ((!flag) ? ((!(obj2 is Dictionary<string, object>)) ? ((types != null && type2.IsArray) ? CreateArray((List<object>)obj2, type2, bt2, globalTypes) : ((!(obj2 is IList)) ? ChangeType(obj2, type2) : CreateGenericList((List<object>)obj2, type2, bt, globalTypes))) : ParseDictionary((Dictionary<string, object>)obj2, globalTypes, type2, null)) : RootDictionary(obj2, type2)); dictionary.Add(obj, obj2); } return dictionary; } private DataSet CreateDataset(Dictionary<string, object> reader, Dictionary<string, object> globalTypes) { DataSet dataSet = new DataSet(); dataSet.EnforceConstraints = false; dataSet.BeginInit(); object obj = reader["$schema"]; if (obj is string) { TextReader reader2 = new StringReader((string)obj); dataSet.ReadXmlSchema(reader2); } else { DatasetSchema datasetSchema = (DatasetSchema)ParseDictionary((Dictionary<string, object>)obj, globalTypes, typeof(DatasetSchema), null); dataSet.DataSetName = datasetSchema.Name; for (int i = 0; i < datasetSchema.Info.Count; i += 3) { if (!dataSet.Tables.Contains(datasetSchema.Info[i])) { dataSet.Tables.Add(datasetSchema.Info[i]); } Type typeFromCache = Reflection.Instance.GetTypeFromCache(datasetSchema.Info[i + 2], badlistChecking: true); dataSet.Tables[datasetSchema.Info[i]].Columns.Add(datasetSchema.Info[i + 1], typeFromCache); } } foreach (KeyValuePair<string, object> item in reader) { if (!(item.Key == "$type") && !(item.Key == "$schema")) { List<object> list = (List<object>)item.Value; if (list != null) { DataTable dt = dataSet.Tables[item.Key]; ReadDataTable(list, dt); } } } dataSet.EndInit(); return dataSet; } private void ReadDataTable(List<object> rows, DataTable dt) { dt.BeginInit(); dt.BeginLoadData(); List<int> list = new List<int>(); List<int> list2 = new List<int>(); List<int> list3 = new List<int>(); foreach (DataColumn column in dt.Columns) { if (column.DataType == typeof(Guid) || column.DataType == typeof(Guid?)) { list.Add(column.Ordinal); } if (_params.UseUTCDateTime && (column.DataType == typeof(DateTime) || column.DataType == typeof(DateTime?))) { list2.Add(column.Ordinal); } if (column.DataType == typeof(byte[])) { list3.Add(column.Ordinal); } } foreach (List<object> row in rows) { List<object> list5 = row; foreach (int item in list) { string text = (string)list5[item]; if (text != null && text.Length < 36) { list5[item] = new Guid(Convert.FromBase64String(text)); } } foreach (int item2 in list3) { string text2 = (string)list5[item2]; if (text2 != null) { list5[item2] = Convert.FromBase64String(text2); } } if (_params.UseUTCDateTime) { foreach (int item3 in list2) { string text3 = (string)list5[item3]; if (text3 != null) { list5[item3] = Helper.CreateDateTime(text3, _params.UseUTCDateTime); } } } dt.Rows.Add(list5.ToArray()); } dt.EndLoadData(); dt.EndInit(); } private DataTable CreateDataTable(Dictionary<string, object> reader, Dictionary<string, object> globalTypes) { DataTable dataTable = new DataTable(); object obj = reader["$schema"]; if (obj is string) { TextReader reader2 = new StringReader((string)obj); dataTable.ReadXmlSchema(reader2); } else { DatasetSchema datasetSchema = (DatasetSchema)ParseDictionary((Dictionary<string, object>)obj, globalTypes, typeof(DatasetSchema), null); dataTable.TableName = datasetSchema.Info[0]; for (int i = 0; i < datasetSchema.Info.Count; i += 3) { Type typeFromCache = Reflection.Instance.GetTypeFromCache(datasetSchema.Info[i + 2], badlistChecking: true); dataTable.Columns.Add(datasetSchema.Info[i + 1], typeFromCache); } } foreach (KeyValuePair<string, object> item in reader) { if (!(item.Key == "$type") && !(item.Key == "$schema")) { List<object> list = (List<object>)item.Value; if (list != null && dataTable.TableName.Equals(item.Key, StringComparison.InvariantCultureIgnoreCase)) { ReadDataTable(list, dataTable); } } } return dataTable; } } internal sealed class JsonParser { private enum Token { None = -1, Curly_Open, Curly_Close, Squared_Open, Squared_Close, Colon, Comma, String, Number, True, False, Null, PosInfinity, NegInfinity, NaN } private readonly char[] json; private readonly StringBuilder s = new StringBuilder(); private Token lookAheadToken = Token.None; private int index; private bool allownonquotedkey; private int _len; private SafeDictionary<string, bool> _lookup; private SafeDictionary<Type, bool> _seen; private bool _parseJsonType; private bool _parseType; internal JsonParser(string json, bool AllowNonQuotedKeys) { allownonquotedkey = AllowNonQuotedKeys; this.json = json.ToCharArray(); _len = json.Length; } private void SetupLookup() { _lookup = new SafeDictionary<string, bool>(); _seen = new SafeDictionary<Type, bool>(); _lookup.Add("$types", value: true); _lookup.Add("$type", value: true); _lookup.Add("$i", value: true); _lookup.Add("$map", value: true); _lookup.Add("$schema", value: true); _lookup.Add("k", value: true); _lookup.Add("v", value: true); } public unsafe object Decode(Type objtype) { fixed (char* p = json) { if (objtype != null && !CheckForTypeInJson(p)) { _parseJsonType = true; SetupLookup(); BuildLookup(objtype); if (!_parseJsonType || _lookup.Count() == 7) { _lookup = null; } } return ParseValue(p); } } private unsafe bool CheckForTypeInJson(char* p) { int i = 0; for (int num = ((_len > 1000) ? 1000 : _len); i < num; i++) { if (p[i] == '$' && p[i + 1] == 't' && p[i + 2] == 'y' && p[i + 3] == 'p' && p[i + 4] == 'e' && p[i + 5] == 's') { return true; } } return false; } private void BuildGenericTypeLookup(Type t) { if (_seen.TryGetValue(t, out var _)) { return; } Type[] genericArguments = t.GetGenericArguments(); foreach (Type type in genericArguments) { if (!type.IsPrimitive) { bool flag = type.IsValueType && !type.IsEnum; if ((type.IsClass || flag || type.IsAbstract) && type != typeof(string) && type != typeof(DateTime) && type != typeof(Guid)) { BuildLookup(type); } } } } private void BuildArrayTypeLookup(Type t) { if (!_seen.TryGetValue(t, out var _)) { bool flag = t.IsValueType && !t.IsEnum; if ((t.IsClass || flag) && t != typeof(string) && t != typeof(DateTime) && t != typeof(Guid)) { BuildLookup(t.GetElementType()); } } } private void BuildLookup(Type objtype) { if (objtype == null || objtype == typeof(NameValueCollection) || objtype == typeof(StringDictionary) || typeof(IDictionary).IsAssignableFrom(objtype) || _seen.TryGetValue(objtype, out var _)) { return; } if (objtype.IsGenericType) { BuildGenericTypeLookup(objtype); return; } if (objtype.IsArray) { BuildArrayTypeLookup(objtype); return; } _seen.Add(objtype, value: true); foreach (KeyValuePair<string, myPropInfo> item in Reflection.Instance.Getproperties(objtype, objtype.FullName, ShowReadOnlyProperties: true)) { Type pt = item.Value.pt; _lookup.Add(item.Key.ToLowerInvariant(), value: true); if (pt.IsArray) { BuildArrayTypeLookup(pt); } if (pt.IsGenericType) { if (typeof(IDictionary).IsAssignableFrom(pt)) { _parseJsonType = false; break; } BuildGenericTypeLookup(pt); } if (pt.FullName.IndexOf("System.") == -1) { BuildLookup(pt); } } } private bool InLookup(string name) { if (_lookup == null) { return true; } bool value; return _lookup.TryGetValue(name.ToLowerInvariant(), out value); } private unsafe Dictionary<string, object> ParseObject(char* p) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); continue; case Token.Curly_Close: ConsumeToken(); return dictionary; } string text = ParseKey(p); Token token = NextToken(p); if (token != Token.Colon) { throw new Exception("Expected colon at index " + index); } if (_parseJsonType) { if (text == "$types") { _parseType = true; Dictionary<string, object> dictionary2 = (Dictionary<string, object>)ParseValue(p); _parseType = false; if (_lookup == null) { SetupLookup(); } foreach (string key in dictionary2.Keys) { BuildLookup(Reflection.Instance.GetTypeFromCache(key, badlistChecking: true)); } dictionary[text] = dictionary2; } else if (text == "$schema") { _parseType = true; object value = ParseValue(p); _parseType = false; dictionary[text] = value; } else if (_parseType || InLookup(text)) { dictionary[text] = ParseValue(p); } else { SkipValue(p); } } else { dictionary[text] = ParseValue(p); } } } private unsafe void SkipValue(char* p) { switch (LookAhead(p)) { case Token.Number: ParseNumber(p, skip: true); break; case Token.String: SkipString(p); break; case Token.Curly_Open: SkipObject(p); break; case Token.Squared_Open: SkipArray(p); break; case Token.True: case Token.False: case Token.Null: case Token.PosInfinity: case Token.NegInfinity: case Token.NaN: ConsumeToken(); break; case Token.Curly_Close: case Token.Squared_Close: case Token.Colon: case Token.Comma: break; } } private unsafe void SkipObject(char* p) { ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); continue; case Token.Curly_Close: ConsumeToken(); return; } SkipString(p); Token token = NextToken(p); if (token != Token.Colon) { throw new Exception("Expected colon at index " + index); } SkipValue(p); } } private unsafe void SkipArray(char* p) { ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); break; case Token.Squared_Close: ConsumeToken(); return; default: SkipValue(p); break; } } } private unsafe void SkipString(char* p) { ConsumeToken(); int len = _len; while (index < len) { switch (p[index++]) { case '"': return; case '\\': { char c = p[index++]; if (c == 'u') { index += 4; } break; } } } } private unsafe List<object> ParseArray(char* p) { List<object> list = new List<object>(); ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); break; case Token.Squared_Close: ConsumeToken(); return list; default: list.Add(ParseValue(p)); break; } } } private unsafe object ParseValue(char* p) { switch (LookAhead(p)) { case Token.Number: return ParseNumber(p, skip: false); case Token.String: return ParseString(p); case Token.Curly_Open: return ParseObject(p); case Token.Squared_Open: return ParseArray(p); case Token.True: ConsumeToken(); return true; case Token.False: ConsumeToken(); return false; case Token.Null: ConsumeToken(); return null; case Token.PosInfinity: ConsumeToken(); return double.PositiveInfinity; case Token.NegInfinity: ConsumeToken(); return double.NegativeInfinity; case Token.NaN: ConsumeToken(); return double.NaN; default: throw new Exception("Unrecognized token at index " + index); } } private unsafe string ParseKey(char* p) { if (!allownonquotedkey || p[index - 1] == '"') { return ParseString(p); } ConsumeToken(); int len = _len; int num = 0; while (index + num < len) { char c = p[index + num++]; if (c == ':') { string result = UnsafeSubstring(p, index, num - 1).Trim(); index += num - 1; return result; } } throw new Exception("Unable to read key"); } private unsafe string ParseString(char* p) { char c = p[index - 1]; ConsumeToken(); if (s.Length > 0) { s.Length = 0; } int len = _len; int num = 0; while (index + num < len) { char c2 = p[index + num++]; if (c2 == '\\') { break; } if (c2 == c) { string result = UnsafeSubstring(p, index, num - 1); index += num; return result; } } while (index < len) { char c3 = p[index++]; if (c3 == c) { return s.ToString(); } if (c3 != '\\') { s.Append(c3); continue; } c3 = p[index++]; switch (c3) { case 'b': s.Append('\b'); continue; case 'f': s.Append('\f'); continue; case 'n': s.Append('\n'); continue; case 'r': s.Append('\r'); continue; case 't': s.Append('\t'); continue; case 'u': { uint num2 = ParseUnicode(p[index], p[index + 1], p[index + 2], p[index + 3]); s.Append((char)num2); index += 4; continue; } } if (c3 == '\r' || c3 == '\n' || c3 == ' ' || c3 == '\t') { while (c3 == '\r' || c3 == '\n' || c3 == ' ' || c3 == '\t') { index++; c3 = p[index]; if (c3 == '\r' || c3 == '\n') { c3 = p[index + 1]; if (c3 == '\r' || c3 == '\n') { index += 2; c3 = p[index]; } break; } } } else { s.Append(c3); } } return s.ToString(); } private unsafe string ParseJson5String(char* p) { throw new NotImplementedException(); } private uint ParseSingleChar(char c1, uint multipliyer) { uint result = 0u; if (c1 >= '0' && c1 <= '9') { result = (uint)(c1 - 48) * multipliyer; } else if (c1 >= 'A' && c1 <= 'F') { result = (uint)(c1 - 65 + 10) * multipliyer; } else if (c1 >= 'a' && c1 <= 'f') { result = (uint)(c1 - 97 + 10) * multipliyer; } return result; } private uint ParseUnicode(char c1, char c2, char c3, char c4) { uint num = ParseSingleChar(c1, 4096u); uint num2 = ParseSingleChar(c2, 256u); uint num3 = ParseSingleChar(c3, 16u); uint num4 = ParseSingleChar(c4, 1u); return num + num2 + num3 + num4; } private unsafe object ParseNumber(char* p, bool skip) { ConsumeToken(); int num = index - 1; bool flag = false; bool flag2 = false; bool flag3 = true; if (p[num] == '.') { flag = true; } while (index != _len) { switch (p[index]) { case 'X': case 'x': index++; return ReadHexNumber(p); case '+': case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': index++; break; case 'E': case 'e': flag2 = true; index++; break; case '.': index++; flag = true; break; case 'N': case 'n': index += 3; return double.NaN; default: flag3 = false; break; } if (index == _len) { flag3 = false; } if (!flag3) { break; } } if (skip) { return 0; } int num2 = index - num; if (flag2 || num2 > 31) { string text = UnsafeSubstring(p, num, num2); return double.Parse(text, NumberFormatInfo.InvariantInfo); } if (!flag && num2 < 20) { return Helper.CreateLong(json, num, num2); } string text2 = UnsafeSubstring(p, num, num2); return decimal.Parse(text2, NumberFormatInfo.InvariantInfo); } private unsafe object ReadHexNumber(char* p) { long num = 0L; bool flag = true; while (flag && index < _len) { char c = p[index]; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': index++; num = (num << 4) + (c - 48); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': index++; num = (num << 4) + (c - 97) + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': index++; num = (num << 4) + (c - 65) + 10; break; default: flag = false; break; } } return num; } private unsafe Token LookAhead(char* p) { if (lookAheadToken != Token.None) { return lookAheadToken; } return lookAheadToken = NextTokenCore(p); } private void ConsumeToken() { lookAheadToken = Token.None; } private unsafe Token NextToken(char* p) { Token result = ((lookAheadToken != Token.None) ? lookAheadToken : NextTokenCore(p)); lookAheadToken = Token.None; return result; } private unsafe void SkipWhitespace(char* p) { char c; do { c = p[index]; if (c == '/' && p[index + 1] == '/') { index++; index++; do { c = p[index]; } while (c != '\r' && c != '\n' && ++index < _len); } if (c != '/' || p[index + 1] != '*') { continue; } index++; index++; do { c = p[index]; if (c == '*' && p[index + 1] == '/') { index += 2; c = p[index]; break; } } while (++index < _len); } while ((c == ' ' || c == '\t' || c == '\n' || c == '\r') && ++index < _len); } private unsafe Token NextTokenCore(char* p) { int len = _len; SkipWhitespace(p); if (index == len) { throw new Exception("Reached end of string unexpectedly"); } char c = p[index]; index++; switch (c) { case '{': return Token.Curly_Open; case '}': return Token.Curly_Close; case '[': return Token.Squared_Open; case ']': return Token.Squared_Close; case ',': return Token.Comma; case '"': case '\'': return Token.String; case '-': if (p[index] == 'i' || p[index] == 'I') { index += 8; return Token.NegInfinity; } return Token.Number; case '+': if (p[index] == 'i' || p[index] == 'I') { index += 8; return Token.PosInfinity; } return Token.Number; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return Token.Number; case ':': return Token.Colon; case 'I': case 'i': index += 7; return Token.PosInfinity; case 'f': if (len - index >= 4 && p[index] == 'a' && p[index + 1] == 'l' && p[index + 2] == 's' && p[index + 3] == 'e') { index += 4; return Token.False; } break; case 't': if (len - index >= 3 && p[index] == 'r' && p[index + 1] == 'u' && p[index + 2] == 'e') { index += 3; return Token.True; } break; case 'N': case 'n': if (len - index >= 3 && p[index] == 'u' && p[index + 1] == 'l' && p[index + 2] == 'l') { index += 3; return Token.Null; } if (len - index >= 2 && p[index] == 'a' && (p[index + 1] == 'n' || p[index + 1] == 'N')) { index += 2; return Token.NaN; } break; } if (allownonquotedkey) { index--; return Token.String; } string[] obj = new string[5] { "Could not find token at index ", null, null, null, null }; obj[1] = (--index).ToString(); obj[2] = " got '"; obj[3] = p[index].ToString(); obj[4] = "'"; throw new Exception(string.Concat(obj)); } private unsafe static string UnsafeSubstring(char* p, int startIndex, int length) { return new string(p, startIndex, length); } } internal struct Getters { public string Name; public string lcName; public string memberName; public Reflection.GenericGetter Getter; public bool ReadOnly; } internal enum myPropInfoType { Int, Long, String, Bool, DateTime, Enum, Guid, Array, ByteArray, Dictionary, StringKeyDictionary, NameValue, StringDictionary, Hashtable, DataSet, DataTable, Custom, Unknown } internal class myPropInfo { public Type pt; public Type bt; public Type changeType; public Reflection.GenericSetter setter; public Reflection.GenericGetter getter; public Type[] GenericTypes; public string Name; public string memberName; public myPropInfoType Type; public bool CanWrite; public bool IsClass; public bool IsValueType; public bool IsGenericType; public bool IsStruct; public bool IsInterface; } internal sealed class Reflection { public delegate string Serialize(object data); public delegate object Deserialize(string data); public delegate object GenericSetter(object target, object value); public delegate object GenericGetter(object obj); private delegate object CreateObject(); private delegate object CreateList(int capacity); private static readonly Reflection instance; public static bool RDBMode; private SafeDictionary<Type, string> _tyname = new SafeDictionary<Type, string>(10); private SafeDictionary<string, Type> _typecache = new SafeDictionary<string, Type>(10); private SafeDictionary<Type, CreateObject> _constrcache = new SafeDictionary<Type, CreateObject>(10); private SafeDictionary<Type, CreateList> _conlistcache = new SafeDictionary<Type, CreateList>(10); private SafeDictionary<Type, Getters[]> _getterscache = new SafeDictionary<Type, Getters[]>(10); private SafeDictionary<string, Dictionary<string, myPropInfo>> _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>(10); private SafeDictionary<Type, Type[]> _genericTypes = new SafeDictionary<Type, Type[]>(10); private SafeDictionary<Type, Type> _genericTypeDef = new SafeDictionary<Type, Type>(10); private static SafeDictionary<short, OpCode> _opCodes; private static List<string> _badlistTypes; private static UTF8Encoding utf8; internal SafeDictionary<Type, Serialize> _customSerializer = new SafeDictionary<Type, Serialize>(); internal SafeDictionary<Type, Deserialize> _customDeserializer = new SafeDictionary<Type, Deserialize>(); public static Reflection Instance => instance; static Reflection() { instance = new Reflection(); RDBMode = false; _badlistTypes = new List<string> { "system.configuration.install.assemblyinstaller", "system.activities.presentation.workflowdesigner", "system.windows.resourcedictionary", "system.windows.data.objectdataprovider", "system.windows.forms.bindingsource", "microsoft.exchange.management.systemmanager.winforms.exchangesettingsprovider" }; utf8 = new UTF8Encoding(); } private Reflection() { } private static bool TryGetOpCode(short code, out OpCode opCode) { if (_opCodes != null) { return _opCodes.TryGetValue(code, out opCode); } SafeDictionary<short, OpCode> safeDictionary = new SafeDictionary<short, OpCode>(); FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (typeof(OpCode).IsAssignableFrom(fieldInfo.FieldType)) { OpCode value = (OpCode)fieldInfo.GetValue(null); if (value.OpCodeType != OpCodeType.Nternal) { safeDictionary.Add(value.Value, value); } } } _opCodes = safeDictionary; return _opCodes.TryGetValue(code, out opCode); } public static byte[] UTF8GetBytes(string str) { return utf8.GetBytes(str); } public static string UTF8GetString(byte[] bytes, int offset, int len) { return utf8.GetString(bytes, offset, len); } public unsafe static byte[] UnicodeGetBytes(string str) { int num = str.Length * 2; byte[] array = new byte[num]; fixed (void* value = str) { Marshal.Copy(new IntPtr(value), array, 0, num); } return array; } public static string UnicodeGetString(byte[] b) { return UnicodeGetString(b, 0, b.Length); } public unsafe static string UnicodeGetString(byte[] bytes, int offset, int buflen) { string text = ""; fixed (byte* ptr = bytes) { char* value = (char*)(ptr + offset); text = new string(value, 0, buflen / 2); } return text; } internal object CreateCustom(string v, Type type) { _customDeserializer.TryGetValue(type, out var value); return value(v); } internal void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer) { if (type != null && serializer != null && deserializer != null) { _customSerializer.Add(type, serializer); _customDeserializer.Add(type, deserializer); Instance.ResetPropertyCache(); } } internal bool IsTypeRegistered(Type t) { if (_customSerializer.Count() == 0) { return false; } Serialize value; return _customSerializer.TryGetValue(t, out value); } public Type GetGenericTypeDefinition(Type t) { Type value = null; if (_genericTypeDef.TryGetValue(t, out value)) { return value; } value = t.GetGenericTypeDefinition(); _genericTypeDef.Add(t, value); return value; } public Type[] GetGenericArguments(Type t) { Type[] value = null; if (_genericTypes.TryGetValue(t, out value)) { return value; } value = t.GetGenericArguments(); _genericTypes.Add(t, value); return value; } public Dictionary<string, myPropInfo> Getproperties(Type type, string typename, bool ShowReadOnlyProperties) { Dictionary<string, myPropInfo> value = null; if (_propertycache.TryGetValue(typename, out value)) { return value; } value = new Dictionary<string, myPropInfo>(10); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; PropertyInfo[] properties = type.GetProperties(bindingAttr); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { if (propertyInfo.GetIndexParameters().Length != 0) { continue; } myPropInfo myPropInfo2 = CreateMyProp(propertyInfo.PropertyType, propertyInfo.Name); myPropInfo2.setter = CreateSetMethod(type, propertyInfo, ShowReadOnlyProperties); if (myPropInfo2.setter != null) { myPropInfo2.CanWrite = true; } myPropInfo2.getter = CreateGetMethod(type, propertyInfo); object[] customAttributes = propertyInfo.GetCustomAttributes(inherit: true); object[] array2 = customAttributes; foreach (object obj in array2) { if (obj is System.Runtime.Serialization.DataMemberAttribute) { System.Runtime.Serialization.DataMemberAttribute dataMemberAttribute = (System.Runtime.Serialization.DataMemberAttribute)obj; if (dataMemberAttribute.Name != "") { myPropInfo2.memberName = dataMemberAttribute.Name; } } if (obj is DataMemberAttribute) { DataMemberAttribute dataMemberAttribute2 = (DataMemberAttribute)obj; if (dataMemberAttribute2.Name != "") { myPropInfo2.memberName = dataMemberAttribute2.Name; } } } if (myPropInfo2.memberName != null) { value.Add(myPropInfo2.memberName, myPropInfo2); } else { value.Add(propertyInfo.Name.ToLowerInvariant(), myPropInfo2); } } FieldInfo[] fields = type.GetFields(bindingAttr); FieldInfo[] array3 = fields; foreach (FieldInfo fieldInfo in array3) { myPropInfo myPropInfo3 = CreateMyProp(fieldInfo.FieldType, fieldInfo.Name); if (fieldInfo.IsLiteral) { continue; } if (!fieldInfo.IsInitOnly) { myPropInfo3.setter = CreateSetField(type, fieldInfo); } if (myPropInfo3.setter != null) { myPropInfo3.CanWrite = true; } myPropInfo3.getter = CreateGetField(type, fieldInfo); object[] customAttributes2 = fieldInfo.GetCustomAttributes(inherit: true); object[] array4 = customAttributes2; foreach (object obj2 in array4) { if (obj2 is System.Runtime.Serialization.DataMemberAttribute) { System.Runtime.Serialization.DataMemberAttribute dataMemberAttribute3 = (System.Runtime.Serialization.DataMemberAttribute)obj2; if (dataMemberAttribute3.Name != "") { myPropInfo3.memberName = dataMemberAttribute3.Name; } } if (obj2 is DataMemberAttribute) { DataMemberAttribute dataMemberAttribute4 = (DataMemberAttribute)obj2; if (dataMemberAttribute4.Name != "") { myPropInfo3.memberName = dataMemberAttribute4.Name; } } } if (myPropInfo3.memberName != null) { value.Add(myPropInfo3.memberName, myPropInfo3); } else { value.Add(fieldInfo.Name.ToLowerInvariant(), myPropInfo3); } } _propertycache.Add(typename, value); return value; } private myPropInfo CreateMyProp(Type t, string name) { myPropInfo myPropInfo2 = new myPropInfo(); myPropInfoType type = myPropInfoType.Unknown; if (t == typeof(int) || t == typeof(int?)) { type = myPropInfoType.Int; } else if (t == typeof(long) || t == typeof(long?)) { type = myPropInfoType.Long; } else if (t == typeof(string)) { type = myPropInfoType.String; } else if (t == typeof(bool) || t == typeof(bool?)) { type = myPropInfoType.Bool; } else if (t == typeof(DateTime) || t == typeof(DateTime?)) { type = myPropInfoType.DateTime; } else if (t.IsEnum) { type = myPropInfoType.Enum; } else if (t == typeof(Guid) || t == typeof(Guid?)) { type = myPropInfoType.Guid; } else if (t == typeof(StringDictionary)) { type = myPropInfoType.StringDictionary; } else if (t == typeof(NameValueCollection)) { type = myPropInfoType.NameValue; } else if (t.IsArray) { myPropInfo2.bt = t.GetElementType(); type = ((!(t == typeof(byte[]))) ? myPropInfoType.Array : myPropInfoType.ByteArray); } else if (t.Name.Contains("Dictionary")) { myPropInfo2.GenericTypes = Instance.GetGenericArguments(t); type = ((myPropInfo2.GenericTypes.Length == 0 || !(myPropInfo2.GenericTypes[0] == typeof(string))) ? myPropInfoType.Dictionary : myPropInfoType.StringKeyDictionary); } else if (t == typeof(Hashtable)) { type = myPropInfoType.Hashtable; } else if (t == typeof(DataSet)) { type = myPropInfoType.DataSet; } else if (t == typeof(DataTable)) { type = myPropInfoType.DataTable; } else if (IsTypeRegistered(t)) { type = myPropInfoType.Custom; } if (t.IsValueType && !t.IsPrimitive && !t.IsEnum && t != typeof(decimal)) { myPropInfo2.IsStruct = true; } myPropInfo2.IsInterface = t.IsInterface; myPropInfo2.IsClass = t.IsClass; myPropInfo2.IsValueType = t.IsValueType; if (t.IsGenericType) { myPropInfo2.IsGenericType = true; myPropInfo2.bt = Instance.GetGenericArguments(t)[0]; } myPropInfo2.pt = t; myPropInfo2.Name = name; myPropInfo2.changeType = GetChangeType(t); myPropInfo2.Type = type; return myPropInfo2; } private Type GetChangeType(Type conversionType) { if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { return Instance.GetGenericArguments(conversionType)[0]; } return conversionType; } public string GetTypeAssemblyName(Type t) { string value = ""; if (_tyname.TryGetValue(t, out value)) { return value; } string assemblyQualifiedName = t.AssemblyQualifiedName; _tyname.Add(t, assemblyQualifiedName); return assemblyQualifiedName; } internal Type GetTypeFromCache(string typename, bool badlistChecking) { Type value = null; if (_typecache.TryGetValue(typename, out value)) { return value; } if (badlistChecking) { string text = typename.Trim().ToLowerInvariant(); foreach (string badlistType in _badlistTypes) { if (text.StartsWith(badlistType, StringComparison.Ordinal)) { throw new Exception("Black list type encountered, possible attack vector when using $type : " + typename); } } } Type type = Type.GetType(typename); if (RDBMode && type == null) { type = Type.GetType(typename, (AssemblyName name) => (from z in AppDomain.CurrentDomain.GetAssemblies() where z.FullName == name.FullName select z).FirstOrDefault(), null, throwOnError: true); } _typecache.Add(typename, type); return type; } internal object FastCreateList(Type objtype, int capacity) { try { int capacity2 = 10; if (capacity > 10) { capacity2 = capacity; } CreateList value = null; if (_conlistcache.TryGetValue(objtype, out value)) { if (value != null) { return value(capacity2); } return FastCreateInstance(objtype); } ConstructorInfo constructor = objtype.GetConstructor(new Type[1] { typeof(int) }); if (constructor != null) { DynamicMethod dynamicMethod = new DynamicMethod("_fcil", objtype, new Type[1] { typeof(int) }, restrictedSkipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Newobj, objtype.GetConstructor(new Type[1] { typeof(int) })); iLGenerator.Emit(OpCodes.Ret); value = (CreateList)dynamicMethod.CreateDelegate(typeof(CreateList)); _conlistcache.Add(objtype, value); return value(capacity2); } _conlistcache.Add(objtype, null); return FastCreateInstance(objtype); } catch (Exception innerException) { throw new Exception($"Failed to fast create instance for type '{objtype.FullName}' from assembly '{objtype.AssemblyQualifiedName}'", innerException); } } internal object FastCreateInstance(Type objtype) { try { CreateObject value = null; if (_constrcache.TryGetValue(objtype, out value)) { return value(); } if (objtype.IsClass) { DynamicMethod dynamicMethod = new DynamicMethod("_fcic", objtype, null, restrictedSkipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes)); iLGenerator.Emit(OpCodes.Ret); value = (CreateObject)dynamicMethod.CreateDelegate(typeof(CreateObject)); _constrcache.Add(objtype, value); } else { DynamicMethod dynamicMethod2 = new DynamicMethod("_fcis", typeof(object), null, restrictedSkipVisibility: true); ILGenerator iLGenerator2 = dynamicMethod2.GetILGenerator(); LocalBuilder local = iLGenerator2.DeclareLocal(objtype); iLGenerator2.Emit(OpCodes.Ldloca_S, local); iLGenerator2.Emit(OpCodes.Initobj, objtype); iLGenerator2.Emit(OpCodes.Ldloc_0); iLGenerator2.Emit(OpCodes.Box, objtype); iLGenerator2.Emit(OpCodes.Ret); value = (CreateObject)dynamicMethod2.CreateDelegate(typeof(CreateObject)); _constrcache.Add(objtype, value); } return value(); } catch (Exception innerException) { throw new Exception($"Failed to fast create instance for type '{objtype.FullName}' from assembly '{objtype.AssemblyQualifiedName}'", innerException); } } internal static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo) { Type[] array = new Type[2]; array[0] = (array[1] = typeof(object)); DynamicMethod dynamicMethod = new DynamicMethod("_csf", typeof(object), array, type, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!type.IsClass) { LocalBuilder local = iLGenerator.DeclareLocal(type); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Unbox_Any, type); iLGenerator.Emit(OpCodes.Stloc_0); iLGenerator.Emit(OpCodes.Ldloca_S, local); iLGenerator.Emit(OpCodes.Ldarg_1); if (fieldInfo.FieldType.IsClass) { iLGenerator.Emit(OpCodes.Castclass, fieldInfo.FieldType); } else { iLGenerator.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); } iLGenerator.Emit(OpCodes.Stfld, fieldInfo); iLGenerator.Emit(OpCodes.Ldloc_0); iLGenerator.Emit(OpCodes.Box, type); iLGenerator.Emit(OpCodes.Ret); } else { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); if (fieldInfo.FieldType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType); } iLGenerator.Emit(OpCodes.Stfld, fieldInfo); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ret); } return (GenericSetter)dynamicMethod.CreateDelegate(typeof(GenericSetter)); } internal static FieldInfo GetGetterBackingField(PropertyInfo autoProperty) { MethodInfo getMethod = autoProperty.GetGetMethod(); if (!getMethod.IsDefined(typeof(CompilerGeneratedAttribute), inherit: false)) { return null; } byte[] array = getMethod.GetMethodBody()?.GetILAsByteArray() ?? new byte[0]; OpCode opCode; for (int i = 0; i < array.Length; i += ((opCode.OperandType != OperandType.InlineNone) ? ((opCode.OperandType == OperandType.ShortInlineBrTarget || opCode.OperandType == OperandType.ShortInlineI || opCode.OperandType == OperandType.ShortInlineVar) ? 1 : ((opCode.OperandType == OperandType.InlineVar) ? 2 : ((opCode.OperandType == OperandType.InlineI8 || opCode.OperandType == OperandType.InlineR) ? 8 : ((opCode.OperandType == OperandType.InlineSwitch) ? (4 * (BitConverter.ToInt32(array, i) + 1)) : 4)))) : 0)) { byte b = array[i++]; if (!TryGetOpCode(b, out opCode) && (i >= array.Length || !TryGetOpCode((short)(b * 256 + array[i++]), out opCode))) { throw new NotSupportedException("Unknown IL code detected."); } if (opCode == OpCodes.Ldfld && opCode.OperandType == OperandType.InlineField && i + 4 <= array.Length) { return getMethod.Module.ResolveMember(BitConverter.ToInt32(array, i), getMethod.DeclaringType?.GetGenericArguments(), null) as FieldInfo; } } return null; } internal static GenericSetter CreateSetMethod(Type type, PropertyInfo propertyInfo, bool ShowReadOnlyProperties) { MethodInfo setMethod = propertyInfo.GetSetMethod(ShowReadOnlyProperties); if (setMethod == null) { if (!ShowReadOnlyProperties) { return null; } FieldInfo getterBackingField = GetGetterBackingField(propertyInfo); if (!(getterBackingField != null)) { return null; } return CreateSetField(type, getterBackingField); } Type[] array = new Type[2]; array[0] = (array[1] = typeof(object)); DynamicMethod dynamicMethod = new DynamicMethod("_csm", typeof(object), array, restrictedSkipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!type.IsClass) { LocalBuilder local = iLGenerator.DeclareLocal(type); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Unbox_Any, type); iLGenerator.Emit(OpCodes.Stloc_0); iLGenerator.Emit(OpCodes.Ldloca_S, local); iLGenerator.Emit(OpCodes.Ldarg_1); if (propertyInfo.PropertyType.IsClass) { iLGenerator.Emit(OpCodes.Castclass, propertyInfo.PropertyType); } else { iLGenerator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); } iLGenerator.EmitCall(OpCodes.Call, setMethod, null); iLGenerator.Emit(OpCodes.Ldloc_0); iLGenerator.Emit(OpCodes.Box, type); } else if (!setMethod.IsStatic) { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); iLGenerator.Emit(OpCodes.Ldarg_1); if (propertyInfo.PropertyType.IsClass) { iLGenerator.Emit(OpCodes.Castclass, propertyInfo.PropertyType); } else { iLGenerator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); } iLGenerator.EmitCall(OpCodes.Callvirt, setMethod, null); iLGenerator.Emit(OpCodes.Ldarg_0); } else { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_1); if (propertyInfo.PropertyType.IsClass) { iLGenerator.Emit(OpCodes.Castclass, propertyInfo.PropertyType); } else { iLGenerator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); } iLGenerator.Emit(OpCodes.Call, setMethod); } iLGenerator.Emit(OpCodes.Ret); return (GenericSetter)dynamicMethod.CreateDelegate(typeof(GenericSetter)); } internal static GenericGetter CreateGetField(Type type, FieldInfo fieldInfo) { DynamicMethod dynamicMethod = new DynamicMethod("_cgf", typeof(object), new Type[1] { typeof(object) }, type, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!type.IsClass) { LocalBuilder local = iLGenerator.DeclareLocal(type); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Unbox_Any, type); iLGenerator.Emit(OpCodes.Stloc_0); iLGenerator.Emit(OpCodes.Ldloca_S, local); iLGenerator.Emit(OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType) { iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType); } } else { iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, fieldInfo); if (fieldInfo.FieldType.IsValueType) { iLGenerator.Emit(OpCodes.Box, fieldInfo.FieldType); } } iLGenerator.Emit(OpCodes.Ret); return (GenericGetter)dynamicMethod.CreateDelegate(typeof(GenericGetter)); } internal static GenericGetter CreateGetMethod(Type type, PropertyInfo propertyInfo) { MethodInfo getMethod = propertyInfo.GetGetMethod(); if (getMethod == null) { return null; } DynamicMethod dynamicMethod = new DynamicMethod("_cgm", typeof(object), new Type[1] { typeof(object) }, type, skipVisibility: true); ILGenerator iLGenerator = dynamicM