1 /* 2 * Copyright (c) 2004, 2010, 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 "jni.h" 28 #include "jni_util.h" 29 #include "jvm.h" 30 #include "jlong.h" 31 #include "sun_net_spi_DefaultProxySelector.h" 32 33 /** 34 * These functions are used by the sun.net.spi.DefaultProxySelector class 35 * to access some platform specific settings. 36 * This is the Windows code using the registry settings. 37 */ 38 39 static jclass proxy_class; 40 static jclass isaddr_class; 41 static jclass ptype_class; 42 static jmethodID isaddr_createUnresolvedID; 43 static jmethodID proxy_ctrID; 44 static jfieldID pr_no_proxyID; 45 static jfieldID ptype_httpID; 46 static jfieldID ptype_socksID; 47 48 /* 49 * Class: sun_net_spi_DefaultProxySelector 50 * Method: init 51 * Signature: ()Z 52 */ 53 JNIEXPORT jboolean JNICALL 54 Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) { 55 HKEY hKey; 56 LONG ret; 57 jclass cls; 58 59 /** 60 * Get all the method & field IDs for later use. 61 */ 62 cls = (*env)->FindClass(env,"java/net/Proxy"); 63 CHECK_NULL_RETURN(cls, JNI_FALSE); 64 proxy_class = (*env)->NewGlobalRef(env, cls); 65 CHECK_NULL_RETURN(proxy_class, JNI_FALSE); 66 cls = (*env)->FindClass(env,"java/net/Proxy$Type"); 67 CHECK_NULL_RETURN(cls, JNI_FALSE); 68 ptype_class = (*env)->NewGlobalRef(env, cls); 69 CHECK_NULL_RETURN(ptype_class, JNI_FALSE); 70 cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); 71 CHECK_NULL_RETURN(cls, JNI_FALSE); 72 isaddr_class = (*env)->NewGlobalRef(env, cls); 73 CHECK_NULL_RETURN(isaddr_class, JNI_FALSE); 74 proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>", 75 "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V"); 76 CHECK_NULL_RETURN(proxy_ctrID, JNI_FALSE); 77 pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY", "Ljava/net/Proxy;"); 78 CHECK_NULL_RETURN(pr_no_proxyID, JNI_FALSE); 79 ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP", "Ljava/net/Proxy$Type;"); 80 CHECK_NULL_RETURN(ptype_httpID, JNI_FALSE); 81 ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS", "Ljava/net/Proxy$Type;"); 82 CHECK_NULL_RETURN(ptype_socksID, JNI_FALSE); 83 isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class, "createUnresolved", 84 "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;"); 85 CHECK_NULL_RETURN(isaddr_createUnresolvedID, JNI_FALSE); 86 87 /** 88 * Let's see if we can find the proper Registry entry. 89 */ 90 ret = RegOpenKeyEx(HKEY_CURRENT_USER, 91 "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 92 0, KEY_READ, (PHKEY)&hKey); 93 if (ret == ERROR_SUCCESS) { 94 RegCloseKey(hKey); 95 /** 96 * It worked, we can probably rely on it then. 97 */ 98 return JNI_TRUE; 99 } 100 101 return JNI_FALSE; 102 } 103 104 #define MAX_STR_LEN 1024 105 106 /* 107 * Class: sun_net_spi_DefaultProxySelector 108 * Method: getSystemProxy 109 * Signature: ([Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy; 110 */ 111 JNIEXPORT jobject JNICALL 112 Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, 113 jobject this, 114 jstring proto, 115 jstring host) 116 { 117 jobject isa = NULL; 118 jobject proxy = NULL; 119 jobject type_proxy = NULL; 120 jobject no_proxy = NULL; 121 jboolean isCopy; 122 HKEY hKey; 123 LONG ret; 124 const char* cproto; 125 const char* urlhost; 126 char pproto[MAX_STR_LEN]; 127 char regserver[MAX_STR_LEN]; 128 char override[MAX_STR_LEN]; 129 char *s, *s2; 130 int pport = 0; 131 int defport = 0; 132 char *phost; 133 134 /** 135 * Let's opem the Registry entry. We'll check a few values in it: 136 * 137 * - ProxyEnable: 0 means no proxy, 1 means use the proxy 138 * - ProxyServer: a string that can take 2 forms: 139 * "server[:port]" 140 * or 141 * "protocol1=server[:port][;protocol2=server[:port]]..." 142 * - ProxyOverride: a string containing a list of prefixes for hostnames. 143 * e.g.: hoth;localhost;<local> 144 */ 145 ret = RegOpenKeyEx(HKEY_CURRENT_USER, 146 "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 147 0, KEY_READ, (PHKEY)&hKey); 148 if (ret == ERROR_SUCCESS) { 149 DWORD dwLen; 150 DWORD dwProxyEnabled; 151 ULONG ulType; 152 dwLen = sizeof(dwProxyEnabled); 153 154 /** 155 * Let's see if the proxy settings are to be used. 156 */ 157 ret = RegQueryValueEx(hKey, "ProxyEnable", NULL, &ulType, 158 (LPBYTE)&dwProxyEnabled, &dwLen); 159 if ((ret == ERROR_SUCCESS) && (dwProxyEnabled > 0)) { 160 /* 161 * Yes, ProxyEnable == 1 162 */ 163 dwLen = sizeof(override); 164 override[0] = 0; 165 ret = RegQueryValueEx(hKey, "ProxyOverride", NULL, &ulType, 166 (LPBYTE)&override, &dwLen); 167 dwLen = sizeof(regserver); 168 regserver[0] = 0; 169 ret = RegQueryValueEx(hKey, "ProxyServer", NULL, &ulType, 170 (LPBYTE)®server, &dwLen); 171 RegCloseKey(hKey); 172 if (ret == ERROR_SUCCESS) { 173 if (strlen(override) > 0) { 174 /** 175 * we did get ProxyServer and may have an override. 176 * So let's check the override list first, by walking down the list 177 * The semicolons (;) separated entries have to be matched with the 178 * the beginning of the hostname. 179 */ 180 s = strtok(override, "; "); 181 urlhost = (*env)->GetStringUTFChars(env, host, &isCopy); 182 while (s != NULL) { 183 if (strncmp(s, urlhost, strlen(s)) == 0) { 184 /** 185 * the URL host name matches with one of the prefixes, 186 * therefore we have to use a direct connection. 187 */ 188 if (isCopy == JNI_TRUE) 189 (*env)->ReleaseStringUTFChars(env, host, urlhost); 190 goto noproxy; 191 } 192 s = strtok(NULL, "; "); 193 } 194 if (isCopy == JNI_TRUE) 195 (*env)->ReleaseStringUTFChars(env, host, urlhost); 196 } 197 198 cproto = (*env)->GetStringUTFChars(env, proto, &isCopy); 199 if (cproto == NULL) 200 goto noproxy; 201 202 /* 203 * Set default port value & proxy type from protocol. 204 */ 205 if ((strcmp(cproto, "http") == 0) || 206 (strcmp(cproto, "ftp") == 0) || 207 (strcmp(cproto, "gopher") == 0)) 208 defport = 80; 209 if (strcmp(cproto, "https") == 0) 210 defport = 443; 211 if (strcmp(cproto, "socks") == 0) { 212 defport = 1080; 213 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID); 214 } else { 215 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); 216 } 217 218 sprintf(pproto,"%s=", cproto); 219 if (isCopy == JNI_TRUE) 220 (*env)->ReleaseStringUTFChars(env, proto, cproto); 221 /** 222 * Let's check the protocol specific form first. 223 */ 224 if ((s = strstr(regserver, pproto)) != NULL) { 225 s += strlen(pproto); 226 } else { 227 /** 228 * If we couldn't find *this* protocol but the string is in the 229 * protocol specific format, then don't use proxy 230 */ 231 if (strchr(regserver, '=') != NULL) 232 goto noproxy; 233 s = regserver; 234 } 235 s2 = strchr(s, ';'); 236 if (s2 != NULL) 237 *s2 = 0; 238 239 /** 240 * Is there a port specified? 241 */ 242 s2 = strchr(s, ':'); 243 if (s2 != NULL) { 244 *s2 = 0; 245 s2++; 246 sscanf(s2, "%d", &pport); 247 } 248 phost = s; 249 250 if (phost != NULL) { 251 /** 252 * Let's create the appropriate Proxy object then. 253 */ 254 jstring jhost; 255 if (pport == 0) 256 pport = defport; 257 jhost = (*env)->NewStringUTF(env, phost); 258 isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport); 259 proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa); 260 return proxy; 261 } 262 } 263 } else { 264 /* ProxyEnable == 0 or Query failed */ 265 /* close the handle to the registry key */ 266 RegCloseKey(hKey); 267 } 268 } 269 270 noproxy: 271 no_proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID); 272 return no_proxy; 273 } --- EOF ---