allow importing database to internal folder

This commit is contained in:
Philipp Crocoll 2014-12-15 04:15:03 +01:00
parent 3110f5c9be
commit 13ab33081d
6 changed files with 161 additions and 25 deletions

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using Android.Content;
using Java.IO;
using KeePassLib.Serialization;
@ -46,5 +47,50 @@ namespace keepass2android.Io
}
return iocParent;
}
public static bool IsInInternalDirectory(string path, Context context)
{
try
{
File filesDir = context.FilesDir.CanonicalFile;
File ourFile = new File(path).CanonicalFile;
//http://www.java2s.com/Tutorial/Java/0180__File/Checkswhetherthechilddirectoryisasubdirectoryofthebasedirectory.htm
File parentFile = ourFile;
while (parentFile != null)
{
if (filesDir.Equals(parentFile))
{
return true;
}
parentFile = parentFile.ParentFile;
}
return false;
}
catch (Exception e)
{
Kp2aLog.Log(e.ToString());
return false;
}
}
public static void Copy(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc, IKp2aApp app)
{
IFileStorage sourceStorage = app.GetFileStorage(sourceIoc, false); //don't cache source. file won't be used ever again
IFileStorage targetStorage = app.GetFileStorage(targetIoc);
using (
var writeTransaction = targetStorage.OpenWriteTransaction(targetIoc,
app.GetBooleanPreference(
PreferenceKey.UseFileTransactions)))
{
using (var writeStream = writeTransaction.OpenFile())
{
sourceStorage.OpenFileForRead(sourceIoc).CopyTo(writeStream);
}
writeTransaction.CommitWrite();
}
}
}
}

View File

@ -293,16 +293,6 @@ namespace keepass2android.Io
return false; //TODO implement. note, however, that we MAY return false even if it's read-only
}
public bool IsPermanentLocation(IOConnectionInfo ioc)
{
return true;
}
public bool IsReadOnly(IOConnectionInfo ioc)
{
return false; //TODO implement. note, however, that we MAY return false even if it's read-only
}
public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
{
_jfs.OnCreate(((IJavaFileStorageFileStorageSetupActivity)activity), savedInstanceState);

View File

@ -249,20 +249,7 @@ namespace keepass2android
protected virtual void CopyFile(IOConnectionInfo targetIoc, IOConnectionInfo sourceIoc)
{
IFileStorage sourceStorage = _app.GetFileStorage(sourceIoc, false); //don't cache source. file won't be used ever again
IFileStorage targetStorage = _app.GetFileStorage(targetIoc);
using (
var writeTransaction = targetStorage.OpenWriteTransaction(targetIoc,
_app.GetBooleanPreference(
PreferenceKey.UseFileTransactions)))
{
using (var writeStream = writeTransaction.OpenFile())
{
sourceStorage.OpenFileForRead(sourceIoc).CopyTo(writeStream);
}
writeTransaction.CommitWrite();
}
IoUtil.Copy(targetIoc, sourceIoc, _app);
}
private void PrimaryIocSelected(IOConnectionInfo ioc)

View File

@ -41,6 +41,12 @@
<string name="FileHandling_prefs">File handling</string>
<string name="keyboard_prefs">Keyboard</string>
<string name="export_prefs">Export database...</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="OnlyAvailableForLocalFiles">Only available for local files.</string>
<string name="FileIsInInternalDirectory">File is stored in internal directory.</string>
<string name="DatabaseFileMoved">Database file was copied to internal folder. Press Ok to open from the new location. Note: Do not forget to regularly export/backup the database!</string>
<string name="brackets">Brackets</string>
<string name="cancel">Cancel</string>
<string name="ClearClipboard">Clipboard cleared.</string>

View File

@ -55,7 +55,17 @@
<intent android:action="keepass2android.ExportDatabaseActivity"/>
</PreferenceScreen>
<Preference
android:key="import_db_prefs"
android:title="@string/import_db_prefs"
/>
<Preference
android:key="import_keyfile_prefs"
android:title="@string/import_keyfile_prefs"
/>
</PreferenceScreen>
<PreferenceScreen

View File

@ -22,7 +22,12 @@ using Android.Content;
using Android.OS;
using Android.Widget;
using Android.Preferences;
using Java.IO;
using KeePassLib.Cryptography.Cipher;
using KeePassLib.Serialization;
using KeePassLib.Utility;
using keepass2android.Io;
using keepass2android.Utils;
namespace keepass2android
{
@ -173,6 +178,98 @@ namespace keepass2android
Preference algorithm = FindPreference(GetString(Resource.String.algorithm_key));
SetAlgorithm(db, algorithm);
UpdateImportDbPref();
}
private void UpdateImportDbPref()
{
//Import db/key file preferences:
Preference importDb = FindPreference("import_db_prefs");
if (!App.Kp2a.GetDb().Ioc.IsLocalFile())
{
importDb.Summary = GetString(Resource.String.OnlyAvailableForLocalFiles);
importDb.Enabled = false;
}
else
{
if (IoUtil.IsInInternalDirectory(App.Kp2a.GetDb().Ioc.Path, this))
{
importDb.Summary = GetString(Resource.String.FileIsInInternalDirectory);
importDb.Enabled = false;
}
else
{
importDb.Enabled = true;
importDb.PreferenceClick += delegate { MoveDbToInternalFolder(); };
}
}
}
private void MoveDbToInternalFolder()
{
Func<Action> copyAndReturnPostExecute = () =>
{
try
{
var sourceIoc = App.Kp2a.GetDb().Ioc;
var newIoc = ImportFileToInternalDirectory(sourceIoc);
return () =>
{
var builder = new AlertDialog.Builder(this);
builder
.SetMessage(Resource.String.DatabaseFileMoved);
builder.SetPositiveButton(Android.Resource.String.Ok, (sender, args) =>
PasswordActivity.Launch(this, newIoc, new NullTask()));
builder.Show();
};
}
catch (Exception e)
{
return () =>
{
Toast.MakeText(this, App.Kp2a.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, ToastLength.Long).Show();
};
}
};
new SimpleLoadingDialog(this, GetString(Resource.String.CopyingFile), false,
copyAndReturnPostExecute
).Execute();
}
private IOConnectionInfo ImportFileToInternalDirectory(IOConnectionInfo sourceIoc)
{
string targetPath = UrlUtil.GetFileName(sourceIoc.Path);
targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray());
if (targetPath == "")
targetPath = "imported";
if (new File(FilesDir, targetPath).Exists())
{
int c = 1;
var ext = UrlUtil.GetExtension(targetPath);
var filenameWithoutExt = UrlUtil.StripExtension(targetPath);
do
{
c++;
targetPath = filenameWithoutExt + c;
if (!String.IsNullOrEmpty(ext))
targetPath += "." + ext;
} while (new File(FilesDir, targetPath).Exists());
}
var targetIoc = IOConnectionInfo.FromPath(new File(FilesDir, targetPath).CanonicalPath);
IoUtil.Copy(targetIoc, sourceIoc, App.Kp2a);
return targetIoc;
}
private void SetRounds(Database db, Preference rounds)