allow to export imported keyfiles, closes https://github.com/PhilippC/keepass2android/issues/599
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = () =>
|
||||
|
||||
113
src/keepass2android/settings/ExportKeyfileActivity.cs
Normal file
113
src/keepass2android/settings/ExportKeyfileActivity.cs
Normal 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user