This commit is contained in:
Philipp Crocoll
2020-11-30 11:56:39 +01:00
parent fec0e7768a
commit 29fca5c1f0
5 changed files with 159 additions and 18 deletions

View File

@@ -6,7 +6,7 @@
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="8"
android:minSdkVersion="14"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />

View File

@@ -56,6 +56,7 @@
<string name="fingerprint_prefs">Biometric unlock</string>
<string name="import_db_prefs">Import database to internal folder</string>
<string name="import_keyfile_prefs">Import key file to internal folder</string>
<string name="export_keyfile_prefs">Export key file from internal folder</string>
<string name="keyboardswitch_prefs">Keyboard switching</string>
<string name="OnlyAvailableForLocalFiles">Only available for local files.</string>
<string name="FileIsInInternalDirectory">File is stored in internal directory.</string>
@@ -248,8 +249,10 @@
<string name="saving_database">Saving database…</string>
<string name="exporting_database">Exporting database…</string>
<string name="export_database_successful">Database exported successfully!</string>
<string name="space">Space</string>
<string name="export_keyfile_successful">Key file exported successfully!</string>
<string name="space">Space</string>
<string name="search_label">Search</string>
<string name="show_password">Show password</string>
<string name="sort_menu">Sort by...</string>
@@ -784,6 +787,7 @@
<string-array name="ChangeLog_1_08c">
<item>Updated Jsch to version 0.1.55</item>
<item>No longer storing package names of Android apps in the URL field</item>
<item>Improve locking behavior - no longer displaying biometric prompt immediately after unlocking</item>
<item>Update OkHttp to support HTTP/2</item>

View File

@@ -128,10 +128,16 @@
android:key="import_keyfile_prefs"
android:title="@string/import_keyfile_prefs"
/>
</PreferenceScreen>
<Preference
android:key="export_keyfile_prefs"
android:title="@string/export_keyfile_prefs"
/>
</PreferenceScreen>
<PreferenceScreen

View File

@@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Android.App;
@@ -28,6 +29,7 @@ using Android.Preferences;
using Android.Provider;
using Android.Views.Autofill;
using Java.IO;
using KeePass.DataExchange;
using KeePassLib.Cryptography.Cipher;
using KeePassLib.Keys;
using KeePassLib.Serialization;
@@ -36,11 +38,12 @@ using keepass2android.Io;
using keepass2android.Utils;
using KeePassLib;
using KeePassLib.Cryptography.KeyDerivation;
using KeePassLib.Interfaces;
namespace keepass2android
{
//http://stackoverflow.com/a/27422401/292233
public class SettingsFragment : PreferenceFragment
public class SettingsFragment : PreferenceFragment
{
@@ -130,8 +133,9 @@ namespace keepass2android
private KeyboardSwitchPrefManager _switchPrefManager;
private Preference aesRounds, argon2parallelism, argon2rounds, argon2memory;
void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
{
if (!(bool)eventArgs.NewValue)
{
@@ -631,13 +635,15 @@ namespace keepass2android
var prefs = PreferenceManager.GetDefaultSharedPreferences(Activity);
var rememberKeyfile = prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default));
Preference importDb = FindPreference("import_keyfile_prefs");
importDb.Summary = "";
Preference importKeyfile = FindPreference("import_keyfile_prefs");
Preference exportKeyfile = FindPreference("export_keyfile_prefs");
importKeyfile.Summary = "";
if (!rememberKeyfile)
{
importDb.Summary = GetString(Resource.String.KeyfileMoveRequiresRememberKeyfile);
importDb.Enabled = false;
importKeyfile.Summary = GetString(Resource.String.KeyfileMoveRequiresRememberKeyfile);
importKeyfile.Enabled = false;
exportKeyfile.Enabled = false;
return;
}
CompositeKey masterKey = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
@@ -646,23 +652,35 @@ namespace keepass2android
IOConnectionInfo iocKeyfile = ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc;
if (iocKeyfile.IsLocalFile() && IoUtil.IsInInternalDirectory(iocKeyfile.Path, Activity))
{
importDb.Enabled = false;
importDb.Summary = GetString(Resource.String.FileIsInInternalDirectory);
importKeyfile.Enabled = false;
exportKeyfile.Enabled = true;
exportKeyfile.PreferenceClick += (sender, args) => { ExportKeyfileFromInternalFolder(); };
importKeyfile.Summary = GetString(Resource.String.FileIsInInternalDirectory);
}
else
{
importDb.Enabled = true;
importDb.PreferenceClick += (sender, args) => { MoveKeyfileToInternalFolder(); };
exportKeyfile.Enabled = false;
importKeyfile.Enabled = true;
importKeyfile.PreferenceClick += (sender, args) => { MoveKeyfileToInternalFolder(); };
}
}
else
{
importDb.Enabled = false;
exportKeyfile.Enabled = false;
importKeyfile.Enabled = false;
}
}
private void ExportKeyfileFromInternalFolder()
{
StartActivity(new Intent(Activity.ApplicationContext, typeof(ExportKeyfileActivity)));
}
private void MoveKeyfileToInternalFolder()
{
Func<Action> copyAndReturnPostExecute = () =>

View File

@@ -0,0 +1,113 @@
using System;
using Android.App;
using Android.Content;
using Android.Widget;
using keepass2android.Io;
using KeePassLib.Keys;
using KeePassLib.Serialization;
namespace keepass2android
{
[Activity]
public class ExportKeyfileActivity : LockCloseActivity
{
public class ExportKeyfile : RunnableOnFinish
{
private readonly IKp2aApp _app;
private IOConnectionInfo _targetIoc;
public ExportKeyfile(Activity activity, IKp2aApp app, OnFinish onFinish, IOConnectionInfo targetIoc) : base(
activity, onFinish)
{
_app = app;
_targetIoc = targetIoc;
}
public override void Run()
{
StatusLogger.UpdateMessage(UiStringKey.exporting_database);
try
{
var fileStorage = _app.GetFileStorage(_targetIoc);
if (fileStorage is IOfflineSwitchable)
{
((IOfflineSwitchable) fileStorage).IsOffline = false;
}
CompositeKey masterKey = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
var sourceIoc = ((KcpKeyFile) masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc;
IoUtil.Copy(_targetIoc, sourceIoc, App.Kp2a);
if (fileStorage is IOfflineSwitchable)
{
((IOfflineSwitchable) fileStorage).IsOffline = App.Kp2a.OfflineMode;
}
Finish(true);
}
catch (Exception ex)
{
Finish(false, ex.Message);
}
}
}
public class ExportKeyfileProcessManager : FileSaveProcessManager
{
public ExportKeyfileProcessManager(int requestCode, Activity activity) : base(requestCode, activity)
{
}
protected override void SaveFile(IOConnectionInfo ioc)
{
var exportKeyfile = new ExportKeyfile(_activity, App.Kp2a, new ActionOnFinish(_activity,
(success, message, activity) =>
{
if (!success)
Toast.MakeText(activity, message, ToastLength.Long).Show();
else
Toast.MakeText(activity, _activity.GetString(Resource.String.export_keyfile_successful),
ToastLength.Long).Show();
activity.Finish();
}
), ioc);
ProgressTask pt = new ProgressTask(App.Kp2a, _activity, exportKeyfile);
pt.Run();
}
}
private ExportKeyfileProcessManager _exportKeyfileProcessManager;
protected override void OnCreate(Android.OS.Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
_exportKeyfileProcessManager = new ExportKeyfileProcessManager(0, this);
_exportKeyfileProcessManager.StartProcess();
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (_exportKeyfileProcessManager?.OnActivityResult(requestCode, resultCode, data) == true)
return;
Finish();
}
}
}