summaryrefslogblamecommitdiffstats
path: root/src/main/java/com/btr/proxy/search/browser/ie/IEProxySearchStrategy.java
blob: 6641aff78490b02d84be30f198ea01b7ab902230 (plain) (tree)
1
2
3
4
5



                                        
                      










                                                            

                                                                
                                          

                                         
































































































































































                                                                                                                

                                                                                                          





























                                                                                                     
package com.btr.proxy.search.browser.ie;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.Proxy;
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.whitelist.ProxyBypassListSelector;
import com.btr.proxy.util.Logger;
import com.btr.proxy.util.Logger.LogLevel;
import com.btr.proxy.util.ProxyException;
import com.btr.proxy.util.ProxyUtil;
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 ("<local>".equals(bypassList.trim())) {
				result = buildLocalBypassSelector(ps);
			} else {
				bypassList = bypassList.replace(';', ',');
				result = new ProxyBypassListSelector(bypassList, ps);
			}
			return result;
		}
		return ps;
	}

	/*************************************************************************
	 * @param ps
	 * @return
	 ************************************************************************/
	
	private ProxyBypassListSelector buildLocalBypassSelector(
			ProtocolDispatchSelector ps) {
		List<UriFilter> localBypassFilter = new ArrayList<UriFilter>();
		localBypassFilter.add(new IELocalByPassFilter());
		return new ProxyBypassListSelector(localBypassFilter, ps);
	}

	/*************************************************************************
	 * Installs a fallback selector that is used whenever no protocol specific
	 * selector is defined.
	 * @param settings to take the proxy settings from.
	 * @param ps to install the created selector on.
	 ************************************************************************/
	
	private void addFallbackSelector(Properties settings, ProtocolDispatchSelector ps) {
		String proxy = settings.getProperty("default");
		if (proxy != null) {
			ps.setFallbackSelector(ProxyUtil.parseProxySettings(proxy));
		}
	}

	/*************************************************************************
	 * Creates a selector for a given protocol. The proxy will be taken
	 * from the settings and installed on the dispatch selector.
	 * @param settings to take the proxy settings from.
	 * @param protocol to create a selector for.
	 * @param ps to install the created selector on.
	 ************************************************************************/
	
	private void addSelectorForProtocol(Properties settings, String protocol, ProtocolDispatchSelector ps) {
		String proxy = settings.getProperty(protocol);
		if (proxy != null) {
			Proxy.Type fb = protocol.startsWith("socks") ? Proxy.Type.SOCKS : Proxy.Type.HTTP;
			ProxySelector protocolSelector = ProxyUtil.parseProxySettings(proxy, fb, 0);
			ps.setSelector(protocol, protocolSelector);
		}
	}

	/*************************************************************************
	 * Parses the proxy list and splits it by protocol.
	 * @param proxyString the proxy list string
	 * @return Properties with separated settings.
	 * @throws ProxyException on parse error.
	 ************************************************************************/
	
	private Properties parseProxyList(String proxyString) throws ProxyException {
		Properties p = new Properties();
		if (proxyString.indexOf('=') == -1) {
			p.setProperty("default", proxyString);
		} else {
			try {
				proxyString = proxyString.replace(';', '\n');
				p.load(new ByteArrayInputStream(proxyString.getBytes("ISO-8859-1")));
			} catch (IOException e) {
				Logger.log(getClass(), LogLevel.ERROR, 
						"Error reading IE settings as properties: {0}", e);
	
				throw new ProxyException(e);
			}
		}
		return p;
	}

}