From d5c203d3c1bdb55ddc1f74996fdcd39eb9bf7aa9 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Tue, 4 Aug 2026 14:34:01 -0400 Subject: [PATCH 1/2] Validate automatic URLs --- .../bukkit/text/TextComponentParser.java | 25 +++++++++++++++++-- .../bukkit/text/TextComponentParserTest.java | 13 ++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/skriptlang/skript/bukkit/text/TextComponentParser.java b/src/main/java/org/skriptlang/skript/bukkit/text/TextComponentParser.java index 4fccca744a6..5b73b0bf549 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/text/TextComponentParser.java +++ b/src/main/java/org/skriptlang/skript/bukkit/text/TextComponentParser.java @@ -4,6 +4,7 @@ import ch.njol.skript.registrations.Classes; import ch.njol.util.coll.CollectionUtils; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; @@ -27,6 +28,8 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -82,7 +85,7 @@ public enum LinkParseMode { */ STRICT(TextReplacementConfig.builder() .match(Pattern.compile("https?://[-\\w.]+\\.\\w{2,}(?:/\\S*)?")) - .replacement(url -> url.clickEvent(ClickEvent.openUrl(url.content()))) + .replacement(LinkParseMode::parseUrl) .build()), /** @@ -90,9 +93,27 @@ public enum LinkParseMode { */ LENIENT(TextReplacementConfig.builder() .match(Pattern.compile("(?:https?://)?[-\\w.]+\\.\\w{2,}(?:/\\S*)?")) - .replacement(url -> url.clickEvent(ClickEvent.openUrl(url.content()))) + .replacement(LinkParseMode::parseUrl) .build()); + private static TextComponent.Builder parseUrl(TextComponent.Builder builder) { + String url = builder.content(); + URI uri; + try { + uri = new URI(url); + } catch (URISyntaxException e) { + if (e.getIndex() == -1) { // no recovery possible + return builder; + } + try { + uri = new URI(url.substring(0, e.getIndex())); + } catch (URISyntaxException ignored) { + return builder; + } + } + return builder.clickEvent(ClickEvent.openUrl(uri.toString())); + } + private final TextReplacementConfig textReplacementConfig; LinkParseMode(TextReplacementConfig textReplacementConfig) { diff --git a/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java b/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java index b123ec39399..903cd57833f 100644 --- a/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java +++ b/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java @@ -1,12 +1,15 @@ package org.skriptlang.skript.bukkit.text; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.ClickEvent.Payload; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.ChatColor; import org.junit.Test; +import org.skriptlang.skript.bukkit.text.TextComponentParser.LinkParseMode; import java.util.Set; @@ -88,4 +91,14 @@ public void testLegacyDoubleHashtag() { assertEquals(parser.parse("<#ffff11>hello"), parser.parse("<##FFFF11>hello")); } + @Test + public void testURLValidation() { + TextComponentParser parser = new TextComponentParser(); + parser.linkParseMode(LinkParseMode.STRICT); + // Example: forgot to allow all formatting, so tag is not parsed, but URL is attempted to be automatically formatted + ClickEvent result = parser.parseSafe("My Website").children().getFirst().clickEvent(); + assertNotNull(result); + assertEquals("https://skriptlang.org/'", ((Payload.Text) result.payload()).value()); + } + } From 4f321937af5588c51d8afdb08806ea3d9cd5312a Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Tue, 4 Aug 2026 14:50:03 -0400 Subject: [PATCH 2/2] Version check for payload call --- .../bukkit/text/TextComponentParserTest.java | 5 ++++- .../skript/environments/java21/paper-1.21.json | 17 ----------------- 2 files changed, 4 insertions(+), 18 deletions(-) delete mode 100644 src/test/skript/environments/java21/paper-1.21.json diff --git a/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java b/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java index 903cd57833f..269966c4a1a 100644 --- a/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java +++ b/src/test/java/org/skriptlang/skript/bukkit/text/TextComponentParserTest.java @@ -1,5 +1,6 @@ package org.skriptlang.skript.bukkit.text; +import ch.njol.skript.Skript; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent.Payload; @@ -98,7 +99,9 @@ public void testURLValidation() { // Example: forgot to allow all formatting, so tag is not parsed, but URL is attempted to be automatically formatted ClickEvent result = parser.parseSafe("My Website").children().getFirst().clickEvent(); assertNotNull(result); - assertEquals("https://skriptlang.org/'", ((Payload.Text) result.payload()).value()); + if (Skript.methodExists(ClickEvent.class, "payload")) { // TODO remove when supporting 1.21.6+ + assertEquals("https://skriptlang.org/'", ((Payload.Text) result.payload()).value()); + } } } diff --git a/src/test/skript/environments/java21/paper-1.21.json b/src/test/skript/environments/java21/paper-1.21.json deleted file mode 100644 index 65821b71ead..00000000000 --- a/src/test/skript/environments/java21/paper-1.21.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "paper-1.21", - "resources": [ - {"source": "server.properties.generic", "target": "server.properties"} - ], - "paperDownloads": [ - { - "version": "1.21", - "target": "paperclip.jar" - } - ], - "skriptTarget": "plugins/Skript.jar", - "commandLine": [ - "-Dcom.mojang.eula.agree=true", - "-jar", "paperclip.jar", "--nogui" - ] -}