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

Quick Search    Search Deep

Source code: mindbright/ssh/SSHStdIO.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:23 $
19   * $Name:  $
20   *****************************************************************************/
21  package mindbright.ssh;
22  
23  import java.io.*;
24  import java.awt.*;
25  import java.awt.datatransfer.*;
26  
27  import mindbright.terminal.*;
28  import mindbright.security.*;
29  
30  public final class SSHStdIO implements TerminalListener, TerminalClipboard, SSHConsole {
31  
32    static public class CtrlDPressedException extends IOException {
33    }
34  
35    static public class SSHExternalMessage extends IOException {
36      public SSHExternalMessage(String msg) {
37        super(msg);
38      }
39    }
40  
41    static Toolkit toolkit;
42  
43    SSHCommandShell      commandShell;
44  
45    Container            ownerContainer;
46    SSHChannelController controller;
47    SSHInteractiveClient client;
48    //
49    // !!! Changed this to TerminalWin instead of Terminal, we were
50    // almost asuming it anyway (theoretical performance gain too! :-)
51    //
52    TerminalWin          term;
53  
54    Cipher               sndCipher;
55    String               ownerName;
56  
57    boolean              selectionAvailable = false;
58  
59    boolean              escapeForced = false;
60  
61    Boolean readLineLock;
62    boolean pressedCtrlD;
63    boolean isReadingLine;
64    boolean echoStar;
65    String  readLineStr;
66  
67    protected boolean isConnected;
68  
69    // The clipboard now is shared with all instances
70    //
71    static Clipboard localClipboard = null;
72  
73    public SSHStdIO() {
74      this.readLineLock   = new Boolean(false);
75      this.controller     = null;
76      this.sndCipher      = null;
77      this.isConnected    = false;
78      this.commandShell   = null;
79    }
80  
81    public boolean isConnected() {
82      return isConnected;
83    }
84  
85    public void setTerminal(TerminalWin term) {
86      this.term = term;
87      if(term != null) {
88        term.addTerminalListener(this);
89        term.addTerminalClipboard(this);
90      }
91    }
92  
93    public void setClient(SSHInteractiveClient client) {
94      this.client = client;
95    }
96  
97    public void setOwnerContainer(Container ownerContainer) {
98      this.ownerContainer = ownerContainer;
99      if(toolkit == null)
100   toolkit = Toolkit.getDefaultToolkit();
101   }
102 
103   public void setOwnerName(String ownerName) {
104     this.ownerName = ownerName;
105   }
106 
107   public boolean hasCommandShell() {
108     return (this.commandShell != null);
109   }
110 
111   public void enableCommandShell(boolean enable) {
112     if(enable) {
113       try {
114     Class c;
115     c = Class.forName("mindbright.ssh.SSHCommandShellImpl");
116     this.commandShell = (SSHCommandShell)c.newInstance();
117     this.commandShell.setStdIO(this);
118       } catch (Throwable t) {
119     println("");
120     println("The local command-shell is not available in this distribution.");
121       }
122     } else {
123       this.commandShell = null;
124     }
125   }
126 
127   public void wantCommandShell() {
128     escapeForced = true;
129   }
130 
131   SSHExternalMessage extMsg = null;
132   public void breakPromptLine(String msg) {
133     if(isReadingLine) {
134       synchronized(readLineLock) {
135   extMsg = new SSHExternalMessage(msg);
136   readLineLock.notify();
137       }
138     }
139   }
140 
141   public String readLine(String defaultVal) {
142     synchronized(readLineLock) {
143       if(defaultVal != null) {
144   readLineStr   = defaultVal;
145   term.write(defaultVal);
146       } else {
147   readLineStr   = "";
148       }
149       isReadingLine = true;
150       try {
151   readLineLock.wait();
152       } catch (InterruptedException e) {
153   // !!!
154       }
155       isReadingLine = false;
156     }
157     return readLineStr;
158   }
159 
160   public String promptLine(String prompt, String defaultVal, boolean echoStar) throws IOException {
161     String line = null;
162     pressedCtrlD = false;
163     if(term != null) {
164       term.setAttribute(Terminal.ATTR_BOLD, true);
165       term.write(prompt);
166       term.setAttribute(Terminal.ATTR_BOLD, false);
167       this.echoStar = echoStar;
168       line = readLine(defaultVal);
169       this.echoStar = false;
170     } else {
171       BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
172       System.out.print(prompt);
173       line = br.readLine();
174 
175       // !!! kludge, winlost doesn't give empty input with ^D, this is a kludgy thing
176       //  anyway since we're not sure that ^D is EOF in the shell...
177       //
178       if(line == null || (line.length() > 0 && line.charAt(0) == (char)4))
179   pressedCtrlD = true;
180     }
181     if(extMsg != null) {
182       SSHExternalMessage msg = extMsg;
183       extMsg = null;
184       throw msg;
185     }
186     if((commandShell != null || client.isDumb()) && pressedCtrlD) {
187       pressedCtrlD = false;
188       throw new CtrlDPressedException();
189     }
190 
191     return line;
192   }
193 
194   public void updateTitle() {
195     int rows = 0;
196     int cols = 0;
197 
198     if(term == null || ownerContainer == null)
199       return;
200 
201     String title = null;
202     title = term.getTitle();
203 
204     if(title == null) {
205   rows = term.rows();
206   cols = term.cols();
207 
208   if(client.isOpened()) {
209       title = client.propsHandler.getProperty("usrname");
210       title += "@" + client.propsHandler.getProperty("server");
211       title += " <" + client.getServerVersion() + ">";
212   } else {
213       title = ownerName;
214   }
215 
216   title += " [" + cols + "x" + rows + "]";
217 
218   if(!client.activateTunnels) {
219       title += " (CLONE)";
220   }
221     }
222 
223     if(ownerContainer instanceof Frame)
224       ((Frame)ownerContainer).setTitle(title);
225   }
226 
227   // SSHConsole interface
228   //
229   public Terminal getTerminal() {
230     return term;
231   }
232   public void stdoutWriteString(byte[] str) {
233     if(isConnected)
234       print(new String(str));
235   }
236   public void stderrWriteString(byte[] str) {
237     if(isConnected)
238       print(new String(str));
239   }
240   public void print(String str) {
241     if(term != null) {
242       term.write(str);
243     } else {
244       System.out.print(str);
245     }
246   }
247   public void println(String str) {
248     if(term != null) {
249       term.write(str + "\n\r");
250     } else {
251       System.out.println(str);
252     }
253   }
254   public void serverConnect(SSHChannelController controller, Cipher sndCipher) {
255     this.controller  = controller;
256     this.sndCipher   = sndCipher;
257     isConnected      = true;
258   }
259   public void serverDisconnect(String reason) {
260     this.controller  = null;
261     this.sndCipher   = null;
262     isConnected      = false;
263     println(reason);
264   }
265 
266   // TerminalListener interface
267   //
268   public void typedChar(char c) throws IOException {
269     if(isConnected) {
270       if(escapeForced || (commandShell != null && commandShell.escapeSequenceTyped(c))) {
271   escapeForced = false;
272   commandShell.launchCommandShell();
273       } else {
274   client.stdinWriteChar(c);
275       }
276     } else {
277       synchronized(readLineLock) {
278   if(isReadingLine) {
279           if(c == (char)4 && commandShell != null) {
280       // !!! We are not interested in ctrl-d for other things than entering the command-shell
281       // Pressed ctrl-d
282       pressedCtrlD = true;
283       readLineLock.notify();
284     } else if(c == (char)127 || c == (char)0x08) {
285       if(readLineStr.length() > 0) {
286     boolean ctrlChar = false;
287     if(readLineStr.charAt(readLineStr.length() - 1) < ' ') {
288         ctrlChar = true;
289     }
290         readLineStr = readLineStr.substring(0, readLineStr.length() - 1);
291         term.write((char)8);
292         if(ctrlChar) term.write((char)8);
293         term.write(' ');
294         if(ctrlChar) term.write(' ');
295         term.write((char)8);
296         if(ctrlChar) term.write((char)8);
297       } else
298         term.doBell();
299     } else if(c == '\r') {
300       //      readLineStr = readLineStr + "\r";
301       readLineLock.notify();
302       term.write("\n\r");
303     } else {
304       readLineStr = readLineStr + c;
305       if(echoStar)
306         term.write('*');
307       else
308         term.write(c);
309     }
310   }
311       }
312     }
313   }
314   public void sendBytes(byte[] b) throws IOException {
315     if(isConnected) {
316       client.stdinWriteString(b);
317     } else {
318       for(int i = 0; i < b.length; i++)
319   typedChar((char)b[i]);
320     }
321   }
322   public void signalWindowChanged(int rows, int cols, int vpixels, int hpixels) {
323     if(isConnected) {
324       client.signalWindowChanged(rows, cols, vpixels, hpixels);
325     } else {
326       // !!!
327     }
328     updateTitle();
329   }
330   public void setSelection(String selection) {
331     Clipboard cb = getClipboard();
332     if(cb == null || term == null)
333       return;
334     if(selection == null)
335       selection = "";
336     StringSelection sl = new StringSelection(selection);
337     cb.setContents(sl, sl);
338   }
339   public String getSelection() {
340     Clipboard cb = getClipboard();
341     String    sl = null;
342     if(cb == null || term == null)
343       return sl;
344     Transferable t = cb.getContents(this);
345     if(t != null) {
346       try {
347   sl = (String) t.getTransferData(DataFlavor.stringFlavor);
348       } catch (Exception e) {
349         try {
350     toolkit.beep();
351   } catch (Throwable ee) {
352     // !!! Could not beep, we are probably an unpriviliged applet
353   }
354       }
355     } else
356       try {
357         toolkit.beep();
358       } catch (Throwable e) {
359   // !!! Could not beep, we are probably an unpriviliged applet
360       }
361     return sl;
362   }
363   public void selectionAvailable(boolean val) {
364     selectionAvailable = val;
365     client.updateMenus();
366   }
367 
368   static synchronized Clipboard getClipboard() {
369     /*if(SSH.NETSCAPE_SECURITY_MODEL) {
370       try {
371   netscape.security.PrivilegeManager.enablePrivilege("UniversalSystemClipboardAccess");
372       } catch (netscape.security.ForbiddenTargetException e) {
373   // !!!
374       }
375      }*/
376 
377     Clipboard cb;
378     if(localClipboard == null) {
379       try {
380   cb = toolkit.getSystemClipboard();
381       } catch (Throwable e) {
382   cb = localClipboard = new Clipboard("MindTerm-local-clipboard");
383       }
384     } else {
385       cb = localClipboard;
386     }
387     return cb;
388   }
389 
390 }