using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; #if NETFX_CORE using System.Reflection; #endif namespace PlayFab.Internal { public static class PlayFabUtil { static PlayFabUtil() { } private static string _localSettingsFileName = "playfab.local.settings.json"; public static readonly string[] _defaultDateTimeFormats = new string[]{ // All parseable ISO 8601 formats for DateTime.[Try]ParseExact - Lets us deserialize any legacy timestamps in one of these formats // These are the standard format with ISO 8601 UTC markers (T/Z) "yyyy-MM-ddTHH:mm:ss.FFFFFFZ", "yyyy-MM-ddTHH:mm:ss.FFFFZ", "yyyy-MM-ddTHH:mm:ss.FFFZ", // DEFAULT_UTC_OUTPUT_INDEX "yyyy-MM-ddTHH:mm:ss.FFZ", "yyyy-MM-ddTHH:mm:ssZ", "yyyy-MM-dd HH:mm:ssZ", // Added for Android Push Plugin // These are the standard format without ISO 8601 UTC markers (T/Z) "yyyy-MM-dd HH:mm:ss.FFFFFF", "yyyy-MM-dd HH:mm:ss.FFFF", "yyyy-MM-dd HH:mm:ss.FFF", "yyyy-MM-dd HH:mm:ss.FF", // DEFAULT_LOCAL_OUTPUT_INDEX "yyyy-MM-dd HH:mm:ss", // These are the result of an input bug, which we now have to support as long as the db has entries formatted like this "yyyy-MM-dd HH:mm.ss.FFFF", "yyyy-MM-dd HH:mm.ss.FFF", "yyyy-MM-dd HH:mm.ss.FF", "yyyy-MM-dd HH:mm.ss", }; public const int DEFAULT_UTC_OUTPUT_INDEX = 2; // The default format everybody should use public const int DEFAULT_LOCAL_OUTPUT_INDEX = 9; // The default format if you want to use local time (This doesn't have universal support in all PlayFab code) public static DateTimeStyles DateTimeStyles = DateTimeStyles.RoundtripKind; public static string timeStamp { get { return DateTime.Now.ToString(_defaultDateTimeFormats[DEFAULT_LOCAL_OUTPUT_INDEX]); } } public static string utcTimeStamp { get { return DateTime.UtcNow.ToString(_defaultDateTimeFormats[DEFAULT_UTC_OUTPUT_INDEX]); } } public static string Format(string text, params object[] args) { return args.Length > 0 ? string.Format(text, args) : text; } [ThreadStatic] private static StringBuilder _sb; /// /// A threadsafe way to block and load a text file /// /// Load a text file, and return the file as text. /// Used for small (usually json) files. /// public static string ReadAllFileText(string filename) { if (!File.Exists(filename)) { return string.Empty; } if (_sb == null) { _sb = new StringBuilder(); } _sb.Length = 0; using (var fs = new FileStream(filename, FileMode.Open)) { using (var br = new BinaryReader(fs)) { while (br.BaseStream.Position != br.BaseStream.Length) { _sb.Append(br.ReadChar()); } } } return _sb.ToString(); } public static T TryEnumParse(string value, T defaultValue) { try { return (T)Enum.Parse(typeof(T), value); } catch (InvalidCastException) { return defaultValue; } catch (Exception e) { UnityEngine.Debug.LogError("Enum cast failed with unknown error: " + e.Message); return defaultValue; } } #if UNITY_2017_1_OR_NEWER internal static string GetLocalSettingsFileProperty(string propertyKey) { string envFileContent = null; string currDir = Directory.GetCurrentDirectory(); string currDirEnvFile = Path.Combine(currDir, _localSettingsFileName); if (File.Exists(currDirEnvFile)) { envFileContent = ReadAllFileText(currDirEnvFile); } else { string tempDir = Path.GetTempPath(); string tempDirEnvFile = Path.Combine(tempDir, _localSettingsFileName); if (File.Exists(tempDirEnvFile)) { envFileContent = ReadAllFileText(tempDirEnvFile); } } if (!string.IsNullOrEmpty(envFileContent)) { var serializer = PluginManager.GetPlugin(PluginContract.PlayFab_Serializer); var envJson = serializer.DeserializeObject>(envFileContent); try { object result; if (envJson.TryGetValue(propertyKey, out result)) { return result == null ? null : result.ToString(); } return null; } catch (KeyNotFoundException) { return string.Empty; } } return string.Empty; } #endif } }