Mercurial > 510Connectbot
comparison src/ch/ethz/ssh2/transport/HTTPProxyClientTransportManager.java @ 342:175c7d68f3c4
merge ganymed into mainline
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 31 Jul 2014 16:33:38 -0700 |
parents | 071eccdff8ea |
children |
comparison
equal
deleted
inserted
replaced
272:ce2f4e397703 | 342:175c7d68f3c4 |
---|---|
1 package ch.ethz.ssh2.transport; | |
2 | |
3 import java.io.IOException; | |
4 import java.io.InputStream; | |
5 import java.io.InputStreamReader; | |
6 import java.io.LineNumberReader; | |
7 import java.io.OutputStream; | |
8 import java.net.InetSocketAddress; | |
9 import java.net.Socket; | |
10 | |
11 import ch.ethz.ssh2.HTTPProxyData; | |
12 import ch.ethz.ssh2.HTTPProxyException; | |
13 import ch.ethz.ssh2.crypto.Base64; | |
14 import ch.ethz.ssh2.util.StringEncoder; | |
15 | |
16 /** | |
17 * @version $Id: HTTPProxyClientTransportManager.java 155 2014-04-28 12:01:19Z dkocher@sudo.ch $ | |
18 */ | |
19 public class HTTPProxyClientTransportManager extends ClientTransportManager { | |
20 | |
21 /** | |
22 * Used to tell the library that the connection shall be established through a proxy server. | |
23 */ | |
24 | |
25 private HTTPProxyData pd; | |
26 | |
27 private final Socket sock; | |
28 | |
29 public HTTPProxyClientTransportManager(final Socket socket, final HTTPProxyData pd) { | |
30 super(socket); | |
31 this.sock = socket; | |
32 this.pd = pd; | |
33 } | |
34 | |
35 @Override | |
36 protected void connect(final String hostname, final int port, final int connectTimeout) throws IOException { | |
37 sock.connect(new InetSocketAddress(pd.proxyHost, pd.proxyPort), connectTimeout); | |
38 // Tell the proxy where we actually want to connect to | |
39 StringBuilder sb = new StringBuilder(); | |
40 sb.append("CONNECT "); | |
41 sb.append(hostname); | |
42 sb.append(':'); | |
43 sb.append(port); | |
44 sb.append(" HTTP/1.0\r\n"); | |
45 | |
46 if ((pd.proxyUser != null) && (pd.proxyPass != null)) { | |
47 String credentials = pd.proxyUser + ":" + pd.proxyPass; | |
48 char[] encoded = Base64.encode(StringEncoder.GetBytes(credentials)); | |
49 sb.append("Proxy-Authorization: Basic "); | |
50 sb.append(encoded); | |
51 sb.append("\r\n"); | |
52 } | |
53 | |
54 if (pd.requestHeaderLines != null) { | |
55 for (int i = 0; i < pd.requestHeaderLines.length; i++) { | |
56 if (pd.requestHeaderLines[i] != null) { | |
57 sb.append(pd.requestHeaderLines[i]); | |
58 sb.append("\r\n"); | |
59 } | |
60 } | |
61 } | |
62 | |
63 sb.append("\r\n"); | |
64 OutputStream out = sock.getOutputStream(); | |
65 out.write(StringEncoder.GetBytes(sb.toString())); | |
66 out.flush(); | |
67 // Parse the HTTP response | |
68 InputStream in = sock.getInputStream(); | |
69 final LineNumberReader reader = new LineNumberReader(new InputStreamReader(in)); | |
70 String httpReponse = reader.readLine(); | |
71 | |
72 if (!httpReponse.startsWith("HTTP/")) { | |
73 throw new IOException("The proxy did not send back a valid HTTP response."); | |
74 } | |
75 | |
76 // "HTTP/1.X XYZ X" => 14 characters minimum | |
77 | |
78 if ((httpReponse.length() < 14) || (httpReponse.charAt(8) != ' ') || (httpReponse.charAt(12) != ' ')) { | |
79 throw new IOException("The proxy did not send back a valid HTTP response."); | |
80 } | |
81 | |
82 int errorCode; | |
83 | |
84 try { | |
85 errorCode = Integer.parseInt(httpReponse.substring(9, 12)); | |
86 } | |
87 catch (NumberFormatException ignore) { | |
88 throw new IOException("The proxy did not send back a valid HTTP response."); | |
89 } | |
90 | |
91 if ((errorCode < 0) || (errorCode > 999)) { | |
92 throw new IOException("The proxy did not send back a valid HTTP response."); | |
93 } | |
94 | |
95 if (errorCode != 200) { | |
96 throw new HTTPProxyException(httpReponse.substring(13), errorCode); | |
97 } | |
98 | |
99 while (reader.readLine() != null) { | |
100 // Read until empty line | |
101 } | |
102 } | |
103 } |