Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import javafx.util.Callback;
import javafx.util.Duration;
import javafx.util.StringConverter;
import org.glavo.url.WebURL;
import org.jackhuang.hmcl.setting.StyleSheets;
import org.jackhuang.hmcl.task.CacheFileTask;
import org.jackhuang.hmcl.task.Schedulers;
Expand Down Expand Up @@ -1166,12 +1167,10 @@ public static Image loadImage(Path path,
}
}

public static Image loadImage(String url) throws Exception {
URI uri = NetworkUtils.toURI(url);

URLConnection connection = NetworkUtils.createConnection(uri);
if (connection instanceof HttpURLConnection)
connection = NetworkUtils.resolveConnection((HttpURLConnection) connection);
public static Image loadImage(WebURL url) throws Exception {
URLConnection connection = NetworkUtils.createConnection(url);
if (connection instanceof HttpURLConnection httpConnection)
connection = NetworkUtils.resolveConnection(httpConnection);

try (BufferedInputStream input = new BufferedInputStream(connection.getInputStream())) {
String contentType = Objects.requireNonNull(connection.getContentType(), "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import com.jfoenix.validation.base.ValidatorBase;
import javafx.beans.NamedArg;
import javafx.scene.control.TextInputControl;
import org.glavo.url.WebURL;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils;

import static org.jackhuang.hmcl.util.i18n.I18n.i18n;

Expand Down Expand Up @@ -54,12 +54,7 @@ private void evalTextInputField() {
if (StringUtils.isBlank(textField.getText()))
hasErrors.set(!nullable);
else {
try {
NetworkUtils.toURI(textField.getText());
hasErrors.set(false);
} catch (IllegalArgumentException e) {
hasErrors.set(true);
}
hasErrors.set(WebURL.tryParseBrowserInput(textField.getText()) == null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import javafx.scene.paint.Paint;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.glavo.url.WebURL;
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDnD;
import org.jackhuang.hmcl.setting.EnumBackgroundImage;
Expand Down Expand Up @@ -205,7 +206,7 @@ private Background getBackground() {
String backgroundImageUrl = config().getBackgroundImageUrl();
if (backgroundImageUrl != null) {
try {
image = FXUtils.loadImage(backgroundImageUrl);
image = FXUtils.loadImage(WebURL.parseBrowserInput(backgroundImageUrl));
} catch (Exception e) {
LOG.warning("Couldn't load background image", e);
}
Expand Down
5 changes: 5 additions & 0 deletions HMCL/src/main/resources/assets/about/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,10 @@
"title": "TomlJ",
"subtitle": "Licensed under the Apache 2.0 License.",
"externalLink": "https://github.com/tomlj/tomlj"
},
{
"title": "WebURL for Java",
"subtitle": "Licensed under the Apache 2.0 License.",
"externalLink": "https://github.com/Glavo/weburl-java"
}
]
1 change: 1 addition & 0 deletions HMCLCore/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
api(libs.jna)
api(libs.pci.ids)
api(libs.hello.nbt)
api(libs.weburl)

compileOnlyApi(libs.jetbrains.annotations)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

import org.glavo.url.WebURL;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
import org.jackhuang.hmcl.util.io.HttpRequest;
import org.jackhuang.hmcl.util.io.NetworkUtils;
Expand Down Expand Up @@ -58,13 +57,17 @@ public class AuthlibInjectorServer implements Observable {
public static AuthlibInjectorServer locateServer(String url) throws IOException {
try {
url = NetworkUtils.addHttpsIfMissing(url);
HttpURLConnection conn = NetworkUtils.createHttpConnection(url);

WebURL webURL = WebURL.parseBrowserInput(url);
url = webURL.toString();

HttpURLConnection conn = NetworkUtils.createHttpConnection(webURL);
conn = NetworkUtils.resolveConnection(conn);

String ali = conn.getHeaderField("x-authlib-injector-api-location");
if (ali != null) {
URI absoluteAli = conn.getURL().toURI().resolve(NetworkUtils.toURI(ali));
if (!urlEqualsIgnoreSlash(url, absoluteAli.toString())) {
WebURL absoluteAli = WebURL.parse(ali, WebURL.of(conn.getURL()));
if (!urlEqualsIgnoreSlash(webURL.toString(), absoluteAli.toString())) {
conn.disconnect();
url = absoluteAli.toString();
conn = NetworkUtils.resolveConnection(NetworkUtils.createHttpConnection(absoluteAli));
Expand All @@ -81,7 +84,7 @@ public static AuthlibInjectorServer locateServer(String url) throws IOException
} finally {
conn.disconnect();
}
} catch (IllegalArgumentException | URISyntaxException e) {
} catch (IllegalArgumentException e) {
throw new IOException(e);
}
}
Expand Down
37 changes: 13 additions & 24 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/util/io/NetworkUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,14 @@
*/
package org.jackhuang.hmcl.util.io;

import org.glavo.url.WebURL;
import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.net.*;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpResponse;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;
Expand Down Expand Up @@ -162,10 +160,10 @@ public static URI dropQuery(URI u) {
}
}

public static URLConnection createConnection(URI uri) throws IOException {
public static URLConnection createConnection(WebURL url) throws IOException {
URLConnection connection;
try {
connection = uri.toURL().openConnection();
connection = url.toURL().openConnection();
} catch (IllegalArgumentException | MalformedURLException e) {
throw new IOException(e);
}
Expand All @@ -179,8 +177,16 @@ public static URLConnection createConnection(URI uri) throws IOException {
return connection;
}

public static URLConnection createConnection(URI uri) throws IOException {
return createConnection(WebURL.of(uri));
}

public static HttpURLConnection createHttpConnection(WebURL url) throws IOException {
return (HttpURLConnection) createConnection(url);
}

public static HttpURLConnection createHttpConnection(String url) throws IOException {
return (HttpURLConnection) createConnection(toURI(url));
return (HttpURLConnection) createConnection(WebURL.parse(url));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

根据 PR 描述,WebURL 库支持宽松解析模式(parseBrowserInput),这更适合处理用户输入的 URL(例如自动补全协议)。为了与 AuthlibInjectorServerDecoratorController 中的改动保持一致,建议在这里也使用 WebURL.parseBrowserInput(url) 而不是严格的 WebURL.parse(url),以提高对各种输入格式的兼容性。

Suggested change
return (HttpURLConnection) createConnection(WebURL.parse(url));
return (HttpURLConnection) createConnection(WebURL.parseBrowserInput(url));

}

public static HttpURLConnection createHttpConnection(URI url) throws IOException {
Expand Down Expand Up @@ -436,24 +442,7 @@ public static String decodeURL(String toDecode) {

/// @throws IllegalArgumentException if the string is not a valid URI
public static @NotNull URI toURI(@NotNull String uri) {
try {
return new URI(encodeLocation(uri));
} catch (URISyntaxException e) {
// Possibly an Internationalized Domain Name (IDN)
return URI.create(uri);
}
}

public static @NotNull URI toURI(@NotNull URL url) {
return toURI(url.toExternalForm());
}

public static @NotNull HttpResponse.ResponseInfo getResponseInfo(@NotNull HttpResponse<?> response) {
record ResponseInfoImpl(int statusCode, HttpHeaders headers, HttpClient.Version version)
implements HttpResponse.ResponseInfo {
}

return new ResponseInfoImpl(response.statusCode(), response.headers(), response.version());
return WebURL.toURI(uri);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

同上,如果 toURI(String) 方法预期会处理可能不完整的用户输入字符串,建议使用宽松解析模式。这可以确保像 glavo.site 这样的输入能被正确启发式补全并转换为 URI,从而维持或提升原有代码的鲁棒性。

Suggested change
return WebURL.toURI(uri);
return WebURL.parseBrowserInput(uri).toURI();

}

public static @Nullable URI toURIOrNull(String uri) {
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ monet-fx = "0.4.0"
terracotta = "0.4.2"
nayuki-qrcodegen = "1.8.0"
jwebp = "0.2.0"
weburl = "0.2.0"

# testing
junit = "6.0.1"
Expand Down Expand Up @@ -58,6 +59,7 @@ lwjgl-unsafe-agent = { module = "org.glavo:lwjgl-unsafe-agent", version.ref = "l
monet-fx = { module = "org.glavo:MonetFX", version.ref = "monet-fx" }
nayuki-qrcodegen = { module = "io.nayuki:qrcodegen", version.ref = "nayuki-qrcodegen" }
jwebp = { module = "org.glavo:webp", version.ref = "jwebp" }
weburl = { module = "org.glavo:weburl", version.ref = "weburl" }

# testing
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
Expand Down