diff options
| -rw-r--r-- | res/values/strings.xml | 1 | ||||
| -rw-r--r-- | src/org/theb/ssh/HostsList.java | 17 | ||||
| -rw-r--r-- | src/org/theb/ssh/R.java | 57 | ||||
| -rw-r--r-- | src/org/theb/ssh/SecureShell.java | 150 | 
4 files changed, 100 insertions, 125 deletions
| diff --git a/res/values/strings.xml b/res/values/strings.xml index b9531d8..75c16ae 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12,6 +12,7 @@      <string name="menu_insert">Add Host</string>      <string name="menu_delete">Delete Host</string> +    <string name="menu_preferences">Preferences</string>      <string name="menu_about">About</string>      <string name="button_ok">Ok</string> diff --git a/src/org/theb/ssh/HostsList.java b/src/org/theb/ssh/HostsList.java index da994d6..4d9e398 100644 --- a/src/org/theb/ssh/HostsList.java +++ b/src/org/theb/ssh/HostsList.java @@ -24,7 +24,8 @@ import android.widget.TextView;  public class HostsList extends ListActivity {  	public static final int DELETE_ID = Menu.FIRST;  	public static final int INSERT_ID = Menu.FIRST + 1; -	public static final int ABOUT_ID = Menu.FIRST + 2; +	public static final int PREFERENCES_ID = Menu.FIRST + 2; +	public static final int ABOUT_ID = Menu.FIRST + 3;  	private static final String[] PROJECTION = new String[] {  		HostDb.Hosts._ID, @@ -124,6 +125,10 @@ public class HostsList extends ListActivity {          menu.add(0, INSERT_ID, R.string.menu_insert).setShortcut(                  KeyEvent.KEYCODE_3, 0, KeyEvent.KEYCODE_A); +        // The preferences link allows users to e.g. set the pubkey +        menu.add(0, PREFERENCES_ID, R.string.menu_preferences).setShortcut( +        		KeyEvent.KEYCODE_4, 0, KeyEvent.KEYCODE_P); +                  // This links to the about dialog for the program.          menu.add(0, ABOUT_ID, R.string.menu_about); @@ -193,6 +198,9 @@ public class HostsList extends ListActivity {          case INSERT_ID:              insertItem();              return true; +        case PREFERENCES_ID: +        	showPreferences(); +        	return true;          case ABOUT_ID:          	showAbout();          	return true; @@ -200,7 +208,12 @@ public class HostsList extends ListActivity {          return super.onOptionsItemSelected(item);      } -    private void showAbout() { +    private void showPreferences() { +		// TODO Auto-generated method stub +		 +	} + +	private void showAbout() {  		Dialog about = new Dialog(this);  		about.setContentView(R.layout.about_dialog);  		about.setTitle(getResources().getString(R.string.app_name) diff --git a/src/org/theb/ssh/R.java b/src/org/theb/ssh/R.java deleted file mode 100644 index 55e280c..0000000 --- a/src/org/theb/ssh/R.java +++ /dev/null @@ -1,57 +0,0 @@ -/* AUTO-GENERATED FILE.  DO NOT MODIFY. - * - * This class was automatically generated by the - * aapt tool from the resource data it found.  It - * should not be modified by hand. - */ - -package org.theb.ssh; - -public final class R { -    public static final class attr { -    } -    public static final class drawable { -        public static final int blue=0x7f020001; -        public static final int even_stripe=0x7f020002; -        public static final int icon=0x7f020000; -        public static final int odd_stripe=0x7f020003; -    } -    public static final class id { -        public static final int add=0x7f050006; -        public static final int cancel=0x7f050007; -        public static final int dismiss=0x7f05000a; -        public static final int hostname=0x7f050003; -        public static final int hostnameLabel=0x7f050002; -        public static final int message=0x7f050009; -        public static final int ok=0x7f05000d; -        public static final int output=0x7f05000e; -        public static final int password=0x7f05000c; -        public static final int passwordLabel=0x7f05000b; -        public static final int port=0x7f050005; -        public static final int portLabel=0x7f050004; -        public static final int shell=0x7f050008; -        public static final int username=0x7f050001; -        public static final int usernameLabel=0x7f050000; -    } -    public static final class layout { -        public static final int host_editor=0x7f030000; -        public static final int main=0x7f030001; -        public static final int message_dialog=0x7f030002; -        public static final int password_dialog=0x7f030003; -        public static final int secure_shell=0x7f030004; -    } -    public static final class string { -        public static final int app_name=0x7f040000; -        public static final int button_add=0x7f040009; -        public static final int button_cancel=0x7f04000a; -        public static final int button_change=0x7f04000b; -        public static final int button_ok=0x7f040008; -        public static final int menu_delete=0x7f040007; -        public static final int menu_insert=0x7f040006; -        public static final int resolve_edit=0x7f040005; -        public static final int title_host=0x7f040002; -        public static final int title_hosts_list=0x7f040001; -        public static final int title_password=0x7f040004; -        public static final int title_shell=0x7f040003; -    } -} diff --git a/src/org/theb/ssh/SecureShell.java b/src/org/theb/ssh/SecureShell.java index 2ec8029..31625f9 100644 --- a/src/org/theb/ssh/SecureShell.java +++ b/src/org/theb/ssh/SecureShell.java @@ -8,8 +8,8 @@ import java.util.concurrent.Semaphore;  import org.theb.provider.HostDb;  import android.app.Activity; -import android.app.Dialog; -import android.content.Context; +import android.app.AlertDialog; +import android.app.ProgressDialog;  import android.content.Intent;  import android.database.Cursor;  import android.os.Bundle; @@ -17,18 +17,15 @@ import android.os.Handler;  import android.text.method.KeyCharacterMap;  import android.util.Log;  import android.view.KeyEvent; -import android.view.View;  import android.view.Window; -import android.view.View.OnClickListener; -import android.widget.Button;  import android.widget.TextView; +import com.trilead.ssh2.ChannelCondition;  import com.trilead.ssh2.Connection;  import com.trilead.ssh2.ConnectionMonitor;  import com.trilead.ssh2.Session;  public class SecureShell extends Activity { -	private Context mContext;  	private TextView mOutput;  	private ConnectionThread mConn;  	private String mBuffer; @@ -54,16 +51,24 @@ public class SecureShell extends Activity {  	private String mUsername;  	private int mPort; -	// This is the toggle for the original thread to release the indeterminate waiting graphic. +	// The toggle for the original thread to release the indeterminate waiting graphic. +	private ProgressDialog progress;  	private boolean mIsWaiting; +	private String mWaitingTitle; +	private String mWaitingMessage; +	 +	// Connection lost reason. +	private String mDisconnectReason; +	  	// This is for the password dialog.  	Semaphore sPass;  	String mPassword = null;  	Connection conn;  	Session sess; -	InputStream in; -	OutputStream out; +	InputStream stdin; +	InputStream stderr; +	OutputStream stdout;  	int x;  	int y; @@ -95,23 +100,22 @@ public class SecureShell extends Activity {  			conn.addConnectionMonitor(mConnectionMonitor); -			setWaiting(true); -			mHandler.post(mUpdateWaiting); +            setWaiting(true, "Connection", +            		"Connecting to " + hostname + "...");  			Log.d("SSH", "Starting connection attempt..."); -			mBuffer =  "Attemping to connect..."; -			mHandler.post(mUpdateView);  	        try {  				conn.connect(new InteractiveHostKeyVerifier()); +				setWaiting(true, "Authenticating", +						"Trying to authenticate..."); +				  				Log.d("SSH", "Starting authentication..."); -				mBuffer =  "Attemping to authenticate..."; -				mHandler.post(mUpdateView); -				boolean enableKeyboardInteractive = true; -				boolean enableDSA = true; -				boolean enableRSA = true; +//				boolean enableKeyboardInteractive = true; +//				boolean enableDSA = true; +//				boolean enableRSA = true;  				while (true) {  					/* @@ -121,6 +125,8 @@ public class SecureShell extends Activity {  					if (conn.isAuthMethodAvailable(username, "password")) {  						Log.d("SSH", "Trying password authentication..."); +						setWaiting(true, "Authenticating", +								"Trying to authenticate using password...");  						// Set a semaphore that is unset by the returning dialog.  						sPass = new Semaphore(0); @@ -143,8 +149,7 @@ public class SecureShell extends Activity {  				}  				Log.d("SSH", "Opening session..."); -				mBuffer =  "Opening session..."; -				mHandler.post(mUpdateView); +				setWaiting(true, "Session", "Requesting shell...");  				sess = conn.openSession(); @@ -158,15 +163,14 @@ public class SecureShell extends Activity {  				Log.d("SSH", "Requesting shell...");  				sess.startShell(); -				out = sess.getStdin(); -				in = sess.getStdout(); +				stdout = sess.getStdin(); +				stderr = sess.getStderr(); +				stdin = sess.getStdout(); -				setWaiting(false); -				mHandler.post(mUpdateWaiting); -				 +				setWaiting(false, null, null);  			} catch (IOException e) {  				Log.e("SSH", e.getMessage()); -				mConnectionMonitor.connectionLost(e); +				setWaiting(false, null, null);  				return;  			} catch (InterruptedException e) {  				// This thread is coming to an end. Let us exit. @@ -179,10 +183,28 @@ public class SecureShell extends Activity {  			try {  				while (true) { -					int len = in.read(buff); -					if (len == -1) -						return; -					addText(buff, len); +					if ((stdin.available() == 0) && (stderr.available() == 0)) { +						int conditions = sess.waitForCondition( +								ChannelCondition.STDOUT_DATA +								| ChannelCondition.STDERR_DATA +								| ChannelCondition.EOF, 2000); +						if ((conditions & ChannelCondition.TIMEOUT) != 0) +							continue; +						if ((conditions & ChannelCondition.EOF) != 0) +							if ((conditions & +									(ChannelCondition.STDERR_DATA +											| ChannelCondition.STDOUT_DATA)) == 0) +								break; +					} +					 +					if (stdin.available() > 0) { +						int len = stdin.read(buff); +						addText(buff, len); +					} +					if (stderr.available() > 0) { +						int len = stderr.read(buff); +						addText(buff, len); +					}  				}  			} catch (Exception e) {  				Log.e("SSH", "Got exception reading: " + e.getMessage()); @@ -266,8 +288,6 @@ public class SecureShell extends Activity {      public void onCreate(Bundle savedValues) {          super.onCreate(savedValues); -        mContext = this; -                  requestWindowFeature(Window.FEATURE_PROGRESS);          setContentView(R.layout.secure_shell);          mOutput  = (TextView) findViewById(R.id.output); @@ -295,22 +315,27 @@ public class SecureShell extends Activity {          mConn.start();      } -    public void setWaiting(boolean isWaiting) { +    public void setWaiting(boolean isWaiting, String title, String message) {      	mIsWaiting = isWaiting; +    	mWaitingTitle = title; +    	mWaitingMessage = message; +    	mHandler.post(mUpdateWaiting);      }  	final Runnable mUpdateWaiting = new Runnable() {  		public void run() {  	    	if (mIsWaiting) { -	    		getWindow().setFeatureInt(Window.FEATURE_PROGRESS, -	    				Window.PROGRESS_VISIBILITY_ON); -	    		getWindow().setFeatureInt(Window.FEATURE_PROGRESS, -	    				Window.PROGRESS_INDETERMINATE_ON); +	    		if (progress == null) +					progress = ProgressDialog.show(SecureShell.this, mWaitingTitle, mWaitingMessage, true, false); +				else { +	    			progress.setTitle(mWaitingTitle); +	    			progress.setMessage(mWaitingMessage); +	    		}  	    	} else { -	    		getWindow().setFeatureInt(Window.FEATURE_PROGRESS, -	    				Window.PROGRESS_VISIBILITY_OFF); -	    		getWindow().setFeatureInt(Window.FEATURE_PROGRESS, -	    				Window.PROGRESS_INDETERMINATE_OFF); +	    		if (progress != null) { +	    			progress.dismiss(); +	    			progress = null; +	    		}  	    	}  		}  	}; @@ -328,14 +353,12 @@ public class SecureShell extends Activity {  	    if (requestCode == PASSWORD_REQUEST) {  	        // If the request was cancelled, then we didn't get anything. -	        if (resultCode == RESULT_CANCELED) { -	            return; -	 -	        // Otherwise, there now should be a password ready for us. -	        } else { +	        if (resultCode == RESULT_CANCELED) +				mPassword = ""; +			else  	            mPassword = data; -	            sPass.release(); -	        } +	         +            sPass.release();  	    }  	} @@ -358,10 +381,10 @@ public class SecureShell extends Activity {      @Override      public boolean onKeyDown(int keyCode, KeyEvent msg) { -    	if (out != null) { +    	if (stdout != null) {  	    	int c = mKMap.get(keyCode, msg.getMetaState());  	    	try { -				out.write(c); +				stdout.write(c);  			} catch (IOException e) {  				// TODO Auto-generated catch block  				e.printStackTrace(); @@ -375,25 +398,20 @@ public class SecureShell extends Activity {      	mOutput.setText(mBuffer);      } +    final Runnable mDisconnectAlert = new Runnable() { +    	public void run() { +			AlertDialog d = AlertDialog.show(SecureShell.this, +					"Connection Lost", mDisconnectReason, "Ok", false); +			d.show(); +			// TODO: Return to previous activity if connection fails. +	    } +    }; +          final ConnectionMonitor mConnectionMonitor = new ConnectionMonitor() {      	public void connectionLost(Throwable reason) {      		Log.d("SSH", "Connection ended."); -    		Dialog d = new Dialog(mContext); -    		d.setTitle("Connection Lost"); -    		d.setContentView(R.layout.message_dialog); -    		 -    		TextView msg = (TextView) d.findViewById(R.id.message); -    		msg.setText(reason.getMessage()); -    		 -    		Button b = (Button) d.findViewById(R.id.dismiss); -    		b.setOnClickListener(new OnClickListener() { -				public void onClick(View v) { -					// TODO Auto-generated method stub -					finish(); -				} -    		}); -    		d.show(); -    		finish(); +    		mDisconnectReason = reason.getMessage(); +    		mHandler.post(mDisconnectAlert);      	}      };  } | 
