First version of Dropbox-Support (not yet really functional - no possible to select the file to open)

This commit is contained in:
Philipp Crocoll 2013-09-15 20:08:14 +02:00
parent 042ee03f56
commit fbd3aafe71
60 changed files with 2175 additions and 306 deletions

13
.gitignore vendored
View File

@ -125,3 +125,16 @@ Thumbs.db
/src/Kp2aUnitTests/bin/ReleaseNoNet
/src/TwofishCipher/bin
/src/TwofishCipher/obj
/src/java/workspace/UITest
/src/java/JavaFileStorage/bin
/src/java/JavaFileStorage/gen/keepass2android/javafilestorage/BuildConfig.java
/src/java/JavaFileStorage/gen/keepass2android/javafilestorage/R.java
/src/JavaFileStorageBindings/bin/Debug
/src/JavaFileStorageBindings/bin/Release
/src/JavaFileStorageBindings/obj/Debug
/src/JavaFileStorageBindings/obj/Release
/src/JavaFileStorageTest
/src/java/workspace/DBRoulette
/src/java/workspace/JavaFileStorageTest
/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SecretKeys.java

View File

@ -0,0 +1,48 @@
Additions allow you to add arbitrary C# to the generated classes
before they are compiled. This can be helpful for providing convenience
methods or adding pure C# classes.
== Adding Methods to Generated Classes ==
Let's say the library being bound has a Rectangle class with a constructor
that takes an x and y position, and a width and length size. It will look like
this:
public partial class Rectangle
{
public Rectangle (int x, int y, int width, int height)
{
// JNI bindings
}
}
Imagine we want to add a constructor to this class that takes a Point and
Size structure instead of 4 ints. We can add a new file called Rectangle.cs
with a partial class containing our new method:
public partial class Rectangle
{
public Rectangle (Point location, Size size) :
this (location.X, location.Y, size.Width, size.Height)
{
}
}
At compile time, the additions class will be added to the generated class
and the final assembly will a Rectangle class with both constructors.
== Adding C# Classes ==
Another thing that can be done is adding fully C# managed classes to the
generated library. In the above example, let's assume that there isn't a
Point class available in Java or our library. The one we create doesn't need
to interact with Java, so we'll create it like a normal class in C#.
By adding a Point.cs file with this class, it will end up in the binding library:
public class Point
{
public int X { get; set; }
public int Y { get; set; }
}

View File

@ -0,0 +1,24 @@
This directory is for Android .jars.
There are 2 types of jars that are supported:
== Input Jar ==
This is the jar that bindings should be generated for.
For example, if you were binding the Google Maps library, this would
be Google's "maps.jar".
Set the build action for these jars in the properties page to "InputJar".
== Reference Jars ==
These are jars that are referenced by the input jar. C# bindings will
not be created for these jars. These jars will be used to resolve
types used by the input jar.
NOTE: Do not add "android.jar" as a reference jar. It will be added automatically
based on the Target Framework selected.
Set the build action for these jars in the properties page to "ReferenceJar".

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{48574278-4779-4B3A-A9E4-9CF1BC285D0B}</ProjectGuid>
<ProjectTypeGuids>{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>JavaFileStorageBindings</RootNamespace>
<AssemblyName>JavaFileStorageBindings</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v2.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Transforms\Metadata.xml" />
<TransformFile Include="Transforms\EnumFields.xml" />
<TransformFile Include="Transforms\EnumMethods.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedJar Include="..\java\JavaFileStorage\bin\javafilestorage.jar">
<Link>Jars\javafilestorage.jar</Link>
</EmbeddedJar>
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="..\java\JavaFileStorage\libs\android-support-v4.jar">
<Link>Jars\android-support-v4.jar</Link>
</EmbeddedReferenceJar>
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="..\java\JavaFileStorage\libs\dropbox-android-sdk-1.5.4.jar">
<Link>Jars\dropbox-android-sdk-1.5.4.jar</Link>
</EmbeddedReferenceJar>
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="..\java\JavaFileStorage\libs\httpmime-4.0.3.jar">
<Link>Jars\httpmime-4.0.3.jar</Link>
</EmbeddedReferenceJar>
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="..\java\JavaFileStorage\libs\json_simple-1.1.jar">
<Link>Jars\json_simple-1.1.jar</Link>
</EmbeddedReferenceJar>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,34 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("JavaFileStorageBindings")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("JavaFileStorageBindings")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]

View File

@ -0,0 +1,14 @@
<enum-field-mappings>
<!--
This example converts the constants Fragment_id, Fragment_name,
and Fragment_tag from android.support.v4.app.FragmentActivity.FragmentTag
to an enum called Android.Support.V4.App.FragmentTagType with values
Id, Name, and Tag.
<mapping jni-class="android/support/v4/app/FragmentActivity$FragmentTag" clr-enum-type="Android.Support.V4.App.FragmentTagType">
<field jni-name="Fragment_name" clr-name="Name" value="0" />
<field jni-name="Fragment_id" clr-name="Id" value="1" />
<field jni-name="Fragment_tag" clr-name="Tag" value="2" />
</mapping>
-->
</enum-field-mappings>

View File

@ -0,0 +1,13 @@
<enum-method-mappings>
<!--
This example changes the Java method:
android.support.v4.app.Fragment.SavedState.writeToParcel (int flags)
to be:
android.support.v4.app.Fragment.SavedState.writeToParcel (Android.OS.ParcelableWriteFlags flags)
when bound in C#.
<mapping jni-class="android/support/v4/app/Fragment.SavedState">
<method jni-name="writeToParcel" parameter="flags" clr-enum-type="Android.OS.ParcelableWriteFlags" />
</mapping>
-->
</enum-method-mappings>

View File

@ -0,0 +1,9 @@
<metadata>
<!--
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
-->
</metadata>

View File

@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aUnitTests", "Kp2aUnitTe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwofishCipher", "TwofishCipher\TwofishCipher.csproj", "{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JavaFileStorageBindings", "JavaFileStorageBindings\JavaFileStorageBindings.csproj", "{48574278-4779-4B3A-A9E4-9CF1BC285D0B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -202,6 +204,24 @@ Global
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Win32.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|x64.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Any CPU.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Win32.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -19,6 +19,17 @@ namespace keepass2android.Io
{
public class BuiltInFileStorage: IFileStorage
{
public IEnumerable<string> SupportedProtocols
{
get
{
yield return "file";
yield return "ftp";
yield return "http";
yield return "https";
}
}
public void DeleteFile(IOConnectionInfo ioc)
{
IOConnection.DeleteFile(ioc);
@ -78,6 +89,8 @@ namespace keepass2android.Io
return new BuiltInFileTransaction(ioc, useFileTransaction);
}
public IFileStorageSetup RequiredSetup { get { return null; } }
public class BuiltInFileTransaction : IWriteTransaction
{
private readonly FileTransactionEx _transaction;
@ -119,5 +132,10 @@ namespace keepass2android.Io
UrlUtil.GetFileName(ioc.Path));
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return (!ioc.IsLocalFile()) && (ioc.CredSaveMode != IOCredSaveMode.SaveCred);
}
}
}

View File

@ -77,6 +77,8 @@ namespace keepass2android.Io
IoUtil.DeleteDir(new Java.IO.File(_streamCacheDir), true);
}
public IEnumerable<string> SupportedProtocols { get { return _cachedStorage.SupportedProtocols; } }
public void DeleteFile(IOConnectionInfo ioc)
{
if (IsCached(ioc))
@ -391,6 +393,8 @@ namespace keepass2android.Io
return new CachedWriteTransaction(ioc, useFileTransaction, this);
}
public IFileStorageSetup RequiredSetup { get { return _cachedStorage.RequiredSetup; } }
public bool CompleteIoId()
{
throw new NotImplementedException();
@ -407,6 +411,11 @@ namespace keepass2android.Io
UrlUtil.GetFileName(ioc.Path));
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return _cachedStorage.RequiresCredentials(ioc);
}
public string GetBaseVersionHash(IOConnectionInfo ioc)
{

View File

@ -0,0 +1,27 @@
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;
using Keepass2android.Javafilestorage;
namespace keepass2android.Io
{
public class DropboxFileStorage: JavaFileStorage
{
public DropboxFileStorage(Context ctx) :
base(new Keepass2android.Javafilestorage.DropboxFileStorage(ctx))
{
}
public override IEnumerable<string> SupportedProtocols { get { yield return "dropbox"; } }
}
}

View File

@ -0,0 +1,67 @@
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
{
public class GDriveFileStorage: IFileStorage
{
public IEnumerable<string> SupportedProtocols { get { yield return "gdrive"; } }
public void DeleteFile(IOConnectionInfo ioc)
{
throw new NotImplementedException();
}
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
{
throw new NotImplementedException();
}
public string GetCurrentFileVersionFast(IOConnectionInfo ioc)
{
throw new NotImplementedException();
}
public Stream OpenFileForRead(IOConnectionInfo ioc)
{
throw new NotImplementedException();
}
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
{
throw new NotImplementedException();
}
public IFileStorageSetup RequiredSetup { get; private set; }
public bool CompleteIoId()
{
throw new NotImplementedException();
}
public bool? FileExists()
{
throw new NotImplementedException();
}
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
{
throw new NotImplementedException();
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
throw new NotImplementedException();
}
}
}

View File

@ -33,6 +33,8 @@ namespace keepass2android.Io
/// have an IIoStorageId interface in few cases.*/
public interface IFileStorage
{
IEnumerable<string> SupportedProtocols { get; }
/// <summary>
/// Deletes the given file.
/// </summary>
@ -55,10 +57,26 @@ namespace keepass2android.Io
/// <returns>A string which should not be null.</returns>
string GetCurrentFileVersionFast(IOConnectionInfo ioc);
/// <summary>
/// Opens the given file for reading
/// </summary>
Stream OpenFileForRead(IOConnectionInfo ioc);
//Stream OpenFileForWrite( IOConnectionInfo ioc, bool useTransaction);
/// <summary>
/// Opens a write transaction for writing to the given ioc.
/// </summary>
/// <param name="ioc">ioc to write to</param>
/// <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>
/// Returns an instance of an implementation of IFileStorageSetup or one of the more complex interfaces.
/// Depending on the type returned, the caller should try to follow the interface as close as possible.
/// Returns null if the file storage is setup or doesn't require anything to work.
/// </summary>
/// This is due to different storage types requiring different workflows for authentication processes
IFileStorageSetup RequiredSetup { get; }
/// <summary>
/// brings up a dialog to query credentials or something like this.
/// </summary>
@ -73,6 +91,37 @@ namespace keepass2android.Io
bool? FileExists( /*ioId*/);
string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc);
/// <summary>
/// Returns true if the the given ioc must be filled with username/password
/// </summary>
bool RequiresCredentials(IOConnectionInfo ioc);
}
/// <summary>
/// Base interface for required setup code
/// </summary>
public interface IFileStorageSetup
{
/// <summary>
/// call this when the user explicitly wants to use this file storage. Might require user interaction.
/// May throw if the setup failed permanentaly.
/// </summary>
/// <returns>true if the setup was succesful immediately (without UI). Returns false if setup was not successful but no error occured or can be displayed.</returns>
bool TrySetup(Activity activity);
}
/// <summary>
/// Interface which can be used additionally for an IFileStorageSetup to indicate that setup must be completed in OnResume()
/// </summary>
public interface IFileStorageSetupOnResume
{
/// <summary>
/// call this after TrySetup() returned false in the next OnResume()
/// May throw if the setup failed permanentaly.
/// </summary>
/// <returns>true if setup was succesful</returns>
bool TrySetupOnResume(Activity activity);
}
public interface IWriteTransaction: IDisposable

View File

@ -0,0 +1,207 @@
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 Java.Lang;
using KeePassLib.Serialization;
using KeePassLib.Utility;
using Keepass2android.Javafilestorage;
using Exception = System.Exception;
namespace keepass2android.Io
{
public abstract class JavaFileStorage: IFileStorage
{
public abstract IEnumerable<string> SupportedProtocols { get; }
private IJavaFileStorage _jfs;
public JavaFileStorage(IJavaFileStorage jfs)
{
this._jfs = jfs;
}
public void DeleteFile(IOConnectionInfo ioc)
{
throw new NotImplementedException();
}
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
{
try
{
return _jfs.CheckForFileChangeFast(ioc.Path, previousFileVersion);
}
catch (Java.Lang.Exception e)
{
Kp2aLog.Log(e.Message);
throw new Exception(e.Message, e);
}
}
public string GetCurrentFileVersionFast(IOConnectionInfo ioc)
{
try
{
return _jfs.GetCurrentFileVersionFast(ioc.Path);
}
catch (Java.Lang.Exception e)
{
Kp2aLog.Log(e.Message);
throw new Exception(e.Message, e);
}
}
public Stream OpenFileForRead(IOConnectionInfo ioc)
{
try
{
return _jfs.OpenFileForRead(IocToPath(ioc));
}
catch (Java.IO.FileNotFoundException e)
{
throw new System.IO.FileNotFoundException(e.Message, e);
}
catch (Java.Lang.Exception e)
{
Kp2aLog.Log(e.Message);
throw new Exception(e.Message, e);
}
}
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
{
return new JavaFileStorageWriteTransaction(IocToPath(ioc), useFileTransaction, _jfs);
}
public IFileStorageSetup RequiredSetup
{
get
{
if (_jfs.IsConnected)
return null;
return new JavaFileStorageSetup(this);
}
}
public class JavaFileStorageSetup : IFileStorageSetup, IFileStorageSetupOnResume
{
private readonly JavaFileStorage _javaFileStorage;
public JavaFileStorageSetup(JavaFileStorage javaFileStorage)
{
_javaFileStorage = javaFileStorage;
}
public bool TrySetup(Activity activity)
{
try
{
return _javaFileStorage._jfs.TryConnect(activity);
}
catch (Java.Lang.Exception e)
{
Kp2aLog.Log(e.Message);
throw new Exception(e.Message, e);
}
}
public bool TrySetupOnResume(Activity activity)
{
try
{
_javaFileStorage._jfs.OnResume();
return _javaFileStorage._jfs.IsConnected;
}
catch (Java.Lang.Exception e)
{
Kp2aLog.Log(e.Message);
throw new Exception(e.Message, e);
}
}
}
class JavaFileStorageWriteTransaction: IWriteTransaction
{
private readonly string _path;
private readonly bool _useFileTransaction;
private readonly IJavaFileStorage _javaFileStorage;
private MemoryStream _memoryStream;
public JavaFileStorageWriteTransaction(string path, bool useFileTransaction, IJavaFileStorage javaFileStorage)
{
_path = path;
_useFileTransaction = useFileTransaction;
_javaFileStorage = javaFileStorage;
}
public void Dispose()
{
_memoryStream.Dispose();
}
public Stream OpenFile()
{
_memoryStream = new MemoryStream();
return _memoryStream;
}
public void CommitWrite()
{
try
{
_javaFileStorage.UploadFile(_path, _memoryStream.ToArray(), _useFileTransaction);
}
catch (Java.Lang.Exception e)
{
Kp2aLog.Log(e.ToString());
throw new Exception(e.Message, e);
}
}
}
public bool CompleteIoId()
{
throw new NotImplementedException();
}
public bool? FileExists()
{
throw new NotImplementedException();
}
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
{
return UrlUtil.StripExtension(
UrlUtil.GetFileName(IocToPath(ioc)));
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return false;
}
private static string IocToPath(IOConnectionInfo ioc)
{
int protocolLength = ioc.Path.IndexOf("://", System.StringComparison.Ordinal);
if (protocolLength < 0)
return ioc.Path;
else
return ioc.Path.Substring(protocolLength + 3);
}
}
}

View File

@ -57,8 +57,11 @@
<Compile Include="database\SynchronizeCachedDatabase.cs" />
<Compile Include="Io\BuiltInFileStorage.cs" />
<Compile Include="Io\CachingFileStorage.cs" />
<Compile Include="Io\DropboxFileStorage.cs" />
<Compile Include="Io\GDriveFileStorage.cs" />
<Compile Include="Io\IFileStorage.cs" />
<Compile Include="Io\IoUtil.cs" />
<Compile Include="Io\JavaFileStorage.cs" />
<Compile Include="IProgressDialog.cs" />
<Compile Include="PreferenceKey.cs" />
<Compile Include="UiStringKey.cs" />
@ -89,6 +92,10 @@
<Compile Include="ProgressDialogStatusLogger.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
<Project>{48574278-4779-4b3a-a9e4-9cf1bc285d0b}</Project>
<Name>JavaFileStorageBindings</Name>
</ProjectReference>
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
<Project>{545b4a6b-8bba-4fbe-92fc-4ac060122a54}</Project>
<Name>KeePassLib2Android</Name>

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using KeePassLib.Serialization;
using keepass2android.Io;
@ -11,6 +12,7 @@ namespace Kp2aUnitTests
public bool Offline { get; set; }
public IEnumerable<string> SupportedProtocols { get { yield return "test"; } }
public void DeleteFile(IOConnectionInfo ioc)
{
@ -19,6 +21,8 @@ namespace Kp2aUnitTests
_builtIn.DeleteFile(ioc);
}
public IFileStorageSetup RequiredSetup { get { return null; } }
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
{
if (Offline)
@ -92,5 +96,10 @@ namespace Kp2aUnitTests
{
return _builtIn.GetFilenameWithoutPathAndExt(ioc);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return _builtIn.RequiresCredentials(ioc);
}
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>JavaFileStorage</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,4 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.source=1.6

View File

@ -0,0 +1,21 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="keepass2android.javafilestorage"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="14" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
</application>
</manifest>

View File

@ -0,0 +1,182 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
This project contains annotations derived from JCIP-ANNOTATIONS
Copyright (c) 2005 Brian Goetz and Tim Peierls.
See http://www.jcip.net and the Creative Commons Attribution License
(http://creativecommons.org/licenses/by/2.5)

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,15 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-17
android.library=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,11 @@
<resources>
<!--
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
<!-- API 11 theme customizations can go here. -->
</style>
</resources>

View File

@ -0,0 +1,12 @@
<resources>
<!--
Base application theme for API 14+. This theme completely replaces
AppBaseTheme from BOTH res/values/styles.xml and
res/values-v11/styles.xml on API 14+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- API 14 theme customizations can go here. -->
</style>
</resources>

View File

@ -0,0 +1,5 @@
<resources>
<string name="app_name">JavaFileStorage</string>
</resources>

View File

@ -0,0 +1,20 @@
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>

View File

@ -0,0 +1,268 @@
package keepass2android.javafilestorage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.DropBoxManager.Entry;
import android.util.Log;
import android.widget.Toast;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.android.AuthActivity;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxServerException;
import com.dropbox.client2.session.AccessTokenPair;
import com.dropbox.client2.session.AppKeyPair;
import com.dropbox.client2.session.TokenPair;
import com.dropbox.client2.session.Session.AccessType;
public class DropboxFileStorage implements JavaFileStorage {
final static private String APP_KEY = "i8shu7v1hgh7ynt";
// If you'd like to change the access type to the full Dropbox instead of
// an app folder, change this value.
final static private AccessType ACCESS_TYPE = AccessType.DROPBOX;
final static private String TAG = "KP2AJ";
final static private String ACCOUNT_PREFS_NAME = "prefs";
final static private String ACCESS_KEY_NAME = "ACCESS_KEY";
final static private String ACCESS_SECRET_NAME = "ACCESS_SECRET";
DropboxAPI<AndroidAuthSession> mApi;
private boolean mLoggedIn = false;
private Context mContext;
public DropboxFileStorage(Context ctx)
{
mContext = ctx;
// We create a new AuthSession so that we can use the Dropbox API.
AndroidAuthSession session = buildSession();
mApi = new DropboxAPI<AndroidAuthSession>(session);
checkAppKeySetup();
}
public boolean tryConnect(Activity activity)
{
if (!mLoggedIn)
mApi.getSession().startAuthentication(activity);
return mLoggedIn;
}
public void onResume()
{
AndroidAuthSession session = mApi.getSession();
// The next part must be inserted in the onResume() method of the
// activity from which session.startAuthentication() was called, so
// that Dropbox authentication completes properly.
if (session.authenticationSuccessful()) {
try {
// Mandatory call to complete the auth
session.finishAuthentication();
// Store it locally in our app for later use
TokenPair tokens = session.getAccessTokenPair();
storeKeys(tokens.key, tokens.secret);
setLoggedIn(true);
} catch (IllegalStateException e) {
showToast("Couldn't authenticate with Dropbox:" + e.getLocalizedMessage());
Log.i(TAG, "Error authenticating", e);
}
}
}
private void setLoggedIn(boolean b) {
mLoggedIn = b;
}
private boolean checkAppKeySetup() {
// Check if the app has set up its manifest properly.
Intent testIntent = new Intent(Intent.ACTION_VIEW);
String scheme = "db-" + APP_KEY;
String uri = scheme + "://" + AuthActivity.AUTH_VERSION + "/test";
testIntent.setData(Uri.parse(uri));
PackageManager pm = mContext.getPackageManager();
if (0 == pm.queryIntentActivities(testIntent, 0).size()) {
showToast("URL scheme in your app's " +
"manifest is not set up correctly. You should have a " +
"com.dropbox.client2.android.AuthActivity with the " +
"scheme: " + scheme);
return false;
}
return true;
}
public boolean isConnected()
{
return mLoggedIn;
}
public ArrayList<String> listContents(String path) throws Exception
{
ArrayList<String> files = new ArrayList<String>();
try {
DropboxAPI.Entry existingEntry = mApi.metadata(path, 0, null, true, null);
for (DropboxAPI.Entry ent: existingEntry.contents)
{
files.add(ent.path);
}
// do stuff with the Entry
} catch (DropboxException e) {
throw getNonDropboxException(e);
}
return files;
}
public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception
{
if ((previousFileVersion == null) || (previousFileVersion == ""))
return false;
try {
com.dropbox.client2.DropboxAPI.Entry entry = mApi.metadata(path, 1, null, false, null);
return entry.hash != previousFileVersion;
} catch (DropboxException e) {
throw getNonDropboxException(e);
}
}
public String getCurrentFileVersionFast(String path)
{
try {
com.dropbox.client2.DropboxAPI.Entry entry = mApi.metadata(path, 1, null, false, null);
return entry.rev;
} catch (DropboxException e) {
Log.d(TAG, e.toString());
return "";
}
}
public InputStream openFileForRead(String path) throws Exception
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
return mApi.getFileStream(path, null);
} catch (DropboxException e) {
//System.out.println("Something went wrong: " + e);
throw getNonDropboxException(e);
}
}
public void uploadFile(String path, byte[] data, boolean writeTransactional) throws Exception
{
ByteArrayInputStream bis = new ByteArrayInputStream(data);
try {
//TODO: it would be nice to be able to use the parent version with putFile()
mApi.putFileOverwrite(path, bis, data.length, null);
} catch (DropboxException e) {
throw getNonDropboxException(e);
}
}
private Exception getNonDropboxException(DropboxException e) {
//TODO test for special error codes like 404
Log.d(TAG, "Exception of type " +e.getClass().getName()+":" + e.getMessage());
if (DropboxServerException.class.isAssignableFrom(e.getClass()) )
{
DropboxServerException serverEx = (DropboxServerException)e;
if (serverEx.error == 404)
return new FileNotFoundException(e.toString());
}
return e;
//return new Exception(e.toString());
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
/**
* Keep the access keys returned from Trusted Authenticator in a local
* store, rather than storing user name & password, and re-authenticating each
* time (which is not to be done, ever).
*
* @return Array of [access_key, access_secret], or null if none stored
*/
private String[] getKeys() {
SharedPreferences prefs = mContext.getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
String key = prefs.getString(ACCESS_KEY_NAME, null);
String secret = prefs.getString(ACCESS_SECRET_NAME, null);
if (key != null && secret != null) {
String[] ret = new String[2];
ret[0] = key;
ret[1] = secret;
return ret;
} else {
return null;
}
}
/**
* Keeping the access keys returned from Trusted Authenticator in a local
* store, rather than storing user name & password, and re-authenticating each
* time (which is not to be done, ever).
*/
private void storeKeys(String key, String secret) {
Log.d(TAG, "Storing Dropbox accessToken");
// Save the access key for later
SharedPreferences prefs = mContext.getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, key);
edit.putString(ACCESS_SECRET_NAME, secret);
edit.commit();
}
//TODO: call when Unlinked Exception
private void clearKeys() {
SharedPreferences prefs = mContext.getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.clear();
edit.commit();
}
private AndroidAuthSession buildSession() {
//note: the SecretKeys class is not public because the App-Secret must be secret!
AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, SecretKeys.DROPBOX_APP_SECRET);
AndroidAuthSession session;
String[] stored = getKeys();
if (stored != null) {
AccessTokenPair accessToken = new AccessTokenPair(stored[0], stored[1]);
session = new AndroidAuthSession(appKeyPair, ACCESS_TYPE, accessToken);
setLoggedIn(true);
Log.d(TAG, "Creating Dropbox Session with accessToken");
} else {
session = new AndroidAuthSession(appKeyPair, ACCESS_TYPE);
setLoggedIn(false);
Log.d(TAG, "Creating Dropbox Session without accessToken");
}
return session;
}
}

View File

@ -0,0 +1,22 @@
package keepass2android.javafilestorage;
import java.io.InputStream;
import android.app.Activity;
public interface JavaFileStorage {
public boolean tryConnect(Activity activity);
public void onResume();
public boolean isConnected();
public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception;
public String getCurrentFileVersionFast(String path);
public InputStream openFileForRead(String path) throws Exception;
public void uploadFile(String path, byte[] data, boolean writeTransactional) throws Exception;
}

View File

@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using keepass2android.Io;
using Object = Java.Lang.Object;
namespace keepass2android
{
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden , Theme="@style/NoTitleBar")]
public class FileStorageSelectionActivity : ListActivity
{
private string _protocolToSetup;
class FileStorageAdapter: BaseAdapter
{
private readonly FileStorageSelectionActivity _context;
private List<string> _protocolIds = new List<string>();
public FileStorageAdapter(FileStorageSelectionActivity context)
{
_context = context;
//show all supported protocols:
foreach (IFileStorage fs in App.Kp2a.FileStorages)
_protocolIds.AddRange(fs.SupportedProtocols);
//except file://
_protocolIds.Remove("file");
}
public override Object GetItem(int position)
{
return position;
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater)_context.GetSystemService(LayoutInflaterService);
View v = inflater.Inflate(Resource.Layout.filestorage_selection_listitem, null);
((TextView)v.FindViewById(Resource.Id.filestorage_label)).Text =
App.Kp2a.GetResourceString("filestoragename_"+_protocolIds[position] );
Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + _protocolIds[position]);
((ImageView)v.FindViewById(Resource.Id.filestorage_logo)).SetImageDrawable(drawable);
v.Click += (sender, args) => _context.OnItemSelected(_protocolIds[position]);
return v;
}
public override int Count
{
get { return _protocolIds.Count; }
}
}
private void OnItemSelected(string protocolId)
{
var fs = App.Kp2a.GetFileStorage(protocolId);
IFileStorageSetup fssetup = fs.RequiredSetup;
try
{
if ((fssetup == null) || (fssetup.TrySetup(this)))
{
ReturnProtocol(protocolId);
}
else
{
//setup not yet complete
_protocolToSetup = protocolId;
}
}
catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
}
}
private void ReturnProtocol(string protocolId)
{
Intent intent = new Intent();
intent.PutExtra("protocolId", protocolId);
SetResult(KeePass.ExitFileStorageSelectionOk, intent);
Finish();
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
if (bundle != null)
_protocolToSetup = bundle.GetString("_protocolToSetup", null);
SetContentView(Resource.Layout.filestorage_selection);
this.ListAdapter = new FileStorageAdapter(this);
}
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
outState.PutString("_protocolToSetup",_protocolToSetup);
}
protected override void OnResume()
{
base.OnResume();
if (!String.IsNullOrEmpty(_protocolToSetup))
{
try
{
string protocolToSetup = _protocolToSetup;
_protocolToSetup = null;
IFileStorageSetupOnResume fsSetup = App.Kp2a.GetFileStorage(protocolToSetup).RequiredSetup as IFileStorageSetupOnResume;
if ((fsSetup == null) || (fsSetup.TrySetupOnResume(this)))
{
ReturnProtocol(protocolToSetup);
}
}
catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
}
}
}
}
}

View File

@ -42,6 +42,7 @@ namespace keepass2android
public const Result TaskComplete = Result.FirstUser + 5;
public const Result ExitReloadDb = Result.FirstUser+6;
public const Result ExitClose = Result.FirstUser + 7;
public const Result ExitFileStorageSelectionOk = Result.FirstUser + 8;
AppTask _appTask;
@ -110,6 +111,8 @@ namespace keepass2android
private void LaunchNextActivity() {
if (!App.Kp2a.GetDb().Loaded)
{
// Load default database

View File

@ -105,12 +105,6 @@ namespace keepass2android
}
public static void Launch(Activity act, String fileName) {
Launch(act, IOConnectionInfo.FromPath(fileName), null);
}
public static void Launch(Activity act, IOConnectionInfo ioc, AppTask appTask)
{
if (ioc.IsLocalFile())

View File

@ -6,6 +6,19 @@
android:installLocation="auto">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" />
<application android:label="keepass2android" android:icon="@drawable/ic_launcher">
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboard">
<intent-filter>
<!-- Change this to be db- followed by your app key -->
<data android:scheme="db-i8shu7v1hgh7ynt" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity" >
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />

View File

@ -512,70 +512,85 @@ namespace keepass2android
public const int ic_menu_view = 2130837595;
// aapt resource value: 0x7f02005c
public const int ic_unlocked_gray = 2130837596;
public const int ic_storage_dropbox = 2130837596;
// aapt resource value: 0x7f02005d
public const int location_web_site = 2130837597;
public const int ic_storage_ftp = 2130837597;
// aapt resource value: 0x7f02005e
public const int navigation_accept = 2130837598;
public const int ic_storage_gdrive = 2130837598;
// aapt resource value: 0x7f02005f
public const int navigation_accept_dark = 2130837599;
public const int ic_storage_http = 2130837599;
// aapt resource value: 0x7f020060
public const int navigation_cancel = 2130837600;
public const int ic_storage_https = 2130837600;
// aapt resource value: 0x7f020061
public const int navigation_previous_item = 2130837601;
public const int ic_unlocked_gray = 2130837601;
// aapt resource value: 0x7f020062
public const int navigation_previous_item_dark = 2130837602;
public const int location_web_site = 2130837602;
// aapt resource value: 0x7f020063
public const int notify = 2130837603;
public const int navigation_accept = 2130837603;
// aapt resource value: 0x7f020064
public const int notify_keyboard = 2130837604;
public const int navigation_accept_dark = 2130837604;
// aapt resource value: 0x7f020065
public const int oktoberfest = 2130837605;
public const int navigation_cancel = 2130837605;
// aapt resource value: 0x7f020066
public const int RedButton = 2130837606;
public const int navigation_previous_item = 2130837606;
// aapt resource value: 0x7f020067
public const int section_header = 2130837607;
public const int navigation_previous_item_dark = 2130837607;
// aapt resource value: 0x7f020068
public const int sym_keyboard = 2130837608;
public const int notify = 2130837608;
// aapt resource value: 0x7f020069
public const int sym_keyboard_delete = 2130837609;
public const int notify_keyboard = 2130837609;
// aapt resource value: 0x7f02006a
public const int sym_keyboard_done = 2130837610;
public const int oktoberfest = 2130837610;
// aapt resource value: 0x7f02006b
public const int sym_keyboard_kp2a = 2130837611;
public const int RedButton = 2130837611;
// aapt resource value: 0x7f02006c
public const int sym_keyboard_return = 2130837612;
public const int section_header = 2130837612;
// aapt resource value: 0x7f02006d
public const int sym_keyboard_search = 2130837613;
public const int sym_keyboard = 2130837613;
// aapt resource value: 0x7f02006e
public const int sym_keyboard_shift = 2130837614;
public const int sym_keyboard_delete = 2130837614;
// aapt resource value: 0x7f02006f
public const int sym_keyboard_space = 2130837615;
public const int sym_keyboard_done = 2130837615;
// aapt resource value: 0x7f020070
public const int transparent = 2130837616;
public const int sym_keyboard_kp2a = 2130837616;
// aapt resource value: 0x7f020071
public const int YellowButton = 2130837617;
public const int sym_keyboard_return = 2130837617;
// aapt resource value: 0x7f020072
public const int sym_keyboard_search = 2130837618;
// aapt resource value: 0x7f020073
public const int sym_keyboard_shift = 2130837619;
// aapt resource value: 0x7f020074
public const int sym_keyboard_space = 2130837620;
// aapt resource value: 0x7f020075
public const int transparent = 2130837621;
// aapt resource value: 0x7f020076
public const int YellowButton = 2130837622;
static Drawable()
{
@ -593,44 +608,44 @@ namespace keepass2android
// aapt resource value: 0x7f0d000f
public const int Credit = 2131558415;
// aapt resource value: 0x7f0d007d
public const int IconGridView = 2131558525;
// aapt resource value: 0x7f0d0080
public const int IconGridView = 2131558528;
// aapt resource value: 0x7f0d008c
public const int QuickUnlock_button = 2131558540;
// aapt resource value: 0x7f0d008f
public const int QuickUnlock_button = 2131558543;
// aapt resource value: 0x7f0d0090
public const int QuickUnlock_buttonLock = 2131558544;
// aapt resource value: 0x7f0d008d
public const int QuickUnlock_buttonLock = 2131558541;
public const int QuickUnlock_label = 2131558541;
// aapt resource value: 0x7f0d008a
public const int QuickUnlock_label = 2131558538;
// aapt resource value: 0x7f0d008e
public const int QuickUnlock_password = 2131558542;
// aapt resource value: 0x7f0d008b
public const int QuickUnlock_password = 2131558539;
// aapt resource value: 0x7f0d0062
public const int RelativeLayout = 2131558498;
// aapt resource value: 0x7f0d005f
public const int RelativeLayout = 2131558495;
// aapt resource value: 0x7f0d005e
public const int ScrollView = 2131558494;
// aapt resource value: 0x7f0d0061
public const int ScrollView = 2131558497;
// aapt resource value: 0x7f0d0000
public const int about_title = 2131558400;
// aapt resource value: 0x7f0d005c
public const int accept_button = 2131558492;
// aapt resource value: 0x7f0d005f
public const int accept_button = 2131558495;
// aapt resource value: 0x7f0d0031
public const int add_advanced = 2131558449;
// aapt resource value: 0x7f0d0072
public const int add_entry = 2131558514;
// aapt resource value: 0x7f0d0075
public const int add_entry = 2131558517;
// aapt resource value: 0x7f0d0071
public const int add_group = 2131558513;
// aapt resource value: 0x7f0d0074
public const int add_group = 2131558516;
// aapt resource value: 0x7f0d00a0
public const int add_url_entry = 2131558560;
// aapt resource value: 0x7f0d00a3
public const int add_url_entry = 2131558563;
// aapt resource value: 0x7f0d0030
public const int advanced_container = 2131558448;
@ -650,83 +665,83 @@ namespace keepass2android
// aapt resource value: 0x7f0d0055
public const int browse_button = 2131558485;
// aapt resource value: 0x7f0d0064
public const int btn_length12 = 2131558500;
// aapt resource value: 0x7f0d0063
public const int btn_length16 = 2131558499;
// aapt resource value: 0x7f0d0067
public const int btn_length12 = 2131558503;
// aapt resource value: 0x7f0d0066
public const int btn_length6 = 2131558502;
public const int btn_length16 = 2131558502;
// aapt resource value: 0x7f0d0065
public const int btn_length8 = 2131558501;
// aapt resource value: 0x7f0d0069
public const int btn_length6 = 2131558505;
// aapt resource value: 0x7f0d0068
public const int btn_length8 = 2131558504;
// aapt resource value: 0x7f0d0013
public const int cancel = 2131558419;
// aapt resource value: 0x7f0d005d
public const int cancel_button = 2131558493;
// aapt resource value: 0x7f0d0060
public const int cancel_button = 2131558496;
// aapt resource value: 0x7f0d0074
public const int cancel_insert_element = 2131558516;
// aapt resource value: 0x7f0d0077
public const int cancel_insert_element = 2131558519;
// aapt resource value: 0x7f0d009d
public const int cbCaseSensitive = 2131558557;
// aapt resource value: 0x7f0d00a0
public const int cbCaseSensitive = 2131558560;
// aapt resource value: 0x7f0d009e
public const int cbExcludeExpiredEntries = 2131558558;
// aapt resource value: 0x7f0d0093
public const int cbRegEx = 2131558547;
// aapt resource value: 0x7f0d009c
public const int cbSearchInGroupName = 2131558556;
// aapt resource value: 0x7f0d0099
public const int cbSearchInNotes = 2131558553;
// aapt resource value: 0x7f0d009a
public const int cbSearchInOtherStrings = 2131558554;
// aapt resource value: 0x7f0d0098
public const int cbSearchInPassword = 2131558552;
// aapt resource value: 0x7f0d009b
public const int cbSearchInTags = 2131558555;
// aapt resource value: 0x7f0d0095
public const int cbSearchInTitle = 2131558549;
// aapt resource value: 0x7f0d00a1
public const int cbExcludeExpiredEntries = 2131558561;
// aapt resource value: 0x7f0d0096
public const int cbSearchInUrl = 2131558550;
public const int cbRegEx = 2131558550;
// aapt resource value: 0x7f0d0097
public const int cbSearchInUsername = 2131558551;
// aapt resource value: 0x7f0d009f
public const int cbSearchInGroupName = 2131558559;
// aapt resource value: 0x7f0d006f
public const int cb_brackets = 2131558511;
// aapt resource value: 0x7f0d009c
public const int cbSearchInNotes = 2131558556;
// aapt resource value: 0x7f0d006a
public const int cb_digits = 2131558506;
// aapt resource value: 0x7f0d009d
public const int cbSearchInOtherStrings = 2131558557;
// aapt resource value: 0x7f0d0069
public const int cb_lowercase = 2131558505;
// aapt resource value: 0x7f0d009b
public const int cbSearchInPassword = 2131558555;
// aapt resource value: 0x7f0d006b
public const int cb_minus = 2131558507;
// aapt resource value: 0x7f0d009e
public const int cbSearchInTags = 2131558558;
// aapt resource value: 0x7f0d0098
public const int cbSearchInTitle = 2131558552;
// aapt resource value: 0x7f0d0099
public const int cbSearchInUrl = 2131558553;
// aapt resource value: 0x7f0d009a
public const int cbSearchInUsername = 2131558554;
// aapt resource value: 0x7f0d0072
public const int cb_brackets = 2131558514;
// aapt resource value: 0x7f0d006d
public const int cb_space = 2131558509;
// aapt resource value: 0x7f0d006e
public const int cb_specials = 2131558510;
public const int cb_digits = 2131558509;
// aapt resource value: 0x7f0d006c
public const int cb_underline = 2131558508;
public const int cb_lowercase = 2131558508;
// aapt resource value: 0x7f0d0068
public const int cb_uppercase = 2131558504;
// aapt resource value: 0x7f0d006e
public const int cb_minus = 2131558510;
// aapt resource value: 0x7f0d0070
public const int cb_space = 2131558512;
// aapt resource value: 0x7f0d0071
public const int cb_specials = 2131558513;
// aapt resource value: 0x7f0d006f
public const int cb_underline = 2131558511;
// aapt resource value: 0x7f0d006b
public const int cb_uppercase = 2131558507;
// aapt resource value: 0x7f0d000b
public const int contributors_title = 2131558411;
@ -734,14 +749,14 @@ namespace keepass2android
// aapt resource value: 0x7f0d0058
public const int create = 2131558488;
// aapt resource value: 0x7f0d00a6
public const int cred_password = 2131558566;
// aapt resource value: 0x7f0d00a9
public const int cred_password = 2131558569;
// aapt resource value: 0x7f0d00a7
public const int cred_remember_mode = 2131558567;
// aapt resource value: 0x7f0d00aa
public const int cred_remember_mode = 2131558570;
// aapt resource value: 0x7f0d00a5
public const int cred_username = 2131558565;
// aapt resource value: 0x7f0d00a8
public const int cred_username = 2131558568;
// aapt resource value: 0x7f0d001d
public const int delete_extra = 2131558429;
@ -767,8 +782,8 @@ namespace keepass2android
// aapt resource value: 0x7f0d003b
public const int edit_extra = 2131558459;
// aapt resource value: 0x7f0d0086
public const int enable_quickunlock = 2131558534;
// aapt resource value: 0x7f0d0089
public const int enable_quickunlock = 2131558537;
// aapt resource value: 0x7f0d004c
public const int entry_accessed = 2131558476;
@ -899,17 +914,23 @@ namespace keepass2android
// aapt resource value: 0x7f0d005b
public const int file_select = 2131558491;
// aapt resource value: 0x7f0d0081
public const int filename = 2131558529;
// aapt resource value: 0x7f0d0084
public const int filename = 2131558532;
// aapt resource value: 0x7f0d0053
public const int filename_form = 2131558483;
// aapt resource value: 0x7f0d007f
public const int filename_label = 2131558527;
// aapt resource value: 0x7f0d0082
public const int filename_label = 2131558530;
// aapt resource value: 0x7f0d0080
public const int filenamescroll = 2131558528;
// aapt resource value: 0x7f0d0083
public const int filenamescroll = 2131558531;
// aapt resource value: 0x7f0d005e
public const int filestorage_label = 2131558494;
// aapt resource value: 0x7f0d005d
public const int filestorage_logo = 2131558493;
// aapt resource value: 0x7f0d0059
public const int fnv_cancel = 2131558489;
@ -920,41 +941,41 @@ namespace keepass2android
// aapt resource value: 0x7f0d0029
public const int generate_button = 2131558441;
// aapt resource value: 0x7f0d0061
public const int generate_password_button = 2131558497;
// aapt resource value: 0x7f0d0064
public const int generate_password_button = 2131558500;
// aapt resource value: 0x7f0d0070
public const int group_header = 2131558512;
// aapt resource value: 0x7f0d0073
public const int group_header = 2131558515;
// aapt resource value: 0x7f0d007b
public const int group_icon = 2131558523;
// aapt resource value: 0x7f0d007d
public const int group_label = 2131558525;
// aapt resource value: 0x7f0d0078
public const int group_icon = 2131558520;
public const int group_name = 2131558520;
// aapt resource value: 0x7f0d007c
public const int group_text = 2131558524;
// aapt resource value: 0x7f0d007a
public const int group_label = 2131558522;
// aapt resource value: 0x7f0d0075
public const int group_name = 2131558517;
// aapt resource value: 0x7f0d0079
public const int group_text = 2131558521;
// aapt resource value: 0x7f0d0077
public const int icon = 2131558519;
public const int icon = 2131558522;
// aapt resource value: 0x7f0d0022
public const int icon_button = 2131558434;
// aapt resource value: 0x7f0d007b
public const int icon_image = 2131558523;
// aapt resource value: 0x7f0d007e
public const int icon_image = 2131558526;
// aapt resource value: 0x7f0d007c
public const int icon_text = 2131558524;
// aapt resource value: 0x7f0d007f
public const int icon_text = 2131558527;
// aapt resource value: 0x7f0d0017
public const int imgoktfest = 2131558423;
// aapt resource value: 0x7f0d0073
public const int insert_element = 2131558515;
// aapt resource value: 0x7f0d0076
public const int insert_element = 2131558518;
// aapt resource value: 0x7f0d0011
public const int install_market = 2131558417;
@ -962,11 +983,11 @@ namespace keepass2android
// aapt resource value: 0x7f0d0012
public const int install_web = 2131558418;
// aapt resource value: 0x7f0d007e
public const int keyboard = 2131558526;
// aapt resource value: 0x7f0d0081
public const int keyboard = 2131558529;
// aapt resource value: 0x7f0d0088
public const int keyfileLine = 2131558536;
// aapt resource value: 0x7f0d008b
public const int keyfileLine = 2131558539;
// aapt resource value: 0x7f0d0054
public const int label_open_by_filename = 2131558484;
@ -977,71 +998,71 @@ namespace keepass2android
// aapt resource value: 0x7f0d004f
public const int label_warning = 2131558479;
// aapt resource value: 0x7f0d0067
public const int length = 2131558503;
// aapt resource value: 0x7f0d006a
public const int length = 2131558506;
// aapt resource value: 0x7f0d0062
public const int length_label = 2131558498;
// aapt resource value: 0x7f0d0065
public const int length_label = 2131558501;
// aapt resource value: 0x7f0d0092
public const int linearLayout1 = 2131558546;
// aapt resource value: 0x7f0d00b1
public const int menu_about = 2131558577;
// aapt resource value: 0x7f0d00b0
public const int menu_app_settings = 2131558576;
// aapt resource value: 0x7f0d00af
public const int menu_cancel_edit = 2131558575;
// aapt resource value: 0x7f0d00b7
public const int menu_change_db = 2131558583;
// aapt resource value: 0x7f0d00b3
public const int menu_change_master_key = 2131558579;
// aapt resource value: 0x7f0d00a8
public const int menu_donate = 2131558568;
// aapt resource value: 0x7f0d00aa
public const int menu_goto_url = 2131558570;
// aapt resource value: 0x7f0d00ab
public const int menu_lock = 2131558571;
// aapt resource value: 0x7f0d00ad
public const int menu_rate = 2131558573;
// aapt resource value: 0x7f0d00b2
public const int menu_search = 2131558578;
// aapt resource value: 0x7f0d00b6
public const int menu_search_advanced = 2131558582;
// aapt resource value: 0x7f0d00b5
public const int menu_sort = 2131558581;
// aapt resource value: 0x7f0d00ac
public const int menu_suggest_improvements = 2131558572;
// aapt resource value: 0x7f0d0095
public const int linearLayout1 = 2131558549;
// aapt resource value: 0x7f0d00b4
public const int menu_sync = 2131558580;
public const int menu_about = 2131558580;
// aapt resource value: 0x7f0d00a9
public const int menu_toggle_pass = 2131558569;
// aapt resource value: 0x7f0d00b3
public const int menu_app_settings = 2131558579;
// aapt resource value: 0x7f0d00b2
public const int menu_cancel_edit = 2131558578;
// aapt resource value: 0x7f0d00ba
public const int menu_change_db = 2131558586;
// aapt resource value: 0x7f0d00b6
public const int menu_change_master_key = 2131558582;
// aapt resource value: 0x7f0d00ab
public const int menu_donate = 2131558571;
// aapt resource value: 0x7f0d00ad
public const int menu_goto_url = 2131558573;
// aapt resource value: 0x7f0d00ae
public const int menu_translate = 2131558574;
public const int menu_lock = 2131558574;
// aapt resource value: 0x7f0d00b0
public const int menu_rate = 2131558576;
// aapt resource value: 0x7f0d00b5
public const int menu_search = 2131558581;
// aapt resource value: 0x7f0d00b9
public const int menu_search_advanced = 2131558585;
// aapt resource value: 0x7f0d00b8
public const int menu_sort = 2131558584;
// aapt resource value: 0x7f0d00af
public const int menu_suggest_improvements = 2131558575;
// aapt resource value: 0x7f0d00b7
public const int menu_sync = 2131558583;
// aapt resource value: 0x7f0d00ac
public const int menu_toggle_pass = 2131558572;
// aapt resource value: 0x7f0d00b1
public const int menu_translate = 2131558577;
// aapt resource value: 0x7f0d0019
public const int no_donate = 2131558425;
// aapt resource value: 0x7f0d00a1
public const int no_results = 2131558561;
// aapt resource value: 0x7f0d00a4
public const int no_results = 2131558564;
// aapt resource value: 0x7f0d0076
public const int ok = 2131558518;
// aapt resource value: 0x7f0d0079
public const int ok = 2131558521;
// aapt resource value: 0x7f0d0018
public const int ok_donate = 2131558424;
@ -1049,26 +1070,26 @@ namespace keepass2android
// aapt resource value: 0x7f0d0057
public const int open = 2131558487;
// aapt resource value: 0x7f0d00a3
public const int pass_conf_password = 2131558563;
// aapt resource value: 0x7f0d0084
public const int pass_keyfile = 2131558532;
// aapt resource value: 0x7f0d0085
public const int pass_ok = 2131558533;
// aapt resource value: 0x7f0d00a2
public const int pass_password = 2131558562;
// aapt resource value: 0x7f0d0060
public const int password = 2131558496;
// aapt resource value: 0x7f0d00a6
public const int pass_conf_password = 2131558566;
// aapt resource value: 0x7f0d0087
public const int passwordLine = 2131558535;
public const int pass_keyfile = 2131558535;
// aapt resource value: 0x7f0d0082
public const int password_label = 2131558530;
// aapt resource value: 0x7f0d0088
public const int pass_ok = 2131558536;
// aapt resource value: 0x7f0d00a5
public const int pass_password = 2131558565;
// aapt resource value: 0x7f0d0063
public const int password = 2131558499;
// aapt resource value: 0x7f0d008a
public const int passwordLine = 2131558538;
// aapt resource value: 0x7f0d0085
public const int password_label = 2131558533;
// aapt resource value: 0x7f0d000e
public const int plugin1 = 2131558414;
@ -1076,8 +1097,8 @@ namespace keepass2android
// aapt resource value: 0x7f0d001c
public const int protection = 2131558428;
// aapt resource value: 0x7f0d0089
public const int qu_filename = 2131558537;
// aapt resource value: 0x7f0d008c
public const int qu_filename = 2131558540;
// aapt resource value: 0x7f0d0014
public const int rounds = 2131558420;
@ -1085,29 +1106,29 @@ namespace keepass2android
// aapt resource value: 0x7f0d0015
public const int rounds_explaination = 2131558421;
// aapt resource value: 0x7f0d0091
public const int scrollView1 = 2131558545;
// aapt resource value: 0x7f0d0090
public const int searchEditText = 2131558544;
// aapt resource value: 0x7f0d008f
public const int search_button = 2131558543;
// aapt resource value: 0x7f0d0094
public const int search_in_label = 2131558548;
public const int scrollView1 = 2131558548;
// aapt resource value: 0x7f0d008e
public const int search_label = 2131558542;
// aapt resource value: 0x7f0d0093
public const int searchEditText = 2131558547;
// aapt resource value: 0x7f0d009f
public const int select_other_entry = 2131558559;
// aapt resource value: 0x7f0d0092
public const int search_button = 2131558546;
// aapt resource value: 0x7f0d0097
public const int search_in_label = 2131558551;
// aapt resource value: 0x7f0d0091
public const int search_label = 2131558545;
// aapt resource value: 0x7f0d00a2
public const int select_other_entry = 2131558562;
// aapt resource value: 0x7f0d0052
public const int start_create = 2131558482;
// aapt resource value: 0x7f0d00a4
public const int start_create_import = 2131558564;
// aapt resource value: 0x7f0d00a7
public const int start_create_import = 2131558567;
// aapt resource value: 0x7f0d0050
public const int start_open_file = 2131558480;
@ -1118,14 +1139,17 @@ namespace keepass2android
// aapt resource value: 0x7f0d0010
public const int text = 2131558416;
// aapt resource value: 0x7f0d005c
public const int textView = 2131558492;
// aapt resource value: 0x7f0d001a
public const int title = 2131558426;
// aapt resource value: 0x7f0d003f
public const int title_block = 2131558463;
// aapt resource value: 0x7f0d0083
public const int toggle_password = 2131558531;
// aapt resource value: 0x7f0d0086
public const int toggle_password = 2131558534;
// aapt resource value: 0x7f0d0044
public const int top = 2131558468;
@ -1213,64 +1237,70 @@ namespace keepass2android
public const int file_selection_no_recent = 2130903058;
// aapt resource value: 0x7f030013
public const int generate_password = 2130903059;
public const int filestorage_selection = 2130903059;
// aapt resource value: 0x7f030014
public const int group_add_entry = 2130903060;
public const int filestorage_selection_listitem = 2130903060;
// aapt resource value: 0x7f030015
public const int group_edit = 2130903061;
public const int generate_password = 2130903061;
// aapt resource value: 0x7f030016
public const int group_empty = 2130903062;
public const int group_add_entry = 2130903062;
// aapt resource value: 0x7f030017
public const int group_header = 2130903063;
public const int group_edit = 2130903063;
// aapt resource value: 0x7f030018
public const int group_list_entry = 2130903064;
public const int group_empty = 2130903064;
// aapt resource value: 0x7f030019
public const int icon = 2130903065;
public const int group_header = 2130903065;
// aapt resource value: 0x7f03001a
public const int icon_picker = 2130903066;
public const int group_list_entry = 2130903066;
// aapt resource value: 0x7f03001b
public const int input = 2130903067;
public const int icon = 2130903067;
// aapt resource value: 0x7f03001c
public const int InViewButton = 2130903068;
public const int icon_picker = 2130903068;
// aapt resource value: 0x7f03001d
public const int password = 2130903069;
public const int input = 2130903069;
// aapt resource value: 0x7f03001e
public const int QuickUnlock = 2130903070;
public const int InViewButton = 2130903070;
// aapt resource value: 0x7f03001f
public const int QuickUnlock_Unused = 2130903071;
public const int password = 2130903071;
// aapt resource value: 0x7f030020
public const int SaveButton = 2130903072;
public const int QuickUnlock = 2130903072;
// aapt resource value: 0x7f030021
public const int search = 2130903073;
public const int QuickUnlock_Unused = 2130903073;
// aapt resource value: 0x7f030022
public const int searchurlresults = 2130903074;
public const int SaveButton = 2130903074;
// aapt resource value: 0x7f030023
public const int searchurlresults_empty = 2130903075;
public const int search = 2130903075;
// aapt resource value: 0x7f030024
public const int set_password = 2130903076;
public const int searchurlresults = 2130903076;
// aapt resource value: 0x7f030025
public const int StartScreenButtons = 2130903077;
public const int searchurlresults_empty = 2130903077;
// aapt resource value: 0x7f030026
public const int url_credentials = 2130903078;
public const int set_password = 2130903078;
// aapt resource value: 0x7f030027
public const int StartScreenButtons = 2130903079;
// aapt resource value: 0x7f030028
public const int url_credentials = 2130903080;
static Layout()
{
@ -1376,38 +1406,38 @@ namespace keepass2android
// aapt resource value: 0x7f060166
public const int CannotMoveGroupHere = 2131100006;
// aapt resource value: 0x7f06017a
public const int ChangeLog = 2131100026;
// aapt resource value: 0x7f060179
public const int ChangeLog_0_7 = 2131100025;
// aapt resource value: 0x7f060177
public const int ChangeLog_0_8 = 2131100023;
// aapt resource value: 0x7f060176
public const int ChangeLog_0_8_1 = 2131100022;
// aapt resource value: 0x7f060175
public const int ChangeLog_0_8_2 = 2131100021;
// aapt resource value: 0x7f060174
public const int ChangeLog = 2131100020;
public const int ChangeLog_0_8_3 = 2131100020;
// aapt resource value: 0x7f060173
public const int ChangeLog_0_7 = 2131100019;
// aapt resource value: 0x7f060171
public const int ChangeLog_0_8 = 2131100017;
// aapt resource value: 0x7f060170
public const int ChangeLog_0_8_1 = 2131100016;
// aapt resource value: 0x7f06016f
public const int ChangeLog_0_8_2 = 2131100015;
// aapt resource value: 0x7f06016e
public const int ChangeLog_0_8_3 = 2131100014;
// aapt resource value: 0x7f06016d
public const int ChangeLog_0_8_4 = 2131100013;
// aapt resource value: 0x7f06016c
public const int ChangeLog_0_8_5 = 2131100012;
// aapt resource value: 0x7f06016b
public const int ChangeLog_0_8_6 = 2131100011;
public const int ChangeLog_0_8_4 = 2131100019;
// aapt resource value: 0x7f060172
public const int ChangeLog_keptDonate = 2131100018;
public const int ChangeLog_0_8_5 = 2131100018;
// aapt resource value: 0x7f06016a
public const int ChangeLog_title = 2131100010;
// aapt resource value: 0x7f060171
public const int ChangeLog_0_8_6 = 2131100017;
// aapt resource value: 0x7f060178
public const int ChangeLog_keptDonate = 2131100024;
// aapt resource value: 0x7f060170
public const int ChangeLog_title = 2131100016;
// aapt resource value: 0x7f060032
public const int CheckForFileChangesOnSave_key = 2131099698;
@ -2024,6 +2054,24 @@ namespace keepass2android
// aapt resource value: 0x7f060094
public const int file_browser = 2131099796;
// aapt resource value: 0x7f06016e
public const int filestoragename_dropbox = 2131100014;
// aapt resource value: 0x7f06016a
public const int filestoragename_file = 2131100010;
// aapt resource value: 0x7f06016b
public const int filestoragename_ftp = 2131100011;
// aapt resource value: 0x7f06016f
public const int filestoragename_gdrive = 2131100015;
// aapt resource value: 0x7f06016c
public const int filestoragename_http = 2131100012;
// aapt resource value: 0x7f06016d
public const int filestoragename_https = 2131100013;
// aapt resource value: 0x7f06000f
public const int further_author_names = 2131099663;
@ -2445,14 +2493,14 @@ namespace keepass2android
public partial class Style
{
// aapt resource value: 0x7f0b001b
public const int AdditionalStringLayout = 2131427355;
// aapt resource value: 0x7f0b001d
public const int AdditionalStringLayout = 2131427357;
// aapt resource value: 0x7f0b0000
public const int Base = 2131427328;
// aapt resource value: 0x7f0b0015
public const int BottomBarActionButton = 2131427349;
// aapt resource value: 0x7f0b0017
public const int BottomBarActionButton = 2131427351;
// aapt resource value: 0x7f0b0002
public const int Dialog = 2131427330;
@ -2505,20 +2553,26 @@ namespace keepass2android
// aapt resource value: 0x7f0b0001
public const int NoTitleBar = 2131427329;
// aapt resource value: 0x7f0b0018
public const int TextAppearance_EditEntry = 2131427352;
// aapt resource value: 0x7f0b0017
public const int TextAppearance_EditEntry_LabelSmall = 2131427351;
// aapt resource value: 0x7f0b0015
public const int PaddedContainer = 2131427349;
// aapt resource value: 0x7f0b0016
public const int TextAppearance_EditEntry_Small = 2131427350;
// aapt resource value: 0x7f0b0019
public const int TextAppearance_EditEntry_Value = 2131427353;
public const int PaddedElement = 2131427350;
// aapt resource value: 0x7f0b001a
public const int TextAppearance_SmallHeading = 2131427354;
public const int TextAppearance_EditEntry = 2131427354;
// aapt resource value: 0x7f0b0019
public const int TextAppearance_EditEntry_LabelSmall = 2131427353;
// aapt resource value: 0x7f0b0018
public const int TextAppearance_EditEntry_Small = 2131427352;
// aapt resource value: 0x7f0b001b
public const int TextAppearance_EditEntry_Value = 2131427355;
// aapt resource value: 0x7f0b001c
public const int TextAppearance_SmallHeading = 2131427356;
// aapt resource value: 0x7f0b000a
public const int WhiteOnBlack = 2131427338;

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,26 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
style="@style/PaddedContainer"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Please select the cloud storage type you want to use:"
style="@style/PaddedElement"
android:id="@+id/textView"
android:layout_gravity="left|center_vertical"/>
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:padding="8dp" />
</LinearLayout>
</merge>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="1">
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:id="@+id/filestorage_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:scaleType="fitXY"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/filestorage_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="20dp" >
</TextView>
</LinearLayout>
<View />
</TableRow>
</TableLayout>

View File

@ -315,6 +315,13 @@
<string name="ok_donate">Tell me more!</string>
<string name="no_thanks">No, I don\'t like it that much</string>
<string name="filestoragename_file">Local file</string>
<string name="filestoragename_ftp">FTP</string>
<string name="filestoragename_http">HTTP (WebDav)</string>
<string name="filestoragename_https">HTTPS (WebDav)</string>
<string name="filestoragename_dropbox">Dropbox</string>
<string name="filestoragename_gdrive">Google Drive</string>
<string name="ChangeLog_title">Change log</string>

View File

@ -114,4 +114,17 @@
<item name="android:textStyle">bold</item>
<item name="@android:background">@android:color/transparent</item>
</style>
<style name="PaddedContainer">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:padding">16dp</item>
</style>
<style name="PaddedElement">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:padding">8dp</item>
</style>
</resources>

View File

@ -20,6 +20,7 @@ using System.Collections.Generic;
using System.IO;
using Android.App;
using Android.Content;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime;
using Android.Widget;
@ -162,6 +163,7 @@ namespace keepass2android
internal EntryEditActivityState EntryEditActivityState = null;
public FileDbHelper FileDbHelper;
private List<IFileStorage> _fileStorages;
public Database GetDb()
{
@ -242,11 +244,22 @@ namespace keepass2android
public string GetResourceString(UiStringKey key)
{
var field = typeof (Resource.String).GetField(key.ToString());
return GetResourceString(key.ToString());
}
public string GetResourceString(string key)
{
var field = typeof(Resource.String).GetField(key);
if (field == null)
throw new Exception("Invalid key " + key);
return Application.Context.GetString((int)field.GetValue(null));
}
public Drawable GetResourceDrawable(string key)
{
var field = typeof(Resource.Drawable).GetField(key);
if (field == null)
throw new Exception("Invalid key " + key);
return Application.Context.Resources.GetDrawable((int)field.GetValue(null));
}
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
EventHandler<DialogClickEventArgs> yesHandler,
@ -335,18 +348,52 @@ namespace keepass2android
return new BuiltInFileStorage();
else
{
IFileStorage innerFileStorage = GetCloudFileStorage(iocInfo);
var prefs = PreferenceManager.GetDefaultSharedPreferences(Application.Context);
if (prefs.GetBoolean(Application.Context.Resources.GetString(Resource.String.UseOfflineCache_key), true))
{
return new CachingFileStorage(new BuiltInFileStorage(), Application.Context.CacheDir.Path, this);
return new CachingFileStorage(innerFileStorage, Application.Context.CacheDir.Path, this);
}
else
{
return new BuiltInFileStorage();
return innerFileStorage;
}
}
}
private IFileStorage GetCloudFileStorage(IOConnectionInfo iocInfo)
{
foreach (IFileStorage fs in FileStorages)
{
foreach (string protocolId in fs.SupportedProtocols)
{
if (iocInfo.Path.StartsWith(protocolId + "://"))
return fs;
}
}
//TODO: catch!
throw new Exception("Unknown protocol " + iocInfo);
}
public IEnumerable<IFileStorage> FileStorages
{
get
{
if (_fileStorages == null)
{
_fileStorages = new List<IFileStorage>
{
new DropboxFileStorage(Application.Context),
new BuiltInFileStorage()
};
}
return _fileStorages;
}
}
public void TriggerReload(Context ctx)
{
Handler handler = new Handler(Looper.MainLooper);
@ -432,6 +479,11 @@ namespace keepass2android
{
new CachingFileStorage(new BuiltInFileStorage(), Application.Context.CacheDir.Path, this).ClearCache();
}
public IFileStorage GetFileStorage(string protocolId)
{
return GetFileStorage(new IOConnectionInfo() {Path = protocolId + "://"});
}
}

View File

@ -224,6 +224,7 @@ namespace keepass2android
Button openFileButton = (Button)FindViewById(Resource.Id.start_open_file);
@ -243,8 +244,12 @@ namespace keepass2android
openUrlButton.Visibility = ViewStates.Gone;
#endif
EventHandler openUrlButtonClick = (sender, e) => ShowFilenameDialog(true, false, false, "", GetString(Resource.String.enter_filename_details_url), Intents.RequestCodeFileBrowseForOpen);
openUrlButton.Click += openUrlButtonClick;
//EventHandler openUrlButtonClick = (sender, e) => ShowFilenameDialog(true, false, false, "", GetString(Resource.String.enter_filename_details_url), Intents.RequestCodeFileBrowseForOpen);
openUrlButton.Click += (sender, args) =>
{
Intent intent = new Intent(this, typeof(FileStorageSelectionActivity));
StartActivityForResult(intent, 0);
};
//CREATE NEW
Button createNewButton = (Button)FindViewById(Resource.Id.start_create);
@ -377,7 +382,7 @@ namespace keepass2android
void LaunchPasswordActivityForIoc(IOConnectionInfo ioc)
{
if ((!ioc.IsLocalFile()) && (ioc.CredSaveMode != IOCredSaveMode.SaveCred))
if (App.Kp2a.GetFileStorage(ioc).RequiresCredentials(ioc))
{
//Build dialog to query credentials:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@ -444,6 +449,15 @@ namespace keepass2android
FillData();
if (resultCode == KeePass.ExitFileStorageSelectionOk)
{
LaunchPasswordActivityForIoc(new IOConnectionInfo()
{
Path = data.GetStringExtra("protocolId")+":///keepass/keepass.kdbx"
}
);
}
if ( (requestCode == Intents.RequestCodeFileBrowseForCreate
|| requestCode == Intents.RequestCodeFileBrowseForOpen)
&& resultCode == Result.Ok) {

View File

@ -78,6 +78,7 @@
<Reference Include="Mono.Android.Support.v4" />
</ItemGroup>
<ItemGroup>
<Compile Include="FileStorageSelectionActivity.cs" />
<Compile Include="DonateReminder.cs" />
<Compile Include="app\ApplicationBroadcastReceiver.cs" />
<Compile Include="ChangeLog.cs" />
@ -654,6 +655,10 @@
<Folder Include="SupportLib\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
<Project>{48574278-4779-4b3a-a9e4-9cf1bc285d0b}</Project>
<Name>JavaFileStorageBindings</Name>
</ProjectReference>
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
<Project>{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}</Project>
<Name>KeePassLib2Android</Name>
@ -765,4 +770,40 @@
<ItemGroup>
<AndroidResource Include="Resources\drawable-xxhdpi-v11\ic_unlocked_gray.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\filestorage_selection.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\filestorage_selection_listitem.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_storage_dropbox.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_storage_ftp.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_storage_gdrive.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\ic_storage_dropbox.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\ic_storage_ftp.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\ic_storage_gdrive.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_storage_https.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_storage_http.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\ic_storage_https.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-hdpi\ic_storage_http.png" />
</ItemGroup>
</Project>