From a90a8754bc64a254bc5ea85834739931c3d79cab Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Wed, 17 Jun 2026 20:45:51 +0200 Subject: [PATCH] fix(wired): bound reward inputs --- .../wired/effects/WiredEffectGiveReward.java | 9 ++- .../habbohotel/wired/WiredGiveRewardItem.java | 28 ++++++-- .../habbo/habbohotel/wired/WiredHandler.java | 69 ++++++++++++++----- .../habbohotel/wired/core/WiredManager.java | 69 ++++++++++++++----- .../wired/WiredGiveRewardItemTest.java | 32 +++++++++ 5 files changed, 165 insertions(+), 42 deletions(-) create mode 100644 Emulator/src/test/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItemTest.java diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java index be5de10b..465e109f 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/items/interactions/wired/effects/WiredEffectGiveReward.java @@ -202,12 +202,15 @@ public class WiredEffectGiveReward extends InteractionWiredEffect { int i = 1; for (String s : items) { - String[] d = s.split(","); + String[] d = s.split(",", -1); if (d.length == 3) { if (!(d[1].contains(":") || d[1].contains(";"))) { - this.rewardItems.add(new WiredGiveRewardItem(i, d[0].equalsIgnoreCase("0"), d[1], Integer.parseInt(d[2]))); - continue; + try { + this.rewardItems.add(new WiredGiveRewardItem(i, d[0].equalsIgnoreCase("0"), d[1], Integer.parseInt(d[2].trim()))); + continue; + } catch (IllegalArgumentException ignored) { + } } } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItem.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItem.java index 168bc750..339413de 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItem.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItem.java @@ -1,6 +1,9 @@ package com.eu.habbo.habbohotel.wired; public class WiredGiveRewardItem { + private static final int MIN_PROBABILITY = 0; + private static final int MAX_PROBABILITY = 100; + public final int id; public final boolean badge; public final String data; @@ -9,17 +12,20 @@ public class WiredGiveRewardItem { public WiredGiveRewardItem(int id, boolean badge, String data, int probability) { this.id = id; this.badge = badge; - this.data = data; - this.probability = probability; + this.data = data == null ? "" : data; + this.probability = normalizeProbability(probability); } public WiredGiveRewardItem(String dataString) { - String[] data = dataString.split(","); + String[] data = dataString == null ? new String[0] : dataString.split(",", -1); + if (data.length < 4) { + throw new IllegalArgumentException("Invalid wired reward item payload"); + } - this.id = Integer.parseInt(data[0]); + this.id = parseRequiredInteger(data[0], "id"); this.badge = data[1].equalsIgnoreCase("0"); this.data = data[2]; - this.probability = Integer.parseInt(data[3]); + this.probability = normalizeProbability(parseRequiredInteger(data[3], "probability")); } @Override @@ -30,4 +36,16 @@ public class WiredGiveRewardItem { public String wiredString() { return (this.badge ? 0 : 1) + "," + this.data + "," + this.probability; } + + private static int parseRequiredInteger(String value, String field) { + try { + return Integer.parseInt(value == null ? "" : value.trim()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid wired reward item " + field, e); + } + } + + private static int normalizeProbability(int probability) { + return Math.max(MIN_PROBABILITY, Math.min(MAX_PROBABILITY, probability)); + } } diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java index 119e1745..a3bc125a 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/WiredHandler.java @@ -525,35 +525,55 @@ public class WiredHandler { if (Emulator.getPluginManager().fireEvent(rewardReceived).isCancelled()) return false; - if (rewardReceived.value.isEmpty()) + String rewardType = rewardReceived.type == null ? "" : rewardReceived.type.trim(); + String rewardValue = rewardReceived.value == null ? "" : rewardReceived.value.trim(); + + if (rewardValue.isEmpty()) return false; - if (rewardReceived.type.equalsIgnoreCase("credits")) { - habbo.giveCredits(Integer.parseInt(rewardReceived.value)); + if (rewardType.equalsIgnoreCase("credits")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.giveCredits(amount); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; - } else if (rewardReceived.type.equalsIgnoreCase("diamonds") || rewardReceived.type.equalsIgnoreCase("diamond")) { - habbo.givePoints(5, Integer.parseInt(rewardReceived.value)); + } else if (rewardType.equalsIgnoreCase("diamonds") || rewardType.equalsIgnoreCase("diamond")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.givePoints(5, amount); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; - } else if (rewardReceived.type.equalsIgnoreCase("pixels")) { - habbo.givePixels(Integer.parseInt(rewardReceived.value)); + } else if (rewardType.equalsIgnoreCase("pixels")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.givePixels(amount); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; - } else if (rewardReceived.type.startsWith("points")) { - int points = Integer.parseInt(rewardReceived.value); + } else if (rewardType.startsWith("points")) { + Integer points = parsePositiveRewardInteger(rewardValue); + if (points == null) return false; + int type = 5; try { - type = Integer.parseInt(rewardReceived.type.replace("points", "")); - } catch (Exception e) { + int parsedType = Integer.parseInt(rewardType.replace("points", "").trim()); + if (parsedType > 0) { + type = parsedType; + } + } catch (NumberFormatException ignored) { } habbo.givePoints(type, points); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; - } else if (rewardReceived.type.equalsIgnoreCase("furni")) { - Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(Integer.parseInt(rewardReceived.value)); + } else if (rewardType.equalsIgnoreCase("furni")) { + Integer itemId = parsePositiveRewardInteger(rewardValue); + if (itemId == null) return false; + + Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(itemId); if (baseItem == null) return false; @@ -567,12 +587,18 @@ public class WiredHandler { habbo.getClient().sendResponse(new InventoryRefreshComposer()); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; - } else if (rewardReceived.type.equalsIgnoreCase("respect")) { - habbo.getHabboStats().respectPointsReceived += Integer.parseInt(rewardReceived.value); + } else if (rewardType.equalsIgnoreCase("respect")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.getHabboStats().respectPointsReceived += amount; completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; - } else if (rewardReceived.type.equalsIgnoreCase("cata")) { - CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(Integer.parseInt(rewardReceived.value)); + } else if (rewardType.equalsIgnoreCase("cata")) { + Integer catalogItemId = parsePositiveRewardInteger(rewardValue); + if (catalogItemId == null) return false; + + CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(catalogItemId); if (item == null) return false; @@ -585,6 +611,15 @@ public class WiredHandler { return false; } + private static Integer parsePositiveRewardInteger(String value) { + try { + int parsed = Integer.parseInt(value == null ? "" : value.trim()); + return parsed > 0 ? parsed : null; + } catch (NumberFormatException ignored) { + return null; + } + } + public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) { if (wiredBox.limit > 0) { if (wiredBox.limit - wiredBox.getGiven() == 0) { diff --git a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java index dbd31773..3368713a 100644 --- a/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java +++ b/Emulator/src/main/java/com/eu/habbo/habbohotel/wired/core/WiredManager.java @@ -1165,35 +1165,52 @@ public final class WiredManager { return false; } - if (rewardReceived.value.isEmpty()) { + String rewardType = rewardReceived.type == null ? "" : rewardReceived.type.trim(); + String rewardValue = rewardReceived.value == null ? "" : rewardReceived.value.trim(); + + if (rewardValue.isEmpty()) { return false; } - if (rewardReceived.type.equalsIgnoreCase("credits")) { - habbo.giveCredits(Integer.parseInt(rewardReceived.value)); + if (rewardType.equalsIgnoreCase("credits")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.giveCredits(amount); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; } - if (rewardReceived.type.equalsIgnoreCase("diamonds") || rewardReceived.type.equalsIgnoreCase("diamond")) { - habbo.givePoints(5, Integer.parseInt(rewardReceived.value)); + if (rewardType.equalsIgnoreCase("diamonds") || rewardType.equalsIgnoreCase("diamond")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.givePoints(5, amount); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; } - if (rewardReceived.type.equalsIgnoreCase("pixels")) { - habbo.givePixels(Integer.parseInt(rewardReceived.value)); + if (rewardType.equalsIgnoreCase("pixels")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.givePixels(amount); completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; } - if (rewardReceived.type.startsWith("points")) { - int points = Integer.parseInt(rewardReceived.value); + if (rewardType.startsWith("points")) { + Integer points = parsePositiveRewardInteger(rewardValue); + if (points == null) return false; + int type = 5; try { - type = Integer.parseInt(rewardReceived.type.replace("points", "")); - } catch (Exception e) { + int parsedType = Integer.parseInt(rewardType.replace("points", "").trim()); + if (parsedType > 0) { + type = parsedType; + } + } catch (NumberFormatException ignored) { } habbo.givePoints(type, points); @@ -1201,8 +1218,11 @@ public final class WiredManager { return true; } - if (rewardReceived.type.equalsIgnoreCase("furni")) { - Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(Integer.parseInt(rewardReceived.value)); + if (rewardType.equalsIgnoreCase("furni")) { + Integer itemId = parsePositiveRewardInteger(rewardValue); + if (itemId == null) return false; + + Item baseItem = Emulator.getGameEnvironment().getItemManager().getItem(itemId); if (baseItem == null) { return false; } @@ -1220,14 +1240,20 @@ public final class WiredManager { return true; } - if (rewardReceived.type.equalsIgnoreCase("respect")) { - habbo.getHabboStats().respectPointsReceived += Integer.parseInt(rewardReceived.value); + if (rewardType.equalsIgnoreCase("respect")) { + Integer amount = parsePositiveRewardInteger(rewardValue); + if (amount == null) return false; + + habbo.getHabboStats().respectPointsReceived += amount; completeReward(habbo, wiredBox, reward, WiredRewardAlertComposer.REWARD_RECEIVED_ITEM); return true; } - if (rewardReceived.type.equalsIgnoreCase("cata")) { - CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(Integer.parseInt(rewardReceived.value)); + if (rewardType.equalsIgnoreCase("cata")) { + Integer catalogItemId = parsePositiveRewardInteger(rewardValue); + if (catalogItemId == null) return false; + + CatalogItem item = Emulator.getGameEnvironment().getCatalogManager().getCatalogItem(catalogItemId); if (item == null) { return false; } @@ -1240,6 +1266,15 @@ public final class WiredManager { return false; } + private static Integer parsePositiveRewardInteger(String value) { + try { + int parsed = Integer.parseInt(value == null ? "" : value.trim()); + return parsed > 0 ? parsed : null; + } catch (NumberFormatException ignored) { + return null; + } + } + public static boolean getReward(Habbo habbo, WiredEffectGiveReward wiredBox) { synchronized (wiredBox) { if (wiredBox.getLimit() > 0) { diff --git a/Emulator/src/test/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItemTest.java b/Emulator/src/test/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItemTest.java new file mode 100644 index 00000000..850ce2bf --- /dev/null +++ b/Emulator/src/test/java/com/eu/habbo/habbohotel/wired/WiredGiveRewardItemTest.java @@ -0,0 +1,32 @@ +package com.eu.habbo.habbohotel.wired; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class WiredGiveRewardItemTest { + @Test + void parsesLegacyRewardPayload() { + WiredGiveRewardItem item = new WiredGiveRewardItem("7,1,credits#25,40"); + + assertEquals(7, item.id); + assertEquals(false, item.badge); + assertEquals("credits#25", item.data); + assertEquals(40, item.probability); + } + + @Test + void rejectsMalformedRewardPayloads() { + assertThrows(IllegalArgumentException.class, () -> new WiredGiveRewardItem("7,1,credits#25")); + assertThrows(IllegalArgumentException.class, () -> new WiredGiveRewardItem("abc,1,credits#25,40")); + assertThrows(IllegalArgumentException.class, () -> new WiredGiveRewardItem("7,1,credits#25,nope")); + } + + @Test + void clampsRewardProbability() { + assertEquals(100, new WiredGiveRewardItem(1, false, "credits#25", 200).probability); + assertEquals(0, new WiredGiveRewardItem(1, false, "credits#25", -20).probability); + assertEquals(100, new WiredGiveRewardItem("1,1,credits#25,200").probability); + } +}