summaryrefslogblamecommitdiffstats
path: root/src/main/java/com/btr/proxy/search/wpad/WpadProxySearchStrategy.java
blob: cf01fd35fcfd507b44a8a885a61fd4c60748d3c1 (plain) (tree)









































































































































































































































                                                                                                                                          
package com.btr.proxy.search.wpad;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Properties;

import com.btr.proxy.search.ProxySearchStrategy;
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;


/*****************************************************************************
 * Uses automatic proxy script search (WPAD) to find an PAC file automatically.
 * <p>
 * Note: at the moment only the DNS name guessing schema is implemented. 
 * All others are missing.
 * </p><p>
 * For more information about WPAD:
 * <a href="http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol">Web_Proxy_Autodiscovery_Protocol</a>
 * </p><p>
 * Outdated RFC draft:
 * <a href="http://www.web-cache.com/Writings/Internet-Drafts/draft-ietf-wrec-wpad-01.txt">draft-ietf-wrec-wpad-01.txt</a>
 * </p>
 * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
 ****************************************************************************/

public class WpadProxySearchStrategy implements ProxySearchStrategy {
	
	/*************************************************************************
	 * Constructor
	 ************************************************************************/
	
	public WpadProxySearchStrategy() {
		super();
	}
	
	/*************************************************************************
	 * Loads the proxy settings from a PAC file. 
	 * The location of the PAC file is determined automatically.
	 * @return a configured ProxySelector, null if none is found.
	 * @throws ProxyException on error. 
	 ************************************************************************/

	public ProxySelector getProxySelector() throws ProxyException {
		try {
			Logger.log(getClass(), LogLevel.TRACE, "Using WPAD to find a proxy");

			String pacScriptUrl = detectScriptUrlPerDHCP();
			if (pacScriptUrl == null) {
				pacScriptUrl = detectScriptUrlPerDNS();
			}
			if (pacScriptUrl == null) {
				return null;
			}
			Logger.log(getClass(), LogLevel.TRACE, "PAC script url found: {0}", pacScriptUrl);
			return ProxyUtil.buildPacSelectorForUrl(pacScriptUrl);
		} catch (IOException e) {
			Logger.log(getClass(), LogLevel.ERROR, "Error during WPAD search.", e);
			throw new ProxyException(e);
		}
	}
	
	/*************************************************************************
	 * Loads the settings and stores them in a properties map.
	 * @return the settings.
	 ************************************************************************/
	
	public Properties readSettings() {
		try {
			String pacScriptUrl = detectScriptUrlPerDHCP();
			if (pacScriptUrl == null) {
				pacScriptUrl = detectScriptUrlPerDNS();
			}
			if (pacScriptUrl == null) {
				return null;
			}
			Properties result = new Properties();
			result.setProperty("url", pacScriptUrl);
			return result;
		} catch (IOException e) {
			// Ignore and return empty properties.
			return new Properties();
		}
	}

	/*************************************************************************
	 * Uses DNS to find the script URL.
	 * Attention: this detection method is known to have some severe security issues. 
	 * @return the URL, null if not found.
	 ************************************************************************/
	
	private String detectScriptUrlPerDNS() throws IOException {
		String result = null;
		// String fqdn = InetAddress.getLocalHost().getCanonicalHostName();

		Logger.log(getClass(), LogLevel.TRACE, "Searching per DNS guessing.");
		// Logger.log(getClass(), LogLevel.INFO, "fqdn: ", fqdn);

		/** Reading address from "/etc/resolv.conf"; file looks like:
		 * 
		 	# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
			#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
			nameserver 127.0.1.1
			search ruf.uni-freiburg.de lp.ruf.uni-freiburg.de
		 */
		
		FileReader fr = new FileReader("/etc/resolv.conf");
		BufferedReader br = new BufferedReader(fr);
		
		String input;
		String[] addresses = null;
		// using the 4th line of the file.
		while ((input = br.readLine()) != null) {
			if (input.startsWith("search")) {
				// the first one is "search" and afterwards addresses are following.
				addresses = input.substring(6).split(" ");
				break;
			}
		}
		
		if (addresses == null) {
			addresses = new String[]{""};
		}
		
		
		for (int i = 0; i < addresses.length; ++i) {
			String address = addresses[i];
			int index = -1;
			do {
				if (index != -1) {
					address = address.substring(index);
				} else {
					address = "";
				}
				
				// Try to connect to URL
				try {
					address = ".uni-freiburg.de";
					URL lookupURL = new URL("http://wpad"+ address +"/wpad.dat");
					Logger.log(getClass(), LogLevel.TRACE, "Trying url: {0}", lookupURL);
	
					HttpURLConnection con = (HttpURLConnection) lookupURL.openConnection(Proxy.NO_PROXY);
					con.setInstanceFollowRedirects(true);
					con.setRequestProperty("accept", "application/x-ns-proxy-autoconfig");
					if (con.getResponseCode() == 200) {
						result = lookupURL.toString();
						return result;
					}
					con.disconnect();
				} catch (UnknownHostException e) {
					Logger.log(getClass(), LogLevel.DEBUG, "Not available!");
					// Not a real error, try next address
				}
				if (address.length() == 0) {
					break;
				}
				index = address.indexOf('.', 1);
			} while (true);
		}
		
		return null;
	}

	/*************************************************************************
	 * Uses DHCP to find the script URL.
	 * @return the URL, null if not found.
	 ************************************************************************/
	
	private String detectScriptUrlPerDHCP() {
		Logger.log(getClass(), LogLevel.DEBUG, "Searching per DHCP not supported yet.");
		// TODO Rossi 28.04.2009 Not implemented yet.
		return null;
	}
	
	// Main method for testing.
	public static void main( String[] args ) throws IOException {
		WpadProxySearchStrategy wPSS = new WpadProxySearchStrategy();
//		System.setProperty("com.btr.proxy.pac.overrideLocalIP", "10.0.0.1");
		try {
			ProxySelector pS = wPSS.getProxySelector();
			ProxySelector.setDefault(pS);
			List<Proxy> proxyList = pS.select(new URI("http://www.google.de"));
			
			if (proxyList.isEmpty()) {
				Logger.log(WpadProxySearchStrategy.class, LogLevel.INFO, "ProxyList is empty!");
			} else {
				Logger.log(WpadProxySearchStrategy.class, LogLevel.INFO, "proxyList contains: {0}", proxyList.toString());
			}
		} catch (ProxyException e) {
			// TODO bjoern 28.10.2014 Auto-generated catch block
			e.printStackTrace();
		} catch (URISyntaxException e) {
			// TODO bjoern 28.10.2014 Auto-generated catch block
			e.printStackTrace();
		}
		
		URL test = new URL("http://www.google.de");
		URLConnection uc = test.openConnection();
		BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
		
		String inputLine;
		while ((inputLine = br.readLine()) != null) {
			System.out.println(inputLine);
		}
		
		Socket socket = new Socket("www.google.de", 80);
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
		bw.write("GET / HTTP/1.1\r\nHost: www.google.de\r\nConnection: close\r\nAccept-Encoding: *\r\n\r\n");
		bw.flush();
		
		br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		while ((inputLine = br.readLine()) != null) {
			System.out.println(inputLine);
		}
		
	}

}