Merge branch 'master' of c:/ph/keepass2android

This commit is contained in:
Philipp Crocoll
2020-06-15 13:10:20 +02:00
22 changed files with 364 additions and 166 deletions

View File

@@ -270,7 +270,7 @@ namespace keepass2android.Io
}
else return false;
}
else throw new Exception("couldn't move to first result element: " + (cursor == null) + uri.ToString());
else return false;
}
catch (Exception e)
{

View File

@@ -49,6 +49,11 @@ namespace keepass2android
get { return _activeActivity; }
private set
{
if (_activeActivity != null && _activeActivity != _previouslyActiveActivity)
{
_previouslyActiveActivity = _activeActivity;
}
_activeActivity = value;
if (_task != null)
_task.ActiveActivity = _activeActivity;
@@ -60,12 +65,18 @@ namespace keepass2android
}
}
private readonly Handler _handler;
public Activity PreviouslyActiveActivity
{
get { return _previouslyActiveActivity; }
}
private readonly Handler _handler;
private readonly RunnableOnFinish _task;
private IProgressDialog _progressDialog;
private readonly IKp2aApp _app;
private Thread _thread;
private Activity _activeActivity;
private Activity _activeActivity, _previouslyActiveActivity;
private ProgressDialogStatusLogger _progressDialogStatusLogger;
public ProgressTask(IKp2aApp app, Activity activity, RunnableOnFinish task)

View File

@@ -88,6 +88,7 @@ namespace keepass2android
ReadOnlyReason_ReadOnlyKitKat,
ReadOnlyReason_LocalBackup,
Ok,
cancel
cancel,
FileNotFound
}
}

View File

@@ -36,8 +36,11 @@ namespace keepass2android
{
_actionToPerform = actionToPerform;
}
public override void Run()
//if set to true, the previously active active will be passed to ActionToPerformOnFinish instead null if no activity is on foreground
public bool AllowInactiveActivity { get; set; }
public override void Run()
{
if (Message == null)
Message = "";
@@ -46,7 +49,7 @@ namespace keepass2android
Handler.Post(() => {_actionToPerform(Success, Message, ActiveActivity);});
}
else
_actionToPerform(Success, Message, ActiveActivity);
_actionToPerform(Success, Message, AllowInactiveActivity ? (ActiveActivity ?? PreviouslyActiveActivity) : ActiveActivity);
base.Run();
}
}

View File

@@ -123,7 +123,7 @@ namespace keepass2android
{
if (!(e is InvalidCompositeKeyException))
Kp2aLog.LogUnexpectedError(e);
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, false, Exception);
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + (e.Message ?? (e is FileNotFoundException ? _app.GetResourceString(UiStringKey.FileNotFound) : "")), false, Exception);
return;
}

View File

@@ -39,7 +39,7 @@ namespace keepass2android
protected OnFinish BaseOnFinish;
protected Handler Handler;
private ProgressDialogStatusLogger _statusLogger = new ProgressDialogStatusLogger(); //default: no logging but not null -> can be used whenever desired
private Activity _activeActivity;
private Activity _activeActivity, _previouslyActiveActivity;
public ProgressDialogStatusLogger StatusLogger
@@ -53,7 +53,12 @@ namespace keepass2android
get { return _activeActivity; }
set
{
_activeActivity = value;
if (_activeActivity != null && _activeActivity != _previouslyActiveActivity)
{
_previouslyActiveActivity = _activeActivity;
}
_activeActivity = value;
if (BaseOnFinish != null)
{
BaseOnFinish.ActiveActivity = value;
@@ -61,8 +66,15 @@ namespace keepass2android
}
}
public Activity PreviouslyActiveActivity
{
get { return _previouslyActiveActivity; }
protected OnFinish(Activity activeActivity, Handler handler)
}
protected OnFinish(Activity activeActivity, Handler handler)
{
ActiveActivity = activeActivity;
BaseOnFinish = null;

View File

@@ -5,6 +5,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import com.burgstaller.okhttp.AuthenticationCacheInterceptor;
@@ -44,6 +45,7 @@ import keepass2android.javafilestorage.webdav.PropfindXmlParser;
import keepass2android.javafilestorage.webdav.WebDavUtil;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
@@ -52,6 +54,7 @@ import okhttp3.internal.tls.OkHostnameVerifier;
public class WebDavStorage extends JavaFileStorageBase {
private final ICertificateErrorHandler mCertificateErrorHandler;
private Context appContext;
public WebDavStorage(ICertificateErrorHandler certificateErrorHandler)
{
@@ -125,9 +128,13 @@ public class WebDavStorage extends JavaFileStorageBase {
}
}
//client to be reused (connection pool/thread pool). We're building a custom client for each ConnectionInfo in getClient for actual usage
final OkHttpClient baseClient = new OkHttpClient();
private OkHttpClient getClient(ConnectionInfo ci) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient.Builder builder = baseClient.newBuilder();
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
com.burgstaller.okhttp.digest.Credentials credentials = new com.burgstaller.okhttp.digest.Credentials(ci.username, ci.password);
@@ -169,6 +176,12 @@ public class WebDavStorage extends JavaFileStorageBase {
builder.writeTimeout(25, TimeUnit.SECONDS);
}
//OkHttp has issues with HTTP/2 (https://github.com/square/okhttp/issues/4964)
//An OkHttp developer suggested to use the same workaround as other apps:
// (https://github.com/PhilippC/keepass2android/issues/747#issuecomment-622946085)
//force HTTP1.1
builder.protocols(Arrays.asList(Protocol.HTTP_1_1));
OkHttpClient client = builder.build();
@@ -503,7 +516,7 @@ public class WebDavStorage extends JavaFileStorageBase {
@Override
public void prepareFileUsage(Context appContext, String path) {
//nothing to do
this.appContext = appContext;
}

View File

@@ -33,8 +33,10 @@ public class Kp2aDialog extends Activity {
final ArrayList<StringForTyping> items = new ArrayList<StringForTyping>();
List<StringForTyping> availableFields = keepass2android.kbbridge.KeyboardData.availableFields;
for (StringForTyping entry : availableFields) {
items.add(entry.clone());
}
StringForTyping openOrChangeEntry = new StringForTyping();
if (keepass2android.kbbridge.KeyboardData.entryName == null)

View File

@@ -21,100 +21,6 @@ using File = System.IO.File;
namespace keepass2android
{
public static class Kp2aLog
{
private static bool? _logToFile;
private static object _fileLocker = new object();
public static void Log(string message)
{
if (message != null)
Android.Util.Log.Debug("KP2A", message);
if (LogToFile)
{
lock (_fileLocker)
{
try
{
using (var streamWriter = System.IO.File.AppendText(LogFilename))
{
string stringToLog = DateTime.Now + ":" + DateTime.Now.Millisecond + " -- " + message;
streamWriter.WriteLine(stringToLog);
}
}
catch (Exception e)
{
Android.Util.Log.Debug("KP2A", "Couldn't write to log file. " + e);
}
}
}
}
private static string LogFilename
{
get { return Application.Context.FilesDir.CanonicalPath + "/keepass2android.log"; }
}
private static bool LogToFile
{
get
{
if (_logToFile == null)
_logToFile = System.IO.File.Exists(LogFilename);
return (bool)_logToFile;
}
}
public static event EventHandler<Exception> OnUnexpectedError;
public static void LogUnexpectedError(Exception exception)
{
Log(exception.ToString());
if (OnUnexpectedError != null)
OnUnexpectedError(null, exception);
}
public static void CreateLogFile()
{
if (!System.IO.File.Exists(LogFilename))
{
System.IO.File.Create(LogFilename).Dispose();
_logToFile = true;
}
}
public static void FinishLogFile()
{
if (System.IO.File.Exists(LogFilename))
{
_logToFile = false;
int count = 0;
while (System.IO.File.Exists(LogFilename + "." + count))
count++;
System.IO.File.Move(LogFilename, LogFilename + "." + count);
}
}
public static void SendLog(Context ctx)
{
if (!System.IO.File.Exists(LogFilename))
return;
Intent sendIntent = new Intent();
sendIntent.SetAction(Intent.ActionSend);
sendIntent.PutExtra(Intent.ExtraText, File.ReadAllText(LogFilename));
sendIntent.PutExtra(Intent.ExtraEmail, "crocoapps@gmail.com");
sendIntent.PutExtra(Intent.ExtraSubject, "Keepass2Android log");
sendIntent.SetType("text/plain");
ctx.StartActivity(Intent.CreateChooser(sendIntent, "Send log to..."));
}
}
public interface IBiometricAuthCallback
{
void OnBiometricAuthSucceeded();
@@ -215,6 +121,7 @@ namespace keepass2android
get
{
var result = BiometricManager.From(Activity).CanAuthenticate();
Kp2aLog.Log("BiometricHardware available = " + result);
return result == BiometricManager.BiometricSuccess
|| result == BiometricManager.BiometricErrorNoneEnrolled;
}

View File

@@ -497,7 +497,7 @@ namespace keepass2android
ActionOnFinish closeOrShowError = new ActionOnFinish(this, (success, message, activity) => {
if (success)
{
activity.Finish();
activity?.Finish();
} else
{
OnFinish.DisplayMessage(activity, message, true);
@@ -505,6 +505,9 @@ namespace keepass2android
State.EditMode.InitializeEntry(State.Entry);
}
});
//make sure we can close the EntryEditActivity activity even if the app went to background till we get to the OnFinish Action
closeOrShowError.AllowInactiveActivity = true;
ActionOnFinish afterAddEntry = new ActionOnFinish(this, (success, message, activity) =>
{

View File

@@ -463,7 +463,7 @@ namespace keepass2android
new AlertDialog.Builder(this)
.SetTitle(Resource.String.autofill_enable)
.SetMessage(Resource.String.autofill_enable_failed)
.SetPositiveButton(Resource.String.ok, (o, eventArgs) => { })
.SetPositiveButton(Resource.String.Ok, (o, eventArgs) => { })
.Show();
const string autofillservicewasenabled = "AutofillServiceWasEnabled";
_prefs.Edit().PutBoolean(autofillservicewasenabled, true).Commit();
@@ -1239,7 +1239,7 @@ namespace keepass2android
{
Handler.Post(() =>
{
Toast.MakeText(ActiveActivity, "Unrecoverable error: " + Message, ToastLength.Long).Show();
Toast.MakeText(ActiveActivity ?? Application.Context, "Unrecoverable error: " + Message, ToastLength.Long).Show();
});
App.Kp2a.Lock(false);

View File

@@ -575,15 +575,13 @@ namespace keepass2android
}
}
int count = 1;
private string mDrawerTitle;
private MeasuringRelativeLayout.MeasureArgs _measureArgs;
private ActivityDesign _activityDesign;
private BiometricDecryption _biometricDec;
private bool _fingerprintPermissionGranted;
private PasswordActivityBroadcastReceiver _intentReceiver;
private PasswordActivityBroadcastReceiver _intentReceiver;
private int _appnameclickCount;

View File

@@ -80,34 +80,112 @@
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:host="*" />
<data android:pathPattern=".*\\.kdbp" />
<data android:pathPattern=".*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\.kdbx" />
<data android:pathPattern=".*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
</intent-filter>
<!-- intent filter for opening database files
Note that this stopped working nicely with Android 7, see e.g. https://stackoverflow.com/a/26635162/292233
KP2A was using
<data android:scheme="content" />
<data android:mimeType="*/*" />
previously, but that leaded to complaints by users saying KP2A is showing up way too often, even when opening contacts and the like.
This is why this was reduced content with mimeType=application/octet-stream or content with pathPattern .
The scheme=file is still there for old OS devices. It's also queried by apps like Dropbox to find apps for a certain file type.
-->
<!-- This intent filter is for apps which use content with a URI containing the extension but no specific mimeType, e.g. ASTRO file manager -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:mimeType="*/*" />
<data android:host="*" />
<data android:pathPattern=".*\\.kdbp" />
<data android:pathPattern=".*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\.kdbx" />
<data android:pathPattern=".*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\.kdb" />
<data android:pathPattern=".*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
</intent-filter>
<!-- This intent filter is for apps which use content with a URI not containing the extension but at least specify mimeType=application/octet-stream, e.g. GoogleDrive or FolderSync -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:mimeType="application/octet-stream" />
<data android:host="*" />
</intent-filter>
<!-- This intent filter is for old OS versions (Android 6 and below) or for apps explicitly querying intents for a certain file:-URI -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:host="*" />
<data android:pathPattern=".*\\.kdbp" />
<data android:pathPattern=".*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\.kdbx" />
<data android:pathPattern=".*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\.kdb" />
<data android:pathPattern=".*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
</intent-filter>
<intent-filter android:label="@string/kp2a_findUrl">
<action android:name="android.intent.action.SEND" />

View File

@@ -85,7 +85,6 @@
<action android:name="kp2a.action.SelectCurrentDbActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.SEND" />
@@ -95,12 +94,27 @@
<data android:mimeType="application/*" />
</intent-filter>
<!-- intent filter for opening database files
Note that this stopped working nicely with Android 7, see e.g. https://stackoverflow.com/a/26635162/292233
KP2A was using
<data android:scheme="content" />
<data android:mimeType="*/*" />
previously, but that leaded to complaints by users saying KP2A is showing up way too often, even when opening contacts and the like.
This is why this was reduced content with mimeType=application/octet-stream or content with pathPattern .
The scheme=file is still there for old OS devices. It's also queried by apps like Dropbox to find apps for a certain file type.
-->
<!-- This intent filter is for apps which use content with a URI containing the extension but no specific mimeType, e.g. ASTRO file manager -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="*/*" />
<data android:host="*" />
@@ -135,7 +149,59 @@
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
</intent-filter>
<intent-filter android:label="@string/kp2a_findUrl">
<!-- This intent filter is for apps which use content with a URI not containing the extension but at least specify mimeType=application/octet-stream, e.g. GoogleDrive or FolderSync -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:mimeType="application/octet-stream" />
<data android:host="*" />
</intent-filter>
<!-- This intent filter is for old OS versions (Android 6 and below) or for apps explicitly querying intents for a certain file:-URI -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:host="*" />
<data android:pathPattern=".*\\.kdbp" />
<data android:pathPattern=".*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\.kdbx" />
<data android:pathPattern=".*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\.kdb" />
<data android:pathPattern=".*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
</intent-filter>
<intent-filter android:label="@string/kp2a_findUrl">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />

View File

@@ -69,11 +69,26 @@
<data android:mimeType="application/*" />
</intent-filter>
<!-- intent filter for opening database files
Note that this stopped working nicely with Android 7, see e.g. https://stackoverflow.com/a/26635162/292233
KP2A was using
<data android:scheme="content" />
<data android:mimeType="*/*" />
previously, but that leaded to complaints by users saying KP2A is showing up way too often, even when opening contacts and the like.
This is why this was reduced content with mimeType=application/octet-stream or content with pathPattern .
The scheme=file is still there for old OS devices. It's also queried by apps like Dropbox to find apps for a certain file type.
-->
<!-- This intent filter is for apps which use content with a URI containing the extension but no specific mimeType, e.g. ASTRO file manager -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="*/*" />
<data android:host="*" />
@@ -108,6 +123,58 @@
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
</intent-filter>
<!-- This intent filter is for apps which use content with a URI not containing the extension but at least specify mimeType=application/octet-stream, e.g. GoogleDrive or FolderSync -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:mimeType="application/octet-stream" />
<data android:host="*" />
</intent-filter>
<!-- This intent filter is for old OS versions (Android 6 and below) or for apps explicitly querying intents for a certain file:-URI -->
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:host="*" />
<data android:pathPattern=".*\\.kdbp" />
<data android:pathPattern=".*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
<data android:pathPattern=".*\\.kdbx" />
<data android:pathPattern=".*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
<data android:pathPattern=".*\\.kdb" />
<data android:pathPattern=".*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>

View File

@@ -62,10 +62,11 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputLayout
android:layout_weight="1"
style="@style/EntryEditSingleLine_TextInputLayout">
<EditText
android:id="@+id/entry_password"
@@ -103,7 +104,7 @@
android:src="@drawable/ic_plus_button"
android:background="?android:selectableItemBackground" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
<EditText
android:id="@+id/entry_confpassword"
android:layout_width="match_parent"

View File

@@ -138,12 +138,10 @@
android:layout_marginTop="16dp"
android:layout_marginLeft="4dp"
android:text="@string/hint_login_pass" />
<RelativeLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/password_edit"
android:layout_width="match_parent"
@@ -152,6 +150,7 @@
android:paddingTop="2dp"
android:singleLine="true"
android:inputType="textPassword"
android:layout_weight="1"
android:fontFamily="sans-serif"
android:hint="@string/hint_login_pass"
android:importantForAccessibility="no"/>
@@ -180,8 +179,8 @@
android:scaleType="fitXY"
android:background="?android:selectableItemBackground" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/keyfileLine"
android:layout_width="fill_parent"

View File

@@ -31,6 +31,7 @@ using Java.IO;
using KeePassLib.Serialization;
using Keepass2android.Pluginsdk;
using keepass2android.Io;
using Console = System.Console;
using Environment = Android.OS.Environment;
namespace keepass2android
@@ -302,6 +303,16 @@ namespace keepass2android
private void EditFileEntry(string filename, IOConnectionInfo newConnectionInfo)
{
try
{
App.Kp2a.GetFileStorage(newConnectionInfo);
}
catch (NoFileStorageFoundException)
{
Toast.MakeText(this, "Don't know how to handle " + newConnectionInfo.Path, ToastLength.Long).Show();
return;
}
_dbHelper.CreateFile(newConnectionInfo, _dbHelper.GetKeyFileForFile(filename), false);
_dbHelper.DeleteFile(filename);

View File

@@ -1888,7 +1888,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="FluentFTP">
<Version>31.3.1</Version>
<Version>32.4.3</Version>
</PackageReference>
<PackageReference Include="Microsoft.Bcl">
<Version>1.1.10</Version>

View File

@@ -826,8 +826,18 @@ namespace keepass2android
//must be enabled in settings first
Toast.MakeText(this, Resource.String.please_activate_keyboard, ToastLength.Long).Show();
Intent settingsIntent = new Intent(Android.Provider.Settings.ActionInputMethodSettings);
settingsIntent.SetFlags(ActivityFlags.NewTask);
StartActivity(settingsIntent);
try
{
settingsIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ExcludeFromRecents);
StartActivity(settingsIntent);
}
catch (Exception e)
{
//seems like on Huawei devices this call can fail.
Kp2aLog.LogUnexpectedError(e);
Toast.MakeText(this, "Failed to switch keyboard.", ToastLength.Long).Show();
}
}
else
{
@@ -839,13 +849,24 @@ namespace keepass2android
ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
ActivityManager.GetMyMemoryState(appProcessInfo);
//at least on Samsung devices, we always need the helper activity
mustUseHelperActivity = (appProcessInfo.Importance != Importance.Foreground) || (Build.Manufacturer != "Google");
mustUseHelperActivity = true;// TODO enable again (appProcessInfo.Importance != Importance.Foreground) || (Build.Manufacturer != "Google");
}
if (mustUseHelperActivity)
{
Intent switchImeIntent = new Intent(this, typeof(SwitchImeActivity));
switchImeIntent.SetFlags(ActivityFlags.NewTask);
StartActivity(switchImeIntent);
try
{
Intent switchImeIntent = new Intent(this, typeof(SwitchImeActivity));
switchImeIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ExcludeFromRecents);
StartActivity(switchImeIntent);
}
catch (Exception e)
{
//seems like on Huawei devices this call can fail.
Kp2aLog.LogUnexpectedError(e);
Toast.MakeText(this, "Failed to switch keyboard.", ToastLength.Long).Show();
}
}
else
{
@@ -897,7 +918,7 @@ namespace keepass2android
if (App.Kp2a.LastOpenedEntry == null)
{
Intent i = new Intent(context, typeof(AppKilledInfo));
i.SetFlags(ActivityFlags.ClearTask | ActivityFlags.NewTask);
i.SetFlags(ActivityFlags.ClearTask | ActivityFlags.NewTask | ActivityFlags.ExcludeFromRecents);
context.StartActivity(i);
return;
}

View File

@@ -42,6 +42,8 @@ namespace keepass2android.services
protected override void HandleSaveRequest(StructureParser parser, string query)
{
var intent = new Intent(this, typeof(SelectCurrentDbActivity));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop | ActivityFlags.SingleTop);
Dictionary<string, string> outputFields = new Dictionary<string, string>();
foreach (var p in parser.ClientFormData.HintMap)

View File

@@ -235,8 +235,11 @@ namespace keepass2android
var dbname = kpDatabase.Name;
if (String.IsNullOrEmpty(dbname))
{
//todo: if paranoid ("don't remember recent files") return "***"
dbname = App.Kp2a.GetFileStorage(kpDatabase.IOConnectionInfo).GetFilenameWithoutPathAndExt(kpDatabase.IOConnectionInfo);
//if paranoid ("don't remember recent files")return "***"
if (!App.Kp2a.GetBooleanPreference(PreferenceKey.remember_keyfile))
return "***";
dbname = UrlUtil.StripExtension(
UrlUtil.GetFileName(App.Kp2a.GetFileStorage(kpDatabase.IOConnectionInfo).GetDisplayName(kpDatabase.IOConnectionInfo)));
}
if (displayString != "")
displayString = displayString + ", ";