/* This file is part of "MidpSSH".
* Copyright (c) 2004 Karl von Randow.
*
* MidpSSH is based upon Telnet Floyd and FloydSSH by Radek Polak.
*
* --LICENSE NOTICE--
* 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.
* --LICENSE NOTICE--
*
*/
package gui.settings;
import gui.EditableForm;
import gui.MainMenu;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import ssh.v2.DHKeyExchange;
import ssh.v2.PublicKeyAuthentication;
import app.Settings;
/**
* NOTE on ChoiceGroup workarounds. Because of a bug in Java support on Blackberry Pearl we change the
* ChoiceGroups to be Popup rather than Exclusive in Midp2. They look nicer as popup in Midp2 as well
* I hope.
* @author Karl von Randow
*/
public class SettingsForm extends EditableForm {
public static final int MODE_NETWORK = 1;
public static final int MODE_INTERFACE = 2;
//#ifndef nofonts
public static final int MODE_FONTS = 3;
//#endif
//#ifdef ssh2
public static final int MODE_SSH = 4;
//#endif
private int mode;
protected TextField tfHttpProxy = new TextField("HTTP Proxy", "", 255, TextField.ANY);
protected ChoiceGroup cgHttpProxyMode = new ChoiceGroup( "HTTP Proxy Mode", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
protected TextField tfType = new TextField( "Terminal Type", "", 20, TextField.ANY );
protected TextField tfCols = new TextField( "Cols", "", 3, TextField.NUMERIC );
protected TextField tfRows = new TextField( "Rows", "", 3, TextField.NUMERIC );
//#ifdef midp2
protected ChoiceGroup cgFullscreen = new ChoiceGroup( "Full Screen", ChoiceGroup.POPUP);
protected ChoiceGroup cgRotated = new ChoiceGroup( "Orientation", ChoiceGroup.POPUP);
protected ChoiceGroup cgPredictiveText = new ChoiceGroup("Predictive Text", ChoiceGroup.POPUP);
//#endif
//#ifndef nofonts
protected ChoiceGroup cgFont = new ChoiceGroup( "Font Size", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
//#ifndef nofonts
protected ChoiceGroup cgLCDFontMode = new ChoiceGroup( "LCD Font Mode", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
//#endif
protected TextField tfFg = new TextField( "Foreground", "", 6, TextField.ANY );
protected TextField tfBg = new TextField( "Background", "", 6, TextField.ANY );
//#endif
protected ChoiceGroup cgPolling = new ChoiceGroup("Polling I/O", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
//#ifdef ssh2
//#ifndef nossh1
protected ChoiceGroup cgSsh = new ChoiceGroup("Prefer", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
//#endif
protected ChoiceGroup cgSshPublicKey = new ChoiceGroup("Public Key", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
protected ChoiceGroup cgSshKeys = new ChoiceGroup("Store Session Key", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
protected ChoiceGroup cgSshKeySize = new ChoiceGroup("Session Key Size", ChoiceGroup.EXCLUSIVE
//#ifdef midp2
* 0 + ChoiceGroup.POPUP
//#endif
);
private static final int[] sshKeySizes = new int[] { 32, 64, 128, 256, 512, 1024 };
//#endif
public static void booleanChoiceGroup(ChoiceGroup cg) {
cg.append( "On", null );
cg.append( "Off", null );
}
public SettingsForm( String title, int mode ) {
super( title );
this.mode = mode;
switch ( mode ) {
case MODE_NETWORK:
{
append(tfHttpProxy);
cgHttpProxyMode.append("Off", null);
cgHttpProxyMode.append("Persistent", null);
cgHttpProxyMode.append("Transient", null);
append(cgHttpProxyMode);
append( tfType );
booleanChoiceGroup(cgPolling);
append(cgPolling);
}
break;
case MODE_INTERFACE:
{
//#ifdef midp2
booleanChoiceGroup(cgFullscreen);
append( cgFullscreen );
//#endif
//#ifdef midp2
cgRotated.append( "Normal", null );
cgRotated.append( "Landscape", null );
cgRotated.append( "Landscape Flipped", null );
append( cgRotated );
//#endif
//#ifndef noinstructions
append( new StringItem( "Terminal Size", "The default is to use the maximum available screen area." ) );
//#endif
append( tfCols );
append( tfRows );
//#ifdef midp2
booleanChoiceGroup(cgPredictiveText);
append(cgPredictiveText);
//#endif
}
break;
//#ifndef nofonts
case MODE_FONTS:
{
cgFont.append( "Tiny", null );
cgFont.append( "Device", null );
//#ifdef midp2
cgFont.append( "LCD 3x6", null );
cgFont.append( "LCD 4x6", null );
cgFont.append( "LCD 4x7", null );
cgFont.append( "LCD 5x9", null );
cgFont.append( "LCD 8x16", null );
//#endif
append( cgFont );
//#ifdef midp2
cgLCDFontMode.append("RGB", null);
cgLCDFontMode.append("BGR", null);
append(cgLCDFontMode);
//#endif
append( tfFg );
append( tfBg );
}
break;
//#endif
//#ifdef ssh2
case MODE_SSH:
{
//#ifndef nossh1
cgSsh.append( "SSH1", null);
cgSsh.append( "SSH2", null);
append(cgSsh);
//#endif
booleanChoiceGroup(cgSshPublicKey);
append(cgSshPublicKey);
booleanChoiceGroup(cgSshKeys);
append(cgSshKeys);
for (int i = 0; i < sshKeySizes.length; i++) {
cgSshKeySize.append(String.valueOf(sshKeySizes[i]), null);
}
append(cgSshKeySize);
}
break;
//#endif
}
}
/* (non-Javadoc)
* @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable)
*/
public void commandAction( Command command, Displayable displayable ) {
//#ifdef ssh2
if (displayable instanceof Alert) {
if (cgSshKeys.getSelectedIndex() == 0 && Settings.ssh2x == null) {
byte[][] keys = DHKeyExchange.generateKeyPairBytes(Settings.ssh2KeySize);
Settings.ssh2x = keys[0];
Settings.ssh2y = keys[1];
}
if (cgSshPublicKey.getSelectedIndex() == 0 && Settings.x == null) {
byte[][] keys = PublicKeyAuthentication.generateKeyPair();
Settings.x = keys[0];
Settings.y = keys[1];
}
Settings.saveSettings();
//#ifdef midp2
MainMenu.getDisplay().vibrate(300);
//#endif
doBack();
}
else
//#endif
super.commandAction( command, displayable );
}
protected void doBack() {
if ( doSave() ) {
Settings.saveSettings( );
super.doBack();
}
}
/* (non-Javadoc)
* @see gui.Activatable#activate()
*/
public void activate() {
switch ( mode ) {
case MODE_NETWORK:
{
tfHttpProxy.setString(Settings.httpProxy);
cgHttpProxyMode.setSelectedIndex(Settings.httpProxyMode, true);
tfType.setString( Settings.terminalType );
cgPolling.setSelectedIndex(Settings.pollingIO ? 0 : 1, true);
}
break;
case MODE_INTERFACE:
{
//#ifdef midp2
cgFullscreen.setSelectedIndex( Settings.terminalFullscreen ? 0 : 1, true );
//#endif
//#ifdef midp2
switch ( Settings.terminalRotated ) {
case Settings.ROT_NORMAL:
cgRotated.setSelectedIndex( 0, true );
break;
case Settings.ROT_270:
cgRotated.setSelectedIndex( 1, true );
break;
case Settings.ROT_90:
cgRotated.setSelectedIndex( 2, true );
break;
}
//#endif
int cols = Settings.terminalCols;
int rows = Settings.terminalRows;
if ( cols > 0 ) {
tfCols.setString( String.valueOf(cols) );
}
else {
tfCols.setString( "" );
}
if ( rows > 0 ) {
tfRows.setString( String.valueOf(rows) );
}
else {
tfRows.setString( "" );
}
//#ifdef midp2
cgPredictiveText.setSelectedIndex(Settings.predictiveText ? 0 : 1, true);
//#endif
}
break;
//#ifndef nofonts
case MODE_FONTS:
{
cgFont.setSelectedIndex(Settings.fontMode, true);
//#ifdef midp2
cgLCDFontMode.setSelectedIndex(Settings.lcdFontMode, true);
//#endif
tfFg.setString( toHex( Settings.fgcolor ) );
tfBg.setString( toHex( Settings.bgcolor ) );
}
break;
//#endif
//#ifdef ssh2
case MODE_SSH:
{
//#ifndef nossh1
cgSsh.setSelectedIndex(Settings.sshVersionPreferred == 2 ? 1 : 0, true);
//#endif
cgSshPublicKey.setSelectedIndex(Settings.x != null ? 0 : 1, true);
cgSshKeys.setSelectedIndex(Settings.ssh2StoreKey ? 0 : 1, true);
for (int i = 0; i < sshKeySizes.length; i++) {
if (Settings.ssh2KeySize == sshKeySizes[i]) {
cgSshKeySize.setSelectedIndex(i, true);
break;
}
}
}
break;
//#endif
}
super.activate();
}
protected boolean doSave() {
switch ( mode ) {
case MODE_NETWORK:
{
Settings.httpProxy = tfHttpProxy.getString();
Settings.httpProxyMode = cgHttpProxyMode.getSelectedIndex();
Settings.terminalType = tfType.getString();
Settings.pollingIO = cgPolling.getSelectedIndex() == 0;
}
break;
case MODE_INTERFACE:
{
//#ifdef midp2
Settings.terminalFullscreen = cgFullscreen.getSelectedIndex() == 0;
//#endif
//#ifdef midp2
switch ( cgRotated.getSelectedIndex() ) {
case 0:
Settings.terminalRotated = Settings.ROT_NORMAL;
break;
case 1:
Settings.terminalRotated = Settings.ROT_270;
break;
case 2:
Settings.terminalRotated = Settings.ROT_90;
break;
}
//#endif
try {
Settings.terminalCols = Integer.parseInt( tfCols.getString() );
}
catch ( NumberFormatException e ) {
Settings.terminalCols = 0;
}
try {
Settings.terminalRows = Integer.parseInt( tfRows.getString() );
}
catch ( NumberFormatException e ) {
Settings.terminalRows = 0;
}
//#ifdef midp2
Settings.predictiveText = cgPredictiveText.getSelectedIndex() == 0;
//#endif
}
break;
//#ifndef nofonts
case MODE_FONTS:
{
Settings.fontMode = cgFont.getSelectedIndex();
//#ifdef midp2
Settings.lcdFontMode = (byte) cgLCDFontMode.getSelectedIndex();
//#endif
try {
int col = Integer.parseInt( tfFg.getString(), 16 );
Settings.fgcolor = col;
}
catch ( NumberFormatException e ) {
Settings.fgcolor = Settings.DEFAULT_FGCOLOR;
}
try {
int col = Integer.parseInt( tfBg.getString(), 16 );
Settings.bgcolor = col;
}
catch ( NumberFormatException e ) {
Settings.bgcolor = Settings.DEFAULT_BGCOLOR;
}
}
break;
//#endif
//#ifdef ssh2
case MODE_SSH:
{
//#ifndef nossh1
Settings.sshVersionPreferred = cgSsh.getSelectedIndex() == 1 ? 2 : 1;
//#endif
boolean ssh2StoreKey = cgSshKeys.getSelectedIndex() == 0;
Settings.ssh2StoreKey = ssh2StoreKey;
int newKeySize = sshKeySizes[cgSshKeySize.getSelectedIndex()];
if (newKeySize != Settings.ssh2KeySize || !ssh2StoreKey) {
Settings.ssh2KeySize = newKeySize;
Settings.ssh2x = null;
Settings.ssh2y = null;
}
boolean ssh2PublicKey = cgSshPublicKey.getSelectedIndex() == 0;
if (!ssh2PublicKey) {
Settings.x = null;
Settings.y = null;
}
if ((ssh2StoreKey && Settings.ssh2x == null) || (ssh2PublicKey && Settings.x == null)) {
/* Pregenerate ssh2 key */
Alert alert = new Alert("MidpSSH");
alert.setString("Generating keys, please wait...");
alert.setTimeout(1);
alert.setCommandListener(this);
MainMenu.setDisplay(alert);
return false;
}
}
break;
//#endif
}
return true;
}
private static String toHex(int i) {
String str = Integer.toHexString(i);
while (str.length() < 6) {
str = "0" + str;
}
return str;
}
// private static int fromHex( String hex ) throws NumberFormatException {
// hex = hex.toLowerCase();
// int total = 0;
// for ( int i = 0; i < hex.length(); i++ ) {
// total <<= 4;
// char c = hex.charAt( i );
// if ( c >= '0' && c <= '9' ) {
// total += ( c - '0' );
// }
// else if ( c >= 'a' && c <= 'f' ) {
// total += ( c - 'a' ) + 10;
// }
// else {
// throw new NumberFormatException( hex );
// }
// }
// return total;
// }
//
// private static String toHex( int i ) {
// char[] buf = new char[32];
// int charPos = 32;
// do {
// buf[--charPos] = digits.charAt(i & 15);
// i >>>= 4;
// } while ( charPos > 26 || i != 0 );
//
// return new String(buf, charPos, (32 - charPos));
// }
//
// private static final String digits = "0123456789abcdef";
}