mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-11-29 04:22:22 -05:00
Key files can be opened from deliberate locations
TODO: fix a problem with .kdb-files and key files Added very basic and not yet functional AndroidContentStorage.cs
This commit is contained in:
parent
2e4c3e3490
commit
3239131a84
2
.gitignore
vendored
2
.gitignore
vendored
@ -282,3 +282,5 @@ Thumbs.db
|
|||||||
/src/java/MasterKee
|
/src/java/MasterKee
|
||||||
|
|
||||||
/src/PluginSdkBinding/obj/ReleaseNoNet
|
/src/PluginSdkBinding/obj/ReleaseNoNet
|
||||||
|
/src/MasterKeeWinPlugin/bin/Release
|
||||||
|
/src/SamplePlugin
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>False</Optimize>
|
<Optimize>False</Optimize>
|
||||||
<OutputPath>bin\Debug</OutputPath>
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;EXCLUDE_KEYTRANSFORM</DefineConstants>
|
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;INCLUDE_KEYTRANSFORM</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<ConsolePause>False</ConsolePause>
|
<ConsolePause>False</ConsolePause>
|
||||||
|
@ -41,7 +41,7 @@ namespace KeePassLib.Keys
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class KcpKeyFile : IUserKey
|
public sealed class KcpKeyFile : IUserKey
|
||||||
{
|
{
|
||||||
private string m_strPath;
|
private IOConnectionInfo m_ioc;
|
||||||
private ProtectedBinary m_pbKeyData;
|
private ProtectedBinary m_pbKeyData;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -49,7 +49,7 @@ namespace KeePassLib.Keys
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Path
|
public string Path
|
||||||
{
|
{
|
||||||
get { return m_strPath; }
|
get { return m_ioc.Path; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -62,6 +62,11 @@ namespace KeePassLib.Keys
|
|||||||
get { return m_pbKeyData; }
|
get { return m_pbKeyData; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IOConnectionInfo Ioc
|
||||||
|
{
|
||||||
|
get { return m_ioc; }
|
||||||
|
}
|
||||||
|
|
||||||
public KcpKeyFile(string strKeyFile)
|
public KcpKeyFile(string strKeyFile)
|
||||||
{
|
{
|
||||||
Construct(IOConnectionInfo.FromPath(strKeyFile), false);
|
Construct(IOConnectionInfo.FromPath(strKeyFile), false);
|
||||||
@ -82,9 +87,13 @@ namespace KeePassLib.Keys
|
|||||||
Construct(iocKeyFile, bThrowIfDbFile);
|
Construct(iocKeyFile, bThrowIfDbFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Construct(IOConnectionInfo iocFile, bool bThrowIfDbFile)
|
public KcpKeyFile(byte[] keyFileContents, IOConnectionInfo iocKeyFile, bool bThrowIfDbFile)
|
||||||
|
{
|
||||||
|
Construct(keyFileContents, iocKeyFile, bThrowIfDbFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Construct(byte[] pbFileData, IOConnectionInfo iocKeyFile, bool bThrowIfDbFile)
|
||||||
{
|
{
|
||||||
byte[] pbFileData = IOConnection.ReadFile(iocFile);
|
|
||||||
if (pbFileData == null) throw new Java.IO.FileNotFoundException();
|
if (pbFileData == null) throw new Java.IO.FileNotFoundException();
|
||||||
|
|
||||||
if (bThrowIfDbFile && (pbFileData.Length >= 8))
|
if (bThrowIfDbFile && (pbFileData.Length >= 8))
|
||||||
@ -110,12 +119,18 @@ namespace KeePassLib.Keys
|
|||||||
|
|
||||||
if (pbKey == null) throw new InvalidOperationException();
|
if (pbKey == null) throw new InvalidOperationException();
|
||||||
|
|
||||||
m_strPath = iocFile.Path;
|
m_ioc = iocKeyFile;
|
||||||
m_pbKeyData = new ProtectedBinary(true, pbKey);
|
m_pbKeyData = new ProtectedBinary(true, pbKey);
|
||||||
|
|
||||||
MemUtil.ZeroByteArray(pbKey);
|
MemUtil.ZeroByteArray(pbKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Construct(IOConnectionInfo iocFile, bool bThrowIfDbFile)
|
||||||
|
{
|
||||||
|
byte[] pbFileData = IOConnection.ReadFile(iocFile);
|
||||||
|
Construct(pbFileData, iocFile, bThrowIfDbFile);
|
||||||
|
}
|
||||||
|
|
||||||
// public void Clear()
|
// public void Clear()
|
||||||
// {
|
// {
|
||||||
// m_strPath = string.Empty;
|
// m_strPath = string.Empty;
|
||||||
|
183
src/Kp2aBusinessLogic/Io/AndroidContentStorage.cs
Normal file
183
src/Kp2aBusinessLogic/Io/AndroidContentStorage.cs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Runtime;
|
||||||
|
using Android.Views;
|
||||||
|
using Android.Widget;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
|
||||||
|
namespace keepass2android.Io
|
||||||
|
{
|
||||||
|
//TODOC,TOTEST, TODO: unimplemented methods?
|
||||||
|
public class AndroidContentStorage: IFileStorage
|
||||||
|
{
|
||||||
|
private readonly Context _ctx;
|
||||||
|
|
||||||
|
public AndroidContentStorage(Context ctx)
|
||||||
|
{
|
||||||
|
_ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> SupportedProtocols
|
||||||
|
{
|
||||||
|
get { yield return "content"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetCurrentFileVersionFast(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream OpenFileForRead(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
return _ctx.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(ioc.Path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
|
||||||
|
{
|
||||||
|
return new AndroidContentWriteTransaction(ioc.Path, _ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RequiresCredentials(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateDirectory(IOConnectionInfo ioc, string newDirName)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDescription GetFileDescription(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RequiresSetup(IOConnectionInfo ioConnection)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string IocToPath(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
return ioc.Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId)
|
||||||
|
{
|
||||||
|
Intent intent = new Intent();
|
||||||
|
activity.IocToIntent(intent, new IOConnectionInfo() { Path = protocolId + "://" });
|
||||||
|
activity.OnImmediateResult(requestCode, (int)FileStorageResults.FileChooserPrepared, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrepareFileUsage(IFileStorageSetupInitiatorActivity activity, IOConnectionInfo ioc, int requestCode,
|
||||||
|
bool alwaysReturnSuccess)
|
||||||
|
{
|
||||||
|
Intent intent = new Intent();
|
||||||
|
activity.IocToIntent(intent, ioc);
|
||||||
|
activity.OnImmediateResult(requestCode, (int)FileStorageResults.FileUsagePrepared, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnResume(IFileStorageSetupActivity activity)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnStart(IFileStorageSetupActivity activity)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDisplayName(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
return ioc.Path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateFilePath(string parent, string newFilename)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AndroidContentWriteTransaction : IWriteTransaction
|
||||||
|
{
|
||||||
|
private readonly string _path;
|
||||||
|
private readonly Context _ctx;
|
||||||
|
private MemoryStream _memoryStream;
|
||||||
|
|
||||||
|
public AndroidContentWriteTransaction(string path, Context ctx)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
_ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_memoryStream.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream OpenFile()
|
||||||
|
{
|
||||||
|
_memoryStream = new MemoryStream();
|
||||||
|
return _memoryStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CommitWrite()
|
||||||
|
{
|
||||||
|
using (Stream outputStream = _ctx.ContentResolver.OpenOutputStream(Android.Net.Uri.Parse(_path)))
|
||||||
|
{
|
||||||
|
outputStream.Write(_memoryStream.ToArray(), 0, (int)_memoryStream.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -20,7 +20,7 @@
|
|||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
<DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;EXCLUDE_KEYTRANSFORM</DefineConstants>
|
<DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;INCLUDE_KEYTRANSFORM</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -64,6 +64,7 @@
|
|||||||
<Compile Include="DataExchange\Formats\KeePassKdb2x.cs" />
|
<Compile Include="DataExchange\Formats\KeePassKdb2x.cs" />
|
||||||
<Compile Include="DataExchange\Formats\KeePassXml2x.cs" />
|
<Compile Include="DataExchange\Formats\KeePassXml2x.cs" />
|
||||||
<Compile Include="DataExchange\PwExportInfo.cs" />
|
<Compile Include="DataExchange\PwExportInfo.cs" />
|
||||||
|
<Compile Include="Io\AndroidContentStorage.cs" />
|
||||||
<Compile Include="Io\BuiltInFileStorage.cs" />
|
<Compile Include="Io\BuiltInFileStorage.cs" />
|
||||||
<Compile Include="Io\CachingFileStorage.cs" />
|
<Compile Include="Io\CachingFileStorage.cs" />
|
||||||
<Compile Include="Io\DropboxFileStorage.cs" />
|
<Compile Include="Io\DropboxFileStorage.cs" />
|
||||||
|
@ -11,5 +11,5 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-20
|
target=android-19
|
||||||
android.library=true
|
android.library=true
|
||||||
|
Binary file not shown.
@ -47,10 +47,14 @@ package com.keepassdroid.database;
|
|||||||
|
|
||||||
// Java
|
// Java
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PushbackInputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.DigestOutputStream;
|
import java.security.DigestOutputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
@ -125,18 +129,18 @@ public class PwDatabaseV3 {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void setMasterKey(String key, String keyFileName)
|
public void setMasterKey(String key, InputStream keyfileStream)
|
||||||
throws InvalidKeyFileException, IOException {
|
throws InvalidKeyFileException, IOException {
|
||||||
assert( key != null && keyFileName != null );
|
assert( key != null && keyfileStream != null );
|
||||||
|
|
||||||
masterKey = getMasterKey(key, keyFileName);
|
masterKey = getMasterKey(key, keyfileStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] getCompositeKey(String key, String keyFileName)
|
protected byte[] getCompositeKey(String key, InputStream keyfileStream)
|
||||||
throws InvalidKeyFileException, IOException {
|
throws InvalidKeyFileException, IOException {
|
||||||
assert(key != null && keyFileName != null);
|
assert(key != null && keyfileStream != null);
|
||||||
|
|
||||||
byte[] fileKey = getFileKey(keyFileName);
|
byte[] fileKey = getFileKey(keyfileStream);
|
||||||
|
|
||||||
byte[] passwordKey = getPasswordKey(key);
|
byte[] passwordKey = getPasswordKey(key);
|
||||||
|
|
||||||
@ -152,45 +156,39 @@ public class PwDatabaseV3 {
|
|||||||
return md.digest(fileKey);
|
return md.digest(fileKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] getFileKey(String fileName)
|
protected byte[] getFileKey(InputStream keyfileStream)
|
||||||
throws InvalidKeyFileException, IOException {
|
throws InvalidKeyFileException, IOException {
|
||||||
assert(fileName != null);
|
assert(keyfileStream != null);
|
||||||
|
|
||||||
File keyfile = new File(fileName);
|
|
||||||
|
|
||||||
if ( ! keyfile.exists() ) {
|
byte[] buff = new byte[8000];
|
||||||
throw new InvalidKeyFileException();
|
|
||||||
|
int bytesRead = 0;
|
||||||
|
|
||||||
|
ByteArrayOutputStream bao = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
while ((bytesRead = keyfileStream.read(buff)) != -1) {
|
||||||
|
bao.write(buff, 0, bytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] key = loadXmlKeyFile(fileName);
|
byte[] keyFileData = bao.toByteArray();
|
||||||
if ( key != null ) {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileInputStream fis;
|
ByteArrayInputStream bin = new ByteArrayInputStream(keyFileData);
|
||||||
try {
|
|
||||||
fis = new FileInputStream(keyfile);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new InvalidKeyFileException();
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedInputStream bis = new BufferedInputStream(fis, 64);
|
|
||||||
|
|
||||||
long fileSize = keyfile.length();
|
|
||||||
if ( fileSize == 0 ) {
|
if ( keyFileData.length == 32 ) {
|
||||||
throw new KeyFileEmptyException();
|
|
||||||
} else if ( fileSize == 32 ) {
|
|
||||||
byte[] outputKey = new byte[32];
|
byte[] outputKey = new byte[32];
|
||||||
if ( bis.read(outputKey, 0, 32) != 32 ) {
|
if ( bin.read(outputKey, 0, 32) != 32 ) {
|
||||||
throw new IOException("Error reading key.");
|
throw new IOException("Error reading key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputKey;
|
return outputKey;
|
||||||
} else if ( fileSize == 64 ) {
|
} else if ( keyFileData.length == 64 ) {
|
||||||
byte[] hex = new byte[64];
|
byte[] hex = new byte[64];
|
||||||
|
|
||||||
bis.mark(64);
|
bin.mark(64);
|
||||||
if ( bis.read(hex, 0, 64) != 64 ) {
|
if ( bin.read(hex, 0, 64) != 64 ) {
|
||||||
throw new IOException("Error reading key.");
|
throw new IOException("Error reading key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +196,7 @@ public class PwDatabaseV3 {
|
|||||||
return hexStringToByteArray(new String(hex));
|
return hexStringToByteArray(new String(hex));
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (IndexOutOfBoundsException e) {
|
||||||
// Key is not base 64, treat it as binary data
|
// Key is not base 64, treat it as binary data
|
||||||
bis.reset();
|
bin.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +212,7 @@ public class PwDatabaseV3 {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
int bytesRead = bis.read(buffer, 0, 2048);
|
bytesRead = bin.read(buffer, 0, 2048);
|
||||||
if ( bytesRead == -1 ) break; // End of file
|
if ( bytesRead == -1 ) break; // End of file
|
||||||
|
|
||||||
md.update(buffer, 0, bytesRead);
|
md.update(buffer, 0, bytesRead);
|
||||||
@ -495,16 +493,16 @@ public class PwDatabaseV3 {
|
|||||||
return newId;
|
return newId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getMasterKey(String key, String keyFileName)
|
public byte[] getMasterKey(String key, InputStream keyfileStream)
|
||||||
throws InvalidKeyFileException, IOException {
|
throws InvalidKeyFileException, IOException {
|
||||||
assert (key != null && keyFileName != null);
|
assert (key != null && keyfileStream != null);
|
||||||
|
|
||||||
if (key.length() > 0 && keyFileName.length() > 0) {
|
if (key.length() > 0 && keyfileStream != null) {
|
||||||
return getCompositeKey(key, keyFileName);
|
return getCompositeKey(key, keyfileStream);
|
||||||
} else if (key.length() > 0) {
|
} else if (key.length() > 0) {
|
||||||
return getPasswordKey(key);
|
return getPasswordKey(key);
|
||||||
} else if (keyFileName.length() > 0) {
|
} else if (keyfileStream != null) {
|
||||||
return getFileKey(keyFileName);
|
return getFileKey(keyfileStream);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Key cannot be empty.");
|
throw new IllegalArgumentException("Key cannot be empty.");
|
||||||
}
|
}
|
||||||
@ -515,11 +513,6 @@ public class PwDatabaseV3 {
|
|||||||
return getPasswordKey(key, "ISO-8859-1");
|
return getPasswordKey(key, "ISO-8859-1");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected byte[] loadXmlKeyFile(String fileName) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public long getNumRounds() {
|
public long getNumRounds() {
|
||||||
return numKeyEncRounds;
|
return numKeyEncRounds;
|
||||||
|
@ -123,13 +123,13 @@ public class ImporterV3 {
|
|||||||
* @throws InvalidAlgorithmParameterException if error decrypting main file body.
|
* @throws InvalidAlgorithmParameterException if error decrypting main file body.
|
||||||
* @throws ShortBufferException if error decrypting main file body.
|
* @throws ShortBufferException if error decrypting main file body.
|
||||||
*/
|
*/
|
||||||
public PwDatabaseV3 openDatabase( InputStream inStream, String password, String keyfile )
|
public PwDatabaseV3 openDatabase( InputStream inStream, String password, InputStream keyfileStream )
|
||||||
throws IOException, InvalidDBException
|
throws IOException, InvalidDBException
|
||||||
{
|
{
|
||||||
return openDatabase(inStream, password, keyfile, new UpdateStatus());
|
return openDatabase(inStream, password, keyfileStream, new UpdateStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PwDatabaseV3 openDatabase( InputStream inStream, String password, String keyfile, UpdateStatus status )
|
public PwDatabaseV3 openDatabase( InputStream inStream, String password, InputStream keyfileStream, UpdateStatus status )
|
||||||
throws IOException, InvalidDBException
|
throws IOException, InvalidDBException
|
||||||
{
|
{
|
||||||
PwDatabaseV3 newManager;
|
PwDatabaseV3 newManager;
|
||||||
@ -175,7 +175,7 @@ public class ImporterV3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newManager = createDB();
|
newManager = createDB();
|
||||||
newManager.setMasterKey( password, keyfile );
|
newManager.setMasterKey( password, keyfileStream );
|
||||||
|
|
||||||
// Select algorithm
|
// Select algorithm
|
||||||
if( (hdr.flags & PwDbHeaderV3.FLAG_RIJNDAEL) != 0 ) {
|
if( (hdr.flags & PwDbHeaderV3.FLAG_RIJNDAEL) != 0 ) {
|
||||||
|
Binary file not shown.
@ -327,9 +327,9 @@ namespace keepass2android
|
|||||||
defaultPath =>
|
defaultPath =>
|
||||||
{
|
{
|
||||||
if (defaultPath.StartsWith("sftp://"))
|
if (defaultPath.StartsWith("sftp://"))
|
||||||
Util.ShowSftpDialog(this, OnReceiveSftpData);
|
Util.ShowSftpDialog(this, OnReceiveSftpData, () => { });
|
||||||
else
|
else
|
||||||
Util.ShowFilenameDialog(this, OnCreateButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
Util.ShowFilenameDialog(this, OnCreateButton, null, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
||||||
Intents.RequestCodeFileBrowseForOpen);
|
Intents.RequestCodeFileBrowseForOpen);
|
||||||
}
|
}
|
||||||
), true, RequestCodeDbFilename, protocolId);
|
), true, RequestCodeDbFilename, protocolId);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
||||||
|
|
||||||
Keepass2Android is free software: you can redistribute it and/or modify
|
Keepass2Android is free software: you can redistribute it and/or modify
|
||||||
@ -682,7 +682,7 @@ namespace keepass2android
|
|||||||
addBinaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuAdd) , null, null, null);
|
addBinaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuAdd) , null, null, null);
|
||||||
addBinaryButton.Click += (sender, e) =>
|
addBinaryButton.Click += (sender, e) =>
|
||||||
{
|
{
|
||||||
Util.ShowBrowseDialog("/mnt/sdcard", this, Intents.RequestCodeFileBrowseForBinary, false);
|
Util.ShowBrowseDialog(this, Intents.RequestCodeFileBrowseForBinary, false);
|
||||||
|
|
||||||
};
|
};
|
||||||
binariesGroup.AddView(addBinaryButton,layoutParams);
|
binariesGroup.AddView(addBinaryButton,layoutParams);
|
||||||
|
@ -61,9 +61,9 @@ namespace keepass2android
|
|||||||
defaultPath =>
|
defaultPath =>
|
||||||
{
|
{
|
||||||
if (defaultPath.StartsWith("sftp://"))
|
if (defaultPath.StartsWith("sftp://"))
|
||||||
Util.ShowSftpDialog(this, OnReceiveSftpData);
|
Util.ShowSftpDialog(this, OnReceiveSftpData, () => { });
|
||||||
else
|
else
|
||||||
Util.ShowFilenameDialog(this, OnCreateButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
Util.ShowFilenameDialog(this, OnCreateButton, null, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
||||||
Intents.RequestCodeFileBrowseForOpen);
|
Intents.RequestCodeFileBrowseForOpen);
|
||||||
}
|
}
|
||||||
), true, RequestCodeDbFilename, protocolId);
|
), true, RequestCodeDbFilename, protocolId);
|
||||||
|
@ -14,7 +14,7 @@ namespace keepass2android
|
|||||||
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden , Theme="@style/NoTitleBar")]
|
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden , Theme="@style/NoTitleBar")]
|
||||||
public class FileStorageSelectionActivity : ListActivity
|
public class FileStorageSelectionActivity : ListActivity
|
||||||
{
|
{
|
||||||
private ActivityDesign _design;
|
private readonly ActivityDesign _design;
|
||||||
|
|
||||||
private FileStorageAdapter _fileStorageAdapter;
|
private FileStorageAdapter _fileStorageAdapter;
|
||||||
|
|
||||||
@ -42,6 +42,9 @@ namespace keepass2android
|
|||||||
//put file:// to the top
|
//put file:// to the top
|
||||||
_protocolIds.Remove("file");
|
_protocolIds.Remove("file");
|
||||||
_protocolIds.Insert(0, "file");
|
_protocolIds.Insert(0, "file");
|
||||||
|
//remove "content" (covered by androidget)
|
||||||
|
_protocolIds.Remove("content");
|
||||||
|
|
||||||
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppGet, false))
|
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppGet, false))
|
||||||
_protocolIds.Add("androidget");
|
_protocolIds.Add("androidget");
|
||||||
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppSend, false))
|
if (context.Intent.GetBooleanExtra(AllowThirdPartyAppSend, false))
|
||||||
|
@ -24,6 +24,7 @@ using System.Xml.Serialization;
|
|||||||
using Android.App;
|
using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.Database;
|
using Android.Database;
|
||||||
|
using Android.Graphics.Drawables;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
using Android.Views;
|
using Android.Views;
|
||||||
@ -86,7 +87,7 @@ namespace keepass2android
|
|||||||
private const int RequestCodePrepareDbFile = 1000;
|
private const int RequestCodePrepareDbFile = 1000;
|
||||||
private const int RequestCodePrepareOtpAuxFile = 1001;
|
private const int RequestCodePrepareOtpAuxFile = 1001;
|
||||||
private const int RequestCodeChallengeYubikey = 1002;
|
private const int RequestCodeChallengeYubikey = 1002;
|
||||||
|
private const int RequestCodeSelectKeyfile = 1003;
|
||||||
|
|
||||||
private Task<MemoryStream> _loadDbTask;
|
private Task<MemoryStream> _loadDbTask;
|
||||||
private IOConnectionInfo _ioConnection;
|
private IOConnectionInfo _ioConnection;
|
||||||
@ -137,6 +138,7 @@ namespace keepass2android
|
|||||||
private ActivityDesign _design;
|
private ActivityDesign _design;
|
||||||
private bool _performingLoad;
|
private bool _performingLoad;
|
||||||
|
|
||||||
|
|
||||||
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
|
||||||
: base(javaReference, transfer)
|
: base(javaReference, transfer)
|
||||||
{
|
{
|
||||||
@ -258,26 +260,20 @@ namespace keepass2android
|
|||||||
|
|
||||||
KcpKeyFile kcpKeyfile = (KcpKeyFile)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpKeyFile));
|
KcpKeyFile kcpKeyfile = (KcpKeyFile)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpKeyFile));
|
||||||
|
|
||||||
SetEditText(Resource.Id.pass_keyfile, kcpKeyfile.Path);
|
FindViewById<TextView>(Resource.Id.label_keyfilename).Text =
|
||||||
|
App.Kp2a.GetFileStorage(kcpKeyfile.Ioc).GetDisplayName(kcpKeyfile.Ioc);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App.Kp2a.LockDatabase(false);
|
App.Kp2a.LockDatabase(false);
|
||||||
break;
|
break;
|
||||||
case Result.Ok: // Key file browse dialog OK'ed.
|
case Result.Ok:
|
||||||
if (requestCode == Intents.RequestCodeFileBrowseForKeyfile) {
|
if (requestCode == RequestCodeSelectKeyfile)
|
||||||
string filename = Util.IntentToFilename(data, this);
|
{
|
||||||
if (filename != null) {
|
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||||
if (filename.StartsWith("file://")) {
|
SetIoConnectionFromIntent(ioc, data);
|
||||||
filename = filename.Substring(7);
|
_keyFileOrProvider = IOConnectionInfo.SerializeToString(ioc);
|
||||||
}
|
UpdateKeyfileIocView();
|
||||||
|
|
||||||
filename = URLDecoder.Decode(filename);
|
|
||||||
|
|
||||||
EditText fn = (EditText) FindViewById(Resource.Id.pass_keyfile);
|
|
||||||
fn.Text = filename;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case (Result)FileStorageResults.FileUsagePrepared:
|
case (Result)FileStorageResults.FileUsagePrepared:
|
||||||
@ -354,6 +350,39 @@ namespace keepass2android
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void UpdateKeyfileIocView()
|
||||||
|
{
|
||||||
|
//store keyfile in the view so that we can show the selected keyfile again if the user switches to another key provider and back to key file
|
||||||
|
FindViewById<TextView>(Resource.Id.label_keyfilename).Tag = _keyFileOrProvider;
|
||||||
|
if (string.IsNullOrEmpty(_keyFileOrProvider))
|
||||||
|
{
|
||||||
|
FindViewById<TextView>(Resource.Id.filestorage_label).Visibility = ViewStates.Gone;
|
||||||
|
FindViewById<ImageView>(Resource.Id.filestorage_logo).Visibility = ViewStates.Gone;
|
||||||
|
FindViewById<TextView>(Resource.Id.label_keyfilename).Text = Resources.GetString(Resource.String.no_keyfile_selected);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var ioc = IOConnectionInfo.UnserializeFromString(_keyFileOrProvider);
|
||||||
|
string displayPath = App.Kp2a.GetFileStorage(ioc).GetDisplayName(ioc);
|
||||||
|
int protocolSeparatorPos = displayPath.IndexOf("://", StringComparison.Ordinal);
|
||||||
|
string protocolId = protocolSeparatorPos < 0 ?
|
||||||
|
"file" : displayPath.Substring(0, protocolSeparatorPos);
|
||||||
|
Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId);
|
||||||
|
FindViewById<ImageView>(Resource.Id.filestorage_logo).SetImageDrawable(drawable);
|
||||||
|
FindViewById<ImageView>(Resource.Id.filestorage_logo).Visibility = ViewStates.Visible;
|
||||||
|
|
||||||
|
|
||||||
|
String title = App.Kp2a.GetResourceString("filestoragename_" + protocolId);
|
||||||
|
FindViewById<TextView>(Resource.Id.filestorage_label).Text = title;
|
||||||
|
FindViewById<TextView>(Resource.Id.filestorage_label).Visibility = ViewStates.Visible;
|
||||||
|
|
||||||
|
FindViewById<TextView>(Resource.Id.label_keyfilename).Text = protocolSeparatorPos < 0 ?
|
||||||
|
displayPath :
|
||||||
|
displayPath.Substring(protocolSeparatorPos + 3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void LoadOtpFile()
|
private void LoadOtpFile()
|
||||||
{
|
{
|
||||||
new LoadingDialog<object, object, object>(this, true,
|
new LoadingDialog<object, object, object>(this, true,
|
||||||
@ -543,14 +572,11 @@ namespace keepass2android
|
|||||||
InitializeFilenameView();
|
InitializeFilenameView();
|
||||||
|
|
||||||
if (KeyProviderType == KeyProviders.KeyFile)
|
if (KeyProviderType == KeyProviders.KeyFile)
|
||||||
SetEditText(Resource.Id.pass_keyfile, _keyFileOrProvider);
|
|
||||||
|
|
||||||
FindViewById<EditText>(Resource.Id.pass_keyfile).TextChanged +=
|
|
||||||
(sender, args) =>
|
|
||||||
{
|
{
|
||||||
_keyFileOrProvider = FindViewById<EditText>(Resource.Id.pass_keyfile).Text;
|
UpdateKeyfileIocView();
|
||||||
UpdateOkButtonState();
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
FindViewById<EditText>(Resource.Id.password).TextChanged +=
|
FindViewById<EditText>(Resource.Id.password).TextChanged +=
|
||||||
(sender, args) =>
|
(sender, args) =>
|
||||||
@ -705,20 +731,14 @@ namespace keepass2android
|
|||||||
|
|
||||||
private void InitializeKeyfileBrowseButton()
|
private void InitializeKeyfileBrowseButton()
|
||||||
{
|
{
|
||||||
ImageButton browse = (ImageButton) FindViewById(Resource.Id.browse_button);
|
var browseButton = (Button)FindViewById(Resource.Id.btn_change_location);
|
||||||
browse.Click += (sender, evt) =>
|
browseButton.Click += (sender, evt) =>
|
||||||
{
|
{
|
||||||
string filename = null;
|
Intent intent = new Intent(this, typeof(SelectStorageLocationActivity));
|
||||||
if (!String.IsNullOrEmpty(_ioConnection.Path))
|
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppGet, true);
|
||||||
{
|
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppSend, false);
|
||||||
File keyfile = new File(_ioConnection.Path);
|
intent.PutExtra(FileStorageSetupDefs.ExtraIsForSave, false);
|
||||||
File parent = keyfile.ParentFile;
|
StartActivityForResult(intent, RequestCodeSelectKeyfile);
|
||||||
if (parent != null)
|
|
||||||
{
|
|
||||||
filename = parent.AbsolutePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Util.ShowBrowseDialog(filename, this, Intents.RequestCodeFileBrowseForKeyfile, false);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -738,7 +758,7 @@ namespace keepass2android
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
//don't set to "" to prevent losing the filename. (ItemSelected is also called during recreation!)
|
//don't set to "" to prevent losing the filename. (ItemSelected is also called during recreation!)
|
||||||
_keyFileOrProvider = FindViewById<EditText>(Resource.Id.pass_keyfile).Text;
|
_keyFileOrProvider = (FindViewById(Resource.Id.label_keyfilename).Tag ?? "").ToString();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_keyFileOrProvider = KeyProviderIdOtp;
|
_keyFileOrProvider = KeyProviderIdOtp;
|
||||||
@ -779,7 +799,7 @@ namespace keepass2android
|
|||||||
_showPassword = savedInstanceState.GetBoolean(ShowpasswordKey, false);
|
_showPassword = savedInstanceState.GetBoolean(ShowpasswordKey, false);
|
||||||
MakePasswordMaskedOrVisible();
|
MakePasswordMaskedOrVisible();
|
||||||
|
|
||||||
_keyFileOrProvider = FindViewById<EditText>(Resource.Id.pass_keyfile).Text = savedInstanceState.GetString(KeyFileOrProviderKey);
|
_keyFileOrProvider = savedInstanceState.GetString(KeyFileOrProviderKey);
|
||||||
_password = FindViewById<EditText>(Resource.Id.password).Text = savedInstanceState.GetString(PasswordKey);
|
_password = FindViewById<EditText>(Resource.Id.password).Text = savedInstanceState.GetString(PasswordKey);
|
||||||
|
|
||||||
_pendingOtps = new List<string>(savedInstanceState.GetStringArrayList(PendingOtpsKey));
|
_pendingOtps = new List<string>(savedInstanceState.GetStringArrayList(PendingOtpsKey));
|
||||||
@ -850,6 +870,11 @@ namespace keepass2android
|
|||||||
FindViewById(Resource.Id.keyfileLine).Visibility = KeyProviderType == KeyProviders.KeyFile
|
FindViewById(Resource.Id.keyfileLine).Visibility = KeyProviderType == KeyProviders.KeyFile
|
||||||
? ViewStates.Visible
|
? ViewStates.Visible
|
||||||
: ViewStates.Gone;
|
: ViewStates.Gone;
|
||||||
|
if (KeyProviderType == KeyProviders.KeyFile)
|
||||||
|
{
|
||||||
|
UpdateKeyfileIocView();
|
||||||
|
}
|
||||||
|
|
||||||
FindViewById(Resource.Id.otpView).Visibility = KeyProviderType == KeyProviders.Otp
|
FindViewById(Resource.Id.otpView).Visibility = KeyProviderType == KeyProviders.Otp
|
||||||
? ViewStates.Visible
|
? ViewStates.Visible
|
||||||
: ViewStates.Gone;
|
: ViewStates.Gone;
|
||||||
@ -880,12 +905,26 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
compositeKey.AddUserKey(new KcpKeyFile(_keyFileOrProvider));
|
if (_keyFileOrProvider == "")
|
||||||
|
throw new System.IO.FileNotFoundException();
|
||||||
|
var ioc = IOConnectionInfo.UnserializeFromString(_keyFileOrProvider);
|
||||||
|
using (var stream = App.Kp2a.GetFileStorage(ioc).OpenFileForRead(ioc))
|
||||||
|
{
|
||||||
|
byte[] keyfileData = StreamToMemoryStream(stream).ToArray();
|
||||||
|
compositeKey.AddUserKey(new KcpKeyFile(keyfileData, ioc, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (System.IO.FileNotFoundException e)
|
||||||
|
{
|
||||||
|
Kp2aLog.Log(e.ToString());
|
||||||
|
Toast.MakeText(this, App.Kp2a.GetResourceString(UiStringKey.keyfile_does_not_exist), ToastLength.Long).Show();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Kp2aLog.Log(e.ToString());
|
Kp2aLog.Log(e.ToString());
|
||||||
Toast.MakeText(this, App.Kp2a.GetResourceString(UiStringKey.keyfile_does_not_exist), ToastLength.Long).Show();
|
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1032,10 +1071,19 @@ namespace keepass2android
|
|||||||
var fileStorage = App.Kp2a.GetFileStorage(_ioConnection);
|
var fileStorage = App.Kp2a.GetFileStorage(_ioConnection);
|
||||||
var stream = fileStorage.OpenFileForRead(_ioConnection);
|
var stream = fileStorage.OpenFileForRead(_ioConnection);
|
||||||
|
|
||||||
|
var memoryStream = StreamToMemoryStream(stream);
|
||||||
|
|
||||||
|
Kp2aLog.Log("Pre-loading database file completed");
|
||||||
|
|
||||||
|
return memoryStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MemoryStream StreamToMemoryStream(Stream stream)
|
||||||
|
{
|
||||||
var memoryStream = stream as MemoryStream;
|
var memoryStream = stream as MemoryStream;
|
||||||
if (memoryStream == null)
|
if (memoryStream == null)
|
||||||
{
|
{
|
||||||
// Read the file into memory
|
// Read the stream into memory
|
||||||
int capacity = 4096; // Default initial capacity, if stream can't report it.
|
int capacity = 4096; // Default initial capacity, if stream can't report it.
|
||||||
if (stream.CanSeek)
|
if (stream.CanSeek)
|
||||||
{
|
{
|
||||||
@ -1044,11 +1092,8 @@ namespace keepass2android
|
|||||||
memoryStream = new MemoryStream(capacity);
|
memoryStream = new MemoryStream(capacity);
|
||||||
stream.CopyTo(memoryStream);
|
stream.CopyTo(memoryStream);
|
||||||
stream.Close();
|
stream.Close();
|
||||||
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Kp2aLog.Log("Pre-loading database file completed");
|
|
||||||
|
|
||||||
return memoryStream;
|
return memoryStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6126
src/keepass2android/Resources/Resource.designer.cs
generated
6126
src/keepass2android/Resources/Resource.designer.cs
generated
File diff suppressed because it is too large
Load Diff
@ -86,25 +86,61 @@ android:layout_height="match_parent"
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/ic_menu_view" />
|
android:src="@drawable/ic_menu_view" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/keyfileLine"
|
android:id="@+id/keyfileLine"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal">
|
android:orientation="vertical">
|
||||||
<EditText
|
|
||||||
android:id="@+id/pass_keyfile"
|
<TextView
|
||||||
android:layout_width="0px"
|
android:id="@+id/keyfile_heading"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:hint="@string/entry_keyfile" />
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/browse_button"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/ic_launcher_folder_small" />
|
android:text="@string/keyfile_heading" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/filestorage_logo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_storage_file"
|
||||||
|
android:padding="5dp"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/filestorage_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:text="Local file (TODO!)"
|
||||||
|
android:textSize="16dp" >
|
||||||
|
</TextView>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_keyfilename"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="[path]"
|
||||||
|
android:layout_marginLeft="18dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button android:id="@+id/btn_change_location"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/button_change_location"
|
||||||
|
style="@style/TextAppearance_SubElement"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/otpView"
|
android:id="@+id/otpView"
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
<string name="ShowGroupInEntry_title">Show group name in entry view</string>
|
<string name="ShowGroupInEntry_title">Show group name in entry view</string>
|
||||||
|
|
||||||
|
<string name="unknown_uri_scheme">Sorry! Keepass2Android cannot handle the returned URI %1$s. Please contact the developer!</string>
|
||||||
|
|
||||||
<string name="security_prefs">Security</string>
|
<string name="security_prefs">Security</string>
|
||||||
<string name="display_prefs">Display</string>
|
<string name="display_prefs">Display</string>
|
||||||
<string name="password_access_prefs">Password entry access</string>
|
<string name="password_access_prefs">Password entry access</string>
|
||||||
@ -68,6 +70,7 @@
|
|||||||
<string name="entry_expires">Expires</string>
|
<string name="entry_expires">Expires</string>
|
||||||
<string name="entry_group_name">Group Name</string>
|
<string name="entry_group_name">Group Name</string>
|
||||||
<string name="entry_keyfile">Key file (optional)</string>
|
<string name="entry_keyfile">Key file (optional)</string>
|
||||||
|
<string name="keyfile_heading">Key file</string>
|
||||||
<string name="entry_modified">Modified</string>
|
<string name="entry_modified">Modified</string>
|
||||||
<string name="entry_password">Password</string>
|
<string name="entry_password">Password</string>
|
||||||
<string name="entry_save">Save</string>
|
<string name="entry_save">Save</string>
|
||||||
@ -114,6 +117,7 @@
|
|||||||
<string name="invalid_algorithm">Invalid algorithm.</string>
|
<string name="invalid_algorithm">Invalid algorithm.</string>
|
||||||
<string name="invalid_db_sig">Database format not recognized.</string>
|
<string name="invalid_db_sig">Database format not recognized.</string>
|
||||||
<string name="keyfile_does_not_exist">Key file does not exist.</string>
|
<string name="keyfile_does_not_exist">Key file does not exist.</string>
|
||||||
|
<string name="no_keyfile_selected">No key file selected.</string>
|
||||||
<string name="keyfile_is_empty">Key file is empty.</string>
|
<string name="keyfile_is_empty">Key file is empty.</string>
|
||||||
<string name="length">Length</string>
|
<string name="length">Length</string>
|
||||||
<string name="list_size_title">Group list size</string>
|
<string name="list_size_title">Group list size</string>
|
||||||
|
245
src/keepass2android/SelectStorageLocationActivity.cs
Normal file
245
src/keepass2android/SelectStorageLocationActivity.cs
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
|
using Android.Runtime;
|
||||||
|
using Android.Views;
|
||||||
|
using Android.Widget;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
using keepass2android.Io;
|
||||||
|
using Environment = Android.OS.Environment;
|
||||||
|
|
||||||
|
namespace keepass2android
|
||||||
|
{
|
||||||
|
[Activity(Label = "")]
|
||||||
|
public class SelectStorageLocationActivity : Activity
|
||||||
|
{
|
||||||
|
private ActivityDesign _design;
|
||||||
|
private bool _isRecreated;
|
||||||
|
private const int RequestCodeFileStorageSelection = 983713;
|
||||||
|
|
||||||
|
public SelectStorageLocationActivity()
|
||||||
|
{
|
||||||
|
_design = new ActivityDesign(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnCreate(Bundle bundle)
|
||||||
|
{
|
||||||
|
base.OnCreate(bundle);
|
||||||
|
|
||||||
|
_design.ApplyTheme();
|
||||||
|
|
||||||
|
|
||||||
|
Kp2aLog.Log("SelectStorageLocationActivity.OnCreate");
|
||||||
|
|
||||||
|
IsForSave = Intent.GetBooleanExtra(FileStorageSetupDefs.ExtraIsForSave, false);
|
||||||
|
if (IsForSave)
|
||||||
|
{
|
||||||
|
throw new Exception("save is not yet implemented. In StartSelectFile, no handler for onCreate is passed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool allowThirdPartyGet = Intent.GetBooleanExtra(FileStorageSelectionActivity.AllowThirdPartyAppGet, false);
|
||||||
|
bool allowThirdPartySend = Intent.GetBooleanExtra(FileStorageSelectionActivity.AllowThirdPartyAppSend, false);
|
||||||
|
if (bundle == null)
|
||||||
|
State = new Bundle();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
State = (Bundle)bundle.Clone();
|
||||||
|
_isRecreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_isRecreated)
|
||||||
|
{
|
||||||
|
Intent intent = new Intent(this, typeof(FileStorageSelectionActivity));
|
||||||
|
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppGet, allowThirdPartyGet);
|
||||||
|
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppSend, allowThirdPartySend);
|
||||||
|
StartActivityForResult(intent, RequestCodeFileStorageSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Bundle State { get; set; }
|
||||||
|
|
||||||
|
protected bool IsForSave { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnSaveInstanceState(Bundle outState)
|
||||||
|
{
|
||||||
|
base.OnSaveInstanceState(outState);
|
||||||
|
|
||||||
|
outState.PutAll(State);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnResume()
|
||||||
|
{
|
||||||
|
base.OnResume();
|
||||||
|
_design.ReapplyTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||||
|
{
|
||||||
|
base.OnActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == RequestCodeFileStorageSelection)
|
||||||
|
{
|
||||||
|
if (resultCode == KeePass.ExitFileStorageSelectionOk)
|
||||||
|
{
|
||||||
|
|
||||||
|
string protocolId = data.GetStringExtra("protocolId");
|
||||||
|
|
||||||
|
if (protocolId == "androidget")
|
||||||
|
{
|
||||||
|
Util.ShowBrowseDialog(this, Intents.RequestCodeFileBrowseForOpen, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
App.Kp2a.GetFileStorage(protocolId).StartSelectFile(new FileStorageSetupInitiatorActivity(this,
|
||||||
|
OnActivityResult,
|
||||||
|
defaultPath =>
|
||||||
|
{
|
||||||
|
if (defaultPath.StartsWith("sftp://"))
|
||||||
|
Util.ShowSftpDialog(this, OnReceivedSftpData, ReturnCancel);
|
||||||
|
else
|
||||||
|
Util.ShowFilenameDialog(this, OnOpenButton, null, ReturnCancel, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
||||||
|
Intents.RequestCodeFileBrowseForOpen);
|
||||||
|
}
|
||||||
|
), false, 0, protocolId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (resultCode == (Result)FileStorageResults.FileChooserPrepared)
|
||||||
|
{
|
||||||
|
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||||
|
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
|
||||||
|
#if !EXCLUDE_FILECHOOSER
|
||||||
|
StartFileChooser(ioc.Path);
|
||||||
|
#else
|
||||||
|
ReturnIoc(new IOConnectionInfo { Path = "/mnt/sdcard/keepass/yubi.kdbx" });
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((resultCode == Result.Canceled) && (data != null) && (data.HasExtra("EXTRA_ERROR_MESSAGE")))
|
||||||
|
{
|
||||||
|
Toast.MakeText(this, data.GetStringExtra("EXTRA_ERROR_MESSAGE"), ToastLength.Long).Show();
|
||||||
|
}
|
||||||
|
ReturnCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestCode == Intents.RequestCodeFileBrowseForOpen)
|
||||||
|
{
|
||||||
|
if (resultCode == Result.Ok)
|
||||||
|
{
|
||||||
|
string filename = Util.IntentToFilename(data, this);
|
||||||
|
if (filename != null)
|
||||||
|
{
|
||||||
|
if (filename.StartsWith("file://"))
|
||||||
|
{
|
||||||
|
filename = filename.Substring(7);
|
||||||
|
filename = Java.Net.URLDecoder.Decode(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOConnectionInfo ioc = new IOConnectionInfo
|
||||||
|
{
|
||||||
|
Path = filename
|
||||||
|
};
|
||||||
|
|
||||||
|
ReturnIoc(ioc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (data.Data.Scheme == "content")
|
||||||
|
{
|
||||||
|
ReturnIoc(IOConnectionInfo.FromPath(data.DataString));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Toast.MakeText(this, Resources.GetString(Resource.String.unknown_uri_scheme, new Java.Lang.Object[] {data.DataString}),
|
||||||
|
ToastLength.Long).Show();
|
||||||
|
ReturnCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ReturnCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReturnCancel()
|
||||||
|
{
|
||||||
|
SetResult(Result.Canceled);
|
||||||
|
Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReturnIoc(IOConnectionInfo ioc)
|
||||||
|
{
|
||||||
|
Intent intent = new Intent();
|
||||||
|
PasswordActivity.PutIoConnectionToIntent(ioc, intent);
|
||||||
|
SetResult(Result.Ok, intent);
|
||||||
|
Finish();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnReceivedSftpData(string filename)
|
||||||
|
{
|
||||||
|
IOConnectionInfo ioc = new IOConnectionInfo { Path = filename };
|
||||||
|
#if !EXCLUDE_FILECHOOSER
|
||||||
|
StartFileChooser(ioc.Path);
|
||||||
|
#else
|
||||||
|
ReturnIoc(ioc);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !EXCLUDE_FILECHOOSER
|
||||||
|
private void StartFileChooser(string defaultPath)
|
||||||
|
{
|
||||||
|
Kp2aLog.Log("FSA: defaultPath="+defaultPath);
|
||||||
|
string fileProviderAuthority = FileChooserFileProvider.TheAuthority;
|
||||||
|
if (defaultPath.StartsWith("file://"))
|
||||||
|
{
|
||||||
|
fileProviderAuthority = PackageName+".android-filechooser.localfile";
|
||||||
|
}
|
||||||
|
Intent i = Keepass2android.Kp2afilechooser.Kp2aFileChooserBridge.GetLaunchFileChooserIntent(this, fileProviderAuthority,
|
||||||
|
defaultPath);
|
||||||
|
|
||||||
|
StartActivityForResult(i, Intents.RequestCodeFileBrowseForOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
private bool OnOpenButton(String fileName)
|
||||||
|
{
|
||||||
|
|
||||||
|
IOConnectionInfo ioc = new IOConnectionInfo
|
||||||
|
{
|
||||||
|
Path = fileName
|
||||||
|
};
|
||||||
|
|
||||||
|
ReturnIoc(ioc);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -141,7 +141,7 @@ namespace keepass2android
|
|||||||
return list.Count > 0;
|
return list.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowBrowseDialog(string filename, Activity act, int requestCodeBrowse, bool forSaving)
|
public static void ShowBrowseDialog(Activity act, int requestCodeBrowse, bool forSaving)
|
||||||
{
|
{
|
||||||
if ((!forSaving) && (IsIntentAvailable(act, Intent.ActionGetContent, "*/*", new List<string> { Intent.CategoryOpenable})))
|
if ((!forSaving) && (IsIntentAvailable(act, Intent.ActionGetContent, "*/*", new List<string> { Intent.CategoryOpenable})))
|
||||||
{
|
{
|
||||||
@ -223,7 +223,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
public delegate bool FileSelectedHandler(string filename);
|
public delegate bool FileSelectedHandler(string filename);
|
||||||
|
|
||||||
public static void ShowSftpDialog(Activity activity, FileSelectedHandler onStartBrowse)
|
public static void ShowSftpDialog(Activity activity, FileSelectedHandler onStartBrowse, Action onCancel)
|
||||||
{
|
{
|
||||||
#if !EXCLUDE_JAVAFILESTORAGE
|
#if !EXCLUDE_JAVAFILESTORAGE
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
@ -244,7 +244,7 @@ namespace keepass2android
|
|||||||
password);
|
password);
|
||||||
onStartBrowse(sftpPath);
|
onStartBrowse(sftpPath);
|
||||||
});
|
});
|
||||||
builder.SetNegativeButton(Android.Resource.String.Cancel, (sender, args) => {});
|
builder.SetNegativeButton(Android.Resource.String.Cancel, onCancel);
|
||||||
builder.SetTitle(activity.GetString(Resource.String.enter_sftp_login_title));
|
builder.SetTitle(activity.GetString(Resource.String.enter_sftp_login_title));
|
||||||
Dialog dialog = builder.Create();
|
Dialog dialog = builder.Create();
|
||||||
|
|
||||||
@ -252,8 +252,22 @@ namespace keepass2android
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowFilenameDialog(Activity activity, FileSelectedHandler onOpen, FileSelectedHandler onCreate, bool showBrowseButton,
|
class DismissListener: Java.Lang.Object, IDialogInterfaceOnDismissListener
|
||||||
string defaultFilename, string detailsText, int requestCodeBrowse)
|
{
|
||||||
|
private readonly Action _onDismiss;
|
||||||
|
|
||||||
|
public DismissListener(Action onDismiss)
|
||||||
|
{
|
||||||
|
_onDismiss = onDismiss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDismiss(IDialogInterface dialog)
|
||||||
|
{
|
||||||
|
_onDismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ShowFilenameDialog(Activity activity, FileSelectedHandler onOpen, FileSelectedHandler onCreate, Action onCancel, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
|
||||||
{
|
{
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
builder.SetView(activity.LayoutInflater.Inflate(Resource.Layout.file_selection_filename, null));
|
builder.SetView(activity.LayoutInflater.Inflate(Resource.Layout.file_selection_filename, null));
|
||||||
@ -262,6 +276,7 @@ namespace keepass2android
|
|||||||
|
|
||||||
Button openButton = (Button) dialog.FindViewById(Resource.Id.open);
|
Button openButton = (Button) dialog.FindViewById(Resource.Id.open);
|
||||||
Button createButton = (Button) dialog.FindViewById(Resource.Id.create);
|
Button createButton = (Button) dialog.FindViewById(Resource.Id.create);
|
||||||
|
|
||||||
TextView enterFilenameDetails = (TextView) dialog.FindViewById(Resource.Id.label_open_by_filename_details);
|
TextView enterFilenameDetails = (TextView) dialog.FindViewById(Resource.Id.label_open_by_filename_details);
|
||||||
openButton.Visibility = onOpen != null ? ViewStates.Visible : ViewStates.Gone;
|
openButton.Visibility = onOpen != null ? ViewStates.Visible : ViewStates.Gone;
|
||||||
createButton.Visibility = onCreate != null? ViewStates.Visible : ViewStates.Gone;
|
createButton.Visibility = onCreate != null? ViewStates.Visible : ViewStates.Gone;
|
||||||
@ -290,7 +305,15 @@ namespace keepass2android
|
|||||||
};
|
};
|
||||||
|
|
||||||
Button cancelButton = (Button) dialog.FindViewById(Resource.Id.fnv_cancel);
|
Button cancelButton = (Button) dialog.FindViewById(Resource.Id.fnv_cancel);
|
||||||
cancelButton.Click += (sender, e) => dialog.Dismiss();
|
cancelButton.Click += delegate
|
||||||
|
{
|
||||||
|
dialog.Dismiss();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if (onCancel != null)
|
||||||
|
dialog.SetOnDismissListener(new DismissListener(onCancel));
|
||||||
|
|
||||||
|
|
||||||
ImageButton browseButton = (ImageButton) dialog.FindViewById(Resource.Id.browse_button);
|
ImageButton browseButton = (ImageButton) dialog.FindViewById(Resource.Id.browse_button);
|
||||||
if (!showBrowseButton)
|
if (!showBrowseButton)
|
||||||
@ -301,7 +324,7 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
string filename = ((EditText) dialog.FindViewById(Resource.Id.file_filename)).Text;
|
string filename = ((EditText) dialog.FindViewById(Resource.Id.file_filename)).Text;
|
||||||
|
|
||||||
Util.ShowBrowseDialog(filename, activity, requestCodeBrowse, onCreate != null);
|
Util.ShowBrowseDialog(activity, requestCodeBrowse, onCreate != null);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -443,7 +443,8 @@ namespace keepass2android
|
|||||||
new SftpFileStorage(this),
|
new SftpFileStorage(this),
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
new BuiltInFileStorage(this)
|
new BuiltInFileStorage(this),
|
||||||
|
new AndroidContentStorage(Application.Context)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return _fileStorages;
|
return _fileStorages;
|
||||||
|
@ -69,6 +69,7 @@ namespace keepass2android
|
|||||||
view.FileSelectButtons _fileSelectButtons;
|
view.FileSelectButtons _fileSelectButtons;
|
||||||
|
|
||||||
internal AppTask AppTask;
|
internal AppTask AppTask;
|
||||||
|
private const int RequestCodeSelectIoc = 456;
|
||||||
|
|
||||||
public const string NoForwardToPasswordActivity = "NoForwardToPasswordActivity";
|
public const string NoForwardToPasswordActivity = "NoForwardToPasswordActivity";
|
||||||
|
|
||||||
@ -129,9 +130,11 @@ namespace keepass2android
|
|||||||
|
|
||||||
EventHandler openFileButtonClick = (sender, e) =>
|
EventHandler openFileButtonClick = (sender, e) =>
|
||||||
{
|
{
|
||||||
Intent intent = new Intent(this, typeof(FileStorageSelectionActivity));
|
Intent intent = new Intent(this, typeof(SelectStorageLocationActivity));
|
||||||
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppGet, true);
|
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppGet, true);
|
||||||
StartActivityForResult(intent, 0);
|
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppSend, false);
|
||||||
|
intent.PutExtra(FileStorageSetupDefs.ExtraIsForSave, false);
|
||||||
|
StartActivityForResult(intent, RequestCodeSelectIoc);
|
||||||
|
|
||||||
};
|
};
|
||||||
openFileButton.Click += openFileButtonClick;
|
openFileButton.Click += openFileButtonClick;
|
||||||
@ -294,19 +297,7 @@ namespace keepass2android
|
|||||||
App.Kp2a.GetFileStorage(ioc)
|
App.Kp2a.GetFileStorage(ioc)
|
||||||
.PrepareFileUsage(new FileStorageSetupInitiatorActivity(this, OnActivityResult, null), ioc, 0, false);
|
.PrepareFileUsage(new FileStorageSetupInitiatorActivity(this, OnActivityResult, null), ioc, 0, false);
|
||||||
}
|
}
|
||||||
private bool OnOpenButton(String fileName)
|
|
||||||
{
|
|
||||||
|
|
||||||
IOConnectionInfo ioc = new IOConnectionInfo
|
|
||||||
{
|
|
||||||
Path = fileName
|
|
||||||
};
|
|
||||||
|
|
||||||
LaunchPasswordActivityForIoc(ioc);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
|
||||||
{
|
{
|
||||||
@ -326,59 +317,6 @@ namespace keepass2android
|
|||||||
|
|
||||||
FillData();
|
FillData();
|
||||||
|
|
||||||
if (resultCode == KeePass.ExitFileStorageSelectionOk)
|
|
||||||
{
|
|
||||||
|
|
||||||
string protocolId = data.GetStringExtra("protocolId");
|
|
||||||
|
|
||||||
if (protocolId == "androidget")
|
|
||||||
{
|
|
||||||
string defaultFilename = Environment.ExternalStorageDirectory +
|
|
||||||
GetString(Resource.String.default_file_path);
|
|
||||||
Util.ShowBrowseDialog(defaultFilename, this, Intents.RequestCodeFileBrowseForOpen, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
App.Kp2a.GetFileStorage(protocolId).StartSelectFile(new FileStorageSetupInitiatorActivity(this,
|
|
||||||
OnActivityResult,
|
|
||||||
defaultPath =>
|
|
||||||
{
|
|
||||||
if (defaultPath.StartsWith("sftp://"))
|
|
||||||
Util.ShowSftpDialog(this, OnReceivedSftpData);
|
|
||||||
else
|
|
||||||
Util.ShowFilenameDialog(this, OnOpenButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url),
|
|
||||||
Intents.RequestCodeFileBrowseForOpen);
|
|
||||||
}
|
|
||||||
), false, 0, protocolId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (requestCode == Intents.RequestCodeFileBrowseForCreate
|
|
||||||
|| requestCode == Intents.RequestCodeFileBrowseForOpen)
|
|
||||||
&& resultCode == Result.Ok) {
|
|
||||||
string filename = Util.IntentToFilename(data, this);
|
|
||||||
if (filename != null) {
|
|
||||||
if (filename.StartsWith("file://")) {
|
|
||||||
filename = filename.Substring(7);
|
|
||||||
filename = Java.Net.URLDecoder.Decode(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestCode == Intents.RequestCodeFileBrowseForOpen)
|
|
||||||
{
|
|
||||||
IOConnectionInfo ioc = new IOConnectionInfo
|
|
||||||
{
|
|
||||||
Path = filename
|
|
||||||
};
|
|
||||||
|
|
||||||
LaunchPasswordActivityForIoc(ioc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resultCode == (Result)FileStorageResults.FileUsagePrepared)
|
if (resultCode == (Result)FileStorageResults.FileUsagePrepared)
|
||||||
{
|
{
|
||||||
@ -386,49 +324,16 @@ namespace keepass2android
|
|||||||
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
|
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
|
||||||
LaunchPasswordActivityForIoc(ioc);
|
LaunchPasswordActivityForIoc(ioc);
|
||||||
}
|
}
|
||||||
if (resultCode == (Result)FileStorageResults.FileChooserPrepared)
|
|
||||||
|
if ((resultCode == Result.Ok) && (requestCode == RequestCodeSelectIoc))
|
||||||
{
|
{
|
||||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||||
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
|
PasswordActivity.SetIoConnectionFromIntent(ioc, data);
|
||||||
#if !EXCLUDE_FILECHOOSER
|
|
||||||
StartFileChooser(ioc.Path);
|
|
||||||
#else
|
|
||||||
LaunchPasswordActivityForIoc(new IOConnectionInfo { Path = "/mnt/sdcard/keepass/yubi.kdbx"});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if ((resultCode == Result.Canceled) && (data != null) && (data.HasExtra("EXTRA_ERROR_MESSAGE")))
|
|
||||||
{
|
|
||||||
Toast.MakeText(this, data.GetStringExtra("EXTRA_ERROR_MESSAGE"), ToastLength.Long).Show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool OnReceivedSftpData(string filename)
|
|
||||||
{
|
|
||||||
IOConnectionInfo ioc = new IOConnectionInfo { Path = filename };
|
|
||||||
#if !EXCLUDE_FILECHOOSER
|
|
||||||
StartFileChooser(ioc.Path);
|
|
||||||
#else
|
|
||||||
LaunchPasswordActivityForIoc(ioc);
|
LaunchPasswordActivityForIoc(ioc);
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !EXCLUDE_FILECHOOSER
|
|
||||||
private void StartFileChooser(string defaultPath)
|
|
||||||
{
|
|
||||||
Kp2aLog.Log("FSA: defaultPath="+defaultPath);
|
|
||||||
string fileProviderAuthority = FileChooserFileProvider.TheAuthority;
|
|
||||||
if (defaultPath.StartsWith("file://"))
|
|
||||||
{
|
|
||||||
fileProviderAuthority = PackageName+".android-filechooser.localfile";
|
|
||||||
}
|
|
||||||
Intent i = Keepass2android.Kp2afilechooser.Kp2aFileChooserBridge.GetLaunchFileChooserIntent(this, fileProviderAuthority,
|
|
||||||
defaultPath);
|
|
||||||
|
|
||||||
StartActivityForResult(i, Intents.RequestCodeFileBrowseForOpen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
protected override void OnResume()
|
protected override void OnResume()
|
||||||
{
|
{
|
||||||
base.OnResume();
|
base.OnResume();
|
||||||
|
@ -58,6 +58,12 @@ namespace keepass2android.fileselect
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnRestart()
|
||||||
|
{
|
||||||
|
base.OnRestart();
|
||||||
|
_isRecreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnStart()
|
protected override void OnStart()
|
||||||
{
|
{
|
||||||
base.OnStart();
|
base.OnStart();
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>bin\Debug</OutputPath>
|
<OutputPath>bin\Debug</OutputPath>
|
||||||
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE;EXCLUDE_KEYTRANSFORM</DefineConstants>
|
<DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE;INCLUDE_KEYTRANSFORM</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<ConsolePause>False</ConsolePause>
|
<ConsolePause>False</ConsolePause>
|
||||||
@ -85,9 +85,6 @@
|
|||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Mono.Android" />
|
<Reference Include="Mono.Android" />
|
||||||
<Reference Include="Mono.Android.Support.v4" />
|
<Reference Include="Mono.Android.Support.v4" />
|
||||||
<Reference Include="GooglePlayServicesFroyoLib">
|
|
||||||
<HintPath>..\Components\googleplayservicesfroyo-9.0\lib\android\GooglePlayServicesFroyoLib.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="addons\OtpKeyProv\EncodingUtil.cs" />
|
<Compile Include="addons\OtpKeyProv\EncodingUtil.cs" />
|
||||||
@ -138,6 +135,7 @@
|
|||||||
<Compile Include="fileselect\FileSelectActivity.cs" />
|
<Compile Include="fileselect\FileSelectActivity.cs" />
|
||||||
<Compile Include="fileselect\FileDbHelper.cs" />
|
<Compile Include="fileselect\FileDbHelper.cs" />
|
||||||
<Compile Include="search\SearchProvider.cs" />
|
<Compile Include="search\SearchProvider.cs" />
|
||||||
|
<Compile Include="SelectStorageLocationActivity.cs" />
|
||||||
<Compile Include="services\OngoingNotificationsService.cs" />
|
<Compile Include="services\OngoingNotificationsService.cs" />
|
||||||
<Compile Include="settings\DatabaseSettingsActivity.cs" />
|
<Compile Include="settings\DatabaseSettingsActivity.cs" />
|
||||||
<Compile Include="intents\Intents.cs" />
|
<Compile Include="intents\Intents.cs" />
|
||||||
@ -832,12 +830,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\layout\text_with_help.xml" />
|
<AndroidResource Include="Resources\layout\text_with_help.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<XamarinComponentReference Include="googleplayservicesfroyo">
|
|
||||||
<Version>9.0</Version>
|
|
||||||
<Visible>False</Visible>
|
|
||||||
</XamarinComponentReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable\ic_storage_skydrive.png" />
|
<AndroidResource Include="Resources\drawable\ic_storage_skydrive.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user