예제 #1
0
        private HttpWebRequest CreateRequest(string url, byte[] payloadData, bool gzip)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            request.Method = "POST";
#if WINDOWS_UWP
            request.Headers[HttpRequestHeader.ContentLength] = payloadData.Length.ToString();
#elif WINDOWS_WSA
            //request.Headers[HttpRequestHeader.ContentLength] = payloadData.Length.ToString();
            // Bug setting Content Length on WSA
#else
            request.ContentLength = payloadData.Length;
#endif

            if (gzip)
            {
                request.Headers[HttpRequestHeader.ContentEncoding] = "gzip";
            }

            // create authorization hash
            String key = GAState.GameSecret;

            request.Headers[HttpRequestHeader.Authorization] = GAUtilities.HmacWithKey(key, payloadData);
            request.ContentType = "application/json";

            return(request);
        }
예제 #2
0
        public void TestValidateClientTs()
        {
            Assert.True(GAValidator.ValidateClientTs(GAUtilities.TimeIntervalSince1970()));

            Assert.False(GAValidator.ValidateClientTs(long.MinValue));
            Assert.False(GAValidator.ValidateClientTs(long.MaxValue));
        }
예제 #3
0
 public static bool ValidateSdkWrapperVersion(string wrapperVersion)
 {
     if (!GAUtilities.StringMatch(wrapperVersion, "^(unity) [0-9]{0,5}(\\.[0-9]{0,5}){0,2}$"))
     {
         return(false);
     }
     return(true);
 }
예제 #4
0
 public static bool ValidateEngineVersion(string engineVersion)
 {
     if (engineVersion == null || !GAUtilities.StringMatch(engineVersion, "^(unity) [0-9]{0,5}(\\.[0-9]{0,5}){0,2}$"))
     {
         return(false);
     }
     return(true);
 }
예제 #5
0
 public static bool ValidateEventPartCharacters(string eventPart)
 {
     if (!GAUtilities.StringMatch(eventPart, "^[A-Za-z0-9\\s\\-_\\.\\(\\)\\!\\?]{1,64}$"))
     {
         return(false);
     }
     return(true);
 }
예제 #6
0
 public static bool ValidateKeys(string gameKey, string gameSecret)
 {
     if (GAUtilities.StringMatch(gameKey, "^[A-z0-9]{32}$"))
     {
         if (GAUtilities.StringMatch(gameSecret, "^[A-z0-9]{40}$"))
         {
             return(true);
         }
     }
     return(false);
 }
예제 #7
0
 public static bool ValidateCurrency(string currency)
 {
     if (string.IsNullOrEmpty(currency))
     {
         return(false);
     }
     if (!GAUtilities.StringMatch(currency, "^[A-Z]{3}$"))
     {
         return(false);
     }
     return(true);
 }
예제 #8
0
        public static bool ValidateEventIdCharacters(string eventId)
        {
            if (string.IsNullOrEmpty(eventId))
            {
                return(false);
            }

            if (!GAUtilities.StringMatch(eventId, "^[A-Za-z0-9\\s\\-_\\.\\(\\)\\!\\?]{1,64}(:[A-Za-z0-9\\s\\-_\\.\\(\\)\\!\\?]{1,64}){0,4}$"))
            {
                return(false);
            }
            return(true);
        }
예제 #9
0
        public static bool ValidateEventIdLength(string eventId)
        {
            if (string.IsNullOrEmpty(eventId))
            {
                return(false);
            }

            if (!GAUtilities.StringMatch(eventId, "^[^:]{1,64}(?::[^:]{1,64}){0,4}$"))
            {
                return(false);
            }
            return(true);
        }
예제 #10
0
        public static long GetClientTsAdjusted()
        {
            long clientTs = GAUtilities.TimeIntervalSince1970();
            long clientTsAdjustedInteger = clientTs + Instance.ClientServerTimeOffset;

            if (GAValidator.ValidateClientTs(clientTsAdjustedInteger))
            {
                return(clientTsAdjustedInteger);
            }
            else
            {
                return(clientTs);
            }
        }
예제 #11
0
        private byte[] CreatePayloadData(string payload, bool gzip)
        {
            byte[] payloadData;

            if (gzip)
            {
                payloadData = GAUtilities.GzipCompress(payload);
                GALogger.D("Gzip stats. Size: " + Encoding.UTF8.GetBytes(payload).Length + ", Compressed: " + payloadData.Length + ", Content: " + payload);
            }
            else
            {
                payloadData = Encoding.UTF8.GetBytes(payload);
            }

            return(payloadData);
        }
예제 #12
0
        public void SendSdkErrorEvent(EGASdkErrorType type)
        {
            if (!GAState.IsEventSubmissionEnabled)
            {
                return;
            }

            string gameKey   = GAState.GameKey;
            string secretKey = GAState.GameSecret;

            // Validate
            if (!GAValidator.ValidateSdkErrorEvent(gameKey, secretKey, type))
            {
                return;
            }

            // Generate URL
            string url = baseUrl + "/" + gameKey + "/" + eventsUrlPath;

            GALogger.D("Sending 'events' URL: " + url);

            string payloadJSONString = "";

            JSONObject json = GAState.GetSdkErrorEventAnnotations();

            string typeString = SdkErrorTypeToString(type);

            json.Add("type", typeString);

            List <JSONNode> eventArray = new List <JSONNode>();

            eventArray.Add(json);
            payloadJSONString = GAUtilities.ArrayOfObjectsToJsonString(eventArray);

            if (string.IsNullOrEmpty(payloadJSONString))
            {
                GALogger.W("sendSdkErrorEvent: JSON encoding failed.");
                return;
            }

            GALogger.D("sendSdkErrorEvent json: " + payloadJSONString);
            byte[]       payloadData  = Encoding.UTF8.GetBytes(payloadJSONString);
            SdkErrorTask sdkErrorTask = new SdkErrorTask(type, payloadData, secretKey);

            sdkErrorTask.Execute(url);
        }
예제 #13
0
        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 (!GAUtilities.StringMatch(resourceCurrency, "^[A-Za-z]+$"))
                {
                    GALogger.I("resource currencies validation failed: a resource currency can only be A-Z, a-z. String was: " + resourceCurrency);
                    return(false);
                }
            }
            return(true);
        }
예제 #14
0
        public static JSONObject ValidateAndCleanCustomFields(IDictionary <string, object> fields)
        {
            JSONObject result = new JSONObject();

            if (fields != null)
            {
                int count = 0;

                foreach (KeyValuePair <string, object> entry in fields)
                {
                    if (entry.Key == null || entry.Value == null)
                    {
                        GALogger.W("ValidateAndCleanCustomFields: entry with key=" + entry.Key + ", value=" + entry.Value + " has been omitted because its key or value is null");
                    }
                    else if (count < MaxCustomFieldsCount)
                    {
                        if (GAUtilities.StringMatch(entry.Key, "^[a-zA-Z0-9_]{1," + MaxCustomFieldsKeyLength + "}$"))
                        {
                            if (entry.Value is string || entry.Value is char)
                            {
                                string value = Convert.ToString(entry.Value);

                                if (value.Length <= MaxCustomFieldsValueStringLength && value.Length > 0)
                                {
                                    result[entry.Key] = value;
                                    ++count;
                                }
                                else
                                {
                                    GALogger.W("ValidateAndCleanCustomFields: entry with key=" + entry.Key + ", value=" + entry.Value + " has been omitted because its value is an empty string or exceeds the max number of characters (" + MaxCustomFieldsValueStringLength + ")");
                                }
                            }
                            else if (entry.Value is double)
                            {
                                result[entry.Key] = new JSONNumber((double)entry.Value);
                                ++count;
                            }
                            else if (entry.Value is float)
                            {
                                result[entry.Key] = new JSONNumber((float)entry.Value);
                                ++count;
                            }
                            else if (entry.Value is long || entry.Value is ulong)
                            {
                                result[entry.Key] = new JSONNumber(Convert.ToInt64(entry.Value));
                                ++count;
                            }
                            else if (entry.Value is int ||
                                     entry.Value is byte ||
                                     entry.Value is sbyte ||
                                     entry.Value is byte ||
                                     entry.Value is uint ||
                                     entry.Value is short ||
                                     entry.Value is ushort)
                            {
                                result[entry.Key] = new JSONNumber(Convert.ToInt32(entry.Value));
                                ++count;
                            }
                            else
                            {
                                GALogger.W("ValidateAndCleanCustomFields: entry with key=" + entry.Key + ", value=" + entry.Value + " has been omitted because its value is not a string or number");
                            }
                        }
                        else
                        {
                            GALogger.W("ValidateAndCleanCustomFields: entry with key=" + entry.Key + ", value=" + entry.Value + " has been omitted because its key illegal characters, an empty or exceeds the max number of characters (" + MaxCustomFieldsKeyLength + ")");
                        }
                    }
                    else
                    {
                        GALogger.W("ValidateAndCleanCustomFields: entry with key=" + entry.Key + ", value=" + entry.Value + " has been omitted because it exceeds the max number of custom fields (" + MaxCustomFieldsCount + ")");
                    }
                }
            }

            return(result);
        }
예제 #15
0
 public static bool ValidateConnectionType(string connectionType)
 {
     return(GAUtilities.StringMatch(connectionType, "^(wwan|wifi|lan|offline)$"));
 }
예제 #16
0
        private static void AddEventToStore(JSONClass eventData)
#endif
        {
            // Check if datastore is available
            if (!GAStore.IsTableReady)
            {
                GALogger.W("Could not add event: SDK datastore error");
                return;
            }

            // Check if we are initialized
            if (!GAState.Initialized)
            {
                GALogger.W("Could not add event: SDK is not initialized");
                return;
            }

            try
            {
                // Check db size limits (10mb)
                // If database is too large block all except user, session and business
                if (GAStore.IsDbTooLargeForEvents && !GAUtilities.StringMatch(eventData["category"].AsString, "^(user|session_end|business)$"))
                {
                    GALogger.W("Database too large. Event has been blocked.");
                    return;
                }

                // Get default annotations
                JSONClass ev = GAState.GetEventAnnotations();

                // Create json with only default annotations
                string jsonDefaults = ev.SaveToBase64();

                // Merge with eventData
                foreach (KeyValuePair <string, JSONNode> pair in eventData)
                {
                    ev.Add(pair.Key, pair.Value);
                }

                // Create json string representation
                string json = ev.ToString();

                // output if VERBOSE LOG enabled

                GALogger.II("Event added to queue: " + json);

                // Add to store
                Dictionary <string, object> parameters = new Dictionary <string, object>();
                parameters.Add("$status", "new");
                parameters.Add("$category", ev["category"].Value);
                parameters.Add("$session_id", ev["session_id"].Value);
                parameters.Add("$client_ts", ev["client_ts"].Value);
                parameters.Add("$event", ev.SaveToBase64());
                string sql = "INSERT INTO ga_events (status, category, session_id, client_ts, event) VALUES($status, $category, $session_id, $client_ts, $event);";

                GAStore.ExecuteQuerySync(sql, parameters);

                // Add to session store if not last
                if (eventData["category"].AsString.Equals(CategorySessionEnd))
                {
                    parameters.Clear();
                    parameters.Add("$session_id", ev["session_id"].Value);
                    sql = "DELETE FROM ga_session WHERE session_id = $session_id;";
                    GAStore.ExecuteQuerySync(sql, parameters);
                }
                else
                {
                    sql = "INSERT OR REPLACE INTO ga_session(session_id, timestamp, event) VALUES($session_id, $timestamp, $event);";
                    parameters.Clear();
                    parameters.Add("$session_id", ev["session_id"].Value);
                    parameters.Add("$timestamp", GAState.SessionStart);
                    parameters.Add("$event", jsonDefaults);
                    GAStore.ExecuteQuerySync(sql, parameters);
                }
            }
            catch (Exception e)
            {
                GALogger.E("addEventToStoreWithEventData: error using json");
                GALogger.E(e.ToString());
            }
        }
예제 #17
0
 public static bool HasAvailableResourceItemType(string itemType)
 {
     return(GAUtilities.StringArrayContainsString(AvailableResourceItemTypes, itemType));
 }
예제 #18
0
 public static bool HasAvailableResourceCurrency(string currency)
 {
     return(GAUtilities.StringArrayContainsString(AvailableResourceCurrencies, currency));
 }
예제 #19
0
 public static bool HasAvailableCustomDimensions03(string dimension3)
 {
     return(GAUtilities.StringArrayContainsString(AvailableCustomDimensions03, dimension3));
 }
예제 #20
0
        public static JSONArray ExecuteQuerySync(string sql, Dictionary <string, object> parameters, bool useTransaction)
        {
            // Force transaction if it is an update, insert or delete.
            if (GAUtilities.StringMatch(sql.ToUpperInvariant(), "^(UPDATE|INSERT|DELETE)"))
            {
                useTransaction = true;
            }

            // Get database connection from singelton sharedInstance
            SqliteConnection sqlDatabasePtr = Instance.SqlDatabase;

            // Create mutable array for results
            JSONArray results = new JSONArray();

            SqliteTransaction transaction = null;
            SqliteCommand     command     = null;

            try
            {
                if (useTransaction)
                {
                    transaction = sqlDatabasePtr.BeginTransaction();
                }

                command = sqlDatabasePtr.CreateCommand();

                if (useTransaction)
                {
                    command.Transaction = transaction;
                }
                command.CommandText = sql;
                command.Prepare();

                // Bind parameters
                if (parameters.Count != 0)
                {
                    foreach (KeyValuePair <string, object> pair in parameters)
                    {
                        command.Parameters.AddWithValue(pair.Key, pair.Value);
                    }
                }

                using (SqliteDataReader reader = command.ExecuteReader())
                {
                    // Loop through results
                    while (reader.Read())
                    {
                        // get columns count
                        int columnCount = reader.FieldCount;

                        JSONObject row = new JSONObject();
                        for (int i = 0; i < columnCount; i++)
                        {
                            string column = reader.GetName(i);

                            if (string.IsNullOrEmpty(column))
                            {
                                continue;
                            }

                            row[column] = reader.GetValue(i).ToString();
                        }
                        results.Add(row);
                    }
                }

                if (useTransaction)
                {
                    transaction.Commit();
                }
            }
            catch (SqliteException e)
            {
                // TODO(nikolaj): Should we do a db validation to see if the db is corrupt here?
                GALogger.E("SQLITE3 ERROR: " + e);
                results = null;

                if (useTransaction)
                {
                    if (transaction != null)
                    {
                        try
                        {
                            transaction.Rollback();
                        }
                        catch (SqliteException ex)
                        {
                            GALogger.E("SQLITE3 ROLLBACK ERROR: " + ex);
                        }
                        finally
                        {
                            transaction.Dispose();
                        }
                    }
                }
            }
            finally
            {
                if (command != null)
                {
                    command.Dispose();
                }

                if (transaction != null)
                {
                    transaction.Dispose();
                }
            }

            // Return results
            return(results);
        }
예제 #21
0
        public KeyValuePair <EGAHTTPApiResponse, JSONNode> SendEventsInArray(List <JSONNode> eventArray)
#endif
        {
            JSONNode json;

            if (eventArray.Count == 0)
            {
                GALogger.D("sendEventsInArray called with missing eventArray");
            }

            EGAHTTPApiResponse result  = EGAHTTPApiResponse.NoResponse;
            string             gameKey = GAState.GameKey;

            // Generate URL
            string url = baseUrl + "/" + gameKey + "/" + eventsUrlPath;

            GALogger.D("Sending 'events' URL: " + url);

            // make JSON string from data
            string JSONstring = GAUtilities.ArrayOfObjectsToJsonString(eventArray);

            if (JSONstring.Length == 0)
            {
                GALogger.D("sendEventsInArray JSON encoding failed of eventArray");
                json   = null;
                result = EGAHTTPApiResponse.JsonEncodeFailed;
                return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json));
            }

            string         body                = "";
            HttpStatusCode responseCode        = (HttpStatusCode)0;
            string         responseDescription = "";
            string         authorization       = "";

            try
            {
                byte[]         payloadData = CreatePayloadData(JSONstring, useGzip);
                HttpWebRequest request     = CreateRequest(url, payloadData, useGzip);
                authorization = request.Headers[HttpRequestHeader.Authorization];
#if WINDOWS_UWP || WINDOWS_WSA
                using (Stream dataStream = await request.GetRequestStreamAsync())
#else
                using (Stream dataStream = request.GetRequestStream())
#endif
                {
                    dataStream.Write(payloadData, 0, payloadData.Length);
                }

#if WINDOWS_UWP || WINDOWS_WSA
                using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse)
#else
                using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
#endif
                {
                    using (Stream dataStream = response.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(dataStream))
                        {
                            string responseString = reader.ReadToEnd();

                            responseCode        = response.StatusCode;
                            responseDescription = response.StatusDescription;

                            // print result
                            body = responseString;
                        }
                    }
                }
            }
            catch (WebException e)
            {
                if (e.Response != null)
                {
                    using (HttpWebResponse response = (HttpWebResponse)e.Response)
                    {
                        using (Stream streamResponse = response.GetResponseStream())
                        {
                            using (StreamReader streamRead = new StreamReader(streamResponse))
                            {
                                string responseString = streamRead.ReadToEnd();

                                responseCode        = response.StatusCode;
                                responseDescription = response.StatusDescription;

                                body = responseString;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                GALogger.E(e.ToString());
            }

            GALogger.D("events request content: " + body);

            EGAHTTPApiResponse requestResponseEnum = ProcessRequestResponse(responseCode, responseDescription, body, "Events");

            // if not 200 result
            if (requestResponseEnum != EGAHTTPApiResponse.Ok && requestResponseEnum != EGAHTTPApiResponse.BadRequest)
            {
                GALogger.D("Failed events Call. URL: " + url + ", Authorization: " + authorization + ", JSONString: " + JSONstring);
                json   = null;
                result = requestResponseEnum;
                return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json));
            }

            // decode JSON
            JSONNode requestJsonDict = JSON.Parse(body);

            if (requestJsonDict == null)
            {
                json   = null;
                result = EGAHTTPApiResponse.JsonDecodeFailed;
                return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json));
            }

            // print reason if bad request
            if (requestResponseEnum == EGAHTTPApiResponse.BadRequest)
            {
                GALogger.D("Failed Events Call. Bad request. Response: " + requestJsonDict.ToString());
            }

            // return response
            json   = requestJsonDict;
            result = requestResponseEnum;
            return(new KeyValuePair <EGAHTTPApiResponse, JSONNode>(result, json));
        }
예제 #22
0
        public static JSONArray ExecuteQuerySync(string sql, Dictionary <string, object> parameters, bool useTransaction)
        {
                        #if !UNITY_EDITOR
            // Force transaction if it is an update, insert or delete.
            if (GAUtilities.StringMatch(sql.ToUpperInvariant(), "^(UPDATE|INSERT|DELETE)"))
            {
                useTransaction = true;
            }

            // Get database connection from singelton sharedInstance
            SqliteConnection sqlDatabasePtr = Instance.SqlDatabase;

            // Create mutable array for results
            JSONArray results = new JSONArray();

            SqliteCommand command = null;

            try
            {
                if (useTransaction)
                {
                    sqlDatabasePtr.BeginTransaction();
                }

                command = sqlDatabasePtr.CreateCommand();

                command.CommandText = sql;

                // Bind parameters
                if (parameters.Count != 0)
                {
                    foreach (KeyValuePair <string, object> pair in parameters)
                    {
                        command.Bind(pair.Key, pair.Value);
                    }
                }

                // Loop through results
                foreach (List <Tuple <string, string> > reader in command.ExecuteQueryMY())
                {
                    // get columns count
                    int columnCount = reader.Count;

                    JSONClass row = new JSONClass();
                    for (int i = 0; i < columnCount; i++)
                    {
                        string column = reader[i].Item1;

                        if (string.IsNullOrEmpty(column))
                        {
                            continue;
                        }

                        row[column] = reader[i].Item2.ToString();
                    }
                    results.Add(row);
                }


                if (useTransaction)
                {
                    //transaction.Commit();
                    sqlDatabasePtr.Commit();
                }
            }
            catch (SqliteException e)
            {
                // TODO(nikolaj): Should we do a db validation to see if the db is corrupt here?
                GALogger.E("SQLITE3 ERROR: " + e);
                results = null;
            }
            finally
            {
            }

            // Return results
            return(results);
                        #else
            return(null);
                        #endif
        }
예제 #23
0
        private static long CalculateServerTimeOffset(long serverTs)
        {
            long clientTs = GAUtilities.TimeIntervalSince1970();

            return(serverTs - clientTs);
        }
예제 #24
0
 public SdkErrorTask(EGASdkErrorType type, byte[] payloadData, string secretKey)
 {
     this.type        = type;
     this.payloadData = payloadData;
     this.hashHmac    = GAUtilities.HmacWithKey(secretKey, payloadData);
 }