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

Quick Search    Search Deep

Source code: mindbright/application/MindVNC.java


1   //
2   //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
3   //
4   //  This is free software; you can redistribute it and/or modify
5   //  it under the terms of the GNU General Public License as published by
6   //  the Free Software Foundation; either version 2 of the License, or
7   //  (at your option) any later version.
8   //
9   //  This software is distributed in the hope that it will be useful,
10  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  //  GNU General Public License for more details.
13  //
14  //  You should have received a copy of the GNU General Public License
15  //  along with this software; if not, write to the Free Software
16  //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
17  //  USA.
18  //
19  
20  //
21  // MindVNC.java - the VNC viewer class.  This class mainly just sets up the
22  // user interface, leaving it to the vncCanvas to do the actual rendering of
23  // a VNC desktop.
24  //
25  package mindbright.application;
26  
27  import java.awt.*;
28  import java.awt.event.*;
29  import java.io.*;
30  
31  import mindbright.ssh.*;
32  import mindbright.vnc.*;
33  
34  public class MindVNC extends java.applet.Applet
35             implements java.lang.Runnable
36  {
37    boolean inAnApplet = true;
38    boolean separateFrame;
39  
40    Container cont;
41  
42    //
43    // main() is called when run as a java program from the command line.  It
44    // simply creates a frame and runs the applet inside it.
45    //
46  
47    public static void main(String[] argv) {
48      MindVNC v = new MindVNC();
49      v.mainArgs = argv;
50      v.inAnApplet = false;
51  
52      v.f = new Frame("MindVNC v0.1");
53      v.f.add("Center", v);
54  
55      v.init();
56      v.start();
57    }
58  
59    Frame f;
60    String[] mainArgs;
61  
62    String sshHost;
63    int    sshPort;
64    String vncHost;
65    int    vncPort;
66    String sshUser;
67    String sshPasswd;
68  
69    ScrollPane sp;
70    vncCanvas vc;
71    public rfbProto rfb;
72    Thread rfbThread;
73    GridBagLayout gridbag;
74    Panel buttonPanel;
75    Button disconnectButton;
76    Button optionsButton;
77    Button clipboardButton;
78    Button ctrlAltDelButton;
79    authenticationPanel authenticator;
80  
81    public optionsFrame options;
82    public clipboardFrame clipboard;
83  
84    //
85    // init()
86    //
87  
88    public void init() {
89  
90      readParameters();
91  
92      if(inAnApplet && separateFrame)
93    cont = f = new Frame("MindVNC v0.1");
94      else
95    cont = this;
96  
97      if(f != null) {
98    f.addWindowListener(new WindowAdapter() {
99        public void windowClosing(WindowEvent e)  { f.dispose(); rfbThread.stop();
100       if(!inAnApplet) System.exit(1); }
101   });
102     }
103 
104 
105     options = new optionsFrame(this);
106     clipboard = new clipboardFrame(this);
107     authenticator = new authenticationPanel();
108 
109     rfbThread = new Thread(this);
110     rfbThread.start();
111   }
112 
113   public void update(Graphics g) {
114   }
115 
116   //
117   // run() - executed by the rfbThread to deal with the RFB socket.
118   //
119 
120   public void run() {
121 
122     gridbag = new GridBagLayout();
123     cont.setLayout(gridbag);
124 
125     buttonPanel = new Panel();
126     buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
127     disconnectButton = new Button("Disconnect");
128     buttonPanel.add(disconnectButton);
129     optionsButton = new Button("Options");
130     buttonPanel.add(optionsButton);
131     clipboardButton = new Button("Clipboard");
132     buttonPanel.add(clipboardButton);
133     ctrlAltDelButton = new Button("Send Ctrl-Alt-Del");
134     buttonPanel.add(ctrlAltDelButton);
135 
136     GridBagConstraints gbc = new GridBagConstraints();
137     gbc.gridwidth = GridBagConstraints.REMAINDER;
138     gbc.anchor = GridBagConstraints.NORTHWEST;
139     gridbag.setConstraints(buttonPanel,gbc);
140     cont.add(buttonPanel);
141 
142     disconnectButton.addActionListener(new ActionListener() {
143   public void actionPerformed(ActionEvent e) {
144       buttonPressed(0);
145   }
146     });
147     optionsButton.addActionListener(new ActionListener() {
148   public void actionPerformed(ActionEvent e) {
149       buttonPressed(1);
150   }
151     });
152     clipboardButton.addActionListener(new ActionListener() {
153   public void actionPerformed(ActionEvent e) {
154       buttonPressed(2);
155   }
156     });
157     ctrlAltDelButton.addActionListener(new ActionListener() {
158   public void actionPerformed(ActionEvent e) {
159       buttonPressed(3);
160   }
161     });
162 
163 
164     while(true) {
165 
166       disconnectButton.disable();
167       clipboardButton.disable();
168       ctrlAltDelButton.disable();
169 
170       try {
171   connectAndAuthenticate();
172 
173   rfb.doProtocolInitialisation(options.encodings, options.nEncodings);
174 
175   vc = new vncCanvas(this);
176 
177   sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
178   gbc.weightx = 1.0;
179   gbc.weighty = 1.0;
180   gbc.fill    = GridBagConstraints.BOTH;
181   gridbag.setConstraints(sp,gbc);
182   cont.add(sp);
183 
184   if(f != null) {
185     int sbw = sp.getVScrollbarWidth();
186     int sbh = sp.getHScrollbarHeight();
187     Dimension max  = Toolkit.getDefaultToolkit().getScreenSize();
188     Insets    fIns = f.getInsets();
189     max.width -= (fIns.left + fIns.right + sbw);
190     max.height -= (fIns.top + fIns.bottom + sbh);
191     int w = max.width > rfb.framebufferWidth + 4 ? rfb.framebufferWidth + 4 : max.width;
192     int h = max.height > rfb.framebufferHeight + 4 ? rfb.framebufferHeight + 4 : max.height;
193     sp.setSize(new Dimension(w, h));
194   } else {
195     sp.setSize(getSize());
196   }
197   sp.add(vc);
198 
199   if(f != null) {
200     f.setTitle(rfb.desktopName);
201     f.pack();
202   } else {
203     validate();
204   }
205 
206   disconnectButton.enable();
207   clipboardButton.enable();
208   ctrlAltDelButton.enable();
209 
210   vc.processNormalProtocol();
211   cont.remove(sp);
212 
213       } catch (Exception e) {
214     e.printStackTrace();
215     fatalError(e.toString());
216       }
217     }
218   }
219 
220 
221   //
222   // Connect to the RFB server and authenticate the user.
223   //
224 
225   void connectAndAuthenticate() throws IOException {
226 
227     GridBagConstraints gbc = new GridBagConstraints();
228     gbc.gridwidth = GridBagConstraints.REMAINDER;
229     gbc.anchor = GridBagConstraints.NORTHWEST;
230     gbc.weightx = 1.0;
231     gbc.weighty = 1.0;
232     gbc.ipadx = 100;
233     gbc.ipady = 50;
234     gridbag.setConstraints(authenticator,gbc);
235     cont.add(authenticator);
236 
237     validate();
238     if(f != null) {
239       f.pack();
240       f.show();
241     }
242 
243     boolean authenticationDone = false;
244 
245     while (!authenticationDone) {
246 
247       synchronized(authenticator) {
248   try {
249     authenticator.wait();
250   } catch (InterruptedException e) {
251   }
252       }
253 
254       sshUser   = authenticator.sshUser.getText();
255       sshPasswd = authenticator.sshPassword.getText();
256       vncHost   = authenticator.vncHost.getText();
257       vncPort   = 5900;
258 
259       int ix;
260       if((ix = vncHost.indexOf(':')) != -1) {
261     try {
262         vncPort += Integer.parseInt(vncHost.substring(ix + 1));
263     } catch (NumberFormatException e) {
264         authenticator.retry("VNC host-string format error");
265         continue;
266     }
267     vncHost = vncHost.substring(0, ix);
268       }
269 
270       try {
271     rfb = new rfbProto(sshHost, sshPort, sshUser, sshPasswd, vncHost, vncPort, this);
272       } catch (java.net.ConnectException e) {
273     System.out.println("Connect...");
274     authenticator.retry("VNC host, connection refused");
275     continue;
276       } catch (java.io.IOException e) {
277     System.out.println("IO...");
278     authenticator.retry("SSH error: " + e.getMessage());
279     continue;
280       }
281 
282       if(rfb.connectAndAuthenticate(authenticator))
283   break;
284     }
285 
286     cont.remove(authenticator);
287   }
288 
289   int getInt(byte[] b, int o) {
290       int i = ( ( b[o + 0] & 0xff ) << 24 ) |
291         ( ( b[o + 1] & 0xff ) << 16 ) |
292         ( ( b[o + 2] & 0xff ) <<  8 ) |
293         ( b[o + 3] & 0xff );
294       return i;
295   }
296 
297   void putInt(byte[] b, int o, int i) {
298       b[o + 0] = (byte) ( i >>> 24 );
299       b[o + 1] = (byte) ( i >>> 16 );
300       b[o + 2] = (byte) ( i >>>  8 );
301       b[o + 3] = (byte)   i;
302   }
303 
304   //
305   // setCutText() - send the given cut text to the RFB server.
306   //
307 
308   public void setCutText(String text) {
309     try {
310       if ((rfb != null) && rfb.inNormalProtocol) {
311   rfb.writeClientCutText(text);
312       }
313     } catch (Exception e) {
314       e.printStackTrace();
315     }
316   }
317 
318 
319   //
320   // Respond to button presses
321   //
322 
323   public void buttonPressed(int buttonNum) {
324       switch(buttonNum) {
325       case 0:
326     rfb.close();
327     rfb = null;
328     break;
329       case 1:
330     if (options.isVisible()) {
331         options.hide();
332     } else {
333         options.show();
334     }
335     break;
336       case 2:
337     if (clipboard.isVisible()) {
338         clipboard.hide();
339     } else {
340         clipboard.show();
341     }
342     break;
343       case 3:
344     rfb.sendCtrlAltDel();
345       }
346   }
347 
348 
349   //
350   // Detect when the focus goes in and out of the applet.  See
351   // vncCanvas.handleEvent() for details of why this is necessary.
352   //
353 
354   public boolean gotFocus = false;
355 
356   public boolean gotFocus(Event evt, Object what) {
357     gotFocus = true;
358     return true;
359   }
360   public boolean lostFocus(Event evt, Object what) {
361     gotFocus = false;
362     return true;
363   }
364 
365 
366   //
367   // encryptBytes() - encrypt some bytes in memory using a password.  Note that
368   // the mapping from password to key must be the same as that used on the rfb
369   // server side.
370   //
371   // Note also that IDEA encrypts data in 8-byte blocks, so here we will ignore
372   // any data beyond the last 8-byte boundary leaving it to the calling
373   // function to pad the data appropriately.
374   //
375 
376   void encryptBytes(byte[] bytes, String passwd) {
377     byte[] key = new byte[8];
378     passwd.getBytes(0, passwd.length(), key, 0);
379 
380     for (int i = passwd.length(); i < 8; i++) {
381       key[i] = (byte)0;
382     }
383 
384     DesCipher des = new DesCipher(key);
385 
386     des.encrypt(bytes,0,bytes,0);
387     des.encrypt(bytes,8,bytes,8);
388   }
389 
390 
391   //
392   // readParameters() - read parameters from the html source or from the
393   // command line.  On the command line, the arguments are just a sequence of
394   // param_name/param_value pairs where the names and values correspond to
395   // those expected in the html applet tag source.
396   //
397 
398   public void readParameters() {
399     sshHost = readParameter("sshhost", !inAnApplet);
400     if (sshHost == null) {
401       sshHost = getCodeBase().getHost();
402       if (sshHost.equals("")) {
403   fatalError("Not able to determine sshhost");
404       }
405     }
406 
407     String s = readParameter("sshport", false);
408     if(s != null)
409   sshPort = Integer.parseInt(s);
410     else
411   sshPort = SSH.DEFAULTPORT;
412 
413     try {
414       separateFrame = (new Boolean(getParameter("sepframe"))).booleanValue();
415     } catch (Exception e) {
416       separateFrame = true;
417     }
418 
419   }
420 
421   public String readParameter(String name, boolean required) {
422     if (inAnApplet) {
423       String s = getParameter(name);
424       if ((s == null) && required) {
425   fatalError(name + " parameter not specified");
426       }
427       return s;
428     }
429 
430     for (int i = 0; i < mainArgs.length; i += 2) {
431       if (mainArgs[i].equalsIgnoreCase(name)) {
432   try {
433     return mainArgs[i+1];
434   } catch (Exception e) {
435     if (required) {
436       fatalError(name + " parameter not specified");
437     }
438     return null;
439   }
440       }
441     }
442     if (required) {
443       fatalError(name + " parameter not specified");
444     }
445     return null;
446   }
447 
448   //
449   // fatalError() - print out a fatal error message.
450   //
451 
452   public void fatalError(String s) {
453     System.out.println(s);
454 
455     if (inAnApplet) {
456       cont.removeAll();
457       Label l = new Label(s);
458 
459       setLayout(new FlowLayout(FlowLayout.LEFT, 30, 30));
460       cont.add(l);
461       validate();
462       Thread.currentThread().stop();
463     } else {
464       System.exit(1);
465     }
466   }
467 }