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";