comparison src/ch/ethz/ssh2/SCPClient.java @ 273:91a31873c42a ganymed

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