Skip to content

Commit

Permalink
Merge pull request #1589 from OneSignal/fix/euid_with_dollar_sign
Browse files Browse the repository at this point in the history
Fix crash when `$` sign is in external user ID
  • Loading branch information
nan-li authored May 16, 2022
2 parents 5f40a60 + 1023b01 commit a6295ad
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 14 deletions.
30 changes: 30 additions & 0 deletions OneSignalSDK/onesignal/src/main/java/com/onesignal/JSONUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.onesignal.UserStateSynchronizer.EXTERNAL_USER_ID;


class JSONUtils {
Expand Down Expand Up @@ -130,6 +134,32 @@ static String toStringNE(JSONArray jsonArray) {
return strArray + "]";
}

/**
* Returns the JSONObject as a String with the external user ID unescaped.
* Needed b/c the default JSONObject.toString() escapes (/) with (\/), which customers may not want.
*/
static String toUnescapedEUIDString(JSONObject json) {
String strJsonBody = json.toString();

if (json.has(EXTERNAL_USER_ID)) {
// find the value of the external user ID
Pattern eidPattern = Pattern.compile("(?<=\"external_user_id\":\").*?(?=\")");
Matcher eidMatcher = eidPattern.matcher(strJsonBody);

if (eidMatcher.find()) {
String matched = eidMatcher.group(0);
if (matched != null) {
String unescapedEID = matched.replace("\\/", "/");
// backslashes (\) and dollar signs ($) in the replacement string will be treated literally
unescapedEID = eidMatcher.quoteReplacement(unescapedEID);
strJsonBody = eidMatcher.replaceAll(unescapedEID);
}
}
}

return strJsonBody;
}

static JSONObject getJSONObjectWithoutBlankValues(ImmutableJSONObject jsonObject, String getKey) {
if (!jsonObject.has(getKey))
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.HttpsURLConnection;

Expand Down Expand Up @@ -168,18 +166,7 @@ private static Thread startHTTPConnection(String url, String method, JSONObject
}

if (jsonBody != null) {
String strJsonBody = jsonBody.toString();

Pattern eidPattern = Pattern.compile("(?<=\"external_user_id\":\").*\\\\/.*?(?=\",|\"\\})");
Matcher eidMatcher = eidPattern.matcher(strJsonBody);

if (eidMatcher.find()) {
String matched = eidMatcher.group(0);
if (matched != null) {
String unescapedEID = matched.replace("\\/", "/");
strJsonBody = eidMatcher.replaceAll(unescapedEID);
}
}
String strJsonBody = JSONUtils.toUnescapedEUIDString(jsonBody);

OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "OneSignalRestClient: " + method + " SEND JSON: " + strJsonBody);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ public static JSONObject bundleAsJSONObject(Bundle bundle) {
return NotificationBundleProcessor.bundleAsJSONObject(bundle);
}

public static String toUnescapedEUIDString(JSONObject json) {
return JSONUtils.toUnescapedEUIDString(json);
}

public static void OneSignal_handleNotificationOpen(Activity context, final JSONArray data, final String notificationId) {
OneSignal.handleNotificationOpen(context, data, notificationId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
import static com.onesignal.OneSignalPackagePrivateHelper.OneSignal_setTrackerFactory;
import static com.onesignal.OneSignalPackagePrivateHelper.OneSignal_taskQueueWaitingForInit;
import static com.onesignal.OneSignalPackagePrivateHelper.OSObservable;
import static com.onesignal.OneSignalPackagePrivateHelper.toUnescapedEUIDString;
import static com.onesignal.ShadowOneSignalRestClient.EMAIL_USER_ID;
import static com.onesignal.ShadowOneSignalRestClient.PUSH_USER_ID;
import static com.onesignal.ShadowOneSignalRestClient.REST_METHOD;
Expand Down Expand Up @@ -3378,6 +3379,69 @@ public void testOSNotificationOpenResultToJSONObject() throws Exception {
assertEquals("collapseId1", firstGroupedNotification.optString("collapseId"));
}

// ####### Unit test JSONUtils methods
@Test
public void test_JSONUtils_toUnescapedEUIDString() throws Exception {
// 1. Test when EUID is first in the json, and has ($) and (/), and ($) elsewhere

// Set up the JSONObject to test with
String jsonStringWithDollarAndSlash = "{" +
"\"external_user_id\":\"$1$/abc/de$f/\"," +
"\"app_id\":\"b4f7f966-d8cc-11e4-bed1-df8f05be55ba\"," +
"\"timezone\":\"$Europe/London\"" +
"}";
JSONObject jsonWithDollarAndSlash = new JSONObject(jsonStringWithDollarAndSlash);

// The expected string which escapes the "timezone" slash (/) only
String expected_jsonStringWithDollarAndSlash = "{" +
"\"external_user_id\":\"$1$/abc/de$f/\"," +
"\"app_id\":\"b4f7f966-d8cc-11e4-bed1-df8f05be55ba\"," +
"\"timezone\":\"$Europe\\/London\"" +
"}";

// The actual string result from calling JSONUtils.toUnescapedEUIDString()
String actual_jsonStringWithDollarAndSlash = toUnescapedEUIDString(jsonWithDollarAndSlash);

// These two strings should be equal
assertEquals(expected_jsonStringWithDollarAndSlash, actual_jsonStringWithDollarAndSlash);

// 2. Test when EUID is first in the json, and has no dollar nor slash

String jsonStringWithEUID = "{" +
"\"external_user_id\":\"123abc\"," +
"\"app_id\":\"b4f7f966-d8cc-11e4-bed1-df8f05be55ba\"," +
"\"timezone\":\"$Europe/London\"" +
"}";
JSONObject jsonWithEUID = new JSONObject(jsonStringWithEUID);

String expected_jsonStringWithEUID = "{" +
"\"external_user_id\":\"123abc\"," +
"\"app_id\":\"b4f7f966-d8cc-11e4-bed1-df8f05be55ba\"," +
"\"timezone\":\"$Europe\\/London\"" +
"}";

String actual_jsonStringWithEUID = toUnescapedEUIDString(jsonWithEUID);

assertEquals(expected_jsonStringWithEUID, actual_jsonStringWithEUID);

// 3. Test when there is no EUID is in the json

String jsonStringWithoutEUID = "{" +
"\"app_id\":\"b4f7f966-d8cc-11e4-bed1-df8f05be55ba\"," +
"\"timezone\":\"Europe/London\"" +
"}";
JSONObject jsonWithoutEUID = new JSONObject(jsonStringWithoutEUID);

String expected_jsonStringWithoutEUID = "{" +
"\"app_id\":\"b4f7f966-d8cc-11e4-bed1-df8f05be55ba\"," +
"\"timezone\":\"Europe\\/London\"" +
"}";

String actual_jsonStringWithoutEUID = toUnescapedEUIDString(jsonWithoutEUID);

assertEquals(expected_jsonStringWithoutEUID, actual_jsonStringWithoutEUID);
}

@Test
public void testNotificationOpenedProcessorHandlesEmptyIntent() {
NotificationOpenedProcessor_processFromContext(blankActivity, new Intent());
Expand Down

0 comments on commit a6295ad

Please sign in to comment.