aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeffrey Sharkey <jsharkey@jsharkey.org>2008-08-27 10:47:56 +0000
committerJeffrey Sharkey <jsharkey@jsharkey.org>2008-08-27 10:47:56 +0000
commitcbf1af86640c76facfc140b5dfb83f2393c02d19 (patch)
tree0af4a26136f833765cc444cbfeaa52c465c83c81 /src
parentba0d4f5a28170e52956705fe75a6763ce79e6264 (diff)
downloadconnectbot-cbf1af86640c76facfc140b5dfb83f2393c02d19.tar.gz
connectbot-cbf1af86640c76facfc140b5dfb83f2393c02d19.tar.bz2
connectbot-cbf1af86640c76facfc140b5dfb83f2393c02d19.zip
* moved all terminal logic into a Service backend. connections are held in place by a TerminalBridge, which keeps the connection alive and renders the screen to a
bitmap if provided. a Console creates TerminalViews for each bridge while it is active, and handles panning back/forth between them. * volume up/down controls will change console font size * extended trilead library to support resizePTY() command * left/right screen gestures will pan between various open consoles * up/down screen gestures on right-half will look through scrollback buffer * up/down screen gestures on left-half will trigger pageup/down keys * broke ctrl+ keyboard mapping, will need to bring back over from older code
Diffstat (limited to 'src')
-rw-r--r--src/com/trilead/ssh2/Session.java11
-rw-r--r--src/com/trilead/ssh2/channel/ChannelManager.java30
-rw-r--r--src/com/trilead/ssh2/packets/PacketSessionPtyResize.java40
-rw-r--r--src/de/mud/terminal/VDUBuffer.java7
-rw-r--r--src/de/mud/terminal/vt320.java11
-rw-r--r--src/org/connectbot/Console.java250
-rw-r--r--src/org/connectbot/FrontPage.java133
-rw-r--r--src/org/connectbot/HostEditor.java15
-rw-r--r--src/org/connectbot/TerminalView.java56
-rw-r--r--src/org/connectbot/TerminalViewSurface.java37
-rw-r--r--src/org/connectbot/service/TerminalBridge.java381
-rw-r--r--src/org/connectbot/service/TerminalBridgeSurface.java310
-rw-r--r--src/org/connectbot/service/TerminalManager.java81
-rw-r--r--src/org/theb/provider/HostDb.java5
-rw-r--r--src/org/theb/ssh/HostDbProvider.java29
-rw-r--r--src/org/theb/ssh/HostEditor.java115
-rw-r--r--src/org/theb/ssh/HostsList.java98
-rw-r--r--src/org/theb/ssh/PasswordDialog.java2
-rw-r--r--src/org/theb/ssh/Pubkey.java2
-rw-r--r--src/org/theb/ssh/SecureShell.java1
-rw-r--r--src/org/theb/ssh/TouchEntropy.java2
-rw-r--r--src/org/theb/ssh/TrileadConnectionThread.java46
22 files changed, 1544 insertions, 118 deletions
diff --git a/src/com/trilead/ssh2/Session.java b/src/com/trilead/ssh2/Session.java
index 4784537..c41d837 100644
--- a/src/com/trilead/ssh2/Session.java
+++ b/src/com/trilead/ssh2/Session.java
@@ -129,6 +129,17 @@ public class Session
cm.requestPTY(cn, term, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels,
terminal_modes);
}
+
+ public void resizePTY(int width, int height) throws IOException {
+ synchronized (this)
+ {
+ /* The following is just a nicer error, we would catch it anyway later in the channel code */
+ if (flag_closed)
+ throw new IOException("This session is closed.");
+ }
+
+ cm.resizePTY(cn, width, height);
+ }
/**
* Request X11 forwarding for the current session.
diff --git a/src/com/trilead/ssh2/channel/ChannelManager.java b/src/com/trilead/ssh2/channel/ChannelManager.java
index ebd7585..74906d3 100644
--- a/src/com/trilead/ssh2/channel/ChannelManager.java
+++ b/src/com/trilead/ssh2/channel/ChannelManager.java
@@ -17,6 +17,7 @@ import com.trilead.ssh2.packets.PacketOpenDirectTCPIPChannel;
import com.trilead.ssh2.packets.PacketOpenSessionChannel;
import com.trilead.ssh2.packets.PacketSessionExecCommand;
import com.trilead.ssh2.packets.PacketSessionPtyRequest;
+import com.trilead.ssh2.packets.PacketSessionPtyResize;
import com.trilead.ssh2.packets.PacketSessionStartShell;
import com.trilead.ssh2.packets.PacketSessionSubsystemRequest;
import com.trilead.ssh2.packets.PacketSessionX11Request;
@@ -675,6 +676,35 @@ public class ChannelManager implements MessageHandler
throw (IOException) new IOException("PTY request failed").initCause(e);
}
}
+
+
+ public void resizePTY(Channel c, int width, int height) throws IOException {
+ PacketSessionPtyResize spr;
+
+ synchronized (c) {
+ if (c.state != Channel.STATE_OPEN)
+ throw new IOException("Cannot request PTY on this channel ("
+ + c.getReasonClosed() + ")");
+
+ spr = new PacketSessionPtyResize(c.remoteID, true, width, height);
+ c.successCounter = c.failedCounter = 0;
+ }
+
+ synchronized (c.channelSendLock) {
+ if (c.closeMessageSent)
+ throw new IOException("Cannot request PTY on this channel ("
+ + c.getReasonClosed() + ")");
+ tm.sendMessage(spr.getPayload());
+ }
+
+ try {
+ waitForChannelSuccessOrFailure(c);
+ } catch (IOException e) {
+ throw (IOException) new IOException("PTY request failed")
+ .initCause(e);
+ }
+ }
+
public void requestX11(Channel c, boolean singleConnection, String x11AuthenticationProtocol,
String x11AuthenticationCookie, int x11ScreenNumber) throws IOException
diff --git a/src/com/trilead/ssh2/packets/PacketSessionPtyResize.java b/src/com/trilead/ssh2/packets/PacketSessionPtyResize.java
new file mode 100644
index 0000000..20d35cd
--- /dev/null
+++ b/src/com/trilead/ssh2/packets/PacketSessionPtyResize.java
@@ -0,0 +1,40 @@
+package com.trilead.ssh2.packets;
+
+public class PacketSessionPtyResize {
+ byte[] payload;
+
+ public int recipientChannelID;
+ public boolean wantReply;
+ public String term;
+ public int width;
+ public int height;
+
+ public PacketSessionPtyResize(int recipientChannelID, boolean wantReply, int width, int height) {
+ this.recipientChannelID = recipientChannelID;
+ this.wantReply = wantReply;
+ this.term = term;
+ this.width = width;
+ this.height = height;
+ }
+
+ public byte[] getPayload()
+ {
+ if (payload == null)
+ {
+ TypesWriter tw = new TypesWriter();
+ tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST);
+ tw.writeUINT32(recipientChannelID);
+ tw.writeString("window-change");
+ tw.writeBoolean(wantReply);
+ tw.writeUINT32(width);
+ tw.writeUINT32(height);
+ tw.writeUINT32(0);
+ tw.writeUINT32(0);
+
+ payload = tw.getBytes();
+ }
+ return payload;
+ }
+}
+
+
diff --git a/src/de/mud/terminal/VDUBuffer.java b/src/de/mud/terminal/VDUBuffer.java
index 50a2268..120f093 100644
--- a/src/de/mud/terminal/VDUBuffer.java
+++ b/src/de/mud/terminal/VDUBuffer.java
@@ -339,7 +339,7 @@ public class VDUBuffer {
(topMargin > 0 ?
topMargin - 1 : 0) : bottomMargin));
- // System.out.println("l is "+l+", top is "+top+", bottom is "+bottom+", bottomargin is "+bottomMargin+", topMargin is "+topMargin);
+ System.out.println("l is "+l+", top is "+top+", bottom is "+bottom+", bottomargin is "+bottomMargin+", topMargin is "+topMargin);
if (scrollDown) {
if (n > (bottom - top)) n = (bottom - top);
@@ -617,6 +617,7 @@ public class VDUBuffer {
* @param l line that is the margin
*/
public void setTopMargin(int l) {
+ //System.out.println("trying setTopMargin " + l);
if (l > bottomMargin) {
topMargin = bottomMargin;
bottomMargin = l;
@@ -624,6 +625,7 @@ public class VDUBuffer {
topMargin = l;
if (topMargin < 0) topMargin = 0;
if (bottomMargin > height - 1) bottomMargin = height - 1;
+ //System.out.println("final setTopMargin " + topMargin);
}
/**
@@ -640,6 +642,7 @@ public class VDUBuffer {
* @param l line that is the margin
*/
public void setBottomMargin(int l) {
+ //System.out.println("trying setBottomMargin " + l);
if (l < topMargin) {
bottomMargin = topMargin;
topMargin = l;
@@ -647,6 +650,7 @@ public class VDUBuffer {
bottomMargin = l;
if (topMargin < 0) topMargin = 0;
if (bottomMargin > height - 1) bottomMargin = height - 1;
+ //System.out.println("final setBottomMargin " + bottomMargin);
}
/**
@@ -756,6 +760,7 @@ public class VDUBuffer {
bottomMargin = h - 1;
update = new boolean[h + 1];
update[0] = true;
+
/* FIXME: ???
if(resizeStrategy == RESIZE_FONT)
setBounds(getBounds());
diff --git a/src/de/mud/terminal/vt320.java b/src/de/mud/terminal/vt320.java
index 5e0f4c2..fccd56a 100644
--- a/src/de/mud/terminal/vt320.java
+++ b/src/de/mud/terminal/vt320.java
@@ -39,6 +39,7 @@ public abstract class vt320 extends VDUBuffer implements VDUInput {
/** The current version id tag.<P>
* $Id: vt320.java 507 2005-10-25 10:14:52Z marcus $
+ *
*/
public final static String ID = "$Id: vt320.java 507 2005-10-25 10:14:52Z marcus $";
@@ -1930,7 +1931,7 @@ public abstract class vt320 extends VDUBuffer implements VDUInput {
break;
case 'r': // XTERM_RESTORE
if (true || debug > 1)
- System.out.println("ESC [ ? " + DCEvars[0] + " r");
+ System.out.println("m1ESC [ ? " + DCEvars[0] + " r");
/* DEC Mode reset */
for (int i = 0; i <= DCEvar; i++) {
switch (DCEvars[i]) {
@@ -2328,7 +2329,7 @@ public abstract class vt320 extends VDUBuffer implements VDUInput {
int limit;
/* FIXME: xterm only cares about 0 and topmargin */
if (R > bm)
- limit = bm; // BUGFIX: corrects scrollback dissapearing in irssi
+ limit = bm; // BUGFIX: corrects scrollback dissapearing in irssi (?)
else if (R >= tm) {
limit = tm;
} else
@@ -2403,15 +2404,17 @@ public abstract class vt320 extends VDUBuffer implements VDUInput {
} else
R = rows - 1;
setBottomMargin(R);
+ System.out.println("setBottomMargin R="+R);
if (R >= DCEvars[0]) {
R = DCEvars[0] - 1;
if (R < 0)
R = 0;
}
setTopMargin(R);
+ System.out.println("setTopMargin R="+R);
_SetCursor(0, 0);
if (debug > 1)
- System.out.println("ESC [" + DCEvars[0] + " ; " + DCEvars[1] + " r");
+ System.out.println("m2ESC [" + DCEvars[0] + " ; " + DCEvars[1] + " r");
break;
case 'G': /* CUP / cursor absolute column */
C = DCEvars[0];
@@ -2682,7 +2685,7 @@ public abstract class vt320 extends VDUBuffer implements VDUInput {
if (debug > 3)
System.out.print("" + DCEvars[i] + ";");
}
- if (debug > 3)
+ if (debug > 4)
System.out.print(" (attributes = " + attributes + ")m \n");
break;
default:
diff --git a/src/org/connectbot/Console.java b/src/org/connectbot/Console.java
new file mode 100644
index 0000000..2895ed5
--- /dev/null
+++ b/src/org/connectbot/Console.java
@@ -0,0 +1,250 @@
+package org.connectbot;
+
+import org.connectbot.service.TerminalBridge;
+import org.connectbot.service.TerminalBridgeSurface;
+import org.connectbot.service.TerminalManager;
+import org.theb.ssh.InteractiveHostKeyVerifier;
+
+import org.theb.ssh.R;
+import com.trilead.ssh2.Connection;
+
+import de.mud.terminal.vt320;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.View.OnKeyListener;
+import android.view.View.OnTouchListener;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Animation.AnimationListener;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.ViewFlipper;
+import android.widget.LinearLayout.LayoutParams;
+
+public class Console extends Activity {
+
+ public ViewFlipper flip = null;
+ public TerminalManager bound = null;
+ public LayoutInflater inflater = null;
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ bound = ((TerminalManager.TerminalBinder) service).getService();
+
+ Log.d(this.getClass().toString(), "ohhai there, i found bridges=" + bound.bridges.size());
+
+ // clear out any existing bridges and record requested index
+ flip.removeAllViews();
+ int requestedIndex = 0;
+
+ // create views for all bridges on this service
+ for(TerminalBridge bridge : bound.bridges) {
+
+ // inflate each terminal view
+ RelativeLayout view = (RelativeLayout)inflater.inflate(R.layout.item_terminal, flip, false);
+
+ // set the terminal overlay text
+ TextView overlay = (TextView)view.findViewById(R.id.terminal_overlay);
+ overlay.setText(bridge.overlay);
+
+ // and add our terminal view control, using index to place behind overlay
+ TerminalView terminal = new TerminalView(Console.this, bridge);
+ terminal.setId(R.id.console_flip);
+ view.addView(terminal, 0);
+
+ // finally attach to the flipper
+ flip.addView(view);
+
+ // check to see if this bridge was requested
+ if(bridge.overlay.equals(requestedBridge))
+ requestedIndex = flip.getChildCount() - 1;
+
+ }
+
+ // show the requested bridge if found, also fade out overlay
+ flip.setDisplayedChild(requestedIndex);
+ flip.getCurrentView().findViewById(R.id.terminal_overlay).startAnimation(fade_out);
+
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // remove all bridge views
+ bound = null;
+ flip.removeAllViews();
+ }
+ };
+
+ public Animation fade_out = null;
+ public String requestedBridge = null;
+
+ public void updateDefault() {
+ // update the current default terminal
+ TerminalView terminal = (TerminalView)flip.getCurrentView().findViewById(R.id.console_flip);
+ if(bound == null || terminal == null) return;
+ bound.defaultBridge = terminal.bridge;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ this.setContentView(R.layout.act_console);
+
+ // pull out any requested bridge
+ this.requestedBridge = this.getIntent().getExtras().getString(Intent.EXTRA_TEXT);
+
+ this.inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ this.flip = (ViewFlipper)this.findViewById(R.id.console_flip);
+
+ this.fade_out = AnimationUtils.loadAnimation(this, R.anim.fade_out);
+
+ // connect with manager service to find all bridges
+ // when connected it will insert all views
+ this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
+
+
+ // preload animations for terminal switching
+ final Animation slide_left_in = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
+ final Animation slide_left_out = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);
+ final Animation slide_right_in = AnimationUtils.loadAnimation(this, R.anim.slide_right_in);
+ final Animation slide_right_out = AnimationUtils.loadAnimation(this, R.anim.slide_right_out);
+ final Animation fade_stay_hidden = AnimationUtils.loadAnimation(this, R.anim.fade_stay_hidden);
+
+ // detect fling gestures to switch between terminals
+ final GestureDetector detect = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
+
+ public float totalY = 0;
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+
+ // if releasing then reset total scroll
+ if(e2.getAction() == MotionEvent.ACTION_UP) {
+ totalY = 0;
+ }
+
+ // activate consider if within x tolerance
+ if(Math.abs(e1.getX() - e2.getX()) < 100) {
+
+ TerminalView terminal = (TerminalView)flip.getCurrentView().findViewById(R.id.console_flip);
+
+ // estimate how many rows we have scrolled through
+ // accumulate distance that doesn't trigger immediate scroll
+ totalY += distanceY;
+ int moved = (int)(totalY / terminal.bridge.charHeight);
+
+ // consume as scrollback only if towards right half of screen
+ if(e2.getX() > flip.getWidth() / 2) {
+ if(moved != 0) {
+ int base = terminal.bridge.buffer.getWindowBase();
+ terminal.bridge.buffer.setWindowBase(base + moved);
+ totalY = 0;
+ return true;
+ }
+ } else {
+ // otherwise consume as pgup/pgdown for every 5 lines
+ if(moved > 5) {
+ Log.d(this.getClass().toString(), "going pagedown");
+ ((vt320)terminal.bridge.buffer).keyPressed(vt320.KEY_PAGE_DOWN, ' ', 0);
+ totalY = 0;
+ return true;
+ } else if(moved < -5) {
+ Log.d(this.getClass().toString(), "going pageup");
+ ((vt320)terminal.bridge.buffer).keyPressed(vt320.KEY_PAGE_UP, ' ', 0);
+ totalY = 0;
+ return true;
+ }
+
+ }
+
+
+ }
+
+ return false;
+ }
+
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+
+ float distx = e2.getRawX() - e1.getRawX();
+ float disty = e2.getRawY() - e1.getRawY();
+ int goalwidth = flip.getWidth() / 2;
+ int goalheight = flip.getHeight() / 2;
+
+ // need to slide across half of display to trigger console change
+ // make sure user kept a steady hand horizontally
+ if(Math.abs(disty) < 100) {
+ if(distx > goalwidth) {
+
+ // keep current overlay from popping up again
+ flip.getCurrentView().findViewById(R.id.terminal_overlay).startAnimation(fade_stay_hidden);
+
+ flip.setInAnimation(slide_right_in);
+ flip.setOutAnimation(slide_right_out);
+ flip.showPrevious();
+ Console.this.updateDefault();
+
+ // show overlay on new slide and start fade
+ flip.getCurrentView().findViewById(R.id.terminal_overlay).startAnimation(fade_out);
+ return true;
+ }
+
+ if(distx < -goalwidth) {
+
+ // keep current overlay from popping up again
+ flip.getCurrentView().findViewById(R.id.terminal_overlay).startAnimation(fade_stay_hidden);
+
+ flip.setInAnimation(slide_left_in);
+ flip.setOutAnimation(slide_left_out);
+ flip.showNext();
+ Console.this.updateDefault();
+
+ // show overlay on new slide and start fade
+ flip.getCurrentView().findViewById(R.id.terminal_overlay).startAnimation(fade_out);
+ return true;
+ }
+
+ }
+
+
+
+ return false;
+ }
+
+
+ });
+
+
+ flip.setLongClickable(true);
+ flip.setOnTouchListener(new OnTouchListener() {
+
+ public boolean onTouch(View v, MotionEvent event) {
+ // pass any touch events back to detector
+ return detect.onTouchEvent(event);
+ }
+
+ });
+
+
+
+
+ }
+
+}
diff --git a/src/org/connectbot/FrontPage.java b/src/org/connectbot/FrontPage.java
new file mode 100644
index 0000000..4fa7734
--- /dev/null
+++ b/src/org/connectbot/FrontPage.java
@@ -0,0 +1,133 @@
+package org.connectbot;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.connectbot.service.TerminalBridge;
+import org.connectbot.service.TerminalManager;
+import org.theb.ssh.InteractiveHostKeyVerifier;
+
+import com.trilead.ssh2.Connection;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnKeyListener;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+import android.widget.AdapterView.OnItemClickListener;
+import org.theb.ssh.R;
+
+public class FrontPage extends Activity {
+
+ public TerminalManager bound = null;
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ bound = ((TerminalManager.TerminalBinder) service).getService();
+
+ // TODO: update our green bulb icons by checking for existing bridges
+ // open up some test sessions
+// try {
+// bound.openConnection("192.168.254.230", 22, "connectbot", "b0tt", "screen", 100);
+// bound.openConnection("192.168.254.230", 22, "connectbot", "b0tt", "screen", 100);
+// bound.openConnection("192.168.254.230", 22, "connectbot", "b0tt", "screen", 100);
+// } catch(Exception e) {
+// e.printStackTrace();
+// }
+
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ bound = null;
+ }
+ };
+
+
+ public final static String ITEM_TITLE = "title";
+ public final static String ITEM_CAPTION = "caption";
+ public final static String ITEM_IMAGE = "image";
+
+ public Map<String,?> createItem(String title, String caption, int image) {
+ Map<String,String> item = new HashMap<String,String>();
+ item.put(ITEM_TITLE, title);
+ item.put(ITEM_CAPTION, caption);
+ item.put(ITEM_IMAGE, Integer.toString(image));
+ return item;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.act_frontpage);
+
+ // start the terminal manager service
+ this.startService(new Intent(this, TerminalManager.class));
+ this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
+
+
+
+ // create some test hostmasks
+ List<Map<String,?>> security = new LinkedList<Map<String,?>>();
+ security.add(createItem("user@example.org", "20 minutes ago, connected", android.R.drawable.presence_online));
+ security.add(createItem("root@home.example.com", "1 hour ago, connected", android.R.drawable.presence_online));
+ security.add(createItem("person@192.168.0.1", "12 days ago", android.R.drawable.presence_invisible));
+ security.add(createItem("root@google.com", "never", android.R.drawable.presence_invisible));
+ security.add(createItem("nobody@example.net", "14 years ago, broken socket", android.R.drawable.presence_busy));
+ security.add(createItem("root@home.example.com", "1 hour ago", android.R.drawable.presence_invisible));
+ security.add(createItem("person@192.168.0.1", "12 minutes ago", android.R.drawable.presence_invisible));
+
+ final ListView list = (ListView)this.findViewById(R.id.front_hostlist);
+ list.setAdapter(new SimpleAdapter(this, security, R.layout.item_host, new String[] { ITEM_TITLE, ITEM_CAPTION, ITEM_IMAGE }, new int[] { R.id.host_title, R.id.host_caption, R.id.host_connected }));
+
+ list.setOnItemClickListener(new OnItemClickListener() {
+
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+
+ // TODO: actually perform connection process here
+ // launch off to console details
+ FrontPage.this.startActivity(new Intent(FrontPage.this, Console.class));
+
+ }
+
+ });
+
+
+// final TextView text = (TextView)this.findViewById(R.id.front_quickconnect);
+// text.setOnKeyListener(new OnKeyListener() {
+//
+// public boolean onKey(View v, int keyCode, KeyEvent event) {
+//
+// // set list filter based on text
+// String filter = text.getText().toString();
+// list.setTextFilterEnabled((filter.length() > 0));
+// list.setFilterText(filter);
+//
+// // TODO Auto-generated method stub
+// return false;
+// }
+//
+// });
+
+
+
+
+
+
+
+
+
+ }
+
+}
diff --git a/src/org/connectbot/HostEditor.java b/src/org/connectbot/HostEditor.java
new file mode 100644
index 0000000..373897d
--- /dev/null
+++ b/src/org/connectbot/HostEditor.java
@@ -0,0 +1,15 @@
+package org.connectbot;
+
+import android.app.Activity;
+import android.os.Bundle;
+import org.theb.ssh.R;
+
+public class HostEditor extends Activity {
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.act_hosteditor);
+ }
+
+}
diff --git a/src/org/connectbot/TerminalView.java b/src/org/connectbot/TerminalView.java
new file mode 100644
index 0000000..0e7e283
--- /dev/null
+++ b/src/org/connectbot/TerminalView.java
@@ -0,0 +1,56 @@
+package org.connectbot;
+
+import org.connectbot.service.TerminalBridge;
+import org.connectbot.service.TerminalBridgeSurface;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.view.SurfaceHolder;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+public class TerminalView extends View {
+
+ public final Context context;
+ public final TerminalBridge bridge;
+ public final Paint paint;
+
+ public TerminalView(Context context, TerminalBridge bridge) {
+ super(context);
+
+ this.context = context;
+ this.bridge = bridge;
+ this.paint = new Paint();
+
+ this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
+ this.setFocusable(true);
+ this.setFocusableInTouchMode(true);
+
+ // connect our view up to the bridge
+ this.setOnKeyListener(bridge);
+
+ }
+
+ public void destroy() {
+ // tell bridge to destroy its bitmap
+ this.bridge.parentDestroyed();
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ this.bridge.parentChanged(this);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ // draw the bridge if it exists
+ if(this.bridge.bitmap != null) {
+ canvas.drawBitmap(this.bridge.bitmap, 0, 0, this.paint);
+ }
+
+ }
+
+}
diff --git a/src/org/connectbot/TerminalViewSurface.java b/src/org/connectbot/TerminalViewSurface.java
new file mode 100644
index 0000000..cb68696
--- /dev/null
+++ b/src/org/connectbot/TerminalViewSurface.java
@@ -0,0 +1,37 @@
+package org.connectbot;
+
+import org.connectbot.service.TerminalBridgeSurface;
+
+import android.content.Context;
+import android.view.KeyEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup.LayoutParams;
+
+public class TerminalViewSurface extends SurfaceView {
+
+ public final Context context;
+ public final TerminalBridgeSurface bridge;
+
+ public TerminalViewSurface(Context context, TerminalBridgeSurface bridge) {
+ super(context);
+
+ this.context = context;
+ this.bridge = bridge;
+
+ this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
+ this.setFocusable(true);
+ this.setFocusableInTouchMode(true);
+
+
+ // connect our surface up to the bridge
+ this.getHolder().setType(SurfaceHolder.SURFACE_TYPE_HARDWARE);
+ this.getHolder().addCallback(bridge);
+ this.setOnKeyListener(bridge);
+
+ }
+
+ // TODO: make sure we pass any keystrokes down to bridge
+
+
+}
diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java
new file mode 100644
index 0000000..ed2424c
--- /dev/null
+++ b/src/org/connectbot/service/TerminalBridge.java
@@ -0,0 +1,381 @@
+package org.connectbot.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.theb.ssh.JTATerminalView;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.Bitmap.Config;
+import android.graphics.Paint.FontMetricsInt;
+import android.util.Log;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.SurfaceHolder;
+import android.view.View;
+import android.view.View.OnKeyListener;
+
+import com.trilead.ssh2.Session;
+import com.trilead.ssh2.Connection;
+
+import de.mud.terminal.VDUBuffer;
+import de.mud.terminal.VDUDisplay;
+import de.mud.terminal.vt320;
+
+
+// provides a bridge between the mud buffer and a surfaceholder
+public class TerminalBridge implements VDUDisplay, OnKeyListener {
+
+ public final Connection connection;
+ public final Session session;
+ public final String overlay;
+
+ public final static int TERM_WIDTH_CHARS = 80,
+ TERM_HEIGHT_CHARS = 24,
+ DEFAULT_FONT_SIZE = 10;
+
+ public final static String ENCODING = "ASCII";
+
+ public final OutputStream stdin;
+ public final InputStream stdout;
+
+ public final Paint defaultPaint;
+
+ public final Thread relay;
+
+ public View parent = null;
+ public Bitmap bitmap = null;
+ public Canvas canvas = new Canvas();
+ public VDUBuffer buffer = null;
+
+ public TerminalBridge(Connection connection, String overlay, String emulation, int scrollback) throws Exception {
+ // create a terminal bridge from an SSH connection over to a SurfaceHolder
+ // will open a new session and handle rendering to the Surface if present
+
+ try {
+ this.connection = connection;
+ this.session = connection.openSession();
+ this.session.requestPTY(emulation, 0, 0, 0, 0, null); // previously tried vt100, xterm, but "screen" works the best
+ this.session.startShell();
+
+ this.overlay = overlay;
+
+ // grab stdin/out from newly formed session
+ this.stdin = this.session.getStdin();
+ this.stdout = this.session.getStdout();
+
+ // create our default paint
+ this.defaultPaint = new Paint();
+ this.defaultPaint.setAntiAlias(true);
+ this.defaultPaint.setTypeface(Typeface.MONOSPACE);
+ this.setFontSize(DEFAULT_FONT_SIZE);
+
+ // create terminal buffer and handle outgoing data
+ // this is probably status reply information
+ this.buffer = new vt320() {
+ public void write(byte[] b) {
+ try {
+ //Log.d("STDIN", new String(b));
+ TerminalBridge.this.stdin.write(b);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void sendTelnetCommand(byte cmd) {
+ }
+
+ public void setWindowSize(int c, int r) {
+ }
+ };
+ this.scrollback = scrollback;
+ this.buffer.setScreenSize(TERM_WIDTH_CHARS, TERM_HEIGHT_CHARS, true);
+ this.buffer.setBufferSize(scrollback);
+ this.buffer.setDisplay(this);
+
+ // create thread to relay incoming connection data to buffer
+ this.relay = new Thread(new Runnable() {
+ public void run() {
+ byte[] b = new byte[256];
+ int n = 0;
+ while(n >= 0) {
+ try {
+ n = TerminalBridge.this.stdout.read(b);
+ if(n > 0) {
+ // pass along data to buffer, then redraw any results
+ ((vt320)TerminalBridge.this.buffer).putString(new String(b, 0, n, ENCODING));
+ TerminalBridge.this.redraw();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+ });
+ this.relay.start();
+
+ } catch(Exception e) {
+ throw e;
+ }
+
+ for(int i = 0; i < color.length; i++)
+ this.darkerColor[i] = darken(color[i]);
+
+ }
+
+ public void dispose() {
+ this.session.close();
+ this.connection.close();
+ }
+
+ KeyCharacterMap keymap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
+
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ // pass through any keystrokes to output stream
+ if(event.getAction() == KeyEvent.ACTION_UP) return false;
+ try {
+
+ // check for resizing keys
+ if(keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+ this.setFontSize(this.fontSize + 2);
+ return true;
+ } else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ this.setFontSize(this.fontSize - 2);
+ return true;
+ }
+
+ // print normal keys
+ if(keymap.isPrintingKey(keyCode) || keyCode == KeyEvent.KEYCODE_SPACE) {
+ int key = keymap.get(keyCode, event.getMetaState());
+ this.stdin.write(key);
+ return true;
+ }
+
+ // look for special chars
+ switch(keyCode) {
+ case KeyEvent.KEYCODE_DEL: stdin.write(0x08); return true;
+ case KeyEvent.KEYCODE_ENTER: ((vt320)buffer).keyTyped(vt320.KEY_ENTER, ' ', event.getMetaState()); return true;
+ case KeyEvent.KEYCODE_DPAD_LEFT: ((vt320)buffer).keyPressed(vt320.KEY_LEFT, ' ', event.getMetaState()); return true;
+ case KeyEvent.KEYCODE_DPAD_UP: ((vt320)buffer).keyPressed(vt320.KEY_UP, ' ', event.getMetaState()); return true;
+ case KeyEvent.KEYCODE_DPAD_DOWN: ((vt320)buffer).keyPressed(vt320.KEY_DOWN, ' ', event.getMetaState()); return true;
+ case KeyEvent.KEYCODE_DPAD_RIGHT: ((vt320)buffer).keyPressed(vt320.KEY_RIGHT, ' ', event.getMetaState()); return true;
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ public int charWidth = -1,
+ charHeight = -1,
+ charDescent = -1;
+
+ public float fontSize = -1;
+
+ public int scrollback = 120;
+
+ public void setFontSize(float size) {
+ this.defaultPaint.setTextSize(size);
+ this.fontSize = size;
+
+ // read new metrics to get exact pixel dimensions
+ FontMetricsInt fm = this.defaultPaint.getFontMetricsInt();
+ this.charDescent = fm.descent;
+
+ float[] widths = new float[1];
+ this.defaultPaint.getTextWidths("X", widths);
+ this.charWidth = (int)widths[0];
+ this.charHeight = Math.abs(fm.top) + Math.abs(fm.descent);
+
+ // refresh any bitmap with new font size
+ if(this.parent != null)
+ this.parentChanged(this.parent);
+ }
+
+ public boolean fullRedraw = false;
+
+ public synchronized void parentChanged(View parent) {
+
+ this.parent = parent;
+ int width = parent.getWidth();
+ int height = parent.getHeight();
+
+ // reallocate new bitmap if needed
+ boolean newBitmap = (this.bitmap == null);
+ if(this.bitmap != null)
+ newBitmap = (this.bitmap.getWidth() != width || this.bitmap.getHeight() != height);
+ if(newBitmap) {
+ this.bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
+ this.canvas.setBitmap(this.bitmap);
+ }
+
+ // clear out any old buffer information
+ this.defaultPaint.setColor(Color.BLACK);
+ this.canvas.drawRect(0, 0, width, height, this.defaultPaint);
+
+ // recalculate buffer size and update buffer
+ int termWidth = width / charWidth;
+ int termHeight = height / charHeight;
+
+ try {
+ buffer.setScreenSize(termWidth, termHeight, true);
+ session.resizePTY(termWidth, termHeight);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ // force full redraw with new buffer size
+ this.fullRedraw = true;
+ this.redraw();
+
+ Log.d(this.getClass().toString(), "parentChanged() now width=" + termWidth + ", height=" + termHeight);
+ }
+
+ public synchronized void parentDestroyed() {
+ this.parent = null;
+ this.bitmap = null;
+ this.canvas.setBitmap(null);
+ }
+
+ public void setVDUBuffer(VDUBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ public VDUBuffer getVDUBuffer() {
+ return buffer;
+ }
+
+ private int darken(int color) {
+ return Color.argb(0xFF,
+ (int)(Color.red(color) * 0.8),
+ (int)(Color.green(color) * 0.8),
+ (int)(Color.blue(color) * 0.8)
+ );
+ }
+
+ private int color[] = { Color.BLACK, Color.RED, Color.GREEN, Color.YELLOW,
+ Color.BLUE, Color.MAGENTA, Color.CYAN, Color.WHITE, };
+
+ private int darkerColor[] = new int[color.length];
+
+ private final static int COLOR_FG_STD = 7;
+ private final static int COLOR_BG_STD = 0;
+
+ public long lastDraw = 0;
+ public long drawTolerance = 100;
+
+ public synchronized void redraw() {
+ // render our buffer only if we have a surface
+ if(this.parent == null) return;
+
+ long time = System.currentTimeMillis();
+ int lines = 0;
+
+ // only worry about rendering if its been awhile
+ //if(time - lastDraw < drawTolerance) return;
+ //lastDraw = time;
+
+ int fg, bg;
+ boolean entireDirty = buffer.update[0] || this.fullRedraw;
+
+ // walk through all lines in the buffer
+ for(int l = 0; l < buffer.height; l++) {
+
+// if(entireDirty)
+// Log.w("BUFFERDUMP", new String(buffer.charArray[l]));
+
+ // check if this line is dirty and needs to be repainted
+ // also check for entire-buffer dirty flags
+ if(!entireDirty && !buffer.update[l + 1]) continue;
+ lines++;
+
+ // reset dirty flag for this line
+ buffer.update[l + 1] = false;
+
+ // lock this entire row as being dirty
+ //Rect dirty = new Rect(0, l * charHeight, buffer.width * charWidth, (l + 1) * charHeight);
+
+ // walk through all characters in this line
+ for (int c = 0; c < buffer.width; c++) {
+ int addr = 0;
+ int currAttr = buffer.charAttributes[buffer.windowBase + l][c];
+
+ // reset default colors
+ fg = color[COLOR_FG_STD];
+ bg = color[COLOR_BG_STD];
+
+ // check if foreground color attribute is set
+ if((currAttr & VDUBuffer.COLOR_FG) != 0)
+ fg = color[((currAttr & VDUBuffer.COLOR_FG) >> VDUBuffer.COLOR_FG_SHIFT) - 1];
+
+ // check if background color attribute is set
+ if((currAttr & VDUBuffer.COLOR_BG) != 0)
+ bg = darkerColor[((currAttr & VDUBuffer.COLOR_BG) >> VDUBuffer.COLOR_BG_SHIFT) - 1];
+
+ // support character inversion by swapping background and foreground color
+ if ((currAttr & VDUBuffer.INVERT) != 0) {
+ int swapc = bg;
+ bg = fg;
+ fg = swapc;
+ }
+
+ // if black-on-black, try correcting to grey
+ if(fg == Color.BLACK && bg == Color.BLACK)
+ fg = Color.GRAY;
+
+ // correctly set bold and underlined attributes if requested
+ this.defaultPaint.setFakeBoldText((currAttr & VDUBuffer.BOLD) != 0);
+ this.defaultPaint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0);
+
+ // determine the amount of continuous characters with the same settings and print them all at once
+ while(c + addr < buffer.width && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) {
+ addr++;
+ }
+
+ // clear this dirty area with background color
+ this.defaultPaint.setColor(bg);
+ canvas.drawRect(c * charWidth, l * charHeight, (c + addr) * charWidth, (l + 1) * charHeight, this.defaultPaint);
+
+ // write the text string starting at 'c' for 'addr' number of characters
+ this.defaultPaint.setColor(fg);
+ if((currAttr & VDUBuffer.INVISIBLE) == 0)
+ canvas.drawText(buffer.charArray[buffer.windowBase + l], c,
+ addr, c * charWidth, ((l + 1) * charHeight) - charDescent,
+ this.defaultPaint);
+
+ // advance to the next text block with different characteristics
+ c += addr - 1;
+ }
+
+ // unlock this row and update
+ //this.current.unlockCanvasAndPost(canvas);
+ }
+
+ // reset entire-buffer flags
+ buffer.update[0] = false;
+ this.fullRedraw = false;
+
+ // dump out rendering statistics
+ time = System.currentTimeMillis() - time;
+ //Log.d(this.getClass().toString(), "redraw called and updated lines=" + lines + " taking ms=" + time);
+
+ this.parent.postInvalidate();
+
+ }
+
+ public void updateScrollBar() {
+ // TODO Auto-generated method stub
+
+ }
+
+
+
+}
diff --git a/src/org/connectbot/service/TerminalBridgeSurface.java b/src/org/connectbot/service/TerminalBridgeSurface.java
new file mode 100644
index 0000000..3fa0c83
--- /dev/null
+++ b/src/org/connectbot/service/TerminalBridgeSurface.java
@@ -0,0 +1,310 @@
+package org.connectbot.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.theb.ssh.JTATerminalView;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.Paint.FontMetricsInt;
+import android.util.Log;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.SurfaceHolder;
+import android.view.View;
+import android.view.View.OnKeyListener;
+
+import com.trilead.ssh2.Session;
+import com.trilead.ssh2.Connection;
+
+import de.mud.terminal.VDUBuffer;
+import de.mud.terminal.VDUDisplay;
+import de.mud.terminal.vt320;
+
+
+// provides a bridge between the mud buffer and a surfaceholder
+public class TerminalBridgeSurface implements SurfaceHolder.Callback, VDUDisplay, OnKeyListener {
+
+ public final Connection connection;
+ public final Session session;
+
+ public final static int TERM_WIDTH_CHARS = 80,
+ TERM_HEIGHT_CHARS = 24,
+ DEFAULT_FONT_SIZE = 10;
+
+ public final static String ENCODING = "ASCII";
+
+ public final OutputStream stdin;
+ public final InputStream stdout;
+
+ public final Paint defaultPaint;
+
+ public final Thread relay;
+
+ public SurfaceHolder current = null;
+ public VDUBuffer buffer = null;
+
+ public TerminalBridgeSurface(Connection connection) throws Exception {
+ // create a terminal bridge from an SSH connection over to a SurfaceHolder
+ // will open a new session and handle rendering to the Surface if present
+
+ try {
+ this.connection = connection;
+ this.session = connection.openSession();
+ this.session.requestPTY("xterm", TERM_WIDTH_CHARS, TERM_HEIGHT_CHARS, 0, 0, null);
+ this.session.startShell();
+
+ // grab stdin/out from newly formed session
+ this.stdin = this.session.getStdin();
+ this.stdout = this.session.getStdout();
+
+ // create our default paint
+ this.defaultPaint = new Paint();
+ this.defaultPaint.setAntiAlias(true);
+ this.defaultPaint.setTypeface(Typeface.MONOSPACE);
+ this.setFontSize(DEFAULT_FONT_SIZE);
+
+ // create terminal buffer and handle outgoing data
+ // this is probably status reply information
+ this.buffer = new vt320() {
+ public void write(byte[] b) {
+ try {
+ Log.d("STDIN", new String(b));
+ TerminalBridgeSurface.this.stdin.write(b);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void sendTelnetCommand(byte cmd) {
+ }
+
+ public void setWindowSize(int c, int r) {
+ }
+ };
+ this.buffer.setDisplay(this);
+
+ // create thread to relay incoming connection data to buffer
+ this.relay = new Thread(new Runnable() {
+ public void run() {
+ byte[] b = new byte[256];
+ int n = 0;
+ while(n >= 0) {
+ try {
+ n = TerminalBridgeSurface.this.stdout.read(b);
+ if(n > 0) {
+ // pass along data to buffer, then redraw any results
+ ((vt320)TerminalBridgeSurface.this.buffer).putString(new String(b, 0, n, ENCODING));
+ TerminalBridgeSurface.this.redraw();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ break;
+ }
+ }
+ }
+ });
+ this.relay.start();
+
+ } catch(Exception e) {
+ throw e;
+ }
+
+ }
+
+ KeyCharacterMap keymap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
+
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ // pass through any keystrokes to output stream
+ if(event.getAction() == KeyEvent.ACTION_UP) return false;
+ try {
+ int key = keymap.get(keyCode, event.getMetaState());
+ switch(keyCode) {
+ case KeyEvent.KEYCODE_DEL: stdin.write(0x08); break;
+ case KeyEvent.KEYCODE_ENTER: ((vt320)buffer).keyTyped(vt320.KEY_ENTER, ' ', event.getMetaState()); break;
+ case KeyEvent.KEYCODE_DPAD_LEFT: ((vt320)buffer).keyPressed(vt320.KEY_LEFT, ' ', event.getMetaState()); break;
+ case KeyEvent.KEYCODE_DPAD_UP: ((vt320)buffer).keyPressed(vt320.KEY_UP, ' ', event.getMetaState()); break;
+ case KeyEvent.KEYCODE_DPAD_DOWN: ((vt320)buffer).keyPressed(vt320.KEY_DOWN, ' ', event.getMetaState()); break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT: ((vt320)buffer).keyPressed(vt320.KEY_RIGHT, ' ', event.getMetaState()); break;
+ default: this.stdin.write(key);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ public int charWidth = -1,
+ charHeight = -1,
+ charDescent = -1;
+
+ public void setFontSize(float size) {
+ this.defaultPaint.setTextSize(size);
+
+ // read new metrics to get exact pixel dimensions
+ FontMetricsInt fm = this.defaultPaint.getFontMetricsInt();
+ this.charDescent = fm.descent;
+
+ float[] widths = new float[1];
+ this.defaultPaint.getTextWidths("X", widths);
+ this.charWidth = (int)widths[0];
+ this.charHeight = Math.abs(fm.top) + Math.abs(fm.descent);
+
+ // we probably need to resize the viewport with changed size
+ // behave just as if the surface changed to reset buffer size
+ this.surfaceChanged(this.current, -1, -1, -1);
+ }
+
+ public boolean newSurface = false;
+
+ public synchronized void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+
+ // mark that we need the entire surface repainted
+ this.current = holder;
+ this.newSurface = true;
+
+ if(this.current == null) return;
+
+ // resize the underlying buffer as needed
+ Rect size = this.current.getSurfaceFrame();
+ int termWidth = size.width() / charWidth;
+ int termHeight = size.height() / charHeight;
+
+ buffer.setScreenSize(termWidth, termHeight, true);
+ buffer.height = termHeight; // TODO: is this really needed?
+
+ Log.d(this.getClass().toString(), "surfaceChanged() now width=" + termWidth + ", height=" + termHeight);
+ this.redraw();
+
+ }
+
+ public synchronized void surfaceCreated(SurfaceHolder holder) {
+ // someone created our Surface, so resize terminal as needed and repaint
+ // we handle this just like we would a changing surface
+ this.surfaceChanged(holder, -1, -1, -1);
+
+ }
+
+ public synchronized void surfaceDestroyed(SurfaceHolder holder) {
+ this.current = null;
+ this.newSurface = false;
+
+ }
+
+
+ public void setVDUBuffer(VDUBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ public VDUBuffer getVDUBuffer() {
+ return buffer;
+ }
+
+ private int color[] = { Color.BLACK, Color.RED, Color.GREEN, Color.YELLOW,
+ Color.BLUE, Color.MAGENTA, Color.CYAN, Color.WHITE, };
+
+ private int darkerColor[] = color;
+
+ private final static int COLOR_FG_STD = 7;
+ private final static int COLOR_BG_STD = 0;
+
+ public void redraw() {
+ // render our buffer only if we have a surface
+ if(this.current == null) return;
+
+ long time = System.currentTimeMillis();
+ int lines = 0;
+
+ int fg, bg;
+ boolean entireDirty = buffer.update[0] || newSurface;
+
+ // walk through all lines in the buffer
+ for(int l = 0; l < buffer.height; l++) {
+
+ // check if this line is dirty and needs to be repainted
+ // also check for entire-buffer dirty flags
+ if(!entireDirty && !buffer.update[l + 1]) continue;
+ lines++;
+
+ // reset dirty flag for this line
+ buffer.update[l + 1] = false;
+
+ // lock this entire row as being dirty
+ Rect dirty = new Rect(0, l * charHeight, buffer.width * charWidth, (l + 1) * charHeight);
+ Canvas canvas = this.current.lockCanvas(dirty);
+
+ // walk through all characters in this line
+ for (int c = 0; c < buffer.width; c++) {
+ int addr = 0;
+ int currAttr = buffer.charAttributes[buffer.windowBase + l][c];
+
+ // reset default colors
+ fg = color[COLOR_FG_STD];
+ bg = color[COLOR_BG_STD];
+
+ // check if foreground color attribute is set
+ if((currAttr & VDUBuffer.COLOR_FG) != 0)
+ fg = color[((currAttr & VDUBuffer.COLOR_FG) >> VDUBuffer.COLOR_FG_SHIFT) - 1];
+
+ // check if background color attribute is set
+ if((currAttr & VDUBuffer.COLOR_BG) != 0)
+ bg = darkerColor[((currAttr & VDUBuffer.COLOR_BG) >> VDUBuffer.COLOR_BG_SHIFT) - 1];
+
+ // support character inversion by swapping background and foreground color
+ if ((currAttr & VDUBuffer.INVERT) != 0) {
+ int swapc = bg;
+ bg = fg;
+ fg = swapc;
+ }
+
+ // correctly set bold and underlined attributes if requested
+ this.defaultPaint.setFakeBoldText((currAttr & VDUBuffer.BOLD) != 0);
+ this.defaultPaint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0);
+
+ // determine the amount of continuous characters with the same settings and print them all at once
+ while(c + addr < buffer.width && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) {
+ addr++;
+ }
+
+ // clear this dirty area with background color
+ this.defaultPaint.setColor(bg);
+ canvas.drawRect(c * charWidth, l * charHeight, (c + addr) * charWidth, (l + 1) * charHeight, this.defaultPaint);
+
+ // write the text string starting at 'c' for 'addr' number of characters
+ this.defaultPaint.setColor(fg);
+ if((currAttr & VDUBuffer.INVISIBLE) == 0)
+ canvas.drawText(buffer.charArray[buffer.windowBase + l], c,
+ addr, c * charWidth, ((l + 1) * charHeight) - charDescent,
+ this.defaultPaint);
+
+ // advance to the next text block with different characteristics
+ c += addr - 1;
+ }
+
+ // unlock this row and update
+ this.current.unlockCanvasAndPost(canvas);
+ }
+
+ // reset entire-buffer flags
+ buffer.update[0] = false;
+ this.newSurface = false;
+
+ // dump out rendering statistics
+ time = System.currentTimeMillis() - time;
+ Log.d(this.getClass().toString(), "redraw called and updated lines=" + lines + " taking ms=" + time);
+
+ }
+
+ public void updateScrollBar() {
+ // TODO Auto-generated method stub
+
+ }
+
+
+
+}
diff --git a/src/org/connectbot/service/TerminalManager.java b/src/org/connectbot/service/TerminalManager.java
new file mode 100644
index 0000000..72203ba
--- /dev/null
+++ b/src/org/connectbot/service/TerminalManager.java
@@ -0,0 +1,81 @@
+package org.connectbot.service;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.theb.ssh.InteractiveHostKeyVerifier;
+
+import com.trilead.ssh2.Connection;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Log;
+
+public class TerminalManager extends Service {
+
+ public List<TerminalBridge> bridges = new LinkedList<TerminalBridge>();
+ public TerminalBridge defaultBridge = null;
+
+ @Override
+ public void onCreate() {
+ Log.w(this.getClass().toString(), "onCreate()");
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.w(this.getClass().toString(), "onDestroy()");
+ // disconnect and dispose of any bridges
+ for(TerminalBridge bridge : bridges)
+ bridge.dispose();
+ }
+
+ public void openConnection(Connection conn, String nickname, String emulation, int scrollback) throws Exception {
+ try {
+ TerminalBridge bridge = new TerminalBridge(conn, nickname, emulation, scrollback);
+ this.bridges.add(bridge);
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+
+ public void openConnection(String nickname, String host, int port, String user, String pass, String emulation, int scrollback) throws Exception {
+ try {
+ Connection conn = new Connection(host, port);
+ conn.connect(new InteractiveHostKeyVerifier());
+ if(conn.isAuthMethodAvailable(user, "password")) {
+ conn.authenticateWithPassword(user, pass);
+ }
+ TerminalBridge bridge = new TerminalBridge(conn, nickname, emulation, scrollback);
+ this.bridges.add(bridge);
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+
+ public TerminalBridge findBridge(String nickname) {
+ // find the first active bridge with given nickname
+ for(TerminalBridge bridge : bridges) {
+ if(bridge.overlay.equals(nickname))
+ return bridge;
+ }
+ return null;
+ }
+
+
+ public class TerminalBinder extends Binder {
+ public TerminalManager getService() {
+ return TerminalManager.this;
+ }
+ }
+
+ private final IBinder binder = new TerminalBinder();
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.w(this.getClass().toString(), "onBind()");
+ return binder;
+ }
+
+}
diff --git a/src/org/theb/provider/HostDb.java b/src/org/theb/provider/HostDb.java
index 3a15c8f..1ed7c0c 100644
--- a/src/org/theb/provider/HostDb.java
+++ b/src/org/theb/provider/HostDb.java
@@ -27,11 +27,14 @@ public final class HostDb {
public static final Uri CONTENT_URI
= Uri.parse("content://org.theb.provider.HostDb/hosts");
- public static final String DEFAULT_SORT_ORDER = "hostname DESC";
+ public static final String DEFAULT_SORT_ORDER = "nickname DESC";
+ public static final String NICKNAME = "nickname";
public static final String USERNAME = "username";
public static final String HOSTNAME = "hostname";
public static final String PORT = "port";
+ public static final String EMULATION = "emulation";
+ public static final String SCROLLBACK = "scrollback";
public static final String HOSTKEY = "hostkey";
}
}
diff --git a/src/org/theb/ssh/HostDbProvider.java b/src/org/theb/ssh/HostDbProvider.java
index ecb0eed..f3bdbd5 100644
--- a/src/org/theb/ssh/HostDbProvider.java
+++ b/src/org/theb/ssh/HostDbProvider.java
@@ -43,7 +43,7 @@ public class HostDbProvider extends ContentProvider {
private static final String TAG = "HostDbProvider";
private static final String DATABASE_NAME = "ssh_hosts.db";
- private static final int DATABASE_VERSION = 2;
+ private static final int DATABASE_VERSION = 3;
private static HashMap<String, String> HOSTS_LIST_PROJECTION_MAP;
@@ -61,9 +61,15 @@ public class HostDbProvider extends ContentProvider {
@Override
public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE hosts (_id INTEGER PRIMARY KEY,"
- + "hostname TEXT," + "username TEXT," + "port INTEGER,"
- + "hostkey TEXT" + ")");
+ db.execSQL("CREATE TABLE hosts (_id INTEGER PRIMARY KEY," +
+ "nickname TEXT," +
+ "hostname TEXT," +
+ "username TEXT," +
+ "port INTEGER," +
+ "emulation TEXT," +
+ "scrollback INTEGER," +
+ "hostkey TEXT" +
+ ")");
}
@Override
@@ -127,6 +133,10 @@ public class HostDbProvider extends ContentProvider {
throw new IllegalArgumentException("Unknown Insert " + uri);
}
*/
+ if (values.containsKey(HostDb.Hosts.NICKNAME) == false) {
+ values.put(HostDb.Hosts.NICKNAME, "");
+ }
+
if (values.containsKey(HostDb.Hosts.HOSTNAME) == false) {
values.put(HostDb.Hosts.HOSTNAME, "");
}
@@ -143,6 +153,14 @@ public class HostDbProvider extends ContentProvider {
values.put(HostDb.Hosts.HOSTKEY, "");
}
+ if (values.containsKey(HostDb.Hosts.EMULATION) == false) {
+ values.put(HostDb.Hosts.EMULATION, "");
+ }
+
+ if (values.containsKey(HostDb.Hosts.SCROLLBACK) == false) {
+ values.put(HostDb.Hosts.SCROLLBACK, "");
+ }
+
rowID = mDB.insert("hosts", "host", values);
if (rowID > 0) {
Uri newUri = ContentUris.withAppendedId(HostDb.Hosts.CONTENT_URI, rowID);
@@ -228,9 +246,12 @@ public class HostDbProvider extends ContentProvider {
HOSTS_LIST_PROJECTION_MAP = new HashMap<String, String>();
HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts._ID, "_id");
+ HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts.NICKNAME, "nickname");
HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts.HOSTNAME, "hostname");
HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts.USERNAME, "username");
HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts.PORT, "port");
HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts.HOSTKEY, "hostkey");
+ HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts.EMULATION, "emulation");
+ HOSTS_LIST_PROJECTION_MAP.put(HostDb.Hosts.SCROLLBACK, "scrollback");
}
}
diff --git a/src/org/theb/ssh/HostEditor.java b/src/org/theb/ssh/HostEditor.java
index d9618eb..ed0d101 100644
--- a/src/org/theb/ssh/HostEditor.java
+++ b/src/org/theb/ssh/HostEditor.java
@@ -18,6 +18,7 @@
*/
package org.theb.ssh;
+import org.theb.ssh.R;
import org.theb.provider.HostDb;
import android.app.Activity;
@@ -31,29 +32,26 @@ import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.Spinner;
public class HostEditor extends Activity {
- public static final String EDIT_HOST_ACTION =
- "com.theb.ssh.action.EDIT_HOST";
+ public static final String EDIT_HOST_ACTION = "com.theb.ssh.action.EDIT_HOST";
- private static final String[] PROJECTION = new String[] {
- HostDb.Hosts._ID, // 0
- HostDb.Hosts.HOSTNAME, // 1
- HostDb.Hosts.USERNAME, // 2
- HostDb.Hosts.PORT, // 3
- HostDb.Hosts.HOSTKEY, // 4
- };
+ private static final String[] PROJECTION = new String[] { HostDb.Hosts._ID,
+ HostDb.Hosts.NICKNAME, HostDb.Hosts.HOSTNAME,
+ HostDb.Hosts.USERNAME, HostDb.Hosts.PORT, HostDb.Hosts.EMULATION,
+ HostDb.Hosts.SCROLLBACK, };
+
+ private static final int INDEX_NICKNAME = 1, INDEX_HOSTNAME = 2,
+ INDEX_USERNAME = 3, INDEX_PORT = 4, INDEX_EMULATION = 5,
+ INDEX_SCROLLBACK = 6;
- static final int HOSTNAME_INDEX = 1;
- private static final int USERNAME_INDEX = 2;
- private static final int PORT_INDEX = 3;
// Set up distinct states that the activity can be run in.
private static final int STATE_EDIT = 0;
private static final int STATE_INSERT = 1;
- private EditText mHostname;
- private EditText mUsername;
- private EditText mPort;
+ private EditText mNickname, mHostname, mUsername, mPort, mScrollback;
+ private Spinner mEmulation;
// Cursor that will provide access to the host data we are editing
private Cursor mCursor;
@@ -64,37 +62,20 @@ public class HostEditor extends Activity {
@Override
public void onCreate(Bundle savedValues) {
super.onCreate(savedValues);
-
- // TODO: update or remove
- // Have the system blur any windows behind this one.
- //getWindow().setFlags(WindowManager.LayoutParams.BLUR_BEHIND_FLAG,
- // WindowManager.LayoutParams.BLUR_BEHIND_FLAG);
-
- // Apply a tint to any windows behind this one. Doing a tint this
- // way is more efficient than using a translucent background. Note
- // that the tint color really should come from a resource.
- WindowManager.LayoutParams lp = getWindow().getAttributes();
- //lp.tintBehind = 0x60000820;
- getWindow().setAttributes(lp);
-
- this.setContentView(R.layout.host_editor);
+ this.setContentView(R.layout.act_hosteditor);
// Set up click handlers for text fields and button
- mHostname = (EditText) findViewById(R.id.hostname);
- mUsername = (EditText) findViewById(R.id.username);
- mPort = (EditText) findViewById(R.id.port);
-
- Button addButton = (Button) findViewById(R.id.add);
- addButton.setOnClickListener(mCommitListener);
-
- Button cancelButton = (Button) findViewById(R.id.cancel);
- cancelButton.setOnClickListener(mCancelListener);
-
- final Intent intent = getIntent();
+ this.mNickname = (EditText) findViewById(R.id.edit_nickname);
+ this.mHostname = (EditText) findViewById(R.id.edit_hostname);
+ this.mUsername = (EditText) findViewById(R.id.edit_username);
+ this.mPort = (EditText) findViewById(R.id.edit_port);
+ this.mEmulation = (Spinner) findViewById(R.id.edit_emulation);
+ this.mScrollback = (EditText) findViewById(R.id.edit_scrollback);
// Do some setup based on the action being performed.
-
+ final Intent intent = getIntent();
final String action = intent.getAction();
+
if (Intent.ACTION_INSERT.equals(action)) {
mState = STATE_INSERT;
mURI = getContentResolver().insert(intent.getData(), null);
@@ -103,8 +84,7 @@ public class HostEditor extends Activity {
// this activity. A RESULT_CANCELED will be sent back to the
// original activity if they requested a result.
if (mURI == null) {
- Log.e("Notes", "Failed to insert new note into "
- + getIntent().getData());
+ Log.e("Notes", "Failed to insert new note into " + getIntent().getData());
finish();
return;
}
@@ -119,13 +99,10 @@ public class HostEditor extends Activity {
// Get the URI of the host whose properties we want to edit
mURI = getIntent().getData();
-
- // If were editing, change the Ok button to be Change instead.
- addButton.setText(R.string.button_change);
}
// Get a cursor to access the host data
- mCursor = managedQuery(mURI, PROJECTION, null, null);
+ this.mCursor = managedQuery(mURI, PROJECTION, null, null);
}
@Override
@@ -133,17 +110,16 @@ public class HostEditor extends Activity {
super.onResume();
// Initialize the text with the host data
- if (mCursor != null) {
+ if(mCursor != null) {
mCursor.moveToFirst();
- String hostname = mCursor.getString(HOSTNAME_INDEX);
- mHostname.setText(hostname);
-
- String username = mCursor.getString(USERNAME_INDEX);
- mUsername.setText(username);
+ this.mNickname.setText(mCursor.getString(this.INDEX_NICKNAME));
+ this.mHostname.setText(mCursor.getString(this.INDEX_HOSTNAME));
+ this.mUsername.setText(mCursor.getString(this.INDEX_USERNAME));
+ this.mPort.setText(mCursor.getString(this.INDEX_PORT));
+ //this.emulation.setText(cursor.getString(this.INDEX_EMULATION));
+ this.mScrollback.setText(mCursor.getString(this.INDEX_SCROLLBACK));
- String port = mCursor.getString(PORT_INDEX);
- mPort.setText(port);
}
}
@@ -152,17 +128,24 @@ public class HostEditor extends Activity {
super.onPause();
// Write the text back into the cursor
- if (mCursor != null) {
+ if(mCursor != null) {
+ String nickname = mNickname.getText().toString();
+ mCursor.updateString(INDEX_NICKNAME, nickname);
+
String hostname = mHostname.getText().toString();
- mCursor.updateString(HOSTNAME_INDEX, hostname);
+ mCursor.updateString(INDEX_HOSTNAME, hostname);
String username = mUsername.getText().toString();
- mCursor.updateString(USERNAME_INDEX, username);
+ mCursor.updateString(INDEX_USERNAME, username);
String portStr = mPort.getText().toString();
int port = Integer.parseInt(portStr);
- mCursor.updateInt(PORT_INDEX, port);
+ mCursor.updateInt(INDEX_PORT, port);
+ String scrollbackStr = mScrollback.getText().toString();
+ int scrollback = Integer.parseInt(scrollbackStr);
+ mCursor.updateInt(INDEX_SCROLLBACK, scrollback);
+
if (isFinishing()
&& ((hostname.length() == 0)
|| (username.length() == 0)
@@ -197,18 +180,4 @@ public class HostEditor extends Activity {
}
}
- OnClickListener mCommitListener = new OnClickListener() {
- public void onClick(View v) {
- // When the user clicks, just finish this activity.
- // onPause will be called, and we save our data there.
- finish();
- }
- };
-
- OnClickListener mCancelListener = new OnClickListener() {
- public void onClick(View v) {
- cancelEdit();
- finish();
- }
- };
}
diff --git a/src/org/theb/ssh/HostsList.java b/src/org/theb/ssh/HostsList.java
index fc62baf..703d09c 100644
--- a/src/org/theb/ssh/HostsList.java
+++ b/src/org/theb/ssh/HostsList.java
@@ -18,18 +18,27 @@
*/
package org.theb.ssh;
+import org.connectbot.Console;
+import org.connectbot.service.TerminalBridge;
+import org.connectbot.service.TerminalManager;
+import org.theb.ssh.R;
import org.theb.provider.HostDb;
+import com.trilead.ssh2.Connection;
+
import android.app.Dialog;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
@@ -55,6 +64,7 @@ public class HostsList extends ListActivity {
HostDb.Hosts.HOSTNAME,
HostDb.Hosts.USERNAME,
HostDb.Hosts.PORT,
+ HostDb.Hosts.NICKNAME
};
private Cursor mCursor;
@@ -78,26 +88,59 @@ public class HostsList extends ListActivity {
String label;
TextView textView = (TextView) view;
- label = cursor.getString(2)
- + "@"
- + cursor.getString(1);
-
- int port = cursor.getInt(3);
- if (port != 22) {
- label = label + ":" + String.valueOf(port);
- }
+// label = cursor.getString(2) + "@" + cursor.getString(1);
+// int port = cursor.getInt(3);
+// if (port != 22) {
+// label = label + ":" + String.valueOf(port);
+// }
+ label = cursor.getString(4);
textView.setText(label);
}
}
+
+
+
+
+ public TerminalManager bound = null;
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Log.d(this.getClass().toString(), "yay we bound to our terminalmanager");
+ bound = ((TerminalManager.TerminalBinder) service).getService();
+
+ // TODO: update our green bulb icons by checking for existing bridges
+ // open up some test sessions
+// try {
+// bound.openConnection("192.168.254.230", 22, "connectbot", "b0tt", "screen", 100);
+// bound.openConnection("192.168.254.230", 22, "connectbot", "b0tt", "screen", 100);
+// bound.openConnection("192.168.254.230", 22, "connectbot", "b0tt", "screen", 100);
+// } catch(Exception e) {
+// e.printStackTrace();
+// }
+
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ Log.d(this.getClass().toString(), "oops our terminalmanager was lost");
+ bound = null;
+ }
+ };
+
+
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
+ // start the terminal manager service and bind locally
+ this.startService(new Intent(this, TerminalManager.class));
+ this.bindService(new Intent(this, TerminalManager.class), connection, Context.BIND_AUTO_CREATE);
+
+
+ //setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
Intent intent = getIntent();
if (intent.getData() == null) {
@@ -267,7 +310,42 @@ public class HostsList extends ListActivity {
setResult(RESULT_OK, intent);
} else {
// Launch activity to view/edit the currently selected item
- startActivity(new Intent(Intent.ACTION_PICK, url));
+ //startActivity(new Intent(Intent.ACTION_PICK, url));
+
+ // collect all connection details
+ Cursor cursor = managedQuery(url, new String[] { "nickname",
+ "username", "hostname", "port", "emulation", "scrollback",
+ "hostkey" }, null, null);
+ cursor.moveToFirst();
+
+ // try finding an already-open bridge for this connection
+ String nickname = cursor.getString(0);
+ TerminalBridge bridge = bound.findBridge(nickname);
+ if(bridge == null) {
+ // too bad, looks like we have to open the bridge ourselves
+ String username = cursor.getString(1);
+ String hostname = cursor.getString(2);
+ int port = cursor.getInt(3);
+ String emulation = cursor.getString(4);
+ int scrollback = cursor.getInt(5);
+ String hostkey = cursor.getString(6);
+
+ try {
+ //Connection conn;
+ //bound.openConnection(conn, nickname, emulation, scrollback);
+ bound.openConnection(nickname, hostname, port, username, "moocow", "screen", 100);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+
+ }
+
+ // open the console view and select this specific terminal
+ Intent intent = new Intent(this, Console.class);
+ intent.putExtra(Intent.EXTRA_TEXT, nickname);
+ this.startActivity(intent);
+
}
}
diff --git a/src/org/theb/ssh/PasswordDialog.java b/src/org/theb/ssh/PasswordDialog.java
index 91da6b0..adcca36 100644
--- a/src/org/theb/ssh/PasswordDialog.java
+++ b/src/org/theb/ssh/PasswordDialog.java
@@ -18,6 +18,8 @@
*/
package org.theb.ssh;
+import org.theb.ssh.R;
+
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
diff --git a/src/org/theb/ssh/Pubkey.java b/src/org/theb/ssh/Pubkey.java
index 9dffe08..95abba7 100644
--- a/src/org/theb/ssh/Pubkey.java
+++ b/src/org/theb/ssh/Pubkey.java
@@ -26,6 +26,8 @@ import java.security.SecureRandom;
import java.security.Security;
import java.util.concurrent.Semaphore;
+import org.theb.ssh.R;
+
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
diff --git a/src/org/theb/ssh/SecureShell.java b/src/org/theb/ssh/SecureShell.java
index 68738f0..e2bb4f4 100644
--- a/src/org/theb/ssh/SecureShell.java
+++ b/src/org/theb/ssh/SecureShell.java
@@ -21,6 +21,7 @@ package org.theb.ssh;
import java.io.IOException;
import java.io.OutputStream;
+import org.theb.ssh.R;
import org.theb.provider.HostDb;
import com.trilead.ssh2.ConnectionMonitor;
diff --git a/src/org/theb/ssh/TouchEntropy.java b/src/org/theb/ssh/TouchEntropy.java
index bf2d737..fc633b0 100644
--- a/src/org/theb/ssh/TouchEntropy.java
+++ b/src/org/theb/ssh/TouchEntropy.java
@@ -1,5 +1,7 @@
package org.theb.ssh;
+import org.theb.ssh.R;
+
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
diff --git a/src/org/theb/ssh/TrileadConnectionThread.java b/src/org/theb/ssh/TrileadConnectionThread.java
index 1e51afc..b874756 100644
--- a/src/org/theb/ssh/TrileadConnectionThread.java
+++ b/src/org/theb/ssh/TrileadConnectionThread.java
@@ -41,12 +41,12 @@ public class TrileadConnectionThread extends ConnectionThread {
private Semaphore sPass;
- protected FeedbackUI ui;
+ //protected FeedbackUI ui;
protected Terminal term;
public TrileadConnectionThread(FeedbackUI ui, Terminal term, String hostname, String username, int port) {
super(ui, hostname, username, port);
- this.ui = ui;
+ //this.ui = ui;
this.term = term;
this.hostname = hostname;
this.username = username;
@@ -80,14 +80,13 @@ public class TrileadConnectionThread extends ConnectionThread {
public void run() {
connection = new Connection(hostname, port);
- connection.addConnectionMonitor((ConnectionMonitor) ui);
-
- ui.setWaiting(true, "Connection", "Connecting to " + hostname + "...");
+ //connection.addConnectionMonitor((ConnectionMonitor) ui);
+ //ui.setWaiting(true, "Connection", "Connecting to " + hostname + "...");
try {
connection.connect(new InteractiveHostKeyVerifier());
- ui.setWaiting(true, "Authenticating", "Trying to authenticate...");
+ //ui.setWaiting(true, "Authenticating", "Trying to authenticate...");
// boolean enableKeyboardInteractive = true;
// boolean enableDSA = true;
@@ -100,21 +99,21 @@ public class TrileadConnectionThread extends ConnectionThread {
*/
if (connection.isAuthMethodAvailable(username, "password")) {
- ui.setWaiting(true, "Authenticating",
- "Trying to authenticate using password...");
+ //ui.setWaiting(true, "Authenticating","Trying to authenticate using password...");
// Set a semaphore that is unset by the returning dialog.
- sPass = new Semaphore(0);
- ui.askPassword();
-
- // Wait for the user to answer.
- sPass.acquire();
- sPass = null;
- if (password == null)
- continue;
-
- boolean res = connection.authenticateWithPassword(username,
- password);
+// sPass = new Semaphore(0);
+// ui.askPassword();
+//
+// // Wait for the user to answer.
+// sPass.acquire();
+// sPass = null;
+// if (password == null)
+// continue;
+
+ password = "b0tt";
+
+ boolean res = connection.authenticateWithPassword(username, password);
password = null;
if (res == true)
break;
@@ -126,7 +125,7 @@ public class TrileadConnectionThread extends ConnectionThread {
"No supported authentication methods available.");
}
- ui.setWaiting(true, "Session", "Requesting shell...");
+ //ui.setWaiting(true, "Session", "Requesting shell...");
session = connection.openSession();
@@ -141,12 +140,9 @@ public class TrileadConnectionThread extends ConnectionThread {
// stderr = session.getStderr();
stdOut = session.getStdout();
- ui.setWaiting(false, null, null);
+ //ui.setWaiting(false, null, null);
} catch (IOException e) {
- ui.setWaiting(false, null, null);
- return;
- } catch (InterruptedException e) {
- // This thread is coming to an end. Let us exit.
+ //ui.setWaiting(false, null, null);
return;
}