mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-12-23 07:28:48 -05:00
* Added file chooser to KP2A
* added functionality to file storage interface and (some) implementations to delete files/folders, create folders, list contents -> Dropbox functionality implemented
This commit is contained in:
parent
15b7ca38c8
commit
74acd19092
48
src/AndroidFileChooserBinding/Additions/AboutAdditions.txt
Normal file
48
src/AndroidFileChooserBinding/Additions/AboutAdditions.txt
Normal file
@ -0,0 +1,48 @@
|
||||
Additions allow you to add arbitrary C# to the generated classes
|
||||
before they are compiled. This can be helpful for providing convenience
|
||||
methods or adding pure C# classes.
|
||||
|
||||
== Adding Methods to Generated Classes ==
|
||||
|
||||
Let's say the library being bound has a Rectangle class with a constructor
|
||||
that takes an x and y position, and a width and length size. It will look like
|
||||
this:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (int x, int y, int width, int height)
|
||||
{
|
||||
// JNI bindings
|
||||
}
|
||||
}
|
||||
|
||||
Imagine we want to add a constructor to this class that takes a Point and
|
||||
Size structure instead of 4 ints. We can add a new file called Rectangle.cs
|
||||
with a partial class containing our new method:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (Point location, Size size) :
|
||||
this (location.X, location.Y, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
At compile time, the additions class will be added to the generated class
|
||||
and the final assembly will a Rectangle class with both constructors.
|
||||
|
||||
|
||||
== Adding C# Classes ==
|
||||
|
||||
Another thing that can be done is adding fully C# managed classes to the
|
||||
generated library. In the above example, let's assume that there isn't a
|
||||
Point class available in Java or our library. The one we create doesn't need
|
||||
to interact with Java, so we'll create it like a normal class in C#.
|
||||
|
||||
By adding a Point.cs file with this class, it will end up in the binding library:
|
||||
|
||||
public class Point
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{3C0F7FE5-639F-4422-A087-8B26CF862D1B}</ProjectGuid>
|
||||
<ProjectTypeGuids>{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AndroidFileChooserBinding</RootNamespace>
|
||||
<AssemblyName>AndroidFileChooserBinding</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkVersion>v2.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<LibraryProjectZip Include="..\java\android-filechooser\code\project.zip">
|
||||
<Link>project.zip</Link>
|
||||
</LibraryProjectZip>
|
||||
<None Include="Jars\AboutJars.txt" />
|
||||
<None Include="Additions\AboutAdditions.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<TransformFile Include="Transforms\Metadata.xml" />
|
||||
<TransformFile Include="Transforms\EnumFields.xml" />
|
||||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedReferenceJar Include="Jars\android-support-v4.jar" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
24
src/AndroidFileChooserBinding/Jars/AboutJars.txt
Normal file
24
src/AndroidFileChooserBinding/Jars/AboutJars.txt
Normal file
@ -0,0 +1,24 @@
|
||||
This directory is for Android .jars.
|
||||
|
||||
There are 2 types of jars that are supported:
|
||||
|
||||
== Input Jar ==
|
||||
|
||||
This is the jar that bindings should be generated for.
|
||||
|
||||
For example, if you were binding the Google Maps library, this would
|
||||
be Google's "maps.jar".
|
||||
|
||||
Set the build action for these jars in the properties page to "InputJar".
|
||||
|
||||
|
||||
== Reference Jars ==
|
||||
|
||||
These are jars that are referenced by the input jar. C# bindings will
|
||||
not be created for these jars. These jars will be used to resolve
|
||||
types used by the input jar.
|
||||
|
||||
NOTE: Do not add "android.jar" as a reference jar. It will be added automatically
|
||||
based on the Target Framework selected.
|
||||
|
||||
Set the build action for these jars in the properties page to "ReferenceJar".
|
BIN
src/AndroidFileChooserBinding/Jars/android-support-v4.jar
Normal file
BIN
src/AndroidFileChooserBinding/Jars/android-support-v4.jar
Normal file
Binary file not shown.
34
src/AndroidFileChooserBinding/Properties/AssemblyInfo.cs
Normal file
34
src/AndroidFileChooserBinding/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Android.App;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("AndroidFileChooserBinding")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AndroidFileChooserBinding")]
|
||||
[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)]
|
14
src/AndroidFileChooserBinding/Transforms/EnumFields.xml
Normal file
14
src/AndroidFileChooserBinding/Transforms/EnumFields.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<enum-field-mappings>
|
||||
<!--
|
||||
This example converts the constants Fragment_id, Fragment_name,
|
||||
and Fragment_tag from android.support.v4.app.FragmentActivity.FragmentTag
|
||||
to an enum called Android.Support.V4.App.FragmentTagType with values
|
||||
Id, Name, and Tag.
|
||||
|
||||
<mapping jni-class="android/support/v4/app/FragmentActivity$FragmentTag" clr-enum-type="Android.Support.V4.App.FragmentTagType">
|
||||
<field jni-name="Fragment_name" clr-name="Name" value="0" />
|
||||
<field jni-name="Fragment_id" clr-name="Id" value="1" />
|
||||
<field jni-name="Fragment_tag" clr-name="Tag" value="2" />
|
||||
</mapping>
|
||||
-->
|
||||
</enum-field-mappings>
|
13
src/AndroidFileChooserBinding/Transforms/EnumMethods.xml
Normal file
13
src/AndroidFileChooserBinding/Transforms/EnumMethods.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<enum-method-mappings>
|
||||
<!--
|
||||
This example changes the Java method:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (int flags)
|
||||
to be:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (Android.OS.ParcelableWriteFlags flags)
|
||||
when bound in C#.
|
||||
|
||||
<mapping jni-class="android/support/v4/app/Fragment.SavedState">
|
||||
<method jni-name="writeToParcel" parameter="flags" clr-enum-type="Android.OS.ParcelableWriteFlags" />
|
||||
</mapping>
|
||||
-->
|
||||
</enum-method-mappings>
|
19
src/AndroidFileChooserBinding/Transforms/Metadata.xml
Normal file
19
src/AndroidFileChooserBinding/Transforms/Metadata.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<metadata>
|
||||
<remove-node path="/api/package[@name='group.pals.android.lib.ui.filechooser.providers.localfile']/class[@name='FileObserverEx']" />
|
||||
|
||||
<!--
|
||||
|
||||
<remove-node path="/api/package[@name='group.pals.android.lib.ui.filechooser']/class[@name='FragmentFiles']" />
|
||||
<remove-node path="/api/package[@name='group.pals.android.lib.ui.filechooser.utils.ui.bookmark']/class[@name='BookmarkFragment']" />
|
||||
<remove-node path="/api/package[@name='group.pals.android.lib.ui.filechooser.utils.ui.history']/class[@name='HistoryFragment']" />
|
||||
|
||||
|
||||
<remove-node path="/api/package[@name='group.pals.android.lib.ui.filechooser.prefs']/class[@name='DisplayPrefs']" />
|
||||
|
||||
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
|
||||
|
||||
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
|
||||
-->
|
||||
</metadata>
|
48
src/AppCompatV7Binding/Additions/AboutAdditions.txt
Normal file
48
src/AppCompatV7Binding/Additions/AboutAdditions.txt
Normal file
@ -0,0 +1,48 @@
|
||||
Additions allow you to add arbitrary C# to the generated classes
|
||||
before they are compiled. This can be helpful for providing convenience
|
||||
methods or adding pure C# classes.
|
||||
|
||||
== Adding Methods to Generated Classes ==
|
||||
|
||||
Let's say the library being bound has a Rectangle class with a constructor
|
||||
that takes an x and y position, and a width and length size. It will look like
|
||||
this:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (int x, int y, int width, int height)
|
||||
{
|
||||
// JNI bindings
|
||||
}
|
||||
}
|
||||
|
||||
Imagine we want to add a constructor to this class that takes a Point and
|
||||
Size structure instead of 4 ints. We can add a new file called Rectangle.cs
|
||||
with a partial class containing our new method:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (Point location, Size size) :
|
||||
this (location.X, location.Y, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
At compile time, the additions class will be added to the generated class
|
||||
and the final assembly will a Rectangle class with both constructors.
|
||||
|
||||
|
||||
== Adding C# Classes ==
|
||||
|
||||
Another thing that can be done is adding fully C# managed classes to the
|
||||
generated library. In the above example, let's assume that there isn't a
|
||||
Point class available in Java or our library. The one we create doesn't need
|
||||
to interact with Java, so we'll create it like a normal class in C#.
|
||||
|
||||
By adding a Point.cs file with this class, it will end up in the binding library:
|
||||
|
||||
public class Point
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
}
|
60
src/AppCompatV7Binding/AppCompatV7Binding.csproj
Normal file
60
src/AppCompatV7Binding/AppCompatV7Binding.csproj
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{23233A28-D74F-4BF8-B4D8-834060840BD7}</ProjectGuid>
|
||||
<ProjectTypeGuids>{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AppCompatV7Binding</RootNamespace>
|
||||
<AssemblyName>AppCompatV7Binding</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkVersion>v2.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Jars\AboutJars.txt" />
|
||||
<None Include="Additions\AboutAdditions.txt" />
|
||||
<LibraryProjectZip Include="project_appcompatv7.zip" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<TransformFile Include="Transforms\Metadata.xml" />
|
||||
<TransformFile Include="Transforms\EnumFields.xml" />
|
||||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
24
src/AppCompatV7Binding/Jars/AboutJars.txt
Normal file
24
src/AppCompatV7Binding/Jars/AboutJars.txt
Normal file
@ -0,0 +1,24 @@
|
||||
This directory is for Android .jars.
|
||||
|
||||
There are 2 types of jars that are supported:
|
||||
|
||||
== Input Jar ==
|
||||
|
||||
This is the jar that bindings should be generated for.
|
||||
|
||||
For example, if you were binding the Google Maps library, this would
|
||||
be Google's "maps.jar".
|
||||
|
||||
Set the build action for these jars in the properties page to "InputJar".
|
||||
|
||||
|
||||
== Reference Jars ==
|
||||
|
||||
These are jars that are referenced by the input jar. C# bindings will
|
||||
not be created for these jars. These jars will be used to resolve
|
||||
types used by the input jar.
|
||||
|
||||
NOTE: Do not add "android.jar" as a reference jar. It will be added automatically
|
||||
based on the Target Framework selected.
|
||||
|
||||
Set the build action for these jars in the properties page to "ReferenceJar".
|
34
src/AppCompatV7Binding/Properties/AssemblyInfo.cs
Normal file
34
src/AppCompatV7Binding/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Android.App;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("AppCompatV7Binding")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AppCompatV7Binding")]
|
||||
[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)]
|
14
src/AppCompatV7Binding/Transforms/EnumFields.xml
Normal file
14
src/AppCompatV7Binding/Transforms/EnumFields.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<enum-field-mappings>
|
||||
<!--
|
||||
This example converts the constants Fragment_id, Fragment_name,
|
||||
and Fragment_tag from android.support.v4.app.FragmentActivity.FragmentTag
|
||||
to an enum called Android.Support.V4.App.FragmentTagType with values
|
||||
Id, Name, and Tag.
|
||||
|
||||
<mapping jni-class="android/support/v4/app/FragmentActivity$FragmentTag" clr-enum-type="Android.Support.V4.App.FragmentTagType">
|
||||
<field jni-name="Fragment_name" clr-name="Name" value="0" />
|
||||
<field jni-name="Fragment_id" clr-name="Id" value="1" />
|
||||
<field jni-name="Fragment_tag" clr-name="Tag" value="2" />
|
||||
</mapping>
|
||||
-->
|
||||
</enum-field-mappings>
|
13
src/AppCompatV7Binding/Transforms/EnumMethods.xml
Normal file
13
src/AppCompatV7Binding/Transforms/EnumMethods.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<enum-method-mappings>
|
||||
<!--
|
||||
This example changes the Java method:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (int flags)
|
||||
to be:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (Android.OS.ParcelableWriteFlags flags)
|
||||
when bound in C#.
|
||||
|
||||
<mapping jni-class="android/support/v4/app/Fragment.SavedState">
|
||||
<method jni-name="writeToParcel" parameter="flags" clr-enum-type="Android.OS.ParcelableWriteFlags" />
|
||||
</mapping>
|
||||
-->
|
||||
</enum-method-mappings>
|
9
src/AppCompatV7Binding/Transforms/Metadata.xml
Normal file
9
src/AppCompatV7Binding/Transforms/Metadata.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<metadata>
|
||||
<!--
|
||||
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
|
||||
|
||||
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
|
||||
-->
|
||||
</metadata>
|
BIN
src/AppCompatV7Binding/project_appcompatv7.zip
Normal file
BIN
src/AppCompatV7Binding/project_appcompatv7.zip
Normal file
Binary file not shown.
@ -19,6 +19,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwofishCipher", "TwofishCip
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JavaFileStorageBindings", "JavaFileStorageBindings\JavaFileStorageBindings.csproj", "{48574278-4779-4B3A-A9E4-9CF1BC285D0B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppCompatV7Binding", "AppCompatV7Binding\AppCompatV7Binding.csproj", "{23233A28-D74F-4BF8-B4D8-834060840BD7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidFileChooserBinding", "AndroidFileChooserBinding\AndroidFileChooserBinding.csproj", "{3C0F7FE5-639F-4422-A087-8B26CF862D1B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -222,6 +226,42 @@ Global
|
||||
{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
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||
{23233A28-D74F-4BF8-B4D8-834060840BD7}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -30,11 +30,11 @@ namespace keepass2android.Io
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteFile(IOConnectionInfo ioc)
|
||||
public void Delete(IOConnectionInfo ioc)
|
||||
{
|
||||
//todo check if directory
|
||||
IOConnection.DeleteFile(ioc);
|
||||
}
|
||||
|
||||
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
|
||||
{
|
||||
if (!ioc.IsLocalFile())
|
||||
@ -137,5 +137,17 @@ namespace keepass2android.Io
|
||||
{
|
||||
return (!ioc.IsLocalFile()) && (ioc.CredSaveMode != IOCredSaveMode.SaveCred);
|
||||
}
|
||||
|
||||
public void CreateDirectory(IOConnectionInfo ioc)
|
||||
{
|
||||
//TODO
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
|
||||
{
|
||||
//TODO
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -88,7 +88,7 @@ namespace keepass2android.Io
|
||||
File.Delete(BaseVersionFilePath(ioc));
|
||||
}
|
||||
|
||||
_cachedStorage.DeleteFile(ioc);
|
||||
_cachedStorage.Delete(ioc);
|
||||
}
|
||||
|
||||
private string CachedFilePath(IOConnectionInfo ioc)
|
||||
@ -105,6 +105,11 @@ namespace keepass2android.Io
|
||||
&& File.Exists(BaseVersionFilePath(ioc));
|
||||
}
|
||||
|
||||
public void Delete(IOConnectionInfo ioc)
|
||||
{
|
||||
_cachedStorage.Delete(ioc);
|
||||
}
|
||||
|
||||
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
|
||||
{
|
||||
//see comment in GetCurrentFileVersionFast
|
||||
@ -416,6 +421,16 @@ namespace keepass2android.Io
|
||||
return _cachedStorage.RequiresCredentials(ioc);
|
||||
}
|
||||
|
||||
public void CreateDirectory(IOConnectionInfo ioc)
|
||||
{
|
||||
_cachedStorage.CreateDirectory(ioc);
|
||||
}
|
||||
|
||||
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
|
||||
{
|
||||
return _cachedStorage.ListContents(ioc);
|
||||
}
|
||||
|
||||
|
||||
public string GetBaseVersionHash(IOConnectionInfo ioc)
|
||||
{
|
||||
|
@ -22,6 +22,9 @@ namespace keepass2android.Io
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<string> SupportedProtocols { get { yield return "dropbox"; } }
|
||||
protected override string Protocol
|
||||
{
|
||||
get { return "dropbox"; }
|
||||
}
|
||||
}
|
||||
}
|
14
src/Kp2aBusinessLogic/Io/FileDescription.cs
Normal file
14
src/Kp2aBusinessLogic/Io/FileDescription.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace keepass2android.Io
|
||||
{
|
||||
public class FileDescription
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public bool IsDirectory { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public bool CanRead { get; set; }
|
||||
public bool CanWrite { get; set; }
|
||||
public long SizeInBytes { get; set; }
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ namespace keepass2android.Io
|
||||
public class GDriveFileStorage: IFileStorage
|
||||
{
|
||||
public IEnumerable<string> SupportedProtocols { get { yield return "gdrive"; } }
|
||||
public void DeleteFile(IOConnectionInfo ioc)
|
||||
public void Delete(IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@ -63,5 +63,15 @@ namespace keepass2android.Io
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void CreateDirectory(IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<FileDescription> ListContents(IOConnectionInfo convertPathToIoc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -36,9 +36,9 @@ namespace keepass2android.Io
|
||||
IEnumerable<string> SupportedProtocols { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the given file.
|
||||
/// Deletes the given file or directory.
|
||||
/// </summary>
|
||||
void DeleteFile(IOConnectionInfo ioc);
|
||||
void Delete(IOConnectionInfo ioc);
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the file was changed.
|
||||
@ -54,7 +54,7 @@ namespace keepass2android.Io
|
||||
/// </summary>
|
||||
/// This string may have a deliberate value (except null) and should not be used by callers except for passing it to
|
||||
/// CheckForFileChangeFast().
|
||||
/// <returns>A string which should not be null.</returns>
|
||||
/// <returns>A string describing the version. Null means, there is no way to get a file version (or it's not implemented).</returns>
|
||||
string GetCurrentFileVersionFast(IOConnectionInfo ioc);
|
||||
|
||||
/// <summary>
|
||||
@ -96,6 +96,16 @@ namespace keepass2android.Io
|
||||
/// Returns true if the the given ioc must be filled with username/password
|
||||
/// </summary>
|
||||
bool RequiresCredentials(IOConnectionInfo ioc);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the directory described by ioc
|
||||
/// </summary>
|
||||
void CreateDirectory(IOConnectionInfo ioc);
|
||||
|
||||
/// <summary>
|
||||
/// Lists the contents of the given path
|
||||
/// </summary>
|
||||
IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Android.App;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
@ -12,7 +13,8 @@ namespace keepass2android.Io
|
||||
{
|
||||
public abstract class JavaFileStorage: IFileStorage
|
||||
{
|
||||
public abstract IEnumerable<string> SupportedProtocols { get; }
|
||||
public IEnumerable<string> SupportedProtocols { get { yield return Protocol; } }
|
||||
|
||||
|
||||
private readonly IJavaFileStorage _jfs;
|
||||
private readonly IKp2aApp _app;
|
||||
@ -23,9 +25,20 @@ namespace keepass2android.Io
|
||||
_app = app;
|
||||
}
|
||||
|
||||
public void DeleteFile(IOConnectionInfo ioc)
|
||||
public void Delete(IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
try
|
||||
{
|
||||
Jfs.Delete(IocToPath(ioc));
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new System.IO.FileNotFoundException(e.Message, e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
throw LogAndConvertJavaException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
|
||||
@ -196,14 +209,68 @@ namespace keepass2android.Io
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string IocToPath(IOConnectionInfo ioc)
|
||||
public void CreateDirectory(IOConnectionInfo ioc)
|
||||
{
|
||||
int protocolLength = ioc.Path.IndexOf("://", StringComparison.Ordinal);
|
||||
|
||||
if (protocolLength < 0)
|
||||
return ioc.Path;
|
||||
else
|
||||
return ioc.Path.Substring(protocolLength + 3);
|
||||
try
|
||||
{
|
||||
Jfs.CreateFolder(IocToPath(ioc));
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new System.IO.FileNotFoundException(e.Message, e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
throw LogAndConvertJavaException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
|
||||
{
|
||||
try
|
||||
{
|
||||
IList<JavaFileStorageFileEntry> entries = Jfs.ListFiles(IocToPath(ioc));
|
||||
|
||||
return entries.Select(
|
||||
e => new FileDescription
|
||||
{
|
||||
CanRead = e.CanRead,
|
||||
CanWrite = e.CanWrite,
|
||||
IsDirectory = e.IsDirectory,
|
||||
LastModified = JavaTimeToCSharp(e.LastModifiedTime),
|
||||
Path = Protocol + "://" + e.Path,
|
||||
SizeInBytes = e.SizeInBytes
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new System.IO.FileNotFoundException(e.Message, e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
throw LogAndConvertJavaException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime JavaTimeToCSharp(long javatime)
|
||||
{
|
||||
//todo test
|
||||
return new DateTime(1970, 1, 1).AddMilliseconds(javatime);
|
||||
|
||||
}
|
||||
|
||||
private string IocToPath(IOConnectionInfo ioc)
|
||||
{
|
||||
if (ioc.Path.StartsWith(Protocol + "://"))
|
||||
return ioc.Path.Substring(Protocol.Length + 3);
|
||||
else
|
||||
{
|
||||
return ioc.Path;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract string Protocol { get; }
|
||||
}
|
||||
}
|
@ -58,6 +58,7 @@
|
||||
<Compile Include="Io\BuiltInFileStorage.cs" />
|
||||
<Compile Include="Io\CachingFileStorage.cs" />
|
||||
<Compile Include="Io\DropboxFileStorage.cs" />
|
||||
<Compile Include="Io\FileDescription.cs" />
|
||||
<Compile Include="Io\GDriveFileStorage.cs" />
|
||||
<Compile Include="Io\IFileStorage.cs" />
|
||||
<Compile Include="Io\IoUtil.cs" />
|
||||
|
@ -18,11 +18,16 @@ namespace Kp2aUnitTests
|
||||
{
|
||||
if (Offline)
|
||||
throw new IOException("offline");
|
||||
_builtIn.DeleteFile(ioc);
|
||||
_builtIn.Delete(ioc);
|
||||
}
|
||||
|
||||
public IFileStorageSetup RequiredSetup { get { return null; } }
|
||||
|
||||
public void Delete(IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
|
||||
{
|
||||
if (Offline)
|
||||
@ -101,5 +106,15 @@ namespace Kp2aUnitTests
|
||||
{
|
||||
return _builtIn.RequiresCredentials(ioc);
|
||||
}
|
||||
|
||||
public void CreateDirectory(IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="8"
|
||||
android:targetSdkVersion="14" />
|
||||
|
@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
@ -31,7 +32,10 @@ import com.dropbox.client2.session.Session.AccessType;
|
||||
|
||||
|
||||
public class DropboxFileStorage implements JavaFileStorage {
|
||||
final static private String APP_KEY = "i8shu7v1hgh7ynt";
|
||||
|
||||
//NOTE: also adjust secret!
|
||||
final static private String APP_KEY = "i8shu7v1hgh7ynt"; //KP2A
|
||||
//final static private String APP_KEY = "4ybka4p4a1027n6"; //FileStorageTest
|
||||
|
||||
// If you'd like to change the access type to the full Dropbox instead of
|
||||
// an app folder, change this value.
|
||||
@ -43,8 +47,6 @@ public class DropboxFileStorage implements JavaFileStorage {
|
||||
final static private String ACCESS_KEY_NAME = "ACCESS_KEY";
|
||||
final static private String ACCESS_SECRET_NAME = "ACCESS_SECRET";
|
||||
|
||||
|
||||
|
||||
DropboxAPI<AndroidAuthSession> mApi;
|
||||
private boolean mLoggedIn = false;
|
||||
private Context mContext;
|
||||
@ -117,22 +119,6 @@ public class DropboxFileStorage implements JavaFileStorage {
|
||||
return mLoggedIn;
|
||||
}
|
||||
|
||||
public ArrayList<String> listContents(String path) throws Exception
|
||||
{
|
||||
ArrayList<String> files = new ArrayList<String>();
|
||||
try {
|
||||
DropboxAPI.Entry existingEntry = mApi.metadata(path, 0, null, true, null);
|
||||
for (DropboxAPI.Entry ent: existingEntry.contents)
|
||||
{
|
||||
files.add(ent.path);
|
||||
|
||||
}
|
||||
// do stuff with the Entry
|
||||
} catch (DropboxException e) {
|
||||
throw convertException(e);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception
|
||||
{
|
||||
@ -159,7 +145,6 @@ public class DropboxFileStorage implements JavaFileStorage {
|
||||
|
||||
public InputStream openFileForRead(String path) throws Exception
|
||||
{
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
try {
|
||||
return mApi.getFileStream(path, null);
|
||||
} catch (DropboxException e) {
|
||||
@ -187,6 +172,7 @@ public class DropboxFileStorage implements JavaFileStorage {
|
||||
{
|
||||
Log.d(TAG, "LoggedIn=false (due to unlink exception)");
|
||||
setLoggedIn(false);
|
||||
clearKeys();
|
||||
return new Exception("Unlinked from Dropbox!", e);
|
||||
|
||||
}
|
||||
@ -272,4 +258,61 @@ public class DropboxFileStorage implements JavaFileStorage {
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createFolder(String path) throws Exception {
|
||||
try
|
||||
{
|
||||
mApi.createFolder(path);
|
||||
}
|
||||
catch (DropboxException e) {
|
||||
throw convertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileEntry> listFiles(String dirName) throws Exception {
|
||||
try
|
||||
{
|
||||
com.dropbox.client2.DropboxAPI.Entry dirEntry = mApi.metadata(dirName, 0, null, true, null);
|
||||
|
||||
if (dirEntry.isDeleted)
|
||||
throw new FileNotFoundException("Directory "+dirName+" is deleted!");
|
||||
|
||||
List<FileEntry> result = new ArrayList<FileEntry>();
|
||||
|
||||
for (com.dropbox.client2.DropboxAPI.Entry e: dirEntry.contents)
|
||||
{
|
||||
if (e.isDeleted)
|
||||
continue;
|
||||
FileEntry fileEntry = new FileEntry();
|
||||
fileEntry.canRead = true;
|
||||
fileEntry.canWrite = true;
|
||||
fileEntry.isDirectory = e.isDir;
|
||||
fileEntry.sizeInBytes = e.bytes;
|
||||
fileEntry.path = e.path;
|
||||
fileEntry.lastModifiedTime = com.dropbox.client2.RESTUtility.parseDate(e.modified).getTime();
|
||||
result.add(fileEntry);
|
||||
}
|
||||
return result;
|
||||
|
||||
|
||||
} catch (DropboxException e) {
|
||||
|
||||
throw convertException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String path) throws Exception {
|
||||
try
|
||||
{
|
||||
mApi.delete(path);
|
||||
} catch (DropboxException e) {
|
||||
throw convertException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,17 +1,77 @@
|
||||
package keepass2android.javafilestorage;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
public interface JavaFileStorage {
|
||||
|
||||
|
||||
public class FileEntry {
|
||||
public String path;
|
||||
public boolean isDirectory;
|
||||
public long lastModifiedTime;
|
||||
public boolean canRead;
|
||||
public boolean canWrite;
|
||||
public long sizeInBytes;
|
||||
|
||||
public FileEntry()
|
||||
{
|
||||
isDirectory = false;
|
||||
canRead = canWrite = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (canRead ? 1231 : 1237);
|
||||
result = prime * result + (canWrite ? 1231 : 1237);
|
||||
result = prime * result + (isDirectory ? 1231 : 1237);
|
||||
result = prime * result
|
||||
+ (int) (lastModifiedTime ^ (lastModifiedTime >>> 32));
|
||||
result = prime * result + ((path == null) ? 0 : path.hashCode());
|
||||
result = prime * result + (int) (sizeInBytes ^ (sizeInBytes >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
FileEntry other = (FileEntry) obj;
|
||||
if (canRead != other.canRead)
|
||||
return false;
|
||||
if (canWrite != other.canWrite)
|
||||
return false;
|
||||
if (isDirectory != other.isDirectory)
|
||||
return false;
|
||||
if (lastModifiedTime != other.lastModifiedTime)
|
||||
return false;
|
||||
if (path == null) {
|
||||
if (other.path != null)
|
||||
return false;
|
||||
} else if (!path.equals(other.path))
|
||||
return false;
|
||||
if (sizeInBytes != other.sizeInBytes)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
@ -19,4 +79,11 @@ public interface JavaFileStorage {
|
||||
public InputStream openFileForRead(String path) throws Exception;
|
||||
|
||||
public void uploadFile(String path, byte[] data, boolean writeTransactional) throws Exception;
|
||||
|
||||
public void createFolder(String path) throws Exception;
|
||||
|
||||
public List<FileEntry> listFiles(String dirName) throws Exception;
|
||||
|
||||
public void delete(String path) throws Exception;
|
||||
|
||||
}
|
@ -28,7 +28,7 @@ public class MimeTypes {
|
||||
/**
|
||||
* Regular expression for files supported by Keepass2Android.
|
||||
*/
|
||||
public static final String REGEX_FILE_TYPE_KEEPASS2ANDROID = "(?si)^.+\\.(kdbx)$";
|
||||
public static final String REGEX_FILE_TYPE_KEEPASS2ANDROID = "(?si)^.+\\.(kdbx|kdbp)$";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -91,8 +91,8 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
getAuthority())
|
||||
.buildUpon()
|
||||
.appendPath(
|
||||
addProtocol(getParentPath(filename))
|
||||
.toString())
|
||||
getParentPath(filename)
|
||||
)
|
||||
.build(), null);
|
||||
count = 1; //success
|
||||
}
|
||||
@ -146,7 +146,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
.genContentIdUriBase(
|
||||
getAuthority())
|
||||
.buildUpon()
|
||||
.appendPath( addProtocol(newFullName)).build();
|
||||
.appendPath( newFullName).build();
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return newUri;
|
||||
}
|
||||
@ -235,9 +235,9 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
|
||||
{
|
||||
String path = Uri.parse(
|
||||
uri.getQueryParameter(BaseFile.PARAM_SOURCE)).getPath();
|
||||
uri.getQueryParameter(BaseFile.PARAM_SOURCE)).toString();
|
||||
|
||||
String parentPath = addProtocol(getParentPath(path));
|
||||
String parentPath = getParentPath(path);
|
||||
|
||||
|
||||
if (parentPath == null)
|
||||
@ -261,7 +261,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
newRow.add(BaseFile
|
||||
.genContentIdUriBase(
|
||||
getAuthority())
|
||||
.buildUpon().appendPath(addProtocol(parentPath))
|
||||
.buildUpon().appendPath(parentPath)
|
||||
.build().toString());
|
||||
newRow.add(parentPath);
|
||||
newRow.add(fname);
|
||||
@ -299,14 +299,14 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
return path;
|
||||
return path.substring(lastSlashPos+1);
|
||||
}
|
||||
|
||||
/*
|
||||
private String addProtocol(String path) {
|
||||
if (path == null)
|
||||
return null;
|
||||
if (path.startsWith(getProtocolId()+"://"))
|
||||
return path;
|
||||
return getProtocolId()+"://"+path;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Lists the content of a directory, if available.
|
||||
@ -366,7 +366,8 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
|
||||
FileEntry f = files.get(i);
|
||||
|
||||
Log.d(CLASSNAME, "listing " + f.path +" for "+dirName);
|
||||
if (Utils.doLog())
|
||||
Log.d(CLASSNAME, "listing " + f.path +" for "+dirName);
|
||||
|
||||
addFileInfo(matrixCursor, i, f);
|
||||
}// for files
|
||||
@ -390,14 +391,14 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
.genContentIdUriBase(
|
||||
getAuthority())
|
||||
.buildUpon()
|
||||
.appendPath(addProtocol(dirName))
|
||||
.appendPath(dirName)
|
||||
.appendQueryParameter(BaseFile.PARAM_HAS_MORE_FILES,
|
||||
Boolean.toString(hasMoreFiles[0])).build()
|
||||
.toString());
|
||||
newRow.add(addProtocol(dirName));
|
||||
newRow.add(dirName);
|
||||
newRow.add(getName(dirName));
|
||||
|
||||
Log.d(CLASSNAME, "Returning name " + getName(dirName)+" for " +addProtocol(dirName));
|
||||
Log.d(CLASSNAME, "Returning name " + getName(dirName)+" for " +dirName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,9 +428,9 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
newRow.add(BaseFile
|
||||
.genContentIdUriBase(
|
||||
getAuthority())
|
||||
.buildUpon().appendPath(addProtocol(f.path))
|
||||
.buildUpon().appendPath(f.path)
|
||||
.build().toString());
|
||||
newRow.add(addProtocol(f.path));
|
||||
newRow.add(f.path);
|
||||
newRow.add(getName(f.path));
|
||||
newRow.add(f.canRead ? 1 : 0);
|
||||
newRow.add(f.canWrite ? 1 : 0);
|
||||
@ -545,24 +546,32 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
* <i>non-null but empty</i> cursor if the source is.
|
||||
*/
|
||||
private MatrixCursor doCheckAncestor(Uri uri) {
|
||||
File source = new File(Uri.parse(
|
||||
uri.getQueryParameter(BaseFile.PARAM_SOURCE)).getPath());
|
||||
File target = new File(Uri.parse(
|
||||
uri.getQueryParameter(BaseFile.PARAM_TARGET)).getPath());
|
||||
String source = Uri.parse(
|
||||
uri.getQueryParameter(BaseFile.PARAM_SOURCE)).toString();
|
||||
String target = Uri.parse(
|
||||
uri.getQueryParameter(BaseFile.PARAM_TARGET)).toString();
|
||||
if (source == null || target == null)
|
||||
return null;
|
||||
|
||||
boolean validate = ProviderUtils.getBooleanQueryParam(uri,
|
||||
BaseFile.PARAM_VALIDATE, true);
|
||||
if (validate) {
|
||||
if (!source.isDirectory() || !target.exists())
|
||||
return null;
|
||||
//not supported
|
||||
}
|
||||
|
||||
if (source.equals(target.getParentFile())
|
||||
|| (target.getParent() != null && target.getParent()
|
||||
.startsWith(source.getAbsolutePath())))
|
||||
|
||||
if (!source.endsWith("/"))
|
||||
source += "/";
|
||||
|
||||
|
||||
String targetParent = getParentPath(target);
|
||||
if (targetParent != null && targetParent.startsWith(source))
|
||||
{
|
||||
if (Utils.doLog())
|
||||
Log.d(CLASSNAME, source+" is parent of "+target);
|
||||
return BaseFileProviderUtils.newClosedCursor();
|
||||
}
|
||||
if (Utils.doLog())
|
||||
Log.d(CLASSNAME, source+" is no parent of "+target);
|
||||
|
||||
return null;
|
||||
}// doCheckAncestor()
|
||||
@ -575,11 +584,10 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
* @return the filename.
|
||||
*/
|
||||
private static String extractFile(Uri uri) {
|
||||
String fileName = Uri.parse(uri.getLastPathSegment()).getPath();
|
||||
String fileName = Uri.parse(uri.getLastPathSegment()).toString();
|
||||
if (uri.getQueryParameter(BaseFile.PARAM_APPEND_PATH) != null)
|
||||
fileName += Uri.parse(
|
||||
uri.getQueryParameter(BaseFile.PARAM_APPEND_PATH))
|
||||
.getPath();
|
||||
uri.getQueryParameter(BaseFile.PARAM_APPEND_PATH)).toString();
|
||||
if (uri.getQueryParameter(BaseFile.PARAM_APPEND_NAME) != null)
|
||||
fileName += "/" + uri.getQueryParameter(BaseFile.PARAM_APPEND_NAME);
|
||||
|
||||
@ -600,33 +608,29 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
private String getParentPath(String path)
|
||||
{
|
||||
path = removeTrailingSlash(path);
|
||||
path = removeProtocol(path);
|
||||
if (path.indexOf("://") == -1)
|
||||
{
|
||||
Log.d(CLASSNAME, "invalid path: " + path);
|
||||
return null;
|
||||
}
|
||||
String pathWithoutProtocol = path.substring(path.indexOf("://")+3);
|
||||
int lastSlashPos = path.lastIndexOf("/");
|
||||
if (lastSlashPos == -1)
|
||||
if (pathWithoutProtocol.indexOf("/") == -1)
|
||||
{
|
||||
Log.d(CLASSNAME, "parent of " + path +" is null");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
return path.substring(0, lastSlashPos)+"/";
|
||||
{
|
||||
String parent = path.substring(0, lastSlashPos)+"/";
|
||||
Log.d(CLASSNAME, "parent of " + path +" is "+parent);
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
private String removeProtocol(String path) {
|
||||
if (path.lastIndexOf("://") == -1)
|
||||
return path;
|
||||
|
||||
if (!path.startsWith(getProtocolId()+"://"))
|
||||
{
|
||||
String msg = path+" does not start with "+getProtocolId();
|
||||
Log.d(CLASSNAME, msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
return path.substring(getProtocolId().length()+3);
|
||||
}
|
||||
|
||||
protected String getRootDirectory(String currentPath)
|
||||
{
|
||||
return getProtocolId() + ":///";
|
||||
}
|
||||
|
||||
protected FileEntry getFileEntry(String path) {
|
||||
|
||||
protected FileEntry getFileEntry(String path) {
|
||||
FileEntry f = new FileEntry();
|
||||
f.path = path;
|
||||
f.isDirectory = path.lastIndexOf(".") == -1;
|
||||
@ -667,6 +671,6 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
|
||||
protected abstract boolean deletePath(String filename, boolean isRecursive);
|
||||
protected abstract boolean createDirectory(String dirname, String newDirName);
|
||||
|
||||
protected abstract String getProtocolId();
|
||||
|
||||
|
||||
}
|
||||
|
@ -621,7 +621,7 @@ namespace keepass2android
|
||||
case (int)Result.Ok:
|
||||
if (requestCode == Intents.RequestCodeFileBrowseForBinary)
|
||||
{
|
||||
string filename = Util.IntentToFilename(data);
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
if (filename != null) {
|
||||
if (filename.StartsWith("file://")) {
|
||||
filename = filename.Substring(7);
|
||||
|
@ -176,7 +176,7 @@ namespace keepass2android
|
||||
break;
|
||||
case Result.Ok: // Key file browse dialog OK'ed.
|
||||
if (requestCode == Intents.RequestCodeFileBrowseForKeyfile) {
|
||||
string filename = Util.IntentToFilename(data);
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
if (filename != null) {
|
||||
if (filename.StartsWith("file://")) {
|
||||
filename = filename.Substring(7);
|
||||
|
@ -1,62 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="23"
|
||||
android:versionName="0.8.6"
|
||||
package="keepass2android.keepass2android"
|
||||
android:installLocation="auto">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="23" android:versionName="0.8.6" package="keepass2android.keepass2android" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" />
|
||||
<application android:label="keepass2android" android:icon="@drawable/ic_launcher">
|
||||
<activity
|
||||
android:name="com.dropbox.client2.android.AuthActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="orientation|keyboard">
|
||||
<activity android:name="com.dropbox.client2.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
|
||||
<intent-filter>
|
||||
<!-- Change this to be db- followed by your app key -->
|
||||
<data android:scheme="db-i8shu7v1hgh7ynt" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity" >
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:host="*" />
|
||||
<data android:pathPattern=".*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
</intent-filter>
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider" android:authorities="keepass2android.keepass2android.android-filechooser.localfile" android:exported="false" />
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android.android-filechooser.history" android:exported="false" />
|
||||
<activity android:name="group.pals.android.lib.ui.filechooser.FileChooserActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:screenOrientation="user" android:theme="@style/Afc.Theme.Light" />
|
||||
<activity android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@style/Base" android:name="keepass2android.PasswordActivity">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="file" />
|
||||
<data android:mimeType="*/*" />
|
||||
<data android:host="*" />
|
||||
<data android:pathPattern=".*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbp" />
|
||||
<data android:pathPattern=".*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdbx" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:name="keepass2android.softkeyboard.KP2AKeyboard"
|
||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
<intent-filter>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/method" />
|
||||
</service>
|
||||
|
||||
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
<intent-filter>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/method" />
|
||||
</service>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
5905
src/keepass2android/Resources/Resource.designer.cs
generated
5905
src/keepass2android/Resources/Resource.designer.cs
generated
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -27,6 +28,7 @@ using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Content.PM;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@ -159,8 +161,16 @@ namespace keepass2android
|
||||
}
|
||||
}
|
||||
|
||||
public static string IntentToFilename(Intent data)
|
||||
public static string IntentToFilename(Intent data, Context ctx)
|
||||
{
|
||||
string EXTRA_RESULTS = "group.pals.android.lib.ui.filechooser.FileChooserActivity.results";
|
||||
if (data.HasExtra(EXTRA_RESULTS))
|
||||
{
|
||||
IList uris = data.GetParcelableArrayListExtra(EXTRA_RESULTS);
|
||||
Uri uri = (Uri) uris[0];
|
||||
return Group.Pals.Android.Lib.UI.Filechooser.Providers.BaseFileProviderUtils.GetRealUri(ctx, uri).ToString();
|
||||
}
|
||||
|
||||
String filename = data.Data.Path;
|
||||
if (String.IsNullOrEmpty(filename))
|
||||
filename = data.DataString;
|
||||
|
104
src/keepass2android/fileselect/FileChooserFileProvider.cs
Normal file
104
src/keepass2android/fileselect/FileChooserFileProvider.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.Content;
|
||||
using KeePassLib.Serialization;
|
||||
using Keepass2android.Kp2afilechooser;
|
||||
using keepass2android.Io;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[ContentProvider(new[] { "keepass2android." + AppNames.PackagePart + ".kp2afilechooser.kp2afile" }, Exported = false)]
|
||||
public class FileChooserFileProvider : Kp2aFileProvider
|
||||
{
|
||||
/*int taskId, final String dirName,
|
||||
final boolean showHiddenFiles, final int filterMode,
|
||||
final int limit, String positiveRegex, String negativeRegex,
|
||||
final List<FileEntry> results, final boolean hasMoreFiles[]*/
|
||||
|
||||
public override string Authority
|
||||
{
|
||||
get { return TheAuthority; }
|
||||
}
|
||||
|
||||
public static string TheAuthority
|
||||
{
|
||||
get { return "keepass2android." + AppNames.PackagePart + ".kp2afilechooser.kp2afile"; }
|
||||
}
|
||||
|
||||
protected override bool CreateDirectory(string parentDirectory, string newDirName)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
parentDirectory = parentDirectory.TrimEnd('/');
|
||||
App.Kp2a.GetFileStorage(parentDirectory).CreateDirectory(ConvertPathToIoc(parentDirectory + "/" + newDirName));
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.Log(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private IOConnectionInfo ConvertPathToIoc(string path)
|
||||
{
|
||||
return new IOConnectionInfo() { Path = path };
|
||||
}
|
||||
|
||||
protected override bool DeletePath(string path, bool recursive)
|
||||
{
|
||||
try
|
||||
{
|
||||
App.Kp2a.GetFileStorage(path).Delete(ConvertPathToIoc(path));
|
||||
return true;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Kp2aLog.Log(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void ListFiles(int taskId, string dirName, bool showHiddenFiles, int filterMode, int limit, string positiveRegex,
|
||||
string negativeRegex, IList<FileEntry> fileList, bool[] hasMoreFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dirContents = App.Kp2a.GetFileStorage(dirName).ListContents(ConvertPathToIoc(dirName));
|
||||
foreach (FileDescription e in dirContents)
|
||||
{
|
||||
fileList.Add(new FileEntry
|
||||
{
|
||||
CanRead = e.CanRead,
|
||||
CanWrite = e.CanWrite,
|
||||
IsDirectory = e.IsDirectory,
|
||||
LastModifiedTime = CSharpTimeToJava(e.LastModified),
|
||||
Path = e.Path,
|
||||
SizeInBytes = e.SizeInBytes
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.Log(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private long CSharpTimeToJava(DateTime dateTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (long)dateTime.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -357,7 +357,7 @@ namespace keepass2android
|
||||
GroupActivity.Launch(_activity, _activity.AppTask);
|
||||
|
||||
} else {
|
||||
App.Kp2a.GetFileStorage(_ioc).DeleteFile(_ioc);
|
||||
App.Kp2a.GetFileStorage(_ioc).Delete(_ioc);
|
||||
|
||||
}
|
||||
}
|
||||
@ -481,17 +481,16 @@ namespace keepass2android
|
||||
|
||||
if (resultCode == KeePass.ExitFileStorageSelectionOk)
|
||||
{
|
||||
LaunchPasswordActivityForIoc(new IOConnectionInfo()
|
||||
{
|
||||
Path = data.GetStringExtra("protocolId")+":///keepass/keepass.kdbx"
|
||||
}
|
||||
);
|
||||
Intent i = Keepass2android.Kp2afilechooser.Kp2aFileChooserBridge.GetLaunchFileChooserIntent(this, FileChooserFileProvider.TheAuthority, data.GetStringExtra("protocolId")+":///");
|
||||
|
||||
StartActivityForResult(i, Intents.RequestCodeFileBrowseForOpen);
|
||||
|
||||
}
|
||||
|
||||
if ( (requestCode == Intents.RequestCodeFileBrowseForCreate
|
||||
|| requestCode == Intents.RequestCodeFileBrowseForOpen)
|
||||
&& resultCode == Result.Ok) {
|
||||
string filename = Util.IntentToFilename(data);
|
||||
string filename = Util.IntentToFilename(data, this);
|
||||
if (filename != null) {
|
||||
if (filename.StartsWith("file://")) {
|
||||
filename = filename.Substring(7);
|
||||
|
@ -78,6 +78,7 @@
|
||||
<Reference Include="Mono.Android.Support.v4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="fileselect\FileChooserFileProvider.cs" />
|
||||
<Compile Include="FileStorageSelectionActivity.cs" />
|
||||
<Compile Include="DonateReminder.cs" />
|
||||
<Compile Include="app\ApplicationBroadcastReceiver.cs" />
|
||||
@ -656,6 +657,14 @@
|
||||
<Folder Include="SupportLib\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AndroidFileChooserBinding\AndroidFileChooserBinding.csproj">
|
||||
<Project>{3c0f7fe5-639f-4422-a087-8b26cf862d1b}</Project>
|
||||
<Name>AndroidFileChooserBinding</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\AppCompatV7Binding\AppCompatV7Binding.csproj">
|
||||
<Project>{23233a28-d74f-4bf8-b4d8-834060840bd7}</Project>
|
||||
<Name>AppCompatV7Binding</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
|
||||
<Project>{48574278-4779-4b3a-a9e4-9cf1bc285d0b}</Project>
|
||||
<Name>JavaFileStorageBindings</Name>
|
||||
|
@ -22,7 +22,6 @@ using Android.OS;
|
||||
using Android.Widget;
|
||||
using keepass2android.view;
|
||||
using KeePassLib;
|
||||
using Android.Support.V4.App;
|
||||
|
||||
namespace keepass2android.search
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user