Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: mindbright/ssh/SSHSCP.java


1   /******************************************************************************
2    *
3    * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4    *                 www.mindbright.se, info@mindbright.se
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation; either version 2 of the License, or
9    * (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   *****************************************************************************
17   * $Author: nallen $
18   * $Date: 2001/11/12 16:31:22 $
19   * $Name:  $
20   *****************************************************************************/
21  package mindbright.ssh;
22  
23  import java.io.*;
24  import java.net.Socket;
25  
26  import mindbright.terminal.Terminal;
27  import mindbright.security.Cipher;
28  
29  public class SSHSCP extends SSHClientUserAdaptor implements SSHConsole {
30  
31      SSHClient       client;
32      SSHInteractor   interactor = null;
33      SSHClientUser   proxyUser  = null;
34      SSHSCPIndicator indicator  = null;
35  
36      SSHInteractor   ourInteractAdapter = null;
37  
38      File    cwd;
39      boolean recursive;
40      boolean verbose;
41  
42      String sshHost;
43  
44      PipedInputStream  inTop;
45      PipedOutputStream inBottom;
46  
47      public SSHSCP(String sshHost, int port, SSHAuthenticator authenticator,
48        File cwd, boolean recursive, boolean verbose) throws IOException {
49    super(sshHost, port);
50  
51    // OUCH: Note must be set before constructing SSHClient since
52    // its constructor calls getInteractor to fetch this
53    //
54    ourInteractAdapter = new SSHInteractorAdapter() {
55        public void open(SSHClient client) {
56      SSHSCP.this.open(client);
57        }
58        public void disconnected(SSHClient client, boolean graceful) {
59      SSHSCP.this.disconnected(client, graceful);
60        }
61        public void alert(String msg) {
62      SSHSCP.this.alert(msg);
63        }
64    };
65  
66    client    = new SSHClient(authenticator, this);
67    inTop     = new PipedInputStream();
68    inBottom  = new PipedOutputStream(inTop);
69    this.cwd       = cwd;
70    this.recursive = recursive;
71    this.verbose   = verbose;
72    this.sshHost   = sshHost;
73  
74    client.setConsole(this);
75    client.activateTunnels = false;
76      }
77  
78      public void setInteractor(SSHInteractor interactor) {
79    this.interactor = interactor;
80      }
81  
82      public void setClientUser(SSHClientUser proxyUser) {
83    this.proxyUser = proxyUser;
84      }
85  
86      public void setIndicator(SSHSCPIndicator indicator) {
87    this.indicator = indicator;
88      }
89  
90      public void abort() {
91    interactor = null;
92    indicator  = null;
93    client.forcedDisconnect();
94      }
95  
96      public void copyToRemote(String localFile, String remoteFile) throws IOException {
97    File lf = new File(localFile);
98  
99    if(!lf.isAbsolute())
100       lf = new File(cwd, localFile);
101 
102   if(!lf.exists()) {
103       throw new IOException("File: " + localFile + " does not exist");
104   }
105   if(!lf.isFile() && !lf.isDirectory()) {
106       throw new IOException("File: " + localFile + " is not a regular file or directory");
107   }
108   if(lf.isDirectory() && !recursive) {
109       throw new IOException("File: " + localFile + " is a directory, use recursive mode");
110   }
111   if(remoteFile == null || remoteFile.equals(""))
112       remoteFile = ".";
113 
114   client.doSingleCommand("scp " + (lf.isDirectory() ? "-d " : "") + "-t " +
115              (recursive ? "-r " : "") + (verbose ? "-v " : "") + remoteFile, true, 0);
116   readResponse("After starting remote scp");
117   writeFileToRemote(lf);
118   client.forcedDisconnect();
119     }
120 
121     public void copyToRemote(String[] localFiles, String remoteFile) throws IOException {
122   if(remoteFile == null || remoteFile.equals(""))
123       remoteFile = ".";
124   if(localFiles.length == 1) {
125       copyToRemote(localFiles[0], remoteFile);
126   } else {
127       client.doSingleCommand("scp " + "-d -t " + (recursive ? "-r " : "") +
128            (verbose ? "-v " : "") + remoteFile, true, 0);
129       readResponse("After starting remote scp");
130       for(int i = 0; i < localFiles.length; i++) {
131     File lf = new File(localFiles[i]);
132     if(!lf.isAbsolute())
133         lf = new File(cwd, localFiles[i]);
134     if(!lf.isFile() && !lf.isDirectory()) {
135         alert("File: " + lf.getName() + " is not a regular file or directory");
136         continue;
137     }
138     writeFileToRemote(lf);
139       }
140       client.forcedDisconnect();
141   }
142     }
143 
144     public void copyToLocal(String localFile, String remoteFile) throws IOException {
145   if(localFile == null || localFile.equals(""))
146       localFile = ".";
147 
148   File lf = new File(localFile);
149   if(!lf.isAbsolute())
150       lf = new File(cwd, localFile);
151 
152   if(lf.exists() && !lf.isFile() && !lf.isDirectory()) {
153       throw new IOException("File: " + localFile + " is not a regular file or directory");
154   }
155   client.doSingleCommand("scp " + "-f " + (recursive ? "-r " : "") + (verbose ? "-v " : "") +
156              remoteFile, true, 0);
157   readFromRemote(lf);
158   client.forcedDisconnect();
159     }
160 
161     boolean writeDirToRemote(File dir) throws IOException {
162   if(!recursive) {
163       writeError("File " + dir.getName() + " is a directory, use recursive mode");
164       return false;
165   }
166   writeString("D0755 0 " + dir.getName() + "\n");
167   if(indicator != null)
168       indicator.startDir(dir.getAbsolutePath());
169   readResponse("After sedning dirdata");
170   String[] dirList = dir.list();
171   for(int i = 0; i < dirList.length; i++) {
172       File f = new File(dir, dirList[i]);
173       writeFileToRemote(f);
174   }
175   writeString("E\n");
176   if(indicator != null)
177       indicator.endDir();
178   return true;
179     }
180 
181     void writeFileToRemote(File file) throws IOException {
182   if(file.isDirectory()) {
183       if(!writeDirToRemote(file))
184     return;
185   } else if(file.isFile()) {
186       writeString("C0644 " + file.length() + " " + file.getName() + "\n");
187       if(indicator != null)
188     indicator.startFile(file.getName(), (int)file.length());
189       readResponse("After sending filedata");
190       FileInputStream fi = new FileInputStream(file);
191       writeFully(fi, (int)file.length());
192       writeByte(0);
193       if(indicator != null)
194     indicator.endFile();
195   } else {
196       throw new IOException("Not ordinary file: " + file.getName());
197   }
198   readResponse("After writing file");
199     }
200 
201     void readFromRemote(File file) throws IOException {
202   String   cmd;
203   String[] cmdParts = new String[3];
204   writeByte(0);
205   while(true) {
206       do {
207     try {
208         cmd = readString();
209     } catch (EOFException e) {
210         return;
211     }
212       } while(cmd == null);
213       char cmdChar = cmd.charAt(0);
214       switch(cmdChar) {
215       case 'E':
216     writeByte(0);
217     return;
218       case 'T':
219     // !!!
220     System.out.println("(T)ime not supported: " + cmd);
221     break;
222       case 'C':
223       case 'D':
224     String targetName = file.getAbsolutePath();
225     parseCommand(cmd, cmdParts);
226     if(file.isDirectory()) {
227         targetName += File.separator + cmdParts[2];
228     }
229     File targetFile = new File(targetName);
230     if(cmdChar == 'D') {
231         if(targetFile.exists()) {
232       if(!targetFile.isDirectory())
233           writeError("Invalid target " + targetFile.getName() +
234                ", must be a directory");
235         } else {
236       if(!targetFile.mkdir())
237           writeError("Could not create directory: " + targetFile.getName());
238         }
239         if(indicator != null)
240       indicator.startDir(targetFile.getAbsolutePath());
241         readFromRemote(targetFile);
242         if(indicator != null)
243       indicator.endDir();
244         continue;
245     }
246     FileOutputStream fo = new FileOutputStream(targetFile);
247     writeByte(0);
248     int len = Integer.parseInt(cmdParts[1]);
249     if(indicator != null)
250         indicator.startFile(targetFile.getName(), len);
251     readFully(fo, len);
252     readResponse("After reading file");
253     if(indicator != null)
254         indicator.endFile();
255     writeByte(0);
256     break;
257       default:
258     writeError("Unexpected cmd: " + cmd);
259     throw new IOException("Unexpected cmd: " + cmd);
260       }
261   }
262     }
263 
264     void parseCommand(String cmd, String[] cmdParts) throws IOException {
265   int l, r;
266   l = cmd.indexOf(' ');
267   r = cmd.indexOf(' ', l + 1);
268   if(l == -1 || r == -1) {
269       writeError("Syntax error in cmd");
270       throw new IOException("Syntax error in cmd");
271   }
272   cmdParts[0] = cmd.substring(1, l);
273   cmdParts[1] = cmd.substring(l + 1, r);
274   cmdParts[2] = cmd.substring(r + 1);
275     }
276 
277     void readResponse(String where) throws IOException {
278   int r = readByte();
279   if(r == 0) {
280       // All is well, no error
281       return;
282   }
283   String errMsg = readString();
284   if(r == (byte)'\02')
285       throw new IOException(errMsg);
286   alert(errMsg);
287     }
288 
289     void writeError(String reason) throws IOException {
290   writeByte(1);
291   writeString(reason);
292   alert(reason);
293     }
294 
295     int readByte() throws IOException {
296   return inTop.read();
297     }
298 
299     String readString() throws IOException {
300   byte[] buf = new byte[2048];
301   int ch, i = 0;
302   while(((ch = readByte()) != ((int)'\n')) && ch >= 0) {
303       buf[i++] = (byte)ch;
304   }
305   if(ch == -1) {
306       throw new EOFException();
307   }
308   if(buf[0] == (byte)'\n')
309       throw new IOException("Unexpected <NL>");
310   if(buf[0] == (byte)'\02' || buf[0] == (byte)'\01') {
311       // !!!
312       String errMsg = new String(buf, 1, i - 1);
313       if(buf[0] == (byte)'\02')
314     throw new IOException(errMsg);
315       alert(errMsg);
316       return null;
317   }
318   return new String(buf, 0, i);
319     }
320 
321     void readFully(FileOutputStream file, int size) throws IOException {
322   byte[] buf = new byte[2048];
323   int cnt = 0, n;
324   while(cnt < size) {
325       n = inTop.read(buf, 0, ((size - cnt) < 2048 ? (size - cnt) : 2048));
326       if(n == -1) {
327     alert("Premature EOF");
328     throw new IOException("Premature EOF");
329       }
330       cnt += n;
331       file.write(buf, 0, n);
332       if(indicator != null)
333     indicator.progress(n);
334   }
335   file.close();
336     }
337 
338     void writeByte(int b) throws IOException {
339   byte[] buf = new byte[1];
340   buf[0] = (byte)b;
341   client.stdinWriteString(buf);
342     }
343 
344     void writeString(String str) throws IOException {
345   byte[] buf = str.getBytes();
346   client.stdinWriteString(buf);
347     }
348 
349     void writeFully(FileInputStream file, int size) throws IOException {
350   byte[] buf = new byte[2048];
351   int cnt = 0, n;
352   while(cnt < size) {
353       n = file.read(buf, 0, ((size - cnt) < 2048 ? (size - cnt) : 2048));
354       if(n == -1)
355     throw new IOException("Premature EOF");
356       cnt += n;
357       client.stdinWriteString(buf, 0, n);
358       if(indicator != null)
359     indicator.progress(n);
360       Thread.yield();
361   }
362   file.close();
363     }
364 
365     public void stdoutWriteString(byte[] str) {
366   try {
367       inBottom.write(str);
368   } catch(IOException e) {
369       try {
370     inBottom.close();
371       } catch (IOException ee) {
372     // !!!
373       }
374       alert("Error writing data to stdout-pipe");
375   }
376     }
377 
378     public void stderrWriteString(byte[] str) {
379   if(verbose) alert("Remote warning/error: " + new String(str));
380     }
381 
382     public Terminal getTerminal() {
383   return null;
384     }
385     public void print(String str) {
386     }
387     public void println(String str) {
388     }
389     public void serverConnect(SSHChannelController controller, Cipher sndCipher) {
390     }
391     public void serverDisconnect(String reason) {
392     }
393     public boolean wantPTY() {
394   return false;
395     }
396     public void open(SSHClient client) {
397   if(indicator != null)
398       indicator.connected(sshHost);
399     }
400     public void disconnected(SSHClient client, boolean graceful) {
401   try {
402       inBottom.close();
403   } catch (IOException e) {
404       // !!!
405   }
406     }
407     public void alert(String msg) {
408   if(interactor != null) {
409       interactor.alert(msg);
410   }
411     }
412 
413     public Socket getProxyConnection() throws IOException {
414   if(proxyUser != null) {
415       return proxyUser.getProxyConnection();
416   }
417   return null;
418     }
419 
420     public SSHInteractor getInteractor() {
421   return ourInteractAdapter;
422     }
423 
424     /* !!! TESTING !!!
425     public static void main(String[] argv) {
426   try {
427       SSHSCP scp = new SSHSCP("hal", 22, new SSHPasswordAuthenticator("mats", "********"),
428                               new File("."), true, true);
429       String[] files = { "foo.h", "foo.c" };
430       scp.copyToRemote(files, "");
431       scp.copyToRemote(files, "foodir");
432       scp.copyToRemote("dummies/", "");
433       scp.copyToLocal("bar.c", "foo.c");
434       scp.copyToLocal("", "foodir");
435       System.exit(0);
436   } catch (IOException e) {
437       System.out.println("Error here: " + e);
438       e.printStackTrace();
439   }
440     }
441     */
442 
443 }