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