From e70ee5b59306ea37dd0c72603c61b33b1555def9 Mon Sep 17 00:00:00 2001 From: Björn Hagemeister Date: Tue, 11 Nov 2014 14:40:18 +0100 Subject: Added proxy java classes. --- .../browser/firefox/FirefoxProfileSource.java | 23 ++ .../firefox/FirefoxProxySearchStrategy.java | 267 +++++++++++++++++++++ .../browser/firefox/FirefoxSettingParser.java | 79 ++++++ .../browser/firefox/LinuxFirefoxProfileSource.java | 46 ++++ .../browser/firefox/WinFirefoxProfileSource.java | 71 ++++++ .../search/browser/ie/IELocalByPassFilter.java | 28 +++ .../search/browser/ie/IEProxySearchStrategy.java | 213 ++++++++++++++++ 7 files changed, 727 insertions(+) create mode 100644 src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProfileSource.java create mode 100644 src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java create mode 100644 src/main/java/com/btr/proxy/search/browser/firefox/FirefoxSettingParser.java create mode 100644 src/main/java/com/btr/proxy/search/browser/firefox/LinuxFirefoxProfileSource.java create mode 100644 src/main/java/com/btr/proxy/search/browser/firefox/WinFirefoxProfileSource.java create mode 100644 src/main/java/com/btr/proxy/search/browser/ie/IELocalByPassFilter.java create mode 100644 src/main/java/com/btr/proxy/search/browser/ie/IEProxySearchStrategy.java (limited to 'src/main/java/com/btr/proxy/search/browser') diff --git a/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProfileSource.java b/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProfileSource.java new file mode 100644 index 0000000..8517074 --- /dev/null +++ b/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProfileSource.java @@ -0,0 +1,23 @@ +package com.btr.proxy.search.browser.firefox; + +import java.io.File; +import java.io.IOException; + +/***************************************************************************** + * A profile source for Firefox profiles. + * + * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 + ****************************************************************************/ + +interface FirefoxProfileSource { + + /************************************************************************* + * Gets a profile folder found on the current system. + * If multiple profile folders are available the "default" profile is chosen. + * @return a profile folder. + * @throws IOException on error. + ************************************************************************/ + + public File getProfileFolder() throws IOException; + +} diff --git a/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java new file mode 100644 index 0000000..30c3be1 --- /dev/null +++ b/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxProxySearchStrategy.java @@ -0,0 +1,267 @@ +package com.btr.proxy.search.browser.firefox; + +import java.io.IOException; +import java.net.ProxySelector; +import java.util.Properties; + +import com.btr.proxy.search.ProxySearchStrategy; +import com.btr.proxy.search.desktop.DesktopProxySearchStrategy; +import com.btr.proxy.search.wpad.WpadProxySearchStrategy; +import com.btr.proxy.selector.direct.NoProxySelector; +import com.btr.proxy.selector.fixed.FixedProxySelector; +import com.btr.proxy.selector.fixed.FixedSocksSelector; +import com.btr.proxy.selector.misc.ProtocolDispatchSelector; +import com.btr.proxy.selector.whitelist.ProxyBypassListSelector; +import com.btr.proxy.util.Logger; +import com.btr.proxy.util.Logger.LogLevel; +import com.btr.proxy.util.PlatformUtil; +import com.btr.proxy.util.PlatformUtil.Platform; +import com.btr.proxy.util.ProxyException; +import com.btr.proxy.util.ProxyUtil; + +/***************************************************************************** + * Loads the Firefox3 proxy settings from the users Firefox3 settings. + * This will load the file prefs.js that is located in the + *
+ * .mozilla/firefox/(profile)/ folder. + *
+ * + * See Mozilla_Networking_Preferences + * for an explanation of the proxy settings. + *+ * The following settings are extracted from + * this file: + *
+ * Some generic settings:+ * Note that if there are more than one profile the first profile found will be used. + *
+ * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 + ****************************************************************************/ + +public class FirefoxProxySearchStrategy implements ProxySearchStrategy { + + private FirefoxProfileSource profileScanner; + private FirefoxSettingParser settingsParser; + + /************************************************************************* + * ProxySelector + * @see java.net.ProxySelector#ProxySelector() + ************************************************************************/ + + public FirefoxProxySearchStrategy() { + super(); + if (PlatformUtil.getCurrentPlattform() == Platform.WIN) { + this.profileScanner = new WinFirefoxProfileSource(); + } else { + this.profileScanner = new LinuxFirefoxProfileSource(); + } + this.settingsParser = new FirefoxSettingParser(); + } + + /************************************************************************* + * Loads the proxy settings and initializes a proxy selector for the firefox + * proxy settings. + * @return a configured ProxySelector, null if none is found. + * @throws ProxyException on file reading error. + ************************************************************************/ + + public ProxySelector getProxySelector() throws ProxyException { + Logger.log(getClass(), LogLevel.TRACE, "Detecting Firefox settings."); + + Properties settings = readSettings(); + + ProxySelector result = null; + int type = Integer.parseInt(settings.getProperty("network.proxy.type", "-1")); + switch (type) { + case -1: // Use system settings + Logger.log(getClass(), LogLevel.TRACE, "Firefox uses system settings"); + result = new DesktopProxySearchStrategy().getProxySelector(); + break; + case 0: // Use no proxy + Logger.log(getClass(), LogLevel.TRACE, "Firefox uses no proxy"); + result = NoProxySelector.getInstance(); + break; + case 1: // Fixed settings + Logger.log(getClass(), LogLevel.TRACE, "Firefox uses manual settings"); + result = setupFixedProxySelector(settings); + break; + case 2: // PAC Script + String pacScriptUrl = settings.getProperty("network.proxy.autoconfig_url", ""); + Logger.log(getClass(), LogLevel.TRACE, "Firefox uses script (PAC) {0}", pacScriptUrl); + result = ProxyUtil.buildPacSelectorForUrl(pacScriptUrl); + break; + case 3: // Backward compatibility to netscape. + Logger.log(getClass(), LogLevel.TRACE, "Netscape compability mode -> uses no proxy"); + result = NoProxySelector.getInstance(); + break; + case 4: // WPAD auto config + Logger.log(getClass(), LogLevel.TRACE, "Firefox uses automatic detection (WPAD)"); + result = new WpadProxySearchStrategy().getProxySelector(); + break; + default: + break; + } + + // Wrap in white list filter. + String noProxyList = settings.getProperty("network.proxy.no_proxies_on", null); + if (result != null && noProxyList != null && noProxyList.trim().length() > 0) { + Logger.log(getClass(), LogLevel.TRACE, "Firefox uses proxy bypass list for: {0}", noProxyList); + result = new ProxyBypassListSelector(noProxyList, result); + } + + return result; + } + + /************************************************************************* + * Reads the settings file and stores all settings in a Properties map. + * @return the parsed settings. + * @throws ProxyException on read error. + ************************************************************************/ + + public Properties readSettings() throws ProxyException { + try { + Properties settings = this.settingsParser.parseSettings(this.profileScanner); + return settings; + } catch (IOException e) { + Logger.log(getClass(), LogLevel.ERROR, "Error parsing settings", e); + throw new ProxyException(e); + } + } + + /************************************************************************* + * Parse the fixed proxy settings and build an ProxySelector for this a + * chained configuration. + * @param settings the proxy settings to evaluate. + ************************************************************************/ + + private ProxySelector setupFixedProxySelector(Properties settings) { + ProtocolDispatchSelector ps = new ProtocolDispatchSelector(); + installHttpProxy(ps, settings); + if (isProxyShared(settings)) { + installSharedProxy(ps); + } else { + installFtpProxy(ps, settings); + installSecureProxy(ps, settings); + installSocksProxy(ps, settings); + } + return ps; + } + + /************************************************************************* + * @param ps + * @param settings + * @throws NumberFormatException + ************************************************************************/ + + private void installFtpProxy(ProtocolDispatchSelector ps, + Properties settings) throws NumberFormatException { + installSelectorForProtocol(ps, settings, "ftp"); + } + + /************************************************************************* + * @param ps + * @param settings + * @throws NumberFormatException + ************************************************************************/ + + private void installHttpProxy(ProtocolDispatchSelector ps, + Properties settings) throws NumberFormatException { + installSelectorForProtocol(ps, settings, "http"); + } + + /************************************************************************* + * @param settings + * @return + ************************************************************************/ + + private boolean isProxyShared(Properties settings) { + return Boolean.TRUE.toString().equals(settings.getProperty("network.proxy.share_proxy_settings", "false").toLowerCase()); + } + + /************************************************************************* + * @param ps + ************************************************************************/ + + private void installSharedProxy(ProtocolDispatchSelector ps) { + ProxySelector httpProxy = ps.getSelector("http"); + if (httpProxy != null) { + ps.setFallbackSelector(httpProxy); + } + } + + /************************************************************************* + * @param ps + * @param settings + * @throws NumberFormatException + ************************************************************************/ + + private void installSocksProxy(ProtocolDispatchSelector ps, + Properties settings) throws NumberFormatException { + String proxyHost = settings.getProperty("network.proxy.socks", null); + int proxyPort = Integer.parseInt(settings.getProperty("network.proxy.socks_port", "0")); + if (proxyHost != null && proxyPort != 0) { + Logger.log(getClass(), LogLevel.TRACE, "Firefox socks proxy is {0}:{1}", proxyHost, proxyPort); + ps.setSelector("socks", new FixedSocksSelector(proxyHost, proxyPort)); + } + } + + /************************************************************************* + * @param ps + * @param settings + * @throws NumberFormatException + ************************************************************************/ + + private void installSecureProxy(ProtocolDispatchSelector ps, + Properties settings) throws NumberFormatException { + String proxyHost = settings.getProperty("network.proxy.ssl", null); + int proxyPort = Integer.parseInt(settings.getProperty("network.proxy.ssl_port", "0")); + if (proxyHost != null && proxyPort != 0) { + Logger.log(getClass(), LogLevel.TRACE, "Firefox secure proxy is {0}:{1}", proxyHost, proxyPort); + ps.setSelector("https", new FixedProxySelector(proxyHost, proxyPort)); + ps.setSelector("sftp", new FixedProxySelector(proxyHost, proxyPort)); + } + } + + /************************************************************************* + * Installs a proxy selector for the given protocol when settings are + * available. + * @param ps a ProtocolDispatchSelector to configure. + * @param settings to read the config from. + * @param protocol to configure. + * @throws NumberFormatException + ************************************************************************/ + + private void installSelectorForProtocol(ProtocolDispatchSelector ps, + Properties settings, String protocol) throws NumberFormatException { + + String proxyHost = settings.getProperty("network.proxy."+protocol, null); + int proxyPort = Integer.parseInt(settings.getProperty("network.proxy."+protocol+"_port", "0")); + if (proxyHost != null && proxyPort != 0) { + Logger.log(getClass(), LogLevel.TRACE, "Firefox "+protocol+" proxy is {0}:{1}", proxyHost, proxyPort); + ps.setSelector(protocol, new FixedProxySelector(proxyHost, proxyPort)); + } + } + + +} diff --git a/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxSettingParser.java b/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxSettingParser.java new file mode 100644 index 0000000..b793299 --- /dev/null +++ b/src/main/java/com/btr/proxy/search/browser/firefox/FirefoxSettingParser.java @@ -0,0 +1,79 @@ +package com.btr.proxy.search.browser.firefox; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Properties; + +/***************************************************************************** + * Parser for the Firefox settings file. + * Will extract all relevant proxy settings form the configuration file. + * + * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 + ****************************************************************************/ + +class FirefoxSettingParser { + + /************************************************************************* + * Constructor + ************************************************************************/ + + public FirefoxSettingParser() { + super(); + } + + /************************************************************************* + * Parse the settings file and extract all network.proxy.* settings from it. + * @param source of the Firefox profiles. + * @return the parsed properties. + * @throws IOException on read error. + ************************************************************************/ + + public Properties parseSettings(FirefoxProfileSource source) throws IOException { + // Search settings folder + File profileFolder = source.getProfileFolder(); + + // Read settings from file + File settingsFile = new File(profileFolder, "prefs.js"); + + BufferedReader fin = new BufferedReader( + new InputStreamReader( + new FileInputStream(settingsFile))); + + Properties result = new Properties(); + try { + String line = fin.readLine(); + while (line != null) { + line = line.trim(); + if (line.startsWith("user_pref(\"network.proxy")) { + line = line.substring(10, line.length()-2); + int index = line.indexOf(","); + String key = line.substring(0, index).trim(); + if (key.startsWith("\"")) { + key = key.substring(1); + } + if (key.endsWith("\"")) { + key = key.substring(0, key.length()-1); + } + String value = line.substring(index+1).trim(); + if (value.startsWith("\"")) { + value = value.substring(1); + } + if (value.endsWith("\"")) { + value = value.substring(0, value.length()-1); + } + result.put(key, value); + } + line = fin.readLine(); + } + } finally { + fin.close(); + } + + return result; + } + + +} diff --git a/src/main/java/com/btr/proxy/search/browser/firefox/LinuxFirefoxProfileSource.java b/src/main/java/com/btr/proxy/search/browser/firefox/LinuxFirefoxProfileSource.java new file mode 100644 index 0000000..38b1553 --- /dev/null +++ b/src/main/java/com/btr/proxy/search/browser/firefox/LinuxFirefoxProfileSource.java @@ -0,0 +1,46 @@ +package com.btr.proxy.search.browser.firefox; + +import java.io.File; + +import com.btr.proxy.util.Logger; +import com.btr.proxy.util.Logger.LogLevel; + +/***************************************************************************** + * Searches for Firefox profile on an Linux / Unix base system. + * This will scan the .mozilla folder in the users home directory to find the + * profiles. + * + * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 + ****************************************************************************/ + +class LinuxFirefoxProfileSource implements FirefoxProfileSource { + + /************************************************************************* + * Get profile folder for the Linux Firefox profile + ************************************************************************/ + + public File getProfileFolder() { + File userDir = new File(System.getProperty("user.home")); + File cfgDir = new File(userDir, ".mozilla"+File.separator+"firefox"+File.separator); + if (!cfgDir.exists()) { + Logger.log(getClass(), LogLevel.DEBUG, "Firefox settings folder not found!"); + return null; + } + File[] profiles = cfgDir.listFiles(); + if (profiles == null || profiles.length == 0) { + Logger.log(getClass(), LogLevel.DEBUG, "Firefox settings folder not found!"); + return null; + } + for (File p : profiles) { + if (p.getName().endsWith(".default")) { + Logger.log(getClass(), LogLevel.TRACE, "Firefox settings folder is {0}", p); + return p; + } + } + + // Fall back -> take the first one found. + Logger.log(getClass(), LogLevel.TRACE, "Firefox settings folder is {0}", profiles[0]); + return profiles[0]; + } + +} diff --git a/src/main/java/com/btr/proxy/search/browser/firefox/WinFirefoxProfileSource.java b/src/main/java/com/btr/proxy/search/browser/firefox/WinFirefoxProfileSource.java new file mode 100644 index 0000000..9189585 --- /dev/null +++ b/src/main/java/com/btr/proxy/search/browser/firefox/WinFirefoxProfileSource.java @@ -0,0 +1,71 @@ +package com.btr.proxy.search.browser.firefox; + +import java.io.File; +import java.io.IOException; + +import com.btr.proxy.search.desktop.win.Win32ProxyUtils; +import com.btr.proxy.util.Logger; +import com.btr.proxy.util.Logger.LogLevel; + +/***************************************************************************** + * Finds the Firefox profile on Windows platforms. + * On Windows the profiles are located in the users appdata directory under: + *+ * Mozilla\Firefox\Profiles\ + *
+ * The location of the appdata folder is read from the windows registry. + * + * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 + ****************************************************************************/ + +class WinFirefoxProfileSource implements FirefoxProfileSource { + + /************************************************************************* + * Constructor + ************************************************************************/ + + public WinFirefoxProfileSource() { + super(); + } + + /************************************************************************* + * Reads the current location of the app data folder from the registry. + * @return a path to the folder. + ************************************************************************/ + + private String getAppFolder() { + return new Win32ProxyUtils().readUserHomedir(); + } + + /************************************************************************* + * Get profile folder for the Windows Firefox profile + * @throws IOException on error. + ************************************************************************/ + + public File getProfileFolder() throws IOException { + + File appDataDir = new File(getAppFolder()); + File cfgDir = new File(appDataDir, "Mozilla"+File.separator+"Firefox"+File.separator+"Profiles"); + + if (!cfgDir.exists()) { + Logger.log(getClass(), LogLevel.DEBUG, "Firefox windows settings folder not found."); + return null; + } + File[] profiles = cfgDir.listFiles(); + if (profiles == null || profiles.length == 0) { + Logger.log(getClass(), LogLevel.DEBUG, "Firefox windows settings folder not found."); + return null; + } + for (File p : profiles) { + if (p.getName().endsWith(".default")) { + Logger.log(getClass(), LogLevel.TRACE, "Firefox windows settings folder is {0}.", p); + return p; + } + } + + // Fall back -> take the first one found. + Logger.log(getClass(), LogLevel.TRACE, "Firefox windows settings folder is {0}.", profiles[0]); + return profiles[0]; + } + +} diff --git a/src/main/java/com/btr/proxy/search/browser/ie/IELocalByPassFilter.java b/src/main/java/com/btr/proxy/search/browser/ie/IELocalByPassFilter.java new file mode 100644 index 0000000..fb81d6f --- /dev/null +++ b/src/main/java/com/btr/proxy/search/browser/ie/IELocalByPassFilter.java @@ -0,0 +1,28 @@ +package com.btr.proxy.search.browser.ie; + +import java.net.URI; + +import com.btr.proxy.util.UriFilter; + +/***************************************************************************** + * + * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 + ****************************************************************************/ + +public class IELocalByPassFilter implements UriFilter { + + /************************************************************************* + * accept + * @see com.btr.proxy.util.UriFilter#accept(java.net.URI) + ************************************************************************/ + + public boolean accept(URI uri) { + if (uri == null) { + return false; + } + String host = uri.getAuthority(); + return host != null && !host.contains("."); + } + +} + diff --git a/src/main/java/com/btr/proxy/search/browser/ie/IEProxySearchStrategy.java b/src/main/java/com/btr/proxy/search/browser/ie/IEProxySearchStrategy.java new file mode 100644 index 0000000..2a9b078 --- /dev/null +++ b/src/main/java/com/btr/proxy/search/browser/ie/IEProxySearchStrategy.java @@ -0,0 +1,213 @@ +package com.btr.proxy.search.browser.ie; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.ProxySelector; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import com.btr.proxy.search.ProxySearchStrategy; +import com.btr.proxy.search.desktop.win.Win32IESettings; +import com.btr.proxy.search.desktop.win.Win32ProxyUtils; +import com.btr.proxy.selector.fixed.FixedProxySelector; +import com.btr.proxy.selector.misc.ProtocolDispatchSelector; +import com.btr.proxy.selector.pac.PacProxySelector; +import com.btr.proxy.selector.pac.UrlPacScriptSource; +import com.btr.proxy.selector.whitelist.ProxyBypassListSelector; +import com.btr.proxy.util.Logger; +import com.btr.proxy.util.ProxyException; +import com.btr.proxy.util.ProxyUtil; +import com.btr.proxy.util.Logger.LogLevel; +import com.btr.proxy.util.UriFilter; + +/***************************************************************************** + * Extracts the proxy settings for Microsoft Internet Explorer. + * The settings are read by invoking native Windows API methods. + * + * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009 + ****************************************************************************/ + +public class IEProxySearchStrategy implements ProxySearchStrategy { + + /************************************************************************* + * getProxySelector + * @see com.btr.proxy.search.ProxySearchStrategy#getProxySelector() + ************************************************************************/ + + public ProxySelector getProxySelector() throws ProxyException { + + Logger.log(getClass(), LogLevel.TRACE, "Detecting IE proxy settings"); + + Win32IESettings ieSettings = readSettings(); + + ProxySelector result = createPacSelector(ieSettings); + if (result == null) { + result = createFixedProxySelector(ieSettings); + } + return result; + } + + /************************************************************************* + * Loads the settings from the windows registry. + * @return WinIESettings containing all proxy settings. + ************************************************************************/ + + public Win32IESettings readSettings() { + Win32IESettings ieSettings = new Win32ProxyUtils().winHttpGetIEProxyConfigForCurrentUser(); + return ieSettings; + } + + /************************************************************************* + * Parses the settings and creates an PAC ProxySelector for it. + * @param ieSettings the IE settings to use. + * @return a PacProxySelector the selector or null. + ************************************************************************/ + + private PacProxySelector createPacSelector(Win32IESettings ieSettings) { + String pacUrl = null; + + if (ieSettings.isAutoDetect()) { + Logger.log(getClass(), LogLevel.TRACE, "Autodetecting script URL."); + // This will take some time. + pacUrl = new Win32ProxyUtils().winHttpDetectAutoProxyConfigUrl( + Win32ProxyUtils.WINHTTP_AUTO_DETECT_TYPE_DHCP+ + Win32ProxyUtils.WINHTTP_AUTO_DETECT_TYPE_DNS_A); + } + if (pacUrl == null) { + pacUrl = ieSettings.getAutoConfigUrl(); + } + if (pacUrl != null && pacUrl.trim().length() > 0) { + Logger.log(getClass(), LogLevel.TRACE, "IE uses script: "+pacUrl); + + // Fix for issue 9 + // If the IE has a file URL and it only starts has 2 slashes, + // add a third so it can be properly converted to the URL class + if (pacUrl.startsWith("file://") && !pacUrl.startsWith("file:///")) { + pacUrl = "file:///" + pacUrl.substring(7); + } + return ProxyUtil.buildPacSelectorForUrl(pacUrl); + } + + return null; + } + + /************************************************************************* + * Parses the proxy settings into an ProxySelector. + * @param ieSettings the settings to use. + * @return a ProxySelector, null if no settings are set. + * @throws ProxyException on error. + ************************************************************************/ + + private ProxySelector createFixedProxySelector(Win32IESettings ieSettings) throws ProxyException { + String proxyString = ieSettings.getProxy(); + String bypassList = ieSettings.getProxyBypass(); + if (proxyString == null) { + return null; + } + Logger.log(getClass(), LogLevel.TRACE, + "IE uses manual settings: {0} with bypass list: {1}", proxyString, bypassList); + + Properties p = parseProxyList(proxyString); + + ProtocolDispatchSelector ps = new ProtocolDispatchSelector(); + addSelectorForProtocol(p, "http", ps); + addSelectorForProtocol(p, "https", ps); + addSelectorForProtocol(p, "ftp", ps); + addSelectorForProtocol(p, "gopher", ps); + addSelectorForProtocol(p, "socks", ps); + addFallbackSelector(p, ps); + + ProxySelector result = setByPassListOnSelector(bypassList, ps); + return result; + } + + /************************************************************************* + * @param bypassList + * @param ps + * @return + ************************************************************************/ + + private ProxySelector setByPassListOnSelector(String bypassList, + ProtocolDispatchSelector ps) { + if (bypassList != null && bypassList.trim().length() > 0) { + ProxyBypassListSelector result; + if ("