/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.gui.communication.views.contributors;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import de.rcenvironment.core.utils.common.StringUtils;
/**
* Abstract class for SSHConnectionDialogs, such as AddSSHConnectionDialog and EditSSHConnectionDialog.
*
* @author Brigitte Boden
* @author Oliver Seebach
*/
public abstract class AbstractSshConnectionDialog extends Dialog {
private static final String KEYFILE_AUTH_WITH_PASSPHRASE = "Keyfile with passphrase protection";
private static final String KEYFILE_AUTH_WITHOUT_PASSPHRASE = "Keyfile without passphrase protection";
private static final String PASSPHRASE_AUTH = "Passphrase";
private static final int DIALOG_WINDOW_OFFSET_Y = 100;
private static final int DIALOG_WINDOW_OFFSET_X = 150;
private static final String INVALID_IP = "0.0.0.0";
private static final String NAME_LABEL = "Name:";
private static final String HOST_LABEL = "Host:";
private static final String PORT_LABEL = "Port:";
private static final String USERNAME_LABEL = "Username:";
private static final String AUTH_TYPE_LABEL = "Authentication type:";
private static final String KEYFILE_LABEL = "SSH key file:";
private static final String PASSPHRASE_LABEL = "Passphrase:";
private static final int CHECKBOX_LABEL_WIDTH = 300;
private static final String COLON = ":";
protected String connectionName = "";
protected String host = "";
protected String port = "";
protected String username = "";
protected String passphrase = "";
protected String keyfileLocation = "";
protected String hint = "";
protected boolean storePassphrase = true;
protected boolean useKeyFile = false;
private boolean connectImmediately = true;
private boolean usePassphrase = true;
private Button useDefaultNameButton;
private Button storePasswordButton;
private Label nameLabel;
private boolean isDefaultName = true;
protected AbstractSshConnectionDialog(Shell parentShell) {
super(parentShell);
}
public AbstractSshConnectionDialog(Shell parentShell, String connectionName, String host, int port,
String username, String keyfileLocation, boolean usePassphrase, boolean storePassphrase, boolean connectImmediately) {
super(parentShell);
this.connectionName = connectionName;
this.host = host;
this.port = Integer.toString(port);
String hostAndPortString = StringUtils.format("%s:%s", host, port);
this.username = username;
this.connectImmediately = connectImmediately;
this.storePassphrase = storePassphrase;
this.isDefaultName = (connectionName.equals(hostAndPortString));
this.keyfileLocation = keyfileLocation;
if (keyfileLocation == null) {
this.keyfileLocation = "";
}
this.useKeyFile = !this.keyfileLocation.isEmpty();
this.usePassphrase = usePassphrase;
}
@Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
// remove scrollbar
if (shell.getHorizontalBar() != null) {
shell.getHorizontalBar().dispose();
}
// place shell in the middle of the screen
shell.setLocation(shell.getParent().getLocation().x + shell.getParent().getSize().x / 2 - DIALOG_WINDOW_OFFSET_X,
shell.getParent().getLocation().y + shell.getParent().getSize().y / 2 - DIALOG_WINDOW_OFFSET_Y);
// set shell label to "Connection" as fallback
shell.setText("Connection");
}
@Override
protected Control createDialogArea(final Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
GridLayout layout = new GridLayout(2, false);
GridData containerGridData = new GridData(SWT.FILL, SWT.FILL, false, false);
container.setLayoutData(containerGridData);
container.setLayout(layout);
GridData useDefaultCheckboxGridData = new GridData();
useDefaultCheckboxGridData.widthHint = CHECKBOX_LABEL_WIDTH;
useDefaultCheckboxGridData.horizontalSpan = 1;
GridData storePassphraseCheckboxGridData = new GridData();
storePassphraseCheckboxGridData.widthHint = CHECKBOX_LABEL_WIDTH;
storePassphraseCheckboxGridData.horizontalSpan = 1;
GridData connectImmediateCheckboxGridData = new GridData();
connectImmediateCheckboxGridData.widthHint = CHECKBOX_LABEL_WIDTH;
connectImmediateCheckboxGridData.horizontalSpan = 2;
Label cpLabelHost = new Label(container, SWT.NULL);
cpLabelHost.setText(HOST_LABEL);
final Text hostTextField = new Text(container, SWT.SINGLE | SWT.BORDER);
hostTextField.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
if (!host.isEmpty()) {
hostTextField.setText(host);
}
Label cpLabelPort = new Label(container, SWT.NULL);
cpLabelPort.setText(PORT_LABEL);
final Text portTextField = new Text(container, SWT.SINGLE | SWT.BORDER);
portTextField.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
if (!port.isEmpty()) {
portTextField.setText(port);
}
GridData separatorGridData = new GridData();
separatorGridData.horizontalAlignment = GridData.FILL;
separatorGridData.grabExcessHorizontalSpace = true;
separatorGridData.horizontalSpan = 2;
nameLabel = new Label(container, SWT.NULL);
nameLabel.setText(NAME_LABEL);
final Text nameText = new Text(container, SWT.SINGLE | SWT.BORDER);
nameText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
nameText.setText(connectionName);
nameText.setEnabled(!isDefaultName);
@SuppressWarnings("unused") final Label placeholderLabel = new Label(container, SWT.NONE); // used for layouting
useDefaultNameButton = new Button(container, SWT.CHECK);
useDefaultNameButton.setSelection(true);
useDefaultNameButton.setText("Use default name (host" + COLON + "port)");
useDefaultNameButton.setLayoutData(useDefaultCheckboxGridData);
useDefaultNameButton.setSelection(isDefaultName);
Label usernameLabel = new Label(container, SWT.NULL);
usernameLabel.setText(USERNAME_LABEL);
final Text usernameText = new Text(container, SWT.SINGLE | SWT.BORDER);
usernameText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
usernameText.setText(username);
Label authTypeLabel = new Label(container, SWT.NULL);
authTypeLabel.setText(AUTH_TYPE_LABEL);
final Combo authTypeCombo = new Combo(container, SWT.READ_ONLY);
String[] authTypes = { PASSPHRASE_AUTH, KEYFILE_AUTH_WITH_PASSPHRASE, KEYFILE_AUTH_WITHOUT_PASSPHRASE };
authTypeCombo.setItems(authTypes);
if (useKeyFile) {
if (usePassphrase) {
authTypeCombo.select(1);
} else {
authTypeCombo.select(2);
}
} else {
authTypeCombo.select(0);
}
final Label keyfileLabel = new Label(container, SWT.NULL);
keyfileLabel.setText(KEYFILE_LABEL);
keyfileLabel.setVisible(useKeyFile);
final Composite keyfileComposite = new Composite(container, SWT.NONE);
GridLayout klayout = new GridLayout(2, false);
keyfileComposite.setLayout(klayout);
keyfileComposite.setVisible(useKeyFile);
keyfileComposite.setLayoutData((new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)));
final Text keyfileText = new Text(keyfileComposite, SWT.SINGLE | SWT.BORDER);
keyfileText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
keyfileText.setText(keyfileLocation);
createFileChooserButton(parent, keyfileComposite, keyfileText);
final Label passphraseLabel = new Label(container, SWT.NULL);
passphraseLabel.setText(PASSPHRASE_LABEL);
passphraseLabel.setVisible(usePassphrase);
final Text passphraseText = new Text(container, SWT.SINGLE | SWT.BORDER);
passphraseText.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
passphraseText.setText(passphrase);
passphraseText.setEchoChar('*');
passphraseText.setVisible(usePassphrase);
@SuppressWarnings("unused") final Label placeholderLabel2 = new Label(container, SWT.NONE); // used for layouting
storePasswordButton = new Button(container, SWT.CHECK);
storePasswordButton.setSelection(true);
storePasswordButton.setText("Store passphrase");
storePasswordButton.setLayoutData(storePassphraseCheckboxGridData);
storePasswordButton.setSelection(storePassphrase);
storePasswordButton.setVisible(usePassphrase);
Label separator = new Label(container, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.setLayoutData(separatorGridData);
final Button immediateConnectButton = new Button(container, SWT.CHECK);
immediateConnectButton.setSelection(connectImmediately);
immediateConnectButton.setText("Connect immediately");
immediateConnectButton.setLayoutData(connectImmediateCheckboxGridData);
final Label persistHint = new Label(container, SWT.NULL);
GridData hintGridData = new GridData();
hintGridData.horizontalSpan = 2;
persistHint.setText(hint);
persistHint.setLayoutData(hintGridData);
defineListenerForAuthenticationType(authTypeCombo, keyfileLabel, keyfileComposite, passphraseLabel, passphraseText);
initVariablesAndCreateListeners(hostTextField, portTextField, nameText, usernameText, passphraseText, keyfileText,
immediateConnectButton);
return container;
}
private void defineListenerForAuthenticationType(final Combo authTypeCombo, final Label keyfileLabel, final Composite keyfileComposite,
final Label passphraseLabel, final Text passphraseText) {
authTypeCombo.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent arg0) {
useKeyFile =
authTypeCombo.getText().equals(KEYFILE_AUTH_WITH_PASSPHRASE)
|| authTypeCombo.getText().equals(KEYFILE_AUTH_WITHOUT_PASSPHRASE);
usePassphrase = !authTypeCombo.getText().equals(KEYFILE_AUTH_WITHOUT_PASSPHRASE);
keyfileLabel.setVisible(useKeyFile);
keyfileComposite.setVisible(useKeyFile);
passphraseLabel.setVisible(usePassphrase);
passphraseText.setVisible(usePassphrase);
storePasswordButton.setVisible(usePassphrase);
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
});
}
private void createFileChooserButton(final Composite parent, Composite container, final Text keyfileText) {
final Button keyfileButton = new Button(container, SWT.NONE);
keyfileButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false,
false, 1, 1));
keyfileButton.setText("...");
keyfileButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent arg0) {
FileDialog dialog = new FileDialog(parent.getShell());
dialog.setText("Choose private key file");
String result = dialog.open();
if (result != null) {
keyfileText.setText(result);
}
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {
widgetSelected(arg0);
}
});
}
private void initVariablesAndCreateListeners(final Text hostTextField, final Text portTextField, final Text nameText,
final Text usernameText,
final Text passphraseText, final Text keyfileText, final Button immediateConnectButton) {
portTextField.addVerifyListener(new VerifyListener() {
@Override
public void verifyText(VerifyEvent e) {
String currentText = ((Text) e.widget).getText();
String portID = currentText.substring(0, e.start) + e.text + currentText.substring(e.end);
final int maxPort = 65535;
try {
int portNum = Integer.valueOf(portID);
if (portNum <= 0 || portNum > maxPort) {
e.doit = false;
}
} catch (NumberFormatException ex) {
if (!portID.equals("")) {
e.doit = false;
}
}
}
});
hostTextField.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
host = hostTextField.getText();
if (useDefaultNameButton.getSelection()) {
if (!hostTextField.getText().isEmpty() && !portTextField.getText().isEmpty()) {
nameText.setText(hostTextField.getText() + COLON + portTextField.getText());
} else {
nameText.setText("");
}
}
updateOkButtonActivation();
}
});
portTextField.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
port = portTextField.getText();
if (useDefaultNameButton.getSelection()) {
if (!hostTextField.getText().isEmpty() && !portTextField.getText().isEmpty()) {
nameText.setText(hostTextField.getText() + COLON + portTextField.getText());
} else {
nameText.setText("");
}
}
updateOkButtonActivation();
}
});
connectionName = nameText.getText();
nameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
connectionName = nameText.getText();
}
});
username = usernameText.getText();
usernameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent arg0) {
username = usernameText.getText();
updateOkButtonActivation();
}
});
passphrase = passphraseText.getText();
passphraseText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent arg0) {
passphrase = passphraseText.getText();
}
});
keyfileLocation = keyfileText.getText();
keyfileText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent arg0) {
keyfileLocation = keyfileText.getText();
}
});
connectImmediately = immediateConnectButton.getSelection();
immediateConnectButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent event) {
connectImmediately = immediateConnectButton.getSelection();
}
@Override
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}
});
storePassphrase = storePasswordButton.getSelection();
storePasswordButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent event) {
storePassphrase = storePasswordButton.getSelection();
}
@Override
public void widgetDefaultSelected(SelectionEvent event) {
widgetSelected(event);
}
});
useDefaultNameButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (useDefaultNameButton.getSelection()) {
// if selection is enabled
nameText.setEnabled(false);
if (!hostTextField.getText().isEmpty() && !portTextField.getText().isEmpty()) {
nameText.setText(hostTextField.getText() + COLON + portTextField.getText());
} else {
nameText.setText("");
}
} else {
// if selection is disabled
nameText.setEnabled(true);
nameText.setText("");
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetDefaultSelected(e);
}
});
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
updateOkButtonActivation();
}
@Override
protected void okPressed() {
if (host.contains(INVALID_IP)) {
MessageDialog.openError(this.getParentShell(), "Invalid host address", "The IP address 0.0.0.0"
+ " configured for the network connection is invalid. For a local connection please use 127.0.0.1 or 'localhost' instead.");
return;
}
super.okPressed();
}
@Override
protected Control createButtonBar(Composite parent) {
Control buttonBar = super.createButtonBar(parent);
// pack shell after button bar is created to fit dialog window to proper size
parent.getShell().pack();
return buttonBar;
}
@Override
protected void setShellStyle(int newShellStyle) {
super.setShellStyle(SWT.OK | SWT.CANCEL | SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
}
public String getConnectionName() {
return connectionName;
}
public String getHost() {
return host;
}
public int getPort() {
return Integer.parseInt(port);
}
public String getUsername() {
return username;
}
/**
* Get entered passphrase.
*
* @return the passphrase, or null, if key file authentication without passphrase is used.
*/
public String getPassphrase() {
if (usePassphrase) {
return passphrase;
}
return null;
}
/**
* Get entered keyfile location.
*
* @return the keyfile location, or null, if password authentication is used.
*/
public String getKeyfileLocation() {
if (useKeyFile) {
return keyfileLocation;
}
return null;
}
public boolean getConnectImmediately() {
return connectImmediately;
}
protected void activateDefaultName() {
isDefaultName = true;
}
protected void deactivateDefaultName() {
isDefaultName = false;
}
/**
* If the passphrase should be stored in the secure store.
*
* @return true, if a passphrase is used and should be stored in the secure store.
*/
public boolean shouldStorePassPhrase() {
if (usePassphrase) {
return storePassphrase;
}
return false;
}
public boolean getUsePassphrase() {
return usePassphrase;
}
private void updateOkButtonActivation() {
getButton(IDialogConstants.OK_ID).setEnabled(!host.isEmpty() && !port.isEmpty() && !username.isEmpty());
}
}