aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2008-11-14 12:07:29 +0000
committerKenny Root <kenny@the-b.org>2008-11-14 12:07:29 +0000
commit12ef92bf1319f2ce698bb979c49f781c2a884316 (patch)
tree0de242e52ad3103f3630dba12cd65f4800961342 /src
parent2f1d9fb2e826a2a40cfe036e22b57dfdf2b0f9e9 (diff)
downloadconnectbot-12ef92bf1319f2ce698bb979c49f781c2a884316.tar.gz
connectbot-12ef92bf1319f2ce698bb979c49f781c2a884316.tar.bz2
connectbot-12ef92bf1319f2ce698bb979c49f781c2a884316.zip
* Convert host entries to beans
* We no longer lose connections to hosts not in the database made from shortcuts
Diffstat (limited to 'src')
-rw-r--r--src/org/connectbot/ConsoleActivity.java20
-rw-r--r--src/org/connectbot/HostListActivity.java267
-rw-r--r--src/org/connectbot/PortForwardListActivity.java22
-rw-r--r--src/org/connectbot/bean/HostBean.java184
-rw-r--r--src/org/connectbot/bean/PortForwardBean.java2
-rw-r--r--src/org/connectbot/service/TerminalBridge.java66
-rw-r--r--src/org/connectbot/service/TerminalManager.java44
-rw-r--r--src/org/connectbot/util/HostBinder.java144
-rw-r--r--src/org/connectbot/util/HostDatabase.java321
9 files changed, 581 insertions, 489 deletions
diff --git a/src/org/connectbot/ConsoleActivity.java b/src/org/connectbot/ConsoleActivity.java
index d93a0ce..53cecfc 100644
--- a/src/org/connectbot/ConsoleActivity.java
+++ b/src/org/connectbot/ConsoleActivity.java
@@ -18,11 +18,11 @@
package org.connectbot;
+import org.connectbot.bean.HostBean;
import org.connectbot.bean.PortForwardBean;
import org.connectbot.service.PromptHelper;
import org.connectbot.service.TerminalBridge;
import org.connectbot.service.TerminalManager;
-import org.connectbot.util.HostDatabase;
import android.app.Activity;
import android.app.AlertDialog;
@@ -92,7 +92,7 @@ public class ConsoleActivity extends Activity {
// first check if we need to create a new session for requested
boolean found = false;
for(TerminalBridge bridge : bound.bridges) {
- if(bridge.nickname.equals(requestedNickname))
+ if(bridge.host.getNickname().equals(requestedNickname))
found = true;
}
@@ -118,7 +118,7 @@ public class ConsoleActivity extends Activity {
// set the terminal overlay text
TextView overlay = (TextView)view.findViewById(R.id.terminal_overlay);
- overlay.setText(bridge.nickname);
+ overlay.setText(bridge.host.getNickname());
// and add our terminal view control, using index to place behind overlay
TerminalView terminal = new TerminalView(ConsoleActivity.this, bridge);
@@ -129,7 +129,7 @@ public class ConsoleActivity extends Activity {
flip.addView(view);
// check to see if this bridge was requested
- if(bridge.nickname.equals(requestedNickname))
+ if(bridge.host.getNickname().equals(requestedNickname))
requestedIndex = flip.getChildCount() - 1;
}
@@ -159,10 +159,10 @@ public class ConsoleActivity extends Activity {
}
};
- protected String getCurrentNickname() {
+ protected HostBean getCurrentHost() {
View view = findCurrentView(R.id.console_flip);
if(!(view instanceof TerminalView)) return null;
- return ((TerminalView)view).bridge.nickname;
+ return ((TerminalView)view).bridge.host;
}
public Handler promptHandler = new Handler() {
@@ -625,7 +625,7 @@ public class ConsoleActivity extends Activity {
boolean sessionOpen = false;
if(activeTerminal) {
authenticated = ((TerminalView) view).bridge.isAuthenticated();
- sessionOpen = ((TerminalView)view).bridge.isSessionOpen();
+ sessionOpen = ((TerminalView) view).bridge.isSessionOpen();
}
disconnect = menu.add(R.string.console_menu_disconnect);
@@ -682,7 +682,7 @@ public class ConsoleActivity extends Activity {
portForward.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(ConsoleActivity.this, PortForwardListActivity.class);
- intent.putExtra(Intent.EXTRA_TITLE, bound.hostdb.findHostByNickname(getCurrentNickname()));
+ intent.putExtra(Intent.EXTRA_TITLE, ((TerminalView) view).bridge.host.getId());
ConsoleActivity.this.startActivityForResult(intent, REQUEST_EDIT);
return true;
}
@@ -712,14 +712,12 @@ public class ConsoleActivity extends Activity {
});
return true;
-
}
protected void createPortForward(TerminalView target, String nickname, String type, String source, String dest) {
String summary = getString(R.string.portforward_problem);
try {
- HostDatabase hostdb = new HostDatabase(this);
- long hostId = hostdb.findHostByNickname(target.bridge.nickname);
+ long hostId = target.bridge.host.getId();
PortForwardBean pfb = new PortForwardBean(hostId, nickname, type, source, dest);
diff --git a/src/org/connectbot/HostListActivity.java b/src/org/connectbot/HostListActivity.java
index 15560d3..86769b4 100644
--- a/src/org/connectbot/HostListActivity.java
+++ b/src/org/connectbot/HostListActivity.java
@@ -18,11 +18,12 @@
package org.connectbot;
+import java.util.List;
import java.util.regex.Pattern;
+import org.connectbot.bean.HostBean;
import org.connectbot.service.TerminalBridge;
import org.connectbot.service.TerminalManager;
-import org.connectbot.util.HostBinder;
import org.connectbot.util.HostDatabase;
import org.connectbot.util.UpdateHelper;
@@ -37,56 +38,64 @@ import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.Intent.ShortcutIconResource;
import android.content.SharedPreferences.Editor;
-import android.database.Cursor;
+import android.content.res.ColorStateList;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
+import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
+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.view.View.OnKeyListener;
import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
public class HostListActivity extends ListActivity {
-
+ protected TerminalManager bound = null;
+
+ protected HostDatabase hostdb;
+ protected List<HostBean> hosts;
+ protected LayoutInflater inflater = null;
+
+ public boolean sortedByColor = false;
+
+ public MenuItem sortcolor;
+
+ public MenuItem sortlast;
+
public Handler updateHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- HostListActivity.this.updateCursor();
+ HostListActivity.this.updateList();
}
};
-
- protected TerminalManager bound = 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
- HostListActivity.this.updateCursor();
+ HostListActivity.this.updateList();
}
-
+
public void onServiceDisconnected(ComponentName className) {
bound = null;
- HostListActivity.this.updateCursor();
+ HostListActivity.this.updateList();
}
};
- protected HostDatabase hostdb;
- protected Cursor hosts;
-
- protected int COL_ID, COL_NICKNAME, COL_USERNAME, COL_HOSTNAME, COL_CONNECTED, COL_PORT;
-
@Override
public void onStart() {
super.onStart();
@@ -98,7 +107,7 @@ public class HostListActivity extends ListActivity {
if(this.hostdb == null)
this.hostdb = new HostDatabase(this);
- this.updateCursor();
+ this.updateList();
}
@@ -107,11 +116,6 @@ public class HostListActivity extends ListActivity {
super.onStop();
this.unbindService(connection);
- if(this.hosts != null) {
- this.hosts.close();
- this.hosts = null;
- }
-
if(this.hostdb != null) {
this.hostdb.close();
this.hostdb = null;
@@ -145,7 +149,7 @@ public class HostListActivity extends ListActivity {
break;
case REQUEST_EDIT:
- this.updateCursor();
+ this.updateList();
break;
}
@@ -175,9 +179,6 @@ public class HostListActivity extends ListActivity {
// start thread to check for new version
new UpdateHelper(this);
-
-
-
this.makingShortcut = Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction());
// connect with hosts database and populate list
@@ -185,30 +186,21 @@ public class HostListActivity extends ListActivity {
ListView list = this.getListView();
this.sortedByColor = prefs.getBoolean(PREF_SORTBYCOLOR, false);
- this.updateCursor();
+ this.updateList();
//this.list.setSelector(R.drawable.highlight_disabled_pressed);
- this.COL_ID = hosts.getColumnIndexOrThrow("_id");
- this.COL_NICKNAME = hosts.getColumnIndexOrThrow(HostDatabase.FIELD_HOST_NICKNAME);
- this.COL_USERNAME = hosts.getColumnIndexOrThrow(HostDatabase.FIELD_HOST_USERNAME);
- this.COL_HOSTNAME = hosts.getColumnIndexOrThrow(HostDatabase.FIELD_HOST_HOSTNAME);
- this.COL_PORT = hosts.getColumnIndexOrThrow(HostDatabase.FIELD_HOST_PORT);
- this.COL_CONNECTED = hosts.getColumnIndexOrThrow(HostDatabase.FIELD_HOST_LASTCONNECT);
-
list.setOnItemClickListener(new OnItemClickListener() {
public synchronized void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// launch off to console details
- Cursor c = (Cursor)parent.getAdapter().getItem(position);
- String username = c.getString(COL_USERNAME);
- String hostname = c.getString(COL_HOSTNAME);
- int port = c.getInt(COL_PORT);
- String nickname = c.getString(COL_NICKNAME);
+ HostBean host = (HostBean) parent.getAdapter().getItem(position);
// create a specific uri that represents this host
- Uri uri = Uri.parse(String.format("ssh://%s@%s:%s/#%s", username, hostname, port, nickname));
+ Uri uri = Uri.parse(String.format("ssh://%s@%s:%s/#%s",
+ host.getUsername(), host.getHostname(),
+ host.getPort(), host.getNickname()));
Intent contents = new Intent(Intent.ACTION_VIEW, uri);
contents.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -219,7 +211,7 @@ public class HostListActivity extends ListActivity {
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, contents);
- intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, nickname);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, host.getNickname());
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
setResult(RESULT_OK, intent);
@@ -228,13 +220,8 @@ public class HostListActivity extends ListActivity {
} else {
// otherwise just launch activity to show this host
HostListActivity.this.startActivity(contents);
-
-
- }
-
-
+ }
}
-
});
this.registerForContextMenu(list);
@@ -273,7 +260,10 @@ public class HostListActivity extends ListActivity {
nickname = String.format("%s@%s:%d", username, hostname, port);
}
- hostdb.createHost(null, nickname, username, hostname, port, HostDatabase.COLOR_GRAY, HostDatabase.PUBKEYID_ANY);
+ HostBean host = new HostBean(nickname, username, hostname, port);
+ host.setColor(HostDatabase.COLOR_GRAY);
+ host.setPubkeyId(HostDatabase.PUBKEYID_ANY);
+ hostdb.saveHost(host);
Intent intent = new Intent(HostListActivity.this, ConsoleActivity.class);
intent.setData(Uri.parse(String.format("ssh://%s@%s:%s/#%s", username, hostname, port, nickname)));
@@ -289,42 +279,18 @@ public class HostListActivity extends ListActivity {
});
+ this.inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
- public MenuItem sortcolor, sortlast;
- public boolean sortedByColor = false;
-
- protected void updateCursor() {
-
- Editor edit = prefs.edit();
- edit.putBoolean(PREF_SORTBYCOLOR, sortedByColor);
- edit.commit();
-
- // refresh cursor because of possible sorting change
- if(this.hosts != null)
- this.hosts.close();
- if(this.hostdb == null) return;
- this.hosts = this.hostdb.allHosts(sortedByColor);
-
- SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_host, this.hosts,
- new String[] { HostDatabase.FIELD_HOST_NICKNAME, HostDatabase.FIELD_HOST_LASTCONNECT, HostDatabase.FIELD_HOST_LASTCONNECT, HostDatabase.FIELD_HOST_COLOR },
- new int[] { android.R.id.text1, android.R.id.text2, android.R.id.icon, android.R.id.content });
- adapter.setViewBinder(new HostBinder(bound, this.getResources()));
-
- //this.adapter = new HostAdapter(this, this.hosts);
- this.setListAdapter(adapter);
-
- }
-
- @Override
+ @Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- if (sortcolor != null)
- sortcolor.setVisible(!sortedByColor);
+ // don't offer menus when creating shortcut
+ if (makingShortcut) return true;
- if (sortlast != null)
- sortlast.setVisible(sortedByColor);
+ sortcolor.setVisible(!sortedByColor);
+ sortlast.setVisible(sortedByColor);
return true;
}
@@ -333,7 +299,7 @@ public class HostListActivity extends ListActivity {
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- // dont offer menus when creating shortcut
+ // don't offer menus when creating shortcut
if(makingShortcut) return true;
// add host, ssh keys, about
@@ -342,7 +308,7 @@ public class HostListActivity extends ListActivity {
sortcolor.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
sortedByColor = true;
- updateCursor();
+ updateList();
return true;
}
});
@@ -352,7 +318,7 @@ public class HostListActivity extends ListActivity {
sortlast.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
sortedByColor = false;
- updateCursor();
+ updateList();
return true;
}
});
@@ -381,15 +347,13 @@ public class HostListActivity extends ListActivity {
// create menu to handle deleting and sharing lists
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Cursor cursor = (Cursor) this.getListView().getItemAtPosition(info.position);
+ final HostBean host = (HostBean) this.getListView().getItemAtPosition(info.position);
- final String nickname = cursor.getString(COL_NICKNAME);
- menu.setHeaderTitle(nickname);
- final long id = cursor.getLong(COL_ID);
+ menu.setHeaderTitle(host.getNickname());
// edit, disconnect, delete
MenuItem connect = menu.add(R.string.list_host_disconnect);
- final TerminalBridge bridge = bound.findBridge(nickname);
+ final TerminalBridge bridge = bound.findBridge(host);
connect.setEnabled((bridge != null));
connect.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
@@ -403,7 +367,7 @@ public class HostListActivity extends ListActivity {
edit.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(HostListActivity.this, HostEditorActivity.class);
- intent.putExtra(Intent.EXTRA_TITLE, id);
+ intent.putExtra(Intent.EXTRA_TITLE, host.getId());
HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT);
return true;
}
@@ -413,7 +377,7 @@ public class HostListActivity extends ListActivity {
portForwards.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(HostListActivity.this, PortForwardListActivity.class);
- intent.putExtra(Intent.EXTRA_TITLE, id);
+ intent.putExtra(Intent.EXTRA_TITLE, host.getId());
HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT);
return true;
}
@@ -424,14 +388,14 @@ public class HostListActivity extends ListActivity {
public boolean onMenuItemClick(MenuItem item) {
// prompt user to make sure they really want this
new AlertDialog.Builder(HostListActivity.this)
- .setMessage(getString(R.string.delete_message, nickname))
+ .setMessage(getString(R.string.delete_message, host.getNickname()))
.setPositiveButton(R.string.delete_pos, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// make sure we disconnect
if(bridge != null)
bridge.dispatchDisconnect();
- hostdb.deleteHost(id);
+ hostdb.deleteHost(host);
updateHandler.sendEmptyMessage(-1);
}
})
@@ -440,7 +404,130 @@ public class HostListActivity extends ListActivity {
return true;
}
});
+ }
+
+ protected void updateList() {
+ Editor edit = prefs.edit();
+ edit.putBoolean(PREF_SORTBYCOLOR, sortedByColor);
+ edit.commit();
+
+ if (hostdb == null)
+ hostdb = new HostDatabase(this);
+
+ hosts = hostdb.getHosts(sortedByColor);
+
+ // Don't lose hosts that are connected via shortcuts but not in the database.
+ if (bound != null) {
+ for (TerminalBridge bridge : bound.bridges) {
+ if (!hosts.contains(bridge.host))
+ hosts.add(0, bridge.host);
+ }
+ }
+ HostAdapter adapter = new HostAdapter(this, hosts, bound);
+
+ this.setListAdapter(adapter);
}
+
+ class HostAdapter extends ArrayAdapter<HostBean> {
+ private List<HostBean> hosts;
+ private final TerminalManager manager;
+ private final ColorStateList red, green, blue;
+
+ public final static int STATE_UNKNOWN = 1, STATE_CONNECTED = 2, STATE_DISCONNECTED = 3;
+
+ public HostAdapter(Context context, List<HostBean> hosts, TerminalManager manager) {
+ super(context, R.layout.item_host, hosts);
+
+ this.hosts = hosts;
+ this.manager = manager;
+
+ red = context.getResources().getColorStateList(R.color.red);
+ green = context.getResources().getColorStateList(R.color.green);
+ blue = context.getResources().getColorStateList(R.color.blue);
+ }
+
+ /**
+ * Check if we're connected to a terminal with the given host.
+ */
+ protected int getConnectedState(HostBean host) {
+ // always disconnected if we dont have backend service
+ if (this.manager == null)
+ return STATE_UNKNOWN;
+
+ if (manager.findBridge(host) != null)
+ return STATE_CONNECTED;
+
+ if (manager.disconnected.contains(host))
+ return STATE_DISCONNECTED;
+
+ return STATE_UNKNOWN;
+ }
+
+ public View getView(int position, View view, ViewGroup parent) {
+ if (view == null)
+ view = inflater.inflate(R.layout.item_host, 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.icon);
+ Log.d("HostAdapter", String.format("Checking position %d", position));
+ HostBean host = hosts.get(position);
+ if (host == null) {
+ Log.e("HostAdapter", "What the fuck, host bean is null!");
+ }
+ nickname.setText(host.getNickname());
+
+ switch(this.getConnectedState(host)) {
+ case STATE_UNKNOWN:
+ icon.setImageState(new int[] { }, true);
+ break;
+ case STATE_CONNECTED:
+ icon.setImageState(new int[] { android.R.attr.state_checked }, true);
+ break;
+ case STATE_DISCONNECTED:
+ icon.setImageState(new int[] { android.R.attr.state_expanded }, true);
+ break;
+ }
+
+ ColorStateList chosen = null;
+ if (HostDatabase.COLOR_RED.equals(host.getColor()))
+ chosen = this.red;
+ else if (HostDatabase.COLOR_GREEN.equals(host.getColor()))
+ chosen = this.green;
+ else if (HostDatabase.COLOR_BLUE.equals(host.getColor()))
+ chosen = this.blue;
+
+ if(chosen != null) {
+ // set color normally if not selected
+ nickname.setTextColor(chosen);
+ caption.setTextColor(chosen);
+ } else {
+ // selected, so revert back to default black text
+ nickname.setTextAppearance(view.getContext(), android.R.attr.textAppearanceLarge);
+ caption.setTextAppearance(view.getContext(), android.R.attr.textAppearanceSmall);
+ }
+
+ long now = System.currentTimeMillis() / 1000;
+
+ String nice = "never";
+ if(host.getLastConnect() > 0) {
+ int minutes = (int)((now - host.getLastConnect()) / 60);
+ nice = view.getContext().getString(R.string.bind_minutes, minutes);
+ if (minutes >= 60) {
+ int hours = (minutes / 60);
+ nice = view.getContext().getString(R.string.bind_hours, hours);
+ if (hours >= 24) {
+ int days = (hours / 24);
+ nice = view.getContext().getString(R.string.bind_days, days);
+ }
+ }
+ }
+
+ caption.setText(nice);
+
+ return view;
+ }
+ }
}
diff --git a/src/org/connectbot/PortForwardListActivity.java b/src/org/connectbot/PortForwardListActivity.java
index e2097fa..688669d 100644
--- a/src/org/connectbot/PortForwardListActivity.java
+++ b/src/org/connectbot/PortForwardListActivity.java
@@ -20,6 +20,7 @@ package org.connectbot;
import java.util.List;
+import org.connectbot.bean.HostBean;
import org.connectbot.bean.PortForwardBean;
import org.connectbot.service.TerminalBridge;
import org.connectbot.service.TerminalManager;
@@ -52,6 +53,7 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
+import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
@@ -73,7 +75,7 @@ public class PortForwardListActivity extends ListActivity {
protected TerminalBridge hostBridge = null;
protected LayoutInflater inflater = null;
- private long hostId;
+ private HostBean host;
@Override
public void onStart() {
@@ -101,25 +103,25 @@ public class PortForwardListActivity extends ListActivity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- this.hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1);
+ long hostId = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1);
setContentView(R.layout.act_portforwardlist);
// connect with hosts database and populate list
this.hostdb = new HostDatabase(this);
- final String hostNickname = hostdb.findNicknameById(hostId);
+ host = hostdb.findHostById(hostId);
this.setTitle(String.format("%s: %s (%s)",
getResources().getText(R.string.app_name),
getResources().getText(R.string.title_port_forwards_list),
- hostNickname));
+ host.getNickname()));
connection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
TerminalManager bound = ((TerminalManager.TerminalBinder) service).getService();
for (TerminalBridge bridge: bound.bridges) {
- if (bridge.nickname.equals(hostNickname)) {
+ if (bridge.host.equals(host)) {
hostBridge = bridge;
updateHandler.sendEmptyMessage(-1);
Log.d(TAG, "Found host bridge; using that instead of database");
@@ -147,8 +149,10 @@ public class PortForwardListActivity extends ListActivity {
if (hostBridge != null) {
if (pfb.isEnabled())
hostBridge.disablePortForward(pfb);
- else
- hostBridge.enablePortForward(pfb);
+ else {
+ if (!hostBridge.enablePortForward(pfb))
+ Toast.makeText(PortForwardListActivity.this, getString(R.string.portforward_problem), Toast.LENGTH_LONG).show();
+ }
updateHandler.sendEmptyMessage(-1);
}
@@ -201,7 +205,7 @@ public class PortForwardListActivity extends ListActivity {
break;
}
- PortForwardBean pfb = new PortForwardBean(hostId,
+ PortForwardBean pfb = new PortForwardBean(host.getId(),
nicknameEdit.getText().toString(), type,
sourcePortEdit.getText().toString(),
destEdit.getText().toString());
@@ -357,7 +361,7 @@ public class PortForwardListActivity extends ListActivity {
this.portForwards = hostBridge.getPortForwards();
} else {
if (this.hostdb == null) return;
- this.portForwards = this.hostdb.getPortForwardsForHost(hostId);
+ this.portForwards = this.hostdb.getPortForwardsForHost(host);
}
PortForwardAdapter adapter = new PortForwardAdapter(this, this.portForwards);
diff --git a/src/org/connectbot/bean/HostBean.java b/src/org/connectbot/bean/HostBean.java
new file mode 100644
index 0000000..683ed15
--- /dev/null
+++ b/src/org/connectbot/bean/HostBean.java
@@ -0,0 +1,184 @@
+/*
+ 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 org.connectbot.util.HostDatabase;
+
+import android.content.ContentValues;
+
+/**
+ * @author kenny
+ *
+ */
+public class HostBean {
+ /* Database fields */
+ private long id = -1;
+ private String nickname = null;
+ private String username = null;
+ private String hostname = null;
+ private int port = 22;
+ private String hostKeyAlgo = null;
+ private byte[] hostKey = null;
+ private long lastConnect = -1;
+ private String color;
+ private boolean useKeys = true;
+ private byte[] postLogin = null;
+ private long pubkeyId = -1;
+ private boolean wantSession = true;
+ private boolean compression = false;
+
+ public HostBean() {
+
+ }
+
+ public HostBean(String nickname, String username, String hostname, int port) {
+ this.nickname = nickname;
+ this.username = username;
+ this.hostname = hostname;
+ this.port = port;
+ }
+
+ 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 setUsername(String username) {
+ this.username = username;
+ }
+ public String getUsername() {
+ return username;
+ }
+ public void setHostname(String hostname) {
+ this.hostname = hostname;
+ }
+ public String getHostname() {
+ return hostname;
+ }
+ public void setPort(int port) {
+ this.port = port;
+ }
+ public int getPort() {
+ return port;
+ }
+ public void setHostKeyAlgo(String hostKeyAlgo) {
+ this.hostKeyAlgo = hostKeyAlgo;
+ }
+ public String getHostKeyAlgo() {
+ return hostKeyAlgo;
+ }
+ public void setHostKey(byte[] hostKey) {
+ this.hostKey = hostKey;
+ }
+ public byte[] getHostKey() {
+ return hostKey;
+ }
+ public void setLastConnect(long lastConnect) {
+ this.lastConnect = lastConnect;
+ }
+ public long getLastConnect() {
+ return lastConnect;
+ }
+ public void setColor(String color) {
+ this.color = color;
+ }
+ public String getColor() {
+ return color;
+ }
+ public void setUseKeys(boolean useKeys) {
+ this.useKeys = useKeys;
+ }
+ public boolean getUseKeys() {
+ return useKeys;
+ }
+ public void setPostLogin(byte[] postLogin) {
+ this.postLogin = postLogin;
+ }
+ public byte[] getPostLogin() {
+ return postLogin;
+ }
+ public void setPubkeyId(long pubkeyId) {
+ this.pubkeyId = pubkeyId;
+ }
+ public long getPubkeyId() {
+ return pubkeyId;
+ }
+ public void setWantSession(boolean wantSession) {
+ this.wantSession = wantSession;
+ }
+ public boolean getWantSession() {
+ return wantSession;
+ }
+ public void setCompression(boolean compression) {
+ this.compression = compression;
+ }
+ public boolean getCompression() {
+ return compression;
+ }
+
+ public String getDescription() {
+ String description = String.format("%s@%s", username, hostname);
+
+ if (port != 22)
+ description += String.format(":%d", port);
+
+ return description;
+ }
+
+ public ContentValues getValues() {
+ ContentValues values = new ContentValues();
+
+ values.put(HostDatabase.FIELD_HOST_NICKNAME, nickname);
+ values.put(HostDatabase.FIELD_HOST_USERNAME, username);
+ values.put(HostDatabase.FIELD_HOST_HOSTNAME, hostname);
+ values.put(HostDatabase.FIELD_HOST_PORT, port);
+ values.put(HostDatabase.FIELD_HOST_HOSTKEYALGO, hostKeyAlgo);
+ values.put(HostDatabase.FIELD_HOST_HOSTKEY, hostKey);
+ values.put(HostDatabase.FIELD_HOST_LASTCONNECT, lastConnect);
+ values.put(HostDatabase.FIELD_HOST_COLOR, color);
+ values.put(HostDatabase.FIELD_HOST_USEKEYS, Boolean.toString(useKeys));
+ values.put(HostDatabase.FIELD_HOST_POSTLOGIN, postLogin);
+ values.put(HostDatabase.FIELD_HOST_PUBKEYID, pubkeyId);
+ values.put(HostDatabase.FIELD_HOST_WANTSESSION, Boolean.toString(wantSession));
+ values.put(HostDatabase.FIELD_HOST_COMPRESSION, Boolean.toString(compression));
+
+ return values;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof HostBean))
+ return false;
+
+ HostBean host = (HostBean)o;
+
+ if (host.getNickname().equals(nickname)
+ && host.getUsername().equals(username)
+ && host.getHostname().equals(hostname)
+ && host.getPort() == port)
+ return true;
+
+ return false;
+ }
+}
diff --git a/src/org/connectbot/bean/PortForwardBean.java b/src/org/connectbot/bean/PortForwardBean.java
index ea344c9..6cbf6fa 100644
--- a/src/org/connectbot/bean/PortForwardBean.java
+++ b/src/org/connectbot/bean/PortForwardBean.java
@@ -27,6 +27,7 @@ import android.content.ContentValues;
*
*/
public class PortForwardBean {
+ /* Database fields */
private long id = -1;
private long hostId = -1;
private String nickname = null;
@@ -35,6 +36,7 @@ public class PortForwardBean {
private String destAddr = null;
private int destPort = -1;
+ /* Transient values */
private boolean enabled = false;
private Object identifier = null;
diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java
index b9dbcdf..d55ad5f 100644
--- a/src/org/connectbot/service/TerminalBridge.java
+++ b/src/org/connectbot/service/TerminalBridge.java
@@ -30,6 +30,7 @@ import java.util.List;
import org.connectbot.R;
import org.connectbot.TerminalView;
+import org.connectbot.bean.HostBean;
import org.connectbot.bean.PortForwardBean;
import org.connectbot.util.HostDatabase;
import org.connectbot.util.PubkeyDatabase;
@@ -106,11 +107,12 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
protected final TerminalManager manager;
- public final String nickname;
- protected final String username;
- public String postlogin = null;
- private boolean wantSession = true;
- private boolean compression = false;
+ public HostBean host;
+ //public final String nickname;
+ //protected final String username;
+ //public String postlogin = null;
+ //private boolean wantSession = true;
+ //private boolean compression = false;
public final Connection connection;
protected Session session;
@@ -137,6 +139,10 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
private boolean pubkeysExhausted = false;
+ private boolean authenticated = false;
+
+ private boolean sessionOpen = false;
+
private boolean forcedSize = false;
private int termWidth;
private int termHeight;
@@ -149,7 +155,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
KnownHosts hosts = manager.hostdb.getKnownHosts();
Boolean result;
- switch(hosts.verifyHostkey(hostname, serverHostKeyAlgorithm, serverHostKey)) {
+ String matchName = String.format("%s:%d", hostname, port);
+
+ switch(hosts.verifyHostkey(matchName, serverHostKeyAlgorithm, serverHostKey)) {
case KnownHosts.HOSTKEY_IS_OK:
return true;
@@ -162,7 +170,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if(result == null) return false;
if(result.booleanValue()) {
// save this key in known database
- manager.hostdb.saveKnownHost(hostname, serverHostKeyAlgorithm, serverHostKey);
+ manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey);
}
return result.booleanValue();
@@ -180,7 +188,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
if(result == null) return false;
if(result.booleanValue()) {
// save this key in known database
- manager.hostdb.saveKnownHost(hostname, serverHostKeyAlgorithm, serverHostKey);
+ manager.hostdb.saveKnownHost(hostname, port, serverHostKeyAlgorithm, serverHostKey);
}
return result.booleanValue();
}
@@ -198,17 +206,13 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
* launch thread to start SSH connection and handle any hostkey verification
* and password authentication.
*/
- public TerminalBridge(final TerminalManager manager, final String nickname, final String username, final String hostname, final int port) throws Exception {
+ public TerminalBridge(final TerminalManager manager, final HostBean host) throws Exception {
this.manager = manager;
- this.nickname = nickname;
- this.username = username;
+ this.host = host;
this.emulation = manager.getEmulation();
this.scrollback = manager.getScrollback();
- this.postlogin = manager.getPostLogin(nickname);
- this.wantSession = manager.getWantSession(nickname);
- this.compression = manager.getCompression(nickname);
// create prompt helper to relay password and hostkey requests up to gui
this.promptHelper = new PromptHelper(this);
@@ -251,14 +255,13 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
this.buffer.setCursorPosition(0, 0);
// TODO Change this when hosts are beans as well
- this.portForwards = manager.hostdb.getPortForwardsForHost(manager.hostdb.findHostByNickname(nickname));
+ this.portForwards = manager.hostdb.getPortForwardsForHost(host);
// prepare the ssh connection for opening
// we perform the actual connection later in startConnection()
- this.outputLine(String.format("Connecting to %s:%d", hostname, port));
- this.connection = new Connection(hostname, port);
+ this.outputLine(String.format("Connecting to %s:%d", host.getHostname(), host.getPort()));
+ this.connection = new Connection(host.getHostname(), host.getPort());
this.connection.addConnectionMonitor(this);
- this.connection.setCompression(compression);
}
public final static int AUTH_TRIES = 20;
@@ -357,7 +360,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
}
- return this.tryPublicKey(this.username, nickname, trileadKey);
+ return this.tryPublicKey(host.getUsername(), host.getNickname(), trileadKey);
}
@@ -371,7 +374,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
public void handleAuthentication() {
try {
- if (connection.authenticateWithNone(username)) {
+ if (connection.authenticateWithNone(host.getUsername())) {
finishConnection();
return;
}
@@ -382,11 +385,11 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
outputLine("Trying to authenticate");
try {
- long pubkeyId = manager.hostdb.getPubkeyId(nickname);
+ long pubkeyId = host.getPubkeyId();
if (!pubkeysExhausted &&
pubkeyId != HostDatabase.PUBKEYID_NEVER &&
- connection.isAuthMethodAvailable(username, AUTH_PUBLICKEY)) {
+ connection.isAuthMethodAvailable(host.getUsername(), AUTH_PUBLICKEY)) {
// if explicit pubkey defined for this host, then prompt for password as needed
// otherwise just try all in-memory keys held in terminalmanager
@@ -396,7 +399,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
outputLine("Attempting 'publickey' authentication with any in-memory SSH keys");
for(String nickname : manager.loadedPubkeys.keySet()) {
Object trileadKey = manager.loadedPubkeys.get(nickname);
- if(this.tryPublicKey(this.username, nickname, trileadKey)) {
+ if(this.tryPublicKey(host.getUsername(), nickname, trileadKey)) {
finishConnection();
break;
}
@@ -414,20 +417,20 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
pubkeysExhausted = true;
- } else if (connection.isAuthMethodAvailable(username, AUTH_PASSWORD)) {
+ } else if (connection.isAuthMethodAvailable(host.getUsername(), AUTH_PASSWORD)) {
outputLine("Attempting 'password' authentication");
String password = promptHelper.requestStringPrompt("Password");
- if(connection.authenticateWithPassword(username, password)) {
+ if(connection.authenticateWithPassword(host.getUsername(), password)) {
finishConnection();
} else {
outputLine("Authentication method 'password' failed");
}
- } else if(connection.isAuthMethodAvailable(username, AUTH_KEYBOARDINTERACTIVE)) {
+ } else if(connection.isAuthMethodAvailable(host.getUsername(), AUTH_KEYBOARDINTERACTIVE)) {
// this auth method will talk with us using InteractiveCallback interface
// it blocks until authentication finishes
outputLine("Attempting 'keyboard-interactive' authentication");
- if(connection.authenticateWithKeyboardInteractive(username, TerminalBridge.this)) {
+ if(connection.authenticateWithKeyboardInteractive(host.getUsername(), TerminalBridge.this)) {
finishConnection();
} else {
outputLine("Authentication method 'keyboard-interactive' failed");
@@ -482,9 +485,6 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}).start();
}
- private boolean authenticated = false;
- private boolean sessionOpen = false;
-
/**
* Internal method to request actual PTY terminal once we've finished
* authentication. If called before authenticated, it will just fail.
@@ -502,7 +502,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
}
}
- if (!wantSession) {
+ if (!host.getWantSession()) {
outputLine("Session will not be started due to host preference.");
return;
}
@@ -549,7 +549,9 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
setSessionOpen(true);
// finally send any post-login string, if requested
- injectString(postlogin);
+ byte[] postLogin = host.getPostLogin();
+ if (postLogin != null)
+ injectString(new String(postLogin));
} catch (IOException e1) {
Log.e(TAG, "Problem while trying to create PTY in finishConnection()", e1);
diff --git a/src/org/connectbot/service/TerminalManager.java b/src/org/connectbot/service/TerminalManager.java
index deeb0f2..78724f1 100644
--- a/src/org/connectbot/service/TerminalManager.java
+++ b/src/org/connectbot/service/TerminalManager.java
@@ -25,6 +25,7 @@ import java.util.LinkedList;
import java.util.List;
import org.connectbot.R;
+import org.connectbot.bean.HostBean;
import org.connectbot.util.HostDatabase;
import org.connectbot.util.PubkeyDatabase;
import org.connectbot.util.PubkeyUtils;
@@ -56,7 +57,7 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
public List<TerminalBridge> bridges = new LinkedList<TerminalBridge>();
public TerminalBridge defaultBridge = null;
- public List<String> disconnected = new LinkedList<String>();
+ public List<HostBean> disconnected = new LinkedList<HostBean>();
protected HashMap<String, Object> loadedPubkeys = new HashMap<String, Object>();
@@ -130,20 +131,19 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
/**
* Open a new SSH session using the given parameters.
*/
- public void openConnection(String nickname, String hostname, String username, int port) throws Exception {
+ public void openConnection(HostBean host) throws Exception {
// throw exception if terminal already open
- if(this.findBridge(nickname) != null) {
+ if (this.findBridge(host) != null) {
throw new Exception("Connection already open for that nickname");
}
- TerminalBridge bridge = new TerminalBridge(this, nickname, username, hostname, port);
+ TerminalBridge bridge = new TerminalBridge(this, host);
bridge.setOnDisconnectedListener(this);
bridge.startConnection();
this.bridges.add(bridge);
// also update database with new connected time
- this.touchHost(nickname);
-
+ this.touchHost(host);
}
public String getEmulation() {
@@ -162,18 +162,6 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
public boolean isSavingKeys() {
return prefs.getBoolean(this.pref_memkeys, true);
}
-
- public String getPostLogin(String nickname) {
- return hostdb.getPostLogin(nickname);
- }
-
- public boolean getWantSession(String nickname) {
- return hostdb.getWantSession(nickname);
- }
-
- public boolean getCompression(String nickname) {
- return hostdb.getCompression(nickname);
- }
public String getKeyMode() {
return prefs.getString(this.pref_keymode, getString(R.string.list_keymode_right)); // "Use right-side keys"
@@ -189,24 +177,32 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
String hostname = uri.getHost();
int port = uri.getPort();
- this.openConnection(nickname, hostname, username, port);
+ HostBean host = hostdb.findHost(nickname, username, hostname, port);
+
+ if (host == null) {
+ Log.d(TAG, String.format("Didn't find existing host (nickname=%s, username=%s, hostname=%s, port=%d)",
+ nickname, username, hostname, port));
+ host = new HostBean(nickname, username, hostname, port);
+ }
+
+ this.openConnection(host);
}
/**
* Update the last-connected value for the given nickname by passing through
* to {@link HostDatabase}.
*/
- protected void touchHost(String nickname) {
- hostdb.touchHost(nickname);
+ protected void touchHost(HostBean host) {
+ hostdb.touchHost(host);
}
/**
* Find the {@link TerminalBridge} with the given nickname.
*/
- public TerminalBridge findBridge(String nickname) {
+ public TerminalBridge findBridge(HostBean host) {
// find the first active bridge with given nickname
for(TerminalBridge bridge : bridges) {
- if(bridge.nickname.equals(nickname))
+ if (bridge.host.equals(host))
return bridge;
}
return null;
@@ -229,7 +225,7 @@ public class TerminalManager extends Service implements BridgeDisconnectedListen
public void onDisconnected(TerminalBridge bridge) {
// remove this bridge from our list
this.bridges.remove(bridge);
- this.disconnected.add(bridge.nickname);
+ this.disconnected.add(bridge.host);
// pass notification back up to gui
if(this.disconnectHandler != null)
diff --git a/src/org/connectbot/util/HostBinder.java b/src/org/connectbot/util/HostBinder.java
deleted file mode 100644
index 39439c7..0000000
--- a/src/org/connectbot/util/HostBinder.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- 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.util;
-
-import org.connectbot.R;
-import org.connectbot.service.TerminalManager;
-
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.SimpleCursorAdapter.ViewBinder;
-
-/**
- * Binder used to help interpret a HostDatabase cursor into a ListView for
- * display. Specifically, it controls the green "bulb" icon by checking against
- * TerminalManager for status, and shows the last-connected time in a
- * user-friendly format like "6 days ago."
- *
- * @author jsharkey
- */
-public class HostBinder implements ViewBinder {
-
- protected final TerminalManager manager;
- protected final ColorStateList red, green, blue;
- protected int COL_NICKNAME = -1;
-
- public HostBinder(TerminalManager manager, Resources res) {
- this.manager = manager;
- this.red = res.getColorStateList(R.color.red);
- this.green = res.getColorStateList(R.color.green);
- this.blue = res.getColorStateList(R.color.blue);
-
- }
-
- public final static int STATE_UNKNOWN = 1, STATE_CONNECTED = 2, STATE_DISCONNECTED = 3;
-
- /**
- * Check if we're connected to a terminal with the given nickname.
- */
- protected int getConnectedState(String nickname) {
- // always disconnected if we dont have backend service
- if(this.manager == null) return STATE_UNKNOWN;
- boolean connected = (this.manager.findBridge(nickname) != null);
- boolean disconnected = (this.manager.disconnected.contains(nickname));
- if(connected) return STATE_CONNECTED;
- if(disconnected) return STATE_DISCONNECTED;
- return STATE_UNKNOWN;
- }
-
- public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
-
- switch(view.getId()) {
- case android.R.id.icon:
- // set icon state based on status from backend service
- ImageView icon = (ImageView)view;
-
- if(COL_NICKNAME == -1)
- COL_NICKNAME = cursor.getColumnIndexOrThrow(HostDatabase.FIELD_HOST_NICKNAME);
-
- String nickname = cursor.getString(COL_NICKNAME);
- switch(this.getConnectedState(nickname)) {
- case STATE_UNKNOWN:
- icon.setImageState(new int[] { }, true);
- break;
- case STATE_CONNECTED:
- icon.setImageState(new int[] { android.R.attr.state_checked }, true);
- break;
- case STATE_DISCONNECTED:
- icon.setImageState(new int[] { android.R.attr.state_expanded }, true);
- break;
- }
- return true;
-
- case android.R.id.content:
- // set background color correctly
- String color = cursor.getString(columnIndex);
- TextView text1 = (TextView)view.findViewById(android.R.id.text1),
- text2 = (TextView)view.findViewById(android.R.id.text2);
-
- ColorStateList chosen = null;
- if(HostDatabase.COLOR_RED.equals(color)) chosen = this.red;
- if(HostDatabase.COLOR_GREEN.equals(color)) chosen = this.green;
- if(HostDatabase.COLOR_BLUE.equals(color)) chosen = this.blue;
-
- if(chosen != null) {
- // set color normally if not selected
- text1.setTextColor(chosen);
- text2.setTextColor(chosen);
- } else {
- // selected, so revert back to default black text
- text1.setTextAppearance(view.getContext(), android.R.attr.textAppearanceLarge);
- text2.setTextAppearance(view.getContext(), android.R.attr.textAppearanceSmall);
- }
- return true;
-
- case android.R.id.text2:
- // correctly set last-connected time and status
- long created = cursor.getLong(columnIndex);
- long now = System.currentTimeMillis() / 1000;
-
- String nice = "never";
- if(created > 0) {
- int minutes = (int)((now - created) / 60);
- nice = view.getContext().getString(R.string.bind_minutes, minutes);
- if(minutes >= 60) {
- int hours = (minutes / 60);
- nice = view.getContext().getString(R.string.bind_hours, hours);
- if(hours >= 24) {
- int days = (hours / 24);
- nice = view.getContext().getString(R.string.bind_days, days);
- }
- }
- }
-
- ((TextView)view).setText(nice);
- return true;
- }
-
- // otherwise fall through to other binding methods
- return false;
-
- }
-
-
-}
diff --git a/src/org/connectbot/util/HostDatabase.java b/src/org/connectbot/util/HostDatabase.java
index d935f69..978c9d7 100644
--- a/src/org/connectbot/util/HostDatabase.java
+++ b/src/org/connectbot/util/HostDatabase.java
@@ -21,6 +21,7 @@ package org.connectbot.util;
import java.util.LinkedList;
import java.util.List;
+import org.connectbot.bean.HostBean;
import org.connectbot.bean.PortForwardBean;
import com.trilead.ssh2.KnownHosts;
@@ -105,8 +106,8 @@ public class HostDatabase extends SQLiteOpenHelper {
// insert a few sample hosts, none of which probably connect
//this.createHost(db, "connectbot@bravo", "connectbot", "192.168.254.230", 22, COLOR_GRAY);
- this.createHost(db, "cron@server.example.com", "cron", "server.example.com", 22, COLOR_GRAY, PUBKEYID_ANY);
- this.createHost(db, "backup@example.net", "backup", "example.net", 22, COLOR_BLUE, PUBKEYID_ANY);
+ //this.createHost(db, "cron@server.example.com", "cron", "server.example.com", 22, COLOR_GRAY, PUBKEYID_ANY);
+ //this.createHost(db, "backup@example.net", "backup", "example.net", 22, COLOR_BLUE, PUBKEYID_ANY);
db.execSQL("CREATE TABLE " + TABLE_PORTFORWARDS
+ " (_id INTEGER PRIMARY KEY, "
@@ -154,196 +155,187 @@ public class HostDatabase extends SQLiteOpenHelper {
* Touch a specific host to update its "last connected" field.
* @param nickname Nickname field of host to update
*/
- public void touchHost(String nickname) {
-
+ public void touchHost(HostBean host) {
SQLiteDatabase db = this.getWritableDatabase();
long now = System.currentTimeMillis() / 1000;
ContentValues values = new ContentValues();
values.put(FIELD_HOST_LASTCONNECT, now);
- db.update(TABLE_HOSTS, values, FIELD_HOST_NICKNAME + " = ?", new String[] { nickname });
- db.close();
-
- }
-
- /**
- * Find a specific host ID
- * @param nickname Nickname field of host to find
- */
- public long findHostByNickname(String nickname) {
- SQLiteDatabase db = this.getReadableDatabase();
- long id = -1;
-
- Cursor c = db.query(TABLE_HOSTS, new String[] { "_id" },
- FIELD_HOST_NICKNAME + " = ?", new String[] { nickname },
- null, null, null);
-
- if (c != null && c.moveToFirst())
- id = c.getLong(0);
+ db.update(TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) });
- c.close();
db.close();
-
- return id;
}
/**
- * Find a host's nickname in the database by its ID.
- * @param hostId
- * @return the host's nickname
+ * Create a new host using the given parameters.
*/
- public String findNicknameById(long hostId) {
- SQLiteDatabase db = this.getReadableDatabase();
- String nickname = "unsaved host";
-
- Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_NICKNAME },
- "_id = ?", new String[] { String.valueOf(hostId) },
- null, null, null);
-
- if (c != null && c.moveToFirst())
- nickname = c.getString(0);
+ public HostBean saveHost(HostBean host) {
+ SQLiteDatabase db = this.getWritableDatabase();
- c.close();
+ long id = db.insert(TABLE_HOSTS, null, host.getValues());
db.close();
-
- return nickname;
- }
- /**
- * Create a new host using the given parameters, and return its new
- * <code>_id</code> value.
- */
- public long createHost(SQLiteDatabase db, String nickname, String username, String hostname, int port, String color, long pubkeyId) {
- // create and insert new host
-
- if(db == null) db = this.getWritableDatabase();
-
- ContentValues values = new ContentValues();
- values.put(FIELD_HOST_NICKNAME, nickname);
- values.put(FIELD_HOST_USERNAME, username);
- values.put(FIELD_HOST_HOSTNAME, hostname);
- values.put(FIELD_HOST_PORT, port);
- values.put(FIELD_HOST_LASTCONNECT, 0);
- values.put(FIELD_HOST_USEKEYS, Boolean.toString(true));
- if(color != null)
- values.put(FIELD_HOST_COLOR, color);
- values.put(FIELD_HOST_PUBKEYID, pubkeyId);
- values.put(FIELD_HOST_WANTSESSION, Boolean.toString(true));
-
- return db.insert(TABLE_HOSTS, null, values);
+ host.setId(id);
+ return host;
}
/**
* Delete a specific host by its <code>_id</code> value.
*/
- public void deleteHost(long id) {
+ public void deleteHost(HostBean host) {
+ if (host.getId() < 0)
+ return;
SQLiteDatabase db = this.getWritableDatabase();
- db.delete(TABLE_HOSTS, "_id = ?", new String[] { Long.toString(id) });
-
+ db.delete(TABLE_HOSTS, "_id = ?", new String[] { String.valueOf(host.getId()) });
+ db.close();
}
/**
* Return a cursor that contains information about all known hosts.
* @param sortColors If true, sort by color, otherwise sort by nickname.
*/
- public Cursor allHosts(boolean sortColors) {
-
+ public List<HostBean> getHosts(boolean sortColors) {
String sortField = sortColors ? FIELD_HOST_COLOR : FIELD_HOST_NICKNAME;
-
SQLiteDatabase db = this.getReadableDatabase();
- return db.query(TABLE_HOSTS, new String[] { "_id", FIELD_HOST_NICKNAME,
- FIELD_HOST_USERNAME, FIELD_HOST_HOSTNAME, FIELD_HOST_PORT,
- FIELD_HOST_LASTCONNECT, FIELD_HOST_COLOR },
- null, null, null, null, sortField + " ASC");
- }
-
- /**
- * Find the post-login command string for the given nickname.
- */
- public String getPostLogin(String nickname) {
- String result = null;
+ List<HostBean> hosts = new LinkedList<HostBean>();
- SQLiteDatabase db = this.getReadableDatabase();
- Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_POSTLOGIN },
- FIELD_HOST_NICKNAME + " = ?", new String[] { nickname }, null, null, null);
+ Cursor c = db.query(TABLE_HOSTS, null, null, null, null, null, sortField + " ASC");
+
+ 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),
+ COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT),
+ COL_LASTCONNECT = c.getColumnIndexOrThrow(FIELD_HOST_LASTCONNECT),
+ COL_COLOR = c.getColumnIndexOrThrow(FIELD_HOST_COLOR),
+ COL_USEKEYS = c.getColumnIndexOrThrow(FIELD_HOST_USEKEYS),
+ COL_POSTLOGIN = c.getColumnIndexOrThrow(FIELD_HOST_POSTLOGIN),
+ COL_PUBKEYID = c.getColumnIndexOrThrow(FIELD_HOST_PUBKEYID),
+ COL_WANTSESSION = c.getColumnIndexOrThrow(FIELD_HOST_WANTSESSION),
+ COL_COMPRESSION = c.getColumnIndexOrThrow(FIELD_HOST_COMPRESSION);
- if (c == null || !c.moveToFirst()) {
- result = null;
- } else {
- result = c.getString(c.getColumnIndexOrThrow(FIELD_HOST_POSTLOGIN));
+ while (c.moveToNext()) {
+ HostBean host = new HostBean();
+
+ host.setId(c.getLong(COL_ID));
+ host.setNickname(c.getString(COL_NICKNAME));
+ host.setUsername(c.getString(COL_USERNAME));
+ host.setHostname(c.getString(COL_HOSTNAME));
+ host.setPort(c.getInt(COL_PORT));
+ host.setLastConnect(c.getLong(COL_LASTCONNECT));
+ host.setColor(c.getString(COL_COLOR));
+ host.setUseKeys(Boolean.valueOf(c.getString(COL_USEKEYS)));
+ host.setPostLogin(c.getBlob(COL_POSTLOGIN));
+ host.setPubkeyId(c.getLong(COL_PUBKEYID));
+ host.setWantSession(Boolean.valueOf(c.getString(COL_WANTSESSION)));
+ host.setCompression(Boolean.valueOf(c.getString(COL_COMPRESSION)));
+
+ hosts.add(host);
}
c.close();
db.close();
-
- return result;
+
+ return hosts;
}
-
+
/**
- * Check whether a host should have a shell session started.
- * @param nickname Nick name of host to check
- * @return true if host should have a shell session started
+ * @param nickname
+ * @param username
+ * @param hostname
+ * @param port
+ * @return
*/
- public boolean getWantSession(String nickname) {
- Boolean result = true;
-
+ public HostBean findHost(String nickname, String username, String hostname,
+ int port) {
SQLiteDatabase db = this.getReadableDatabase();
- Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_WANTSESSION },
- FIELD_HOST_NICKNAME + " = ?", new String[] { nickname }, null, null, null);
- if(c == null || !c.moveToFirst()) {
- result = true;
- } else {
- result = Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_WANTSESSION)));
+
+ Cursor c = db.query(TABLE_HOSTS, null,
+ FIELD_HOST_NICKNAME + " = ? AND " +
+ FIELD_HOST_USERNAME + " = ? AND " +
+ FIELD_HOST_HOSTNAME + " = ? AND " +
+ FIELD_HOST_PORT + " = ?",
+ new String[] { nickname, username, hostname, String.valueOf(port) },
+ null, null, null);
+
+ HostBean host = null;
+
+ if (c != null && c.moveToFirst()) {
+ host = createHostBean(c);
}
c.close();
db.close();
- return result;
+ return host;
}
/**
- * Check whether a host should have compression enabled.
- * @param nickname Nick name of host to check
- * @return true if host should have compression enabled
+ * @param hostId
+ * @return
*/
- public boolean getCompression(String nickname) {
- Boolean result = false;
-
+ public HostBean findHostById(long hostId) {
SQLiteDatabase db = this.getReadableDatabase();
- Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_COMPRESSION },
- FIELD_HOST_NICKNAME + " = ?", new String[] { nickname }, null, null, null);
- if (c != null && c.moveToFirst())
- result = Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_COMPRESSION)));
+ Cursor c = db.query(TABLE_HOSTS, null,
+ "_id = ?", new String[] { String.valueOf(hostId) },
+ null, null, null);
+
+ HostBean host = null;
+
+ if (c != null && c.moveToFirst()) {
+ host = createHostBean(c);
+ }
c.close();
db.close();
- return result;
+ return host;
+ }
+
+ private HostBean createHostBean(Cursor c) {
+ HostBean host = new HostBean();
+
+ host.setId(c.getLong(c.getColumnIndexOrThrow("_id")));
+ host.setNickname(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_NICKNAME)));
+ host.setUsername(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_USERNAME)));
+ host.setHostname(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME)));
+ host.setPort(c.getInt(c.getColumnIndexOrThrow(FIELD_HOST_PORT)));
+ host.setLastConnect(c.getLong(c.getColumnIndexOrThrow(FIELD_HOST_LASTCONNECT)));
+ host.setColor(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_COLOR)));
+ host.setUseKeys(Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_USEKEYS))));
+ host.setPostLogin(c.getBlob(c.getColumnIndexOrThrow(FIELD_HOST_POSTLOGIN)));
+ host.setPubkeyId(c.getLong(c.getColumnIndexOrThrow(FIELD_HOST_PUBKEYID)));
+ host.setWantSession(Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_WANTSESSION))));
+ host.setCompression(Boolean.valueOf(c.getString(c.getColumnIndexOrThrow(FIELD_HOST_COMPRESSION))));
+
+ return host;
}
/**
* Record the given hostkey into database under this nickname.
* @param hostname
+ * @param port
* @param hostkeyalgo
* @param hostkey
*/
- public void saveKnownHost(String hostname, String hostkeyalgo, byte[] hostkey) {
-
+ public void saveKnownHost(String hostname, int port, String hostkeyalgo, byte[] hostkey) {
SQLiteDatabase db = this.getReadableDatabase();
ContentValues values = new ContentValues();
values.put(FIELD_HOST_HOSTKEYALGO, hostkeyalgo);
values.put(FIELD_HOST_HOSTKEY, hostkey);
- db.update(TABLE_HOSTS, values, FIELD_HOST_HOSTNAME + " = ?", new String[] { hostname });
+ db.update(TABLE_HOSTS, values,
+ FIELD_HOST_HOSTNAME + " = ? AND " + FIELD_HOST_PORT + " = ?",
+ new String[] { hostname, String.valueOf(port) });
Log.d(TAG, String.format("Finished saving hostkey information for '%s'", hostname));
+ db.close();
}
/**
@@ -355,66 +347,38 @@ public class HostDatabase extends SQLiteOpenHelper {
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_HOSTNAME,
- FIELD_HOST_HOSTKEYALGO, FIELD_HOST_HOSTKEY }, null, null, null,
- null, null);
- if(c == null) return null;
-
- int COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME),
- COL_HOSTKEYALGO = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEYALGO),
- COL_HOSTKEY = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEY);
-
- while(c.moveToNext()) {
- String hostname = c.getString(COL_HOSTNAME),
- hostkeyalgo = c.getString(COL_HOSTKEYALGO);
- byte[] hostkey = c.getBlob(COL_HOSTKEY);
-
- if(hostkeyalgo == null || hostkeyalgo.length() == 0) continue;
- if(hostkey == null || hostkey.length == 0) continue;
+ FIELD_HOST_PORT, FIELD_HOST_HOSTKEYALGO, FIELD_HOST_HOSTKEY },
+ null, null, null, null, null);
+
+ if (c != null) {
+
+ int COL_HOSTNAME = c.getColumnIndexOrThrow(FIELD_HOST_HOSTNAME),
+ COL_PORT = c.getColumnIndexOrThrow(FIELD_HOST_PORT),
+ COL_HOSTKEYALGO = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEYALGO),
+ COL_HOSTKEY = c.getColumnIndexOrThrow(FIELD_HOST_HOSTKEY);
- try {
- known.addHostkey(new String[] { hostname }, hostkeyalgo, hostkey);
- } catch(Exception e) {
- Log.e(TAG, "Problem while adding a known host from database", e);
+ while(c.moveToNext()) {
+ String hostname = c.getString(COL_HOSTNAME),
+ hostkeyalgo = c.getString(COL_HOSTKEYALGO);
+ int port = c.getInt(COL_PORT);
+ byte[] hostkey = c.getBlob(COL_HOSTKEY);
+
+ if(hostkeyalgo == null || hostkeyalgo.length() == 0) continue;
+ if(hostkey == null || hostkey.length == 0) continue;
+
+ try {
+ known.addHostkey(new String[] { String.format("%s:%d", hostname, port) }, hostkeyalgo, hostkey);
+ } catch(Exception e) {
+ Log.e(TAG, "Problem while adding a known host from database", e);
+ }
+
}
-
}
- return known;
- }
-
- /**
- * Find the pubkey to use for a given nickname.
- * @param nickname of host
- * @return pubkey ID in database
- */
- public long getPubkeyId(String nickname) {
- long result = PUBKEYID_ANY;
-
- SQLiteDatabase db = this.getReadableDatabase();
- Cursor c = db.query(TABLE_HOSTS, new String[] { FIELD_HOST_PUBKEYID },
- FIELD_HOST_NICKNAME + " = ?", new String[] { nickname }, null, null, null);
-
- if (c != null && c.moveToFirst())
- result = c.getLong(0);
-
- return result;
- }
-
- /**
- * Set which public key to use for a particular host.
- * @param hostId host ID in database
- * @param pubkeyId public key ID in databae
- */
- public void setPubkeyId(long hostId, long pubkeyId) {
- SQLiteDatabase db = this.getWritableDatabase();
-
- ContentValues values = new ContentValues();
- values.put(FIELD_HOST_PUBKEYID, pubkeyId);
-
- db.update(TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(hostId) });
+ c.close();
db.close();
-
- Log.d(TAG, String.format("Updated host id %d to use pubkey id %d", hostId, pubkeyId));
+
+ return known;
}
/**
@@ -441,23 +405,23 @@ public class HostDatabase extends SQLiteOpenHelper {
/**
* Returns a list of all the port forwards associated with a particular host ID.
- * @param hostId ID of host
+ * @param host the host for which we want the port forward list
* @return port forwards associated with host ID
*/
- public List<PortForwardBean> getPortForwardsForHost(long hostId) {
+ public List<PortForwardBean> getPortForwardsForHost(HostBean host) {
SQLiteDatabase db = this.getReadableDatabase();
List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>();
Cursor c = db.query(TABLE_PORTFORWARDS, new String[] {
"_id", FIELD_PORTFORWARD_NICKNAME, FIELD_PORTFORWARD_TYPE, FIELD_PORTFORWARD_SOURCEPORT,
FIELD_PORTFORWARD_DESTADDR, FIELD_PORTFORWARD_DESTPORT },
- FIELD_PORTFORWARD_HOSTID + " = ?", new String[] { String.valueOf(hostId) },
+ FIELD_PORTFORWARD_HOSTID + " = ?", new String[] { String.valueOf(host.getId()) },
null, null, null);
while (c.moveToNext()) {
PortForwardBean pfb = new PortForwardBean(
c.getInt(0),
- hostId,
+ host.getId(),
c.getString(1),
c.getString(2),
c.getInt(3),
@@ -472,7 +436,6 @@ public class HostDatabase extends SQLiteOpenHelper {
return portForwards;
}
-
/**
* Update the parameters of a port forward in the database.
* @param pfb {@link PortForwardBean} to save