aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2008-11-07 11:30:23 +0000
committerKenny Root <kenny@the-b.org>2008-11-07 11:30:23 +0000
commit706a57a55373b68604acc9a54ddcf5fd8f47d9d2 (patch)
tree3ab7e2c99284bb8a9f3d1348ae136739ea4e0034 /src
parent1a6ca4d897fe789a589e165e49281f1fb27785ca (diff)
downloadconnectbot-706a57a55373b68604acc9a54ddcf5fd8f47d9d2.tar.gz
connectbot-706a57a55373b68604acc9a54ddcf5fd8f47d9d2.tar.bz2
connectbot-706a57a55373b68604acc9a54ddcf5fd8f47d9d2.zip
* Add port forward list activity so port forwards can be saved in database
* Start saved port forwards when host is connected * Add titles to activities to distinguish where user is
Diffstat (limited to 'src')
-rw-r--r--src/org/connectbot/ConsoleActivity.java73
-rw-r--r--src/org/connectbot/HostEditorActivity.java10
-rw-r--r--src/org/connectbot/HostListActivity.java15
-rw-r--r--src/org/connectbot/PortForwardListActivity.java258
-rw-r--r--src/org/connectbot/PubkeyListActivity.java74
-rw-r--r--src/org/connectbot/bean/PortForwardBean.java235
-rw-r--r--src/org/connectbot/service/TerminalBridge.java144
-rw-r--r--src/org/connectbot/util/HostDatabase.java166
8 files changed, 878 insertions, 97 deletions
diff --git a/src/org/connectbot/ConsoleActivity.java b/src/org/connectbot/ConsoleActivity.java
index a1523cc..ee24993 100644
--- a/src/org/connectbot/ConsoleActivity.java
+++ b/src/org/connectbot/ConsoleActivity.java
@@ -18,9 +18,11 @@
package org.connectbot;
+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;
@@ -485,7 +487,6 @@ public class ConsoleActivity extends Activity {
if(copySource == null) return false;
float row = event.getY() / copySource.bridge.charHeight;
float col = event.getX() / copySource.bridge.charWidth;
- Log.d(TAG, String.format("X = %f, Y = %f, row = %f, col = %f", event.getX(), event.getY(), row, col));
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
@@ -595,7 +596,7 @@ public class ConsoleActivity extends Activity {
}
- protected MenuItem disconnect, copy, paste, tunnel, resize;
+ protected MenuItem disconnect, copy, paste, portForward, resize;
protected boolean copying = false;
protected TerminalView copySource = null;
@@ -658,29 +659,31 @@ public class ConsoleActivity extends Activity {
});
- tunnel = menu.add(R.string.console_menu_tunnel);
- tunnel.setIcon(android.R.drawable.ic_menu_manage);
- tunnel.setEnabled(activeTerminal && authenticated);
- tunnel.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ portForward = menu.add(R.string.console_menu_portforwards);
+ portForward.setIcon(android.R.drawable.ic_menu_manage);
+ portForward.setEnabled(activeTerminal && authenticated);
+ portForward.setOnMenuItemClickListener(new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
- // show dialog to create tunnel for this host
+ // show dialog to create portForward for this host
final TerminalView terminal = (TerminalView)view;
// build dialog to prompt user about updating
- final View tunnelView = inflater.inflate(R.layout.dia_tunnel, null, false);
- ((RadioButton)tunnelView.findViewById(R.id.tunnel_local)).setChecked(true);
+ final View portForwardView = inflater.inflate(R.layout.dia_portforward, null, false);
+ ((RadioButton)portForwardView.findViewById(R.id.portforward_local)).setChecked(true);
new AlertDialog.Builder(ConsoleActivity.this)
- .setView(tunnelView)
- .setPositiveButton("Create tunnel", new DialogInterface.OnClickListener() {
+ .setView(portForwardView)
+ .setPositiveButton(R.string.portforward_pos, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- String type = ((RadioButton)tunnelView.findViewById(R.id.tunnel_local)).isChecked() ? TUNNEL_LOCAL : TUNNEL_REMOTE;
- String source = ((TextView)tunnelView.findViewById(R.id.tunnel_source)).getText().toString();
- String dest = ((TextView)tunnelView.findViewById(R.id.tunnel_destination)).getText().toString();
+ String nickname = ((TextView)portForwardView.findViewById(R.id.nickname)).getText().toString();
+ String type = ((RadioButton)portForwardView.findViewById(R.id.portforward_local)).isChecked()
+ ? HostDatabase.PORTFORWARD_LOCAL : HostDatabase.PORTFORWARD_REMOTE;
+ String source = ((TextView)portForwardView.findViewById(R.id.portforward_source)).getText().toString();
+ String dest = ((TextView)portForwardView.findViewById(R.id.portforward_destination)).getText().toString();
- createTunnel(terminal, type, source, dest);
+ createPortForward(terminal, nickname, type, source, dest);
}
})
- .setNegativeButton("Cancel", null).create().show();
+ .setNegativeButton(R.string.portforward_neg, null).create().show();
return true;
}
@@ -703,7 +706,7 @@ public class ConsoleActivity extends Activity {
terminal.forceSize(width, height);
}
- }).setNegativeButton(R.string.button_cancel, null).create().show();
+ }).setNegativeButton(android.R.string.cancel, null).create().show();
return true;
}
@@ -713,34 +716,24 @@ public class ConsoleActivity extends Activity {
}
- public final static String EXTRA_TYPE = "type", EXTRA_SOURCE = "source", EXTRA_DEST = "dest", EXTRA_SILENT = "silent";
- public final static String TUNNEL_LOCAL = "local", TUNNEL_REMOTE = "remote";
-
- protected void createTunnel(TerminalView target, String type, String source, String dest) {
- String summary = null;
+ protected void createPortForward(TerminalView target, String nickname, String type, String source, String dest) {
+ String summary = getString(R.string.portforward_problem);
try {
- boolean local = TUNNEL_LOCAL.equals(type);
- int sourcePort = Integer.parseInt(source);
- String[] destSplit = dest.split(":");
- String destHost = destSplit[0];
- int destPort = Integer.parseInt(destSplit[1]);
-
- if(local) {
- target.bridge.connection.createLocalPortForwarder(sourcePort, destHost, destPort);
- summary = getString(R.string.tunnel_done_local, sourcePort, destHost, destPort);
- } else {
- target.bridge.connection.requestRemotePortForwarding("", sourcePort, destHost, destPort);
- summary = getString(R.string.tunnel_done_remote, sourcePort, destHost, destPort);
+ HostDatabase hostdb = new HostDatabase(this);
+ long hostId = hostdb.findHostByNickname(target.bridge.nickname);
+
+ PortForwardBean pfb = new PortForwardBean(hostId, nickname, type, source, dest);
+
+ target.bridge.addPortForward(pfb);
+ if (target.bridge.enablePortForward(pfb)) {
+ summary = getString(R.string.portforward_done);
}
} catch(Exception e) {
- Log.e(TAG, "Problem trying to create tunnel", e);
- summary = getString(R.string.tunnel_problem);
+ Log.e(TAG, "Problem trying to create portForward", e);
}
- Toast.makeText(ConsoleActivity.this, summary, Toast.LENGTH_LONG).show();
-
+ Toast.makeText(ConsoleActivity.this, summary, Toast.LENGTH_LONG).show();
}
-
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
@@ -755,7 +748,7 @@ public class ConsoleActivity extends Activity {
disconnect.setEnabled(activeTerminal);
copy.setEnabled(activeTerminal && authenticated);
paste.setEnabled(clipboard.hasText() && activeTerminal && authenticated);
- tunnel.setEnabled(activeTerminal && authenticated);
+ portForward.setEnabled(activeTerminal && authenticated);
resize.setEnabled(activeTerminal && authenticated);
return true;
diff --git a/src/org/connectbot/HostEditorActivity.java b/src/org/connectbot/HostEditorActivity.java
index daa81a0..3c5367d 100644
--- a/src/org/connectbot/HostEditorActivity.java
+++ b/src/org/connectbot/HostEditorActivity.java
@@ -46,12 +46,12 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
public class CursorPreferenceHack implements SharedPreferences {
protected final String table;
- protected final int id;
+ protected final long id;
protected Map<String, String> values = new HashMap<String, String>();
// protected Map<String, String> pubkeys = new HashMap<String, String>();
- public CursorPreferenceHack(String table, int id) {
+ public CursorPreferenceHack(String table, long id) {
this.table = table;
this.id = id;
@@ -65,7 +65,7 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
SQLiteDatabase db = hostdb.getReadableDatabase();
Cursor cursor = db.query(table, null, "_id = ?",
- new String[] { Integer.toString(id) }, null, null, null);
+ new String[] { String.valueOf(id) }, null, null, null);
cursor.moveToFirst();
for(int i = 0; i < cursor.getColumnCount(); i++) {
@@ -112,7 +112,7 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
public boolean commit() {
//Log.d(this.getClass().toString(), "commit() changes back to database");
SQLiteDatabase db = hostdb.getWritableDatabase();
- db.update(table, update, "_id = ?", new String[] { Integer.toString(id) });
+ db.update(table, update, "_id = ?", new String[] { String.valueOf(id) });
db.close();
// make sure we refresh the parent cached values
@@ -217,7 +217,7 @@ public class HostEditorActivity extends PreferenceActivity implements OnSharedPr
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- int id = this.getIntent().getIntExtra(Intent.EXTRA_TITLE, -1);
+ long id = this.getIntent().getLongExtra(Intent.EXTRA_TITLE, -1);
// TODO: we could pass through a specific ContentProvider uri here
//this.getPreferenceManager().setSharedPreferencesName(uri);
diff --git a/src/org/connectbot/HostListActivity.java b/src/org/connectbot/HostListActivity.java
index 429d4e0..f931111 100644
--- a/src/org/connectbot/HostListActivity.java
+++ b/src/org/connectbot/HostListActivity.java
@@ -160,6 +160,9 @@ public class HostListActivity extends ListActivity {
super.onCreate(icicle);
setContentView(R.layout.act_hostlist);
+ this.setTitle(String.format("%s: %s",
+ getResources().getText(R.string.app_name),
+ getResources().getText(R.string.title_hosts_list)));
// check for eula agreement
this.prefs = PreferenceManager.getDefaultSharedPreferences(this);
@@ -380,7 +383,7 @@ public class HostListActivity extends ListActivity {
final String nickname = cursor.getString(COL_NICKNAME);
menu.setHeaderTitle(nickname);
- final int id = cursor.getInt(COL_ID);
+ final long id = cursor.getLong(COL_ID);
// edit, disconnect, delete
MenuItem connect = menu.add(R.string.list_host_disconnect);
@@ -403,6 +406,16 @@ public class HostListActivity extends ListActivity {
return true;
}
});
+
+ MenuItem portForwards = menu.add(R.string.list_host_portforwards);
+ portForwards.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ Intent intent = new Intent(HostListActivity.this, PortForwardListActivity.class);
+ intent.putExtra(Intent.EXTRA_TITLE, id);
+ HostListActivity.this.startActivityForResult(intent, REQUEST_EDIT);
+ return true;
+ }
+ });
MenuItem delete = menu.add(R.string.list_host_delete);
delete.setOnMenuItemClickListener(new OnMenuItemClickListener() {
diff --git a/src/org/connectbot/PortForwardListActivity.java b/src/org/connectbot/PortForwardListActivity.java
new file mode 100644
index 0000000..3bee861
--- /dev/null
+++ b/src/org/connectbot/PortForwardListActivity.java
@@ -0,0 +1,258 @@
+/*
+ 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;
+
+import java.util.List;
+
+import org.connectbot.bean.PortForwardBean;
+import org.connectbot.util.HostDatabase;
+
+import android.app.AlertDialog;
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.ContextMenu;
+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.RadioButton;
+import android.widget.TextView;
+
+/**
+ * List all portForwards for a particular host and provide a way for users to add more portForwards,
+ * edit existing portForwards, and delete portForwards.
+ *
+ * @author Kenny Root
+ */
+public class PortForwardListActivity extends ListActivity {
+ public final static String TAG = PortForwardListActivity.class.toString();
+
+ protected HostDatabase hostdb;
+
+ protected Cursor hosts;
+ protected List<PortForwardBean> portForwards;
+
+ protected LayoutInflater inflater = null;
+
+ private long hostId;
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ if(this.hostdb == null)
+ this.hostdb = new HostDatabase(this);
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+
+ if(this.hostdb != null) {
+ this.hostdb.close();
+ this.hostdb = null;
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ this.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);
+
+ this.setTitle(String.format("%s: %s (%s)",
+ getResources().getText(R.string.app_name),
+ getResources().getText(R.string.title_port_forwards_list),
+ hostdb.findNicknameById(hostId)));
+
+ this.updateList();
+
+ this.registerForContextMenu(this.getListView());
+
+ this.inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ MenuItem add = menu.add(R.string.portforward_menu_add);
+ add.setIcon(android.R.drawable.ic_menu_add);
+ add.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ // build dialog to prompt user about updating
+ final View portForwardView = inflater.inflate(R.layout.dia_portforward, null, false);
+ ((RadioButton)portForwardView.findViewById(R.id.portforward_local)).setChecked(true);
+ new AlertDialog.Builder(PortForwardListActivity.this)
+ .setView(portForwardView)
+ .setPositiveButton(R.string.portforward_pos, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ try {
+ final EditText nicknameEdit = (EditText) portForwardView.findViewById(R.id.nickname);
+ final EditText sourcePortEdit = (EditText) portForwardView.findViewById(R.id.portforward_source);
+ final EditText destEdit = (EditText) portForwardView.findViewById(R.id.portforward_destination);
+
+ String type = ((RadioButton)portForwardView.findViewById(R.id.portforward_local)).isChecked()
+ ? HostDatabase.PORTFORWARD_LOCAL : HostDatabase.PORTFORWARD_REMOTE;
+
+ PortForwardBean pfb = new PortForwardBean(hostId,
+ nicknameEdit.getText().toString(), type,
+ sourcePortEdit.getText().toString(),
+ destEdit.getText().toString());
+
+ if (!hostdb.savePortForward(pfb))
+ throw new Exception("Could not save port forward");
+
+ updateHandler.sendEmptyMessage(-1);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not update port forward", e);
+ // TODO Show failure dialog.
+ }
+ }
+ })
+ .setNegativeButton(R.string.portforward_neg, null).create().show();
+
+ return true;
+ }
+ });
+
+ return true;
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ // Create menu to handle deleting and editing port forward
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ final PortForwardBean pfb = (PortForwardBean) this.getListView().getItemAtPosition(info.position);
+
+ menu.setHeaderTitle(pfb.getNickname());
+
+ MenuItem edit = menu.add(R.string.portforward_edit);
+ edit.setOnMenuItemClickListener(new OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ final View editTunnelView = inflater.inflate(R.layout.dia_portforward, null, false);
+
+ final RadioButton portForwardLocal = (RadioButton) editTunnelView.findViewById(R.id.portforward_local);
+ if (HostDatabase.PORTFORWARD_LOCAL.equals(pfb.getType())) {
+ portForwardLocal.setChecked(true);
+ } else { // if (HostDatabase.PORTFORWARD_REMOTE.equals(type)) {
+ ((RadioButton) editTunnelView.findViewById(R.id.portforward_remote)).setChecked(true);
+ }
+
+ final EditText nicknameEdit = (EditText) editTunnelView.findViewById(R.id.nickname);
+ nicknameEdit.setText(pfb.getNickname());
+
+ final EditText sourcePortEdit = (EditText) editTunnelView.findViewById(R.id.portforward_source);
+ sourcePortEdit.setText(String.valueOf(pfb.getSourcePort()));
+
+ final EditText destEdit = (EditText) editTunnelView.findViewById(R.id.portforward_destination);
+ destEdit.setText(String.format("%s:%d", pfb.getDestAddr(), pfb.getDestPort()));
+
+ new AlertDialog.Builder(PortForwardListActivity.this)
+ .setView(editTunnelView)
+ .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ try {
+ pfb.setNickname(nicknameEdit.getText().toString());
+
+ if (portForwardLocal.isChecked())
+ pfb.setType(HostDatabase.PORTFORWARD_LOCAL);
+ else
+ pfb.setType(HostDatabase.PORTFORWARD_REMOTE);
+
+ pfb.setSourcePort(Integer.parseInt(sourcePortEdit.getText().toString()));
+ pfb.setDest(destEdit.getText().toString());
+
+ if (!hostdb.savePortForward(pfb))
+ throw new Exception("Could not save port forward");
+
+ updateHandler.sendEmptyMessage(-1);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not update port forward", e);
+ // TODO Show failure dialog.
+ }
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null).create().show();
+
+ return true;
+ }
+ });
+ }
+
+ public Handler updateHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ PortForwardListActivity.this.updateList();
+ }
+ };
+
+ protected void updateList() {
+ if (this.hostdb == null) return;
+
+ this.portForwards = this.hostdb.getPortForwardsForHost(hostId);
+
+ PortForwardAdapter adapter = new PortForwardAdapter(this, this.portForwards);
+ this.setListAdapter(adapter);
+
+ //this.startManagingCursor(portForwards);
+ }
+
+ class PortForwardAdapter extends ArrayAdapter<PortForwardBean> {
+ private List<PortForwardBean> portForwards;
+
+ public PortForwardAdapter(Context context, List<PortForwardBean> portForwards) {
+ super(context, R.layout.item_portforward, portForwards);
+
+ this.portForwards = portForwards;
+ }
+
+ 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);
+
+ PortForwardBean pfb = portForwards.get(position);
+ nickname.setText(pfb.getNickname());
+ caption.setText(pfb.getDescription());
+
+ return view;
+ }
+ }
+
+}
diff --git a/src/org/connectbot/PubkeyListActivity.java b/src/org/connectbot/PubkeyListActivity.java
index 24dbdcf..7d0d590 100644
--- a/src/org/connectbot/PubkeyListActivity.java
+++ b/src/org/connectbot/PubkeyListActivity.java
@@ -68,6 +68,12 @@ import android.widget.SimpleCursorAdapter.ViewBinder;
import com.trilead.ssh2.crypto.PEMDecoder;
import com.trilead.ssh2.crypto.PEMStructure;
+/**
+ * List public keys in database by nickname and describe their properties. Allow users to import,
+ * generate, rename, and delete key pairs.
+ *
+ * @author Kenny Root
+ */
public class PubkeyListActivity extends ListActivity implements EventListener {
public final static String TAG = PubkeyListActivity.class.toString();
@@ -123,6 +129,10 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
super.onCreate(icicle);
setContentView(R.layout.act_pubkeylist);
+ this.setTitle(String.format("%s: %s",
+ getResources().getText(R.string.app_name),
+ getResources().getText(R.string.title_pubkey_list)));
+
// connect with hosts database and populate list
this.pubkeydb = new PubkeyDatabase(this);
@@ -327,7 +337,7 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
// TODO: option load/unload key from in-memory list
// prompt for password as needed for passworded keys
- final int id = cursor.getInt(COL_ID);
+ 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);
@@ -388,39 +398,39 @@ public class PubkeyListActivity extends ListActivity implements EventListener {
((TableRow)changePasswordView.findViewById(R.id.old_password_prompt))
.setVisibility(encrypted != 0 ? View.VISIBLE : View.GONE);
new AlertDialog.Builder(PubkeyListActivity.this)
- .setView(changePasswordView)
- .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- String oldPassword = ((EditText)changePasswordView.findViewById(R.id.old_password)).getText().toString();
- String password1 = ((EditText)changePasswordView.findViewById(R.id.password1)).getText().toString();
- String password2 = ((EditText)changePasswordView.findViewById(R.id.password2)).getText().toString();
-
- if (!password1.equals(password2)) {
- new AlertDialog.Builder(PubkeyListActivity.this)
- .setMessage(R.string.alert_passwords_do_not_match_msg)
- .setPositiveButton(android.R.string.ok, null)
- .create().show();
- return;
- }
-
- try {
- if (!pubkeydb.changePassword(id, oldPassword, password1))
+ .setView(changePasswordView)
+ .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ String oldPassword = ((EditText)changePasswordView.findViewById(R.id.old_password)).getText().toString();
+ String password1 = ((EditText)changePasswordView.findViewById(R.id.password1)).getText().toString();
+ String password2 = ((EditText)changePasswordView.findViewById(R.id.password2)).getText().toString();
+
+ if (!password1.equals(password2)) {
new AlertDialog.Builder(PubkeyListActivity.this)
- .setMessage(R.string.alert_wrong_password_msg)
- .setPositiveButton(android.R.string.ok, null)
- .create().show();
- else
- updateHandler.sendEmptyMessage(-1);
- } catch (Exception e) {
- Log.e(TAG, "Could not change private key password", e);
- new AlertDialog.Builder(PubkeyListActivity.this)
- .setMessage(R.string.alert_key_corrupted_msg)
- .setPositiveButton(android.R.string.ok, null)
- .create().show();
+ .setMessage(R.string.alert_passwords_do_not_match_msg)
+ .setPositiveButton(android.R.string.ok, null)
+ .create().show();
+ return;
+ }
+
+ try {
+ if (!pubkeydb.changePassword(id, oldPassword, password1))
+ new AlertDialog.Builder(PubkeyListActivity.this)
+ .setMessage(R.string.alert_wrong_password_msg)
+ .setPositiveButton(android.R.string.ok, null)
+ .create().show();
+ else
+ updateHandler.sendEmptyMessage(-1);
+ } catch (Exception e) {
+ Log.e(TAG, "Could not change private key password", e);
+ new AlertDialog.Builder(PubkeyListActivity.this)
+ .setMessage(R.string.alert_key_corrupted_msg)
+ .setPositiveButton(android.R.string.ok, null)
+ .create().show();
+ }
}
- }
- })
- .setNegativeButton(android.R.string.cancel, null).create().show();
+ })
+ .setNegativeButton(android.R.string.cancel, null).create().show();
return true;
}
diff --git a/src/org/connectbot/bean/PortForwardBean.java b/src/org/connectbot/bean/PortForwardBean.java
new file mode 100644
index 0000000..f5fd7ac
--- /dev/null
+++ b/src/org/connectbot/bean/PortForwardBean.java
@@ -0,0 +1,235 @@
+/*
+ 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 Root
+ *
+ */
+public class PortForwardBean {
+ private long id = -1;
+ private long hostId = -1;
+ private String nickname = null;
+ private String type = null;
+ private int sourcePort = -1;
+ private String destAddr = null;
+ private int destPort = -1;
+
+ private boolean enabled = false;
+ private Object identifier = null;
+
+ /**
+ * @param id database ID of port forward
+ * @param nickname Nickname to use to identify port forward
+ * @param type One of the port forward types from {@link HostDatabase}
+ * @param sourcePort Source port number
+ * @param destAddr Destination hostname or IP address
+ * @param destPort Destination port number
+ */
+ public PortForwardBean(long id, long hostId, String nickname, String type, int sourcePort, String destAddr, int destPort) {
+ this.id = id;
+ this.hostId = hostId;
+ this.nickname = nickname;
+ this.type = type;
+ this.sourcePort = sourcePort;
+ this.destAddr = destAddr;
+ this.destPort = destPort;
+ }
+
+ /**
+ *
+ */
+ public PortForwardBean(long hostId) {
+ this.hostId = hostId;
+ }
+
+ /**
+ * @param type One of the port forward types from {@link HostDatabase}
+ * @param source Source port number
+ * @param dest Destination is "host:port" format
+ */
+ public PortForwardBean(long hostId, String nickname, String type, String source, String dest) {
+ this.hostId = hostId;
+ this.nickname = nickname;
+ this.type = type;
+ this.sourcePort = Integer.parseInt(source);
+
+ this.setDest(dest);
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the id
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * @param nickname the nickname to set
+ */
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+
+ /**
+ * @return the nickname
+ */
+ public String getNickname() {
+ return nickname;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * @param sourcePort the sourcePort to set
+ */
+ public void setSourcePort(int sourcePort) {
+ this.sourcePort = sourcePort;
+ }
+
+ /**
+ * @return the sourcePort
+ */
+ public int getSourcePort() {
+ return sourcePort;
+ }
+
+ /**
+ * @param dest The destination in "host:port" format
+ */
+ public void setDest(String dest) {
+ String[] destSplit = dest.split(":");
+ this.destAddr = destSplit[0];
+ this.destPort = Integer.parseInt(destSplit[1]);
+ }
+
+ /**
+ * @param destAddr the destAddr to set
+ */
+ public void setDestAddr(String destAddr) {
+ this.destAddr = destAddr;
+ }
+
+ /**
+ * @return the destAddr
+ */
+ public String getDestAddr() {
+ return destAddr;
+ }
+
+ /**
+ * @param destPort the destPort to set
+ */
+ public void setDestPort(int destPort) {
+ this.destPort = destPort;
+ }
+
+ /**
+ * @return the destPort
+ */
+ public int getDestPort() {
+ return destPort;
+ }
+
+ /**
+ * @param enabled the enabled to set
+ */
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ /**
+ * @return the enabled
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * @param identifier the identifier of this particular type to set
+ */
+ public void setIdentifier(Object identifier) {
+ this.identifier = identifier;
+ }
+
+ /**
+ * @return the identifier used by this particular type
+ */
+ public Object getIdentifier() {
+ return identifier;
+ }
+
+ /**
+ * @return human readable description of the port forward
+ */
+ public CharSequence getDescription() {
+ String description = "Unknown type";
+
+ if (HostDatabase.PORTFORWARD_LOCAL.equals(type)) {
+ description = String.format("Local port %d to %s:%d", sourcePort, destAddr, destPort);
+ } else if (HostDatabase.PORTFORWARD_REMOTE.equals(type)) {
+ description = String.format("Remote port %d to %s:%d", sourcePort, destAddr, destPort);
+ } else if (HostDatabase.PORTFORWARD_DYNAMIC4.equals(type)) {
+ description = String.format("Dynamic port %d (SOCKS4)", sourcePort);
+ } else if (HostDatabase.PORTFORWARD_DYNAMIC5.equals(type)) {
+ description = String.format("Dynamic port %d (SOCKS5)", sourcePort);
+ }
+
+ return description;
+ }
+
+ /**
+ * @return
+ */
+ public ContentValues getValues() {
+ ContentValues values = new ContentValues();
+
+ values.put(HostDatabase.FIELD_PORTFORWARD_HOSTID, hostId);
+ values.put(HostDatabase.FIELD_PORTFORWARD_NICKNAME, nickname);
+ values.put(HostDatabase.FIELD_PORTFORWARD_TYPE, type);
+ values.put(HostDatabase.FIELD_PORTFORWARD_SOURCEPORT, sourcePort);
+ values.put(HostDatabase.FIELD_PORTFORWARD_DESTADDR, destAddr);
+ values.put(HostDatabase.FIELD_PORTFORWARD_DESTPORT, destPort);
+
+ return values;
+ }
+}
diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java
index bb1ae20..9bf4790 100644
--- a/src/org/connectbot/service/TerminalBridge.java
+++ b/src/org/connectbot/service/TerminalBridge.java
@@ -25,9 +25,14 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
import org.connectbot.R;
import org.connectbot.TerminalView;
+import org.connectbot.bean.PortForwardBean;
import org.connectbot.util.HostDatabase;
import org.connectbot.util.PubkeyDatabase;
import org.connectbot.util.PubkeyUtils;
@@ -50,6 +55,7 @@ import com.trilead.ssh2.Connection;
import com.trilead.ssh2.ConnectionMonitor;
import com.trilead.ssh2.InteractiveCallback;
import com.trilead.ssh2.KnownHosts;
+import com.trilead.ssh2.LocalPortForwarder;
import com.trilead.ssh2.ServerHostKeyVerifier;
import com.trilead.ssh2.Session;
import com.trilead.ssh2.crypto.PEMDecoder;
@@ -89,6 +95,8 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
);
}
+ private List<PortForwardBean> portForwards = new LinkedList<PortForwardBean>();
+
public int color[] = { Color.BLACK, Color.RED, Color.GREEN, Color.YELLOW,
Color.BLUE, Color.MAGENTA, Color.CYAN, Color.WHITE, };
@@ -125,10 +133,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
private boolean ctrlPressed = false;
private boolean altPressed = false;
private boolean shiftPressed = false;
-
- //protected PubkeyDatabase pubkeydb = null;
- //protected Cursor pubkeys = null;
- //final int COL_NICKNAME, COL_TYPE, COL_PRIVATE, COL_PUBLIC, COL_ENCRYPTED;
+
private boolean pubkeysExhausted = false;
private boolean forcedSize = false;
@@ -236,20 +241,14 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
this.buffer.setDisplay(this);
this.buffer.setCursorPosition(0, 0);
+ // TODO Change this when hosts are beans as well
+ this.portForwards = manager.hostdb.getPortForwardsForHost(manager.hostdb.findHostByNickname(nickname));
+
// 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.connection.addConnectionMonitor(this);
-
-// this.pubkeydb = new PubkeyDatabase(manager);
-// this.pubkeys = this.pubkeydb.allPubkeys();
-//
-// 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);
}
public final static int AUTH_TRIES = 20;
@@ -517,6 +516,14 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
this.fullyConnected = true;
+ // Start up predefined port forwards
+ ListIterator<PortForwardBean> itr = portForwards.listIterator();
+ while (itr.hasNext()) {
+ PortForwardBean pfb = itr.next();
+ Log.d(TAG, String.format("Enabling port forward %s", pfb.getDescription()));
+ enablePortForward(pfb);
+ }
+
// finally send any post-login string, if requested
this.injectString(postlogin);
@@ -987,6 +994,117 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener, InteractiveCal
return -1;
}
+ /**
+ * Adds the {@link PortForwardBean} to the list.
+ * @param portForward the port forward bean to add
+ * @return true on successful addition
+ */
+ public boolean addPortForward(PortForwardBean portForward) {
+ return this.portForwards.add(portForward);
+ }
+
+ /**
+ * Removes the {@link PortForwardBean} from the list.
+ * @param portForward the port forward bean to remove
+ * @return true on successful removal
+ */
+ public boolean removePortForward(PortForwardBean portForward) {
+ // Make sure we don't have a phantom forwarder.
+ disablePortForward(portForward);
+
+ return this.portForwards.remove(portForward);
+ }
+
+ /**
+ * @return the list of port forwards
+ */
+ public List<PortForwardBean> getPortForwards() {
+ return portForwards;
+ }
+
+ /**
+ * Enables a port forward member. After calling this method, the port forward should
+ * be operational.
+ * @param portForward member of our current port forwards list to enable
+ * @return true on successful port forward setup
+ */
+ public boolean enablePortForward(PortForwardBean portForward) {
+ if (!this.portForwards.contains(portForward)) {
+ Log.e(TAG, "Attempt to enable port forward not in list");
+ return false;
+ }
+
+ if (HostDatabase.PORTFORWARD_LOCAL.equals(portForward.getType())) {
+ LocalPortForwarder lpf = null;
+ try {
+ lpf = this.connection.createLocalPortForwarder(portForward.getSourcePort(), portForward.getDestAddr(), portForward.getDestPort());
+ } catch (IOException e) {
+ Log.e(TAG, "Could not create local port forward", e);
+ return false;
+ }
+
+ if (lpf == null) {
+ Log.e(TAG, "returned LocalPortForwarder object is null");
+ return false;
+ }
+
+ portForward.setIdentifier(lpf);
+ portForward.setEnabled(true);
+ return true;
+ } else if (HostDatabase.PORTFORWARD_REMOTE.equals(portForward.getType())) {
+ try {
+ this.connection.requestRemotePortForwarding("", portForward.getSourcePort(), portForward.getDestAddr(), portForward.getDestPort());
+ } catch (IOException e) {
+ Log.e(TAG, "Could not create remote port forward", e);
+ return false;
+ }
+
+ portForward.setEnabled(false);
+ return true;
+ } else {
+ // Unsupported type
+ Log.e(TAG, String.format("attempt to forward unknown type %s", portForward.getType()));
+ return false;
+ }
+ }
+
+ /**
+ * Disables a port forward member. After calling this method, the port forward should
+ * be non-functioning.
+ * @param portForward member of our current port forwards list to enable
+ * @return true on successful port forward tear-down
+ */
+ public boolean disablePortForward(PortForwardBean portForward) {
+ if (portForward.getType() == HostDatabase.PORTFORWARD_LOCAL) {
+ LocalPortForwarder lpf = null;
+ lpf = (LocalPortForwarder)portForward.getIdentifier();
+
+ if (!portForward.isEnabled() || lpf == null)
+ return false;
+
+ portForward.setEnabled(false);
+ try {
+ lpf.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Could not stop local port forwarder, setting enabled to false", e);
+ return false;
+ }
+
+ return true;
+ } else if (portForward.getType() == HostDatabase.PORTFORWARD_REMOTE) {
+ portForward.setEnabled(false);
+ try {
+ this.connection.cancelRemotePortForwarding(portForward.getSourcePort());
+ } catch (IOException e) {
+ Log.e(TAG, "Could not stop remote port forwarding, setting enabled to false", e);
+ return false;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/src/org/connectbot/util/HostDatabase.java b/src/org/connectbot/util/HostDatabase.java
index fe4c8d4..59d6326 100644
--- a/src/org/connectbot/util/HostDatabase.java
+++ b/src/org/connectbot/util/HostDatabase.java
@@ -18,6 +18,11 @@
package org.connectbot.util;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.connectbot.bean.PortForwardBean;
+
import com.trilead.ssh2.KnownHosts;
import android.content.ContentValues;
@@ -38,7 +43,7 @@ public class HostDatabase extends SQLiteOpenHelper {
public final static String TAG = HostDatabase.class.toString();
public final static String DB_NAME = "hosts";
- public final static int DB_VERSION = 11;
+ public final static int DB_VERSION = 12;
public final static String TABLE_HOSTS = "hosts";
public final static String FIELD_HOST_NICKNAME = "nickname";
@@ -52,11 +57,24 @@ public class HostDatabase extends SQLiteOpenHelper {
public final static String FIELD_HOST_USEKEYS = "usekeys";
public final static String FIELD_HOST_POSTLOGIN = "postlogin";
public final static String FIELD_HOST_PUBKEYID = "pubkeyid";
+
+ public final static String TABLE_PORTFORWARDS = "portforwards";
+ public final static String FIELD_PORTFORWARD_HOSTID = "hostid";
+ public final static String FIELD_PORTFORWARD_NICKNAME = "nickname";
+ public final static String FIELD_PORTFORWARD_TYPE = "type";
+ public final static String FIELD_PORTFORWARD_SOURCEPORT = "sourceport";
+ public final static String FIELD_PORTFORWARD_DESTADDR = "destaddr";
+ public final static String FIELD_PORTFORWARD_DESTPORT = "destport";
public final static String COLOR_RED = "red";
public final static String COLOR_GREEN = "green";
public final static String COLOR_BLUE = "blue";
public final static String COLOR_GRAY = "gray";
+
+ public final static String PORTFORWARD_LOCAL = "local";
+ public final static String PORTFORWARD_REMOTE = "remote";
+ public final static String PORTFORWARD_DYNAMIC4 = "dynamic4";
+ public final static String PORTFORWARD_DYNAMIC5 = "dynamic5";
public final static long PUBKEYID_NEVER = -2;
public final static long PUBKEYID_ANY = -1;
@@ -86,6 +104,14 @@ public class HostDatabase extends SQLiteOpenHelper {
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, "
+ + FIELD_PORTFORWARD_HOSTID + " INTEGER, "
+ + FIELD_PORTFORWARD_NICKNAME + " TEXT, "
+ + FIELD_PORTFORWARD_TYPE + " TEXT NOT NULL DEFAULT " + PORTFORWARD_LOCAL + ", "
+ + FIELD_PORTFORWARD_SOURCEPORT + " INTEGER NOT NULL DEFAULT 8080, "
+ + FIELD_PORTFORWARD_DESTADDR + " TEXT, "
+ + FIELD_PORTFORWARD_DESTPORT + " TEXT)");
}
@Override
@@ -94,12 +120,23 @@ public class HostDatabase extends SQLiteOpenHelper {
// shot without warning.
if (oldVersion <= 9) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_HOSTS);
- onCreate(db);
+ onCreate(db);
+ return;
}
- if (oldVersion == 10) {
+ switch (oldVersion) {
+ case 10:
db.execSQL("ALTER TABLE " + TABLE_HOSTS
+ " ADD COLUMN " + FIELD_HOST_PUBKEYID + " INTEGER DEFAULT " + PUBKEYID_ANY);
+ case 11:
+ db.execSQL("CREATE TABLE " + TABLE_PORTFORWARDS
+ + " (_id INTEGER PRIMARY KEY, "
+ + FIELD_PORTFORWARD_HOSTID + " INTEGER, "
+ + FIELD_PORTFORWARD_NICKNAME + " TEXT, "
+ + FIELD_PORTFORWARD_TYPE + " TEXT NOT NULL DEFAULT " + PORTFORWARD_LOCAL + ", "
+ + FIELD_PORTFORWARD_SOURCEPORT + " INTEGER NOT NULL DEFAULT 8080, "
+ + FIELD_PORTFORWARD_DESTADDR + " TEXT, "
+ + FIELD_PORTFORWARD_DESTPORT + " INTEGER)");
}
}
@@ -121,6 +158,49 @@ public class HostDatabase extends SQLiteOpenHelper {
}
/**
+ * 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);
+
+ c.close();
+ db.close();
+
+ return id;
+ }
+
+ /**
+ * Find a host's nickname in the database by its ID.
+ * @param hostId
+ * @return the host's nickname
+ */
+ 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);
+
+ c.close();
+ db.close();
+
+ return nickname;
+ }
+
+ /**
* Create a new host using the given parameters, and return its new
* <code>_id</code> value.
*/
@@ -188,9 +268,12 @@ public class HostDatabase extends SQLiteOpenHelper {
return result;
}
-
+
/**
* Record the given hostkey into database under this nickname.
+ * @param hostname
+ * @param hostkeyalgo
+ * @param hostkey
*/
public void saveKnownHost(String hostname, String hostkeyalgo, byte[] hostkey) {
@@ -207,6 +290,7 @@ public class HostDatabase extends SQLiteOpenHelper {
/**
* Build list of known hosts for Trilead library.
+ * @return
*/
public KnownHosts getKnownHosts() {
KnownHosts known = new KnownHosts();
@@ -242,6 +326,8 @@ public class HostDatabase extends SQLiteOpenHelper {
/**
* 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;
@@ -256,6 +342,11 @@ public class HostDatabase extends SQLiteOpenHelper {
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();
@@ -267,9 +358,10 @@ public class HostDatabase extends SQLiteOpenHelper {
Log.d(TAG, String.format("Updated host id %d to use pubkey id %d", hostId, pubkeyId));
}
-
+
/**
- * Unset any hosts using a pubkey that has been deleted.
+ * Unset any hosts using a pubkey ID that has been deleted.
+ * @param pubkeyId
*/
public void stopUsingPubkey(long pubkeyId) {
if (pubkeyId < 0) return;
@@ -284,4 +376,66 @@ public class HostDatabase extends SQLiteOpenHelper {
Log.d(TAG, String.format("Set all hosts using pubkey id %d to -1", pubkeyId));
}
+
+ /*
+ * Methods for dealing with port forwards attached to hosts
+ */
+
+ /**
+ * Returns a list of all the port forwards associated with a particular host ID.
+ * @param hostId ID of host
+ * @return port forwards associated with host ID
+ */
+ public List<PortForwardBean> getPortForwardsForHost(long hostId) {
+ 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) },
+ null, null, null);
+
+ while (c.moveToNext()) {
+ PortForwardBean pfb = new PortForwardBean(
+ c.getInt(0),
+ hostId,
+ c.getString(1),
+ c.getString(2),
+ c.getInt(3),
+ c.getString(4),
+ c.getInt(5));
+ portForwards.add(pfb);
+ }
+
+ c.close();
+ db.close();
+
+ return portForwards;
+ }
+
+
+ /**
+ * Update the parameters of a port forward in the database.
+ * @param port forwardId ID of port forward in database
+ * @param values
+ * @return true on success
+ */
+ public boolean savePortForward(PortForwardBean pfb) {
+ boolean success = false;
+ SQLiteDatabase db = this.getWritableDatabase();
+
+ if (pfb.getId() < 0) {
+ long id = db.insert(TABLE_PORTFORWARDS, null, pfb.getValues());
+ pfb.setId(id);
+ success = true;
+ } else {
+ if (db.update(TABLE_PORTFORWARDS, pfb.getValues(), "_id = ?", new String[] { String.valueOf(pfb.getId()) }) > 0)
+ success = true;
+ }
+
+ db.close();
+
+ return success;
+ }
}