summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/btr/proxy/util/ProxyUtil.java
blob: 857b680d292126f04a480be5ee6a86435c82d3c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package com.btr.proxy.util;

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import com.btr.proxy.selector.fixed.FixedProxySelector;
import com.btr.proxy.selector.pac.PacProxySelector;
import com.btr.proxy.selector.pac.PacScriptSource;
import com.btr.proxy.selector.pac.UrlPacScriptSource;
import com.btr.proxy.util.Logger.LogLevel;

/*****************************************************************************
 * Small helper class for some common utility methods.
 * 
 * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
 ****************************************************************************/

public class ProxyUtil {

	public static final int DEFAULT_HTTP_PROXY_PORT = 80;
	
	public static final int DEFAULT_SOCKS_PROXY_PORT = 1080;

	private static List<Proxy> noProxyList;

	/*************************************************************************
	 * Parse host and port out of a proxy variable.
	 * 
	 * @param proxyVar the proxy string. example: http://192.168.10.9:8080/
	 * @return a FixedProxySelector using this settings, null on parse error.
	 ************************************************************************/

	public static FixedProxySelector parseProxySettings(String proxyVar) {
		return parseProxySettings(proxyVar, Proxy.Type.HTTP, 0);
	}
	
	public static FixedProxySelector parseProxySettings(String proxyVar, Proxy.Type fallback, int fallbackPort) {
		Proxy proxy = parseProxyString(proxyVar, fallback, fallbackPort);
		if (proxy == null)
			return null;
		return new FixedProxySelector(proxy);
	}
	
	public static Proxy parseProxyString(String proxyVar, Proxy.Type fallback, int fallbackPort) {
		if (proxyVar == null || proxyVar.trim().length() == 0) {
			return null;
		}
		
		Proxy.Type type;
		int port = -1;
		String host;
		
		int protoIdx = proxyVar.indexOf(":/");
		if (protoIdx == -1) {
			type = fallback;
		} else {
			String stype = proxyVar.substring(0, protoIdx);
			proxyVar = proxyVar.substring(protoIdx + 2);
			proxyVar = proxyVar.replaceAll("(^/+|/+$)", "");
			if (stype.isEmpty()) {
				type = fallback;
			} else if (stype.startsWith("socks")) {
				type = Proxy.Type.SOCKS;
			} else {
				type = Proxy.Type.HTTP;
			}
		}
		
		int portIdx = proxyVar.lastIndexOf(':');
		if (portIdx == -1) {
			host = proxyVar;
		} else {
			String portStr = proxyVar.substring(portIdx + 1).replaceAll("[^0-9]", "");
			if (!portStr.isEmpty()) {
				port = MiscUtil.parseInt(portStr);
			}
			host = proxyVar.substring(0, portIdx);
		}
			
		if (port == -1 && fallbackPort > 0) {
			port = fallbackPort;
		}
		if (port < 0 || port > 65535) {
			if (type == Proxy.Type.HTTP) {
				port = DEFAULT_HTTP_PROXY_PORT;
			} else if (type == Proxy.Type.SOCKS) {
				port = DEFAULT_SOCKS_PROXY_PORT;
			}
		}
		return new Proxy(type, InetSocketAddress.createUnresolved(host.trim(), port));
	}

	/*************************************************************************
	 * Gets an unmodifiable proxy list that will have as it's only entry an
	 * DIRECT proxy.
	 * 
	 * @return a list with a DIRECT proxy in it.
	 ************************************************************************/

	public static synchronized List<Proxy> noProxyList() {
		if (noProxyList == null) {
			ArrayList<Proxy> list = new ArrayList<Proxy>(1);
			list.add(Proxy.NO_PROXY);
			noProxyList = Collections.unmodifiableList(list);
		}
		return noProxyList;
	}

	/*************************************************************************
	 * Build a PAC proxy selector for the given URL.
	 * 
	 * @param url to fetch the PAC script from.
	 * @return a PacProxySelector or null if it is not possible to build a
	 *         working
	 *         selector.
	 ************************************************************************/

	public static PacProxySelector buildPacSelectorForUrl(final String url) {
		Logger.log(ProxyUtil.class, LogLevel.TRACE, "Fetching PAC script from {0}", url);
		final AtomicReference<PacProxySelector> result = new AtomicReference<>();
		Thread t = new Thread() {
			@Override
			public void run() {
				PacScriptSource pacSource = new UrlPacScriptSource(url);
				if (pacSource.isScriptValid()) {
					result.set(new PacProxySelector(pacSource));
				}
			}
		};
		t.start();
		try {
			t.join(2500);
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
		return result.get();
	}

}