X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=getdown%2Fsrc%2Fgetdown%2Flauncher%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Flauncher%2FProxyUtil.java;fp=getdown%2Fsrc%2Fgetdown%2Flauncher%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Flauncher%2FProxyUtil.java;h=a36b5fa671e1e632077ceb948a1e365ded6eba9f;hb=74393b51f368cb9f58589472d432a433d9c4386d;hp=0000000000000000000000000000000000000000;hpb=7a0d503181fe41452120a8a02ca63476392aa08c;p=jalview.git diff --git a/getdown/src/getdown/launcher/src/main/java/com/threerings/getdown/launcher/ProxyUtil.java b/getdown/src/getdown/launcher/src/main/java/com/threerings/getdown/launcher/ProxyUtil.java new file mode 100644 index 0000000..a36b5fa --- /dev/null +++ b/getdown/src/getdown/launcher/src/main/java/com/threerings/getdown/launcher/ProxyUtil.java @@ -0,0 +1,210 @@ +// +// Getdown - application installer, patcher and launcher +// Copyright (C) 2004-2018 Getdown authors +// https://github.com/threerings/getdown/blob/master/LICENSE + +package com.threerings.getdown.launcher; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.util.Iterator; +import java.util.ServiceLoader; + +import ca.beq.util.win32.registry.RegistryKey; +import ca.beq.util.win32.registry.RegistryValue; +import ca.beq.util.win32.registry.RootKey; + +import com.threerings.getdown.data.Application; +import com.threerings.getdown.spi.ProxyAuth; +import com.threerings.getdown.util.Config; +import com.threerings.getdown.util.ConnectionUtil; +import com.threerings.getdown.util.LaunchUtil; +import com.threerings.getdown.util.StringUtil; + +import static com.threerings.getdown.Log.log; + +public class ProxyUtil { + + public static boolean autoDetectProxy (Application app) + { + String host = null, port = null; + + // check for a proxy configured via system properties + if (System.getProperty("https.proxyHost") != null) { + host = System.getProperty("https.proxyHost"); + port = System.getProperty("https.proxyPort"); + } + if (StringUtil.isBlank(host) && System.getProperty("http.proxyHost") != null) { + host = System.getProperty("http.proxyHost"); + port = System.getProperty("http.proxyPort"); + } + + // check the Windows registry + if (StringUtil.isBlank(host) && 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(); ) { + RegistryValue value = (RegistryValue)iter.next(); + if (value.getName().equals("ProxyEnable")) { + enabled = value.getStringValue().equals("1"); + } + if (value.getName().equals("ProxyServer")) { + String strval = value.getStringValue(); + int cidx = strval.indexOf(":"); + if (cidx != -1) { + rport = strval.substring(cidx+1); + strval = strval.substring(0, cidx); + } + rhost = strval; + } + } + if (enabled) { + host = rhost; + port = rport; + } else { + log.info("Detected no proxy settings in the registry."); + } + } catch (Throwable t) { + log.info("Failed to find proxy settings in Windows registry", "error", t); + } + } + + // look for a proxy.txt file + if (StringUtil.isBlank(host)) { + String[] hostPort = loadProxy(app); + host = hostPort[0]; + port = hostPort[1]; + } + + if (StringUtil.isBlank(host)) { + return false; + } + + // yay, we found a proxy configuration, configure it in the app + initProxy(app, host, port, null, null); + return true; + } + + public static boolean canLoadWithoutProxy (URL rurl) + { + log.info("Testing whether proxy is needed, via: " + rurl); + try { + // try to make a HEAD request for this URL (use short connect and read timeouts) + URLConnection conn = ConnectionUtil.open(Proxy.NO_PROXY, rurl, 5, 5); + if (conn instanceof HttpURLConnection) { + HttpURLConnection hcon = (HttpURLConnection)conn; + try { + hcon.setRequestMethod("HEAD"); + hcon.connect(); + // make sure we got a satisfactory response code + int rcode = hcon.getResponseCode(); + if (rcode == HttpURLConnection.HTTP_PROXY_AUTH || + rcode == HttpURLConnection.HTTP_FORBIDDEN) { + log.warning("Got an 'HTTP credentials needed' response", "code", rcode); + } else { + return true; + } + } finally { + hcon.disconnect(); + } + } else { + // if the appbase is not an HTTP/S URL (like file:), then we don't need a proxy + return true; + } + } catch (IOException ioe) { + log.info("Failed to HEAD " + rurl + ": " + ioe); + log.info("We probably need a proxy, but auto-detection failed."); + } + return false; + } + + public static void configProxy (Application app, String host, String port, + String username, String password) { + // save our proxy host and port in a local file + saveProxy(app, host, port); + + // save our credentials via the SPI + if (!StringUtil.isBlank(username) && !StringUtil.isBlank(password)) { + ServiceLoader loader = ServiceLoader.load(ProxyAuth.class); + Iterator iterator = loader.iterator(); + String appDir = app.getAppDir().getAbsolutePath(); + while (iterator.hasNext()) { + iterator.next().saveCredentials(appDir, username, password); + } + } + + // also configure them in the app + initProxy(app, host, port, username, password); + } + + public static String[] loadProxy (Application app) { + File pfile = app.getLocalPath("proxy.txt"); + if (pfile.exists()) { + try { + Config pconf = Config.parseConfig(pfile, Config.createOpts(false)); + return new String[] { pconf.getString("host"), pconf.getString("port") }; + } catch (IOException ioe) { + log.warning("Failed to read '" + pfile + "': " + ioe); + } + } + return new String[] { null, null}; + } + + public static void saveProxy (Application app, String host, String port) { + File pfile = app.getLocalPath("proxy.txt"); + try (PrintStream pout = new PrintStream(new FileOutputStream(pfile))) { + if (!StringUtil.isBlank(host)) { + pout.println("host = " + host); + } + if (!StringUtil.isBlank(port)) { + pout.println("port = " + port); + } + } catch (IOException ioe) { + log.warning("Error creating proxy file '" + pfile + "': " + ioe); + } + } + + public static void initProxy (Application app, String host, String port, + String username, String password) + { + // check whether we have saved proxy credentials + String appDir = app.getAppDir().getAbsolutePath(); + ServiceLoader loader = ServiceLoader.load(ProxyAuth.class); + Iterator iter = loader.iterator(); + ProxyAuth.Credentials creds = iter.hasNext() ? iter.next().loadCredentials(appDir) : null; + if (creds != null) { + username = creds.username; + password = creds.password; + } + boolean haveCreds = !StringUtil.isBlank(username) && !StringUtil.isBlank(password); + + int pport = StringUtil.isBlank(port) ? 80 : Integer.valueOf(port); + log.info("Using proxy", "host", host, "port", pport, "haveCreds", haveCreds); + app.proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, pport)); + + if (haveCreds) { + final String fuser = username; + final char[] fpass = password.toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override protected PasswordAuthentication getPasswordAuthentication () { + return new PasswordAuthentication(fuser, fpass); + } + }); + } + } + + protected static final String PROXY_REGISTRY = + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; +}