blob: eefc522e918b252023a8660c91a906126a0f76bb [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include "jni.h"
27#include "jni_util.h"
28#include "jvm.h"
29#include "jlong.h"
30#include "sun_net_spi_DefaultProxySelector.h"
31#include <dlfcn.h>
32#include <stdio.h>
33#ifdef __linux__
34#include <string.h>
35#else
36#include <strings.h>
37#endif
38
39/**
40 * These functions are used by the sun.net.spi.DefaultProxySelector class
41 * to access some platform specific settings.
42 * This is the Solaris/Linux Gnome 2.x code using the GConf-2 library.
43 * Everything is loaded dynamically so no hard link with any library exists.
44 * The GConf-2 settings used are:
45 * - /system/http_proxy/use_http_proxy boolean
46 * - /system/http_proxy/use_authentcation boolean
47 * - /system/http_proxy/host string
48 * - /system/http_proxy/authentication_user string
49 * - /system/http_proxy/authentication_password string
50 * - /system/http_proxy/port int
51 * - /system/proxy/socks_host string
52 * - /system/proxy/mode string
53 * - /system/proxy/ftp_host string
54 * - /system/proxy/secure_host string
55 * - /system/proxy/socks_port int
56 * - /system/proxy/ftp_port int
57 * - /system/proxy/secure_port int
58 * - /system/proxy/no_proxy_for list
59 * - /system/proxy/gopher_host string
60 * - /system/proxy/gopher_port int
61 */
62typedef void* gconf_client_get_default_func();
63typedef char* gconf_client_get_string_func(void *, char *, void**);
64typedef int gconf_client_get_int_func(void*, char *, void**);
65typedef int gconf_client_get_bool_func(void*, char *, void**);
66typedef int gconf_init_func(int, char**, void**);
67typedef void g_type_init_func ();
68gconf_client_get_default_func* my_get_default_func = NULL;
69gconf_client_get_string_func* my_get_string_func = NULL;
70gconf_client_get_int_func* my_get_int_func = NULL;
71gconf_client_get_bool_func* my_get_bool_func = NULL;
72gconf_init_func* my_gconf_init_func = NULL;
73g_type_init_func* my_g_type_init_func = NULL;
74
75static jclass proxy_class;
76static jclass isaddr_class;
77static jclass ptype_class;
78static jmethodID isaddr_createUnresolvedID;
79static jmethodID proxy_ctrID;
80static jfieldID pr_no_proxyID;
81static jfieldID ptype_httpID;
82static jfieldID ptype_socksID;
83
84static int gconf_ver = 0;
85static void* gconf_client = NULL;
86
87#define CHECK_NULL(X) { if ((X) == NULL) fprintf (stderr,"JNI errror at line %d\n", __LINE__); }
88
89/*
90 * Class: sun_net_spi_DefaultProxySelector
91 * Method: init
92 * Signature: ()Z
93 */
94JNIEXPORT jboolean JNICALL
95Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
96 jclass cls = NULL;
97 CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy"));
98 proxy_class = (*env)->NewGlobalRef(env, cls);
99 CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy$Type"));
100 ptype_class = (*env)->NewGlobalRef(env, cls);
101 CHECK_NULL(cls = (*env)->FindClass(env, "java/net/InetSocketAddress"));
102 isaddr_class = (*env)->NewGlobalRef(env, cls);
103 proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>", "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
104 pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY", "Ljava/net/Proxy;");
105 ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP", "Ljava/net/Proxy$Type;");
106 ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS", "Ljava/net/Proxy$Type;");
107 isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class, "createUnresolved", "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
108
109 /**
110 * Let's try to load le GConf-2 library
111 */
112 if (dlopen("libgconf-2.so", RTLD_GLOBAL | RTLD_LAZY) != NULL ||
113 dlopen("libgconf-2.so.4", RTLD_GLOBAL | RTLD_LAZY) != NULL) {
114 gconf_ver = 2;
115 }
116 if (gconf_ver > 0) {
117 /*
118 * Now let's get pointer to the functions we need.
119 */
120 my_g_type_init_func = (g_type_init_func*) dlsym(RTLD_DEFAULT, "g_type_init");
121 my_get_default_func = (gconf_client_get_default_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_default");
122 if (my_g_type_init_func != NULL && my_get_default_func != NULL) {
123 /**
124 * Try to connect to GConf.
125 */
126 (*my_g_type_init_func)();
127 gconf_client = (*my_get_default_func)();
128 if (gconf_client != NULL) {
129 my_get_string_func = (gconf_client_get_string_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_string");
130 my_get_int_func = (gconf_client_get_int_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_int");
131 my_get_bool_func = (gconf_client_get_bool_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_bool");
132 if (my_get_int_func != NULL && my_get_string_func != NULL &&
133 my_get_bool_func != NULL) {
134 /**
135 * We did get all we need. Let's enable the System Proxy Settings.
136 */
137 return JNI_TRUE;
138 }
139 }
140 }
141 }
142 return JNI_FALSE;
143}
144
145
146/*
147 * Class: sun_net_spi_DefaultProxySelector
148 * Method: getSystemProxy
149 * Signature: ([Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;
150 */
151JNIEXPORT jobject JNICALL
152Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env,
153 jobject this,
154 jstring proto,
155 jstring host)
156{
157 char *phost = NULL;
158 char *mode = NULL;
159 int pport = 0;
160 int use_proxy;
161 const char* urlhost;
162 jobject isa = NULL;
163 jobject proxy = NULL;
164 jobject type_proxy = NULL;
165 jobject no_proxy = NULL;
166 const char *cproto;
167 jboolean isCopy;
168
169 if (gconf_ver > 0) {
170 if (gconf_client == NULL) {
171 (*my_g_type_init_func)();
172 gconf_client = (*my_get_default_func)();
173 }
174 if (gconf_client != NULL) {
175 cproto = (*env)->GetStringUTFChars(env, proto, &isCopy);
176 if (cproto != NULL) {
177 /**
178 * We will have to check protocol by protocol as they do use different
179 * entries.
180 */
181
182 /**
183 * HTTP:
184 * /system/http_proxy/use_http_proxy (boolean)
185 * /system/http_proxy/host (string)
186 * /system/http_proxy/port (integer)
187 */
188 if (strcasecmp(cproto, "http") == 0) {
189 use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL);
190 if (use_proxy) {
191 phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
192 pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
193 CHECK_NULL(type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID));
194 }
195 }
196
197 /**
198 * HTTPS:
199 * /system/proxy/mode (string) [ "manual" means use proxy settings ]
200 * /system/proxy/secure_host (string)
201 * /system/proxy/secure_port (integer)
202 */
203 if (strcasecmp(cproto, "https") == 0) {
204 mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
205 if (mode != NULL && (strcasecmp(mode,"manual") == 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);
209 if (use_proxy)
210 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
211 }
212 }
213
214 /**
215 * FTP:
216 * /system/proxy/mode (string) [ "manual" means use proxy settings ]
217 * /system/proxy/ftp_host (string)
218 * /system/proxy/ftp_port (integer)
219 */
220 if (strcasecmp(cproto, "ftp") == 0) {
221 mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
222 if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
223 phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL);
224 pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL);
225 use_proxy = (phost != NULL);
226 if (use_proxy)
227 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
228 }
229 }
230
231 /**
232 * GOPHER:
233 * /system/proxy/mode (string) [ "manual" means use proxy settings ]
234 * /system/proxy/gopher_host (string)
235 * /system/proxy/gopher_port (integer)
236 */
237 if (strcasecmp(cproto, "gopher") == 0) {
238 mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
239 if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
240 phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL);
241 pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL);
242 use_proxy = (phost != NULL);
243 if (use_proxy)
244 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
245 }
246 }
247
248 /**
249 * SOCKS:
250 * /system/proxy/mode (string) [ "manual" means use proxy settings ]
251 * /system/proxy/socks_host (string)
252 * /system/proxy/socks_port (integer)
253 */
254 if (strcasecmp(cproto, "socks") == 0) {
255 mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
256 if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
257 phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL);
258 pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL);
259 use_proxy = (phost != NULL);
260 if (use_proxy)
261 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
262 }
263 }
264
265 if (isCopy == JNI_TRUE)
266 (*env)->ReleaseStringUTFChars(env, proto, cproto);
267
268 if (use_proxy && (phost != NULL)) {
269 jstring jhost;
270 char *noproxyfor;
271 char *s;
272
273 /**
274 * check for the exclude list (aka "No Proxy For" list).
275 * It's a list of comma separated suffixes (e.g. domain name).
276 */
277 noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL);
278 if (noproxyfor != NULL) {
279 char *tmpbuf[512];
280
281 s = strtok_r(noproxyfor, ", ", tmpbuf);
282 urlhost = (*env)->GetStringUTFChars(env, host, &isCopy);
283 if (urlhost != NULL) {
284 while (s != NULL && strlen(s) <= strlen(urlhost)) {
285 if (strcasecmp(urlhost+(strlen(urlhost) - strlen(s)), s) == 0) {
286 /**
287 * the URL host name matches with one of the sufixes,
288 * therefore we have to use a direct connection.
289 */
290 use_proxy = 0;
291 break;
292 }
293 s = strtok_r(NULL, ", ", tmpbuf);
294 }
295 if (isCopy == JNI_TRUE)
296 (*env)->ReleaseStringUTFChars(env, host, urlhost);
297 }
298 }
299 if (use_proxy) {
300 jhost = (*env)->NewStringUTF(env, phost);
301 isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport);
302 proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
303 return proxy;
304 }
305 }
306 }
307 }
308 }
309
310 CHECK_NULL(no_proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID));
311 return no_proxy;
312}