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">
|
android:versionName="1.0">
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="8"
|
android:minSdkVersion="14"
|
||||||
android:targetSdkVersion="14" />
|
android:targetSdkVersion="14" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
<string name="fingerprint_prefs">Biometric unlock</string>
|
<string name="fingerprint_prefs">Biometric unlock</string>
|
||||||
<string name="import_db_prefs">Import database to internal folder</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="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="keyboardswitch_prefs">Keyboard switching</string>
|
||||||
<string name="OnlyAvailableForLocalFiles">Only available for local files.</string>
|
<string name="OnlyAvailableForLocalFiles">Only available for local files.</string>
|
||||||
<string name="FileIsInInternalDirectory">File is stored in internal directory.</string>
|
<string name="FileIsInInternalDirectory">File is stored in internal directory.</string>
|
||||||
@@ -248,8 +249,10 @@
|
|||||||
<string name="saving_database">Saving database…</string>
|
<string name="saving_database">Saving database…</string>
|
||||||
<string name="exporting_database">Exporting database…</string>
|
<string name="exporting_database">Exporting database…</string>
|
||||||
<string name="export_database_successful">Database exported successfully!</string>
|
<string name="export_database_successful">Database exported successfully!</string>
|
||||||
|
<string name="export_keyfile_successful">Key file exported successfully!</string>
|
||||||
|
|
||||||
<string name="space">Space</string>
|
|
||||||
|
<string name="space">Space</string>
|
||||||
<string name="search_label">Search</string>
|
<string name="search_label">Search</string>
|
||||||
<string name="show_password">Show password</string>
|
<string name="show_password">Show password</string>
|
||||||
<string name="sort_menu">Sort by...</string>
|
<string name="sort_menu">Sort by...</string>
|
||||||
@@ -784,6 +787,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<string-array name="ChangeLog_1_08c">
|
<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>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>Improve locking behavior - no longer displaying biometric prompt immediately after unlocking</item>
|
||||||
<item>Update OkHttp to support HTTP/2</item>
|
<item>Update OkHttp to support HTTP/2</item>
|
||||||
|
|||||||
@@ -129,9 +129,15 @@
|
|||||||
android:title="@string/import_keyfile_prefs"
|
android:title="@string/import_keyfile_prefs"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="export_keyfile_prefs"
|
||||||
|
android:title="@string/export_keyfile_prefs"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Android.App;
|
using Android.App;
|
||||||
@@ -28,6 +29,7 @@ using Android.Preferences;
|
|||||||
using Android.Provider;
|
using Android.Provider;
|
||||||
using Android.Views.Autofill;
|
using Android.Views.Autofill;
|
||||||
using Java.IO;
|
using Java.IO;
|
||||||
|
using KeePass.DataExchange;
|
||||||
using KeePassLib.Cryptography.Cipher;
|
using KeePassLib.Cryptography.Cipher;
|
||||||
using KeePassLib.Keys;
|
using KeePassLib.Keys;
|
||||||
using KeePassLib.Serialization;
|
using KeePassLib.Serialization;
|
||||||
@@ -36,11 +38,12 @@ using keepass2android.Io;
|
|||||||
using keepass2android.Utils;
|
using keepass2android.Utils;
|
||||||
using KeePassLib;
|
using KeePassLib;
|
||||||
using KeePassLib.Cryptography.KeyDerivation;
|
using KeePassLib.Cryptography.KeyDerivation;
|
||||||
|
using KeePassLib.Interfaces;
|
||||||
|
|
||||||
namespace keepass2android
|
namespace keepass2android
|
||||||
{
|
{
|
||||||
//http://stackoverflow.com/a/27422401/292233
|
//http://stackoverflow.com/a/27422401/292233
|
||||||
public class SettingsFragment : PreferenceFragment
|
public class SettingsFragment : PreferenceFragment
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@@ -131,7 +134,8 @@ namespace keepass2android
|
|||||||
private KeyboardSwitchPrefManager _switchPrefManager;
|
private KeyboardSwitchPrefManager _switchPrefManager;
|
||||||
private Preference aesRounds, argon2parallelism, argon2rounds, argon2memory;
|
private Preference aesRounds, argon2parallelism, argon2rounds, argon2memory;
|
||||||
|
|
||||||
void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
|
||||||
|
void OnRememberKeyFileHistoryChanged(object sender, Preference.PreferenceChangeEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (!(bool)eventArgs.NewValue)
|
if (!(bool)eventArgs.NewValue)
|
||||||
{
|
{
|
||||||
@@ -631,13 +635,15 @@ namespace keepass2android
|
|||||||
var prefs = PreferenceManager.GetDefaultSharedPreferences(Activity);
|
var prefs = PreferenceManager.GetDefaultSharedPreferences(Activity);
|
||||||
var rememberKeyfile = prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default));
|
var rememberKeyfile = prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default));
|
||||||
|
|
||||||
Preference importDb = FindPreference("import_keyfile_prefs");
|
Preference importKeyfile = FindPreference("import_keyfile_prefs");
|
||||||
importDb.Summary = "";
|
Preference exportKeyfile = FindPreference("export_keyfile_prefs");
|
||||||
|
importKeyfile.Summary = "";
|
||||||
|
|
||||||
if (!rememberKeyfile)
|
if (!rememberKeyfile)
|
||||||
{
|
{
|
||||||
importDb.Summary = GetString(Resource.String.KeyfileMoveRequiresRememberKeyfile);
|
importKeyfile.Summary = GetString(Resource.String.KeyfileMoveRequiresRememberKeyfile);
|
||||||
importDb.Enabled = false;
|
importKeyfile.Enabled = false;
|
||||||
|
exportKeyfile.Enabled = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CompositeKey masterKey = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
|
CompositeKey masterKey = App.Kp2a.CurrentDb.KpDatabase.MasterKey;
|
||||||
@@ -646,23 +652,35 @@ namespace keepass2android
|
|||||||
IOConnectionInfo iocKeyfile = ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc;
|
IOConnectionInfo iocKeyfile = ((KcpKeyFile)masterKey.GetUserKey(typeof(KcpKeyFile))).Ioc;
|
||||||
if (iocKeyfile.IsLocalFile() && IoUtil.IsInInternalDirectory(iocKeyfile.Path, Activity))
|
if (iocKeyfile.IsLocalFile() && IoUtil.IsInInternalDirectory(iocKeyfile.Path, Activity))
|
||||||
{
|
{
|
||||||
importDb.Enabled = false;
|
importKeyfile.Enabled = false;
|
||||||
importDb.Summary = GetString(Resource.String.FileIsInInternalDirectory);
|
exportKeyfile.Enabled = true;
|
||||||
|
exportKeyfile.PreferenceClick += (sender, args) => { ExportKeyfileFromInternalFolder(); };
|
||||||
|
importKeyfile.Summary = GetString(Resource.String.FileIsInInternalDirectory);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
importDb.Enabled = true;
|
exportKeyfile.Enabled = false;
|
||||||
importDb.PreferenceClick += (sender, args) => { MoveKeyfileToInternalFolder(); };
|
importKeyfile.Enabled = true;
|
||||||
|
importKeyfile.PreferenceClick += (sender, args) => { MoveKeyfileToInternalFolder(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
importDb.Enabled = false;
|
exportKeyfile.Enabled = false;
|
||||||
|
importKeyfile.Enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void ExportKeyfileFromInternalFolder()
|
||||||
|
{
|
||||||
|
StartActivity(new Intent(Activity.ApplicationContext, typeof(ExportKeyfileActivity)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void MoveKeyfileToInternalFolder()
|
private void MoveKeyfileToInternalFolder()
|
||||||
{
|
{
|
||||||
Func<Action> copyAndReturnPostExecute = () =>
|
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