/* * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ #include "jni.h" #include "jni_util.h" #include "jvm.h" #include "jlong.h" #include "sun_net_spi_DefaultProxySelector.h" #include #include #ifdef __linux__ #include #else #include #endif /** * These functions are used by the sun.net.spi.DefaultProxySelector class * to access some platform specific settings. * This is the Solaris/Linux Gnome 2.x code using the GConf-2 library. * Everything is loaded dynamically so no hard link with any library exists. * The GConf-2 settings used are: * - /system/http_proxy/use_http_proxy boolean * - /system/http_proxy/use_authentcation boolean * - /system/http_proxy/use_same_proxy boolean * - /system/http_proxy/host string * - /system/http_proxy/authentication_user string * - /system/http_proxy/authentication_password string * - /system/http_proxy/port int * - /system/proxy/socks_host string * - /system/proxy/mode string * - /system/proxy/ftp_host string * - /system/proxy/secure_host string * - /system/proxy/socks_port int * - /system/proxy/ftp_port int * - /system/proxy/secure_port int * - /system/proxy/no_proxy_for list * - /system/proxy/gopher_host string * - /system/proxy/gopher_port int */ typedef void* gconf_client_get_default_func(); typedef char* gconf_client_get_string_func(void *, char *, void**); typedef int gconf_client_get_int_func(void*, char *, void**); typedef int gconf_client_get_bool_func(void*, char *, void**); typedef int gconf_init_func(int, char**, void**); typedef void g_type_init_func (); gconf_client_get_default_func* my_get_default_func = NULL; gconf_client_get_string_func* my_get_string_func = NULL; gconf_client_get_int_func* my_get_int_func = NULL; gconf_client_get_bool_func* my_get_bool_func = NULL; gconf_init_func* my_gconf_init_func = NULL; g_type_init_func* my_g_type_init_func = NULL; static jclass proxy_class; static jclass isaddr_class; static jclass ptype_class; static jmethodID isaddr_createUnresolvedID; static jmethodID proxy_ctrID; static jfieldID pr_no_proxyID; static jfieldID ptype_httpID; static jfieldID ptype_socksID; static int gconf_ver = 0; static void* gconf_client = NULL; #define CHECK_NULL(X) { if ((X) == NULL) fprintf (stderr,"JNI errror at line %d\n", __LINE__); } /* * Class: sun_net_spi_DefaultProxySelector * Method: init * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) { jclass cls = NULL; CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy")); proxy_class = (*env)->NewGlobalRef(env, cls); CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy$Type")); ptype_class = (*env)->NewGlobalRef(env, cls); CHECK_NULL(cls = (*env)->FindClass(env, "java/net/InetSocketAddress")); isaddr_class = (*env)->NewGlobalRef(env, cls); proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "", "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V"); pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY", "Ljava/net/Proxy;"); ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP", "Ljava/net/Proxy$Type;"); ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS", "Ljava/net/Proxy$Type;"); isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class, "createUnresolved", "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;"); /** * Let's try to load le GConf-2 library */ if (dlopen("libgconf-2.so", RTLD_GLOBAL | RTLD_LAZY) != NULL || dlopen("libgconf-2.so.4", RTLD_GLOBAL | RTLD_LAZY) != NULL) { gconf_ver = 2; } if (gconf_ver > 0) { /* * Now let's get pointer to the functions we need. */ my_g_type_init_func = (g_type_init_func*) dlsym(RTLD_DEFAULT, "g_type_init"); my_get_default_func = (gconf_client_get_default_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_default"); if (my_g_type_init_func != NULL && my_get_default_func != NULL) { /** * Try to connect to GConf. */ (*my_g_type_init_func)(); gconf_client = (*my_get_default_func)(); if (gconf_client != NULL) { my_get_string_func = (gconf_client_get_string_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_string"); my_get_int_func = (gconf_client_get_int_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_int"); my_get_bool_func = (gconf_client_get_bool_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_bool"); if (my_get_int_func != NULL && my_get_string_func != NULL && my_get_bool_func != NULL) { /** * We did get all we need. Let's enable the System Proxy Settings. */ return JNI_TRUE; } } } } return JNI_FALSE; } /* * Class: sun_net_spi_DefaultProxySelector * Method: getSystemProxy * Signature: ([Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy; */ JNIEXPORT jobject JNICALL Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, jobject this, jstring proto, jstring host) { char *phost = NULL; char *mode = NULL; int pport = 0; int use_proxy; int use_same_proxy = 0; const char* urlhost; jobject isa = NULL; jobject proxy = NULL; jobject type_proxy = NULL; jobject no_proxy = NULL; const char *cproto; jboolean isCopy; if (gconf_ver > 0) { if (gconf_client == NULL) { (*my_g_type_init_func)(); gconf_client = (*my_get_default_func)(); } if (gconf_client != NULL) { cproto = (*env)->GetStringUTFChars(env, proto, &isCopy); if (cproto != NULL) { /** * We will have to check protocol by protocol as they do use different * entries. */ use_same_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_same_proxy", NULL); if (use_same_proxy) { use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL); if (use_proxy) { phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL); pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL); } } /** * HTTP: * /system/http_proxy/use_http_proxy (boolean) * /system/http_proxy/host (string) * /system/http_proxy/port (integer) */ if (strcasecmp(cproto, "http") == 0) { use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL); if (use_proxy) { if (!use_same_proxy) { phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL); pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL); } CHECK_NULL(type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID)); } } /** * HTTPS: * /system/proxy/mode (string) [ "manual" means use proxy settings ] * /system/proxy/secure_host (string) * /system/proxy/secure_port (integer) */ if (strcasecmp(cproto, "https") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { if (!use_same_proxy) { phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL); pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL); } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); } } /** * FTP: * /system/proxy/mode (string) [ "manual" means use proxy settings ] * /system/proxy/ftp_host (string) * /system/proxy/ftp_port (integer) */ if (strcasecmp(cproto, "ftp") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { if (!use_same_proxy) { phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL); pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL); } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); } } /** * GOPHER: * /system/proxy/mode (string) [ "manual" means use proxy settings ] * /system/proxy/gopher_host (string) * /system/proxy/gopher_port (integer) */ if (strcasecmp(cproto, "gopher") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { if (!use_same_proxy) { phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL); pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL); } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); } } /** * SOCKS: * /system/proxy/mode (string) [ "manual" means use proxy settings ] * /system/proxy/socks_host (string) * /system/proxy/socks_port (integer) */ if (strcasecmp(cproto, "socks") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { if (!use_same_proxy) { phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL); pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL); } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID); } } if (isCopy == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, proto, cproto); if (use_proxy && (phost != NULL)) { jstring jhost; char *noproxyfor; char *s; /** * check for the exclude list (aka "No Proxy For" list). * It's a list of comma separated suffixes (e.g. domain name). */ noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL); if (noproxyfor != NULL) { char *tmpbuf[512]; s = strtok_r(noproxyfor, ", ", tmpbuf); urlhost = (*env)->GetStringUTFChars(env, host, &isCopy); if (urlhost != NULL) { while (s != NULL && strlen(s) <= strlen(urlhost)) { if (strcasecmp(urlhost+(strlen(urlhost) - strlen(s)), s) == 0) { /** * the URL host name matches with one of the sufixes, * therefore we have to use a direct connection. */ use_proxy = 0; break; } s = strtok_r(NULL, ", ", tmpbuf); } if (isCopy == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, host, urlhost); } } if (use_proxy) { jhost = (*env)->NewStringUTF(env, phost); isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport); proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa); return proxy; } } } } } CHECK_NULL(no_proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID)); return no_proxy; }