diff options
author | Kenny Root <kenny@the-b.org> | 2008-11-20 21:59:46 +0000 |
---|---|---|
committer | Kenny Root <kenny@the-b.org> | 2008-11-20 21:59:46 +0000 |
commit | fedb9892fcf2a5be87ecc4fc0a80584266f68b1b (patch) | |
tree | 53a8187d32e04b18dfb63d24e4cdc89c5635a60a /src | |
parent | 8c27256ce99583f97ede7994a5e722f1e1da52bb (diff) | |
download | connectbot-fedb9892fcf2a5be87ecc4fc0a80584266f68b1b.tar.gz connectbot-fedb9892fcf2a5be87ecc4fc0a80584266f68b1b.tar.bz2 connectbot-fedb9892fcf2a5be87ecc4fc0a80584266f68b1b.zip |
Convert Pubkey handling to PubkeyBean in preparation for backup/restore functionality
Diffstat (limited to 'src')
-rw-r--r-- | src/org/connectbot/PortForwardListActivity.java | 2 | ||||
-rw-r--r-- | src/org/connectbot/PubkeyListActivity.java | 259 | ||||
-rw-r--r-- | src/org/connectbot/TerminalView.java | 52 | ||||
-rw-r--r-- | src/org/connectbot/bean/HostBean.java | 2 | ||||
-rw-r--r-- | src/org/connectbot/bean/PubkeyBean.java | 160 | ||||
-rw-r--r-- | src/org/connectbot/service/TerminalManager.java | 24 | ||||
-rw-r--r-- | src/org/connectbot/util/HostDatabase.java | 2 | ||||
-rw-r--r-- | src/org/connectbot/util/PubkeyDatabase.java | 134 | ||||
-rw-r--r-- | src/org/connectbot/util/PubkeyUtils.java | 4 |
9 files changed, 425 insertions, 214 deletions
diff --git a/src/org/connectbot/PortForwardListActivity.java b/src/org/connectbot/PortForwardListActivity.java index 26fe490..81cb2f3 100644 --- a/src/org/connectbot/PortForwardListActivity.java +++ b/src/org/connectbot/PortForwardListActivity.java @@ -362,7 +362,7 @@ public class PortForwardListActivity extends ListActivity { this.portForwards = this.hostdb.getPortForwardsForHost(host); } - PortForwardAdapter adapter = new PortForwardAdapter(this, this.portForwards); + PortForwardAdapter adapter = new PortForwardAdapter(this, portForwards); this.setListAdapter(adapter); } diff --git a/src/org/connectbot/PubkeyListActivity.java b/src/org/connectbot/PubkeyListActivity.java index fb3df54..04c57c9 100644 --- a/src/org/connectbot/PubkeyListActivity.java +++ b/src/org/connectbot/PubkeyListActivity.java @@ -30,6 +30,7 @@ import java.util.EventListener; import java.util.LinkedList; import java.util.List; +import org.connectbot.bean.PubkeyBean; import org.connectbot.service.TerminalManager; import org.connectbot.util.PubkeyDatabase; import org.connectbot.util.PubkeyUtils; @@ -42,7 +43,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.content.DialogInterface.OnClickListener; -import android.database.Cursor; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -55,16 +55,16 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.view.MenuItem.OnMenuItemClickListener; import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ImageView; -import android.widget.SimpleCursorAdapter; import android.widget.TableRow; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; -import android.widget.SimpleCursorAdapter.ViewBinder; import com.trilead.ssh2.crypto.PEMDecoder; import com.trilead.ssh2.crypto.PEMStructure; @@ -79,27 +79,27 @@ public class PubkeyListActivity extends ListActivity implements EventListener { public final static String TAG = PubkeyListActivity.class.toString(); protected PubkeyDatabase pubkeydb; - private Cursor pubkeys; + private List<PubkeyBean> pubkeys; - private int COL_ID, COL_NICKNAME, COL_TYPE, COL_PRIVATE, COL_PUBLIC, COL_ENCRYPTED, COL_STARTUP; - protected ClipboardManager clipboard; protected LayoutInflater inflater = null; protected TerminalManager bound = null; + private MenuItem onstartToggle = null; + private ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { bound = ((TerminalManager.TerminalBinder) service).getService(); // update our listview binder to find the service - PubkeyListActivity.this.updateCursor(); + updateList(); } public void onServiceDisconnected(ComponentName className) { bound = null; - PubkeyListActivity.this.updateCursor(); + updateList(); } }; @@ -107,21 +107,21 @@ public class PubkeyListActivity extends ListActivity implements EventListener { public void onStart() { super.onStart(); - this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); + bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE); - if(this.pubkeydb == null) - this.pubkeydb = new PubkeyDatabase(this); + if(pubkeydb == null) + pubkeydb = new PubkeyDatabase(this); } @Override public void onStop() { super.onStop(); - this.unbindService(connection); + unbindService(connection); - if(this.pubkeydb != null) { - this.pubkeydb.close(); - this.pubkeydb = null; + if(pubkeydb != null) { + pubkeydb.close(); + pubkeydb = null; } } @@ -135,40 +135,31 @@ public class PubkeyListActivity extends ListActivity implements EventListener { getResources().getText(R.string.title_pubkey_list))); // connect with hosts database and populate list - this.pubkeydb = new PubkeyDatabase(this); + pubkeydb = new PubkeyDatabase(this); - this.updateCursor(); + updateList(); - this.registerForContextMenu(this.getListView()); + registerForContextMenu(getListView()); - this.COL_ID = pubkeys.getColumnIndexOrThrow("_id"); - this.COL_NICKNAME = pubkeys.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_NICKNAME); - this.COL_TYPE = pubkeys.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_TYPE); - this.COL_PRIVATE = pubkeys.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_PRIVATE); - this.COL_PUBLIC = pubkeys.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_PUBLIC); - this.COL_ENCRYPTED = pubkeys.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_ENCRYPTED); - this.COL_STARTUP = pubkeys.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_STARTUP); - - this.getListView().setOnItemClickListener(new OnItemClickListener() { + getListView().setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { - Cursor cursor = (Cursor) getListView().getItemAtPosition(position); - String nickname = cursor.getString(COL_NICKNAME); - boolean loaded = bound.isKeyLoaded(nickname); + PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(position); + boolean loaded = bound.isKeyLoaded(pubkey.getNickname()); // handle toggling key in-memory on/off if(loaded) { - bound.removeKey(nickname); + bound.removeKey(pubkey.getNickname()); updateHandler.sendEmptyMessage(-1); } else { - handleAddKey(cursor); + handleAddKey(pubkey); } } }); - this.clipboard = (ClipboardManager)this.getSystemService(CLIPBOARD_SERVICE); + clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE); - this.inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); } /** @@ -269,10 +260,8 @@ public class PubkeyListActivity extends ListActivity implements EventListener { return true; } - protected void handleAddKey(final Cursor c) { - int encrypted = c.getInt(COL_ENCRYPTED); - - if(encrypted != 0) { + protected void handleAddKey(final PubkeyBean pubkey) { + if(!pubkey.isEncrypted()) { final View view = inflater.inflate(R.layout.dia_password, null); final EditText passwordField = (EditText)view.findViewById(android.R.id.text1); @@ -280,26 +269,23 @@ public class PubkeyListActivity extends ListActivity implements EventListener { .setView(view) .setPositiveButton(R.string.pubkey_unlock, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { - handleAddKey(c, passwordField.getText().toString()); + handleAddKey(pubkey, passwordField.getText().toString()); } }) .setNegativeButton(android.R.string.cancel, null).create().show(); } else { - handleAddKey(c, null); + handleAddKey(pubkey, null); } } - protected void handleAddKey(Cursor c, String password) { - String keyNickname = c.getString(COL_NICKNAME); + protected void handleAddKey(PubkeyBean pubkey, String password) { Object trileadKey = null; - String type = c.getString(COL_TYPE); - if(PubkeyDatabase.KEY_TYPE_IMPORTED.equals(type)) { + if(PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType())) { // load specific key using pem format - byte[] raw = c.getBlob(COL_PRIVATE); try { - trileadKey = PEMDecoder.decode(new String(raw).toCharArray(), password); + trileadKey = PEMDecoder.decode(new String(pubkey.getPrivateKey()).toCharArray(), password); } catch(Exception e) { - String message = getResources().getString(R.string.pubkey_failed_add, keyNickname); + String message = getResources().getString(R.string.pubkey_failed_add, pubkey.getNickname()); Log.e(TAG, message, e); Toast.makeText(PubkeyListActivity.this, message, Toast.LENGTH_LONG); } @@ -309,10 +295,10 @@ public class PubkeyListActivity extends ListActivity implements EventListener { PrivateKey privKey = null; PublicKey pubKey = null; try { - privKey = PubkeyUtils.decodePrivate(c.getBlob(COL_PRIVATE), c.getString(COL_TYPE), password); - pubKey = PubkeyUtils.decodePublic(c.getBlob(COL_PUBLIC), c.getString(COL_TYPE)); + privKey = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), pubkey.getType(), password); + pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); } catch (Exception e) { - String message = getResources().getString(R.string.pubkey_failed_add, keyNickname); + String message = getResources().getString(R.string.pubkey_failed_add, pubkey.getNickname()); Log.e(TAG, message, e); Toast.makeText(PubkeyListActivity.this, message, Toast.LENGTH_LONG); } @@ -324,50 +310,39 @@ public class PubkeyListActivity extends ListActivity implements EventListener { if(trileadKey == null) return; - Log.d(TAG, String.format("Unlocked key '%s'", keyNickname)); + Log.d(TAG, String.format("Unlocked key '%s'", pubkey.getNickname())); // save this key in-memory if option enabled if(bound.isSavingKeys()) { - bound.addKey(keyNickname, trileadKey); + bound.addKey(pubkey.getNickname(), trileadKey); } updateHandler.sendEmptyMessage(-1); - - } - private MenuItem onstartToggle = null; - @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { // Create menu to handle deleting and editing pubkey AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; - final Cursor cursor = (Cursor) this.getListView().getItemAtPosition(info.position); + final PubkeyBean pubkey = (PubkeyBean) getListView().getItemAtPosition(info.position); - final String nickname = cursor.getString(COL_NICKNAME); - menu.setHeaderTitle(nickname); + menu.setHeaderTitle(pubkey.getNickname()); // TODO: option load/unload key from in-memory list // prompt for password as needed for passworded keys - final long id = cursor.getLong(COL_ID); - final byte[] pubkeyEncoded = cursor.getBlob(COL_PUBLIC); - final String keyType = cursor.getString(COL_TYPE); - final int encrypted = cursor.getInt(COL_ENCRYPTED); - // cant change password or clipboard imported keys - boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(cursor.getString(COL_TYPE)); - final boolean loaded = bound.isKeyLoaded(nickname); - final boolean onstart = (cursor.getInt(COL_STARTUP) == 1); + boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); + final boolean loaded = bound.isKeyLoaded(pubkey.getNickname()); MenuItem load = menu.add(loaded ? R.string.pubkey_memory_unload : R.string.pubkey_memory_load); load.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { if(loaded) { - bound.removeKey(nickname); + bound.removeKey(pubkey.getNickname()); updateHandler.sendEmptyMessage(-1); } else { - handleAddKey(cursor); + handleAddKey(pubkey); //bound.addKey(nickname, trileadKey); } return true; @@ -375,13 +350,14 @@ public class PubkeyListActivity extends ListActivity implements EventListener { }); onstartToggle = menu.add(R.string.pubkey_load_on_start); - onstartToggle.setEnabled((encrypted == 0)); + onstartToggle.setEnabled(!pubkey.isEncrypted()); onstartToggle.setCheckable(true); - onstartToggle.setChecked(onstart); + onstartToggle.setChecked(pubkey.isStartup()); onstartToggle.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { // toggle onstart status - pubkeydb.setOnStart(id, !onstart); + pubkey.setStartup(!pubkey.isStartup()); + pubkeydb.savePubkey(pubkey); updateHandler.sendEmptyMessage(-1); return true; } @@ -390,15 +366,15 @@ public class PubkeyListActivity extends ListActivity implements EventListener { MenuItem copyToClipboard = menu.add(R.string.pubkey_copy_clipboard); copyToClipboard.setEnabled(!imported); copyToClipboard.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - try { - PublicKey pk = PubkeyUtils.decodePublic(pubkeyEncoded, keyType); + public boolean onMenuItemClick(MenuItem item) { + try { + PublicKey pk = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); String openSSHPubkey = new String(PubkeyUtils.convertToOpenSSHFormat(pk)); clipboard.setText(openSSHPubkey); } catch (Exception e) { e.printStackTrace(); - } + } return true; } }); @@ -409,7 +385,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener { public boolean onMenuItemClick(MenuItem item) { final View changePasswordView = inflater.inflate(R.layout.dia_changepassword, null, false); ((TableRow)changePasswordView.findViewById(R.id.old_password_prompt)) - .setVisibility(encrypted != 0 ? View.VISIBLE : View.GONE); + .setVisibility(pubkey.isEncrypted() ? View.VISIBLE : View.GONE); new AlertDialog.Builder(PubkeyListActivity.this) .setView(changePasswordView) .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() { @@ -427,13 +403,15 @@ public class PubkeyListActivity extends ListActivity implements EventListener { } try { - if (!pubkeydb.changePassword(id, oldPassword, password1)) + if (!pubkey.changePassword(oldPassword, password1)) new AlertDialog.Builder(PubkeyListActivity.this) .setMessage(R.string.alert_wrong_password_msg) .setPositiveButton(android.R.string.ok, null) .create().show(); - else + else { + pubkeydb.savePubkey(pubkey); updateHandler.sendEmptyMessage(-1); + } } catch (Exception e) { Log.e(TAG, "Could not change private key password", e); new AlertDialog.Builder(PubkeyListActivity.this) @@ -454,16 +432,16 @@ public class PubkeyListActivity extends ListActivity implements EventListener { public boolean onMenuItemClick(MenuItem item) { // prompt user to make sure they really want this new AlertDialog.Builder(PubkeyListActivity.this) - .setMessage(getString(R.string.delete_message, nickname)) + .setMessage(getString(R.string.delete_message, pubkey.getNickname())) .setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // dont forget to remove from in-memory if(loaded) - bound.removeKey(nickname); + bound.removeKey(pubkey.getNickname()); // delete from backend database and update gui - pubkeydb.deletePubkey(id); + pubkeydb.deletePubkey(pubkey); updateHandler.sendEmptyMessage(-1); } }) @@ -479,86 +457,71 @@ public class PubkeyListActivity extends ListActivity implements EventListener { protected Handler updateHandler = new Handler() { @Override public void handleMessage(Message msg) { - PubkeyListActivity.this.updateCursor(); + updateList(); } }; - protected void updateCursor() { - if (this.pubkeys != null) - pubkeys.close(); - //pubkeys.requery(); - - if (this.pubkeydb == null) return; + protected void updateList() { + if (pubkeydb == null) return; - this.pubkeys = this.pubkeydb.allPubkeys(); + pubkeys = pubkeydb.allPubkeys(); + PubkeyAdapter adapter = new PubkeyAdapter(this, pubkeys); - SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_pubkey, this.pubkeys, - new String[] { PubkeyDatabase.FIELD_PUBKEY_NICKNAME, PubkeyDatabase.FIELD_PUBKEY_TYPE, PubkeyDatabase.FIELD_PUBKEY_ENCRYPTED }, - new int[] { android.R.id.text1, android.R.id.text2, android.R.id.icon1 }); - adapter.setViewBinder(new PubkeyBinder()); this.setListAdapter(adapter); - - //this.startManagingCursor(pubkeys); } - class PubkeyBinder implements ViewBinder { - public boolean setViewValue(View view, Cursor cursor, int columnIndex) { - switch (view.getId()) { - case android.R.id.text2: - int encrypted = cursor.getInt(cursor.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_ENCRYPTED)); - boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(cursor.getString(COL_TYPE)); - TextView caption = (TextView)view; - - if(imported) { - // for imported keys, have trilead parse them to get stats - try { - byte[] raw = cursor.getBlob(cursor.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_PRIVATE)); - PEMStructure struct = PEMDecoder.parsePEM(new String(raw).toCharArray()); - String type = (struct.pemType == PEMDecoder.PEM_RSA_PRIVATE_KEY) ? "RSA" : "DSA"; - caption.setText(String.format("%s unknown-bit", type)); - } catch (IOException e) { - Log.e(TAG, "Error decoding IMPORTED public key at " + cursor.toString(), e); - } - - - } else { - - try { - PublicKey pub = PubkeyUtils.decodePublic(cursor.getBlob(cursor.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_PUBLIC)), - cursor.getString(columnIndex)); - caption.setText(PubkeyUtils.describeKey(pub, encrypted)); - } catch (Exception e) { - Log.e(TAG, "Error decoding public key at " + cursor.toString(), e); - caption.setText(R.string.pubkey_unknown_format); - } + class PubkeyAdapter extends ArrayAdapter<PubkeyBean> { + private List<PubkeyBean> pubkeys; + + public PubkeyAdapter(Context context, List<PubkeyBean> pubkeys) { + super(context, R.layout.item_pubkey, pubkeys); + + this.pubkeys = pubkeys; + } + + public View getView(int position, View view, ViewGroup parent) { + if (view == null) + view = inflater.inflate(R.layout.item_portforward, null, false); + + TextView nickname = (TextView)view.findViewById(android.R.id.text1); + TextView caption = (TextView)view.findViewById(android.R.id.text2); + ImageView icon = (ImageView)view.findViewById(android.R.id.icon1); + + PubkeyBean pubkey = pubkeys.get(position); + nickname.setText(pubkey.getNickname()); + + boolean imported = PubkeyDatabase.KEY_TYPE_IMPORTED.equals(pubkey.getType()); + + if (imported) { + try { + PEMStructure struct = PEMDecoder.parsePEM(new String(pubkey.getPrivateKey()).toCharArray()); + String type = (struct.pemType == PEMDecoder.PEM_RSA_PRIVATE_KEY) ? "RSA" : "DSA"; + caption.setText(String.format("%s unknown-bit", type)); + } catch (IOException e) { + Log.e(TAG, "Error decoding IMPORTED public key at " + pubkey.getId(), e); } - - return true; - - case android.R.id.icon1: - - ImageView icon = (ImageView)view; - if(bound == null) { - icon.setVisibility(View.GONE); - return true; - - } else { - icon.setVisibility(View.VISIBLE); - + } else { + try { + PublicKey pub = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); + caption.setText(PubkeyUtils.describeKey(pub, pubkey.isEncrypted())); + } catch (Exception e) { + Log.e(TAG, "Error decoding public key at " + pubkey.getId(), e); + caption.setText(R.string.pubkey_unknown_format); } - - // read key in-memory status from backend terminalmanager - String nickname = cursor.getString(COL_NICKNAME); - boolean loaded = bound.isKeyLoaded(nickname); - - if(loaded) + } + + if (bound == null) { + icon.setVisibility(View.GONE); + } else { + icon.setVisibility(View.VISIBLE); + + if (bound.isKeyLoaded(pubkey.getNickname())) icon.setImageState(new int[] { android.R.attr.state_checked }, true); else icon.setImageState(new int[] { }, true); - return true; } - return false; - } + return view; + } } } diff --git a/src/org/connectbot/TerminalView.java b/src/org/connectbot/TerminalView.java index ea8c229..dfcd6f8 100644 --- a/src/org/connectbot/TerminalView.java +++ b/src/org/connectbot/TerminalView.java @@ -49,10 +49,10 @@ public class TerminalView extends View { protected int top = -1, bottom = -1, left = -1, right = -1; public void resetSelected() { - this.top = -1; - this.bottom = -1; - this.left = -1; - this.right = -1; + top = -1; + bottom = -1; + left = -1; + right = -1; } public TerminalView(Context context, TerminalBridge bridge) { @@ -60,56 +60,56 @@ public class TerminalView extends View { this.context = context; this.bridge = bridge; - this.paint = new Paint(); + paint = new Paint(); - this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); - this.setFocusable(true); - this.setFocusableInTouchMode(true); + setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); + setFocusable(true); + setFocusableInTouchMode(true); - this.cursorPaint = new Paint(); - this.cursorPaint.setColor(bridge.color[TerminalBridge.COLOR_FG_STD]); - this.cursorPaint.setXfermode(new PixelXorXfermode(bridge.color[TerminalBridge.COLOR_BG_STD])); + cursorPaint = new Paint(); + cursorPaint.setColor(bridge.color[TerminalBridge.COLOR_FG_STD]); + cursorPaint.setXfermode(new PixelXorXfermode(bridge.color[TerminalBridge.COLOR_BG_STD])); // connect our view up to the bridge - this.setOnKeyListener(bridge); + setOnKeyListener(bridge); } public void destroy() { // tell bridge to destroy its bitmap - this.bridge.parentDestroyed(); + bridge.parentDestroyed(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); - this.bridge.parentChanged(this); + bridge.parentChanged(this); } @Override public void onDraw(Canvas canvas) { - if(this.bridge.bitmap != null) { + if(bridge.bitmap != null) { // draw the bridge bitmap if it exists - canvas.drawBitmap(this.bridge.bitmap, 0, 0, this.paint); + canvas.drawBitmap(bridge.bitmap, 0, 0, paint); // also draw cursor if visible - if(this.bridge.buffer.isCursorVisible()) { - int x = this.bridge.buffer.getCursorColumn() * this.bridge.charWidth; - int y = (this.bridge.buffer.getCursorRow() - + this.bridge.buffer.screenBase - this.bridge.buffer.windowBase) - * this.bridge.charHeight; + if(bridge.buffer.isCursorVisible()) { + int x = bridge.buffer.getCursorColumn() * bridge.charWidth; + int y = (bridge.buffer.getCursorRow() + + bridge.buffer.screenBase - bridge.buffer.windowBase) + * bridge.charHeight; - canvas.drawRect(x, y, x + this.bridge.charWidth, - y + this.bridge.charHeight, cursorPaint); + canvas.drawRect(x, y, x + bridge.charWidth, + y + bridge.charHeight, cursorPaint); } // draw any highlighted area if(top >= 0 && bottom >= 0 && left >= 0 && right >= 0) { - canvas.drawRect(left * this.bridge.charWidth, top * this.bridge.charHeight, - right * this.bridge.charWidth, bottom * this.bridge.charHeight, cursorPaint); + canvas.drawRect(left * bridge.charWidth, top * bridge.charHeight, + right * bridge.charWidth, bottom * bridge.charHeight, cursorPaint); } } @@ -138,6 +138,6 @@ public class TerminalView extends View { * @param height */ public void forceSize(int width, int height) { - this.bridge.resizeComputed(width, height, getWidth(), getHeight()); + bridge.resizeComputed(width, height, getWidth(), getHeight()); } } diff --git a/src/org/connectbot/bean/HostBean.java b/src/org/connectbot/bean/HostBean.java index 3ee48d5..7e6966b 100644 --- a/src/org/connectbot/bean/HostBean.java +++ b/src/org/connectbot/bean/HostBean.java @@ -22,7 +22,7 @@ import org.connectbot.util.HostDatabase; import android.content.ContentValues; /** - * @author kenny + * @author Kenny Root * */ public class HostBean extends AbstractBean { diff --git a/src/org/connectbot/bean/PubkeyBean.java b/src/org/connectbot/bean/PubkeyBean.java new file mode 100644 index 0000000..2e5606d --- /dev/null +++ b/src/org/connectbot/bean/PubkeyBean.java @@ -0,0 +1,160 @@ +/* + ConnectBot: simple, powerful, open-source SSH client for Android + Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey + + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ +package org.connectbot.bean; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.spec.InvalidKeySpecException; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + +import org.connectbot.util.PubkeyDatabase; +import org.connectbot.util.PubkeyUtils; + +import android.content.ContentValues; + +/** + * @author Kenny Root + * + */ +public class PubkeyBean extends AbstractBean { + /* Database fields */ + private long id; + private String nickname; + private String type; + private byte[] privateKey; + private byte[] publicKey; + private boolean encrypted; + private boolean startup; + + /* Transient values */ + private boolean unlocked = false; + private Object unlockedPrivate = null; + + public void setId(long id) { + this.id = id; + } + + public long getId() { + return id; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getNickname() { + return nickname; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setPrivateKey(byte[] privateKey) { + this.privateKey = privateKey; + } + + public byte[] getPrivateKey() { + return privateKey; + } + + public void setPublicKey(byte[] publicKey) { + this.publicKey = publicKey; + } + + public byte[] getPublicKey() { + return publicKey; + } + + public void setEncrypted(boolean encrypted) { + this.encrypted = encrypted; + } + + public boolean isEncrypted() { + return encrypted; + } + + public void setStartup(boolean startup) { + this.startup = startup; + } + + public boolean isStartup() { + return startup; + } + + public void setUnlocked(boolean unlocked) { + this.unlocked = unlocked; + } + + public boolean isUnlocked() { + return unlocked; + } + + public void setUnlockedPrivate(Object unlockedPrivate) { + this.unlockedPrivate = unlockedPrivate; + } + + public Object getUnlockedPrivate() { + return unlockedPrivate; + } + + /* (non-Javadoc) + * @see org.connectbot.bean.AbstractBean#getValues() + */ + @Override + public ContentValues getValues() { + ContentValues values = new ContentValues(); + + values.put("_id", id); + values.put(PubkeyDatabase.FIELD_PUBKEY_NICKNAME, nickname); + values.put(PubkeyDatabase.FIELD_PUBKEY_TYPE, type); + values.put(PubkeyDatabase.FIELD_PUBKEY_PRIVATE, privateKey); + values.put(PubkeyDatabase.FIELD_PUBKEY_PUBLIC, publicKey); + values.put(PubkeyDatabase.FIELD_PUBKEY_ENCRYPTED, encrypted ? 1 : 0); + values.put(PubkeyDatabase.FIELD_PUBKEY_STARTUP, startup ? 1 : 0); + + return values; + } + + public boolean changePassword(String oldPassword, String newPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException { + PrivateKey priv; + + try { + priv = PubkeyUtils.decodePrivate(getPrivateKey(), getType(), oldPassword); + } catch (InvalidKeyException e) { + return false; + } catch (BadPaddingException e) { + return false; + } catch (InvalidKeySpecException e) { + return false; + } + + setPrivateKey(PubkeyUtils.getEncodedPrivate(priv, newPassword)); + setEncrypted(newPassword.length() > 0); + + return true; + } +} diff --git a/src/org/connectbot/service/TerminalManager.java b/src/org/connectbot/service/TerminalManager.java index a316936..bc2ecba 100644 --- a/src/org/connectbot/service/TerminalManager.java +++ b/src/org/connectbot/service/TerminalManager.java @@ -26,6 +26,7 @@ import java.util.List; import org.connectbot.R; import org.connectbot.bean.HostBean; +import org.connectbot.bean.PubkeyBean; import org.connectbot.util.HostDatabase; import org.connectbot.util.PubkeyDatabase; import org.connectbot.util.PubkeyUtils; @@ -34,7 +35,6 @@ import android.app.Service; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; -import android.database.Cursor; import android.net.Uri; import android.os.Binder; import android.os.Handler; @@ -84,28 +84,20 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen this.pubkeydb = new PubkeyDatabase(this); // load all marked pubkeys into memory - Cursor c = pubkeydb.getAllStartPubkeys(); - int COL_NICKNAME = c.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_NICKNAME), - COL_TYPE = c.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_TYPE), - COL_PRIVATE = c.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_PRIVATE), - COL_PUBLIC = c.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_PUBLIC); + List<PubkeyBean> pubkeys = pubkeydb.getAllStartPubkeys(); - while(c.moveToNext()) { - String keyNickname = c.getString(COL_NICKNAME); + for (PubkeyBean pubkey : pubkeys) { try { - PrivateKey privKey = PubkeyUtils.decodePrivate(c.getBlob(COL_PRIVATE), c.getString(COL_TYPE)); - PublicKey pubKey = PubkeyUtils.decodePublic(c.getBlob(COL_PUBLIC), c.getString(COL_TYPE)); + PrivateKey privKey = PubkeyUtils.decodePrivate(pubkey.getPrivateKey(), pubkey.getType()); + PublicKey pubKey = PubkeyUtils.decodePublic(pubkey.getPublicKey(), pubkey.getType()); Object trileadKey = PubkeyUtils.convertToTrilead(privKey, pubKey); - this.loadedPubkeys.put(keyNickname, trileadKey); - Log.d(TAG, String.format("Added key '%s' to in-memory cache", keyNickname)); + this.loadedPubkeys.put(pubkey.getNickname(), trileadKey); + Log.d(TAG, String.format("Added key '%s' to in-memory cache", pubkey.getNickname())); } catch (Exception e) { - Log.d(TAG, String.format("Problem adding key '%s' to in-memory cache", keyNickname), e); + Log.d(TAG, String.format("Problem adding key '%s' to in-memory cache", pubkey.getNickname()), e); } } - c.close(); - - } @Override diff --git a/src/org/connectbot/util/HostDatabase.java b/src/org/connectbot/util/HostDatabase.java index 0ccf5c0..91472ea 100644 --- a/src/org/connectbot/util/HostDatabase.java +++ b/src/org/connectbot/util/HostDatabase.java @@ -205,7 +205,7 @@ public class HostDatabase extends SQLiteOpenHelper { Cursor c = db.query(TABLE_HOSTS, null, null, null, null, null, sortField + " ASC"); - int COL_ID = c.getColumnIndexOrThrow("_id"), + final int COL_ID = c.getColumnIndexOrThrow("_id"), COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_HOST_NICKNAME), COL_USERNAME = c.getColumnIndexOrThrow(FIELD_HOST_USERNAME), COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME), diff --git a/src/org/connectbot/util/PubkeyDatabase.java b/src/org/connectbot/util/PubkeyDatabase.java index f7228b2..685c960 100644 --- a/src/org/connectbot/util/PubkeyDatabase.java +++ b/src/org/connectbot/util/PubkeyDatabase.java @@ -18,16 +18,10 @@ package org.connectbot.util; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.spec.InvalidKeySpecException; import java.util.LinkedList; import java.util.List; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; +import org.connectbot.bean.PubkeyBean; import android.content.ContentValues; import android.content.Context; @@ -39,10 +33,9 @@ import android.database.sqlite.SQLiteOpenHelper; * Public Key Encryption database. Contains private and public key pairs * for public key authentication. * - * @author kroot + * @author Kenny Root */ -public class PubkeyDatabase extends SQLiteOpenHelper { - +public class PubkeyDatabase extends SQLiteOpenHelper { public final static String TAG = PubkeyDatabase.class.toString(); public final static String DB_NAME = "pubkeys"; @@ -110,24 +103,69 @@ public class PubkeyDatabase extends SQLiteOpenHelper { /** * Delete a specific host by its <code>_id</code> value. */ - public void deletePubkey(long id) { - SQLiteDatabase db = this.getWritableDatabase(); - db.delete(TABLE_PUBKEYS, "_id = ?", new String[] { Long.toString(id) }); - + public void deletePubkey(PubkeyBean pubkey) { HostDatabase hostdb = new HostDatabase(context); - hostdb.stopUsingPubkey(id); + hostdb.stopUsingPubkey(pubkey.getId()); hostdb.close(); + + SQLiteDatabase db = getWritableDatabase(); + db.delete(TABLE_PUBKEYS, "_id = ?", new String[] { Long.toString(pubkey.getId()) }); + db.close(); } /** * Return a cursor that contains information about all known hosts. */ + /* public Cursor allPubkeys() { SQLiteDatabase db = this.getReadableDatabase(); return db.query(TABLE_PUBKEYS, new String[] { "_id", FIELD_PUBKEY_NICKNAME, FIELD_PUBKEY_TYPE, FIELD_PUBKEY_PRIVATE, FIELD_PUBKEY_PUBLIC, FIELD_PUBKEY_ENCRYPTED, FIELD_PUBKEY_STARTUP }, null, null, null, null, null); + }*/ + + public List<PubkeyBean> allPubkeys() { + return getPubkeys(null, null); + } + + public List<PubkeyBean> getAllStartPubkeys() { + return getPubkeys(FIELD_PUBKEY_STARTUP + " = 1 AND " + FIELD_PUBKEY_ENCRYPTED + " = 0", null); + } + + private List<PubkeyBean> getPubkeys(String selection, String[] selectionArgs) { + SQLiteDatabase db = getReadableDatabase(); + + List<PubkeyBean> pubkeys = new LinkedList<PubkeyBean>(); + + Cursor c = db.query(TABLE_PUBKEYS, null, selection, selectionArgs, null, null, null); + + final int COL_ID = c.getColumnIndexOrThrow("_id"), + COL_NICKNAME = c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME), + COL_TYPE = c.getColumnIndexOrThrow(FIELD_PUBKEY_TYPE), + COL_PRIVATE = c.getColumnIndexOrThrow(FIELD_PUBKEY_PRIVATE), + COL_PUBLIC = c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC), + COL_ENCRYPTED = c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED), + COL_STARTUP = c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP); + + while (c.moveToNext()) { + PubkeyBean pubkey = new PubkeyBean(); + + pubkey.setId(c.getLong(COL_ID)); + pubkey.setNickname(c.getString(COL_NICKNAME)); + pubkey.setType(c.getString(COL_TYPE)); + pubkey.setPrivateKey(c.getBlob(COL_PRIVATE)); + pubkey.setPublicKey(c.getBlob(COL_PUBLIC)); + pubkey.setEncrypted(Boolean.valueOf(c.getString(COL_ENCRYPTED))); + pubkey.setStartup(Boolean.valueOf(c.getString(COL_STARTUP))); + + pubkeys.add(pubkey); + } + + c.close(); + db.close(); + + return pubkeys; } public Cursor getPubkey(long id) { @@ -139,14 +177,50 @@ public class PubkeyDatabase extends SQLiteOpenHelper { null, null, null); } - public Cursor getAllStartPubkeys() { + /*public Cursor getAllStartPubkeys() { SQLiteDatabase db = this.getReadableDatabase(); return db.query(TABLE_PUBKEYS, new String[] { "_id", FIELD_PUBKEY_NICKNAME, FIELD_PUBKEY_TYPE, FIELD_PUBKEY_PRIVATE, FIELD_PUBKEY_PUBLIC, FIELD_PUBKEY_ENCRYPTED, FIELD_PUBKEY_STARTUP }, FIELD_PUBKEY_STARTUP + " = 1 AND " + FIELD_PUBKEY_ENCRYPTED + " = 0", null, null, null, null); + }*/ + + /** + * @param hostId + * @return + */ + public PubkeyBean findPubkeyById(long pubkeyId) { + SQLiteDatabase db = getReadableDatabase(); + + Cursor c = db.query(TABLE_PUBKEYS, null, + "_id = ?", new String[] { String.valueOf(pubkeyId) }, + null, null, null); + + PubkeyBean pubkey = null; + + if (c != null && c.moveToFirst()) { + pubkey = createPubkeyBean(c); + } + + c.close(); + db.close(); + + return pubkey; } + private PubkeyBean createPubkeyBean(Cursor c) { + PubkeyBean pubkey = new PubkeyBean(); + + pubkey.setId(c.getLong(c.getColumnIndexOrThrow("_id"))); + pubkey.setNickname(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_NICKNAME))); + pubkey.setType(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_TYPE))); + pubkey.setPrivateKey(c.getBlob(c.getColumnIndexOrThrow(FIELD_PUBKEY_PRIVATE))); + pubkey.setPublicKey(c.getBlob(c.getColumnIndexOrThrow(FIELD_PUBKEY_PUBLIC))); + pubkey.setEncrypted(Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_ENCRYPTED)))); + pubkey.setStartup(Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_PUBKEY_STARTUP)))); + + return pubkey; + } /** * Pull all values for a given column as a list of Strings, probably for use @@ -167,7 +241,7 @@ public class PubkeyDatabase extends SQLiteOpenHelper { return list; } - + public String getNickname(long id) { String nickname = null; @@ -183,7 +257,7 @@ public class PubkeyDatabase extends SQLiteOpenHelper { return nickname; } - +/* public void setOnStart(long id, boolean onStart) { SQLiteDatabase db = this.getWritableDatabase(); @@ -195,7 +269,6 @@ public class PubkeyDatabase extends SQLiteOpenHelper { } - public boolean changePassword(long id, String oldPassword, String newPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException { SQLiteDatabase db = this.getWritableDatabase(); @@ -229,5 +302,28 @@ public class PubkeyDatabase extends SQLiteOpenHelper { return true; } + */ + + /** + * @param pubkey + */ + public PubkeyBean savePubkey(PubkeyBean pubkey) { + SQLiteDatabase db = this.getWritableDatabase(); + boolean success = false; + ContentValues values = pubkey.getValues(); + if (pubkey.getId() > 0) { + values.remove("_id"); + if (db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(pubkey.getId()) }) > 0) + success = true; + } + + if (!success) { + long id = db.insert(TABLE_PUBKEYS, null, pubkey.getValues()); + pubkey.setId(id); + } + + db.close(); + return pubkey; + } } diff --git a/src/org/connectbot/util/PubkeyUtils.java b/src/org/connectbot/util/PubkeyUtils.java index 8702987..e13129e 100644 --- a/src/org/connectbot/util/PubkeyUtils.java +++ b/src/org/connectbot/util/PubkeyUtils.java @@ -54,7 +54,7 @@ public class PubkeyUtils { ", bytes=" + encoded.length + "]"; } - public static String describeKey(Key key, int encrypted) { + public static String describeKey(Key key, boolean encrypted) { String desc = null; if (key instanceof RSAPublicKey) { int bits = ((RSAPublicKey)key).getModulus().bitLength(); @@ -65,7 +65,7 @@ public class PubkeyUtils { desc = "Unknown Key Type"; } - if (encrypted != 0) + if (encrypted) desc += " (encrypted)"; return desc; |