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 <Winhttp.h>
28
29 #include "jni.h"
30 #include "jni_util.h"
31 #include "jvm.h"
32
33 #include "proxy_util.h"
34
35 #include "sun_net_spi_DefaultProxySelector.h"
36
37 /**
38 * These functions are used by the sun.net.spi.DefaultProxySelector class
39 * to access some platform specific settings.
40 * This is the Windows code using WinHTTP functions to get the system settings.
41 */
42
43 /* Keep one static session for all requests. */
44 static HINTERNET session = NULL;
45
46 /*
47 * Class: sun_net_spi_DefaultProxySelector
48 * Method: init
49 * Signature: ()Z
50 */
51 JNIEXPORT jboolean JNICALL
52 Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
53
54 /*
55 * Get one WinHTTP session handle to initialize the WinHTTP internal data structures
56 * We keep and use only this one for the whole life time.
57 */
58 session = WinHttpOpen(L"Only used internal", /* we need no real agent string here */
59 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
60 WINHTTP_NO_PROXY_NAME,
61 WINHTTP_NO_PROXY_BYPASS,
62 0);
63 if (session == NULL) {
64 return JNI_FALSE;
65 }
66
67 if (!initJavaClass(env)) {
68 return JNI_FALSE;
69 }
70
71 return JNI_TRUE;
72 }
73
74
75 #define MAX_STR_LEN 1024
76
90 free(current->host);
91 free(current);
92 current = next;
93 }
94 }
95
96
97 /*
98 * Creates a linked list of list_item elements that has to be freed later on.
99 * Returns the size of the array as int.
100 */
101 static int createProxyList(LPWSTR win_proxy, const WCHAR *pproto, list_item **head) {
102 static const wchar_t separators[] = L"\t\r\n ;";
103 list_item *current = NULL;
104 int nr_elems = 0;
105 wchar_t *context = NULL;
106 wchar_t *current_proxy = NULL;
107 BOOL error = FALSE;
108
109 /*
110 * The proxy server list contains one or more of the following strings separated by semicolons or whitespace.
111 * ([<scheme>=][<scheme>"://"]<server>[":"<port>])
112 */
113 current_proxy = wcstok_s(win_proxy, separators, &context);
114 while (current_proxy != NULL) {
115 LPWSTR pport;
116 LPWSTR phost;
117 int portVal = 0;
118 wchar_t *next_proxy = NULL;
119 list_item *proxy = NULL;
120 wchar_t* pos = NULL;
121
122 /* Filter based on the scheme, if there is one */
123 pos = wcschr(current_proxy, L'=');
124 if (pos) {
125 *pos = L'\0';
126 if (wcscmp(current_proxy, pproto) != 0) {
127 current_proxy = wcstok_s(NULL, separators, &context);
128 continue;
129 }
130 current_proxy = pos + 1;
240 win_bypass_proxy = ie_proxy_config.lpszProxyBypass;
241 win_proxy = ie_proxy_config.lpszProxy;
242 }
243
244 if (use_auto_proxy) {
245 WCHAR url[MAX_STR_LEN];
246 /* Create url for WinHttpGetProxyForUrl */
247 _snwprintf(url, sizeof(url) - 1, L"%s://%s", lpProto, lpHost);
248 /* Get proxy for URL from Windows */
249 use_auto_proxy = WinHttpGetProxyForUrl(session, &url[0], &auto_proxy_options, &proxy_info);
250 if (use_auto_proxy) {
251 win_proxy = proxy_info.lpszProxy;
252 win_bypass_proxy = proxy_info.lpszProxyBypass;
253 }
254 }
255
256 /* Check the bypass entry. */
257 if (NULL != win_bypass_proxy) {
258 /*
259 * From MSDN:
260 * The proxy bypass list contains one or more server names separated by semicolons or
261 * whitespace. The proxy bypass list can also contain the string "<local>" to indicate
262 * that all local intranet sites are bypassed. Local intranet sites are considered to
263 * be all servers that do not contain a period in their name.
264 */
265 wchar_t *context = NULL;
266 LPWSTR s = wcstok_s(win_bypass_proxy, L"; ", &context);
267
268 while (s != NULL) {
269 size_t maxlen = wcslen(s);
270 if (wcsncmp(s, lpHost, maxlen) == 0) {
271 /*
272 * The URL host name matches with one of the prefixes, we have to use a direct
273 * connection.
274 */
275 goto noproxy;
276 }
277 if (wcsncmp(s, L"<local>", maxlen) == 0) {
278 /*
279 * All local intranet sites are bypassed - Microsoft considers all servers that
280 * do not contain a period in their name to be local.
281 */
282 if (wcschr(lpHost, '.') == NULL) {
283 goto noproxy;
284 }
285 }
286 s = wcstok_s(NULL, L"; ", &context);
287 }
288 }
289
290 if (win_proxy != NULL) {
291 wchar_t *context = NULL;
292 int defport = 0;
293 int nr_elems = 0;
294
295 /**
296 * Set default port value & proxy type from protocol.
297 */
298 if ((wcscmp(lpProto, L"http") == 0) ||
299 (wcscmp(lpProto, L"ftp") == 0) ||
300 (wcscmp(lpProto, L"gopher") == 0))
301 defport = 80;
302 if (wcscmp(lpProto, L"https") == 0)
303 defport = 443;
304 if (wcscmp(lpProto, L"socks") == 0) {
305 defport = 1080;
306 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
307 } else {
308 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
309 }
310 if (type_proxy == NULL || (*env)->ExceptionCheck(env)) {
311 goto noproxy;
312 }
313
314 nr_elems = createProxyList(win_proxy, lpProto, &head);
315 if (nr_elems != 0 && head != NULL) {
316 int index = 0;
317 proxy_array = (*env)->NewObjectArray(env, nr_elems, proxy_class, NULL);
|
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 <Winhttp.h>
28
29 #include "jni.h"
30 #include "jni_util.h"
31 #include "jvm.h"
32
33 #include "proxy_util.h"
34
35 #include "sun_net_spi_DefaultProxySelector.h"
36
37 /*
38 * These functions are used by the sun.net.spi.DefaultProxySelector class
39 * to access some platform specific settings.
40 * On Windows use WinHTTP functions to get the system settings.
41 */
42
43 /* Keep one static session for all requests. */
44 static HINTERNET session = NULL;
45
46 /*
47 * Class: sun_net_spi_DefaultProxySelector
48 * Method: init
49 * Signature: ()Z
50 */
51 JNIEXPORT jboolean JNICALL
52 Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
53
54 /*
55 * Get one WinHTTP session handle to initialize the WinHTTP internal data
56 * structures. Keep and use only this one for the whole life time.
57 */
58 session = WinHttpOpen(L"Only used internal", /* we need no real agent string here */
59 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
60 WINHTTP_NO_PROXY_NAME,
61 WINHTTP_NO_PROXY_BYPASS,
62 0);
63 if (session == NULL) {
64 return JNI_FALSE;
65 }
66
67 if (!initJavaClass(env)) {
68 return JNI_FALSE;
69 }
70
71 return JNI_TRUE;
72 }
73
74
75 #define MAX_STR_LEN 1024
76
90 free(current->host);
91 free(current);
92 current = next;
93 }
94 }
95
96
97 /*
98 * Creates a linked list of list_item elements that has to be freed later on.
99 * Returns the size of the array as int.
100 */
101 static int createProxyList(LPWSTR win_proxy, const WCHAR *pproto, list_item **head) {
102 static const wchar_t separators[] = L"\t\r\n ;";
103 list_item *current = NULL;
104 int nr_elems = 0;
105 wchar_t *context = NULL;
106 wchar_t *current_proxy = NULL;
107 BOOL error = FALSE;
108
109 /*
110 * The proxy server list contains one or more of the following strings
111 * separated by semicolons or whitespace:
112 * ([<scheme>=][<scheme>"://"]<server>[":"<port>])
113 */
114 current_proxy = wcstok_s(win_proxy, separators, &context);
115 while (current_proxy != NULL) {
116 LPWSTR pport;
117 LPWSTR phost;
118 int portVal = 0;
119 wchar_t *next_proxy = NULL;
120 list_item *proxy = NULL;
121 wchar_t* pos = NULL;
122
123 /* Filter based on the scheme, if there is one */
124 pos = wcschr(current_proxy, L'=');
125 if (pos) {
126 *pos = L'\0';
127 if (wcscmp(current_proxy, pproto) != 0) {
128 current_proxy = wcstok_s(NULL, separators, &context);
129 continue;
130 }
131 current_proxy = pos + 1;
241 win_bypass_proxy = ie_proxy_config.lpszProxyBypass;
242 win_proxy = ie_proxy_config.lpszProxy;
243 }
244
245 if (use_auto_proxy) {
246 WCHAR url[MAX_STR_LEN];
247 /* Create url for WinHttpGetProxyForUrl */
248 _snwprintf(url, sizeof(url) - 1, L"%s://%s", lpProto, lpHost);
249 /* Get proxy for URL from Windows */
250 use_auto_proxy = WinHttpGetProxyForUrl(session, &url[0], &auto_proxy_options, &proxy_info);
251 if (use_auto_proxy) {
252 win_proxy = proxy_info.lpszProxy;
253 win_bypass_proxy = proxy_info.lpszProxyBypass;
254 }
255 }
256
257 /* Check the bypass entry. */
258 if (NULL != win_bypass_proxy) {
259 /*
260 * From MSDN:
261 * The proxy bypass list contains one or more server names separated by
262 * semicolons or whitespace. The proxy bypass list can also contain the
263 * string "<local>" to indicate that all local intranet sites are
264 * bypassed. Local intranet sites are considered to be all servers that
265 * do not contain a period in their name.
266 */
267 wchar_t *context = NULL;
268 LPWSTR s = wcstok_s(win_bypass_proxy, L"; ", &context);
269
270 while (s != NULL) {
271 size_t maxlen = wcslen(s);
272 if (wcsncmp(s, lpHost, maxlen) == 0) {
273 /*
274 * The URL host name matches with one of the prefixes, use a
275 * direct connection.
276 */
277 goto noproxy;
278 }
279 if (wcsncmp(s, L"<local>", maxlen) == 0) {
280 /*
281 * All local intranet sites are bypassed - Microsoft consider all
282 * servers that do not contain a period in their name to be local.
283 */
284 if (wcschr(lpHost, '.') == NULL) {
285 goto noproxy;
286 }
287 }
288 s = wcstok_s(NULL, L"; ", &context);
289 }
290 }
291
292 if (win_proxy != NULL) {
293 wchar_t *context = NULL;
294 int defport = 0;
295 int nr_elems = 0;
296
297 /* Set the default port value & proxy type from protocol. */
298 if ((wcscmp(lpProto, L"http") == 0) ||
299 (wcscmp(lpProto, L"ftp") == 0) ||
300 (wcscmp(lpProto, L"gopher") == 0))
301 defport = 80;
302 if (wcscmp(lpProto, L"https") == 0)
303 defport = 443;
304 if (wcscmp(lpProto, L"socks") == 0) {
305 defport = 1080;
306 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
307 } else {
308 type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
309 }
310 if (type_proxy == NULL || (*env)->ExceptionCheck(env)) {
311 goto noproxy;
312 }
313
314 nr_elems = createProxyList(win_proxy, lpProto, &head);
315 if (nr_elems != 0 && head != NULL) {
316 int index = 0;
317 proxy_array = (*env)->NewObjectArray(env, nr_elems, proxy_class, NULL);
|