Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/windows/native/libnet/DefaultProxySelector.c
41119 views
1
/*
2
* Copyright (c) 2004, 2017, 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
#include <windows.h>
27
#include <Winhttp.h>
28
29
#include "jni.h"
30
#include "jni_util.h"
31
#include "jvm.h"
32
33
#include "proxy_util.h"
34
35
#include "sun_net_spi_DefaultProxySelector.h"
36
37
/*
38
* These functions are used by the sun.net.spi.DefaultProxySelector class
39
* to access some platform specific settings.
40
* On Windows use WinHTTP functions to get the system settings.
41
*/
42
43
/* Keep one static session for all requests. */
44
static HINTERNET session = NULL;
45
46
/*
47
* Class: sun_net_spi_DefaultProxySelector
48
* Method: init
49
* Signature: ()Z
50
*/
51
JNIEXPORT jboolean JNICALL
52
Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
53
54
/*
55
* Get one WinHTTP session handle to initialize the WinHTTP internal data
56
* structures. Keep and use only this one for the whole life time.
57
*/
58
session = WinHttpOpen(L"Only used internal", /* we need no real agent string here */
59
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
60
WINHTTP_NO_PROXY_NAME,
61
WINHTTP_NO_PROXY_BYPASS,
62
0);
63
if (session == NULL) {
64
return JNI_FALSE;
65
}
66
67
if (!initJavaClass(env)) {
68
return JNI_FALSE;
69
}
70
71
return JNI_TRUE;
72
}
73
74
75
#define MAX_STR_LEN 1024
76
77
/* A linked list element for a proxy */
78
typedef struct list_item {
79
wchar_t *host;
80
int port;
81
struct list_item *next;
82
} list_item;
83
84
/* Free the linked list */
85
static void freeList(list_item *head) {
86
list_item *next = NULL;
87
list_item *current = head;
88
while (current != NULL) {
89
next = current->next;
90
free(current->host);
91
free(current);
92
current = next;
93
}
94
}
95
96
97
/*
98
* Creates a linked list of list_item elements that has to be freed later on.
99
* Returns the size of the array as int.
100
*/
101
static int createProxyList(LPWSTR win_proxy, const WCHAR *pproto, list_item **head) {
102
static const wchar_t separators[] = L"\t\r\n ;";
103
list_item *current = NULL;
104
int nr_elems = 0;
105
wchar_t *context = NULL;
106
wchar_t *current_proxy = NULL;
107
BOOL error = FALSE;
108
109
/*
110
* The proxy server list contains one or more of the following strings
111
* separated by semicolons or whitespace:
112
* ([<scheme>=][<scheme>"://"]<server>[":"<port>])
113
*/
114
current_proxy = wcstok_s(win_proxy, separators, &context);
115
while (current_proxy != NULL) {
116
LPWSTR pport;
117
LPWSTR phost;
118
int portVal = 0;
119
wchar_t *next_proxy = NULL;
120
list_item *proxy = NULL;
121
wchar_t* pos = NULL;
122
123
/* Filter based on the scheme, if there is one */
124
pos = wcschr(current_proxy, L'=');
125
if (pos) {
126
*pos = L'\0';
127
if (wcscmp(current_proxy, pproto) != 0) {
128
current_proxy = wcstok_s(NULL, separators, &context);
129
continue;
130
}
131
current_proxy = pos + 1;
132
}
133
134
/* Let's check for a scheme and ignore it. */
135
if ((phost = wcsstr(current_proxy, L"://")) != NULL) {
136
phost += 3;
137
} else {
138
phost = current_proxy;
139
}
140
141
/* Get the port */
142
pport = wcschr(phost, L':');
143
if (pport != NULL) {
144
*pport = 0;
145
pport++;
146
swscanf(pport, L"%d", &portVal);
147
}
148
149
proxy = (list_item *)malloc(sizeof(list_item));
150
if (proxy != NULL) {
151
proxy->next = NULL;
152
proxy->port = portVal;
153
proxy->host = _wcsdup(phost);
154
155
if (proxy->host != NULL) {
156
if (*head == NULL) {
157
*head = proxy; /* first elem */
158
}
159
if (current != NULL) {
160
current->next = proxy;
161
}
162
current = proxy;
163
nr_elems++;
164
} else {
165
free(proxy); /* cleanup */
166
}
167
}
168
/* goto next proxy if available... */
169
current_proxy = wcstok_s(NULL, separators, &context);
170
}
171
return nr_elems;
172
}
173
174
175
176
/*
177
* Class: sun_net_spi_DefaultProxySelector
178
* Method: getSystemProxies
179
* Signature: ([Ljava/lang/String;Ljava/lang/String;)[Ljava/net/Proxy;
180
*/
181
JNIEXPORT jobjectArray JNICALL
182
Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env,
183
jobject this,
184
jstring proto,
185
jstring host)
186
{
187
jobjectArray proxy_array = NULL;
188
jobject type_proxy = NULL;
189
LPCWSTR lpProto;
190
LPCWSTR lpHost;
191
list_item *head = NULL;
192
193
BOOL use_auto_proxy = FALSE;
194
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_config;
195
WINHTTP_AUTOPROXY_OPTIONS auto_proxy_options;
196
WINHTTP_PROXY_INFO proxy_info;
197
LPWSTR win_proxy = NULL;
198
LPWSTR win_bypass_proxy = NULL;
199
200
memset(&ie_proxy_config, 0, sizeof(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG));
201
memset(&auto_proxy_options, 0, sizeof(WINHTTP_AUTOPROXY_OPTIONS));
202
memset(&proxy_info, 0, sizeof(WINHTTP_PROXY_INFO));
203
204
lpHost = (*env)->GetStringChars(env, host, NULL);
205
if (lpHost == NULL) {
206
if (!(*env)->ExceptionCheck(env))
207
JNU_ThrowOutOfMemoryError(env, NULL);
208
return NULL;
209
}
210
211
lpProto = (*env)->GetStringChars(env, proto, NULL);
212
if (lpProto == NULL) {
213
(*env)->ReleaseStringChars(env, host, lpHost);
214
if (!(*env)->ExceptionCheck(env))
215
JNU_ThrowOutOfMemoryError(env, NULL);
216
return NULL;
217
}
218
219
if (WinHttpGetIEProxyConfigForCurrentUser(&ie_proxy_config) == FALSE) {
220
/* cleanup and exit */
221
(*env)->ReleaseStringChars(env, host, lpHost);
222
(*env)->ReleaseStringChars(env, proto, lpProto);
223
return NULL;
224
}
225
226
if (ie_proxy_config.fAutoDetect) {
227
/* Windows uses WPAD */
228
auto_proxy_options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP |
229
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
230
auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
231
auto_proxy_options.fAutoLogonIfChallenged = TRUE;
232
use_auto_proxy = TRUE;
233
} else if (ie_proxy_config.lpszAutoConfigUrl != NULL) {
234
/* Windows uses PAC file */
235
auto_proxy_options.lpszAutoConfigUrl = ie_proxy_config.lpszAutoConfigUrl;
236
auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
237
use_auto_proxy = TRUE;
238
} else if (ie_proxy_config.lpszProxy != NULL) {
239
/* Windows uses manually entered proxy. */
240
use_auto_proxy = FALSE;
241
win_bypass_proxy = ie_proxy_config.lpszProxyBypass;
242
win_proxy = ie_proxy_config.lpszProxy;
243
}
244
245
if (use_auto_proxy) {
246
WCHAR url[MAX_STR_LEN];
247
/* Create url for WinHttpGetProxyForUrl */
248
_snwprintf(url, sizeof(url) - 1, L"%s://%s", lpProto, lpHost);
249
/* Get proxy for URL from Windows */
250
use_auto_proxy = WinHttpGetProxyForUrl(session, &url[0], &auto_proxy_options, &proxy_info);
251
if (use_auto_proxy) {
252
win_proxy = proxy_info.lpszProxy;
253
win_bypass_proxy = proxy_info.lpszProxyBypass;
254
}
255
}
256
257
/* Check the bypass entry. */
258
if (NULL != win_bypass_proxy) {
259
/*
260
* From MSDN:
261
* The proxy bypass list contains one or more server names separated by
262
* semicolons or whitespace. The proxy bypass list can also contain the
263
* string "<local>" to indicate that all local intranet sites are
264
* bypassed. Local intranet sites are considered to be all servers that
265
* do not contain a period in their name.
266
*/
267
wchar_t *context = NULL;
268
LPWSTR s = wcstok_s(win_bypass_proxy, L"; ", &context);
269
270
while (s != NULL) {
271
size_t maxlen = wcslen(s);
272
if (wcsncmp(s, lpHost, maxlen) == 0) {
273
/*
274
* The URL host name matches with one of the prefixes, use a
275
* direct connection.
276
*/
277
goto noproxy;
278
}
279
if (wcsncmp(s, L"<local>", maxlen) == 0) {
280
/*
281
* All local intranet sites are bypassed - Microsoft consider all
282
* servers that do not contain a period in their name to be local.
283
*/
284
if (wcschr(lpHost, '.') == NULL) {
285
goto noproxy;
286
}
287
}
288
s = wcstok_s(NULL, L"; ", &context);
289
}
290
}
291
292
if (win_proxy != NULL) {
293
wchar_t *context = NULL;
294
int defport = 0;
295
int nr_elems = 0;
296
297
/* Set the default port value & proxy type from protocol. */
298
if ((wcscmp(lpProto, L"http") == 0) ||
299
(wcscmp(lpProto, L"ftp") == 0))
300
defport = 80;
301
if (wcscmp(lpProto, L"https") == 0)
302
defport = 443;
303
if (wcscmp(lpProto, L"socks") == 0) {
304
defport = 1080;
305
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
306
} else {
307
type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
308
}
309
if (type_proxy == NULL || (*env)->ExceptionCheck(env)) {
310
goto noproxy;
311
}
312
313
nr_elems = createProxyList(win_proxy, lpProto, &head);
314
if (nr_elems != 0 && head != NULL) {
315
int index = 0;
316
proxy_array = (*env)->NewObjectArray(env, nr_elems, proxy_class, NULL);
317
if (proxy_array == NULL || (*env)->ExceptionCheck(env)) {
318
goto noproxy;
319
}
320
while (head != NULL && index < nr_elems) {
321
jstring jhost;
322
jobject isa;
323
jobject proxy;
324
325
if (head->host != NULL && proxy_array != NULL) {
326
/* Let's create the appropriate Proxy object then. */
327
if (head->port == 0) {
328
head->port = defport;
329
}
330
jhost = (*env)->NewString(env, head->host, (jsize)wcslen(head->host));
331
if (jhost == NULL || (*env)->ExceptionCheck(env)) {
332
proxy_array = NULL;
333
}
334
isa = (*env)->CallStaticObjectMethod(env, isaddr_class,
335
isaddr_createUnresolvedID, jhost,
336
head->port);
337
if (isa == NULL || (*env)->ExceptionCheck(env)) {
338
proxy_array = NULL;
339
}
340
proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
341
if (proxy == NULL || (*env)->ExceptionCheck(env)) {
342
proxy_array = NULL;
343
}
344
(*env)->SetObjectArrayElement(env, proxy_array, index, proxy);
345
if ((*env)->ExceptionCheck(env)) {
346
proxy_array = NULL;
347
}
348
index++;
349
}
350
head = head->next;
351
}
352
}
353
}
354
355
noproxy:
356
if (head != NULL) {
357
freeList(head);
358
}
359
if (proxy_info.lpszProxy != NULL)
360
GlobalFree(proxy_info.lpszProxy);
361
if (proxy_info.lpszProxyBypass != NULL)
362
GlobalFree(proxy_info.lpszProxyBypass);
363
if (ie_proxy_config.lpszAutoConfigUrl != NULL)
364
GlobalFree(ie_proxy_config.lpszAutoConfigUrl);
365
if (ie_proxy_config.lpszProxy != NULL)
366
GlobalFree(ie_proxy_config.lpszProxy);
367
if (ie_proxy_config.lpszProxyBypass != NULL)
368
GlobalFree(ie_proxy_config.lpszProxyBypass);
369
if (lpHost != NULL)
370
(*env)->ReleaseStringChars(env, host, lpHost);
371
if (lpProto != NULL)
372
(*env)->ReleaseStringChars(env, proto, lpProto);
373
374
return proxy_array;
375
}
376
377