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 char *ctx = NULL; 131 int pport = 0; 132 int defport = 0; 133 char *phost; 134 135 /** 136 * Let's open the Registry entry. We'll check a few values in it: 137 * 138 * - ProxyEnable: 0 means no proxy, 1 means use the proxy 139 * - ProxyServer: a string that can take 2 forms: 140 * "server[:port]" 141 * or 142 * "protocol1=server[:port][;protocol2=server[:port]]..." 143 * - ProxyOverride: a string containing a list of prefixes for hostnames. 144 * e.g.: hoth;localhost;<local> 145 */ 146 ret = RegOpenKeyEx(HKEY_CURRENT_USER, 147 "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 148 0, KEY_READ, (PHKEY)&hKey); 149 if (ret == ERROR_SUCCESS) { 150 DWORD dwLen; 151 DWORD dwProxyEnabled; 152 ULONG ulType; 153 dwLen = sizeof(dwProxyEnabled); 154 155 /** 156 * Let's see if the proxy settings are to be used. 157 */ 158 ret = RegQueryValueEx(hKey, "ProxyEnable", NULL, &ulType, 159 (LPBYTE)&dwProxyEnabled, &dwLen); 160 if ((ret == ERROR_SUCCESS) && (dwProxyEnabled > 0)) { 161 /* 162 * Yes, ProxyEnable == 1 163 */ 164 dwLen = sizeof(override); 165 override[0] = 0; 166 ret = RegQueryValueEx(hKey, "ProxyOverride", NULL, &ulType, 167 (LPBYTE)&override, &dwLen); 168 dwLen = sizeof(regserver); 169 regserver[0] = 0; 170 ret = RegQueryValueEx(hKey, "ProxyServer", NULL, &ulType, 171 (LPBYTE)®server, &dwLen); 172 RegCloseKey(hKey); 173 if (ret == ERROR_SUCCESS) { 174 if (strlen(override) > 0) { 175 /** 176 * we did get ProxyServer and may have an override. 177 * So let's check the override list first, by walking down the list 178 * The semicolons (;) separated entries have to be matched with the 179 * the beginning of the hostname. 180 */ 181 s = strtok_s(override, "; ", &ctx); 182 urlhost = (*env)->GetStringUTFChars(env, host, &isCopy); 183 if (urlhost == NULL) { 184 if (!(*env)->ExceptionCheck(env)) 185 JNU_ThrowOutOfMemoryError(env, NULL); 186 return NULL; 187 } 188 while (s != NULL) { 189 if (strncmp(s, urlhost, strlen(s)) == 0) { 190 /** 191 * the URL host name matches with one of the prefixes, 192 * therefore we have to use a direct connection. 193 */ 194 if (isCopy == JNI_TRUE) 195 (*env)->ReleaseStringUTFChars(env, host, urlhost); 196 goto noproxy; 197 } 198 s = strtok_s(NULL, "; ", &ctx); 199 } 200 if (isCopy == JNI_TRUE) 201 (*env)->ReleaseStringUTFChars(env, host, urlhost); 202 } 203 204 cproto = (*env)->GetStringUTFChars(env, proto, &isCopy); 205 if (cproto == NULL) { 206 if (!(*env)->ExceptionCheck(env)) 207 JNU_ThrowOutOfMemoryError(env, NULL); 208 return NULL; 209 } 210 211 /* 212 * Set default port value & proxy type from protocol. 213 */ 214 if ((strcmp(cproto, "http") == 0) || 215 (strcmp(cproto, "ftp") == 0) || 216 (strcmp(cproto, "gopher") == 0)) 217 defport = 80; 218 if (strcmp(cproto, "https") == 0) 219 defport = 443; 220 if (strcmp(cproto, "socks") == 0) { 221 defport = 1080; 222 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID); 223 } else { 224 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); 225 } 226 227 sprintf(pproto,"%s=", cproto); 228 if (isCopy == JNI_TRUE) 229 (*env)->ReleaseStringUTFChars(env, proto, cproto); 230 /** 231 * Let's check the protocol specific form first. 232 */ 233 if ((s = strstr(regserver, pproto)) != NULL) { 234 s += strlen(pproto); 235 } else { 236 /** 237 * If we couldn't find *this* protocol but the string is in the 238 * protocol specific format, then don't use proxy 239 */ 240 if (strchr(regserver, '=') != NULL) 241 goto noproxy; 242 s = regserver; 243 } 244 s2 = strchr(s, ';'); 245 if (s2 != NULL) 246 *s2 = 0; 247 248 /** 249 * Is there a port specified? 250 */ 251 s2 = strchr(s, ':'); 252 if (s2 != NULL) { 253 *s2 = 0; 254 s2++; 255 sscanf(s2, "%d", &pport); 256 } 257 phost = s; 258 259 if (phost != NULL) { 260 /** 261 * Let's create the appropriate Proxy object then. 262 */ 263 jstring jhost; 264 if (pport == 0) 265 pport = defport; 266 jhost = (*env)->NewStringUTF(env, phost); 267 CHECK_NULL_RETURN(jhost, NULL); 268 isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport); 269 CHECK_NULL_RETURN(isa, NULL); 270 proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa); 271 return proxy; 272 } 273 } 274 } else { 275 /* ProxyEnable == 0 or Query failed */ 276 /* close the handle to the registry key */ 277 RegCloseKey(hKey); 278 } 279 } 280 281 noproxy: 282 no_proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID); 283 return no_proxy; 284 }