1 /*
2 * SSHTools - Java SSH2 API
3 *
4 * Copyright (C) 2002-2003 Lee David Painter and Contributors.
5 *
6 * Contributions made by:
7 *
8 * Brett Smith
9 * Richard Pernavas
10 * Erwin Bolwidt
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26 package com.sshtools.common.ui;
27
28 import com.sshtools.common.authentication.AuthenticationDialog;
29 import com.sshtools.common.authentication.BannerDialog;
30 import com.sshtools.common.authentication.KBIRequestHandlerDialog;
31 import com.sshtools.common.authentication.PasswordAuthenticationDialog;
32 import com.sshtools.common.authentication.PasswordChange;
33 import com.sshtools.common.authentication.PublicKeyAuthenticationPrompt;
34 import com.sshtools.common.automate.RemoteIdentification;
35 import com.sshtools.common.automate.RemoteIdentificationException;
36 import com.sshtools.common.automate.RemoteIdentificationFactory;
37 import com.sshtools.common.configuration.InvalidProfileFileException;
38 import com.sshtools.common.configuration.SshToolsConnectionProfile;
39 import com.sshtools.common.hosts.DialogKnownHostsKeyVerification;
40
41 import com.sshtools.j2ssh.SshClient;
42 import com.sshtools.j2ssh.SshException;
43 import com.sshtools.j2ssh.SshThread;
44 import com.sshtools.j2ssh.agent.AgentAuthenticationClient;
45 import com.sshtools.j2ssh.agent.AgentNotAvailableException;
46 import com.sshtools.j2ssh.agent.SshAgentClient;
47 import com.sshtools.j2ssh.authentication.AuthenticationProtocolState;
48 import com.sshtools.j2ssh.authentication.KBIAuthenticationClient;
49 import com.sshtools.j2ssh.authentication.PasswordAuthenticationClient;
50 import com.sshtools.j2ssh.authentication.PublicKeyAuthenticationClient;
51 import com.sshtools.j2ssh.authentication.SshAuthenticationClient;
52 import com.sshtools.j2ssh.authentication.SshAuthenticationClientFactory;
53 import com.sshtools.j2ssh.configuration.ConfigurationLoader;
54 import com.sshtools.j2ssh.transport.AbstractKnownHostsKeyVerification;
55 import com.sshtools.j2ssh.transport.HostKeyVerification;
56 import com.sshtools.j2ssh.transport.InvalidHostFileException;
57 import com.sshtools.j2ssh.transport.TransportProtocolException;
58 import com.sshtools.j2ssh.transport.TransportProtocolState;
59 import com.sshtools.j2ssh.transport.publickey.SshPublicKey;
60
61 import org.apache.commons.logging.Log;
62 import org.apache.commons.logging.LogFactory;
63
64 import java.awt.Frame;
65 import java.awt.LayoutManager;
66
67 import java.io.File;
68 import java.io.FilePermission;
69 import java.io.IOException;
70
71 import java.security.AccessControlException;
72 import java.security.AccessController;
73
74 import java.util.Comparator;
75 import java.util.HashMap;
76 import java.util.Iterator;
77 import java.util.Map;
78
79 import javax.swing.JFileChooser;
80 import javax.swing.JOptionPane;
81 import javax.swing.SwingConstants;
82 import javax.swing.SwingUtilities;
83 import javax.swing.UIManager;
84 import javax.swing.filechooser.FileFilter;
85
86
87 /**
88 *
89 *
90 * @author $author$
91 * @version $Revision: 1.24 $
92 */
93 public abstract class SshToolsApplicationClientPanel
94 extends SshToolsApplicationPanel {
95 /** */
96 public final static String PREF_CONNECTION_FILE_DIRECTORY = "sshapps.connectionFile.directory";
97
98 //
99
100 /** */
101 public final static int BANNER_TIMEOUT = 2000;
102
103 /** */
104 protected static AbstractKnownHostsKeyVerification ver;
105
106 //
107
108 /** */
109 protected Log log = LogFactory.getLog(SshToolsApplicationClientPanel.class);
110
111 /** */
112 protected HostKeyVerification hostKeyVerification;
113
114 /** */
115 protected File currentConnectionFile;
116
117 /** */
118 protected boolean needSave;
119
120 /** */
121 protected SshToolsConnectionProfile currentConnectionProfile;
122
123 /** */
124 protected javax.swing.filechooser.FileFilter connectionFileFilter = new ConnectionFileFilter();
125
126 /** */
127 protected SshClient ssh;
128
129 /**
130 * Creates a new SshToolsApplicationClientPanel object.
131 */
132 public SshToolsApplicationClientPanel() {
133 super();
134 }
135
136 /**
137 * Creates a new SshToolsApplicationClientPanel object.
138 *
139 * @param mgr
140 */
141 public SshToolsApplicationClientPanel(LayoutManager mgr) {
142 super(mgr);
143 }
144
145 /**
146 *
147 *
148 * @return
149 */
150 public abstract SshToolsConnectionTab[] getAdditionalConnectionTabs();
151
152 /**
153 *
154 *
155 * @return
156 */
157 public HostKeyVerification getHostKeyVerification() {
158 return hostKeyVerification;
159 }
160
161 /**
162 *
163 *
164 * @param hostKeyVerification
165 */
166 public void setHostHostVerification(HostKeyVerification hostKeyVerification) {
167 this.hostKeyVerification = hostKeyVerification;
168 }
169
170 /**
171 *
172 *
173 * @param application
174 *
175 * @throws SshToolsApplicationException
176 */
177 public void init(SshToolsApplication application)
178 throws SshToolsApplicationException {
179 super.init(application);
180
181 try {
182 //if (ver == null) {
183 ver = new DialogKnownHostsKeyVerification(this);
184
185 //}
186 setHostHostVerification(ver);
187
188 if (ver.isHostFileWriteable()) {
189 application.addAdditionalOptionsTab(new HostsTab(ver));
190 }
191 } catch (InvalidHostFileException uhfe) {
192 log.warn("Host key verification will be DISABLED.", uhfe);
193 }
194 }
195
196 /**
197 *
198 */
199 public void editConnection() {
200 // Create a file chooser with the current directory set to the
201 // application home
202 JFileChooser fileDialog = new JFileChooser(PreferencesStore.get(
203 PREF_CONNECTION_FILE_DIRECTORY,
204 System.getProperty("sshtools.home",
205 System.getProperty("user.home"))));
206 fileDialog.setFileFilter(connectionFileFilter);
207
208 // Show it
209 int ret = fileDialog.showOpenDialog(this);
210
211 // If we've approved the selection then process
212 if (ret == fileDialog.APPROVE_OPTION) {
213 PreferencesStore.put(PREF_CONNECTION_FILE_DIRECTORY,
214 fileDialog.getCurrentDirectory().getAbsolutePath());
215
216 // Get the file
217 File f = fileDialog.getSelectedFile();
218
219 // Load the profile
220 SshToolsConnectionProfile p = new SshToolsConnectionProfile();
221
222 try {
223 p.open(f);
224
225 if (editConnection(p)) {
226 saveConnection(false, f, p);
227 }
228 } catch (IOException ioe) {
229 showErrorMessage(this, "Failed to load connection profile.",
230 "Error", ioe);
231 }
232 }
233 }
234
235 /**
236 *
237 *
238 * @param profile
239 *
240 * @return
241 */
242 public SshToolsConnectionProfile newConnectionProfile(
243 SshToolsConnectionProfile profile) {
244 return SshToolsConnectionPanel.showConnectionDialog(SshToolsApplicationClientPanel.this,
245 profile, getAdditionalConnectionTabs());
246 }
247
248 /**
249 *
250 */
251 public void open() {
252 // Create a file chooser with the current directory set to the
253 // application home
254 String prefsDir = super.getApplication()
255 .getApplicationPreferencesDirectory()
256 .getAbsolutePath();
257 JFileChooser fileDialog = new JFileChooser(prefsDir);
258 fileDialog.setFileFilter(connectionFileFilter);
259
260 // Show it
261 int ret = fileDialog.showOpenDialog(this);
262
263 // If we've approved the selection then process
264 if (ret == fileDialog.APPROVE_OPTION) {
265 PreferencesStore.put(PREF_CONNECTION_FILE_DIRECTORY,
266 fileDialog.getCurrentDirectory().getAbsolutePath());
267
268 // Get the file
269 File f = fileDialog.getSelectedFile();
270 open(f);
271 }
272 }
273
274 /**
275 *
276 *
277 * @param f
278 */
279 public void open(File f) {
280 log.debug("Opening connection file " + f);
281
282 // Make sure a connection is not already open
283 if (isConnected()) {
284 Option optNew = new Option("New", "New create a new window", 'n');
285 Option optClose = new Option("Close", "Close current connection",
286 'l');
287 Option optCancel = new Option("Cancel",
288 "Cancel the opening of this connection", 'c');
289 OptionsDialog dialog = OptionsDialog.createOptionDialog(this,
290 new Option[] { optNew, optClose, optCancel },
291 "You already have a connection open. Select\n" +
292 "Close to close the current connection, New\n" +
293 "to create a new terminal or Cancel to abort.",
294 "Existing connection", optNew, null,
295 UIManager.getIcon("OptionPane.warningIcon"));
296 UIUtil.positionComponent(SwingConstants.CENTER, dialog);
297 dialog.setVisible(true);
298
299 Option opt = dialog.getSelectedOption();
300
301 if ((opt == null) || (opt == optCancel)) {
302 return;
303 } else if (opt == optNew) {
304 try {
305 SshToolsApplicationContainer c = (SshToolsApplicationContainer) application.newContainer();
306 ((SshToolsApplicationClientPanel) c.getApplicationPanel()).open(f);
307
308 return;
309 } catch (SshToolsApplicationException stae) {
310 log.error(stae);
311 }
312 } else {
313 closeConnection(true);
314 }
315 }
316
317 // Save to MRU
318 if (getApplication().getMRUModel() != null) {
319 getApplication().getMRUModel().add(f);
320 }
321
322 // Make sure its not invalid
323 if (f != null) {
324 // Create a new connection properties object
325 SshToolsConnectionProfile profile = new SshToolsConnectionProfile();
326
327 try {
328 // Open the file
329 profile.open(f.getAbsolutePath());
330 setNeedSave(false);
331 currentConnectionFile = f;
332 setContainerTitle(f);
333
334 // Connect with the new details.
335 connect(profile, false);
336 } catch (InvalidProfileFileException fnfe) {
337 showExceptionMessage(fnfe.getMessage(), "Open Connection");
338 } catch (SshException e) {
339 e.printStackTrace();
340 showExceptionMessage("An unexpected error occured!",
341 "Open Connection");
342 }
343 } else {
344 showExceptionMessage("Invalid file specified", "Open Connection");
345 }
346 }
347
348 /**
349 *
350 *
351 * @param profile
352 * @param newProfile
353 */
354 public void connect(final SshToolsConnectionProfile profile,
355 final boolean newProfile) {
356 // We need to connect
357 ssh = new SshClient();
358
359 // Set the current connection properties
360 setCurrentConnectionProfile(profile);
361
362 // We'll do the threading rather than j2ssh as we want to get errors
363 Runnable r = new Runnable() {
364 public void run() {
365 // Update the status bar
366 getStatusBar().setStatusText("Connecting");
367 getStatusBar().setHost(getCurrentConnectionProfile()
368 .getHost(),
369 getCurrentConnectionProfile().getPort());
370 getStatusBar().setUser(getCurrentConnectionProfile()
371 .getUsername());
372
373 //
374 try {
375 log.info("Connecting to " +
376 getCurrentConnectionProfile().getHost() + " as " +
377 getCurrentConnectionProfile().getUsername());
378 ssh.connect(getCurrentConnectionProfile(),
379 (getHostKeyVerification() == null)
380 ? new SinkHostKeyVerification()
381 : getHostKeyVerification());
382
383 // Set the remote id if we can find on
384 try {
385 RemoteIdentification rid = RemoteIdentificationFactory.getInstance(ssh.getServerId(),
386 ssh.getConnectionProperties().getHost());
387 getStatusBar().setRemoteId(rid.getName(
388 ssh.getServerId()));
389 } catch (RemoteIdentificationException ex) {
390 getStatusBar().setRemoteId("Unknown");
391 }
392
393 if (postConnection()) {
394 if (!authenticateUser(newProfile)) {
395 closeConnection(false);
396 } else {
397 setAvailableActions();
398 }
399 }
400 } catch (IOException sshe) {
401 ssh = null;
402 showExceptionMessage("Connection Error",
403 "Could not establish a connection to host: \n\n " +
404 sshe.getMessage());
405 SshToolsApplicationClientPanel.this.closeConnection(false);
406 } catch (SecurityException se) {
407 ssh = null;
408 showErrorMessage(SshToolsApplicationClientPanel.this,
409 "Error", se);
410 SshToolsApplicationClientPanel.this.closeConnection(false);
411 }
412 }
413 };
414
415 Thread thread = new SshThread(r,
416 application.getApplicationName() + " connection", true);
417 thread.start();
418 }
419
420 /**
421 *
422 *
423 * @param ssh
424 * @param profile
425 *
426 * @throws IOException
427 */
428 public void connect(SshClient ssh, SshToolsConnectionProfile profile)
429 throws IOException {
430 this.ssh = ssh;
431
432 if (!ssh.isAuthenticated()) {
433 authenticateUser(false);
434 }
435
436 // Set the current connection properties
437 setCurrentConnectionProfile(profile);
438 authenticationComplete(false);
439 }
440
441 /**
442 *
443 *
444 * @param newProfile
445 *
446 * @return
447 *
448 * @throws IOException
449 */
450 protected boolean authenticateUser(boolean newProfile)
451 throws IOException {
452 // We should now authenticate
453 int result = AuthenticationProtocolState.READY;
454
455 // Our authenticated flag
456 boolean authenticated = false;
457
458 // Get the supported authentication methods
459 java.util.List supported = SshAuthenticationClientFactory.getSupportedMethods();
460
461 // If the server supports public key lets look for an agent and try
462 // some of his keys
463 if (supported.contains("publickey")) {
464 if (System.getProperty("sshtools.agent") != null) {
465 try {
466 SshAgentClient agent = SshAgentClient.connectLocalAgent("SSHTerm",
467 System.getProperty("sshtools.agent") /*, 5*/);
468 AgentAuthenticationClient aac = new AgentAuthenticationClient();
469 aac.setAgent(agent);
470 aac.setUsername(getCurrentConnectionProfile().getUsername());
471 result = ssh.authenticate(aac);
472 agent.close();
473 } catch (AgentNotAvailableException ex) {
474 log.info("No agent was available for authentication");
475
476 // Just continue
477 }
478
479 if (result == AuthenticationProtocolState.COMPLETE) {
480 authenticationComplete(newProfile);
481
482 return true;
483 }
484 }
485 }
486
487 // Create a list for display that will contain only the
488 // supported and available methods
489 java.util.List display = new java.util.ArrayList();
490
491 // Get the available methods
492 java.util.List auths = null;
493 auths = ssh.getAvailableAuthMethods(getCurrentConnectionProfile()
494 .getUsername());
495
496 // Did we receive a banner from the remote computer
497 final String banner = ssh.getAuthenticationBanner(BANNER_TIMEOUT);
498
499 if (banner != null) {
500 if (!banner.trim().equals("")) {
501 try {
502 SwingUtilities.invokeAndWait(new Runnable() {
503 public void run() {
504 BannerDialog.showBannerDialog(SshToolsApplicationClientPanel.this,
505 banner);
506 }
507 });
508 } catch (Exception e) {
509 log.error("Failed to invoke and wait on BannerDialog", e);
510 }
511 }
512 }
513
514 // Are there any authentication methods within the properties file?
515 // Iterate through selecting only the supported and available
516 Iterator it = supported.iterator();
517
518 while (it.hasNext() && !authenticated) {
519 Object obj = it.next();
520
521 if (auths.contains(obj)) {
522 display.add(obj);
523 }
524 }
525
526 // First look to see if we have any authenticaiton methods available
527 // in the profile properties object as this will overide a manual selection
528 java.util.Map authMethods = (Map) ((HashMap) getCurrentConnectionProfile()
529 .getAuthenticationMethods()).clone();
530 it = authMethods.entrySet().iterator();
531
532 //Iterator it2 = null;
533 java.util.List selected;
534
535 // Loop until the user either cancels or completes
536 boolean completed = false;
537 SshAuthenticationClient auth;
538 Map.Entry entry;
539 String msg = null;
540
541 while (!completed &&
542 (ssh.getConnectionState().getValue() != TransportProtocolState.DISCONNECTED)) {
543 auth = null;
544
545 // Select an authentication method from the properties file or
546 // prompt the user to choose
547 if (it.hasNext()) {
548 Object obj = it.next();
549
550 if (obj instanceof Map.Entry) {
551 entry = (Map.Entry) obj;
552 auth = (SshAuthenticationClient) entry.getValue();
553 } else if (obj instanceof String) {
554 auth = SshAuthenticationClientFactory.newInstance((String) obj);
555 auth.setUsername(getCurrentConnectionProfile().getUsername());
556 } else {
557 closeConnection(true);
558 throw new IOException(
559 "Iterator of Map or List of String expected");
560 }
561 } else {
562 selected = AuthenticationDialog.showAuthenticationDialog(this,
563 display, ((msg == null) ? "" : msg));
564
565 if (selected.size() > 0) {
566 it = selected.iterator();
567 } else {
568 closeConnection(true);
569
570 return false;
571 }
572 }
573
574 if (auth != null) {
575 // The password authentication client can act upon requests to change the password
576
577 /* if (auth instanceof PasswordAuthenticationClient) {
578 PasswordAuthenticationDialog dialog = new PasswordAuthenticationDialog(SshTerminalPanel.this);
579 ((PasswordAuthenticationClient) auth).setAuthenticationPrompt(dialog);
580 ( (PasswordAuthenticationClient) auth)
581 .setPasswordChangePrompt(PasswordChange.getInstance());
582 PasswordChange.getInstance().setParentComponent(
583 SshTerminalPanel.this);
584 }*/
585
586 // Show the implementations dialog
587 // if(auth.showAuthenticationDialog()) {
588 // Authentication with the details supplied
589 result = showAuthenticationPrompt(auth); //ssh.authenticate(auth);
590
591 if (result == AuthenticationProtocolState.FAILED) {
592 msg = auth.getMethodName() +
593 " authentication failed, try again?";
594 }
595
596 // If the result returned partial success then continue
597 if (result == AuthenticationProtocolState.PARTIAL) {
598 // We succeeded so add to the connections authenticaiton
599 // list and continue on to the next one
600 getCurrentConnectionProfile().addAuthenticationMethod(auth);
601 msg = auth.getMethodName() +
602 " authentication succeeded but another is required";
603 }
604
605 if (result == AuthenticationProtocolState.COMPLETE) {
606 authenticated = true;
607
608 //If successfull add to the connections list so we can save later
609 getCurrentConnectionProfile().addAuthenticationMethod(auth);
610
611 // Set the completed flag
612 completed = true;
613 authenticationComplete(newProfile);
614 }
615
616 if (result == AuthenticationProtocolState.CANCELLED) {
617 ssh.disconnect();
618
619 return false;
620 }
621
622 // }
623 // else {
624 // User has cancelled the authenticaiton
625 // closeConnection(true);
626 // return false;
627 // }
628 }
629
630 // end of if
631 }
632
633 // end of while
634 return authenticated;
635 }
636
637 /**
638 *
639 *
640 * @param instance
641 *
642 * @return
643 *
644 * @throws IOException
645 */
646 protected int showAuthenticationPrompt(SshAuthenticationClient instance)
647 throws IOException {
648 instance.setUsername(getCurrentConnectionProfile().getUsername());
649
650 if (instance instanceof PasswordAuthenticationClient) {
651 PasswordAuthenticationDialog dialog = new PasswordAuthenticationDialog((Frame) SwingUtilities.getAncestorOfClass(
652 Frame.class, SshToolsApplicationClientPanel.this));
653 instance.setAuthenticationPrompt(dialog);
654 ((PasswordAuthenticationClient) instance).setPasswordChangePrompt(PasswordChange.getInstance());
655 PasswordChange.getInstance().setParentComponent(SshToolsApplicationClientPanel.this);
656 } else if (instance instanceof PublicKeyAuthenticationClient) {
657 PublicKeyAuthenticationPrompt prompt = new PublicKeyAuthenticationPrompt(SshToolsApplicationClientPanel.this);
658 instance.setAuthenticationPrompt(prompt);
659 } else if (instance instanceof KBIAuthenticationClient) {
660 KBIAuthenticationClient kbi = new KBIAuthenticationClient();
661 ((KBIAuthenticationClient) instance).setKBIRequestHandler(new KBIRequestHandlerDialog(
662 (Frame) SwingUtilities.getAncestorOfClass(Frame.class,
663 SshToolsApplicationClientPanel.this)));
664 }
665
666 return ssh.authenticate(instance);
667 }
668
669 /**
670 *
671 *
672 * @return
673 */
674 public abstract boolean postConnection();
675
676 /**
677 *
678 *
679 * @param newProfile
680 *
681 * @throws SshException
682 * @throws IOException
683 */
684 public abstract void authenticationComplete(boolean newProfile)
685 throws SshException, IOException;
686
687 /**
688 *
689 *
690 * @param file
691 */
692 public void setContainerTitle(File file) {
693 String verString = ConfigurationLoader.getVersionString(application.getApplicationName(),
694 application.getApplicationVersion());
695
696 if (container != null) {
697 container.setContainerTitle((file == null) ? verString
698 : (verString + " [" +
699 file.getName() + "]"));
700 }
701 }
702
703 /**
704 *
705 *
706 * @param needSave
707 */
708 public void setNeedSave(boolean needSave) {
709 if (needSave != this.needSave) {
710 this.needSave = needSave;
711 setAvailableActions();
712 }
713 }
714
715 /**
716 *
717 *
718 * @param file
719 */
720 public void setCurrentConnectionFile(File file) {
721 currentConnectionFile = file;
722 }
723
724 /**
725 *
726 *
727 * @return
728 */
729 public File getCurrentConnectionFile() {
730 return currentConnectionFile;
731 }
732
733 /**
734 *
735 *
736 * @param profile
737 */
738 public void setCurrentConnectionProfile(SshToolsConnectionProfile profile) {
739 currentConnectionProfile = profile;
740 }
741
742 /**
743 *
744 *
745 * @return
746 */
747 public SshToolsConnectionProfile getCurrentConnectionProfile() {
748 return currentConnectionProfile;
749 }
750
751 /**
752 *
753 *
754 * @return
755 */
756 public boolean isNeedSave() {
757 return needSave;
758 }
759
760 /**
761 *
762 *
763 * @return
764 */
765 public boolean isConnected() {
766 return (ssh != null) && ssh.isConnected();
767 }
768
769 /**
770 *
771 *
772 * @throws SshException
773 */
774 public void connect() throws SshException {
775 if (getCurrentConnectionProfile() == null) {
776 throw new SshException(
777 "Can't connect, no connection profile have been set.");
778 }
779
780 // There isn't anywhere to store this setting yet
781 connect(getCurrentConnectionProfile(), false);
782 }
783
784 /**
785 *
786 *
787 * @param disconnect
788 */
789 public void closeConnection(boolean disconnect) {
790 //
791 if (isNeedSave()) {
792 // Only allow saving of files if allowed by the security manager
793 try {
794 if (System.getSecurityManager() != null) {
795 AccessController.checkPermission(new FilePermission(
796 "<<ALL FILES>>", "write"));
797
798 if (JOptionPane.showConfirmDialog(this,
799 "You have unsaved changes to the connection " +
800 ((currentConnectionFile == null) ? "<Untitled>"
801 : currentConnectionFile.getName()) +
802 ".\nDo you want to save the changes now?",
803 "Unsaved changes", JOptionPane.YES_NO_OPTION,
804 JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
805 saveConnection(false, getCurrentConnectionFile(),
806 getCurrentConnectionProfile());
807 setNeedSave(false);
808 }
809 }
810 } catch (AccessControlException ace) {
811 log.warn(
812 "Changes made to connection, but security manager won't allow saving of files.");
813 }
814 }
815
816 setCurrentConnectionFile(null);
817 }
818
819 /**
820 *
821 *
822 * @return
823 */
824 protected boolean allowConnectionSettingsEditing() {
825 return true;
826 }
827
828 /**
829 *
830 *
831 * @param profile
832 *
833 * @return
834 */
835 public boolean editConnection(SshToolsConnectionProfile profile) {
836 final SshToolsConnectionPanel panel = new SshToolsConnectionPanel(allowConnectionSettingsEditing());
837 SshToolsConnectionTab[] tabs = getAdditionalConnectionTabs();
838
839 for (int i = 0; (tabs != null) && (i < tabs.length); i++) {
840 tabs[i].setConnectionProfile(profile);
841 panel.addTab(tabs[i]);
842 }
843
844 panel.setConnectionProfile(profile);
845
846 final Option ok = new Option("Ok",
847 "Apply the settings and close this dialog", 'o');
848 final Option cancel = new Option("Cancel",
849 "Close this dialog without applying the settings", 'c');
850 OptionCallback callback = new OptionCallback() {
851 public boolean canClose(OptionsDialog dialog, Option option) {
852 if (option == ok) {
853 return panel.validateTabs();
854 }
855
856 return true;
857 }
858 };
859
860 OptionsDialog od = OptionsDialog.createOptionDialog(SshToolsApplicationClientPanel.this,
861 new Option[] { ok, cancel }, panel, "Connection Settings", ok,
862 callback, null);
863 od.pack();
864 UIUtil.positionComponent(SwingConstants.CENTER, od);
865 od.setVisible(true);
866
867 if (od.getSelectedOption() == ok) {
868 panel.applyTabs();
869
870 if (profile == getCurrentConnectionProfile()) {
871 setNeedSave(true);
872 }
873
874 return true;
875 }
876
877 return false;
878 }
879
880 /**
881 *
882 *
883 * @param saveAs
884 * @param file
885 * @param profile
886 *
887 * @return
888 */
889 public File saveConnection(boolean saveAs, File file,
890 SshToolsConnectionProfile profile) {
891 if (profile != null) {
892 if ((file == null) || saveAs) {
893 String prefsDir = super.getApplication()
894 .getApplicationPreferencesDirectory()
895 .getAbsolutePath();
896 JFileChooser fileDialog = new JFileChooser(prefsDir);
897 fileDialog.setFileFilter(connectionFileFilter);
898
899 int ret = fileDialog.showSaveDialog(this);
900
901 if (ret == fileDialog.CANCEL_OPTION) {
902 return null;
903 }
904
905 file = fileDialog.getSelectedFile();
906
907 if (!file.getName().toLowerCase().endsWith(".xml")) {
908 file = new File(file.getAbsolutePath() + ".xml");
909 }
910 }
911
912 try {
913 if (saveAs && file.exists()) {
914 if (JOptionPane.showConfirmDialog(this,
915 "File already exists. Are you sure?",
916 "File exists", JOptionPane.YES_NO_OPTION,
917 JOptionPane.WARNING_MESSAGE) == JOptionPane.NO_OPTION) {
918 return null;
919 }
920 }
921
922 // Check to make sure its valid
923 if (file != null) {
924 // Save the connection details to file
925 log.debug("Saving connection to " + file.getAbsolutePath());
926 profile.save(file.getAbsolutePath());
927
928 if (profile == getCurrentConnectionProfile()) {
929 log.debug(
930 "Current connection saved, disabling save action.");
931 setNeedSave(false);
932 }
933
934 return file;
935 } else {
936 showExceptionMessage("The file specified is invalid!",
937 "Save Connection");
938 }
939 } catch (InvalidProfileFileException e) {
940 showExceptionMessage(e.getMessage(), "Save Connection");
941 }
942 }
943
944 return null;
945 }
946
947 public static class ActionMenu implements Comparable {
948 int weight;
949 int mnemonic;
950 String name;
951 String displayName;
952
953 public ActionMenu(String name, String displayName, int mnemonic,
954 int weight) {
955 this.name = name;
956 this.displayName = displayName;
957 this.mnemonic = mnemonic;
958 this.weight = weight;
959 }
960
961 public int compareTo(Object o) {
962 int i = new Integer(weight).compareTo(new Integer(
963 ((ActionMenu) o).weight));
964
965 return (i == 0)
966 ? displayName.compareTo(((ActionMenu) o).displayName) : i;
967 }
968 }
969
970 class ToolBarActionComparator implements Comparator {
971 public int compare(Object o1, Object o2) {
972 int i = ((Integer) ((StandardAction) o1).getValue(StandardAction.TOOLBAR_GROUP)).compareTo((Integer) ((StandardAction) o2).getValue(
973 StandardAction.TOOLBAR_GROUP));
974
975 return (i == 0)
976 ? ((Integer) ((StandardAction) o1).getValue(StandardAction.TOOLBAR_WEIGHT)).compareTo((Integer) ((StandardAction) o2).getValue(
977 StandardAction.TOOLBAR_WEIGHT)) : i;
978 }
979 }
980
981 class MenuItemActionComparator implements Comparator {
982 public int compare(Object o1, Object o2) {
983 int i = ((Integer) ((StandardAction) o1).getValue(StandardAction.MENU_ITEM_GROUP)).compareTo((Integer) ((StandardAction) o2).getValue(
984 StandardAction.MENU_ITEM_GROUP));
985
986 return (i == 0)
987 ? ((Integer) ((StandardAction) o1).getValue(StandardAction.MENU_ITEM_WEIGHT)).compareTo((Integer) ((StandardAction) o2).getValue(
988 StandardAction.MENU_ITEM_WEIGHT)) : i;
989 }
990 }
991
992 class ConnectionFileFilter extends javax.swing.filechooser.FileFilter {
993 public boolean accept(File f) {
994 return f.isDirectory() ||
995 f.getName().toLowerCase().endsWith(".xml");
996 }
997
998 public String getDescription() {
999 return "Connection files (*.xml)";
1000 }
1001 }
1002
1003 class SinkHostKeyVerification implements HostKeyVerification {
1004 public boolean verifyHost(String host, SshPublicKey pk)
1005 throws TransportProtocolException {
1006 log.warn("Accepting host " + host +
1007 " as host key verification is disabled.");
1008
1009 return true;
1010 }
1011 }
1012 }