/**
* Copyright (c) 2010 Marc A. Paradise
*
* This file is part of "BBSSH"
*
* BBSSH is based upon MidpSSH by Karl von Randow.
* MidpSSH was based upon Telnet Floyd and FloydSSH by Radek Polak.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
package org.bbssh.ui.screens;
import java.io.IOException;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ObjectChoiceField;
import net.rim.device.api.ui.component.Status;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import org.bbssh.model.ConnectionProperties;
import org.bbssh.model.FontSettings;
import org.bbssh.model.Key;
import org.bbssh.model.KeyManager;
import org.bbssh.ui.components.ClickableButtonField;
import org.bbssh.util.Tools;
/**
* Screen for displaying and editing connection/session instance properties. Extends ConnectionProperties, which
* provides for editing of properties that are not specific to any one session.
*
*/
public final class ConnectionInstancePropertiesScreen extends ConnectionPropertiesScreen {
protected BasicEditField nameField;
protected BasicEditField hostField;
protected BasicEditField portField;
protected BasicEditField userNameField;
protected ClickableButtonField setPasswordButton;
protected ClickableButtonField clearPasswordButton;
protected HorizontalFieldManager passwordFieldManager;
protected ObjectChoiceField sessionTypeField;
protected ObjectChoiceField keyListField;
protected ObjectChoiceField proxyModeField;
protected BasicEditField proxyHostField;
protected boolean clearPassword = false;
protected boolean changePassword = false;
protected String password = null;
LabelField passwordNoteLabel;
/**
* Instantiates a new session detail screen.
*
* @param prop the prop
*/
ConnectionInstancePropertiesScreen(ConnectionProperties prop) {
super(prop);
if (prop.isNew()) {
setTitle(res.getString(SESSION_DTL_TITLE_1));
} else {
setTitle(res.getString(SESSION_DTL_TITLE_2));
}
}
/**
* Creates the fields.
*/
protected void createFields() {
super.createFields();
// Extract port from host
String host = prop.getHost();
String port = "";
if (host != null && host.indexOf(':') >= 0) {
int delimiterIndex = host.indexOf(':');
port = host.substring(delimiterIndex + 1);
host = host.substring(0, delimiterIndex);
}
// Basic
sessionTypeField = new ObjectChoiceField(res.getString(SESSION_DTL_LBL_SESSION_TYPE), res
.getStringArray(SESSION_DTL_LIST_SESSION_TYPES));
sessionTypeField.setSelectedIndex(prop.getSessionType());
nameField = new BasicEditField(res.getString(SESSION_DTL_LBL_CONN_NAME), prop.getName(), 64, Field.EDITABLE
| BasicEditField.NO_NEWLINE | BasicEditField.NON_SPELLCHECKABLE);
hostField = new BasicEditField(res.getString(SESSION_DTL_LBL_CONN_HOST), host, 255, Field.EDITABLE
| BasicEditField.NO_NEWLINE | BasicEditField.NON_SPELLCHECKABLE | BasicEditField.FILTER_URL);
portField = new BasicEditField(res.getString(SESSION_DTL_LBL_CONN_PORT), port, 5, Field.EDITABLE
| BasicEditField.NO_NEWLINE | BasicEditField.NON_SPELLCHECKABLE | BasicEditField.FILTER_NUMERIC);
userNameField = new BasicEditField(res.getString(SESSION_DTL_LBL_LOGIN_USERNAME), prop.getUsername(), 64,
Field.EDITABLE | BasicEditField.NO_NEWLINE | BasicEditField.NON_SPELLCHECKABLE);
setPasswordButton = new ClickableButtonField(res.getString(SESSION_DTL_LBL_SET_PASSWORD));
passwordNoteLabel = new LabelField();
passwordNoteLabel.setFont(Tools.deriveBBSSHDialogFont(passwordNoteLabel.getFont()));
clearPasswordButton = new ClickableButtonField(res.getString(SESSION_DTL_LBL_CLEAR_PASSWORD));
passwordFieldManager = new HorizontalFieldManager();
passwordFieldManager.add(new LabelField(res.getString(SESSION_DTL_LBL_LOGIN_PASSWORD)));
passwordFieldManager.add(setPasswordButton);
passwordFieldManager.add(clearPasswordButton);
setPasswordButton.setChangeListener(this);
clearPasswordButton.setChangeListener(this);
updatePasswordNoteText(prop.getPassword());
KeyManager mgr = KeyManager.getInstance();
Object[] keys = Tools.vectorToArray(mgr.getKeys(), 1);
keys[0] = res.getString(SESSION_DTL_NO_KEY);
int index = mgr.findKeyIndexById(prop.getKeyId());
keyListField = new ObjectChoiceField(res.getString(SESSION_DTL_LBL_KEY), keys);
if (index > -1) {
keyListField.setSelectedIndex(index + 1);
} else {
keyListField.setSelectedIndex(0);
}
int mode = prop.getHttpProxyMode();
if (mode == -1)
mode = 0;
proxyModeField = new ObjectChoiceField(res.getString(SESSION_DTL_LBL_HTTP_PROXY_MODE),
res.getStringArray(SESSION_DTL_LIST_PROXY_CHOICES), mode);
// Note: disable if proxy none.
proxyHostField = new BasicEditField(res.getString(SESSION_DTL_LBL_HTTP_PROXY_HOST), prop.getHttpProxyHost(),
255, Field.EDITABLE | BasicEditField.NO_NEWLINE | BasicEditField.NON_SPELLCHECKABLE);
}
void updatePasswordNoteText(String password) {
if (password == null) {
passwordNoteLabel.setText(res.getString(SESSION_DTL_LBL_NOPASS));
} else {
passwordNoteLabel.setText(res.getString(SESSION_DTL_LBL_HASPASS));
}
}
void updateFontButtonText(FontSettings fs) {
String s = fs.toString();
if (s == null || s.length() == 0) {
s = res.getString(GEN_LBL_CLICK_TO_CHOOSE);
}
chooseFont.setLabel(s);
}
/*
* (non-Javadoc)
*
* @see net.rim.device.api.ui.Screen#isDataValid()
*/
public boolean isDataValid() {
if (nameField.getTextLength() < 1) {
Status.show(res.getString(MSG_INVALID_SESSION_NAME));
nameField.setFocus();
return false;
}
if (!validateHostAndPort()) {
return false;
}
// telnet has no authentication guaranteed (as you can connect via telnet to
// any socket) so username and password are not supported
if (sessionTypeField.getSelectedIndex() == ConnectionProperties.SESSION_TYPE_TELNET) {
if ((password != null && password.length() > 0) || userNameField.getTextLength() > 0) {
Status.show(res.getString(MSG_NO_USER_NAME_PASS_ALLOWED));
userNameField.setFocus();
return false;
}
// -1 = 0 no selection (good) , 0 = "make a choice" indicator.
if (keyListField.getSelectedIndex() > 0) {
Status.show(res.getString(MSG_NO_KEY_ALLOWED));
keyListField.setFocus();
return false;
}
} else {
int val;
if (keepAliveDurationField.getTextLength() == 0) {
val = -1;
} else {
val = Integer.parseInt(keepAliveDurationField.getText());
}
// If the user entered no value, or if value < 0, stop them.
if (val < 0) {
Status.show(res.getString(MSG_INVALID_CLIENT_KEEPALIVE));
keepAliveDurationField.setFocus();
return false;
}
// Values of less than 60 can drain the battery. Warn the user.
if (val > 0 && val < 60) {
if (Dialog.ask(Dialog.D_YES_NO, res.getString(MSG_CLIENT_KEEPALIVE_LOW_VAL_WARN), 0) == Dialog.NO) {
keepAliveDurationField.setFocus();
return false;
}
}
}
// If proxy is enabled, a host must be provided.
if (proxyModeField.getSelectedIndex() > 0) {
if (proxyHostField.getTextLength() < 1) {
Status.show(res.getString(MSG_PROXY_HOST_INVALID));
proxyHostField.setFocus();
return false;
}
}
return super.isDataValid();
// .
// Note: we used to have checking of WAP2 service book availability,
// but because th service book name will vary regionally, I haven't found a
// reliable way to do that.
}
private boolean validateHostAndPort() {
String port;
String host = hostField.getText().trim();
if (host.length() == 0) {
Status.show(res.getString(MSG_INVALID_HOST_NAME));
hostField.setFocus();
return false;
}
int pos = host.indexOf(':');
if (pos == -1) {
port = portField.getText().trim();
if (port.length() == 0) {
if (sessionTypeField.getSelectedIndex() == ConnectionProperties.SESSION_TYPE_SSH)
port = "22";
else
port = "23";
}
} else {
if (pos == host.length() - 1) { // eg host.com: w/ nothing after colon
port = "0";
} else {
port = host.substring(pos + 1);
}
host = host.substring(0, pos - 1);
}
hostField.setText(host);
portField.setText(port);
try {
int value = Integer.parseInt(port);
if (value <= 0 || value > 65535) {
throw new NumberFormatException();
}
} catch (NumberFormatException e) {
Status.show(res.getString(MSG_INVALID_PORT));
portField.setFocus();
return false;
}
return true;
}
/*
* (non-Javadoc)
*
* @see net.rim.device.api.ui.Screen#save()
*/
public void save() throws IOException {
super.save();
int keyId = keyListField.getSelectedIndex();
if (keyId > 0) {
Key k = (Key) keyListField.getChoice(keyId);
keyId = k.getId();
} else {
keyId = -1; // keyId == 0 is "no selection" row.
}
prop.setName(nameField.getText());
prop.setHost(hostField.getText() + ':' + portField.getText());
prop.setUsername(userNameField.getText());
if (changePassword && password != null) {
prop.setPassword(password);
}
if (clearPassword) {
prop.setPassword(null);
}
prop.setSessionType((byte) sessionTypeField.getSelectedIndex());
prop.setKeyId(keyId);
prop.setConnectionType((byte) connectionTypeField.getSelectedIndex());
prop.setHttpProxyMode((byte) proxyModeField.getSelectedIndex());
prop.setHttpProxyHost(proxyHostField.getText());
super.save();
}
/**
* Adds fields to the screen
*
* @todo split into ssh vs telnet -for validation too. Provide a ConnectionPropertiesValidator?
*/
protected void addFields() {
super.addFields();
baseFields.add(nameField);
baseFields.add(hostField);
baseFields.add(portField);
baseFields.add(sessionTypeField);
baseFields.add(userNameField);
baseFields.add(passwordFieldManager);
baseFields.add(passwordNoteLabel);
baseFields.add(keyListField);
networkingFields.add(proxyModeField);
networkingFields.add(proxyHostField);
}
/*
* (non-Javadoc)
*
* @see net.rim.device.api.ui.FieldChangeListener#fieldChanged(net.rim.device.api.ui.Field, int)
*/
public void fieldChanged(Field field, int context) {
if (field == setPasswordButton) {
if (sessionTypeField.getSelectedIndex() == ConnectionProperties.SESSION_TYPE_TELNET) {
Status.show(res.getString(MSG_NO_USER_NAME_PASS_ALLOWED));
return;
}
PasswordPromptPopup prompt = new PasswordPromptPopup(res.getString(SESSION_DTL_LBL_CONNECTION_PASSWORD),
false);
if (prompt.show()) {
password = prompt.getPassword();
changePassword = true;
clearPassword = false;
updatePasswordNoteText(password);
}
} else if (field == clearPasswordButton) {
clearPassword = true;
changePassword = false;
updatePasswordNoteText(null);
Status.show(res.getString(SESSION_DTL_MSG_PASSWORD_CLEARED));
} else {
super.fieldChanged(field, context);
}
}
}