You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
Merge pull request #230 from simoleo89/fix/catalog-inputs
fix(catalog): bound marketplace inputs
This commit is contained in:
@@ -58,6 +58,10 @@ public class MarketPlace {
|
|||||||
public static void takeBackItem(Habbo habbo, int offerId) {
|
public static void takeBackItem(Habbo habbo, int offerId) {
|
||||||
MarketPlaceOffer offer = habbo.getInventory().getOffer(offerId);
|
MarketPlaceOffer offer = habbo.getInventory().getOffer(offerId);
|
||||||
|
|
||||||
|
if (offer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Emulator.getPluginManager().fireEvent(new MarketPlaceItemCancelledEvent(offer)).isCancelled()) {
|
if (!Emulator.getPluginManager().fireEvent(new MarketPlaceItemCancelledEvent(offer)).isCancelled()) {
|
||||||
takeBackItem(habbo, offer);
|
takeBackItem(habbo, offer);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -13,6 +13,10 @@ public class BuyItemEvent extends MessageHandler {
|
|||||||
public void handle() throws Exception {
|
public void handle() throws Exception {
|
||||||
int offerId = this.packet.readInt();
|
int offerId = this.packet.readInt();
|
||||||
|
|
||||||
|
if (!MarketplaceInputGuard.isPositiveId(offerId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MarketPlace.buyItem(offerId, this.client);
|
MarketPlace.buyItem(offerId, this.client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.catalog.marketplace;
|
||||||
|
|
||||||
|
import com.eu.habbo.habbohotel.catalog.marketplace.MarketPlace;
|
||||||
|
|
||||||
|
final class MarketplaceInputGuard {
|
||||||
|
static final int MAX_SEARCH_LENGTH = 30;
|
||||||
|
static final int DEFAULT_SORT = 1;
|
||||||
|
static final int MIN_SORT = 1;
|
||||||
|
static final int MAX_SORT = 6;
|
||||||
|
|
||||||
|
private MarketplaceInputGuard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isPositiveId(int id) {
|
||||||
|
return id > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String normalizeSearch(String query) {
|
||||||
|
if (query == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalized = query.trim();
|
||||||
|
return normalized.length() > MAX_SEARCH_LENGTH ? normalized.substring(0, MAX_SEARCH_LENGTH) : normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int normalizeSort(int sort) {
|
||||||
|
return sort >= MIN_SORT && sort <= MAX_SORT ? sort : DEFAULT_SORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int normalizeMinPrice(int minPrice) {
|
||||||
|
if (minPrice == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(0, Math.min(minPrice, MarketPlace.MAXIMUM_LISTING_PRICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int normalizeMaxPrice(int maxPrice, int minPrice) {
|
||||||
|
if (maxPrice == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int normalized = Math.max(0, Math.min(maxPrice, MarketPlace.MAXIMUM_LISTING_PRICE));
|
||||||
|
return minPrice > 0 && normalized > 0 && normalized < minPrice ? minPrice : normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -9,6 +9,10 @@ public class RequestItemInfoEvent extends MessageHandler {
|
|||||||
this.packet.readInt();
|
this.packet.readInt();
|
||||||
int id = this.packet.readInt();
|
int id = this.packet.readInt();
|
||||||
|
|
||||||
|
if (!MarketplaceInputGuard.isPositiveId(id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.client.sendResponse(new MarketplaceItemInfoComposer(id));
|
this.client.sendResponse(new MarketplaceItemInfoComposer(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-8
@@ -20,14 +20,10 @@ public class RequestOffersEvent extends MessageHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle() throws Exception {
|
public void handle() throws Exception {
|
||||||
int min = this.packet.readInt();
|
int min = MarketplaceInputGuard.normalizeMinPrice(this.packet.readInt());
|
||||||
int max = this.packet.readInt();
|
int max = MarketplaceInputGuard.normalizeMaxPrice(this.packet.readInt(), min);
|
||||||
String query = this.packet.readString();
|
String query = MarketplaceInputGuard.normalizeSearch(this.packet.readString());
|
||||||
int type = this.packet.readInt();
|
int type = MarketplaceInputGuard.normalizeSort(this.packet.readInt());
|
||||||
|
|
||||||
if (query.length() > 30) {
|
|
||||||
query = query.substring(0, 30);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
boolean tryCache = min == -1 && max == -1 && query.isEmpty();
|
boolean tryCache = min == -1 && max == -1 && query.isEmpty();
|
||||||
|
|||||||
+1
@@ -29,6 +29,7 @@ public class SellItemEvent extends MessageHandler {
|
|||||||
final int furniType = this.packet.readInt(); // 1 = FLOOR_TYPE, 2 = WALL_TYPE
|
final int furniType = this.packet.readInt(); // 1 = FLOOR_TYPE, 2 = WALL_TYPE
|
||||||
final int itemId = this.packet.readInt();
|
final int itemId = this.packet.readInt();
|
||||||
|
|
||||||
|
if (!MarketplaceInputGuard.isPositiveId(itemId)) return;
|
||||||
if (furniType != 1 && furniType != 2) return;
|
if (furniType != 1 && furniType != 2) return;
|
||||||
|
|
||||||
HabboItem item = this.client.getHabbo().getInventory().getItemsComponent().getHabboItem(itemId);
|
HabboItem item = this.client.getHabbo().getInventory().getItemsComponent().getHabboItem(itemId);
|
||||||
|
|||||||
+5
@@ -12,6 +12,11 @@ public class TakeBackItemEvent extends MessageHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void handle() throws Exception {
|
public void handle() throws Exception {
|
||||||
int offerId = this.packet.readInt();
|
int offerId = this.packet.readInt();
|
||||||
|
|
||||||
|
if (!MarketplaceInputGuard.isPositiveId(offerId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MarketPlace.takeBackItem(this.client.getHabbo(), offerId);
|
MarketPlace.takeBackItem(this.client.getHabbo(), offerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.catalog.marketplace;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class MarketplaceInputContractTest {
|
||||||
|
@Test
|
||||||
|
void marketplaceIdHandlersRejectNonPositiveIds() throws Exception {
|
||||||
|
Path base = Path.of("src/main/java/com/eu/habbo/messages/incoming/catalog/marketplace");
|
||||||
|
|
||||||
|
for (String handler : List.of(
|
||||||
|
"BuyItemEvent.java",
|
||||||
|
"RequestItemInfoEvent.java",
|
||||||
|
"SellItemEvent.java",
|
||||||
|
"TakeBackItemEvent.java"
|
||||||
|
)) {
|
||||||
|
String source = Files.readString(base.resolve(handler));
|
||||||
|
|
||||||
|
assertTrue(source.contains("MarketplaceInputGuard.isPositiveId"),
|
||||||
|
handler + " must reject zero or negative ids before marketplace or inventory lookup");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void offerSearchNormalizesCacheKeyInputs() throws Exception {
|
||||||
|
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/messages/incoming/catalog/marketplace/RequestOffersEvent.java"));
|
||||||
|
|
||||||
|
assertTrue(source.contains("MarketplaceInputGuard.normalizeMinPrice"),
|
||||||
|
"marketplace offer search must normalize minimum price");
|
||||||
|
assertTrue(source.contains("MarketplaceInputGuard.normalizeMaxPrice"),
|
||||||
|
"marketplace offer search must normalize maximum price");
|
||||||
|
assertTrue(source.contains("MarketplaceInputGuard.normalizeSearch"),
|
||||||
|
"marketplace offer search must trim and bound search text");
|
||||||
|
assertTrue(source.contains("MarketplaceInputGuard.normalizeSort"),
|
||||||
|
"marketplace offer search must normalize sort before using it as a cache key");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void takeBackDoesNotFirePluginEventForMissingOffer() throws Exception {
|
||||||
|
String source = Files.readString(Path.of("src/main/java/com/eu/habbo/habbohotel/catalog/marketplace/MarketPlace.java"));
|
||||||
|
|
||||||
|
assertTrue(source.contains("if (offer == null)"),
|
||||||
|
"takeBackItem must ignore missing offers before constructing plugin events");
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package com.eu.habbo.messages.incoming.catalog.marketplace;
|
||||||
|
|
||||||
|
import com.eu.habbo.habbohotel.catalog.marketplace.MarketPlace;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class MarketplaceInputGuardTest {
|
||||||
|
@Test
|
||||||
|
void idsMustBePositive() {
|
||||||
|
assertFalse(MarketplaceInputGuard.isPositiveId(0));
|
||||||
|
assertFalse(MarketplaceInputGuard.isPositiveId(-1));
|
||||||
|
assertTrue(MarketplaceInputGuard.isPositiveId(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void searchIsTrimmedAndBounded() {
|
||||||
|
assertEquals("", MarketplaceInputGuard.normalizeSearch(null));
|
||||||
|
assertEquals("rare", MarketplaceInputGuard.normalizeSearch(" rare "));
|
||||||
|
assertEquals(MarketplaceInputGuard.MAX_SEARCH_LENGTH, MarketplaceInputGuard.normalizeSearch("a".repeat(80)).length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sortFallsBackToDefaultOutsideKnownRange() {
|
||||||
|
assertEquals(MarketplaceInputGuard.DEFAULT_SORT, MarketplaceInputGuard.normalizeSort(0));
|
||||||
|
assertEquals(3, MarketplaceInputGuard.normalizeSort(3));
|
||||||
|
assertEquals(MarketplaceInputGuard.DEFAULT_SORT, MarketplaceInputGuard.normalizeSort(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void priceRangesPreserveCacheSentinelAndStayBounded() {
|
||||||
|
assertEquals(-1, MarketplaceInputGuard.normalizeMinPrice(-1));
|
||||||
|
assertEquals(0, MarketplaceInputGuard.normalizeMinPrice(-100));
|
||||||
|
assertEquals(MarketPlace.MAXIMUM_LISTING_PRICE, MarketplaceInputGuard.normalizeMinPrice(Integer.MAX_VALUE));
|
||||||
|
|
||||||
|
assertEquals(-1, MarketplaceInputGuard.normalizeMaxPrice(-1, -1));
|
||||||
|
assertEquals(500, MarketplaceInputGuard.normalizeMaxPrice(100, 500));
|
||||||
|
assertEquals(MarketPlace.MAXIMUM_LISTING_PRICE, MarketplaceInputGuard.normalizeMaxPrice(Integer.MAX_VALUE, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user