From 50b71e84feba70c8fe1f81acfb4cc75e2f5a01a3 Mon Sep 17 00:00:00 2001 From: Xavier LEGER Date: Thu, 19 Jun 2025 19:14:48 +0200 Subject: [PATCH 1/6] Integration of Proxy Vole --- .../bekoenig/getdown/data/SysProps.java | 10 +++ .../bekoenig/getdown/data/SysPropsTest.java | 50 ++++++++++++ launcher/pom.xml | 5 ++ .../bekoenig/getdown/launcher/ProxyUtil.java | 79 ++++++++++++++++--- 4 files changed, 132 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java b/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java index 5478fde1..6a299e29 100644 --- a/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java +++ b/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java @@ -142,6 +142,14 @@ public static boolean useProxy() { return !"false".equals(System.getProperty("use_proxy")); } + /** + * If false, Getdown will detect proxy through Proxy Vole. Default is false (legacy proxy search). + * Usage: {@code -Duse_proxy=false}. + */ + public static boolean useProxyVole() { + return "proxy_vole".equals(System.getProperty("use_proxy")); + } + /** * If true, Getdown will always try to connect without proxy settings even it a proxy is set * in {@code proxy.txt}. If direct access is possible it will not clear {@code proxy.txt}, it @@ -248,4 +256,6 @@ public static String replaceDomain(String appbase) { } return appbase; } + + } diff --git a/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java b/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java index 2b135f44..87021ecd 100644 --- a/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java +++ b/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java @@ -142,4 +142,54 @@ void test_useProxy_false() { assertThat(useProxy).isFalse(); } + + @Test + @SetSystemProperty(key = "use_proxy", value = "proxy_vole") + void test_useProxy_proxyvole() { + // GIVEN + + // WHEN + boolean useProxy = SysProps.useProxy(); + + // THEN + assertThat(useProxy).isTrue(); + } + + + @Test + @SetSystemProperty(key = "use_proxy", value = "proxy_vole") + void test_useProxyVole_proxyvole() { + // GIVEN + + // WHEN + boolean useProxyVole = SysProps.useProxyVole(); + + // THEN + assertThat(useProxyVole).isTrue(); + } + + @Test + @SetSystemProperty(key = "use_proxy", value = "true") + void test_useProxyVole_true() { + // GIVEN + + // WHEN + boolean useProxyVole = SysProps.useProxyVole(); + + // THEN + assertThat(useProxyVole).isFalse(); + } + + @Test + @SetSystemProperty(key = "use_proxy", value = "false") + void test_useProxyVole_false() { + // GIVEN + + // WHEN + boolean useProxyVole = SysProps.useProxyVole(); + + // THEN + assertThat(useProxyVole).isFalse(); + } + } diff --git a/launcher/pom.xml b/launcher/pom.xml index 76ff15b2..1fdab865 100644 --- a/launcher/pom.xml +++ b/launcher/pom.xml @@ -69,6 +69,11 @@ 22.0.0 test + + org.bidib.com.github.markusbernhardt + proxy-vole + 1.1.6 + diff --git a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java index 81a046a1..bce9801f 100644 --- a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java +++ b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java @@ -9,6 +9,7 @@ import ca.beq.util.win32.registry.RegistryValue; import ca.beq.util.win32.registry.RootKey; import io.github.bekoenig.getdown.data.Application; +import io.github.bekoenig.getdown.data.SysProps; import io.github.bekoenig.getdown.net.Connector; import io.github.bekoenig.getdown.spi.ProxyAuth; import io.github.bekoenig.getdown.util.Config; @@ -16,12 +17,14 @@ import io.github.bekoenig.getdown.util.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.github.markusbernhardt.proxy.ProxySearch; import javax.script.*; import java.io.*; import java.net.*; import java.nio.file.Files; import java.util.Iterator; +import java.util.List; import java.util.ServiceLoader; public final class ProxyUtil { @@ -40,31 +43,38 @@ public static boolean autoDetectProxy(Application app) { port = System.getProperty("http.proxyPort"); } - // check the Windows registry - if (StringUtil.isBlank(host) && LaunchUtil.isWindows()) { + //check using Proxy Vole else check the Windows registry + if (StringUtil.isBlank(host) && SysProps.useProxyVole()) { + Proxy neededProxy = getProxyForInternetAccess(app.getConfigResource().getRemote()); + + if (neededProxy != null) + host= ((InetSocketAddress) neededProxy.address()).getHostString(); + assert neededProxy != null; + port= String.valueOf(((InetSocketAddress) neededProxy.address()).getPort()); + } else if (LaunchUtil.isWindows()) { try { String rhost = null, rport = null; boolean enabled = false; RegistryKey.initialize(); RegistryKey r = new RegistryKey(RootKey.HKEY_CURRENT_USER, PROXY_REGISTRY); - for (Iterator iter = r.values(); iter.hasNext(); ) { + for(Iterator iter = r.values(); iter.hasNext(); ) { RegistryValue value = (RegistryValue) iter.next(); - if ("ProxyEnable".equals(value.getName())) { + if("ProxyEnable".equals(value.getName())) { enabled = "1".equals(value.getStringValue()); } - if (value.getName().equals("ProxyServer")) { + if(value.getName().equals("ProxyServer")) { String[] hostPort = splitHostPort(value.getStringValue()); rhost = hostPort[0]; rport = hostPort[1]; } - if (value.getName().equals("AutoConfigURL")) { + if(value.getName().equals("AutoConfigURL")) { String acurl = value.getStringValue(); Reader acjs = new InputStreamReader(new URL(acurl).openStream()); // technically we should be returning all this info and trying each proxy // in succession, but that's complexity we'll leave for another day URL configURL = app.getConfigResource().getRemote(); - for (String proxy : findPACProxiesForURL(acjs, configURL)) { - if (proxy.startsWith("PROXY ")) { + for(String proxy : findPACProxiesForURL(acjs, configURL)) { + if(proxy.startsWith("PROXY ")) { String[] hostPort = splitHostPort(proxy.substring(6)); rhost = hostPort[0]; rport = hostPort[1]; @@ -76,7 +86,7 @@ public static boolean autoDetectProxy(Application app) { } } - if (enabled) { + if(enabled) { host = rhost; port = rport; } else { @@ -85,9 +95,9 @@ public static boolean autoDetectProxy(Application app) { } catch (Throwable t) { LOGGER.atInfo() - .setMessage("Failed to find proxy settings in Windows registry") - .addKeyValue("error", t) - .log(); + .setMessage("Failed to find proxy settings in Windows registry") + .addKeyValue("error", t) + .log(); } } @@ -284,4 +294,49 @@ private static String[] splitHostPort(String hostPort) { private static final String PROXY_REGISTRY = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; + + public static Proxy getProxyForInternetAccess(URL rurl) { + // Use the static factory method getDefaultProxySearch to create a proxy search instance + // configured with the default proxy search strategies for the current environment. + ProxySearch proxySearch = ProxySearch.getDefaultProxySearch(); + + // Invoke the proxy search. This will create a ProxySelector with the detected proxy settings. + ProxySelector proxySelector = proxySearch.getProxySelector(); + + // Install this ProxySelector as default ProxySelector for all connections. + ProxySelector.setDefault(proxySelector); + + // Get list of proxies from default ProxySelector available for given URL + List proxies = null; + if (ProxySelector.getDefault() != null) { + try { + proxies = ProxySelector.getDefault().select(rurl.toURI()); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + + Proxy proxy = Proxy.NO_PROXY; + // Find first proxy for HTTP/S. Any DIRECT proxy in the list returned is only second choice + if (proxies != null) { + loop: for (Proxy p : proxies) { + switch (p.type()) { + case HTTP: + proxy = p; + break loop; + case DIRECT: + proxy = Proxy.NO_PROXY; + break; + } + } + } + if (proxy != Proxy.NO_PROXY) + return proxy; + else + return null; + } + + } + + From ef56c358b741aba7c21e2e82505b9471a486acce Mon Sep 17 00:00:00 2001 From: Xavier LEGER Date: Fri, 20 Jun 2025 11:22:58 +0200 Subject: [PATCH 2/6] Change of default value for Proxy research : use Proxy Vole by default --- .../bekoenig/getdown/data/SysProps.java | 4 +-- .../bekoenig/getdown/data/SysPropsTest.java | 35 ++++++++++++++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java b/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java index 6a299e29..3d0d45f6 100644 --- a/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java +++ b/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java @@ -143,11 +143,11 @@ public static boolean useProxy() { } /** - * If false, Getdown will detect proxy through Proxy Vole. Default is false (legacy proxy search). + * If true, Getdown will detect proxy through Proxy Vole. Default is true. * Usage: {@code -Duse_proxy=false}. */ public static boolean useProxyVole() { - return "proxy_vole".equals(System.getProperty("use_proxy")); + return !"false".equals(System.getProperty("use_proxy")) && !"legacy".equals(System.getProperty("use_proxy")); } /** diff --git a/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java b/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java index 87021ecd..e1d16d92 100644 --- a/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java +++ b/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java @@ -106,6 +106,19 @@ void test_useProxy_undefined() { assertThat(useProxy).isTrue(); } + + @Test + @ClearSystemProperty(key = "use_proxy") + void test_useProxyVole_undefined() { + // GIVEN + + // WHEN + boolean useProxyVole = SysProps.useProxyVole(); + + // THEN + assertThat(useProxyVole).isTrue(); + } + @Test @SetSystemProperty(key = "use_proxy", value = "") void test_useProxy_defined() { @@ -118,6 +131,18 @@ void test_useProxy_defined() { assertThat(useProxy).isTrue(); } + @Test + @SetSystemProperty(key = "use_proxy", value = "") + void test_useProxyVole_defined() { + // GIVEN + + // WHEN + boolean useProxyVole = SysProps.useProxyVole(); + + // THEN + assertThat(useProxyVole).isTrue(); + } + @Test @SetSystemProperty(key = "use_proxy", value = "true") void test_useProxy_true() { @@ -144,7 +169,7 @@ void test_useProxy_false() { @Test - @SetSystemProperty(key = "use_proxy", value = "proxy_vole") + @SetSystemProperty(key = "use_proxy", value = "true") void test_useProxy_proxyvole() { // GIVEN @@ -157,7 +182,7 @@ void test_useProxy_proxyvole() { @Test - @SetSystemProperty(key = "use_proxy", value = "proxy_vole") + @SetSystemProperty(key = "use_proxy", value = "legacy") void test_useProxyVole_proxyvole() { // GIVEN @@ -165,7 +190,7 @@ void test_useProxyVole_proxyvole() { boolean useProxyVole = SysProps.useProxyVole(); // THEN - assertThat(useProxyVole).isTrue(); + assertThat(useProxyVole).isFalse(); } @Test @@ -177,11 +202,11 @@ void test_useProxyVole_true() { boolean useProxyVole = SysProps.useProxyVole(); // THEN - assertThat(useProxyVole).isFalse(); + assertThat(useProxyVole).isTrue(); } @Test - @SetSystemProperty(key = "use_proxy", value = "false") + @SetSystemProperty(key = "use_proxy", value = "legacy") void test_useProxyVole_false() { // GIVEN From 14681dd84e1330f25ef9946c9d141d1123e4ad77 Mon Sep 17 00:00:00 2001 From: Xavier LEGER Date: Fri, 20 Jun 2025 12:00:37 +0200 Subject: [PATCH 3/6] Correction for proxy retrieval --- .../io/github/bekoenig/getdown/launcher/ProxyUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java index bce9801f..054d30a0 100644 --- a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java +++ b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java @@ -47,10 +47,10 @@ public static boolean autoDetectProxy(Application app) { if (StringUtil.isBlank(host) && SysProps.useProxyVole()) { Proxy neededProxy = getProxyForInternetAccess(app.getConfigResource().getRemote()); - if (neededProxy != null) - host= ((InetSocketAddress) neededProxy.address()).getHostString(); - assert neededProxy != null; - port= String.valueOf(((InetSocketAddress) neededProxy.address()).getPort()); + if (neededProxy != null) { + host = ((InetSocketAddress) neededProxy.address()).getHostString(); + port = String.valueOf(((InetSocketAddress) neededProxy.address()).getPort()); + } } else if (LaunchUtil.isWindows()) { try { String rhost = null, rport = null; From 5ecdeb5bde3032cdf7ac5630aeac3e8088b3c8a3 Mon Sep 17 00:00:00 2001 From: Xavier LEGER Date: Fri, 20 Jun 2025 12:04:53 +0200 Subject: [PATCH 4/6] Typo corrections for code review clarity --- .../bekoenig/getdown/launcher/ProxyUtil.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java index 054d30a0..9c9e4b30 100644 --- a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java +++ b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java @@ -57,24 +57,24 @@ public static boolean autoDetectProxy(Application app) { boolean enabled = false; RegistryKey.initialize(); RegistryKey r = new RegistryKey(RootKey.HKEY_CURRENT_USER, PROXY_REGISTRY); - for(Iterator iter = r.values(); iter.hasNext(); ) { + for (Iterator iter = r.values(); iter.hasNext(); ) { RegistryValue value = (RegistryValue) iter.next(); - if("ProxyEnable".equals(value.getName())) { + if ("ProxyEnable".equals(value.getName())) { enabled = "1".equals(value.getStringValue()); } - if(value.getName().equals("ProxyServer")) { + if (value.getName().equals("ProxyServer")) { String[] hostPort = splitHostPort(value.getStringValue()); rhost = hostPort[0]; rport = hostPort[1]; } - if(value.getName().equals("AutoConfigURL")) { + if (value.getName().equals("AutoConfigURL")) { String acurl = value.getStringValue(); Reader acjs = new InputStreamReader(new URL(acurl).openStream()); // technically we should be returning all this info and trying each proxy // in succession, but that's complexity we'll leave for another day URL configURL = app.getConfigResource().getRemote(); - for(String proxy : findPACProxiesForURL(acjs, configURL)) { - if(proxy.startsWith("PROXY ")) { + for (String proxy : findPACProxiesForURL(acjs, configURL)) { + if (proxy.startsWith("PROXY ")) { String[] hostPort = splitHostPort(proxy.substring(6)); rhost = hostPort[0]; rport = hostPort[1]; @@ -86,7 +86,7 @@ public static boolean autoDetectProxy(Application app) { } } - if(enabled) { + if (enabled) { host = rhost; port = rport; } else { @@ -95,9 +95,9 @@ public static boolean autoDetectProxy(Application app) { } catch (Throwable t) { LOGGER.atInfo() - .setMessage("Failed to find proxy settings in Windows registry") - .addKeyValue("error", t) - .log(); + .setMessage("Failed to find proxy settings in Windows registry") + .addKeyValue("error", t) + .log(); } } From 6f7f595819c37b7049cb63fa22ba5f0d03416c0f Mon Sep 17 00:00:00 2001 From: Xavier LEGER Date: Fri, 20 Jun 2025 12:56:50 +0200 Subject: [PATCH 5/6] Typo corrections for code review clarity --- .../java/io/github/bekoenig/getdown/launcher/ProxyUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java index 9c9e4b30..a1fd86c4 100644 --- a/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java +++ b/launcher/src/main/java/io/github/bekoenig/getdown/launcher/ProxyUtil.java @@ -95,9 +95,9 @@ public static boolean autoDetectProxy(Application app) { } catch (Throwable t) { LOGGER.atInfo() - .setMessage("Failed to find proxy settings in Windows registry") - .addKeyValue("error", t) - .log(); + .setMessage("Failed to find proxy settings in Windows registry") + .addKeyValue("error", t) + .log(); } } From 1836ae8b5b3db890075220b5ceb739197de9459c Mon Sep 17 00:00:00 2001 From: Xavier LEGER Date: Fri, 20 Jun 2025 13:06:10 +0200 Subject: [PATCH 6/6] Changelog file updated --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a74ec52..8de8ac36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Getdown Releases +## 2.0.1 - +* Introduction of ProxyVole dependency library as default proxy detection, old usage of JRegistryKey + kept, require setting property `use_proxy` to value `legacy` + + ## 2.0.0 - May 01, 2024 * GroupId and package root have moved from `com.threerings.getdown` to `io.github.bekoenig.getdown`