package com.btr.proxy.search.browser.firefox; import java.io.IOException; import java.net.Proxy; 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.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; httpProxy = ps.getSelector("socks"); if (httpProxy != null) { ps.setFallbackSelector(httpProxy); return; } httpProxy = ps.getSelector("http"); if (httpProxy != null) { ps.setFallbackSelector(httpProxy); return; } } /************************************************************************* * @param ps * @param settings * @throws NumberFormatException ************************************************************************/ private void installSocksProxy(ProtocolDispatchSelector ps, Properties settings) throws NumberFormatException { installSelectorForProtocol(ps, settings, "socks"); } /************************************************************************* * @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) { Logger.log(getClass(), LogLevel.TRACE, "Firefox secure proxy is {0}:{1}", proxyHost, proxyPort); ProxySelector p = ProxyUtil.parseProxySettings(proxyHost, Proxy.Type.HTTP, proxyPort); ps.setSelector("https", p); ps.setSelector("sftp", p); } } /************************************************************************* * 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) { Proxy.Type type; if (protocol.startsWith("socks")) { type = Proxy.Type.SOCKS; protocol = "socket"; } else { type = Proxy.Type.HTTP; } Logger.log(getClass(), LogLevel.TRACE, "Firefox "+protocol+" proxy is {0}:{1}", proxyHost, proxyPort); ps.setSelector(protocol, ProxyUtil.parseProxySettings(proxyHost, type, proxyPort)); } } }