implement prompt callbacks for JSch, fixes https://github.com/PhilippC/keepass2android/issues/519
This commit is contained in:
BIN
graphics/launcher_icon/Logo-green-96.png
Normal file
BIN
graphics/launcher_icon/Logo-green-96.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
@@ -55,8 +55,8 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<LibraryProjectZip Include="..\java\JavaFileStorage\app\build\outputs\aar\JavaFileStorage-debug.aar">
|
<LibraryProjectZip Include="..\java\JavaFileStorage\app\build\outputs\aar\JavaFileStorage-release.aar">
|
||||||
<Link>Jars\JavaFileStorage-debug.aar</Link>
|
<Link>Jars\JavaFileStorage-release.aar</Link>
|
||||||
</LibraryProjectZip>
|
</LibraryProjectZip>
|
||||||
<None Include="Jars\AboutJars.txt" />
|
<None Include="Jars\AboutJars.txt" />
|
||||||
<None Include="Additions\AboutAdditions.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"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="keepass2android.javafilestorage"
|
package="keepass2android.javafilestorage"
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="1.0">
|
android:versionName="1.0">
|
||||||
|
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="8"
|
android:minSdkVersion="8"
|
||||||
android:targetSdkVersion="14" />
|
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 String localPath;
|
||||||
public int port;
|
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();
|
jsch = new JSch();
|
||||||
ConnectionInfo ci = splitStringToConnectionInfo(filename);
|
ConnectionInfo ci = splitStringToConnectionInfo(filename);
|
||||||
|
|
||||||
|
jsch.setKnownHosts(_appContext.getFilesDir().getAbsolutePath() + "/known_hosts");
|
||||||
|
|
||||||
Session session = jsch.getSession(ci.username, ci.host, ci.port);
|
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.setUserInfo(ui);
|
||||||
|
|
||||||
session.setConfig("PreferredAuthentications",
|
session.setConfig("PreferredAuthentications",
|
||||||
|
|||||||
@@ -1,14 +1,119 @@
|
|||||||
package keepass2android.javafilestorage;
|
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 android.util.Log;
|
||||||
|
|
||||||
import com.jcraft.jsch.UserInfo;
|
import com.jcraft.jsch.UserInfo;
|
||||||
|
|
||||||
public class SftpUserInfo implements 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;
|
String _password;
|
||||||
|
|
||||||
public SftpUserInfo(String password) {
|
public SftpUserInfo(String password, Context appContext)
|
||||||
|
{
|
||||||
_password = password;
|
_password = password;
|
||||||
|
_appContext = appContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -35,12 +140,15 @@ public class SftpUserInfo implements UserInfo {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean promptYesNo(String message) {
|
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
|
@Override
|
||||||
public void showMessage(String message) {
|
public void showMessage(String message)
|
||||||
Log.d("KP2AJ", 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>
|
<resources>
|
||||||
|
|
||||||
|
|
||||||
|
<string name="title_activity_notif_slave">Keepass2Android</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -526,9 +526,9 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JavaFileStorage createStorageToTest(Context ctx, Context appContext, boolean simulateRestart) {
|
static JavaFileStorage createStorageToTest(Context ctx, Context appContext, boolean simulateRestart) {
|
||||||
//storageToTest = new SftpStorage();
|
storageToTest = new SftpStorage(ctx.getApplicationContext());
|
||||||
//storageToTest = new SkyDriveFileStorage("000000004010C234", appContext);
|
//storageToTest = new SkyDriveFileStorage("000000004010C234", appContext);
|
||||||
storageToTest = new OneDriveStorage(appContext, "000000004010C234");
|
//storageToTest = new OneDriveStorage(appContext, "000000004010C234");
|
||||||
//storageToTest = new GoogleDriveFileStorage();
|
//storageToTest = new GoogleDriveFileStorage();
|
||||||
/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
|
/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user