Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libnet/DefaultProxySelector.c
41119 views
1
/*
2
* Copyright (c) 2004, 2019, 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 <dlfcn.h>
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <string.h>
30
31
#include "jni.h"
32
#include "jni_util.h"
33
#include "jvm.h"
34
#include "jvm_md.h"
35
36
#include "proxy_util.h"
37
38
#include "sun_net_spi_DefaultProxySelector.h"
39
40
41
/**
42
* These functions are used by the sun.net.spi.DefaultProxySelector class
43
* to access some platform specific settings.
44
* This is the Solaris/Linux Gnome 2.x code using the GConf-2 library.
45
* Everything is loaded dynamically so no hard link with any library exists.
46
* The GConf-2 settings used are:
47
* - /system/http_proxy/use_http_proxy boolean
48
* - /system/http_proxy/use_authentcation boolean
49
* - /system/http_proxy/use_same_proxy boolean
50
* - /system/http_proxy/host string
51
* - /system/http_proxy/authentication_user string
52
* - /system/http_proxy/authentication_password string
53
* - /system/http_proxy/port int
54
* - /system/proxy/socks_host string
55
* - /system/proxy/mode string
56
* - /system/proxy/ftp_host string
57
* - /system/proxy/secure_host string
58
* - /system/proxy/socks_port int
59
* - /system/proxy/ftp_port int
60
* - /system/proxy/secure_port int
61
* - /system/proxy/no_proxy_for list
62
*
63
* The following keys are not used in the new gnome 3
64
* - /system/http_proxy/use_http_proxy
65
* - /system/http_proxy/use_same_proxy
66
*/
67
typedef void* gconf_client_get_default_func();
68
typedef char* gconf_client_get_string_func(void *, char *, void**);
69
typedef int gconf_client_get_int_func(void*, char *, void**);
70
typedef int gconf_client_get_bool_func(void*, char *, void**);
71
typedef int gconf_init_func(int, char**, void**);
72
typedef void g_type_init_func ();
73
gconf_client_get_default_func* my_get_default_func = NULL;
74
gconf_client_get_string_func* my_get_string_func = NULL;
75
gconf_client_get_int_func* my_get_int_func = NULL;
76
gconf_client_get_bool_func* my_get_bool_func = NULL;
77
g_type_init_func* my_g_type_init_func = NULL;
78
79
80
/*
81
* GProxyResolver provides synchronous and asynchronous network
82
* proxy resolution. It is based on GSettings, which is the standard
83
* of Gnome 3, to get system settings.
84
*
85
* In the current implementation, GProxyResolver has a higher priority
86
* than the old GConf. And we only resolve the proxy synchronously. In
87
* the future, we can also do the asynchronous network proxy resolution
88
* if necessary.
89
*
90
*/
91
typedef struct _GProxyResolver GProxyResolver;
92
typedef struct _GSocketConnectable GSocketConnectable;
93
typedef struct GError GError;
94
typedef GProxyResolver* g_proxy_resolver_get_default_func();
95
typedef char** g_proxy_resolver_lookup_func();
96
typedef GSocketConnectable* g_network_address_parse_uri_func();
97
typedef const char* g_network_address_get_hostname_func();
98
typedef unsigned short g_network_address_get_port_func();
99
typedef void g_strfreev_func();
100
101
static g_proxy_resolver_get_default_func* g_proxy_resolver_get_default = NULL;
102
static g_proxy_resolver_lookup_func* g_proxy_resolver_lookup = NULL;
103
static g_network_address_parse_uri_func* g_network_address_parse_uri = NULL;
104
static g_network_address_get_hostname_func* g_network_address_get_hostname = NULL;
105
static g_network_address_get_port_func* g_network_address_get_port = NULL;
106
static g_strfreev_func* g_strfreev = NULL;
107
108
static void* gconf_client = NULL;
109
static int use_gproxyResolver = 0;
110
static int use_gconf = 0;
111
112
113
static int initGConf() {
114
/**
115
* Let's try to load GConf-2 library
116
*/
117
if (dlopen(JNI_LIB_NAME("gconf-2"), RTLD_GLOBAL | RTLD_LAZY) != NULL ||
118
dlopen(VERSIONED_JNI_LIB_NAME("gconf-2", "4"),
119
RTLD_GLOBAL | RTLD_LAZY) != NULL)
120
{
121
/*
122
* Now let's get pointer to the functions we need.
123
*/
124
my_g_type_init_func =
125
(g_type_init_func*)dlsym(RTLD_DEFAULT, "g_type_init");
126
my_get_default_func =
127
(gconf_client_get_default_func*)dlsym(RTLD_DEFAULT,
128
"gconf_client_get_default");
129
130
if (my_g_type_init_func != NULL && my_get_default_func != NULL) {
131
/**
132
* Try to connect to GConf.
133
*/
134
(*my_g_type_init_func)();
135
gconf_client = (*my_get_default_func)();
136
if (gconf_client != NULL) {
137
my_get_string_func =
138
(gconf_client_get_string_func*)dlsym(RTLD_DEFAULT,
139
"gconf_client_get_string");
140
my_get_int_func =
141
(gconf_client_get_int_func*)dlsym(RTLD_DEFAULT,
142
"gconf_client_get_int");
143
my_get_bool_func =
144
(gconf_client_get_bool_func*)dlsym(RTLD_DEFAULT,
145
"gconf_client_get_bool");
146
if (my_get_int_func != NULL && my_get_string_func != NULL &&
147
my_get_bool_func != NULL)
148
{
149
/**
150
* We did get all we need. Let's enable the System Proxy Settings.
151
*/
152
return 1;
153
}
154
}
155
}
156
}
157
return 0;
158
}
159
160
static jobjectArray getProxyByGConf(JNIEnv *env, const char* cproto,
161
const char* chost)
162
{
163
char *phost = NULL;
164
char *mode = NULL;
165
int pport = 0;
166
int use_proxy = 0;
167
int use_same_proxy = 0;
168
jobjectArray proxy_array = NULL;
169
jfieldID ptype_ID = ptype_httpID;
170
171
/* We only check manual proxy configurations */
172
mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
173
if (mode && !strcasecmp(mode, "manual")) {
174
/*
175
* Even though /system/http_proxy/use_same_proxy is no longer used,
176
* its value is set to false in gnome 3. So it is not harmful to check
177
* it first in case jdk is used with an old gnome.
178
*/
179
use_same_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_same_proxy", NULL);
180
if (use_same_proxy) {
181
phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
182
pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
183
use_proxy = (phost != NULL && pport != 0);
184
}
185
186
if (!use_proxy) {
187
/**
188
* HTTP:
189
* /system/http_proxy/use_http_proxy (boolean) - it's no longer used
190
* /system/http_proxy/host (string)
191
* /system/http_proxy/port (integer)
192
*/
193
if (strcasecmp(cproto, "http") == 0) {
194
phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
195
pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
196
use_proxy = (phost != NULL && pport != 0);
197
}
198
199
/**
200
* HTTPS:
201
* /system/proxy/mode (string) [ "manual" means use proxy settings ]
202
* /system/proxy/secure_host (string)
203
* /system/proxy/secure_port (integer)
204
*/
205
if (strcasecmp(cproto, "https") == 0) {
206
phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL);
207
pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL);
208
use_proxy = (phost != NULL && pport != 0);
209
}
210
211
/**
212
* FTP:
213
* /system/proxy/mode (string) [ "manual" means use proxy settings ]
214
* /system/proxy/ftp_host (string)
215
* /system/proxy/ftp_port (integer)
216
*/
217
if (strcasecmp(cproto, "ftp") == 0) {
218
phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL);
219
pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL);
220
use_proxy = (phost != NULL && pport != 0);
221
}
222
223
/**
224
* SOCKS:
225
* /system/proxy/mode (string) [ "manual" means use proxy settings ]
226
* /system/proxy/socks_host (string)
227
* /system/proxy/socks_port (integer)
228
*/
229
if (strcasecmp(cproto, "socks") == 0) {
230
phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL);
231
pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL);
232
use_proxy = (phost != NULL && pport != 0);
233
if (use_proxy)
234
ptype_ID = ptype_socksID;
235
}
236
}
237
}
238
239
if (use_proxy) {
240
jstring jhost;
241
char *noproxyfor;
242
char *s;
243
244
/**
245
* Check for the exclude list (aka "No Proxy For" list).
246
* It's a list of comma separated suffixes (e.g. domain name).
247
*/
248
noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL);
249
if (noproxyfor != NULL) {
250
char *tmpbuf[512];
251
s = strtok_r(noproxyfor, ", ", tmpbuf);
252
253
while (s != NULL && strlen(s) <= strlen(chost)) {
254
if (strcasecmp(chost+(strlen(chost) - strlen(s)), s) == 0) {
255
/**
256
* the URL host name matches with one of the sufixes,
257
* therefore we have to use a direct connection.
258
*/
259
use_proxy = 0;
260
break;
261
}
262
s = strtok_r(NULL, ", ", tmpbuf);
263
}
264
}
265
if (use_proxy) {
266
jobject proxy = NULL;
267
/* create a proxy array with one element. */
268
proxy_array = (*env)->NewObjectArray(env, 1, proxy_class, NULL);
269
if (proxy_array == NULL || (*env)->ExceptionCheck(env)) {
270
return NULL;
271
}
272
proxy = createProxy(env, ptype_ID, phost, pport);
273
if (proxy == NULL || (*env)->ExceptionCheck(env)) {
274
return NULL;
275
}
276
(*env)->SetObjectArrayElement(env, proxy_array, 0, proxy);
277
if ((*env)->ExceptionCheck(env)) {
278
return NULL;
279
}
280
}
281
}
282
283
return proxy_array;
284
}
285
286
static int initGProxyResolver() {
287
void *gio_handle;
288
289
gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
290
if (!gio_handle) {
291
gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
292
if (!gio_handle) {
293
return 0;
294
}
295
}
296
297
my_g_type_init_func = (g_type_init_func*)dlsym(gio_handle, "g_type_init");
298
299
g_proxy_resolver_get_default =
300
(g_proxy_resolver_get_default_func*)dlsym(gio_handle,
301
"g_proxy_resolver_get_default");
302
303
g_proxy_resolver_lookup =
304
(g_proxy_resolver_lookup_func*)dlsym(gio_handle,
305
"g_proxy_resolver_lookup");
306
307
g_network_address_parse_uri =
308
(g_network_address_parse_uri_func*)dlsym(gio_handle,
309
"g_network_address_parse_uri");
310
311
g_network_address_get_hostname =
312
(g_network_address_get_hostname_func*)dlsym(gio_handle,
313
"g_network_address_get_hostname");
314
315
g_network_address_get_port =
316
(g_network_address_get_port_func*)dlsym(gio_handle,
317
"g_network_address_get_port");
318
319
g_strfreev = (g_strfreev_func*)dlsym(gio_handle, "g_strfreev");
320
321
if (!my_g_type_init_func ||
322
!g_proxy_resolver_get_default ||
323
!g_proxy_resolver_lookup ||
324
!g_network_address_parse_uri ||
325
!g_network_address_get_hostname ||
326
!g_network_address_get_port ||
327
!g_strfreev)
328
{
329
dlclose(gio_handle);
330
return 0;
331
}
332
333
(*my_g_type_init_func)();
334
return 1;
335
}
336
337
static jobjectArray getProxyByGProxyResolver(JNIEnv *env, const char *cproto,
338
const char *chost)
339
{
340
GProxyResolver* resolver = NULL;
341
char** proxies = NULL;
342
GError *error = NULL;
343
344
size_t protoLen = 0;
345
size_t hostLen = 0;
346
char* uri = NULL;
347
348
jobjectArray proxy_array = NULL;
349
350
resolver = (*g_proxy_resolver_get_default)();
351
if (resolver == NULL) {
352
return NULL;
353
}
354
355
/* Construct the uri, cproto + "://" + chost */
356
protoLen = strlen(cproto);
357
hostLen = strlen(chost);
358
uri = malloc(protoLen + hostLen + 4);
359
if (!uri) {
360
/* Out of memory */
361
return NULL;
362
}
363
memcpy(uri, cproto, protoLen);
364
memcpy(uri + protoLen, "://", 3);
365
memcpy(uri + protoLen + 3, chost, hostLen + 1);
366
367
/*
368
* Looks into the system proxy configuration to determine what proxy,
369
* if any, to use to connect to uri. The returned proxy URIs are of
370
* the form <protocol>://[user[:password]@]host:port or direct://,
371
* where <protocol> could be http, rtsp, socks or other proxying protocol.
372
* direct:// is used when no proxy is needed.
373
*/
374
proxies = (*g_proxy_resolver_lookup)(resolver, uri, NULL, &error);
375
free(uri);
376
377
if (proxies) {
378
if (!error) {
379
int i;
380
int nr_proxies = 0;
381
char** p = proxies;
382
/* count the elements in the null terminated string vector. */
383
while (*p) {
384
nr_proxies++;
385
p++;
386
}
387
/* create a proxy array that has to be filled. */
388
proxy_array = (*env)->NewObjectArray(env, nr_proxies, proxy_class, NULL);
389
if (proxy_array != NULL && !(*env)->ExceptionCheck(env)) {
390
for (i = 0; proxies[i]; i++) {
391
if (strncmp(proxies[i], "direct://", 9)) {
392
GSocketConnectable* conn =
393
(*g_network_address_parse_uri)(proxies[i], 0,
394
&error);
395
if (conn && !error) {
396
const char *phost = NULL;
397
unsigned short pport = 0;
398
phost = (*g_network_address_get_hostname)(conn);
399
pport = (*g_network_address_get_port)(conn);
400
if (phost && pport > 0) {
401
jobject proxy = NULL;
402
jfieldID ptype_ID = ptype_httpID;
403
if (!strncmp(proxies[i], "socks", 5))
404
ptype_ID = ptype_socksID;
405
406
proxy = createProxy(env, ptype_ID, phost, pport);
407
if (proxy == NULL || (*env)->ExceptionCheck(env)) {
408
proxy_array = NULL;
409
break;
410
}
411
(*env)->SetObjectArrayElement(env, proxy_array, i, proxy);
412
if ((*env)->ExceptionCheck(env)) {
413
proxy_array = NULL;
414
break;
415
}
416
}
417
}
418
} else {
419
/* direct connection - no proxy */
420
jobject proxy = (*env)->GetStaticObjectField(env, proxy_class,
421
pr_no_proxyID);
422
if (proxy == NULL || (*env)->ExceptionCheck(env)) {
423
proxy_array = NULL;
424
break;
425
}
426
(*env)->SetObjectArrayElement(env, proxy_array, i, proxy);
427
if ((*env)->ExceptionCheck(env)) {
428
proxy_array = NULL;
429
break;
430
}
431
}
432
}
433
}
434
}
435
(*g_strfreev)(proxies);
436
}
437
438
return proxy_array;
439
}
440
441
/*
442
* Class: sun_net_spi_DefaultProxySelector
443
* Method: init
444
* Signature: ()Z
445
*/
446
JNIEXPORT jboolean JNICALL
447
Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
448
use_gproxyResolver = initGProxyResolver();
449
if (!use_gproxyResolver)
450
use_gconf = initGConf();
451
452
if (use_gproxyResolver || use_gconf) {
453
if (initJavaClass(env))
454
return JNI_TRUE;
455
}
456
return JNI_FALSE;
457
}
458
459
/*
460
* Class: sun_net_spi_DefaultProxySelector
461
* Method: getSystemProxies
462
* Signature: ([Ljava/lang/String;Ljava/lang/String;)[Ljava/net/Proxy;
463
*/
464
JNIEXPORT jobjectArray JNICALL
465
Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env,
466
jobject this,
467
jstring proto,
468
jstring host)
469
{
470
const char* cproto;
471
const char* chost;
472
473
jboolean isProtoCopy;
474
jboolean isHostCopy;
475
476
jobjectArray proxyArray = NULL;
477
478
cproto = (*env)->GetStringUTFChars(env, proto, &isProtoCopy);
479
480
if (cproto != NULL && (use_gproxyResolver || use_gconf)) {
481
chost = (*env)->GetStringUTFChars(env, host, &isHostCopy);
482
if (chost != NULL) {
483
if (use_gproxyResolver)
484
proxyArray = getProxyByGProxyResolver(env, cproto, chost);
485
else if (use_gconf)
486
proxyArray = getProxyByGConf(env, cproto, chost);
487
if (isHostCopy == JNI_TRUE)
488
(*env)->ReleaseStringUTFChars(env, host, chost);
489
}
490
if (isProtoCopy == JNI_TRUE)
491
(*env)->ReleaseStringUTFChars(env, proto, cproto);
492
}
493
return proxyArray;
494
}
495
496
497