Facebook.Unity/Utils/Utilities.cs (326 lines of code) (raw):

/** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, * copy, modify, and distribute this software in source code or binary form for use * in connection with the web services and APIs provided by Facebook. * * As with any software that integrates with the Facebook platform, your use of * this software is subject to the Facebook Developer Principles and Policies * [http://developers.facebook.com/policy/]. This copyright notice shall be * included in all copies or substantial portions of the software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ namespace Facebook.Unity { using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; internal static class Utilities { private const string WarningMissingParameter = "Did not find expected value '{0}' in dictionary"; private static Dictionary<string, string> commandLineArguments; public delegate void Callback<T>(T obj); public static Dictionary<string, string> CommandLineArguments { get { if (commandLineArguments != null) { return commandLineArguments; } var localCommandLineArguments = new Dictionary<string, string>(); var arguments = Environment.GetCommandLineArgs(); for (int i = 0; i < arguments.Length; i++) { if (arguments[i].StartsWith("/") || arguments[i].StartsWith("-")) { var value = i + 1 < arguments.Length ? arguments[i + 1] : null; localCommandLineArguments.Add(arguments[i], value); } } commandLineArguments = localCommandLineArguments; return commandLineArguments; } } public static bool TryGetValue<T>( this IDictionary<string, object> dictionary, string key, out T value) { object resultObj; if (dictionary.TryGetValue(key, out resultObj) && resultObj is T) { value = (T)resultObj; return true; } value = default(T); return false; } public static long TotalSeconds(this DateTime dateTime) { TimeSpan t = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); long secondsSinceEpoch = (long)t.TotalSeconds; return secondsSinceEpoch; } public static T GetValueOrDefault<T>( this IDictionary<string, object> dictionary, string key, bool logWarning = true) { T result; if (!dictionary.TryGetValue<T>(key, out result) && logWarning) { FacebookLogger.Warn(WarningMissingParameter, key); } return result; } public static string ToCommaSeparateList(this IEnumerable<string> list) { if (list == null) { return string.Empty; } return string.Join(",", list.ToArray()); } public static string AbsoluteUrlOrEmptyString(this Uri uri) { if (uri == null) { return string.Empty; } return uri.AbsoluteUri; } public static string GetUserAgent(string productName, string productVersion) { return string.Format( CultureInfo.InvariantCulture, "{0}/{1}", productName, productVersion); } public static string ToJson(this IDictionary<string, object> dictionary) { return MiniJSON.Json.Serialize(dictionary); } public static void AddAllKVPFrom<T1, T2>(this IDictionary<T1, T2> dest, IDictionary<T1, T2> source) { foreach (T1 key in source.Keys) { dest[key] = source[key]; } } public static AccessToken ParseAccessTokenFromResult(IDictionary<string, object> resultDictionary) { string userID = resultDictionary.GetValueOrDefault<string>(LoginResult.UserIdKey); string accessToken = resultDictionary.GetValueOrDefault<string>(LoginResult.AccessTokenKey); DateTime expiration = Utilities.ParseExpirationDateFromResult(resultDictionary); ICollection<string> permissions = Utilities.ParsePermissionFromResult(resultDictionary); DateTime? lastRefresh = Utilities.ParseLastRefreshFromResult(resultDictionary); string graphDomain = resultDictionary.GetValueOrDefault<string>(LoginResult.GraphDomain); return new AccessToken( accessToken, userID, expiration, permissions, lastRefresh, graphDomain); } public static AuthenticationToken ParseAuthenticationTokenFromResult(IDictionary<string, object> resultDictionary) { string tokenString = resultDictionary.GetValueOrDefault<string>(LoginResult.AuthTokenString); string nonce = resultDictionary.GetValueOrDefault<string>(LoginResult.AuthNonce); return new AuthenticationToken(tokenString, nonce); } public static string ToStringNullOk(this object obj) { if (obj == null) { return "null"; } return obj.ToString(); } // Use this instead of reflection to avoid crashing at // runtime due to Unity's stripping public static string FormatToString( string baseString, string className, IDictionary<string, string> propertiesAndValues) { StringBuilder sb = new StringBuilder(); if (baseString != null) { sb.Append(baseString); } sb.AppendFormat("\n{0}:", className); foreach (var kvp in propertiesAndValues) { string value = kvp.Value != null ? kvp.Value : "null"; sb.AppendFormat("\n\t{0}: {1}", kvp.Key, value); } return sb.ToString(); } private static DateTime ParseExpirationDateFromResult(IDictionary<string, object> resultDictionary) { DateTime expiration; if (Constants.IsWeb) { // For canvas we get back the time as seconds since now instead of in epoch time. long timeTillExpiration = resultDictionary.GetValueOrDefault<long>(LoginResult.ExpirationTimestampKey); expiration = DateTime.UtcNow.AddSeconds(timeTillExpiration); } else { string expirationStr = resultDictionary.GetValueOrDefault<string>(LoginResult.ExpirationTimestampKey); int expiredTimeSeconds; if (int.TryParse(expirationStr, out expiredTimeSeconds) && expiredTimeSeconds > 0) { expiration = Utilities.FromTimestamp(expiredTimeSeconds); } else { expiration = DateTime.MaxValue; } } return expiration; } private static DateTime? ParseLastRefreshFromResult(IDictionary<string, object> resultDictionary) { string lastRefreshStr = resultDictionary.GetValueOrDefault<string>(LoginResult.LastRefreshKey, false); int lastRefresh; if (int.TryParse(lastRefreshStr, out lastRefresh) && lastRefresh > 0) { return Utilities.FromTimestamp(lastRefresh); } else { return null; } } private static ICollection<string> ParsePermissionFromResult(IDictionary<string, object> resultDictionary) { string permissions; IEnumerable<object> permissionList; // For permissions we can get the result back in either a comma separated string or // a list depending on the platform. if (resultDictionary.TryGetValue(LoginResult.PermissionsKey, out permissions)) { permissionList = permissions.Split(','); } else if (!resultDictionary.TryGetValue(LoginResult.PermissionsKey, out permissionList)) { permissionList = new string[0]; FacebookLogger.Warn("Failed to find parameter '{0}' in login result", LoginResult.PermissionsKey); } return permissionList.Select(permission => permission.ToString()).ToList(); } public static IList<Product> ParseCatalogFromResult(IDictionary<string, object> resultDictionary) { object catalogObject; IList<Product> products = new List<Product>(); if (resultDictionary.TryGetValue("success", out catalogObject)) { IList<object> deserializedCatalogObject = (IList<object>) MiniJSON.Json.Deserialize(catalogObject as string); foreach (IDictionary<string, object> product in deserializedCatalogObject) { products.Add(ParseProductFromCatalogResult(product)); } return products; } else { return null; } } public static Product ParseProductFromCatalogResult(IDictionary<string, object> product, bool isWindows = false) { string title = product["title"].ToStringNullOk(); string productID = product[isWindows ? "product_id" : "productID"].ToStringNullOk(); string description = product["description"].ToStringNullOk(); string imageURI = product.ContainsKey(isWindows ? "image_uri" : "imageURI") ? product[isWindows ? "image_uri" : "imageURI"].ToStringNullOk() : ""; string price = product["price"].ToStringNullOk(); double? priceAmount = product.ContainsKey(isWindows ? "price_amount" : "priceAmount") ? (double?)product[isWindows ? "price_amount" : "priceAmount"] : null; string priceCurrencyCode = product[isWindows ? "price_currency_code" : "priceCurrencyCode"].ToStringNullOk(); return new Product(title, productID, description, imageURI, price, priceAmount, priceCurrencyCode); } public static IList<Purchase> ParsePurchasesFromResult(IDictionary<string, object> resultDictionary) { object purchasesObject; IList<Purchase> purchases = new List<Purchase>(); if (resultDictionary.TryGetValue("success", out purchasesObject)) { IList<object> deserializedPurchasesObject = (IList<object>) MiniJSON.Json.Deserialize(purchasesObject as string); foreach (IDictionary<string, object> purchase in (List<object>) deserializedPurchasesObject) { purchases.Add(ParsePurchaseFromDictionary(purchase)); } return purchases; } else { return null; } } public static Purchase ParsePurchaseFromResult(IDictionary<string, object> resultDictionary) { object purchaseObject; if (resultDictionary.TryGetValue("success", out purchaseObject)) { IDictionary<string, object> deserializedPurchaseObject = (IDictionary<string, object>) MiniJSON.Json.Deserialize(purchaseObject as string); return ParsePurchaseFromDictionary(deserializedPurchaseObject); } else { return null; } } public static Purchase ParsePurchaseFromDictionary(IDictionary<string, object> purchase, bool isWindows = false) { bool isConsumed = false; if ( !purchase.TryGetValue(isWindows ? "is_consumed" : "isConsumed", out isConsumed)) // compatibility with Graph API 11 or higher { purchase.TryGetValue(isWindows ? "consumed" : "isConsumed", out isConsumed); // compatibility with Graph API 10 or lower } string developerPayload = purchase.ContainsKey(isWindows ? "developer_payload" : "developerPayload") ? purchase[isWindows ? "developer_payload" : "developerPayload"].ToStringNullOk() : ""; string paymentActionType = "charge"; if (purchase.ContainsKey("payment_action_type") || purchase.ContainsKey("paymentActionType")) { paymentActionType = purchase[isWindows ? "payment_action_type" : "paymentActionType"].ToStringNullOk(); } string paymentID = purchase[isWindows ? "payment_id" : "paymentID"].ToStringNullOk(); string productID = purchase[isWindows ? "product_id" : "productID"].ToStringNullOk(); IDictionary<string, object> purchasePrice = new Dictionary<string, object>(); if (purchase.ContainsKey("purchase_price") || purchase.ContainsKey("purchasePrice")) { purchasePrice = (IDictionary<string, object>)purchase[isWindows ? "purchase_price" : "purchasePrice"]; } else { purchasePrice.Add("amount", "1.11"); purchasePrice.Add("currency", "USD"); } long purchaseTime; if (isWindows) { purchase.TryGetValue("purchase_time", out purchaseTime); } else { purchase.TryGetValue("purchaseTime", out purchaseTime); } string purchaseToken = purchase[isWindows ? "purchase_token" : "purchaseToken"].ToStringNullOk(); string signedRequest = purchase[isWindows ? "signed_request" : "signedRequest"].ToStringNullOk(); string purchasePlatform = purchase[isWindows ? "purchase_platform" : "purchasePlatform"].ToStringNullOk(); return new Purchase(developerPayload, isConsumed, paymentActionType, paymentID, productID, purchasePlatform, purchasePrice, purchaseTime, purchaseToken, signedRequest); } public static IDictionary<string, string> ParseStringDictionaryFromString(string input) { Dictionary<string, object> dict = MiniJSON.Json.Deserialize(input) as Dictionary<string, object>; if (dict == null || dict.Count == 0) { return null; } IDictionary<string, string> result = new Dictionary<string, string>(); foreach (KeyValuePair<string, object> kvp in dict) { result.Add(kvp.Key, kvp.Value != null ? kvp.Value.ToString() : ""); } return result; } // key parameter is the key whose value is the inner dictionary that will be parsed public static IDictionary<string, string> ParseInnerStringDictionary(IDictionary<string, object> resultDictionary, string key) { object resultObject; if (resultDictionary.TryGetValue(key, out resultObject)) { return ParseStringDictionaryFromString(resultObject as string); } else { return null; } } public static DateTime FromTimestamp(int timestamp) { return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(timestamp); } } }