diff --git a/CHANGELOG.md b/CHANGELOG.md index 79a284c3..1b1c757e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # pusher-websocket-java changelog +### Version 2.4.2 - 23th Sep 2022 +* Fixes a crash when an event comes in without and escaped data json member. +* update to com.google.code.gson:gson:2.9.1 +* update to org.java-websocket:Java-WebSocket:1.5.3 + ### Version 2.4.1 - 13th Sep 2022 * Refactoring and code cleanup of event handling in the SDK * Fixes subscription_count events diff --git a/build.gradle b/build.gradle index a7d52f6e..010ad15f 100644 --- a/build.gradle +++ b/build.gradle @@ -46,8 +46,8 @@ repositories { } dependencies { - implementation "com.google.code.gson:gson:2.8.9" - implementation "org.java-websocket:Java-WebSocket:1.5.1" + implementation "com.google.code.gson:gson:2.9.1" + implementation "org.java-websocket:Java-WebSocket:1.5.3" testImplementation "org.mockito:mockito-all:1.8.5" testImplementation "org.powermock:powermock-module-junit4:1.4.11" diff --git a/src/main/java/com/pusher/client/channel/PusherEvent.java b/src/main/java/com/pusher/client/channel/PusherEvent.java index 7f9d05a8..e60ab529 100644 --- a/src/main/java/com/pusher/client/channel/PusherEvent.java +++ b/src/main/java/com/pusher/client/channel/PusherEvent.java @@ -1,19 +1,17 @@ package com.pusher.client.channel; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import com.google.gson.annotations.SerializedName; import java.util.Map; public class PusherEvent { - @SerializedName("user_id") - private final String userId; - private final String data; - private final String channel; - private final String event; + private JsonObject jsonObject = new JsonObject(); /** * getProperty returns the value associated with the key, or null. @@ -36,7 +34,7 @@ public Object getProperty(String key) { case "channel": return getChannelName(); case "data": - return getData(); + return jsonObject.get("data"); case "event": return getEventName(); default: @@ -45,47 +43,52 @@ public Object getProperty(String key) { } public String getUserId() { - return userId; + return jsonObject.has("user_id") ? jsonObject.get("user_id").getAsString() : null; } public String getChannelName() { - return channel; + return jsonObject.has("channel") ? jsonObject.get("channel").getAsString() : null; } public String getEventName() { - return event; + return jsonObject.has("event") ? jsonObject.get("event").getAsString() : null; } public String getData() { - return data; + JsonElement data = jsonObject.get("data"); + if (data.isJsonPrimitive()) { + return data.getAsString(); + } + final Gson gson = new GsonBuilder().serializeNulls().disableHtmlEscaping().create(); + return gson.toJson(data); } public String toString() { - return new Gson().toJson(this); + return this.toJson(); } public PusherEvent(String event, String channel, String userId, String data) { - this.event = event; - this.channel = channel; - this.userId = userId; - this.data = data; + jsonObject.addProperty("event", event); + jsonObject.addProperty("channel", channel); + jsonObject.addProperty("userId", userId); + jsonObject.addProperty("data", data); } public PusherEvent(String event, String channel, String userId, Map data) { this(event, channel, userId, new Gson().toJson(data)); } + public PusherEvent(JsonObject jsonObject) { + this.jsonObject = jsonObject; + } + public String toJson() { - return new Gson().toJson(this); + final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + return gson.toJson(jsonObject); } public static PusherEvent fromJson(String json) { - JsonObject o = new Gson().fromJson(json, JsonObject.class); - return new PusherEvent( - o.has("event") ? o.get("event").getAsString() : "", - o.has("channel") ? o.get("channel").getAsString() : "", - o.has("user_id") ? o.get("user_id").getAsString() : "", - o.has("data") ? o.get("data").getAsString() : "" - ); + final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + return new PusherEvent(gson.fromJson(json, JsonObject.class)); } } diff --git a/src/main/java/com/pusher/client/channel/impl/ChannelManager.java b/src/main/java/com/pusher/client/channel/impl/ChannelManager.java index 3d464815..32f9acc1 100644 --- a/src/main/java/com/pusher/client/channel/impl/ChannelManager.java +++ b/src/main/java/com/pusher/client/channel/impl/ChannelManager.java @@ -100,10 +100,12 @@ public void unsubscribeFrom(final String channelName) { } public void handleEvent(final PusherEvent event) { - final InternalChannel channel = channelNameToChannelMap.get(event.getChannelName()); - - if (channel != null) { - channel.handleEvent(event); + String channelName = event.getChannelName(); + if (channelName != null) { + final InternalChannel channel = channelNameToChannelMap.get(channelName); + if (channel != null) { + channel.handleEvent(event); + } } } diff --git a/src/main/java/com/pusher/client/channel/impl/PrivateChannelImpl.java b/src/main/java/com/pusher/client/channel/impl/PrivateChannelImpl.java index 0b7efc81..93bfded7 100644 --- a/src/main/java/com/pusher/client/channel/impl/PrivateChannelImpl.java +++ b/src/main/java/com/pusher/client/channel/impl/PrivateChannelImpl.java @@ -61,7 +61,8 @@ public void trigger(final String eventName, final String data) { ); } - connection.sendMessage(new PusherEvent(eventName, name, null, data).toJson()); + String json = new PusherEvent(eventName, name, null, data).toJson(); + connection.sendMessage(json); } /* Base class overrides */ diff --git a/src/test/java/com/pusher/client/channel/PusherEventTest.java b/src/test/java/com/pusher/client/channel/PusherEventTest.java index 608ce85e..c2312f6f 100644 --- a/src/test/java/com/pusher/client/channel/PusherEventTest.java +++ b/src/test/java/com/pusher/client/channel/PusherEventTest.java @@ -45,4 +45,11 @@ public void testUserIdIsExtracted() { ); assertEquals("my-user-id", e.getUserId()); } -} + @Test + public void testErrorData() { + final PusherEvent e = PusherEvent.fromJson( + "{\"event\":\"pusher:error\",\"data\":{\"code\":null,\"message\":\"Invalid key in subscription auth data: ''\"}}" + ); + assertEquals("{\"code\":null,\"message\":\"Invalid key in subscription auth data: ''\"}", e.getData()); + } +} \ No newline at end of file diff --git a/src/test/java/com/pusher/client/channel/impl/PrivateChannelImplTest.java b/src/test/java/com/pusher/client/channel/impl/PrivateChannelImplTest.java index fedfe5dc..11b48106 100644 --- a/src/test/java/com/pusher/client/channel/impl/PrivateChannelImplTest.java +++ b/src/test/java/com/pusher/client/channel/impl/PrivateChannelImplTest.java @@ -143,9 +143,7 @@ public void testTriggerWithValidEventSendsMessage() { verify(mockConnection) .sendMessage( - "{\"data\":\"{\\\"fish\\\":\\\"chips\\\"}\",\"channel\":\"" + - getChannelName() + - "\",\"event\":\"client-myEvent\"}" + "{\"event\":\"client-myEvent\",\"channel\":\"" + getChannelName() + "\",\"data\":\"{\\\"fish\\\":\\\"chips\\\"}\"}" ); } @@ -173,7 +171,7 @@ public void testTriggerWithString() { ((PrivateChannelImpl) channel).trigger("client-myEvent", "string"); verify(mockConnection) - .sendMessage("{\"data\":\"string\",\"channel\":\"" + channel.getName() + "\",\"event\":\"client-myEvent\"}"); + .sendMessage("{\"event\":\"client-myEvent\",\"channel\":\"" + channel.getName() + "\",\"data\":\"string\"}"); } @Test(expected = IllegalStateException.class)