From 9fca7430a86ab8f45e42d72f7da7386c7e926ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sun, 5 Oct 2025 13:24:47 +0200 Subject: [PATCH] implemented working fingerprinting prototype --- .../DeviceFingerprinting.java | 218 ++++++++++++++++++ .../PlayerJoinListener.java | 27 +++ .../resources/deviceFingerprinting/README.md | 5 + .../deviceFingerprinting/gen_packs.py | 33 +++ .../resources/deviceFingerprinting/packs.json | 122 ++++++++++ .../deviceFingerprinting/packs/.gitignore | 1 + .../resources/deviceFingerprinting/packs/0 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/1 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/10 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/11 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/12 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/13 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/14 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/15 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/16 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/17 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/18 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/19 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/2 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/20 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/21 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/22 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/23 | Bin 0 -> 201 bytes .../resources/deviceFingerprinting/packs/3 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/4 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/5 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/6 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/7 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/8 | Bin 0 -> 200 bytes .../resources/deviceFingerprinting/packs/9 | Bin 0 -> 200 bytes .../deviceFingerprinting/packs/base.zip | Bin 0 -> 37490 bytes .../spawn/core/api/server/HttpServer.java | 9 +- 32 files changed, 413 insertions(+), 2 deletions(-) create mode 100644 common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/DeviceFingerprinting.java create mode 100644 common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/PlayerJoinListener.java create mode 100644 common/src/main/resources/deviceFingerprinting/README.md create mode 100644 common/src/main/resources/deviceFingerprinting/gen_packs.py create mode 100644 common/src/main/resources/deviceFingerprinting/packs.json create mode 100644 common/src/main/resources/deviceFingerprinting/packs/.gitignore create mode 100644 common/src/main/resources/deviceFingerprinting/packs/0 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/1 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/10 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/11 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/12 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/13 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/14 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/15 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/16 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/17 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/18 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/19 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/2 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/20 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/21 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/22 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/23 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/3 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/4 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/5 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/6 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/7 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/8 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/9 create mode 100644 common/src/main/resources/deviceFingerprinting/packs/base.zip diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/DeviceFingerprinting.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/DeviceFingerprinting.java new file mode 100644 index 0000000..73d1fde --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/DeviceFingerprinting.java @@ -0,0 +1,218 @@ +package eu.mhsl.craftattack.spawn.common.appliances.tooling.deviceFingerprinting; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import eu.mhsl.craftattack.spawn.core.Main; +import eu.mhsl.craftattack.spawn.core.api.server.HttpServer; +import eu.mhsl.craftattack.spawn.core.appliance.Appliance; +import net.kyori.adventure.resource.ResourcePackInfo; +import net.kyori.adventure.resource.ResourcePackRequest; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerResourcePackStatusEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import spark.Response; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.net.URI; +import java.util.*; + +public class DeviceFingerprinting extends Appliance { + public record PackInfo(String url, UUID uuid, String hash) { + private static final String failingUrl = "http://127.0.0.1:0"; + public PackInfo asFailing() { + return new PackInfo(failingUrl, this.uuid, this.hash); + } + } + + public enum PackStatus { + ERROR, + SUCCESS; + + public static PackStatus fromBukkitStatus(PlayerResourcePackStatusEvent.Status status) { + return switch(status) { + case DISCARDED -> SUCCESS; + case FAILED_DOWNLOAD -> ERROR; + default -> throw new IllegalStateException("Unexpected value: " + status); + }; + } + } + + public enum PlayerStatus { + PREPARATION, + TESTING, + FINISHED; + } + + public record FingerprintData( + Player player, + PlayerStatus status, + @Nullable Long fingerPrint, + @Nullable List pendingPacks + ) { + public FingerprintData(Player player) { + this(player, PlayerStatus.PREPARATION, null, null); + } + } + + private List packs; + private final Map> pendingPacks = new WeakHashMap<>(); + + @Override + public void onEnable() { + this.packs = this.readPacksFromConfig(); + + } + + public void testAllPacks(Player player) { + this.pendingPacks.put(player, Arrays.asList(new PackStatus[this.packs.size()])); + System.out.println("Sending packs..."); + this.packs.forEach(pack -> this.sendPack(player, pack.asFailing())); + } + + public void onPackReceive(Player player, UUID packId, PlayerResourcePackStatusEvent.Status status) { + if(!this.pendingPacks.containsKey(player)) return; + + PackInfo pack = this.packs.stream() + .filter(packInfo -> packInfo.uuid.equals(packId)) + .findFirst() + .orElse(null); + if(pack == null) return; + int packIndex = this.packs.indexOf(pack); + + List currentPendingStatus = this.pendingPacks.get(player); + try { + currentPendingStatus.set(packIndex, PackStatus.fromBukkitStatus(status)); + System.out.println(packIndex + " > " + PackStatus.fromBukkitStatus(status)); + } catch(IllegalStateException ignored) { + return; + } + + long fingerPrint = this.calculateFingerprintId(currentPendingStatus); + if(fingerPrint == -1) return; + + if(fingerPrint == 0) { + // new Player + long newFingerprintId = this.generateNewFingerprintId(); + System.out.println("New Fingerprint: " + newFingerprintId); + this.sendMarkedPacks(player, newFingerprintId); + } else { + System.out.println("Fingerprint: " + fingerPrint); + } + + this.pendingPacks.remove(player); + } + + private long calculateFingerprintId(List packStatus) { + long fingerprintId = 0; + for (int i = 0; i < packStatus.size(); i++) { + var status = packStatus.get(i); + if(status == null) return -1; + switch (status) { + case SUCCESS: + fingerprintId |= 1L << i; + break; + case ERROR: + break; + default: + return -1; + } + } + return fingerprintId; + } + + private long generateNewFingerprintId() { + long id = 0; + Random random = new Random(); + for (int i = 0; i < this.packs.size() / 2; i++) { + while (true) { + int bitIndex = random.nextInt(this.packs.size()); + if ((id & (1L << bitIndex)) == 0) { + id |= 1L << bitIndex; + break; + } + } + } + return id; + } + + private void sendMarkedPacks(Player player, long fingerprintId) { + for (int i = 0; i < this.packs.size(); i++) { + if ((fingerprintId & (1L << i)) != 0) { + PackInfo pack = this.packs.get(i); + this.sendPack(player, pack); + } + } + } + + public void sendPack(Player player, PackInfo pack) { + System.out.println("Sending pack: " + pack.url); + player.sendResourcePacks( + ResourcePackRequest.resourcePackRequest() + .required(true) + .packs(ResourcePackInfo.resourcePackInfo(pack.uuid, URI.create(pack.url), pack.hash)) + ); + } + + private List readPacksFromConfig() { + try (InputStreamReader reader = new InputStreamReader(Objects.requireNonNull(Main.class.getResourceAsStream("/deviceFingerprinting/packs.json")))) { + Type packListType = new TypeToken>(){}.getType(); + List packs = new Gson().fromJson(reader, packListType); + + if (packs.isEmpty()) + throw new IllegalStateException("No resource packs found in packs.json."); + + return packs; + } catch (Exception e) { + throw new IllegalStateException("Failed to parse packs.json.", e); + } + } + + @Override + public void httpApi(HttpServer.ApiBuilder apiBuilder) { + apiBuilder.rawGet( + "base.zip", + (request, response) -> this.servePack("base.zip", response) + ); + + for(int i = 0; i < this.packs.size(); i++) { + int packIndex = i; + apiBuilder.rawGet( + String.format("packs/%d", i), + (request, response) -> this.servePack(String.valueOf(packIndex), response) + ); + } + } + + private Object servePack(String name, Response response) { + try { + String resourcePath = String.format("/deviceFingerprinting/packs/%s", name); + var inputStream = Main.class.getResourceAsStream(resourcePath); + + if (inputStream == null) { + throw new IllegalStateException("Pack file not found: " + resourcePath); + } + + response.header("Content-Type", "application/zip"); + response.header("Content-Disposition", String.format("attachment; filename=\"pack-%s.zip\"", name)); + + var outputStream = response.raw().getOutputStream(); + inputStream.transferTo(outputStream); + outputStream.close(); + + return HttpServer.nothing; + } catch (IOException e) { + throw new RuntimeException(String.format("Failed to serve pack '%s'", name), e); + } + } + + @Override + protected @NotNull List listeners() { + return List.of( + new PlayerJoinListener() + ); + } +} diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/PlayerJoinListener.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/PlayerJoinListener.java new file mode 100644 index 0000000..2d92e04 --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/deviceFingerprinting/PlayerJoinListener.java @@ -0,0 +1,27 @@ +package eu.mhsl.craftattack.spawn.common.appliances.tooling.deviceFingerprinting; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerResourcePackStatusEvent; + +class PlayerJoinListener extends ApplianceListener { + @EventHandler + public void onJoin(PlayerJoinEvent event) { +// if(Bukkit.getServer().getServerResourcePack() != null && !event.getPlayer().hasResourcePack()) { +// System.out.println("NO RESSOURCEPACK"); +// return; +// } + + this.getAppliance().testAllPacks(event.getPlayer()); + } + + @EventHandler + public void onResourcePackEvent(PlayerResourcePackStatusEvent event) { + this.getAppliance().onPackReceive( + event.getPlayer(), + event.getID(), + event.getStatus() + ); + } +} diff --git a/common/src/main/resources/deviceFingerprinting/README.md b/common/src/main/resources/deviceFingerprinting/README.md new file mode 100644 index 0000000..b40a304 --- /dev/null +++ b/common/src/main/resources/deviceFingerprinting/README.md @@ -0,0 +1,5 @@ +## Files originally from "TrackPack" +https://github.com/ALaggyDev/TrackPack/blob/main/README.md + + +Discovered by: [Laggy](https://github.com/ALaggyDev/) and [NikOverflow](https://github.com/NikOverflow) \ No newline at end of file diff --git a/common/src/main/resources/deviceFingerprinting/gen_packs.py b/common/src/main/resources/deviceFingerprinting/gen_packs.py new file mode 100644 index 0000000..2e7b1df --- /dev/null +++ b/common/src/main/resources/deviceFingerprinting/gen_packs.py @@ -0,0 +1,33 @@ +import zipfile +import hashlib +import uuid +import json + +SERVER_URL = "http://localhost:8080/api/devicefingerprinting" +packs = [] + +def file_sha1(path): + h = hashlib.sha1() + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(8192), b""): + h.update(chunk) + return h.hexdigest() + +for i in range(0, 24): + path = f"packs/{i}" + + with zipfile.ZipFile(path, mode="w") as zf: + zf.writestr( + "pack.mcmeta", + '{"pack":{"pack_format":22,"supported_formats":[22,1000],"description":"pack ' + str(i) + '"}}', + ) + + hash = file_sha1(path) + packs.append({ + "url": f"{SERVER_URL}/packs/{i}", + "uuid": str(uuid.uuid4()), + "hash": hash + }) + +with open("packs.json", "w") as f: + json.dump(packs, f, indent=4) diff --git a/common/src/main/resources/deviceFingerprinting/packs.json b/common/src/main/resources/deviceFingerprinting/packs.json new file mode 100644 index 0000000..59cbad1 --- /dev/null +++ b/common/src/main/resources/deviceFingerprinting/packs.json @@ -0,0 +1,122 @@ +[ + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/0", + "uuid": "b35f6e2f-1b50-4493-85be-fb18bd90f9bb", + "hash": "7a39af839ea6484431f7b707759546bea991d435" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/1", + "uuid": "71095b62-d5ef-4ab2-ba3b-3c1b403f5e34", + "hash": "a9192ee73df1c5cff2c188fac6e9e638a1e7b6ce" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/2", + "uuid": "a4dba0a2-f8f2-4a81-bbb2-a9a818820330", + "hash": "6b85b0eb54865dae70bbda89746d83717dc2a214" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/3", + "uuid": "79fa2dc4-8c84-45fc-a09f-d89906f0d900", + "hash": "c7abf7a316f7e8c98985e8317a8b649e824e9f79" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/4", + "uuid": "15702c9b-a22b-426d-b48a-3d65b0368e9a", + "hash": "10cd0e2c46f192deb87ac75c149827d44a713017" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/5", + "uuid": "3d702d41-8e2f-4920-8dd0-1fd2146da9fb", + "hash": "8ad517d259e800b88a38ff00ee6721d5656822f2" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/6", + "uuid": "c20a2e47-ef43-49da-a80d-adf238df3695", + "hash": "798677405a4fd678892e1cf55585c8c91f82e1e2" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/7", + "uuid": "7ce51b81-1263-4919-9f4e-bb749ffe6e2e", + "hash": "af473b8eb7572f35d307bede5f2e20f263c0d804" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/8", + "uuid": "0c70d586-fe48-4ffc-86b0-6b9ec3bfe045", + "hash": "2fb698ff88f2436637641f3b2e6792201feb5144" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/9", + "uuid": "c7af75a8-0b72-495d-a0ff-c1c40e229c13", + "hash": "cf660460798eecf451d639873cc1fedc4661db1b" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/10", + "uuid": "248dbce6-4b2a-44b5-b038-8d718b0ced99", + "hash": "a8ebe708d0f3747c76e4e5e68db5dcb561922706" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/11", + "uuid": "10979174-cb02-40eb-a754-275551ad608d", + "hash": "54961b48db1582a1a0981c8cc9be5ae0f3122cf3" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/12", + "uuid": "a361cfa7-674c-4493-a4cf-4baff851f276", + "hash": "013719dc8da79c96b45a1c5319c20bffe1a56cc9" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/13", + "uuid": "24b39bdb-ada9-40ec-9e3a-132c74b81dc6", + "hash": "206898c6b6600d2648b2d79c61fc6255b19587d9" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/14", + "uuid": "158fc5b4-be2c-4f7a-98cb-af5993adcc90", + "hash": "061b266a7c526fb3a3152a4ea70ca5592e0b503c" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/15", + "uuid": "4f9097a7-be02-48ad-919c-f292307f8490", + "hash": "45a667a0fe06246defabca14ef1271fb6db5a1ac" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/16", + "uuid": "3ce31e60-7e8a-4fb1-8c6d-da9065bea798", + "hash": "75bb12e46203d49e89aa9a826d267552372758bc" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/17", + "uuid": "cd978e5c-3de0-4ada-8ec5-3a88a305eec6", + "hash": "5b20261f7be03e83e9c52307f1408b0c5e58358c" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/18", + "uuid": "75001e58-3999-4779-a1d1-43ab161770ce", + "hash": "544420cffb6c17113c06fb49eeba892c208719d3" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/19", + "uuid": "6a7005a9-c2ca-476d-9a12-07d120ee121a", + "hash": "fcc066a4d3193b60b102e3d906ad8dc0b0fcf65b" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/20", + "uuid": "521c0d84-d82e-49ef-b096-d9b90f15aa19", + "hash": "4545835983ec7f07d02675a69181a80dc396f038" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/21", + "uuid": "c1b590c5-43fc-41e3-83c0-47f35b14f845", + "hash": "8d4c670eaefc0482734e839b72758226dde13bc3" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/22", + "uuid": "43958a18-c087-4f2b-a6ea-066231606eb1", + "hash": "004282602f7bdbb7cd7724f23aae23876f224092" + }, + { + "url": "http://localhost:8080/api/devicefingerprinting/packs/23", + "uuid": "4b91ac81-9de4-4c2b-a876-47e621496d10", + "hash": "dae68eae109e08ea4c4c943905502eb331939f64" + } +] \ No newline at end of file diff --git a/common/src/main/resources/deviceFingerprinting/packs/.gitignore b/common/src/main/resources/deviceFingerprinting/packs/.gitignore new file mode 100644 index 0000000..073c2a0 --- /dev/null +++ b/common/src/main/resources/deviceFingerprinting/packs/.gitignore @@ -0,0 +1 @@ +!base.zip \ No newline at end of file diff --git a/common/src/main/resources/deviceFingerprinting/packs/0 b/common/src/main/resources/deviceFingerprinting/packs/0 new file mode 100644 index 0000000000000000000000000000000000000000..9ed350355ee1c79a0bbb36b7efe24e1a47efd027 GIT binary patch literal 200 zcmWIWW@Zs#00GTp*XUK!dzJ?P*&xgf#081T*?PIjxv3?I)k+|ak`;uGPs=aLO)OEe zGBVOpDlRQ3$S*2MO@WFQD_KPY#SIM%3}SVZQc{bPi!uvJGV}A4tiXmS7%0`&26!_v hi7?}~8fZHhG%$iFB!>iev$BDN7=h3dNLPY53;?EBF3bP` literal 0 HcmV?d00001 diff --git a/common/src/main/resources/deviceFingerprinting/packs/1 b/common/src/main/resources/deviceFingerprinting/packs/1 new file mode 100644 index 0000000000000000000000000000000000000000..5303a21b7ccefb96225f2518393c6ac7ec3a8421 GIT binary patch literal 200 zcmWIWW@Zs#00GTp*XZ*#4Dta$HVAVAaY15owq9;>ZfZ$lwGxP7N>p|g6p~8@EcY*&xgf#081T*?PIjxv3?I)k+|ak`;uGPs=aLO)OEe zGBVOpDlRQ3$S*2MO@WFQD_KPY#SIM%3}SVZQc{bPi!uvJGV}A4tiXmS7#b?o)&_Vp iGKnzbwi{?Y7&I_~C?uBzc(byBgcyO)5=d8pI1B(9moJ3? literal 0 HcmV?d00001 diff --git a/common/src/main/resources/deviceFingerprinting/packs/12 b/common/src/main/resources/deviceFingerprinting/packs/12 new file mode 100644 index 0000000000000000000000000000000000000000..4104d6d2fed0a4e796374530f7f6874f386863ba GIT binary patch literal 201 zcmWIWW@Zs#00GTp*Jx+v?gN29HVAVAaY15owq9;>ZfZ$lwGxP7N>6)&_Vp iGKnzbwi{?Y7&I_~C?uBzc(byBgcyO)5=d8pI1B)8EHE|z literal 0 HcmV?d00001 diff --git a/common/src/main/resources/deviceFingerprinting/packs/15 b/common/src/main/resources/deviceFingerprinting/packs/15 new file mode 100644 index 0000000000000000000000000000000000000000..cac2af0b1013823143b35d013976897f2b9df822 GIT binary patch literal 201 zcmWIWW@Zs#00GTp*XUo?F|mO_HVAVAaY15owq9;>ZfZ$lwGxP7N> literal 0 HcmV?d00001 diff --git a/common/src/main/resources/deviceFingerprinting/packs/16 b/common/src/main/resources/deviceFingerprinting/packs/16 new file mode 100644 index 0000000000000000000000000000000000000000..5aaf529a1d67fc66448bd268b659d7ee0e635d36 GIT binary patch literal 201 zcmWIWW@Zs#00GTp*JzO`FZ~07Y!K!K;)2BFY`xs%+|-i9Y9$ay$qGWpr{x#rCYC5! z85!v)6_*wip|g6p~8p|g6p~8p|g6p~8ZfZ$lwGxP7N>ZfZ$lwGxP7N>p|g6p~8iev$BDN7=h3dNLPY53;^>kFKYk* literal 0 HcmV?d00001 diff --git a/common/src/main/resources/deviceFingerprinting/packs/6 b/common/src/main/resources/deviceFingerprinting/packs/6 new file mode 100644 index 0000000000000000000000000000000000000000..8bc5b39212686ccd24cb7df9a01ed108d902df6d GIT binary patch literal 200 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 onCall) { + Spark.get(this.buildRoute(path), (req, resp) -> this.process(() -> onCall.apply(req, resp))); + } + public void get(String path, Function onCall) { Spark.get(this.buildRoute(path), (req, resp) -> this.process(() -> onCall.apply(req))); } - public void rawPost(String path, Function onCall) { - Spark.post(this.buildRoute(path), (req, resp) -> this.process(() -> onCall.apply(req))); + public void rawPost(String path, BiFunction onCall) { + Spark.post(this.buildRoute(path), (req, resp) -> this.process(() -> onCall.apply(req, resp))); } public void post(String path, Class clazz, RequestProvider onCall) {