fix(wired): bound utility effect payloads

This commit is contained in:
simoleo89
2026-06-17 20:33:52 +02:00
parent 416d0bb088
commit f292426529
9 changed files with 142 additions and 43 deletions
@@ -93,16 +93,17 @@ public class WiredEffectAdjustClock extends InteractionWiredEffect {
this.items.clear(); this.items.clear();
String wiredData = set.getString("wired_data"); String wiredData = set.getString("wired_data");
if (wiredData != null && wiredData.startsWith("{")) { JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); if (jsonData != null) {
this.setDelay(data.delay); this.setDelay(WiredUtilityPayloadGuard.delay(jsonData.delay));
this.operator = this.normalizeOperator(data.operator); this.operator = this.normalizeOperator(jsonData.operator);
this.furniSource = data.furniSource; this.furniSource = WiredUtilityPayloadGuard.furniSource(jsonData.furniSource);
this.minutes = this.normalizeMinutes(data.minutes); this.minutes = this.normalizeMinutes(jsonData.minutes);
this.halfSecondSteps = this.normalizeHalfSecondSteps(data.halfSecondSteps); this.halfSecondSteps = this.normalizeHalfSecondSteps(jsonData.halfSecondSteps);
if (data.itemIds != null) { if (jsonData.itemIds != null) {
for (Integer id : data.itemIds) { for (Integer id : jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id); HabboItem item = room.getHabboItem(id);
if (item != null) { if (item != null) {
@@ -298,7 +298,7 @@ public class WiredEffectChangeVariableValue extends InteractionWiredEffect {
String wiredData = set.getString("wired_data"); String wiredData = set.getString("wired_data");
if (wiredData == null || wiredData.isEmpty() || !wiredData.startsWith("{")) return; if (wiredData == null || wiredData.isEmpty() || !wiredData.startsWith("{")) return;
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); JsonData data = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (data == null) return; if (data == null) return;
this.destinationTargetType = normalizeTargetType(data.destinationTargetType); this.destinationTargetType = normalizeTargetType(data.destinationTargetType);
@@ -312,7 +312,7 @@ public class WiredEffectChangeVariableValue extends InteractionWiredEffect {
this.destinationFurniSource = normalizeDestinationFurniSource(data.destinationFurniSource); this.destinationFurniSource = normalizeDestinationFurniSource(data.destinationFurniSource);
this.referenceUserSource = normalizeUserSource(data.referenceUserSource); this.referenceUserSource = normalizeUserSource(data.referenceUserSource);
this.referenceFurniSource = normalizeReferenceFurniSource(data.referenceFurniSource); this.referenceFurniSource = normalizeReferenceFurniSource(data.referenceFurniSource);
this.setDelay(Math.max(0, data.delay)); this.setDelay(WiredUtilityPayloadGuard.delay(data.delay));
if (room != null) { if (room != null) {
try { try {
@@ -260,14 +260,14 @@ public class WiredEffectRemoveVariable extends InteractionWiredEffect {
} }
if (wiredData.startsWith("{")) { if (wiredData.startsWith("{")) {
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); JsonData data = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
if (data != null) { if (data != null) {
this.variableItemId = Math.max(0, data.variableItemId); this.variableItemId = Math.max(0, data.variableItemId);
this.targetType = normalizeTargetType(data.targetType); this.targetType = normalizeTargetType(data.targetType);
this.userSource = normalizeUserSource(data.userSource); this.userSource = normalizeUserSource(data.userSource);
this.furniSource = normalizeFurniSource(data.furniSource); this.furniSource = normalizeFurniSource(data.furniSource);
this.setDelay(Math.max(0, data.delay)); this.setDelay(WiredUtilityPayloadGuard.delay(data.delay));
if (room != null && data.selectedFurniIds != null) { if (room != null && data.selectedFurniIds != null) {
for (Integer itemId : data.selectedFurniIds) { for (Integer itemId : data.selectedFurniIds) {
@@ -96,19 +96,16 @@ public class WiredEffectResetTimers extends InteractionWiredEffect {
public void loadWiredData(ResultSet set, Room room) throws SQLException { public void loadWiredData(ResultSet set, Room room) throws SQLException {
String wiredData = set.getString("wired_data"); String wiredData = set.getString("wired_data");
if (wiredData.startsWith("{")) { JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); if (jsonData != null) {
this.delay = data.delay; this.delay = WiredUtilityPayloadGuard.delay(jsonData.delay);
} else { } else {
try { if (wiredData != null && !wiredData.equals("")) {
if (!wiredData.equals("")) { this.delay = WiredUtilityPayloadGuard.parseDelay(wiredData);
this.delay = Integer.parseInt(wiredData);
}
} catch (Exception e) {
} }
} }
this.setDelay(this.delay); this.setDelay(WiredUtilityPayloadGuard.delay(this.delay));
} }
@Override @Override
@@ -350,9 +350,9 @@ public class WiredEffectSendSignal extends InteractionWiredEffect {
this.forwardItems = new THashSet<>(); this.forwardItems = new THashSet<>();
String wiredData = set.getString("wired_data"); String wiredData = set.getString("wired_data");
if (wiredData != null && wiredData.startsWith("{")) { JsonData data = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); if (data != null) {
this.setDelay(data.delay); this.setDelay(WiredUtilityPayloadGuard.delay(data.delay));
this.antennaSource = data.antennaSource; this.antennaSource = data.antennaSource;
this.furniForward = normalizeSource(data.furniForward); this.furniForward = normalizeSource(data.furniForward);
this.userForward = normalizeSource(data.userForward); this.userForward = normalizeSource(data.userForward);
@@ -100,15 +100,16 @@ public class WiredEffectSetAltitude extends InteractionWiredEffect {
this.items.clear(); this.items.clear();
String wiredData = set.getString("wired_data"); String wiredData = set.getString("wired_data");
if (wiredData != null && wiredData.startsWith("{")) { JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); if (jsonData != null) {
this.setDelay(data.delay); this.setDelay(WiredUtilityPayloadGuard.delay(jsonData.delay));
this.operator = this.normalizeOperator(data.operator); this.operator = this.normalizeOperator(jsonData.operator);
this.altitude = this.parseAltitudeOrDefault(data.altitude); this.altitude = this.parseAltitudeOrDefault(jsonData.altitude);
this.furniSource = data.furniSource; this.furniSource = WiredUtilityPayloadGuard.furniSource(jsonData.furniSource);
if (data.itemIds != null) { if (jsonData.itemIds != null) {
for (Integer id : data.itemIds) { for (Integer id : jsonData.itemIds) {
if (id == null) continue;
HabboItem item = room.getHabboItem(id); HabboItem item = room.getHabboItem(id);
if (item != null) { if (item != null) {
@@ -272,22 +272,23 @@ public class WiredEffectWhisper extends InteractionWiredEffect {
public void loadWiredData(ResultSet set, Room room) throws SQLException { public void loadWiredData(ResultSet set, Room room) throws SQLException {
String wiredData = set.getString("wired_data"); String wiredData = set.getString("wired_data");
if(wiredData.startsWith("{")) { JsonData jsonData = WiredUtilityPayloadGuard.fromJson(wiredData, JsonData.class);
JsonData data = WiredManager.getGson().fromJson(wiredData, JsonData.class); if(jsonData != null) {
this.setDelay(data.delay); this.setDelay(WiredUtilityPayloadGuard.delay(jsonData.delay));
this.message = data.message; this.message = WiredUtilityPayloadGuard.text(jsonData.message);
this.userSource = (data.userSource != null) ? data.userSource : WiredSourceUtil.SOURCE_TRIGGER; this.userSource = (jsonData.userSource != null) ? WiredUtilityPayloadGuard.userSource(jsonData.userSource) : WiredSourceUtil.SOURCE_TRIGGER;
this.visibilitySelection = (data.visibilitySelection != null && data.visibilitySelection == VISIBILITY_ALL_ROOM_USERS) this.visibilitySelection = (jsonData.visibilitySelection != null && jsonData.visibilitySelection == VISIBILITY_ALL_ROOM_USERS)
? VISIBILITY_ALL_ROOM_USERS ? VISIBILITY_ALL_ROOM_USERS
: VISIBILITY_SOURCE_USERS; : VISIBILITY_SOURCE_USERS;
this.bubbleStyle = (data.bubbleStyle != null) ? data.bubbleStyle : RoomChatMessageBubbles.WIRED.getType(); this.bubbleStyle = (jsonData.bubbleStyle != null) ? jsonData.bubbleStyle : RoomChatMessageBubbles.WIRED.getType();
} }
else { else {
this.message = ""; this.message = "";
if (wiredData.split("\t").length >= 2) { String[] wiredDataSplit = wiredData != null ? wiredData.split("\t") : new String[0];
super.setDelay(Integer.parseInt(wiredData.split("\t")[0])); if (wiredDataSplit.length >= 2) {
this.message = wiredData.split("\t")[1]; super.setDelay(WiredUtilityPayloadGuard.parseDelay(wiredDataSplit[0]));
this.message = wiredDataSplit[1];
} }
this.userSource = WiredSourceUtil.SOURCE_TRIGGER; this.userSource = WiredSourceUtil.SOURCE_TRIGGER;
@@ -0,0 +1,67 @@
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
import com.eu.habbo.habbohotel.wired.core.WiredManager;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
final class WiredUtilityPayloadGuard {
static final int MAX_LOAD_DELAY = 3600;
private WiredUtilityPayloadGuard() {
}
static int delay(int value) {
if (value < 0) {
return 0;
}
return Math.min(value, MAX_LOAD_DELAY);
}
static int parseDelay(String value) {
return delay(parseInt(value, 0));
}
static int parseInt(String value, int fallback) {
if (value == null) {
return fallback;
}
try {
return Integer.parseInt(value.trim());
} catch (RuntimeException e) {
return fallback;
}
}
static int userSource(int value) {
return WiredSourceUtil.isDefaultUserSource(value) ? value : WiredSourceUtil.SOURCE_TRIGGER;
}
static int furniSource(int value) {
switch (value) {
case WiredSourceUtil.SOURCE_TRIGGER:
case WiredSourceUtil.SOURCE_SELECTED:
case WiredSourceUtil.SOURCE_SELECTOR:
case WiredSourceUtil.SOURCE_SIGNAL:
return value;
default:
return WiredSourceUtil.SOURCE_TRIGGER;
}
}
static String text(String value) {
return value == null ? "" : value;
}
static <T> T fromJson(String wiredData, Class<T> type) {
if (wiredData == null || !wiredData.startsWith("{")) {
return null;
}
try {
return WiredManager.getGson().fromJson(wiredData, type);
} catch (RuntimeException e) {
return null;
}
}
}
@@ -0,0 +1,32 @@
package com.eu.habbo.habbohotel.items.interactions.wired.effects;
import com.eu.habbo.habbohotel.wired.core.WiredSourceUtil;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class WiredUtilityPayloadGuardTest {
@Test
void clampsDelayAndParsesLegacyNumbers() {
assertEquals(0, WiredUtilityPayloadGuard.delay(-1));
assertEquals(20, WiredUtilityPayloadGuard.parseDelay("20"));
assertEquals(0, WiredUtilityPayloadGuard.parseDelay("bad"));
assertEquals(WiredUtilityPayloadGuard.MAX_LOAD_DELAY, WiredUtilityPayloadGuard.delay(Integer.MAX_VALUE));
}
@Test
void normalizesSourcesAndText() {
assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredUtilityPayloadGuard.userSource(999));
assertEquals(WiredSourceUtil.SOURCE_SELECTOR, WiredUtilityPayloadGuard.userSource(WiredSourceUtil.SOURCE_SELECTOR));
assertEquals(WiredSourceUtil.SOURCE_TRIGGER, WiredUtilityPayloadGuard.furniSource(-1));
assertEquals(WiredSourceUtil.SOURCE_SELECTED, WiredUtilityPayloadGuard.furniSource(WiredSourceUtil.SOURCE_SELECTED));
assertEquals("", WiredUtilityPayloadGuard.text(null));
}
@Test
void malformedJsonReturnsNull() {
assertNull(WiredUtilityPayloadGuard.fromJson("{broken", WiredEffectResetTimers.JsonData.class));
assertNull(WiredUtilityPayloadGuard.fromJson(null, WiredEffectResetTimers.JsonData.class));
}
}