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