com.github.markusbernhardt.proxy.search.browser.firefox.FirefoxProxySearchStrategy Maven / Gradle / Ivy
package com.github.markusbernhardt.proxy.search.browser.firefox;
import java.io.IOException;
import java.net.ProxySelector;
import java.util.Properties;
import com.github.markusbernhardt.proxy.ProxySearchStrategy;
import com.github.markusbernhardt.proxy.search.desktop.DesktopProxySearchStrategy;
import com.github.markusbernhardt.proxy.search.wpad.WpadProxySearchStrategy;
import com.github.markusbernhardt.proxy.selector.direct.NoProxySelector;
import com.github.markusbernhardt.proxy.selector.fixed.FixedProxySelector;
import com.github.markusbernhardt.proxy.selector.fixed.FixedSocksSelector;
import com.github.markusbernhardt.proxy.selector.misc.ProtocolDispatchSelector;
import com.github.markusbernhardt.proxy.selector.whitelist.ProxyBypassListSelector;
import com.github.markusbernhardt.proxy.util.Logger;
import com.github.markusbernhardt.proxy.util.Logger.LogLevel;
import com.github.markusbernhardt.proxy.util.PlatformUtil;
import com.github.markusbernhardt.proxy.util.PlatformUtil.Platform;
import com.github.markusbernhardt.proxy.util.ProxyException;
import com.github.markusbernhardt.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:
*
* - network.proxy.type -> n/a = use system settings, 0 = direct, 1
* = Fixed proxy settings, 2 = proxy script (PAC), 3 = also direct , 4 = auto
* detect (WPAD)
* - network.proxy.share_proxy_settings -> true = use same proxy for
* all protocols
* - network.proxy.no_proxies_on -> a comma separated ignore list.
*
* - network.proxy.autoconfig_url -> a URL to an proxy configuration
* script
*
* Host names and ports per protocol are stored in the following settings:
*
* - network.proxy.http
* - network.proxy.http_port
* - network.proxy.ssl
* - network.proxy.ssl_port
* - network.proxy.ftp
* - network.proxy.ftp_port
* - network.proxy.gopher
* - network.proxy.gopher_port
* - network.proxy.socks
* - network.proxy.socks_port
* - network.proxy.socks_version -> 4 or 5
*
*
* Note that if there are more than one profile the first profile found will be
* used.
*
*
* @author Markus Bernhardt, Copyright 2016
* @author Bernd Rosstauscher, 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 if (PlatformUtil.getCurrentPlattform() == Platform.MAC_OS) {
this.profileScanner = new OsxFirefoxProfileSource();
} 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.
************************************************************************/
@Override
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) {}", 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: {}", noProxyList);
result = new ProxyBypassListSelector(noProxyList, result);
}
return result;
}
/*************************************************************************
* Gets the printable name of the search strategy.
*
* @return the printable name of the search strategy
************************************************************************/
@Override
public String getName() {
return "firefox";
}
/*************************************************************************
* 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 = settingsParser.parseSettings(profileScanner);
return settings;
} catch (IOException e) {
throw new ProxyException("No Firefox installation found");
}
}
/*************************************************************************
* 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");
}
/*************************************************************************
* Checks if the "share proxy settings" option is set
*
* @param settings
* to parse
* @return true if the option is set else false
************************************************************************/
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 {}:{}", 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 {}:{}", 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 {}:{}", proxyHost, proxyPort);
ps.setSelector(protocol, new FixedProxySelector(proxyHost, proxyPort));
}
}
}