added UI for opening a database with OTPs. Some TODOs and things not yet working!
This commit is contained in:
@@ -3,6 +3,7 @@ using Android.App;
|
||||
using System.IO;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using KeePassLib.Keys;
|
||||
using KeePassLib.Serialization;
|
||||
using keepass2android.Io;
|
||||
|
||||
@@ -22,7 +23,7 @@ namespace keepass2android
|
||||
/// <summary>
|
||||
/// Loads the specified data as the currently open database, as unlocked.
|
||||
/// </summary>
|
||||
void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, string s, string keyFile, ProgressDialogStatusLogger statusLogger);
|
||||
void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compKey, ProgressDialogStatusLogger statusLogger);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current database
|
||||
|
||||
@@ -107,16 +107,6 @@ namespace keepass2android.Io
|
||||
}
|
||||
}
|
||||
|
||||
public bool CompleteIoId()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool? FileExists()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
|
||||
{
|
||||
return UrlUtil.StripExtension(
|
||||
@@ -207,5 +197,19 @@ namespace keepass2android.Io
|
||||
parent += "/";
|
||||
return parent + newFilename;
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
|
||||
{
|
||||
return IoUtil.GetParentPath(ioc);
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)
|
||||
{
|
||||
IOConnectionInfo res = folderPath.CloneDeep();
|
||||
if (!res.Path.EndsWith("/"))
|
||||
res.Path += "/";
|
||||
res.Path += filename;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,16 +400,6 @@ namespace keepass2android.Io
|
||||
return new CachedWriteTransaction(ioc, useFileTransaction, this);
|
||||
}
|
||||
|
||||
public bool CompleteIoId()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool? FileExists()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
|
||||
{
|
||||
return UrlUtil.StripExtension(
|
||||
@@ -487,6 +477,54 @@ namespace keepass2android.Io
|
||||
return _cachedStorage.CreateFilePath(parent, newFilename);
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
|
||||
{
|
||||
return _cachedStorage.GetParentPath(ioc);
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
IOConnectionInfo res = _cachedStorage.GetFilePath(folderPath, filename);
|
||||
//some file storage implementations require accessing the network to determine the file path (e.g. because
|
||||
//they might contain file ids). In this case, we need to cache the result to enable cached access to such files
|
||||
StoreFilePath(folderPath, filename, res);
|
||||
return res;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
IOConnectionInfo res;
|
||||
if (!TryGetCachedFilePath(folderPath, filename, out res)) throw;
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void StoreFilePath(IOConnectionInfo folderPath, string filename, IOConnectionInfo res)
|
||||
{
|
||||
File.WriteAllText(CachedFilePath(GetPseudoIoc(folderPath, filename)) + ".filepath", res.Path);
|
||||
}
|
||||
|
||||
private IOConnectionInfo GetPseudoIoc(IOConnectionInfo folderPath, string filename)
|
||||
{
|
||||
IOConnectionInfo res = folderPath.CloneDeep();
|
||||
if (!res.Path.EndsWith("/"))
|
||||
res.Path += "/";
|
||||
res.Path += filename;
|
||||
return res;
|
||||
}
|
||||
|
||||
private bool TryGetCachedFilePath(IOConnectionInfo folderPath, string filename, out IOConnectionInfo res)
|
||||
{
|
||||
res = folderPath.CloneDeep();
|
||||
string filePathCache = CachedFilePath(GetPseudoIoc(folderPath, filename)) + ".filepath";
|
||||
if (!File.Exists(filePathCache))
|
||||
return false;
|
||||
res.Path = File.ReadAllText(filePathCache);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public string GetBaseVersionHash(IOConnectionInfo ioc)
|
||||
{
|
||||
|
||||
@@ -82,19 +82,6 @@ namespace keepass2android.Io
|
||||
/// <param name="useFileTransaction">if true, force to use file system level transaction. This might be ignored if the file storage has built in transaction support</param>
|
||||
IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction);
|
||||
|
||||
/// <summary>
|
||||
/// brings up a dialog to query credentials or something like this.
|
||||
/// </summary>
|
||||
/// <returns>true if success, false if error or cancelled by user</returns>
|
||||
bool CompleteIoId( /*in/out ioId*/);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the given file exists.
|
||||
/// </summary>
|
||||
/// <returns>true if it exists, false if not. Null if the check couldn't be performed (e.g. because no credentials available or no connection established.)</returns>
|
||||
bool? FileExists( /*ioId*/);
|
||||
|
||||
string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc);
|
||||
|
||||
/// <summary>
|
||||
@@ -135,10 +122,10 @@ namespace keepass2android.Io
|
||||
void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId);
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the process for choosing a file in the given file storage.
|
||||
/// Initiates the process for using a file in the given file storage.
|
||||
/// The file storage should either call OnImmediateResult or StartFileUsageProcess
|
||||
/// If alwaysReturnSuccess is true, the activity should be finished with ResultCode Ok.
|
||||
/// This can make sense if a higher-level file storage has the file cached by still wants to
|
||||
/// This can make sense if a higher-level file storage has the file cached but still wants to
|
||||
/// give the cached storage the chance to initialize file access.
|
||||
/// </summary>
|
||||
void PrepareFileUsage(IFileStorageSetupInitiatorActivity activity, IOConnectionInfo ioc, int requestCode, bool alwaysReturnSuccess);
|
||||
@@ -157,6 +144,17 @@ namespace keepass2android.Io
|
||||
//returns the path of a file "newFilename" in the folder "parent"
|
||||
//this may create the file if this is required to get a path (if a UUID is part of the file path)
|
||||
string CreateFilePath(string parent, string newFilename);
|
||||
|
||||
/// <summary>
|
||||
/// returns the parent folder of ioc
|
||||
/// </summary>
|
||||
IOConnectionInfo GetParentPath(IOConnectionInfo ioc);
|
||||
|
||||
/// <summary>
|
||||
/// returns the file path of the file "filename" in the folderPath.
|
||||
/// </summary>
|
||||
/// The method may throw FileNotFoundException or not in case the file doesn't exist.
|
||||
IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename);
|
||||
}
|
||||
|
||||
public interface IWriteTransaction: IDisposable
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Java.IO;
|
||||
using KeePassLib.Serialization;
|
||||
|
||||
namespace keepass2android.Io
|
||||
{
|
||||
@@ -30,5 +31,20 @@ namespace keepass2android.Io
|
||||
}
|
||||
|
||||
|
||||
public static IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
|
||||
{
|
||||
var iocParent = ioc.CloneDeep();
|
||||
if (iocParent.Path.EndsWith("/"))
|
||||
iocParent.Path = iocParent.Path.Substring(0, iocParent.Path.Length - 1);
|
||||
|
||||
int slashPos = iocParent.Path.LastIndexOf("/", StringComparison.Ordinal);
|
||||
if (slashPos == -1)
|
||||
iocParent.Path = "";
|
||||
else
|
||||
{
|
||||
iocParent.Path = iocParent.Path.Substring(0, slashPos);
|
||||
}
|
||||
return iocParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,16 +151,6 @@ namespace keepass2android.Io
|
||||
}
|
||||
}
|
||||
|
||||
public bool CompleteIoId()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool? FileExists()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
|
||||
{
|
||||
return UrlUtil.StripExtension(
|
||||
|
||||
@@ -82,29 +82,14 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Do not call this method directly. Call App.Kp2a.LoadDatabase instead.
|
||||
/// </summary>
|
||||
public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, MemoryStream databaseData, String password, String keyfile, ProgressDialogStatusLogger status)
|
||||
public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, MemoryStream databaseData, CompositeKey compositeKey, ProgressDialogStatusLogger status)
|
||||
{
|
||||
PwDatabase pwDatabase = new PwDatabase();
|
||||
|
||||
CompositeKey compositeKey = new CompositeKey();
|
||||
compositeKey.AddUserKey(new KcpPassword(password));
|
||||
if (!String.IsNullOrEmpty(keyfile))
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
compositeKey.AddUserKey(new KcpKeyFile(keyfile));
|
||||
} catch (Exception e)
|
||||
{
|
||||
Kp2aLog.Log(e.ToString());
|
||||
throw new KeyFileException();
|
||||
}
|
||||
}
|
||||
|
||||
IFileStorage fileStorage = _app.GetFileStorage(iocInfo);
|
||||
var filename = fileStorage.GetFilenameWithoutPathAndExt(iocInfo);
|
||||
try
|
||||
@@ -115,7 +100,9 @@ namespace keepass2android
|
||||
}
|
||||
catch (InvalidCompositeKeyException)
|
||||
{
|
||||
if ((password == "") && (keyfile != null))
|
||||
KcpPassword passwordKey = (KcpPassword)compositeKey.GetUserKey(typeof(KcpPassword));
|
||||
|
||||
if ((passwordKey != null) && (passwordKey.Password.ReadString() == "") && (compositeKey.UserKeyCount > 1))
|
||||
{
|
||||
//if we don't get a password, we don't know whether this means "empty password" or "no password"
|
||||
//retry without password:
|
||||
|
||||
@@ -19,6 +19,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using KeePassLib.Keys;
|
||||
using KeePassLib.Serialization;
|
||||
|
||||
namespace keepass2android
|
||||
@@ -26,20 +27,20 @@ namespace keepass2android
|
||||
public class LoadDb : RunnableOnFinish {
|
||||
private readonly IOConnectionInfo _ioc;
|
||||
private readonly Task<MemoryStream> _databaseData;
|
||||
private readonly String _pass;
|
||||
private readonly String _key;
|
||||
private readonly CompositeKey _compositeKey;
|
||||
private readonly string _keyfileOrProvider;
|
||||
private readonly IKp2aApp _app;
|
||||
private readonly bool _rememberKeyfile;
|
||||
|
||||
public LoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, String pass, String key, OnFinish finish): base(finish)
|
||||
public LoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish): base(finish)
|
||||
{
|
||||
_app = app;
|
||||
_ioc = ioc;
|
||||
_databaseData = databaseData;
|
||||
_pass = pass;
|
||||
_key = key;
|
||||
_compositeKey = compositeKey;
|
||||
_keyfileOrProvider = keyfileOrProvider;
|
||||
|
||||
|
||||
|
||||
_rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);
|
||||
}
|
||||
|
||||
@@ -50,8 +51,8 @@ namespace keepass2android
|
||||
{
|
||||
StatusLogger.UpdateMessage(UiStringKey.loading_database);
|
||||
MemoryStream memoryStream = _databaseData == null ? null : _databaseData.Result;
|
||||
_app.LoadDatabase(_ioc, memoryStream, _pass, _key, StatusLogger);
|
||||
SaveFileData(_ioc, _key);
|
||||
_app.LoadDatabase(_ioc, memoryStream, _compositeKey, StatusLogger);
|
||||
SaveFileData(_ioc, _keyfileOrProvider);
|
||||
|
||||
}
|
||||
catch (KeyFileException)
|
||||
@@ -88,13 +89,13 @@ namespace keepass2android
|
||||
Finish(true);
|
||||
}
|
||||
|
||||
private void SaveFileData(IOConnectionInfo ioc, String key) {
|
||||
private void SaveFileData(IOConnectionInfo ioc, String keyfileOrProvider) {
|
||||
|
||||
if (!_rememberKeyfile)
|
||||
{
|
||||
key = "";
|
||||
keyfileOrProvider = "";
|
||||
}
|
||||
_app.StoreOpenedFileAsRecent(ioc, key);
|
||||
_app.StoreOpenedFileAsRecent(ioc, keyfileOrProvider);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user