using System; using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using GameAnalyticsSDK.State; namespace GameAnalyticsSDK.Validators { internal static class GAValidator { #region Public methods /// /// Check if a string matches a defined pattern /// /// true, if match false otherwise. /// Given string /// Pattern. public static bool StringMatch(string s, string pattern) { if(s == null || pattern == null) { return false; } return Regex.IsMatch(s, pattern); } public static bool ValidateBusinessEvent(string currency, int amount, string cartType, string itemType, string itemId) { // validate currency if (!ValidateCurrency(currency)) { Debug.Log("Validation fail - business event - currency: Cannot be (null) and need to be A-Z, 3 characters and in the standard at openexchangerates.org. Failed currency: " + currency); return false; } // do not validate amount - integer is never null ! // validate cartType if (!ValidateShortString(cartType, true)) { Debug.Log("Validation fail - business event - cartType. Cannot be above 32 length. String: " + cartType); return false; } // validate itemType length if (!ValidateEventPartLength(itemType, false)) { Debug.Log("Validation fail - business event - itemType: Cannot be (null), empty or above 64 characters. String: " + itemType); return false; } // validate itemType chars if (!ValidateEventPartCharacters(itemType)) { Debug.Log("Validation fail - business event - itemType: Cannot contain other characters than A-z, 0-9, -_. ()!?. String: " + itemType); return false; } // validate itemId if (!ValidateEventPartLength(itemId, false)) { Debug.Log("Validation fail - business event - itemId. Cannot be (null), empty or above 64 characters. String: " + itemId); return false; } if (!ValidateEventPartCharacters(itemId)) { Debug.Log("Validation fail - business event - itemId: Cannot contain other characters than A-z, 0-9, -_., ()!?. String: " + itemId); return false; } return true; } public static bool ValidateResourceEvent(GAResourceFlowType flowType, string currency, float amount, string itemType, string itemId) { if (string.IsNullOrEmpty(currency)) { Debug.Log("Validation fail - resource event - currency: Cannot be (null)"); return false; } if (flowType == GAResourceFlowType.Undefined) { Debug.Log("Validation fail - resource event - flowType: Invalid flowType"); } if (!GAState.HasAvailableResourceCurrency(currency)) { Debug.Log("Validation fail - resource event - currency: Not found in list of pre-defined resource currencies. String: " + currency); return false; } if (!(amount > 0)) { Debug.Log("Validation fail - resource event - amount: Float amount cannot be 0 or negative. Value: " + amount); return false; } if (string.IsNullOrEmpty(itemType)) { Debug.Log("Validation fail - resource event - itemType: Cannot be (null)"); return false; } if (!ValidateEventPartLength(itemType, false)) { Debug.Log("Validation fail - resource event - itemType: Cannot be (null), empty or above 64 characters. String: " + itemType); return false; } if (!ValidateEventPartCharacters(itemType)) { Debug.Log("Validation fail - resource event - itemType: Cannot contain other characters than A-z, 0-9, -_. ()!?. String: " + itemType); return false; } if (!GAState.HasAvailableResourceItemType(itemType)) { Debug.Log("Validation fail - resource event - itemType: Not found in list of pre-defined available resource itemTypes. String: " + itemType); return false; } if (!ValidateEventPartLength(itemId, false)) { Debug.Log("Validation fail - resource event - itemId: Cannot be (null), empty or above 64 characters. String: " + itemId); return false; } if (!ValidateEventPartCharacters(itemId)) { Debug.Log("Validation fail - resource event - itemId: Cannot contain other characters than A-z, 0-9, -_., ()!?. String: " + itemId); return false; } return true; } public static bool ValidateProgressionEvent(GAProgressionStatus progressionStatus, string progression01, string progression02, string progression03) { if (progressionStatus == GAProgressionStatus.Undefined) { Debug.Log("Validation fail - progression event: Invalid progression status."); return false; } // Make sure progressions are defined as either 01, 01+02 or 01+02+03 if (!string.IsNullOrEmpty(progression03) && !(!string.IsNullOrEmpty(progression02) || string.IsNullOrEmpty(progression01))) { Debug.Log("Validation fail - progression event: 03 found but 01+02 are invalid. Progression must be set as either 01, 01+02 or 01+02+03."); return false; } else if (!string.IsNullOrEmpty(progression02) && string.IsNullOrEmpty(progression01)) { Debug.Log("Validation fail - progression event: 02 found but not 01. Progression must be set as either 01, 01+02 or 01+02+03"); return false; } else if (string.IsNullOrEmpty(progression01)) { Debug.Log("Validation fail - progression event: progression01 not valid. Progressions must be set as either 01, 01+02 or 01+02+03"); return false; } // progression01 (required) if (!ValidateEventPartLength(progression01, false)) { Debug.Log("Validation fail - progression event - progression01: Cannot be (null), empty or above 64 characters. String: " + progression01); return false; } if (!ValidateEventPartCharacters(progression01)) { Debug.Log("Validation fail - progression event - progression01: Cannot contain other characters than A-z, 0-9, -_. ()!?. String: " + progression01); return false; } // progression02 if (!string.IsNullOrEmpty(progression02)) { if (!ValidateEventPartLength(progression02, true)) { Debug.Log("Validation fail - progression event - progression02: Cannot be empty or above 64 characters. String: " + progression02); return false; } if (!ValidateEventPartCharacters(progression02)) { Debug.Log("Validation fail - progression event - progression02: Cannot contain other characters than A-z, 0-9, -_. ()!?. String: " + progression02); return false; } } // progression03 if (!string.IsNullOrEmpty(progression03)) { if (!ValidateEventPartLength(progression03, true)) { Debug.Log("Validation fail - progression event - progression03: Cannot be empty or above 64 characters. String: " + progression03); return false; } if (!ValidateEventPartCharacters(progression03)) { Debug.Log("Validation fail - progression event - progression03: Cannot contain other characters than A-z, 0-9, -_. ()!?. String: " + progression03); return false; } } return true; } public static bool ValidateDesignEvent(string eventId) { if (!ValidateEventIdLength(eventId)) { Debug.Log("Validation fail - design event - eventId: Cannot be (null) or empty. Only 5 event parts allowed seperated by :. Each part need to be 32 characters or less. String: " + eventId); return false; } if (!ValidateEventIdCharacters(eventId)) { Debug.Log("Validation fail - design event - eventId: Non valid characters. Only allowed A-z, 0-9, -_. ()!?. String: " + eventId); return false; } // value: allow 0, negative and nil (not required) return true; } public static bool ValidateErrorEvent(GAErrorSeverity severity, string message) { if (severity == GAErrorSeverity.Undefined) { Debug.Log("Validation fail - error event - severity: Severity was unsupported value."); return false; } if (!ValidateLongString(message, true)) { Debug.Log("Validation fail - error event - message: Message cannot be above 8192 characters."); return false; } return true; } public static bool ValidateAdEvent(GAAdAction adAction, GAAdType adType, string adSdkName, string adPlacement) { if (adAction == GAAdAction.Undefined) { Debug.Log("Validation fail - ad event - adAction: Ad action was unsupported value."); return false; } if (adType == GAAdType.Undefined) { Debug.Log("Validation fail - ad event - adType: Ad type was unsupported value."); return false; } if (!ValidateShortString(adSdkName, false)) { Debug.Log("Validation fail - ad event - message: Ad SDK name cannot be above 32 characters."); return false; } if (!ValidateString(adPlacement, false)) { Debug.Log("Validation fail - ad event - message: Ad placement cannot be above 64 characters."); return false; } return true; } public static bool ValidateSdkErrorEvent(string gameKey, string gameSecret, GAErrorSeverity type) { if(!ValidateKeys(gameKey, gameSecret)) { return false; } if (type == GAErrorSeverity.Undefined) { Debug.Log("Validation fail - sdk error event - type: Type was unsupported value."); return false; } return true; } public static bool ValidateKeys(string gameKey, string gameSecret) { if (StringMatch(gameKey, "^[A-z0-9]{32}$")) { if (StringMatch(gameSecret, "^[A-z0-9]{40}$")) { return true; } } return false; } public static bool ValidateCurrency(string currency) { if (string.IsNullOrEmpty(currency)) { return false; } if (!StringMatch(currency, "^[A-Z]{3}$")) { return false; } return true; } public static bool ValidateEventPartLength(string eventPart, bool allowNull) { if (allowNull == true && string.IsNullOrEmpty(eventPart)) { return true; } if (string.IsNullOrEmpty(eventPart)) { return false; } if (eventPart.Length > 64) { return false; } return true; } public static bool ValidateEventPartCharacters(string eventPart) { if (!StringMatch(eventPart, "^[A-Za-z0-9\\s\\-_\\.\\(\\)\\!\\?]{1,64}$")) { return false; } return true; } public static bool ValidateEventIdLength(string eventId) { if (string.IsNullOrEmpty(eventId)) { return false; } if (!StringMatch(eventId, "^[^:]{1,64}(?::[^:]{1,64}){0,4}$")) { return false; } return true; } public static bool ValidateEventIdCharacters(string eventId) { if (string.IsNullOrEmpty(eventId)) { return false; } if (!StringMatch(eventId, "^[A-Za-z0-9\\s\\-_\\.\\(\\)\\!\\?]{1,64}(:[A-Za-z0-9\\s\\-_\\.\\(\\)\\!\\?]{1,64}){0,4}$")) { return false; } return true; } public static bool ValidateBuild(string build) { if (!ValidateShortString(build, false)) { return false; } return true; } public static bool ValidateUserId(string uId) { if (!ValidateString(uId, false)) { Debug.Log("Validation fail - user id: id cannot be (null), empty or above 64 characters."); return false; } return true; } public static bool ValidateShortString(string shortString, bool canBeEmpty) { // String is allowed to be empty or nil if (canBeEmpty && string.IsNullOrEmpty(shortString)) { return true; } if (string.IsNullOrEmpty(shortString) || shortString.Length > 32) { return false; } return true; } public static bool ValidateString(string s, bool canBeEmpty) { // String is allowed to be empty or nil if (canBeEmpty && string.IsNullOrEmpty(s)) { return true; } if (string.IsNullOrEmpty(s) || s.Length > 64) { return false; } return true; } public static bool ValidateLongString(string longString, bool canBeEmpty) { // String is allowed to be empty if (canBeEmpty && string.IsNullOrEmpty(longString)) { return true; } if (string.IsNullOrEmpty(longString) || longString.Length > 8192) { return false; } return true; } public static bool ValidateConnectionType(string connectionType) { return StringMatch(connectionType, "^(wwan|wifi|lan|offline)$"); } public static bool ValidateCustomDimensions(params string[] customDimensions) { return ValidateArrayOfStrings(20, 32, false, "custom dimensions", customDimensions); } public static bool ValidateResourceCurrencies(params string[] resourceCurrencies) { if (!ValidateArrayOfStrings(20, 64, false, "resource currencies", resourceCurrencies)) { return false; } // validate each string for regex foreach (string resourceCurrency in resourceCurrencies) { if (!StringMatch(resourceCurrency, "^[A-Za-z]+$")) { Debug.Log("resource currencies validation failed: a resource currency can only be A-Z, a-z. String was: " + resourceCurrency); return false; } } return true; } public static bool ValidateResourceItemTypes(params string[] resourceItemTypes) { if (!ValidateArrayOfStrings(20, 32, false, "resource item types", resourceItemTypes)) { return false; } // validate each resourceItemType for eventpart validation foreach (string resourceItemType in resourceItemTypes) { if (!ValidateEventPartCharacters(resourceItemType)) { Debug.Log("resource item types validation failed: a resource item type cannot contain other characters than A-z, 0-9, -_. ()!?. String was: " + resourceItemType); return false; } } return true; } public static bool ValidateDimension01(string dimension01) { // we do not allow null if (string.IsNullOrEmpty(dimension01)) { Debug.Log("Validation failed - custom dimension01 - value cannot be empty."); return false; } if (!GAState.HasAvailableCustomDimensions01(dimension01)) { Debug.Log("Validation failed - custom dimension 01 - value was not found in list of custom dimensions 01 in the Settings object. \nGiven dimension value: " + dimension01); return false; } return true; } public static bool ValidateDimension02(string dimension02) { // we do not allow null if (string.IsNullOrEmpty(dimension02)) { Debug.Log("Validation failed - custom dimension01 - value cannot be empty."); return false; } if (!GAState.HasAvailableCustomDimensions02(dimension02)) { Debug.Log("Validation failed - custom dimension 02 - value was not found in list of custom dimensions 02 in the Settings object. \nGiven dimension value: " + dimension02); return false; } return true; } public static bool ValidateDimension03(string dimension03) { // we do not allow null if (string.IsNullOrEmpty(dimension03)) { Debug.Log("Validation failed - custom dimension01 - value cannot be empty."); return false; } if (!GAState.HasAvailableCustomDimensions03(dimension03)) { Debug.Log("Validation failed - custom dimension 03 - value was not found in list of custom dimensions 03 in the Settings object. \nGiven dimension value: " + dimension03); return false; } return true; } public static bool ValidateArrayOfStrings(long maxCount, long maxStringLength, bool allowNoValues, string logTag, params string[] arrayOfStrings) { string arrayTag = logTag; // use arrayTag to annotate warning log if (string.IsNullOrEmpty(arrayTag)) { arrayTag = "Array"; } if(arrayOfStrings == null) { Debug.Log(arrayTag + " validation failed: array cannot be null. "); return false; } // check if empty if (allowNoValues == false && arrayOfStrings.Length == 0) { Debug.Log(arrayTag + " validation failed: array cannot be empty. "); return false; } // check if exceeding max count if (maxCount > 0 && arrayOfStrings.Length > maxCount) { Debug.Log(arrayTag + " validation failed: array cannot exceed " + maxCount + " values. It has " + arrayOfStrings.Length + " values."); return false; } // validate each string foreach (string arrayString in arrayOfStrings) { int stringLength = arrayString == null ? 0 : arrayString.Length; // check if empty (not allowed) if (stringLength == 0) { Debug.Log(arrayTag + " validation failed: contained an empty string."); return false; } // check if exceeding max length if (maxStringLength > 0 && stringLength > maxStringLength) { Debug.Log(arrayTag + " validation failed: a string exceeded max allowed length (which is: " + maxStringLength + "). String was: " + arrayString); return false; } } return true; } public static bool ValidateClientTs(long clientTs) { // TODO(nikolaj): validate other way? (instead of max possible) if (clientTs < (long.MinValue+1) || clientTs > (long.MaxValue-1)) { return false; } return true; } //public static bool ValidateCustomDimension01Settings(s #endregion // Public methods } }