187 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			187 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | using System; | |||
|  | using System.Collections.Generic; | |||
|  | using System.Text.RegularExpressions; | |||
|  | 
 | |||
|  | namespace ThinkingData.Analytics.Utils | |||
|  | { | |||
|  |     public class TDPropertiesChecker | |||
|  |     { | |||
|  |         private static readonly Regex keyPattern = new Regex(@"^[a-zA-Z][a-zA-Z\d_#]{0,49}$"); | |||
|  |         private static readonly List<string> propertyNameWhitelist = new List<string>() { "#scene_name", "#scene_path", "#app_crashed_reason" }; | |||
|  | 
 | |||
|  |         public static bool IsNumeric(object obj) | |||
|  |         { | |||
|  |             return obj is sbyte  | |||
|  |                 || obj is byte  | |||
|  |                 || obj is short  | |||
|  |                 || obj is ushort | |||
|  |                 || obj is int  | |||
|  |                 || obj is uint  | |||
|  |                 || obj is long  | |||
|  |                 || obj is ulong  | |||
|  |                 || obj is double  | |||
|  |                 || obj is decimal  | |||
|  |                 || obj is float; | |||
|  |         } | |||
|  |         public static bool IsString(object obj) | |||
|  |         { | |||
|  |             if (obj == null) | |||
|  |                 return false; | |||
|  |             return obj is string; | |||
|  |         } | |||
|  |         public static bool IsDictionary(object obj)  | |||
|  |         { | |||
|  |             if (obj == null) | |||
|  |                 return false; | |||
|  |             return (obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(Dictionary<,>)); | |||
|  |         } | |||
|  |         public static bool IsList(object obj)  | |||
|  |         { | |||
|  |             if (obj == null) | |||
|  |                 return false; | |||
|  |             return (obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(List<>)) || obj is Array; | |||
|  |         } | |||
|  |         public static bool CheckProperties<V>(Dictionary<string, V> properties) | |||
|  |         { | |||
|  |             if (properties == null) | |||
|  |             { | |||
|  |                 return true; | |||
|  |             } | |||
|  |             bool ret = true; | |||
|  |             foreach(KeyValuePair<string, V> kv in properties)  | |||
|  |             { | |||
|  |                 if (!CheckString(kv.Key)) | |||
|  |                 { | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |                 if (!(kv.Value is string || kv.Value is DateTime || kv.Value is bool || IsNumeric(kv.Value) || IsList(kv.Value) || IsDictionary(kv.Value))) | |||
|  |                 { | |||
|  |                     if(TDLog.GetEnable()) TDLog.w("Incorrect property - property values must be one of: String, Numberic, Boolean, DateTime, Array, Row"); | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |                 if (IsString(kv.Value) && !CheckProperties(kv.Value as string))  | |||
|  |                 { | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |                 if (IsNumeric(kv.Value)) { | |||
|  |                     double number = Convert.ToDouble(kv.Value); | |||
|  |                     if (!CheckProperties(number)) | |||
|  |                     { | |||
|  |                         ret = false; | |||
|  |                     } | |||
|  |                 } | |||
|  |                 if (IsList(kv.Value) && !CheckProperties(kv.Value as List<object>)) { | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |                 if (IsDictionary(kv.Value) && !CheckProperties(kv.Value as Dictionary<string, object>))  | |||
|  |                 { | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |             } | |||
|  |             return ret; | |||
|  |         } | |||
|  |         public static bool CheckProperties(List<object> properties) | |||
|  |         { | |||
|  |             if (properties == null) | |||
|  |             { | |||
|  |                 return true; | |||
|  |             } | |||
|  |             bool ret = true; | |||
|  |             foreach (object value in properties) | |||
|  |             { | |||
|  |                 if (!(value is string || value is DateTime || value is bool || IsNumeric(value) || IsDictionary(value))) | |||
|  |                 { | |||
|  |                     if(TDLog.GetEnable()) TDLog.w("Incorrect property - property values in list must be one of: String, Numberic, Boolean, DateTime, Row"); | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |                 if (IsString(value) && !CheckProperties(value as string))  | |||
|  |                 { | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |                 if (IsNumeric(value)) { | |||
|  |                     double number = Convert.ToDouble(value); | |||
|  |                     if (!CheckProperties(number)) | |||
|  |                     { | |||
|  |                         ret = false; | |||
|  |                     } | |||
|  |                 } | |||
|  |                 if (IsDictionary(value) && !CheckProperties(value as Dictionary<string, object>))  | |||
|  |                 { | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |             } | |||
|  |             return ret; | |||
|  |         } | |||
|  |         public static bool CheckProperties(List<string> properties) | |||
|  |         { | |||
|  |             if (properties == null) | |||
|  |             { | |||
|  |                 return true; | |||
|  |             } | |||
|  | 
 | |||
|  |             bool ret = true; | |||
|  |             foreach(string value in properties) | |||
|  |             { | |||
|  |                 if (!CheckProperties(value)) | |||
|  |                 { | |||
|  |                     ret = false; | |||
|  |                 } | |||
|  |             } | |||
|  |             return ret; | |||
|  |         } | |||
|  |         public static bool CheckProperties(string properties)  | |||
|  |         { | |||
|  |             if (properties is string && System.Text.Encoding.UTF8.GetBytes(Convert.ToString(properties)).Length > 2048) { | |||
|  |                 if(TDLog.GetEnable()) TDLog.w("Incorrect properties - the string is too long: " + (string)(object)properties); | |||
|  |                 return false; | |||
|  |             } | |||
|  |             return true; | |||
|  |         } | |||
|  |         public static bool CheckProperties(double properties)  | |||
|  |         { | |||
|  |             if (properties > 9999999999999.999 || properties < -9999999999999.999) | |||
|  |             { | |||
|  |                 if(TDLog.GetEnable()) TDLog.w("Incorrect properties - number value is invalid: " + properties + ", the data range is -9E15 to 9E15, with a maximum of 3 decimal places"); | |||
|  |                 return false; | |||
|  |             } | |||
|  |             return true; | |||
|  |         } | |||
|  |         public static bool CheckString(string eventName) | |||
|  |         { | |||
|  |             if (string.IsNullOrEmpty(eventName)) | |||
|  |             { | |||
|  |                 if(TDLog.GetEnable()) TDLog.w("Incorrect event name - the string is null"); | |||
|  |                 return false; | |||
|  |             } | |||
|  |             if (keyPattern.IsMatch(eventName)) | |||
|  |             { | |||
|  |                 return true; | |||
|  |             }  | |||
|  |             else | |||
|  |             { | |||
|  |                 if (propertyNameWhitelist.Contains(eventName)) | |||
|  |                 { | |||
|  |                     return true; | |||
|  |                 } | |||
|  |                 if(TDLog.GetEnable()) TDLog.w("Incorrect event name - the string is invalid for TDAnalytics: " + eventName + ", event name and properties name rules: must be character string type, starting with a character and containing figures, characters, and an underline \"_\", with a maximum length of 50 characters"); | |||
|  |                 return false; | |||
|  |             } | |||
|  |         } | |||
|  |         public static void MergeProperties(Dictionary<string, object> source, Dictionary<string, object> dest) | |||
|  |         { | |||
|  |             if (null == source) return; | |||
|  |             foreach (KeyValuePair<string, object> kv in source) | |||
|  |             { | |||
|  |                 if (dest.ContainsKey(kv.Key)) | |||
|  |                 { | |||
|  |                     dest[kv.Key] = kv.Value; | |||
|  |                 } else | |||
|  |                 { | |||
|  |                     dest.Add(kv.Key, kv.Value); | |||
|  |                 } | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | } | |||
|  | 
 |