Mercurial > 510Connectbot
comparison src/ch/ethz/ssh2/SCPClient.java @ 308:42b15aaa7ac7 ganymed
merge
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 30 Jul 2014 14:21:50 -0700 |
parents | 071eccdff8ea |
children |
comparison
equal
deleted
inserted
replaced
306:90e47d99ea54 | 308:42b15aaa7ac7 |
---|---|
21 * | 21 * |
22 * @author Christian Plattner, plattner@inf.ethz.ch | 22 * @author Christian Plattner, plattner@inf.ethz.ch |
23 * @version $Id: SCPClient.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ | 23 * @version $Id: SCPClient.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ |
24 */ | 24 */ |
25 | 25 |
26 public class SCPClient | 26 public class SCPClient { |
27 { | 27 Connection conn; |
28 Connection conn; | 28 |
29 | 29 String charsetName = null; |
30 String charsetName = null; | 30 |
31 | 31 /** |
32 /** | 32 * Set the charset used to convert between Java Unicode Strings and byte encodings |
33 * Set the charset used to convert between Java Unicode Strings and byte encodings | 33 * used by the server for paths and file names. |
34 * used by the server for paths and file names. | 34 * |
35 * | 35 * @param charset the name of the charset to be used or <code>null</code> to use the platform's |
36 * @param charset the name of the charset to be used or <code>null</code> to use the platform's | 36 * default encoding. |
37 * default encoding. | 37 * @throws IOException |
38 * @throws IOException | 38 * @see #getCharset() |
39 * @see #getCharset() | 39 */ |
40 */ | 40 public void setCharset(String charset) throws IOException { |
41 public void setCharset(String charset) throws IOException | 41 if (charset == null) { |
42 { | 42 charsetName = charset; |
43 if (charset == null) | 43 return; |
44 { | 44 } |
45 charsetName = charset; | 45 |
46 return; | 46 try { |
47 } | 47 Charset.forName(charset); |
48 | 48 } |
49 try | 49 catch (UnsupportedCharsetException e) { |
50 { | 50 throw new IOException("This charset is not supported", e); |
51 Charset.forName(charset); | 51 } |
52 } | 52 |
53 catch (UnsupportedCharsetException e) | 53 charsetName = charset; |
54 { | 54 } |
55 throw new IOException("This charset is not supported", e); | 55 |
56 } | 56 /** |
57 charsetName = charset; | 57 * The currently used charset for filename encoding/decoding. |
58 } | 58 * |
59 | 59 * @return The name of the charset (<code>null</code> if the platform's default charset is being used) |
60 /** | 60 * @see #setCharset(String) |
61 * The currently used charset for filename encoding/decoding. | 61 */ |
62 * | 62 public String getCharset() { |
63 * @return The name of the charset (<code>null</code> if the platform's default charset is being used) | 63 return charsetName; |
64 * @see #setCharset(String) | 64 } |
65 */ | 65 |
66 public String getCharset() | 66 public class LenNamePair { |
67 { | 67 public long length; |
68 return charsetName; | 68 String filename; |
69 } | 69 } |
70 | 70 |
71 public class LenNamePair | 71 public SCPClient(Connection conn) { |
72 { | 72 if (conn == null) |
73 public long length; | 73 throw new IllegalArgumentException("Cannot accept null argument!"); |
74 String filename; | 74 |
75 } | 75 this.conn = conn; |
76 | 76 } |
77 public SCPClient(Connection conn) | 77 |
78 { | 78 protected void readResponse(InputStream is) throws IOException { |
79 if (conn == null) | 79 int c = is.read(); |
80 throw new IllegalArgumentException("Cannot accept null argument!"); | 80 |
81 this.conn = conn; | 81 if (c == 0) |
82 } | 82 return; |
83 | 83 |
84 protected void readResponse(InputStream is) throws IOException | 84 if (c == -1) |
85 { | 85 throw new IOException("Remote scp terminated unexpectedly."); |
86 int c = is.read(); | 86 |
87 | 87 if ((c != 1) && (c != 2)) |
88 if (c == 0) | 88 throw new IOException("Remote scp sent illegal error code."); |
89 return; | 89 |
90 | 90 if (c == 2) |
91 if (c == -1) | 91 throw new IOException("Remote scp terminated with error."); |
92 throw new IOException("Remote scp terminated unexpectedly."); | 92 |
93 | 93 String err = receiveLine(is); |
94 if ((c != 1) && (c != 2)) | 94 throw new IOException("Remote scp terminated with error (" + err + ")."); |
95 throw new IOException("Remote scp sent illegal error code."); | 95 } |
96 | 96 |
97 if (c == 2) | 97 protected String receiveLine(InputStream is) throws IOException { |
98 throw new IOException("Remote scp terminated with error."); | 98 StringBuilder sb = new StringBuilder(30); |
99 | 99 |
100 String err = receiveLine(is); | 100 while (true) { |
101 throw new IOException("Remote scp terminated with error (" + err + ")."); | 101 /* This is a random limit - if your path names are longer, then adjust it */ |
102 } | 102 if (sb.length() > 8192) |
103 | 103 throw new IOException("Remote scp sent a too long line"); |
104 protected String receiveLine(InputStream is) throws IOException | 104 |
105 { | 105 int c = is.read(); |
106 StringBuilder sb = new StringBuilder(30); | 106 |
107 | 107 if (c < 0) |
108 while (true) | 108 throw new IOException("Remote scp terminated unexpectedly."); |
109 { | 109 |
110 /* This is a random limit - if your path names are longer, then adjust it */ | 110 if (c == '\n') |
111 | 111 break; |
112 if (sb.length() > 8192) | 112 |
113 throw new IOException("Remote scp sent a too long line"); | 113 sb.append((char) c); |
114 | 114 } |
115 int c = is.read(); | 115 |
116 | 116 return sb.toString(); |
117 if (c < 0) | 117 } |
118 throw new IOException("Remote scp terminated unexpectedly."); | 118 |
119 | 119 protected LenNamePair parseCLine(String line) throws IOException { |
120 if (c == '\n') | 120 /* Minimum line: "xxxx y z" ---> 8 chars */ |
121 break; | 121 if (line.length() < 8) |
122 | 122 throw new IOException("Malformed C line sent by remote SCP binary, line too short."); |
123 sb.append((char) c); | 123 |
124 | 124 if ((line.charAt(4) != ' ') || (line.charAt(5) == ' ')) |
125 } | 125 throw new IOException("Malformed C line sent by remote SCP binary."); |
126 return sb.toString(); | 126 |
127 } | 127 int length_name_sep = line.indexOf(' ', 5); |
128 | 128 |
129 protected LenNamePair parseCLine(String line) throws IOException | 129 if (length_name_sep == -1) |
130 { | 130 throw new IOException("Malformed C line sent by remote SCP binary."); |
131 /* Minimum line: "xxxx y z" ---> 8 chars */ | 131 |
132 | 132 String length_substring = line.substring(5, length_name_sep); |
133 if (line.length() < 8) | 133 String name_substring = line.substring(length_name_sep + 1); |
134 throw new IOException("Malformed C line sent by remote SCP binary, line too short."); | 134 |
135 | 135 if ((length_substring.length() <= 0) || (name_substring.length() <= 0)) |
136 if ((line.charAt(4) != ' ') || (line.charAt(5) == ' ')) | 136 throw new IOException("Malformed C line sent by remote SCP binary."); |
137 throw new IOException("Malformed C line sent by remote SCP binary."); | 137 |
138 | 138 if ((6 + length_substring.length() + name_substring.length()) != line.length()) |
139 int length_name_sep = line.indexOf(' ', 5); | 139 throw new IOException("Malformed C line sent by remote SCP binary."); |
140 | 140 |
141 if (length_name_sep == -1) | 141 final long len; |
142 throw new IOException("Malformed C line sent by remote SCP binary."); | 142 |
143 | 143 try { |
144 String length_substring = line.substring(5, length_name_sep); | 144 len = Long.parseLong(length_substring); |
145 String name_substring = line.substring(length_name_sep + 1); | 145 } |
146 | 146 catch (NumberFormatException e) { |
147 if ((length_substring.length() <= 0) || (name_substring.length() <= 0)) | 147 throw new IOException("Malformed C line sent by remote SCP binary, cannot parse file length."); |
148 throw new IOException("Malformed C line sent by remote SCP binary."); | 148 } |
149 | 149 |
150 if ((6 + length_substring.length() + name_substring.length()) != line.length()) | 150 if (len < 0) |
151 throw new IOException("Malformed C line sent by remote SCP binary."); | 151 throw new IOException("Malformed C line sent by remote SCP binary, illegal file length."); |
152 | 152 |
153 final long len; | 153 LenNamePair lnp = new LenNamePair(); |
154 try | 154 lnp.length = len; |
155 { | 155 lnp.filename = name_substring; |
156 len = Long.parseLong(length_substring); | 156 return lnp; |
157 } | 157 } |
158 catch (NumberFormatException e) | 158 |
159 { | 159 /** |
160 throw new IOException("Malformed C line sent by remote SCP binary, cannot parse file length."); | 160 * The session for opened for this SCP transfer must be closed using |
161 } | 161 * SCPOutputStream#close |
162 | 162 * |
163 if (len < 0) | 163 * @param remoteFile |
164 throw new IOException("Malformed C line sent by remote SCP binary, illegal file length."); | 164 * @param length The size of the file to send |
165 | 165 * @param remoteTargetDirectory |
166 LenNamePair lnp = new LenNamePair(); | 166 * @param mode |
167 lnp.length = len; | 167 * @return |
168 lnp.filename = name_substring; | 168 * @throws IOException |
169 | 169 */ |
170 return lnp; | 170 public SCPOutputStream put(final String remoteFile, long length, String remoteTargetDirectory, String mode) |
171 } | 171 throws IOException { |
172 | 172 Session sess = null; |
173 /** | 173 |
174 * The session for opened for this SCP transfer must be closed using | 174 if (null == remoteFile) |
175 * SCPOutputStream#close | 175 throw new IllegalArgumentException("Null argument."); |
176 * | 176 |
177 * @param remoteFile | 177 if (null == remoteTargetDirectory) |
178 * @param length The size of the file to send | 178 remoteTargetDirectory = ""; |
179 * @param remoteTargetDirectory | 179 |
180 * @param mode | 180 if (null == mode) |
181 * @return | 181 mode = "0600"; |
182 * @throws IOException | 182 |
183 */ | 183 if (mode.length() != 4) |
184 public SCPOutputStream put(final String remoteFile, long length, String remoteTargetDirectory, String mode) | 184 throw new IllegalArgumentException("Invalid mode."); |
185 throws IOException | 185 |
186 { | 186 for (int i = 0; i < mode.length(); i++) |
187 Session sess = null; | 187 if (Character.isDigit(mode.charAt(i)) == false) |
188 | 188 throw new IllegalArgumentException("Invalid mode."); |
189 if (null == remoteFile) | 189 |
190 throw new IllegalArgumentException("Null argument."); | 190 remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; |
191 if (null == remoteTargetDirectory) | 191 String cmd = "scp -t -d \"" + remoteTargetDirectory + "\""; |
192 remoteTargetDirectory = ""; | 192 sess = conn.openSession(); |
193 if (null == mode) | 193 sess.execCommand(cmd, charsetName); |
194 mode = "0600"; | 194 return new SCPOutputStream(this, sess, remoteFile, length, mode); |
195 if (mode.length() != 4) | 195 } |
196 throw new IllegalArgumentException("Invalid mode."); | 196 |
197 | 197 /** |
198 for (int i = 0; i < mode.length(); i++) | 198 * The session for opened for this SCP transfer must be closed using |
199 if (Character.isDigit(mode.charAt(i)) == false) | 199 * SCPInputStream#close |
200 throw new IllegalArgumentException("Invalid mode."); | 200 * |
201 | 201 * @param remoteFile |
202 remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; | 202 * @return |
203 | 203 * @throws IOException |
204 String cmd = "scp -t -d \"" + remoteTargetDirectory + "\""; | 204 */ |
205 | 205 public SCPInputStream get(final String remoteFile) throws IOException { |
206 sess = conn.openSession(); | 206 Session sess = null; |
207 sess.execCommand(cmd, charsetName); | 207 |
208 | 208 if (null == remoteFile) |
209 return new SCPOutputStream(this, sess, remoteFile, length, mode); | 209 throw new IllegalArgumentException("Null argument."); |
210 } | 210 |
211 | 211 if (remoteFile.length() == 0) |
212 /** | 212 throw new IllegalArgumentException("Cannot accept empty filename."); |
213 * The session for opened for this SCP transfer must be closed using | 213 |
214 * SCPInputStream#close | 214 String cmd = "scp -f"; |
215 * | 215 cmd += (" \"" + remoteFile + "\""); |
216 * @param remoteFile | 216 sess = conn.openSession(); |
217 * @return | 217 sess.execCommand(cmd, charsetName); |
218 * @throws IOException | 218 return new SCPInputStream(this, sess); |
219 */ | 219 } |
220 public SCPInputStream get(final String remoteFile) throws IOException | |
221 { | |
222 Session sess = null; | |
223 | |
224 if (null == remoteFile) | |
225 throw new IllegalArgumentException("Null argument."); | |
226 | |
227 if (remoteFile.length() == 0) | |
228 throw new IllegalArgumentException("Cannot accept empty filename."); | |
229 | |
230 String cmd = "scp -f"; | |
231 cmd += (" \"" + remoteFile + "\""); | |
232 | |
233 sess = conn.openSession(); | |
234 sess.execCommand(cmd, charsetName); | |
235 | |
236 return new SCPInputStream(this, sess); | |
237 } | |
238 private void sendBytes(Session sess, byte[] data, String fileName, String mode) throws IOException { | 220 private void sendBytes(Session sess, byte[] data, String fileName, String mode) throws IOException { |
239 OutputStream os = sess.getStdin(); | 221 OutputStream os = sess.getStdin(); |
240 InputStream is = new BufferedInputStream(sess.getStdout(), 512); | 222 InputStream is = new BufferedInputStream(sess.getStdout(), 512); |
241 readResponse(is); | 223 readResponse(is); |
242 String cline = "C" + mode + " " + data.length + " " + fileName + "\n"; | 224 String cline = "C" + mode + " " + data.length + " " + fileName + "\n"; |