1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package wjhk.jupload2.upload.helper;
28
29 import java.io.IOException;
30 import java.net.ConnectException;
31 import java.net.InetSocketAddress;
32 import java.net.Proxy;
33 import java.net.ProxySelector;
34 import java.net.Socket;
35 import java.net.URISyntaxException;
36 import java.net.URL;
37 import java.net.UnknownHostException;
38 import java.security.KeyManagementException;
39 import java.security.KeyStoreException;
40 import java.security.NoSuchAlgorithmException;
41 import java.security.UnrecoverableKeyException;
42 import java.security.cert.CertificateException;
43 import java.util.regex.Matcher;
44 import java.util.regex.Pattern;
45
46 import javax.net.ssl.SSLContext;
47
48 import wjhk.jupload2.exception.JUploadException;
49 import wjhk.jupload2.policies.UploadPolicy;
50 import javax.net.ssl.X509TrustManager;
51
52 import java.security.cert.X509Certificate;
53
54 import java.io.InputStreamReader;
55 import java.io.OutputStreamWriter;
56 import java.io.BufferedReader;
57 import java.io.BufferedWriter;
58
59
60
61
62
63
64 public class HttpConnect {
65
66
67 private final class TM implements X509TrustManager {
68 public void checkClientTrusted(X509Certificate[] arg0, String arg1)
69 throws CertificateException {
70 }
71
72 public void checkServerTrusted(X509Certificate[] chain, String authType)
73 throws CertificateException {
74 }
75
76 public X509Certificate[] getAcceptedIssuers() {
77 return new X509Certificate[0];
78 }
79 }
80
81 private final static String HTTPCONNECT_DEFAULT_PROTOCOL = "HTTP/1.1";
82
83
84
85
86
87
88 private UploadPolicy uploadPolicy;
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 public Socket connect(URL url, Proxy proxy)
109 throws NoSuchAlgorithmException, KeyManagementException,
110 ConnectException, UnknownHostException, IOException,
111 KeyStoreException, CertificateException, IllegalArgumentException,
112 UnrecoverableKeyException {
113
114 Socket tsock;
115 Socket ret = null;
116 String host = url.getHost();
117 int port;
118 boolean useProxy = ((proxy != null) && (proxy.type() != Proxy.Type.DIRECT));
119
120
121 if (url.getProtocol().equals("https")) {
122 port = (-1 == url.getPort()) ? 443 : url.getPort();
123 SSLContext context = SSLContext.getInstance("SSL");
124
125
126 boolean bNoChange = false;
127 if (bNoChange) {
128
129 context.init(null, new X509TrustManager[] {
130 new TM()
131 }, null);
132 } else {
133 switch (uploadPolicy.getSslVerifyCert()) {
134 case InteractiveTrustManager.NONE:
135
136 context.init(null, new X509TrustManager[] {
137 new TM()
138 }, null);
139 break;
140 case InteractiveTrustManager.SERVER:
141 case InteractiveTrustManager.STRICT:
142 case InteractiveTrustManager.CLIENT:
143
144 InteractiveTrustManager tm = new InteractiveTrustManager(
145 uploadPolicy, host, null);
146 context.init(tm.getKeyManagers(),
147 new X509TrustManager[] {
148 tm
149 }, null);
150 break;
151 default:
152 throw new IllegalArgumentException(
153 "Unknown value for sslVerifyCert: "
154 + uploadPolicy.getSslVerifyCert());
155 }
156 }
157 if (useProxy) {
158 if (proxy.type() == Proxy.Type.HTTP) {
159
160
161
162
163 BufferedWriter writer;
164 BufferedReader reader;
165 String proxyhost;
166 int proxyport;
167 InetSocketAddress sa = (InetSocketAddress) proxy.address();
168 proxyhost = (sa.isUnresolved()) ? sa.getHostName() : sa
169 .getAddress().getHostAddress();
170 proxyport = sa.getPort();
171 this.uploadPolicy.displayDebug(
172 "Using SSL socket, via HTTP proxy", 20);
173 tsock = new Socket(proxyhost, proxyport);
174 writer = new BufferedWriter(new OutputStreamWriter(
175 tsock.getOutputStream()));
176 reader = new BufferedReader(new InputStreamReader(
177 tsock.getInputStream()));
178 String hostport = host + ":" + port;
179 String req = "CONNECT " + hostport + " HTTP/1.0\r\n\r\n";
180 writer.write(req);
181 writer.flush();
182 String res = reader.readLine();
183 String[] status = res.split(" ", 3);
184 if (status.length < 2 || !status[1].startsWith("200")) {
185 this.uploadPolicy.displayDebug("res: " + res, 10);
186 throw new ConnectException("proxy connection error");
187 }
188 ret = context.getSocketFactory().createSocket(tsock,
189 url.getHost(), port, true);
190 } else if (proxy.type() == Proxy.Type.SOCKS) {
191 this.uploadPolicy.displayDebug(
192 "Using SSL socket, via SOCKS proxy", 20);
193 tsock = new Socket(proxy);
194 tsock.connect(new InetSocketAddress(host, port));
195 ret = context.getSocketFactory().createSocket(tsock, host,
196 port, true);
197
198 } else
199 throw new ConnectException("Unkown proxy type "
200 + proxy.type());
201 } else {
202
203
204 this.uploadPolicy.displayDebug(
205 "Using SSL socket, direct connection", 20);
206 ret = context.getSocketFactory().createSocket(host, port);
207 }
208 } else {
209
210 port = (-1 == url.getPort()) ? 80 : url.getPort();
211 if (useProxy) {
212 if (proxy.type() == Proxy.Type.HTTP) {
213 InetSocketAddress sa = (InetSocketAddress) proxy.address();
214 host = (sa.isUnresolved()) ? sa.getHostName() : sa
215 .getAddress().getHostAddress();
216 port = sa.getPort();
217 this.uploadPolicy.displayDebug(
218 "Using non SSL socket, proxy=" + host + ":" + port,
219 20);
220 ret = new Socket(host, port);
221 } else if (proxy.type() == Proxy.Type.SOCKS) {
222 this.uploadPolicy.displayDebug(
223 "Using non SSL socket, via SOCKS proxy", 20);
224 tsock = new Socket(proxy);
225 tsock.connect(new InetSocketAddress(host, port));
226 ret = tsock;
227 } else
228 throw new ConnectException("Unkown proxy type "
229 + proxy.type());
230 } else {
231 this.uploadPolicy.displayDebug(
232 "Using non SSL socket, direct connection", 20);
233 ret = new Socket(host, port);
234 }
235 }
236 return ret;
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257 public Socket connect(URL url) throws NoSuchAlgorithmException,
258 KeyManagementException, ConnectException, UnknownHostException,
259 IOException, URISyntaxException, KeyStoreException,
260 CertificateException, IllegalArgumentException,
261 UnrecoverableKeyException {
262 Proxy proxy = ProxySelector.getDefault().select(url.toURI()).get(0);
263 return connect(url, proxy);
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283 public String getProtocol() throws URISyntaxException,
284 KeyManagementException, NoSuchAlgorithmException,
285 UnknownHostException, KeyStoreException, CertificateException,
286 IllegalArgumentException, UnrecoverableKeyException, IOException,
287 JUploadException {
288
289 String protocol = HTTPCONNECT_DEFAULT_PROTOCOL;
290 URL url = new URL(this.uploadPolicy.getPostURL());
291 this.uploadPolicy
292 .displayDebug("Checking protocol with URL: " + url, 30);
293 HTTPConnectionHelper connectionHelper = new HTTPConnectionHelper(url,
294 "HEAD", false, true, this.uploadPolicy);
295 connectionHelper.append("\r\n");
296 this.uploadPolicy.displayDebug("Before sendRequest()", 30);
297 connectionHelper.sendRequest();
298 this.uploadPolicy.displayDebug("After sendRequest()", 30);
299 connectionHelper.getOutputStream().flush();
300 if (this.uploadPolicy.getDebugLevel() >= 80) {
301 this.uploadPolicy
302 .displayDebug(
303 "-------------------------------------------------------------------------",
304 80);
305 this.uploadPolicy
306 .displayDebug(
307 "----------------- HEAD message sent (start) --------------------------",
308 80);
309 this.uploadPolicy
310 .displayDebug(
311 "-------------------------------------------------------------------------",
312 80);
313 this.uploadPolicy.displayDebug(connectionHelper
314 .getByteArrayEncoder().getString(), 80);
315 this.uploadPolicy
316 .displayDebug(
317 "-------------------------------------------------------------------------",
318 80);
319 this.uploadPolicy
320 .displayDebug(
321 "----------------- HEAD message sent (end) -----------------------------",
322 80);
323 this.uploadPolicy
324 .displayDebug(
325 "-------------------------------------------------------------------------",
326 80);
327 }
328
329 int status = connectionHelper.readHttpResponse();
330 this.uploadPolicy.displayDebug("HEAD status: " + status, 30);
331 String headers = connectionHelper.getResponseHeaders();
332
333
334 Matcher m = Pattern.compile("^(HTTP/\\d\\.\\d)\\s(.*)\\s.*$",
335 Pattern.MULTILINE).matcher(headers);
336 if (!m.find()) {
337
338 this.uploadPolicy
339 .displayErr("Unexpected HEAD response (can't find the protocol): will use the default one.");
340 } else {
341
342 protocol = m.group(1);
343 this.uploadPolicy.displayDebug("HEAD protocol: " + protocol, 30);
344 }
345
346
347
348 Pattern pIIS = Pattern.compile("^Server: .*IIS*$", Pattern.MULTILINE);
349 Matcher mIIS = pIIS.matcher(headers);
350 if (mIIS.find()) {
351 try {
352 this.uploadPolicy.setProperty(
353 UploadPolicy.PROP_ALLOW_HTTP_PERSISTENT, "false");
354 this.uploadPolicy
355 .displayWarn(UploadPolicy.PROP_ALLOW_HTTP_PERSISTENT
356 + "' forced to false, for IIS compatibility (in HttpConnect.getProtocol())");
357 } catch (JUploadException e) {
358 this.uploadPolicy.displayWarn("Can't set property '"
359 + UploadPolicy.PROP_ALLOW_HTTP_PERSISTENT
360 + "' to false, in HttpConnect.getProtocol()");
361 }
362 }
363
364
365 if (status == 301 || status == 302 || status == 303) {
366 Pattern pLocation = Pattern.compile("^Location: (.*)$",
367 Pattern.MULTILINE);
368 Matcher mLocation = pLocation.matcher(headers);
369 if (mLocation.find()) {
370
371
372 this.uploadPolicy.displayDebug(
373 "Location read: " + mLocation.group(1), 50);
374 changePostURL(mLocation.group(1));
375 }
376 }
377
378
379 connectionHelper.dispose();
380 connectionHelper.close();
381
382 return protocol;
383 }
384
385
386
387
388
389
390
391
392 private void changePostURL(String newLocation) throws JUploadException {
393 String currentPostURL = this.uploadPolicy.getPostURL();
394 String newPostURL;
395 Pattern pHostName = Pattern.compile("http://([^/]*)/.*");
396 Matcher mOldPostURL = Pattern.compile("(.*)\\?(.*)").matcher(
397 currentPostURL);
398
399
400
401 if (mOldPostURL.matches()) {
402 newPostURL = newLocation + '?' + mOldPostURL.group(2);
403
404 } else {
405 newPostURL = newLocation;
406 }
407
408
409
410
411
412
413 Matcher mHostOldPostURL = pHostName.matcher(currentPostURL);
414 if (!mHostOldPostURL.matches()) {
415
416 throw new JUploadException(
417 "[HttpConnect.changePostURL()] No host found in the old postURL !");
418 }
419
420
421 Matcher mHostNewLocation = pHostName.matcher(newLocation);
422 if (mHostNewLocation.matches()) {
423
424
425 } else if (newLocation.startsWith("/")) {
426
427 newPostURL = "http://" + mHostOldPostURL.group(1) + newPostURL;
428 } else {
429
430
431 Matcher mOldPostURLAllButFilename = Pattern
432 .compile("(.*)/([^/]*)$").matcher(currentPostURL);
433 if (!mOldPostURLAllButFilename.matches()) {
434
435 throw new JUploadException(
436 "[HttpConnect.changePostURL()] Can't find the filename in the URL !");
437 }
438 newPostURL = mOldPostURLAllButFilename.group(1) + "/" + newPostURL;
439 }
440
441
442 this.uploadPolicy.setPostURL(newPostURL);
443 this.uploadPolicy.displayInfo("postURL switched from " + currentPostURL
444 + " to " + newPostURL);
445 }
446
447
448
449
450
451
452 public HttpConnect(UploadPolicy policy) {
453 this.uploadPolicy = policy;
454 }
455 }