Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java
41159 views
1
/*
2
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.net.spi;
27
28
import java.net.InetSocketAddress;
29
import java.net.Proxy;
30
import java.net.ProxySelector;
31
import java.net.SocketAddress;
32
import java.net.URI;
33
import java.util.Collections;
34
import java.util.List;
35
import java.io.IOException;
36
import java.security.AccessController;
37
import java.security.PrivilegedAction;
38
import java.util.StringJoiner;
39
import java.util.regex.Pattern;
40
import java.util.stream.Stream;
41
import sun.net.NetProperties;
42
import sun.net.SocksProxy;
43
import static java.util.regex.Pattern.quote;
44
import static java.util.stream.Collectors.collectingAndThen;
45
import static java.util.stream.Collectors.toList;
46
47
/**
48
* Supports proxy settings using system properties This proxy selector
49
* provides backward compatibility with the old http protocol handler
50
* as far as how proxy is set
51
*
52
* Most of the implementation copied from the old http protocol handler
53
*
54
* Supports http/https/ftp.proxyHost, http/https/ftp.proxyPort,
55
* proxyHost, proxyPort, and http/https/ftp.nonProxyHost, and socks.
56
*/
57
public class DefaultProxySelector extends ProxySelector {
58
59
/**
60
* This is where we define all the valid System Properties we have to
61
* support for each given protocol.
62
* The format of this 2 dimensional array is :
63
* - 1 row per protocol (http, ftp, ...)
64
* - 1st element of each row is the protocol name
65
* - subsequent elements are prefixes for Host & Port properties
66
* listed in order of priority.
67
* Example:
68
* {"ftp", "ftp.proxy", "ftpProxy", "proxy", "socksProxy"},
69
* means for FTP we try in that oder:
70
* + ftp.proxyHost & ftp.proxyPort
71
* + ftpProxyHost & ftpProxyPort
72
* + proxyHost & proxyPort
73
* + socksProxyHost & socksProxyPort
74
*
75
* Note that the socksProxy should *always* be the last on the list
76
*/
77
static final String[][] props = {
78
/*
79
* protocol, Property prefix 1, Property prefix 2, ...
80
*/
81
{"http", "http.proxy", "proxy", "socksProxy"},
82
{"https", "https.proxy", "proxy", "socksProxy"},
83
{"ftp", "ftp.proxy", "ftpProxy", "proxy", "socksProxy"},
84
{"socket", "socksProxy"}
85
};
86
87
private static final String SOCKS_PROXY_VERSION = "socksProxyVersion";
88
89
private static boolean hasSystemProxies = false;
90
91
private static final List<Proxy> NO_PROXY_LIST = List.of(Proxy.NO_PROXY);
92
93
static {
94
final String key = "java.net.useSystemProxies";
95
@SuppressWarnings("removal")
96
Boolean b = AccessController.doPrivileged(
97
new PrivilegedAction<Boolean>() {
98
public Boolean run() {
99
return NetProperties.getBoolean(key);
100
}});
101
if (b != null && b.booleanValue()) {
102
jdk.internal.loader.BootLoader.loadLibrary("net");
103
hasSystemProxies = init();
104
}
105
}
106
107
@SuppressWarnings("removal")
108
public static int socksProxyVersion() {
109
return AccessController.doPrivileged(
110
new PrivilegedAction<Integer>() {
111
@Override public Integer run() {
112
return NetProperties.getInteger(SOCKS_PROXY_VERSION, 5);
113
}
114
});
115
}
116
117
/**
118
* How to deal with "non proxy hosts":
119
* since we do have to generate a pattern we don't want to do that if
120
* it's not necessary. Therefore we do cache the result, on a per-protocol
121
* basis, and change it only when the "source", i.e. the system property,
122
* did change.
123
*/
124
125
static class NonProxyInfo {
126
// Default value for nonProxyHosts, this provides backward compatibility
127
// by excluding localhost and its litteral notations.
128
static final String defStringVal = "localhost|127.*|[::1]|0.0.0.0|[::0]";
129
130
String hostsSource;
131
Pattern pattern;
132
final String property;
133
final String defaultVal;
134
static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal);
135
static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal);
136
static NonProxyInfo socksNonProxyInfo = new NonProxyInfo("socksNonProxyHosts", null, null, defStringVal);
137
138
NonProxyInfo(String p, String s, Pattern pattern, String d) {
139
property = p;
140
hostsSource = s;
141
this.pattern = pattern;
142
defaultVal = d;
143
}
144
}
145
146
147
/**
148
* select() method. Where all the hard work is done.
149
* Build a list of proxies depending on URI.
150
* Since we're only providing compatibility with the system properties
151
* from previous releases (see list above), that list will typically
152
* contain one single proxy, default being NO_PROXY.
153
* If we can get a system proxy it might contain more entries.
154
*/
155
public java.util.List<Proxy> select(URI uri) {
156
if (uri == null) {
157
throw new IllegalArgumentException("URI can't be null.");
158
}
159
String protocol = uri.getScheme();
160
String host = uri.getHost();
161
162
if (host == null) {
163
// This is a hack to ensure backward compatibility in two
164
// cases: 1. hostnames contain non-ascii characters,
165
// internationalized domain names. in which case, URI will
166
// return null, see BugID 4957669; 2. Some hostnames can
167
// contain '_' chars even though it's not supposed to be
168
// legal, in which case URI will return null for getHost,
169
// but not for getAuthority() See BugID 4913253
170
String auth = uri.getAuthority();
171
if (auth != null) {
172
int i;
173
i = auth.indexOf('@');
174
if (i >= 0) {
175
auth = auth.substring(i+1);
176
}
177
i = auth.lastIndexOf(':');
178
if (i >= 0) {
179
auth = auth.substring(0,i);
180
}
181
host = auth;
182
}
183
}
184
185
if (protocol == null || host == null) {
186
throw new IllegalArgumentException("protocol = "+protocol+" host = "+host);
187
}
188
189
NonProxyInfo pinfo = null;
190
191
if ("http".equalsIgnoreCase(protocol)) {
192
pinfo = NonProxyInfo.httpNonProxyInfo;
193
} else if ("https".equalsIgnoreCase(protocol)) {
194
// HTTPS uses the same property as HTTP, for backward
195
// compatibility
196
pinfo = NonProxyInfo.httpNonProxyInfo;
197
} else if ("ftp".equalsIgnoreCase(protocol)) {
198
pinfo = NonProxyInfo.ftpNonProxyInfo;
199
} else if ("socket".equalsIgnoreCase(protocol)) {
200
pinfo = NonProxyInfo.socksNonProxyInfo;
201
}
202
203
/**
204
* Let's check the System properties for that protocol
205
*/
206
final String proto = protocol;
207
final NonProxyInfo nprop = pinfo;
208
final String urlhost = host.toLowerCase();
209
210
/**
211
* This is one big doPrivileged call, but we're trying to optimize
212
* the code as much as possible. Since we're checking quite a few
213
* System properties it does help having only 1 call to doPrivileged.
214
* Be mindful what you do in here though!
215
*/
216
@SuppressWarnings("removal")
217
Proxy[] proxyArray = AccessController.doPrivileged(
218
new PrivilegedAction<Proxy[]>() {
219
public Proxy[] run() {
220
int i, j;
221
String phost = null;
222
int pport = 0;
223
String nphosts = null;
224
InetSocketAddress saddr = null;
225
226
// Then let's walk the list of protocols in our array
227
for (i=0; i<props.length; i++) {
228
if (props[i][0].equalsIgnoreCase(proto)) {
229
for (j = 1; j < props[i].length; j++) {
230
/* System.getProp() will give us an empty
231
* String, "" for a defined but "empty"
232
* property.
233
*/
234
phost = NetProperties.get(props[i][j]+"Host");
235
if (phost != null && phost.length() != 0)
236
break;
237
}
238
if (phost == null || phost.isEmpty()) {
239
/**
240
* No system property defined for that
241
* protocol. Let's check System Proxy
242
* settings (Gnome, MacOsX & Windows) if
243
* we were instructed to.
244
*/
245
if (hasSystemProxies) {
246
String sproto;
247
if (proto.equalsIgnoreCase("socket"))
248
sproto = "socks";
249
else
250
sproto = proto;
251
return getSystemProxies(sproto, urlhost);
252
}
253
return null;
254
}
255
// If a Proxy Host is defined for that protocol
256
// Let's get the NonProxyHosts property
257
if (nprop != null) {
258
nphosts = NetProperties.get(nprop.property);
259
synchronized (nprop) {
260
if (nphosts == null) {
261
if (nprop.defaultVal != null) {
262
nphosts = nprop.defaultVal;
263
} else {
264
nprop.hostsSource = null;
265
nprop.pattern = null;
266
}
267
} else if (!nphosts.isEmpty()) {
268
// add the required default patterns
269
// but only if property no set. If it
270
// is empty, leave empty.
271
nphosts += "|" + NonProxyInfo
272
.defStringVal;
273
}
274
if (nphosts != null) {
275
if (!nphosts.equals(nprop.hostsSource)) {
276
nprop.pattern = toPattern(nphosts);
277
nprop.hostsSource = nphosts;
278
}
279
}
280
if (shouldNotUseProxyFor(nprop.pattern, urlhost)) {
281
return null;
282
}
283
}
284
}
285
// We got a host, let's check for port
286
287
pport = NetProperties.getInteger(props[i][j]+"Port", 0).intValue();
288
if (pport == 0 && j < (props[i].length - 1)) {
289
// Can't find a port with same prefix as Host
290
// AND it's not a SOCKS proxy
291
// Let's try the other prefixes for that proto
292
for (int k = 1; k < (props[i].length - 1); k++) {
293
if ((k != j) && (pport == 0))
294
pport = NetProperties.getInteger(props[i][k]+"Port", 0).intValue();
295
}
296
}
297
298
// Still couldn't find a port, let's use default
299
if (pport == 0) {
300
if (j == (props[i].length - 1)) // SOCKS
301
pport = defaultPort("socket");
302
else
303
pport = defaultPort(proto);
304
}
305
// We did find a proxy definition.
306
// Let's create the address, but don't resolve it
307
// as this will be done at connection time
308
saddr = InetSocketAddress.createUnresolved(phost, pport);
309
// Socks is *always* the last on the list.
310
if (j == (props[i].length - 1)) {
311
return new Proxy[] {SocksProxy.create(saddr, socksProxyVersion())};
312
}
313
return new Proxy[] {new Proxy(Proxy.Type.HTTP, saddr)};
314
}
315
}
316
return null;
317
}});
318
319
320
if (proxyArray != null) {
321
// Remove duplicate entries, while preserving order.
322
return Stream.of(proxyArray).distinct().collect(
323
collectingAndThen(toList(), Collections::unmodifiableList));
324
}
325
326
// If no specific proxy was found, return a standard list containing
327
// only one NO_PROXY entry.
328
return NO_PROXY_LIST;
329
}
330
331
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
332
if (uri == null || sa == null || ioe == null) {
333
throw new IllegalArgumentException("Arguments can't be null.");
334
}
335
// ignored
336
}
337
338
339
private int defaultPort(String protocol) {
340
if ("http".equalsIgnoreCase(protocol)) {
341
return 80;
342
} else if ("https".equalsIgnoreCase(protocol)) {
343
return 443;
344
} else if ("ftp".equalsIgnoreCase(protocol)) {
345
return 80;
346
} else if ("socket".equalsIgnoreCase(protocol)) {
347
return 1080;
348
} else {
349
return -1;
350
}
351
}
352
353
private static native boolean init();
354
private synchronized native Proxy[] getSystemProxies(String protocol, String host);
355
356
/**
357
* @return {@code true} if given this pattern for non-proxy hosts and this
358
* urlhost the proxy should NOT be used to access this urlhost
359
*/
360
static boolean shouldNotUseProxyFor(Pattern pattern, String urlhost) {
361
if (pattern == null || urlhost.isEmpty())
362
return false;
363
boolean matches = pattern.matcher(urlhost).matches();
364
return matches;
365
}
366
367
/**
368
* @param mask non-null mask
369
* @return {@link java.util.regex.Pattern} corresponding to this mask
370
* or {@code null} in case mask should not match anything
371
*/
372
static Pattern toPattern(String mask) {
373
boolean disjunctionEmpty = true;
374
StringJoiner joiner = new StringJoiner("|");
375
for (String disjunct : mask.split("\\|")) {
376
if (disjunct.isEmpty())
377
continue;
378
disjunctionEmpty = false;
379
String regex = disjunctToRegex(disjunct.toLowerCase());
380
joiner.add(regex);
381
}
382
return disjunctionEmpty ? null : Pattern.compile(joiner.toString());
383
}
384
385
/**
386
* @param disjunct non-null mask disjunct
387
* @return java regex string corresponding to this mask
388
*/
389
static String disjunctToRegex(String disjunct) {
390
String regex;
391
if (disjunct.equals("*")) {
392
regex = ".*";
393
} else if (disjunct.startsWith("*") && disjunct.endsWith("*")) {
394
regex = ".*" + quote(disjunct.substring(1, disjunct.length() - 1)) + ".*";
395
} else if (disjunct.startsWith("*")) {
396
regex = ".*" + quote(disjunct.substring(1));
397
} else if (disjunct.endsWith("*")) {
398
regex = quote(disjunct.substring(0, disjunct.length() - 1)) + ".*";
399
} else {
400
regex = quote(disjunct);
401
}
402
return regex;
403
}
404
}
405
406