diff --git a/.gitignore b/.gitignore
index 8d3e8133..76d73205 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/src/JavaFileStorageBindings/Additions/AboutAdditions.txt b/src/JavaFileStorageBindings/Additions/AboutAdditions.txt
new file mode 100644
index 00000000..08caee33
--- /dev/null
+++ b/src/JavaFileStorageBindings/Additions/AboutAdditions.txt
@@ -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; }
+}
\ No newline at end of file
diff --git a/src/JavaFileStorageBindings/Jars/AboutJars.txt b/src/JavaFileStorageBindings/Jars/AboutJars.txt
new file mode 100644
index 00000000..c359b62f
--- /dev/null
+++ b/src/JavaFileStorageBindings/Jars/AboutJars.txt
@@ -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".
\ No newline at end of file
diff --git a/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj b/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj
new file mode 100644
index 00000000..d9d0dfb2
--- /dev/null
+++ b/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj
@@ -0,0 +1,84 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {48574278-4779-4B3A-A9E4-9CF1BC285D0B}
+ {10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Properties
+ JavaFileStorageBindings
+ JavaFileStorageBindings
+ 512
+ v2.2
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Jars\javafilestorage.jar
+
+
+
+
+ Jars\android-support-v4.jar
+
+
+
+
+ Jars\dropbox-android-sdk-1.5.4.jar
+
+
+
+
+ Jars\httpmime-4.0.3.jar
+
+
+
+
+ Jars\json_simple-1.1.jar
+
+
+
+
+
\ No newline at end of file
diff --git a/src/JavaFileStorageBindings/Properties/AssemblyInfo.cs b/src/JavaFileStorageBindings/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..c49cfd29
--- /dev/null
+++ b/src/JavaFileStorageBindings/Properties/AssemblyInfo.cs
@@ -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)]
diff --git a/src/JavaFileStorageBindings/Transforms/EnumFields.xml b/src/JavaFileStorageBindings/Transforms/EnumFields.xml
new file mode 100644
index 00000000..22959957
--- /dev/null
+++ b/src/JavaFileStorageBindings/Transforms/EnumFields.xml
@@ -0,0 +1,14 @@
+
+
+
\ No newline at end of file
diff --git a/src/JavaFileStorageBindings/Transforms/EnumMethods.xml b/src/JavaFileStorageBindings/Transforms/EnumMethods.xml
new file mode 100644
index 00000000..49216c61
--- /dev/null
+++ b/src/JavaFileStorageBindings/Transforms/EnumMethods.xml
@@ -0,0 +1,13 @@
+
+
+
\ No newline at end of file
diff --git a/src/JavaFileStorageBindings/Transforms/Metadata.xml b/src/JavaFileStorageBindings/Transforms/Metadata.xml
new file mode 100644
index 00000000..2587ddc4
--- /dev/null
+++ b/src/JavaFileStorageBindings/Transforms/Metadata.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/src/KeePass.sln b/src/KeePass.sln
index c0b6a9f6..9342928d 100644
--- a/src/KeePass.sln
+++ b/src/KeePass.sln
@@ -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
diff --git a/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs b/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs
index da2a2553..c5f2b370 100644
--- a/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/BuiltInFileStorage.cs
@@ -19,6 +19,17 @@ namespace keepass2android.Io
{
public class BuiltInFileStorage: IFileStorage
{
+ public IEnumerable 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);
+ }
}
}
\ No newline at end of file
diff --git a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs
index 508c73ea..b96135a5 100644
--- a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs
@@ -77,6 +77,8 @@ namespace keepass2android.Io
IoUtil.DeleteDir(new Java.IO.File(_streamCacheDir), true);
}
+ public IEnumerable 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)
{
diff --git a/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs b/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs
new file mode 100644
index 00000000..634f2692
--- /dev/null
+++ b/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs
@@ -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 SupportedProtocols { get { yield return "dropbox"; } }
+ }
+}
\ No newline at end of file
diff --git a/src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs b/src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs
new file mode 100644
index 00000000..fd3e49ea
--- /dev/null
+++ b/src/Kp2aBusinessLogic/Io/GDriveFileStorage.cs
@@ -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 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();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Kp2aBusinessLogic/Io/IFileStorage.cs b/src/Kp2aBusinessLogic/Io/IFileStorage.cs
index 91cf972c..a3a90402 100644
--- a/src/Kp2aBusinessLogic/Io/IFileStorage.cs
+++ b/src/Kp2aBusinessLogic/Io/IFileStorage.cs
@@ -33,6 +33,8 @@ namespace keepass2android.Io
/// have an IIoStorageId interface in few cases.*/
public interface IFileStorage
{
+ IEnumerable SupportedProtocols { get; }
+
///
/// Deletes the given file.
///
@@ -55,10 +57,26 @@ namespace keepass2android.Io
/// A string which should not be null.
string GetCurrentFileVersionFast(IOConnectionInfo ioc);
+ ///
+ /// Opens the given file for reading
+ ///
Stream OpenFileForRead(IOConnectionInfo ioc);
- //Stream OpenFileForWrite( IOConnectionInfo ioc, bool useTransaction);
+
+ ///
+ /// Opens a write transaction for writing to the given ioc.
+ ///
+ /// ioc to write to
+ /// if true, force to use file system level transaction. This might be ignored if the file storage has built in transaction support
IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction);
+ ///
+ /// 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.
+ ///
+ /// This is due to different storage types requiring different workflows for authentication processes
+ IFileStorageSetup RequiredSetup { get; }
+
///
/// brings up a dialog to query credentials or something like this.
///
@@ -73,6 +91,37 @@ namespace keepass2android.Io
bool? FileExists( /*ioId*/);
string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc);
+
+ ///
+ /// Returns true if the the given ioc must be filled with username/password
+ ///
+ bool RequiresCredentials(IOConnectionInfo ioc);
+ }
+
+ ///
+ /// Base interface for required setup code
+ ///
+ public interface IFileStorageSetup
+ {
+ ///
+ /// call this when the user explicitly wants to use this file storage. Might require user interaction.
+ /// May throw if the setup failed permanentaly.
+ ///
+ /// true if the setup was succesful immediately (without UI). Returns false if setup was not successful but no error occured or can be displayed.
+ bool TrySetup(Activity activity);
+ }
+
+ ///
+ /// Interface which can be used additionally for an IFileStorageSetup to indicate that setup must be completed in OnResume()
+ ///
+ public interface IFileStorageSetupOnResume
+ {
+ ///
+ /// call this after TrySetup() returned false in the next OnResume()
+ /// May throw if the setup failed permanentaly.
+ ///
+ /// true if setup was succesful
+ bool TrySetupOnResume(Activity activity);
}
public interface IWriteTransaction: IDisposable
diff --git a/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs
new file mode 100644
index 00000000..40f9ea5e
--- /dev/null
+++ b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs
@@ -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 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);
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
index 255fa70e..b4ea8a6a 100644
--- a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
+++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
@@ -57,8 +57,11 @@
+
+
+
@@ -89,6 +92,10 @@
+
+ {48574278-4779-4b3a-a9e4-9cf1bc285d0b}
+ JavaFileStorageBindings
+
{545b4a6b-8bba-4fbe-92fc-4ac060122a54}
KeePassLib2Android
diff --git a/src/Kp2aUnitTests/TestFileStorage.cs b/src/Kp2aUnitTests/TestFileStorage.cs
index ed70ee3c..9dcf2727 100644
--- a/src/Kp2aUnitTests/TestFileStorage.cs
+++ b/src/Kp2aUnitTests/TestFileStorage.cs
@@ -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 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);
+ }
}
}
\ No newline at end of file
diff --git a/src/java/JavaFileStorage/.classpath b/src/java/JavaFileStorage/.classpath
new file mode 100644
index 00000000..2731f9c5
--- /dev/null
+++ b/src/java/JavaFileStorage/.classpath
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/java/JavaFileStorage/.project b/src/java/JavaFileStorage/.project
new file mode 100644
index 00000000..32ed6251
--- /dev/null
+++ b/src/java/JavaFileStorage/.project
@@ -0,0 +1,33 @@
+
+
+ JavaFileStorage
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/src/java/JavaFileStorage/.settings/org.eclipse.jdt.core.prefs b/src/java/JavaFileStorage/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..b080d2dd
--- /dev/null
+++ b/src/java/JavaFileStorage/.settings/org.eclipse.jdt.core.prefs
@@ -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
diff --git a/src/java/JavaFileStorage/AndroidManifest.xml b/src/java/JavaFileStorage/AndroidManifest.xml
new file mode 100644
index 00000000..4b9c3feb
--- /dev/null
+++ b/src/java/JavaFileStorage/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/java/JavaFileStorage/libs/HTTPCOMPONENTS-LICENSE.txt b/src/java/JavaFileStorage/libs/HTTPCOMPONENTS-LICENSE.txt
new file mode 100644
index 00000000..2c41ec88
--- /dev/null
+++ b/src/java/JavaFileStorage/libs/HTTPCOMPONENTS-LICENSE.txt
@@ -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)
+
diff --git a/src/java/JavaFileStorage/libs/JSON-SIMPLE-LICENSE.txt b/src/java/JavaFileStorage/libs/JSON-SIMPLE-LICENSE.txt
new file mode 100644
index 00000000..57bc88a1
--- /dev/null
+++ b/src/java/JavaFileStorage/libs/JSON-SIMPLE-LICENSE.txt
@@ -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.
+
diff --git a/src/java/JavaFileStorage/libs/android-support-v4.jar b/src/java/JavaFileStorage/libs/android-support-v4.jar
new file mode 100644
index 00000000..428bdbc0
Binary files /dev/null and b/src/java/JavaFileStorage/libs/android-support-v4.jar differ
diff --git a/src/java/JavaFileStorage/libs/dropbox-android-sdk-1.5.4.jar b/src/java/JavaFileStorage/libs/dropbox-android-sdk-1.5.4.jar
new file mode 100644
index 00000000..38a3602f
Binary files /dev/null and b/src/java/JavaFileStorage/libs/dropbox-android-sdk-1.5.4.jar differ
diff --git a/src/java/JavaFileStorage/libs/httpmime-4.0.3.jar b/src/java/JavaFileStorage/libs/httpmime-4.0.3.jar
new file mode 100644
index 00000000..0dfd3312
Binary files /dev/null and b/src/java/JavaFileStorage/libs/httpmime-4.0.3.jar differ
diff --git a/src/java/JavaFileStorage/libs/json_simple-1.1.jar b/src/java/JavaFileStorage/libs/json_simple-1.1.jar
new file mode 100644
index 00000000..f395f414
Binary files /dev/null and b/src/java/JavaFileStorage/libs/json_simple-1.1.jar differ
diff --git a/src/java/JavaFileStorage/proguard-project.txt b/src/java/JavaFileStorage/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/src/java/JavaFileStorage/proguard-project.txt
@@ -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 *;
+#}
diff --git a/src/java/JavaFileStorage/project.properties b/src/java/JavaFileStorage/project.properties
new file mode 100644
index 00000000..484dab07
--- /dev/null
+++ b/src/java/JavaFileStorage/project.properties
@@ -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
diff --git a/src/java/JavaFileStorage/res/drawable-hdpi/ic_launcher.png b/src/java/JavaFileStorage/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..96a442e5
Binary files /dev/null and b/src/java/JavaFileStorage/res/drawable-hdpi/ic_launcher.png differ
diff --git a/src/java/JavaFileStorage/res/drawable-mdpi/ic_launcher.png b/src/java/JavaFileStorage/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..359047df
Binary files /dev/null and b/src/java/JavaFileStorage/res/drawable-mdpi/ic_launcher.png differ
diff --git a/src/java/JavaFileStorage/res/drawable-xhdpi/ic_launcher.png b/src/java/JavaFileStorage/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
Binary files /dev/null and b/src/java/JavaFileStorage/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/src/java/JavaFileStorage/res/values-v11/styles.xml b/src/java/JavaFileStorage/res/values-v11/styles.xml
new file mode 100644
index 00000000..3c02242a
--- /dev/null
+++ b/src/java/JavaFileStorage/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/src/java/JavaFileStorage/res/values-v14/styles.xml b/src/java/JavaFileStorage/res/values-v14/styles.xml
new file mode 100644
index 00000000..a91fd037
--- /dev/null
+++ b/src/java/JavaFileStorage/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/src/java/JavaFileStorage/res/values/strings.xml b/src/java/JavaFileStorage/res/values/strings.xml
new file mode 100644
index 00000000..51a5f8cc
--- /dev/null
+++ b/src/java/JavaFileStorage/res/values/strings.xml
@@ -0,0 +1,5 @@
+
+
+ JavaFileStorage
+
+
diff --git a/src/java/JavaFileStorage/res/values/styles.xml b/src/java/JavaFileStorage/res/values/styles.xml
new file mode 100644
index 00000000..6ce89c7b
--- /dev/null
+++ b/src/java/JavaFileStorage/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/DropboxFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/DropboxFileStorage.java
new file mode 100644
index 00000000..d5a3fa69
--- /dev/null
+++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/DropboxFileStorage.java
@@ -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 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(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 listContents(String path) throws Exception
+ {
+ ArrayList files = new ArrayList();
+ 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;
+ }
+
+}
diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java
new file mode 100644
index 00000000..588ea0f0
--- /dev/null
+++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java
@@ -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;
+}
\ No newline at end of file
diff --git a/src/keepass2android/FileStorageSelectionActivity.cs b/src/keepass2android/FileStorageSelectionActivity.cs
new file mode 100644
index 00000000..48c47864
--- /dev/null
+++ b/src/keepass2android/FileStorageSelectionActivity.cs
@@ -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 _protocolIds = new List();
+
+ 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();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/keepass2android/KeePass.cs b/src/keepass2android/KeePass.cs
index 8167eb13..92e5e481 100644
--- a/src/keepass2android/KeePass.cs
+++ b/src/keepass2android/KeePass.cs
@@ -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
@@ -144,7 +147,7 @@ namespace keepass2android
StartActivityForResult(intent, 0);
Finish();
-
+
}
diff --git a/src/keepass2android/PasswordActivity.cs b/src/keepass2android/PasswordActivity.cs
index 7bc97e25..ef9a3525 100644
--- a/src/keepass2android/PasswordActivity.cs
+++ b/src/keepass2android/PasswordActivity.cs
@@ -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())
diff --git a/src/keepass2android/Properties/AndroidManifest_net.xml b/src/keepass2android/Properties/AndroidManifest_net.xml
index 333821da..f58af94c 100644
--- a/src/keepass2android/Properties/AndroidManifest_net.xml
+++ b/src/keepass2android/Properties/AndroidManifest_net.xml
@@ -6,6 +6,19 @@
android:installLocation="auto">
+
+
+
+
+
+
+
+
+
+
diff --git a/src/keepass2android/Resources/Resource.designer.cs b/src/keepass2android/Resources/Resource.designer.cs
index 057fc203..c76147fc 100644
--- a/src/keepass2android/Resources/Resource.designer.cs
+++ b/src/keepass2android/Resources/Resource.designer.cs
@@ -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;
diff --git a/src/keepass2android/Resources/drawable-hdpi/ic_storage_dropbox.png b/src/keepass2android/Resources/drawable-hdpi/ic_storage_dropbox.png
new file mode 100644
index 00000000..3170535d
Binary files /dev/null and b/src/keepass2android/Resources/drawable-hdpi/ic_storage_dropbox.png differ
diff --git a/src/keepass2android/Resources/drawable-hdpi/ic_storage_ftp.png b/src/keepass2android/Resources/drawable-hdpi/ic_storage_ftp.png
new file mode 100644
index 00000000..b5f28c47
Binary files /dev/null and b/src/keepass2android/Resources/drawable-hdpi/ic_storage_ftp.png differ
diff --git a/src/keepass2android/Resources/drawable-hdpi/ic_storage_gdrive.png b/src/keepass2android/Resources/drawable-hdpi/ic_storage_gdrive.png
new file mode 100644
index 00000000..d983a004
Binary files /dev/null and b/src/keepass2android/Resources/drawable-hdpi/ic_storage_gdrive.png differ
diff --git a/src/keepass2android/Resources/drawable-hdpi/ic_storage_http.png b/src/keepass2android/Resources/drawable-hdpi/ic_storage_http.png
new file mode 100644
index 00000000..b5f28c47
Binary files /dev/null and b/src/keepass2android/Resources/drawable-hdpi/ic_storage_http.png differ
diff --git a/src/keepass2android/Resources/drawable-hdpi/ic_storage_https.png b/src/keepass2android/Resources/drawable-hdpi/ic_storage_https.png
new file mode 100644
index 00000000..b5f28c47
Binary files /dev/null and b/src/keepass2android/Resources/drawable-hdpi/ic_storage_https.png differ
diff --git a/src/keepass2android/Resources/drawable/ic_storage_dropbox.png b/src/keepass2android/Resources/drawable/ic_storage_dropbox.png
new file mode 100644
index 00000000..27b8fc40
Binary files /dev/null and b/src/keepass2android/Resources/drawable/ic_storage_dropbox.png differ
diff --git a/src/keepass2android/Resources/drawable/ic_storage_ftp.png b/src/keepass2android/Resources/drawable/ic_storage_ftp.png
new file mode 100644
index 00000000..e164a9f3
Binary files /dev/null and b/src/keepass2android/Resources/drawable/ic_storage_ftp.png differ
diff --git a/src/keepass2android/Resources/drawable/ic_storage_gdrive.png b/src/keepass2android/Resources/drawable/ic_storage_gdrive.png
new file mode 100644
index 00000000..1761d023
Binary files /dev/null and b/src/keepass2android/Resources/drawable/ic_storage_gdrive.png differ
diff --git a/src/keepass2android/Resources/drawable/ic_storage_http.png b/src/keepass2android/Resources/drawable/ic_storage_http.png
new file mode 100644
index 00000000..e164a9f3
Binary files /dev/null and b/src/keepass2android/Resources/drawable/ic_storage_http.png differ
diff --git a/src/keepass2android/Resources/drawable/ic_storage_https.png b/src/keepass2android/Resources/drawable/ic_storage_https.png
new file mode 100644
index 00000000..e164a9f3
Binary files /dev/null and b/src/keepass2android/Resources/drawable/ic_storage_https.png differ
diff --git a/src/keepass2android/Resources/layout/filestorage_selection.xml b/src/keepass2android/Resources/layout/filestorage_selection.xml
new file mode 100644
index 00000000..1fdf3438
--- /dev/null
+++ b/src/keepass2android/Resources/layout/filestorage_selection.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/keepass2android/Resources/layout/filestorage_selection_listitem.xml b/src/keepass2android/Resources/layout/filestorage_selection_listitem.xml
new file mode 100644
index 00000000..ae77705b
--- /dev/null
+++ b/src/keepass2android/Resources/layout/filestorage_selection_listitem.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml
index 586c86d3..80a46cd8 100644
--- a/src/keepass2android/Resources/values/strings.xml
+++ b/src/keepass2android/Resources/values/strings.xml
@@ -314,6 +314,13 @@
Today, it\'s Oktoberfest! If you like Keepass2Android: wouldn\'t today be a good day to buy me a beer?
Tell me more!
No, I don\'t like it that much
+
+ Local file
+ FTP
+ HTTP (WebDav)
+ HTTPS (WebDav)
+ Dropbox
+ Google Drive
Change log
diff --git a/src/keepass2android/Resources/values/styles.xml b/src/keepass2android/Resources/values/styles.xml
index 42ee4bd2..1492a654 100644
--- a/src/keepass2android/Resources/values/styles.xml
+++ b/src/keepass2android/Resources/values/styles.xml
@@ -114,4 +114,17 @@
- bold
- @android:color/transparent
+
+
+
+
+
\ No newline at end of file
diff --git a/src/keepass2android/app/App.cs b/src/keepass2android/app/App.cs
index dd7bf28f..0d17f293 100644
--- a/src/keepass2android/app/App.cs
+++ b/src/keepass2android/app/App.cs
@@ -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,8 +163,9 @@ namespace keepass2android
internal EntryEditActivityState EntryEditActivityState = null;
public FileDbHelper FileDbHelper;
+ private List _fileStorages;
- public Database GetDb()
+ public Database GetDb()
{
if (_db == null)
{
@@ -242,11 +244,22 @@ namespace keepass2android
public string GetResourceString(UiStringKey key)
{
- var field = typeof (Resource.String).GetField(key.ToString());
- if (field == null)
- throw new Exception("Invalid key " + key);
- return Application.Context.GetString((int)field.GetValue(null));
+ 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 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 FileStorages
+ {
+ get
+ {
+ if (_fileStorages == null)
+ {
+ _fileStorages = new List
+ {
+ 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 + "://"});
+ }
}
diff --git a/src/keepass2android/fileselect/FileSelectActivity.cs b/src/keepass2android/fileselect/FileSelectActivity.cs
index ec9d7d7c..2e410795 100644
--- a/src/keepass2android/fileselect/FileSelectActivity.cs
+++ b/src/keepass2android/fileselect/FileSelectActivity.cs
@@ -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);
@@ -443,6 +448,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)
diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj
index e49addbe..ed78c11d 100644
--- a/src/keepass2android/keepass2android.csproj
+++ b/src/keepass2android/keepass2android.csproj
@@ -78,6 +78,7 @@
+
@@ -654,6 +655,10 @@
+
+ {48574278-4779-4b3a-a9e4-9cf1bc285d0b}
+ JavaFileStorageBindings
+
{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}
KeePassLib2Android
@@ -765,4 +770,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file