implement prompt callbacks for JSch, fixes https://github.com/PhilippC/keepass2android/issues/519
This commit is contained in:
		| @@ -55,8 +55,8 @@ | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <LibraryProjectZip Include="..\java\JavaFileStorage\app\build\outputs\aar\JavaFileStorage-debug.aar"> | ||||
|       <Link>Jars\JavaFileStorage-debug.aar</Link> | ||||
|     <LibraryProjectZip Include="..\java\JavaFileStorage\app\build\outputs\aar\JavaFileStorage-release.aar"> | ||||
|       <Link>Jars\JavaFileStorage-release.aar</Link> | ||||
|     </LibraryProjectZip> | ||||
|     <None Include="Jars\AboutJars.txt" /> | ||||
|     <None Include="Additions\AboutAdditions.txt" /> | ||||
|   | ||||
| @@ -1,15 +1,21 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     package="keepass2android.javafilestorage" | ||||
|     android:versionCode="1" | ||||
|     android:versionName="1.0"> | ||||
|  | ||||
|      | ||||
|     <uses-sdk | ||||
|         android:minSdkVersion="8" | ||||
|         android:targetSdkVersion="14" /> | ||||
|      | ||||
|  | ||||
|     <uses-permission android:name="android.permission.GET_ACCOUNTS"/> | ||||
|     <uses-permission android:name="android.permission.GET_ACCOUNTS" /> | ||||
|  | ||||
| </manifest> | ||||
|  | ||||
|     <application> | ||||
|         <activity | ||||
|             android:name=".NotifSlave" | ||||
|             android:label="@string/title_activity_notif_slave"></activity> | ||||
|     </application> | ||||
|  | ||||
| </manifest> | ||||
| @@ -0,0 +1,169 @@ | ||||
| package keepass2android.javafilestorage; | ||||
|  | ||||
| import android.app.Activity; | ||||
| import android.app.AlertDialog; | ||||
| import android.app.Dialog; | ||||
| import android.content.DialogInterface; | ||||
| import android.content.Intent; | ||||
| import android.os.Bundle; | ||||
| import android.os.Message; | ||||
| import android.os.Messenger; | ||||
| import android.util.Log; | ||||
| import android.view.View; | ||||
| import android.widget.Button; | ||||
| import android.widget.TextView; | ||||
| import android.widget.Toast; | ||||
|  | ||||
| //based on https://github.com/jwise/dumload/blob/master/src/com/joshuawise/dumload/NotifSlave.java | ||||
| public class NotifSlave extends Activity { | ||||
|  | ||||
|     @Override | ||||
|     public void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|     } | ||||
|  | ||||
|     private void say(String s) { | ||||
|         Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show(); | ||||
|     } | ||||
|  | ||||
|     private int _nextdialog = 0; | ||||
|     private Dialog dialog = null; | ||||
|  | ||||
|     @Override | ||||
|     protected Dialog onCreateDialog(int id) | ||||
|     { | ||||
|         Log.e("KP2AJ.NotifSlave", "Create for dialog "+(Integer.toString(id))); | ||||
|         if (id != _nextdialog) | ||||
|             return null; | ||||
|         return dialog; | ||||
|     } | ||||
|  | ||||
|     private void showDialog(Dialog d) | ||||
|     { | ||||
|         _nextdialog++; | ||||
|         dialog = d; | ||||
|         Log.e("KP2AJ.NotifSlave", "Attempting to show dialog "+(Integer.toString(_nextdialog))); | ||||
|         showDialog(_nextdialog); | ||||
|     } | ||||
|  | ||||
|     public void onStart() { | ||||
|         super.onStart(); | ||||
|  | ||||
|         Intent i = getIntent(); /* i *am* not an intent! */ | ||||
|         final Activity thisact = this; | ||||
|  | ||||
|         final Messenger m = (Messenger)i.getParcelableExtra("keepass2android.sftp.returnmessenger"); | ||||
|         String reqtype = i.getStringExtra("keepass2android.sftp.reqtype"); | ||||
|         String prompt = i.getStringExtra("keepass2android.sftp.prompt"); | ||||
|  | ||||
|         if (prompt == null || reqtype == null || m == null)	/* i.e., we got called by a dummy notification */ | ||||
|         { | ||||
|             this.finish(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (reqtype.equals("yesno")) { | ||||
|             AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||||
|             builder.setTitle("Keepass2Android"); | ||||
|             builder.setMessage(prompt); | ||||
|             builder.setCancelable(false); | ||||
|             builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { | ||||
|                 public void onClick(DialogInterface dialog, int id) { | ||||
|                     Log.e("KP2AJ.NotifSlave", "Responding with a 1."); | ||||
|                     try { | ||||
|                         Message me = Message.obtain(); | ||||
|                         me.arg1 = 1; | ||||
|                         m.send(me); | ||||
|                     } catch (Exception e) { | ||||
|                         Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy."); | ||||
|                     } | ||||
|                     dialog.cancel(); | ||||
|                     thisact.finish(); | ||||
|                 } | ||||
|             }); | ||||
|             builder.setNegativeButton("No", new DialogInterface.OnClickListener() { | ||||
|                 public void onClick(DialogInterface dialog, int id) { | ||||
|                     Log.e("KP2AJ.NotifSlave", "Responding with a 1."); | ||||
|                     try { | ||||
|                         Message me = Message.obtain(); | ||||
|                         me.arg1 = 0; | ||||
|                         m.send(me); | ||||
|                     } catch (Exception e) { | ||||
|                         Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy."); | ||||
|                     } | ||||
|                     dialog.cancel(); | ||||
|                     thisact.finish(); | ||||
|                 } | ||||
|             }); | ||||
|             AlertDialog alert = builder.create(); | ||||
|             showDialog(alert); | ||||
|         } else if (reqtype.equals("message")) { | ||||
|             AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||||
|             builder.setTitle("Keepass2Android"); | ||||
|             builder.setMessage(prompt); | ||||
|             builder.setCancelable(false); | ||||
|             builder.setNeutralButton("OK", new DialogInterface.OnClickListener() { | ||||
|                 public void onClick(DialogInterface dialog, int id) { | ||||
|                     try { | ||||
|                         Message me = Message.obtain(); | ||||
|                         m.send(me); | ||||
|                     } catch (Exception e) { | ||||
|                         Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy."); | ||||
|                     } | ||||
|                     dialog.cancel(); | ||||
|                     thisact.finish(); | ||||
|                 } | ||||
|             }); | ||||
|             AlertDialog alert = builder.create(); | ||||
|             showDialog(alert); | ||||
|         } else if (reqtype.equals("password")) { | ||||
|             final Dialog d = new Dialog(this); | ||||
|  | ||||
|             d.setContentView(R.layout.notfif_slave); | ||||
|             d.setTitle("Keepass2Android"); | ||||
|             d.setCancelable(false); | ||||
|  | ||||
|             TextView text = (TextView) d.findViewById(R.id.prompt); | ||||
|             text.setText(prompt); | ||||
|  | ||||
|             Button ok = (Button) d.findViewById(R.id.ok); | ||||
|             ok.setOnClickListener(new View.OnClickListener() { | ||||
|                 public void onClick(View v) { | ||||
|                     try { | ||||
|                         Message me = Message.obtain(); | ||||
|                         me.arg1 = 1; | ||||
|                         TextView entry = (TextView) d.findViewById(R.id.entry); | ||||
|                         Bundle b = new Bundle(1); | ||||
|                         b.putString("response", entry.getText().toString()); | ||||
|                         me.setData(b); | ||||
|                         m.send(me); | ||||
|                     } catch (Exception e) { | ||||
|                         Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy."); | ||||
|                     } | ||||
|                     d.cancel(); | ||||
|                     thisact.finish(); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             Button cancel = (Button) d.findViewById(R.id.cancel); | ||||
|             cancel.setOnClickListener(new View.OnClickListener() { | ||||
|                 public void onClick(View v) { | ||||
|                     try { | ||||
|                         Message me = Message.obtain(); | ||||
|                         me.arg1 = 0; | ||||
|                         m.send(me); | ||||
|                     } catch (Exception e) { | ||||
|                         Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy."); | ||||
|                     } | ||||
|                     d.cancel(); | ||||
|                     thisact.finish(); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|  | ||||
|             showDialog(d); | ||||
|         } else { | ||||
|             Log.e("KP2AJ.NotifSlave", "What's a "+reqtype+"?"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -35,8 +35,10 @@ public class SftpStorage extends JavaFileStorageBase { | ||||
| 		public String localPath; | ||||
| 		public int port; | ||||
| 	} | ||||
| 	Context _appContext; | ||||
|  | ||||
| 	public SftpStorage() { | ||||
| 	public SftpStorage(Context appContext) { | ||||
| 		_appContext = appContext; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| @@ -318,8 +320,10 @@ public class SftpStorage extends JavaFileStorageBase { | ||||
| 		jsch = new JSch(); | ||||
| 		ConnectionInfo ci = splitStringToConnectionInfo(filename); | ||||
|  | ||||
| 		jsch.setKnownHosts(_appContext.getFilesDir().getAbsolutePath() + "/known_hosts"); | ||||
|  | ||||
| 		Session session = jsch.getSession(ci.username, ci.host, ci.port); | ||||
| 		UserInfo ui = new SftpUserInfo(ci.password); | ||||
| 		UserInfo ui = new SftpUserInfo(ci.password,_appContext); | ||||
| 		session.setUserInfo(ui); | ||||
|  | ||||
| 		session.setConfig("PreferredAuthentications", | ||||
|   | ||||
| @@ -1,14 +1,119 @@ | ||||
| package keepass2android.javafilestorage; | ||||
|  | ||||
| import android.app.Notification; | ||||
| import android.app.NotificationManager; | ||||
| import android.app.PendingIntent; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.net.Uri; | ||||
| import android.os.Bundle; | ||||
| import android.os.Handler; | ||||
| import android.os.Looper; | ||||
| import android.os.Message; | ||||
| import android.os.Messenger; | ||||
| import android.os.SystemClock; | ||||
| import android.support.v4.app.NotificationCompat; | ||||
| import android.util.Log; | ||||
|  | ||||
| import com.jcraft.jsch.UserInfo; | ||||
|  | ||||
| public class SftpUserInfo implements UserInfo { | ||||
|  | ||||
| 	private Object /* pick one type, and fixate on it */ dance(final String type, final String text)	/* for inside the thread */ | ||||
| 	{ | ||||
|  | ||||
| 		final Message msg = Message.obtain(); | ||||
|  | ||||
| 		/* t(*A*t) */ | ||||
| 		Thread t = new Thread() { | ||||
| 			public void run() { | ||||
| 				Looper.prepare(); | ||||
| 				int bogon = (int)SystemClock.elapsedRealtime(); | ||||
|  | ||||
| 				NotificationManager mNotificationManager = (NotificationManager)_appContext.getSystemService(Context.NOTIFICATION_SERVICE); | ||||
| 				NotificationCompat.Builder builder = new NotificationCompat.Builder(_appContext); | ||||
| 				builder.setContentText("SFTP prompt"); | ||||
| 				builder.setSmallIcon(R.drawable.ic_logo_green_foreground); | ||||
|  | ||||
|  | ||||
| 				Handler h = new Handler() { | ||||
| 					public void handleMessage(Message M) { | ||||
| 						msg.copyFrom(M); | ||||
| 						Looper.myLooper().quit(); | ||||
| 					} | ||||
| 				}; | ||||
| 				Messenger m = new Messenger(h); | ||||
|  | ||||
| 				Intent intent = new Intent(_appContext, NotifSlave.class); | ||||
|  | ||||
| 				intent.setAction("keepass2android.sftp.NotifSlave"); | ||||
| 				intent.putExtra("keepass2android.sftp.returnmessenger", m); | ||||
| 				intent.putExtra("keepass2android.sftp.reqtype", type); | ||||
| 				intent.putExtra("keepass2android.sftp.prompt", text); | ||||
| 				intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime()))); | ||||
|  | ||||
| 				PendingIntent contentIntent = PendingIntent.getActivity(_appContext, 0, intent, 0); | ||||
| 				builder.setContentIntent(contentIntent); | ||||
|  | ||||
| 				{ | ||||
| 					Intent directIntent = new Intent(_appContext, NotifSlave.class); | ||||
| 					directIntent.setAction("keepass2android.sftp.NotifSlave"); | ||||
| 					directIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
|  | ||||
| 					directIntent.putExtra("keepass2android.sftp.returnmessenger", m); | ||||
| 					directIntent.putExtra("keepass2android.sftp.reqtype", type); | ||||
| 					directIntent.putExtra("keepass2android.sftp.prompt", text); | ||||
| 					directIntent.setData((Uri.parse("suckit://" + SystemClock.elapsedRealtime()))); | ||||
| 					_appContext.startActivity(directIntent); | ||||
| 				} | ||||
|  | ||||
|  | ||||
|  | ||||
| 				Log.e("KP2AJFS[thread]", "Notifying..."); | ||||
|  | ||||
| 				mNotificationManager.notify(bogon, builder.build()); | ||||
|  | ||||
|  | ||||
|  | ||||
| 				Log.e("KP2AJFS[thread]", "About to go to 'sleep'..."); | ||||
| 				Looper.loop(); | ||||
| 				Log.e("KP2AJFS[thread]", "And we're alive!"); | ||||
|  | ||||
| 				Log.e("KP2AJFS[thread]", "result was: "+(Integer.toString(msg.arg1))); | ||||
|  | ||||
| 				mNotificationManager.cancel(bogon); | ||||
| 			} | ||||
| 		}; | ||||
|  | ||||
| 		t.start(); | ||||
| 		try { | ||||
| 			t.join(); | ||||
| 		} catch (Exception e) { | ||||
| 			return null; | ||||
| 		} | ||||
|  | ||||
| 		if (type.equals("yesno")) | ||||
| 			return new Boolean(msg.arg1 == 1); | ||||
| 		else if (type.equals("message")) | ||||
| 			return null; | ||||
| 		else if (type.equals("password")) { | ||||
| 			if (msg.arg1 == 0) | ||||
| 				return null; | ||||
| 			Bundle b = msg.getData(); | ||||
| 			return b.getString("response"); | ||||
| 		} else | ||||
| 			return null; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	Context _appContext; | ||||
|  | ||||
| 	String _password; | ||||
| 	 | ||||
| 	public SftpUserInfo(String password) { | ||||
| 	public SftpUserInfo(String password, Context appContext) | ||||
| 	{ | ||||
| 		_password = password; | ||||
| 		_appContext = appContext; | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| @@ -35,12 +140,15 @@ public class SftpUserInfo implements UserInfo { | ||||
|  | ||||
| 	@Override | ||||
| 	public boolean promptYesNo(String message) { | ||||
| 		return true; //continue all operations without user action | ||||
| 		return (Boolean)dance("yesno", message); | ||||
|  | ||||
| 		//test with https://www.sftp.net/public-online-sftp-servers? | ||||
| 	} | ||||
|  | ||||
| 	@Override | ||||
| 	public void showMessage(String message) { | ||||
| 		Log.d("KP2AJ", message); | ||||
| 	public void showMessage(String message) | ||||
| 	{ | ||||
| 		dance("message", message); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,4 @@ | ||||
| <vector android:height="24dp" android:viewportHeight="800.0" | ||||
|     android:viewportWidth="800.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <path android:fillColor="#ffffff" android:fillType="evenOdd" android:pathData="m318.7,232c13.6,0 24.6,10.9 24.6,24.4 0,13.5 -11,24.4 -24.6,24.4 -13.6,0 -24.6,-10.9 -24.6,-24.4 0,-13.5 11,-24.4 24.6,-24.4zM453.5,256.4c0,13.5 11,24.4 24.6,24.4 13.6,0 24.6,-10.9 24.6,-24.4 0,-13.5 -11,-24.4 -24.6,-24.4 -13.6,0 -24.6,10.9 -24.6,24.4zM399.8,177.7M140.2,600.6v47h517.3v-47zM140.2,350.9v47h517.3v-47zM140.1,481.2h191.8c-0.8,-4.1 -1.2,-8.3 -1.2,-12.4 0,-12.4 3.4,-24.2 9.9,-34.6L140.1,434.2ZM657.5,481.2v-47L454.9,434.2c6.5,10.4 9.8,22.2 9.8,34.6 0,4.1 -0.4,8.3 -1.2,12.4zM140.1,517.4v47h186.6l14.3,-47zM454.3,517.4 L468.7,564.4h188.8v-47zM432.7,565.8 L411.7,496.9 414.4,495.3c10.3,-5.9 16.7,-16.9 16.7,-28.6 0,-18.2 -15,-33 -33.3,-33 -18.3,0 -33.3,14.8 -33.3,33 0,11.8 6.4,22.7 16.7,28.6l2.7,1.6 -21.1,68.9zM507.5,158.5 L507.7,158.2 543.3,106.9c2.4,-3.5 1.8,-8.1 -1.4,-10.3 -3.2,-2.2 -7.7,-1.1 -10.2,2.4l-37.2,53.5 -0.1,0.3c-29.3,-11.8 -62.1,-18.5 -96.8,-18.5 -35.2,0 -68.5,6.9 -98.1,19L261.8,99c-2.4,-3.5 -7,-4.6 -10.2,-2.4 -3.2,2.2 -3.8,6.8 -1.4,10.3l36.2,52.2c-66.8,32.2 -111.9,92.4 -111.9,161.3h42.9c0,-79.1 80.8,-143.5 180.1,-143.5 99.3,0 180.1,64.3 180.1,143.5h42.9c0.2,-69.3 -45.4,-129.8 -113,-161.9z"/> | ||||
| </vector> | ||||
| @@ -1,3 +1,5 @@ | ||||
| <resources> | ||||
|  | ||||
|  | ||||
|     <string name="title_activity_notif_slave">Keepass2Android</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -526,9 +526,9 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag | ||||
| 	} | ||||
|  | ||||
| 	static JavaFileStorage createStorageToTest(Context ctx, Context appContext, boolean simulateRestart) { | ||||
| 		//storageToTest = new SftpStorage(); | ||||
| 		storageToTest = new SftpStorage(ctx.getApplicationContext()); | ||||
| 		//storageToTest = new SkyDriveFileStorage("000000004010C234", appContext); | ||||
| 		storageToTest = new OneDriveStorage(appContext, "000000004010C234"); | ||||
| 		//storageToTest = new OneDriveStorage(appContext, "000000004010C234"); | ||||
| 		//storageToTest = new GoogleDriveFileStorage(); | ||||
| 		/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() { | ||||
| 			@Override | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll