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" />
 | 
			
		||||
  </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" />
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <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