BIN
graphics/launcher_icon/Logo-green-96.png
Normal file
BIN
graphics/launcher_icon/Logo-green-96.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
64
src/AdalBindings/AdalBindings.csproj
Normal file
64
src/AdalBindings/AdalBindings.csproj
Normal file
@@ -0,0 +1,64 @@
|
||||
<?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>{0B109C0E-0514-4340-8779-5BD6A0DDE84E}</ProjectGuid>
|
||||
<ProjectTypeGuids>{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AdalBindings</RootNamespace>
|
||||
<AssemblyName>AdalBindings</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
|
||||
<TargetFrameworkVersion>v8.1</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="Jars\adal-1.14.0.aar" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<TransformFile Include="Transforms\Metadata.xml" />
|
||||
<TransformFile Include="Transforms\EnumFields.xml" />
|
||||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedReferenceJar Include="Jars\gson-2.3.1.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>
|
||||
48
src/AdalBindings/Additions/AboutAdditions.txt
Normal file
48
src/AdalBindings/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; }
|
||||
}
|
||||
24
src/AdalBindings/Jars/AboutJars.txt
Normal file
24
src/AdalBindings/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/AdalBindings/Jars/gson-2.3.1.jar
Normal file
BIN
src/AdalBindings/Jars/gson-2.3.1.jar
Normal file
Binary file not shown.
30
src/AdalBindings/Properties/AssemblyInfo.cs
Normal file
30
src/AdalBindings/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
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("AdalBindings")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AdalBindings")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[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")]
|
||||
14
src/AdalBindings/Transforms/EnumFields.xml
Normal file
14
src/AdalBindings/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/AdalBindings/Transforms/EnumMethods.xml
Normal file
13
src/AdalBindings/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>
|
||||
13
src/AdalBindings/Transforms/Metadata.xml
Normal file
13
src/AdalBindings/Transforms/Metadata.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<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']" />
|
||||
-->
|
||||
<remove-node path="/api/package[@name='com.microsoft.aad.adal']/class[@name='AuthenticationActivity']" />
|
||||
<remove-node path="/api/package[@name='com.microsoft.aad.adal']/class[@name='DateTimeAdapter']" />
|
||||
<remove-node path="/api/package[@name='com.microsoft.aad.adal']" />
|
||||
|
||||
</metadata>
|
||||
@@ -60,7 +60,6 @@
|
||||
</LibraryProjectZip>
|
||||
<None Include="Jars\AboutJars.txt" />
|
||||
<None Include="Additions\AboutAdditions.txt" />
|
||||
<LibraryProjectZip Include="Jars\adal-1.14.0.aar" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<TransformFile Include="Transforms\Metadata.xml" />
|
||||
@@ -82,6 +81,10 @@
|
||||
</XamarinComponentReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AdalBindings\AdalBindings.csproj">
|
||||
<Project>{0b109c0e-0514-4340-8779-5bd6a0dde84e}</Project>
|
||||
<Name>AdalBindings</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\PCloudBindings\PCloudBindings.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -153,4 +156,4 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedReferenceJar Include="Jars\okio-1.13.0.jar" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -11,6 +11,8 @@
|
||||
<remove-node path="/api/package[@name='com.jcraft.jsch.jcraft']" />
|
||||
<remove-node path="/api/package[@name='com.jcraft.jzlib']" />
|
||||
|
||||
<remove-node path="/api/package[@name='com.pcloud.sdk']" />
|
||||
|
||||
<remove-node path="/api/package[@name='com.dropbox.core']" />
|
||||
<remove-node path="/api/package[@name='com.dropbox.core.util']" />
|
||||
<remove-node path="/api/package[@name='com.dropbox.core.http']" />
|
||||
|
||||
@@ -29,6 +29,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCloudBindings", "PCloudBindings\PCloudBindings.csproj", "{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdalBindings", "AdalBindings\AdalBindings.csproj", "{0B109C0E-0514-4340-8779-5BD6A0DDE84E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -158,19 +160,25 @@ Global
|
||||
{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|Win32.Build.0 = Debug|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|x64.Build.0 = 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|Win32.Build.0 = 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}.Release|x64.Build.0 = Release|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.Build.0 = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.Build.0 = ReleaseNoNet|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
|
||||
@@ -285,16 +293,54 @@ Global
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.Build.0 = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.Build.0 = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Win32.Build.0 = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
||||
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|x64.Build.0 = ReleaseNoNet|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|Win32.Build.0 = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||
{0B109C0E-0514-4340-8779-5BD6A0DDE84E}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -5,8 +5,8 @@ namespace keepass2android.Io
|
||||
{
|
||||
public class SftpFileStorage: JavaFileStorage
|
||||
{
|
||||
public SftpFileStorage(IKp2aApp app) :
|
||||
base(new Keepass2android.Javafilestorage.SftpStorage(), app)
|
||||
public SftpFileStorage(Context ctx, IKp2aApp app) :
|
||||
base(new Keepass2android.Javafilestorage.SftpStorage(ctx.ApplicationContext), app)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -156,6 +156,10 @@
|
||||
<Compile Include="Utils\Spr\SprEngine.PickChars.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AdalBindings\AdalBindings.csproj">
|
||||
<Project>{0b109c0e-0514-4340-8779-5bd6a0dde84e}</Project>
|
||||
<Name>AdalBindings</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
|
||||
<Project>{48574278-4779-4b3a-a9e4-9cf1bc285d0b}</Project>
|
||||
<Name>JavaFileStorageBindings</Name>
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||
<TransformFile Include="Transforms\Metadata.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
||||
<ItemGroup>
|
||||
<Folder Include="libs\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -4,8 +4,13 @@
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}</ProjectGuid>
|
||||
<ProjectTypeGuids>{6322E8A7-5C46-4E8C-8B19-448B7BC95DC1};{E1126D83-ADAB-4E4F-81F7-4B0A645A68C7}</ProjectTypeGuids>
|
||||
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
|
||||
|
||||
|
||||
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PCloudBindings</RootNamespace>
|
||||
<AssemblyName>PCouldBindings</AssemblyName>
|
||||
@@ -21,6 +26,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>0</WarningLevel>
|
||||
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
@@ -31,6 +37,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseNoNet|AnyCPU'">
|
||||
<OutputPath>bin\ReleaseNoNet\</OutputPath>
|
||||
@@ -46,12 +53,18 @@
|
||||
<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="Jars\pcloud-sdk-android-1.0.1.aar" />
|
||||
@@ -60,6 +73,7 @@
|
||||
<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.
|
||||
@@ -72,4 +86,5 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedReferenceJar Include="Jars\pcloud-sdk-java-core-1.0.1.jar" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
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']" />
|
||||
-->
|
||||
<remove-node path="/api/package[@name='com.pcloud.sdk']" />
|
||||
</metadata>
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\app-debug.aar">
|
||||
<Link>Jars\app-debug.aar</Link>
|
||||
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\app-release.aar">
|
||||
<Link>Jars\app-release.aar</Link>
|
||||
</LibraryProjectZip>
|
||||
<None Include="Jars\AboutJars.txt" />
|
||||
<None Include="Additions\AboutAdditions.txt" />
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="keepass2android.javafilestorage"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="8"
|
||||
android:targetSdkVersion="14" />
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
|
||||
</manifest>
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name=".NotifSlave"
|
||||
android:label="Keepass2Android"></activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,169 @@
|
||||
package keepass2android.javafilestorage;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
//based on https://github.com/jwise/dumload/blob/master/src/com/joshuawise/dumload/NotifSlave.java
|
||||
public class NotifSlave extends Activity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
private void say(String s) {
|
||||
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private int _nextdialog = 0;
|
||||
private Dialog dialog = null;
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id)
|
||||
{
|
||||
Log.e("KP2AJ.NotifSlave", "Create for dialog "+(Integer.toString(id)));
|
||||
if (id != _nextdialog)
|
||||
return null;
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private void showDialog(Dialog d)
|
||||
{
|
||||
_nextdialog++;
|
||||
dialog = d;
|
||||
Log.e("KP2AJ.NotifSlave", "Attempting to show dialog "+(Integer.toString(_nextdialog)));
|
||||
showDialog(_nextdialog);
|
||||
}
|
||||
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
Intent i = getIntent(); /* i *am* not an intent! */
|
||||
final Activity thisact = this;
|
||||
|
||||
final Messenger m = (Messenger)i.getParcelableExtra("keepass2android.sftp.returnmessenger");
|
||||
String reqtype = i.getStringExtra("keepass2android.sftp.reqtype");
|
||||
String prompt = i.getStringExtra("keepass2android.sftp.prompt");
|
||||
|
||||
if (prompt == null || reqtype == null || m == null) /* i.e., we got called by a dummy notification */
|
||||
{
|
||||
this.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reqtype.equals("yesno")) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle("Keepass2Android");
|
||||
builder.setMessage(prompt);
|
||||
builder.setCancelable(false);
|
||||
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
Log.e("KP2AJ.NotifSlave", "Responding with a 1.");
|
||||
try {
|
||||
Message me = Message.obtain();
|
||||
me.arg1 = 1;
|
||||
m.send(me);
|
||||
} catch (Exception e) {
|
||||
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
|
||||
}
|
||||
dialog.cancel();
|
||||
thisact.finish();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
Log.e("KP2AJ.NotifSlave", "Responding with a 1.");
|
||||
try {
|
||||
Message me = Message.obtain();
|
||||
me.arg1 = 0;
|
||||
m.send(me);
|
||||
} catch (Exception e) {
|
||||
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
|
||||
}
|
||||
dialog.cancel();
|
||||
thisact.finish();
|
||||
}
|
||||
});
|
||||
AlertDialog alert = builder.create();
|
||||
showDialog(alert);
|
||||
} else if (reqtype.equals("message")) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle("Keepass2Android");
|
||||
builder.setMessage(prompt);
|
||||
builder.setCancelable(false);
|
||||
builder.setNeutralButton("OK", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
try {
|
||||
Message me = Message.obtain();
|
||||
m.send(me);
|
||||
} catch (Exception e) {
|
||||
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
|
||||
}
|
||||
dialog.cancel();
|
||||
thisact.finish();
|
||||
}
|
||||
});
|
||||
AlertDialog alert = builder.create();
|
||||
showDialog(alert);
|
||||
} /*else if (reqtype.equals("password")) {
|
||||
final Dialog d = new Dialog(this);
|
||||
|
||||
d.setContentView(R.layout.notfif_slave);
|
||||
d.setTitle("Keepass2Android");
|
||||
d.setCancelable(false);
|
||||
|
||||
TextView text = (TextView) d.findViewById(R.id.prompt);
|
||||
text.setText(prompt);
|
||||
|
||||
Button ok = (Button) d.findViewById(R.id.ok);
|
||||
ok.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
Message me = Message.obtain();
|
||||
me.arg1 = 1;
|
||||
TextView entry = (TextView) d.findViewById(R.id.entry);
|
||||
Bundle b = new Bundle(1);
|
||||
b.putString("response", entry.getText().toString());
|
||||
me.setData(b);
|
||||
m.send(me);
|
||||
} catch (Exception e) {
|
||||
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
|
||||
}
|
||||
d.cancel();
|
||||
thisact.finish();
|
||||
}
|
||||
});
|
||||
|
||||
Button cancel = (Button) d.findViewById(R.id.cancel);
|
||||
cancel.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
Message me = Message.obtain();
|
||||
me.arg1 = 0;
|
||||
m.send(me);
|
||||
} catch (Exception e) {
|
||||
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
|
||||
}
|
||||
d.cancel();
|
||||
thisact.finish();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
showDialog(d);
|
||||
} */else {
|
||||
Log.e("KP2AJ.NotifSlave", "What's a "+reqtype+"?");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@ package keepass2android.javafilestorage;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
@@ -13,6 +15,7 @@ import com.jcraft.jsch.ChannelSftp;
|
||||
import com.jcraft.jsch.ChannelSftp.LsEntry;
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.KeyPair;
|
||||
import com.jcraft.jsch.Session;
|
||||
import com.jcraft.jsch.SftpATTRS;
|
||||
import com.jcraft.jsch.SftpException;
|
||||
@@ -21,6 +24,7 @@ import com.jcraft.jsch.UserInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
public class SftpStorage extends JavaFileStorageBase {
|
||||
|
||||
@@ -35,8 +39,10 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
public String localPath;
|
||||
public int port;
|
||||
}
|
||||
Context _appContext;
|
||||
|
||||
public SftpStorage() {
|
||||
public SftpStorage(Context appContext) {
|
||||
_appContext = appContext;
|
||||
|
||||
}
|
||||
|
||||
@@ -318,12 +324,28 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
jsch = new JSch();
|
||||
ConnectionInfo ci = splitStringToConnectionInfo(filename);
|
||||
|
||||
String base_dir = getBaseDir();
|
||||
jsch.setKnownHosts(base_dir + "/known_hosts");
|
||||
|
||||
String key_filename = getKeyFileName();
|
||||
try{
|
||||
createKeyPair(key_filename);
|
||||
} catch (Exception ex) {
|
||||
System.out.println(ex);
|
||||
}
|
||||
|
||||
try {
|
||||
jsch.addIdentity(key_filename);
|
||||
} catch (java.lang.Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Session session = jsch.getSession(ci.username, ci.host, ci.port);
|
||||
UserInfo ui = new SftpUserInfo(ci.password);
|
||||
UserInfo ui = new SftpUserInfo(ci.password,_appContext);
|
||||
session.setUserInfo(ui);
|
||||
|
||||
session.setConfig("PreferredAuthentications",
|
||||
"password,publickey");
|
||||
session.setConfig("PreferredAuthentications", "publickey,password");
|
||||
|
||||
session.connect();
|
||||
|
||||
@@ -336,6 +358,37 @@ public class SftpStorage extends JavaFileStorageBase {
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getBaseDir() {
|
||||
return _appContext.getFilesDir().getAbsolutePath();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getKeyFileName() {
|
||||
return getBaseDir() + "/id_kp2a_rsa";
|
||||
}
|
||||
|
||||
public String createKeyPair() throws IOException, JSchException {
|
||||
return createKeyPair(getKeyFileName());
|
||||
|
||||
}
|
||||
|
||||
private String createKeyPair(String key_filename) throws JSchException, IOException {
|
||||
String public_key_filename = key_filename + ".pub";
|
||||
File file = new File(key_filename);
|
||||
if (file.exists())
|
||||
return public_key_filename;
|
||||
int type = KeyPair.RSA;
|
||||
KeyPair kpair = KeyPair.genKeyPair(jsch, type, 2048);
|
||||
kpair.writePrivateKey(key_filename);
|
||||
|
||||
kpair.writePublicKey(public_key_filename, "generated by Keepass2Android");
|
||||
//ret = "Fingerprint: " + kpair.getFingerPrint();
|
||||
kpair.dispose();
|
||||
return public_key_filename;
|
||||
|
||||
}
|
||||
|
||||
public ConnectionInfo splitStringToConnectionInfo(String filename)
|
||||
throws UnsupportedEncodingException {
|
||||
ConnectionInfo ci = new ConnectionInfo();
|
||||
|
||||
@@ -1,14 +1,119 @@
|
||||
package keepass2android.javafilestorage;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jcraft.jsch.UserInfo;
|
||||
|
||||
public class SftpUserInfo implements UserInfo {
|
||||
|
||||
private Object /* pick one type, and fixate on it */ dance(final String type, final String text) /* for inside the thread */
|
||||
{
|
||||
|
||||
final Message msg = Message.obtain();
|
||||
|
||||
/* t(*A*t) */
|
||||
Thread t = new Thread() {
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
int bogon = (int)SystemClock.elapsedRealtime();
|
||||
|
||||
NotificationManager mNotificationManager = (NotificationManager)_appContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(_appContext);
|
||||
builder.setContentText("SFTP prompt");
|
||||
builder.setSmallIcon(R.drawable.ic_logo_green_foreground);
|
||||
|
||||
|
||||
Handler h = new Handler() {
|
||||
public void handleMessage(Message M) {
|
||||
msg.copyFrom(M);
|
||||
Looper.myLooper().quit();
|
||||
}
|
||||
};
|
||||
Messenger m = new Messenger(h);
|
||||
|
||||
Intent intent = new Intent(_appContext, NotifSlave.class);
|
||||
|
||||
intent.setAction("keepass2android.sftp.NotifSlave");
|
||||
intent.putExtra("keepass2android.sftp.returnmessenger", m);
|
||||
intent.putExtra("keepass2android.sftp.reqtype", type);
|
||||
intent.putExtra("keepass2android.sftp.prompt", text);
|
||||
intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
|
||||
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(_appContext, 0, intent, 0);
|
||||
builder.setContentIntent(contentIntent);
|
||||
|
||||
{
|
||||
Intent directIntent = new Intent(_appContext, NotifSlave.class);
|
||||
directIntent.setAction("keepass2android.sftp.NotifSlave");
|
||||
directIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
directIntent.putExtra("keepass2android.sftp.returnmessenger", m);
|
||||
directIntent.putExtra("keepass2android.sftp.reqtype", type);
|
||||
directIntent.putExtra("keepass2android.sftp.prompt", text);
|
||||
directIntent.setData((Uri.parse("suckit://" + SystemClock.elapsedRealtime())));
|
||||
_appContext.startActivity(directIntent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Log.e("KP2AJFS[thread]", "Notifying...");
|
||||
|
||||
mNotificationManager.notify(bogon, builder.build());
|
||||
|
||||
|
||||
|
||||
Log.e("KP2AJFS[thread]", "About to go to 'sleep'...");
|
||||
Looper.loop();
|
||||
Log.e("KP2AJFS[thread]", "And we're alive!");
|
||||
|
||||
Log.e("KP2AJFS[thread]", "result was: "+(Integer.toString(msg.arg1)));
|
||||
|
||||
mNotificationManager.cancel(bogon);
|
||||
}
|
||||
};
|
||||
|
||||
t.start();
|
||||
try {
|
||||
t.join();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type.equals("yesno"))
|
||||
return new Boolean(msg.arg1 == 1);
|
||||
else if (type.equals("message"))
|
||||
return null;
|
||||
else if (type.equals("password")) {
|
||||
if (msg.arg1 == 0)
|
||||
return null;
|
||||
Bundle b = msg.getData();
|
||||
return b.getString("response");
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Context _appContext;
|
||||
|
||||
String _password;
|
||||
|
||||
public SftpUserInfo(String password) {
|
||||
public SftpUserInfo(String password, Context appContext)
|
||||
{
|
||||
_password = password;
|
||||
_appContext = appContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,12 +140,15 @@ public class SftpUserInfo implements UserInfo {
|
||||
|
||||
@Override
|
||||
public boolean promptYesNo(String message) {
|
||||
return true; //continue all operations without user action
|
||||
return (Boolean)dance("yesno", message);
|
||||
|
||||
//test with https://www.sftp.net/public-online-sftp-servers?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(String message) {
|
||||
Log.d("KP2AJ", message);
|
||||
public void showMessage(String message)
|
||||
{
|
||||
dance("message", message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<vector android:height="24dp" android:viewportHeight="800.0"
|
||||
android:viewportWidth="800.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#ffffff" android:fillType="evenOdd" android:pathData="m318.7,232c13.6,0 24.6,10.9 24.6,24.4 0,13.5 -11,24.4 -24.6,24.4 -13.6,0 -24.6,-10.9 -24.6,-24.4 0,-13.5 11,-24.4 24.6,-24.4zM453.5,256.4c0,13.5 11,24.4 24.6,24.4 13.6,0 24.6,-10.9 24.6,-24.4 0,-13.5 -11,-24.4 -24.6,-24.4 -13.6,0 -24.6,10.9 -24.6,24.4zM399.8,177.7M140.2,600.6v47h517.3v-47zM140.2,350.9v47h517.3v-47zM140.1,481.2h191.8c-0.8,-4.1 -1.2,-8.3 -1.2,-12.4 0,-12.4 3.4,-24.2 9.9,-34.6L140.1,434.2ZM657.5,481.2v-47L454.9,434.2c6.5,10.4 9.8,22.2 9.8,34.6 0,4.1 -0.4,8.3 -1.2,12.4zM140.1,517.4v47h186.6l14.3,-47zM454.3,517.4 L468.7,564.4h188.8v-47zM432.7,565.8 L411.7,496.9 414.4,495.3c10.3,-5.9 16.7,-16.9 16.7,-28.6 0,-18.2 -15,-33 -33.3,-33 -18.3,0 -33.3,14.8 -33.3,33 0,11.8 6.4,22.7 16.7,28.6l2.7,1.6 -21.1,68.9zM507.5,158.5 L507.7,158.2 543.3,106.9c2.4,-3.5 1.8,-8.1 -1.4,-10.3 -3.2,-2.2 -7.7,-1.1 -10.2,2.4l-37.2,53.5 -0.1,0.3c-29.3,-11.8 -62.1,-18.5 -96.8,-18.5 -35.2,0 -68.5,6.9 -98.1,19L261.8,99c-2.4,-3.5 -7,-4.6 -10.2,-2.4 -3.2,2.2 -3.8,6.8 -1.4,10.3l36.2,52.2c-66.8,32.2 -111.9,92.4 -111.9,161.3h42.9c0,-79.1 80.8,-143.5 180.1,-143.5 99.3,0 180.1,64.3 180.1,143.5h42.9c0.2,-69.3 -45.4,-129.8 -113,-161.9z"/>
|
||||
</vector>
|
||||
@@ -135,7 +135,12 @@ package com.crocoapps.javafilestoragetest;
|
||||
import group.pals.android.lib.ui.filechooser.FileChooserActivity;
|
||||
import group.pals.android.lib.ui.filechooser.providers.BaseFileProviderUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -526,9 +531,9 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
|
||||
}
|
||||
|
||||
static JavaFileStorage createStorageToTest(Context ctx, Context appContext, boolean simulateRestart) {
|
||||
//storageToTest = new SftpStorage();
|
||||
storageToTest = new SftpStorage(ctx.getApplicationContext());
|
||||
//storageToTest = new SkyDriveFileStorage("000000004010C234", appContext);
|
||||
storageToTest = new OneDriveStorage(appContext, "000000004010C234");
|
||||
//storageToTest = new OneDriveStorage(appContext, "000000004010C234");
|
||||
//storageToTest = new GoogleDriveFileStorage();
|
||||
/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
|
||||
@Override
|
||||
@@ -662,6 +667,20 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
|
||||
return this;
|
||||
}
|
||||
|
||||
public static String readStream(InputStream is) {
|
||||
StringBuilder sb = new StringBuilder(512);
|
||||
try {
|
||||
Reader r = new InputStreamReader(is, "UTF-8");
|
||||
int c = 0;
|
||||
while ((c = r.read()) != -1) {
|
||||
sb.append((char) c);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performManualFileSelect(boolean isForSave, final int requestCode,
|
||||
String protocolId)
|
||||
@@ -669,6 +688,30 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
|
||||
if (protocolId.equals("sftp"))
|
||||
{
|
||||
final View view = getLayoutInflater().inflate(R.layout.sftp_credentials, null);
|
||||
|
||||
view.findViewById(R.id.send_public_key).setOnClickListener(v -> {
|
||||
Intent sendIntent = new Intent();
|
||||
|
||||
|
||||
SftpStorage sftpStorage = (SftpStorage)storageToTest;
|
||||
try {
|
||||
String pub_filename = sftpStorage.createKeyPair();
|
||||
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, readStream(new FileInputStream(pub_filename)));
|
||||
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Keepass2Android sftp public key");
|
||||
sendIntent.setType("text/plain");
|
||||
this.startActivity(Intent.createChooser(sendIntent, "Send public key to..."));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Toast.makeText(this,"Failed to create key pair: " + ex.getMessage(), Toast.LENGTH_LONG);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
new AlertDialog.Builder(this)
|
||||
.setView(view)
|
||||
.setTitle("Enter SFTP credentials")
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
android:singleLine="true"
|
||||
android:text="/home/philipp"
|
||||
/>
|
||||
|
||||
<Button android:id="@+id/send_public_key"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="send public key" />
|
||||
|
||||
</LinearLayout>
|
||||
2
src/java/KP2ASoftkeyboard_AS/.idea/misc.xml
generated
2
src/java/KP2ASoftkeyboard_AS/.idea/misc.xml
generated
@@ -24,7 +24,7 @@
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
@@ -521,6 +521,7 @@ public class KP2AKeyboard extends InputMethodService
|
||||
mOrientation = conf.orientation;
|
||||
reloadKeyboards();
|
||||
}
|
||||
updateKp2aKeyLabels();
|
||||
mConfigurationChanging = true;
|
||||
super.onConfigurationChanged(conf);
|
||||
mConfigurationChanging = false;
|
||||
@@ -545,6 +546,7 @@ public class KP2AKeyboard extends InputMethodService
|
||||
mKeyboardSwitcher.setKeyboardMode(
|
||||
KeyboardSwitcher.MODE_TEXT, 0);
|
||||
}
|
||||
updateKp2aKeyLabels();
|
||||
|
||||
return mKeyboardSwitcher.getInputView();
|
||||
}
|
||||
@@ -706,6 +708,7 @@ public class KP2AKeyboard extends InputMethodService
|
||||
attribute.imeOptions);
|
||||
}
|
||||
}
|
||||
updateKp2aKeyLabels();
|
||||
}
|
||||
|
||||
private void updateShowKp2aMode() {
|
||||
@@ -1365,7 +1368,8 @@ public class KP2AKeyboard extends InputMethodService
|
||||
}
|
||||
|
||||
private void onKp2aPasswordKeyPressed() {
|
||||
commitStringForTyping(KeyboardData.availableFields.get(KeyboardData.kp2aFieldIndex+1));
|
||||
if (KeyboardData.availableFields.size() > KeyboardData.kp2aFieldIndex+1) //some entries may have only title, then there are no two buttons available
|
||||
commitStringForTyping(KeyboardData.availableFields.get(KeyboardData.kp2aFieldIndex+1));
|
||||
}
|
||||
|
||||
|
||||
@@ -1394,38 +1398,61 @@ public class KP2AKeyboard extends InputMethodService
|
||||
updateKp2aKeyLabels();
|
||||
}
|
||||
|
||||
String makeShort(String input, int lineLength)
|
||||
{
|
||||
String result = input;
|
||||
if (input.length() > lineLength)
|
||||
{
|
||||
result = input.substring(0,lineLength-1)+"…";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void updateKp2aKeyLabels() {
|
||||
for (Keyboard.Key key : mKeyboardSwitcher.getInputView().getKeyboard().getKeys()) {
|
||||
|
||||
boolean isFirstKey = false;
|
||||
boolean isSecondKey = false;
|
||||
for (int code : key.codes) {
|
||||
if (code == -201)
|
||||
isFirstKey = true;
|
||||
if (code == -202)
|
||||
isSecondKey = true;
|
||||
}
|
||||
if ((mKeyboardSwitcher.getInputView() != null)
|
||||
&& (mKeyboardSwitcher.getInputView().getKeyboard() != null))
|
||||
{
|
||||
for (Keyboard.Key key : mKeyboardSwitcher.getInputView().getKeyboard().getKeys()) {
|
||||
|
||||
boolean isFirstKey = false;
|
||||
boolean isSecondKey = false;
|
||||
for (int code : key.codes) {
|
||||
if (code == -201)
|
||||
isFirstKey = true;
|
||||
if (code == -202)
|
||||
isSecondKey = true;
|
||||
}
|
||||
|
||||
|
||||
int fieldIndex = -1;
|
||||
if (isFirstKey) {
|
||||
fieldIndex = KeyboardData.kp2aFieldIndex;
|
||||
}
|
||||
if (isSecondKey)
|
||||
{
|
||||
fieldIndex = KeyboardData.kp2aFieldIndex+1;
|
||||
}
|
||||
if (fieldIndex >= 0)
|
||||
{
|
||||
String displayName = KeyboardData.availableFields.get(fieldIndex).displayName;
|
||||
if ("Password".equals(KeyboardData.availableFields.get(fieldIndex).key))
|
||||
displayName = getString(R.string.kp2a_password); //might be a shorter variant
|
||||
if ("UserName".equals(KeyboardData.availableFields.get(fieldIndex).key ))
|
||||
displayName = getString(R.string.kp2a_user); //might be a shorter variant
|
||||
key.label = displayName;
|
||||
int fieldIndex = -1;
|
||||
if (isFirstKey) {
|
||||
fieldIndex = KeyboardData.kp2aFieldIndex;
|
||||
}
|
||||
if (isSecondKey) {
|
||||
fieldIndex = KeyboardData.kp2aFieldIndex + 1;
|
||||
}
|
||||
|
||||
if (fieldIndex >= 0) {
|
||||
key.label = "";
|
||||
if (fieldIndex < KeyboardData.availableFields.size()) {
|
||||
String displayName = "";
|
||||
StringForTyping fieldData = KeyboardData.availableFields.get(fieldIndex);
|
||||
if (fieldData != null) {
|
||||
displayName = makeShort(fieldData.displayName, 10);
|
||||
|
||||
if ("Password".equals(fieldData.key))
|
||||
displayName = getString(R.string.kp2a_password); //might be a shorter variant
|
||||
if ("UserName".equals(fieldData.key))
|
||||
displayName = getString(R.string.kp2a_user); //might be a shorter variant
|
||||
}
|
||||
key.label = displayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
mKeyboardSwitcher.getInputView().invalidateAllKeys();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onKp2aKeyPressed() {
|
||||
@@ -1455,14 +1482,135 @@ public class KP2AKeyboard extends InputMethodService
|
||||
}
|
||||
}
|
||||
|
||||
private void showKp2aDialog() {
|
||||
final EditorInfo attribute = getCurrentInputEditorInfo();
|
||||
final String clientPackageName = attribute.packageName;
|
||||
private void showKp2aDialog()
|
||||
{
|
||||
boolean androidP = android.os.Build.VERSION.SDK_INT >= 28;
|
||||
//due to a change in Android P, showing the dialog as dialog does not work (only visible
|
||||
// above the keyboard, not above the target application). Use an activity here.
|
||||
// However, this is not perfect as it has another behavior regarding which task is
|
||||
// in foreground, e.g. Chrome closes the IME when the activity is brought up which causes
|
||||
// trouble entering data. So we still use the dialog in previous android versions.
|
||||
if (androidP)
|
||||
{
|
||||
final EditorInfo attribute = getCurrentInputEditorInfo();
|
||||
final String clientPackageName = attribute.packageName;
|
||||
|
||||
Intent i = new Intent(this, Kp2aDialog.class);
|
||||
i.putExtra("clientPackageName", clientPackageName);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
String title = "Keepass2Android";
|
||||
List<StringForTyping> availableFields = keepass2android.kbbridge.KeyboardData.availableFields;
|
||||
|
||||
final EditorInfo attribute = getCurrentInputEditorInfo();
|
||||
attribute.dump(new Printer() {
|
||||
|
||||
@Override
|
||||
public void println(String x) {
|
||||
Log.d("KP2AK", x);
|
||||
|
||||
}
|
||||
}, "");
|
||||
final ArrayList<StringForTyping> items = new ArrayList<StringForTyping>();
|
||||
for (StringForTyping entry : availableFields) {
|
||||
items.add(entry.clone());
|
||||
}
|
||||
|
||||
|
||||
StringForTyping openOrChangeEntry = new StringForTyping();
|
||||
if (keepass2android.kbbridge.KeyboardData.entryName == null) {
|
||||
openOrChangeEntry.displayName = openOrChangeEntry.key = getString(R.string.open_entry);
|
||||
} else {
|
||||
openOrChangeEntry.displayName = openOrChangeEntry.key = getString(R.string.change_entry);
|
||||
}
|
||||
openOrChangeEntry.value = "KP2ASPECIAL_SelectEntryTask";
|
||||
items.add(openOrChangeEntry);
|
||||
|
||||
|
||||
final String clientPackageName = attribute.packageName;
|
||||
|
||||
if ((clientPackageName != null) && (clientPackageName != "")) {
|
||||
StringForTyping searchEntry = new StringForTyping();
|
||||
try {
|
||||
searchEntry.key = searchEntry.displayName
|
||||
= getString(R.string.open_entry_for_app, new Object[]{clientPackageName});
|
||||
} catch (java.util.FormatFlagsConversionMismatchException e) //buggy crowdin support for Arabic?
|
||||
{
|
||||
android.util.Log.e("KP2A", "Please report this error to crocoapps@gmail.com");
|
||||
android.util.Log.e("KP2A", e.toString());
|
||||
|
||||
searchEntry.key = searchEntry.displayName
|
||||
= "Search entry for app";
|
||||
}
|
||||
|
||||
searchEntry.value = "KP2ASPECIAL_SearchUrlTask";
|
||||
items.add(searchEntry);
|
||||
}
|
||||
|
||||
|
||||
builder.setTitle(title);
|
||||
|
||||
CharSequence[] itemNames = new CharSequence[items.size()];
|
||||
int i = 0;
|
||||
for (StringForTyping sft : items)
|
||||
itemNames[i++] = sft.displayName;
|
||||
|
||||
builder.setItems(itemNames,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int item) {
|
||||
|
||||
|
||||
if (items.get(item).value.startsWith("KP2ASPECIAL")) {
|
||||
//change entry
|
||||
String packageName = getApplicationContext().getPackageName();
|
||||
Intent startKp2aIntent = getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
if (startKp2aIntent != null) {
|
||||
startKp2aIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
String value = items.get(item).value;
|
||||
String taskName = value.substring("KP2ASPECIAL_".length());
|
||||
startKp2aIntent.putExtra("KP2A_APPTASK", taskName);
|
||||
if (taskName.equals("SearchUrlTask")) {
|
||||
startKp2aIntent.putExtra("UrlToSearch", "androidapp://" + clientPackageName);
|
||||
}
|
||||
startActivity(startKp2aIntent);
|
||||
} else Log.w("KP2AK", "didn't find intent for " + packageName);
|
||||
} else {
|
||||
|
||||
StringForTyping theItem = items.get(item);
|
||||
|
||||
commitStringForTyping(theItem);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
builder.setNegativeButton(android.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
// User cancelled the dialog
|
||||
}
|
||||
});
|
||||
|
||||
// Create the AlertDialog
|
||||
AlertDialog dialog = builder.create();
|
||||
Window window = dialog.getWindow();
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
LatinKeyboardView inputView = mKeyboardSwitcher.getInputView();
|
||||
lp.token = inputView.getWindowToken();
|
||||
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
window.setAttributes(lp);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
Intent i = new Intent(this, Kp2aDialog.class);
|
||||
i.putExtra("clientPackageName", clientPackageName);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(i);
|
||||
}
|
||||
public void commitStringForTyping(StringForTyping theItem) {
|
||||
|
||||
@@ -1480,7 +1628,7 @@ public class KP2AKeyboard extends InputMethodService
|
||||
|
||||
|
||||
|
||||
Log.d("KP2AK", "committing text for " + theItem.key);
|
||||
|
||||
commitKp2aString(theItem.value, getCurrentInputEditorInfo());
|
||||
}
|
||||
|
||||
@@ -1789,6 +1937,7 @@ public class KP2AKeyboard extends InputMethodService
|
||||
}
|
||||
setCandidatesViewShown(true);
|
||||
updateInputViewShown();
|
||||
updateKp2aKeyLabels();
|
||||
postUpdateSuggestions();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -30,6 +30,7 @@ using Android.Widget;
|
||||
using Android.Preferences;
|
||||
using Android.Text.Method;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using Android.Content.PM;
|
||||
using Android.Webkit;
|
||||
using Android.Graphics;
|
||||
@@ -540,9 +541,12 @@ namespace keepass2android
|
||||
binaryDirectory = CacheDir.Path + File.Separator + AttachmentContentProvider.AttachmentCacheSubDir;
|
||||
|
||||
string filepart = key;
|
||||
if (writeToCacheDirectory)
|
||||
filepart = filepart.Replace(" ", "");
|
||||
var targetFile = new File(binaryDirectory, filepart);
|
||||
if (writeToCacheDirectory)
|
||||
{
|
||||
Java.Lang.String javaFilename = new Java.Lang.String(filepart);
|
||||
filepart = javaFilename.ReplaceAll("[^a-zA-Z0-9.-]", "_");
|
||||
}
|
||||
var targetFile = new File(binaryDirectory, filepart);
|
||||
|
||||
File parent = targetFile.ParentFile;
|
||||
|
||||
@@ -1022,7 +1026,12 @@ namespace keepass2android
|
||||
{
|
||||
case Resource.Id.menu_donate:
|
||||
return Util.GotoDonateUrl(this);
|
||||
case Resource.Id.menu_toggle_pass:
|
||||
case Resource.Id.menu_delete:
|
||||
DeleteEntry task = new DeleteEntry(this, App.Kp2a, Entry,
|
||||
new ActionOnFinish(this, (success, message, activity) => { if (success) { RequiresRefresh(); Finish();}}));
|
||||
task.Start();
|
||||
break;
|
||||
case Resource.Id.menu_toggle_pass:
|
||||
if (_showPassword)
|
||||
{
|
||||
item.SetTitle(Resource.String.show_password);
|
||||
|
||||
@@ -279,7 +279,17 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
private void CreateNewFromKpEntryTemplate(Database db, PwEntry templateEntry)
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
if (PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false))
|
||||
{
|
||||
CopyToClipboardService.ActivateKeyboard(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateNewFromKpEntryTemplate(Database db, PwEntry templateEntry)
|
||||
{
|
||||
var entry = new PwEntry(true, true);
|
||||
KpEntryTemplatedEdit.InitializeEntry(entry, templateEntry);
|
||||
|
||||
@@ -42,15 +42,49 @@ namespace keepass2android
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.sftpcredentials, null);
|
||||
|
||||
if (!defaultPath.EndsWith(_schemeSeparator))
|
||||
var spinner = dlgContents.FindViewById<Spinner>(Resource.Id.sftp_auth_mode_spinner);
|
||||
dlgContents.FindViewById<Button>(Resource.Id.send_public_key_button).Click += (sender, args) =>
|
||||
{
|
||||
var fileStorage = new Keepass2android.Javafilestorage.SftpStorage();
|
||||
var fileStorage = new Keepass2android.Javafilestorage.SftpStorage(activity.ApplicationContext);
|
||||
string pub_filename = fileStorage.CreateKeyPair();
|
||||
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.SetAction(Intent.ActionSend);
|
||||
sendIntent.PutExtra(Intent.ExtraText, System.IO.File.ReadAllText(pub_filename));
|
||||
|
||||
sendIntent.PutExtra(Intent.ExtraSubject, "Keepass2Android sftp public key");
|
||||
sendIntent.SetType("text/plain");
|
||||
activity.StartActivity(Intent.CreateChooser(sendIntent, "Send public key to..."));
|
||||
};
|
||||
|
||||
|
||||
spinner.ItemSelected += (sender, args) =>
|
||||
{
|
||||
if (spinner.SelectedItemPosition == 0)
|
||||
{
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_password).Visibility = ViewStates.Visible;
|
||||
dlgContents.FindViewById<Button>(Resource.Id.send_public_key_button).Visibility = ViewStates.Gone;
|
||||
}
|
||||
else
|
||||
{
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_password).Visibility = ViewStates.Gone;
|
||||
dlgContents.FindViewById<Button>(Resource.Id.send_public_key_button).Visibility = ViewStates.Visible;
|
||||
}
|
||||
};
|
||||
|
||||
if (!defaultPath.EndsWith(_schemeSeparator))
|
||||
{
|
||||
var fileStorage = new Keepass2android.Javafilestorage.SftpStorage(activity.ApplicationContext);
|
||||
SftpStorage.ConnectionInfo ci = fileStorage.SplitStringToConnectionInfo(defaultPath);
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_host).Text = ci.Host;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_port).Text = ci.Port.ToString();
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_user).Text = ci.Username;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_password).Text = ci.Password;
|
||||
dlgContents.FindViewById<EditText>(Resource.Id.sftp_initial_dir).Text = ci.LocalPath;
|
||||
if (string.IsNullOrEmpty(ci.Password))
|
||||
{
|
||||
spinner.SetSelection(1);
|
||||
}
|
||||
}
|
||||
|
||||
builder.SetView(dlgContents);
|
||||
@@ -67,7 +101,7 @@ namespace keepass2android
|
||||
string initialPath = dlgContents.FindViewById<EditText>(Resource.Id.sftp_initial_dir).Text;
|
||||
if (string.IsNullOrEmpty(initialPath))
|
||||
initialPath = "/";
|
||||
string sftpPath = new Keepass2android.Javafilestorage.SftpStorage().BuildFullPath(host, port, initialPath, user,
|
||||
string sftpPath = new Keepass2android.Javafilestorage.SftpStorage(activity.ApplicationContext).BuildFullPath(host, port, initialPath, user,
|
||||
password);
|
||||
onStartBrowse(sftpPath);
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
@@ -38,16 +38,12 @@ using Android.Preferences;
|
||||
using Android.Text;
|
||||
using Android.Content.PM;
|
||||
using Android.Graphics;
|
||||
using Android.Hardware.Fingerprints;
|
||||
using Android.Provider;
|
||||
using Android.Support.Design.Widget;
|
||||
using Android.Support.V4.Widget;
|
||||
using Android.Support.V7.App;
|
||||
using Java.Lang;
|
||||
using keepass2android;
|
||||
using KeePassLib.Keys;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
using Keepass2android.Pluginsdk;
|
||||
using OtpKeyProv;
|
||||
using keepass2android.Io;
|
||||
@@ -60,12 +56,10 @@ using Object = Java.Lang.Object;
|
||||
using Process = Android.OS.Process;
|
||||
|
||||
using KeeChallenge;
|
||||
using KeePassLib.Cryptography.KeyDerivation;
|
||||
using AlertDialog = Android.App.AlertDialog;
|
||||
using Enum = System.Enum;
|
||||
using Exception = System.Exception;
|
||||
using String = System.String;
|
||||
using Toolbar = Android.Support.V7.Widget.Toolbar;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -80,15 +74,13 @@ namespace keepass2android
|
||||
|
||||
enum KeyProviders
|
||||
{
|
||||
//int values correspond to indices in passwordSpinner
|
||||
None = 0,
|
||||
KeyFile = 1,
|
||||
Otp = 2,
|
||||
OtpRecovery = 3,
|
||||
Challenge = 4,
|
||||
ChalRecovery = 5,
|
||||
ChallengeXC = 6 //KeepassXC compatible Challenge-Response
|
||||
}
|
||||
ChallengeXC = 6, //KeepassXC compatible Challenge-Response
|
||||
}
|
||||
|
||||
public const String KeyDefaultFilename = "defaultFileName";
|
||||
|
||||
@@ -106,9 +98,9 @@ namespace keepass2android
|
||||
private const string KeyProviderIdChallenge = "KP2A-Chal";
|
||||
private const string KeyProviderIdChallengeRecovery = "KP2A-ChalSecret";
|
||||
private const string KeyProviderIdChallengeXC = "KP2A-ChalXC";
|
||||
|
||||
|
||||
private const int RequestCodePrepareDbFile = 1000;
|
||||
|
||||
private const int RequestCodePrepareDbFile = 1000;
|
||||
private const int RequestCodePrepareOtpAuxFile = 1001;
|
||||
|
||||
private const int RequestCodeSelectKeyfile = 1003;
|
||||
@@ -120,7 +112,7 @@ namespace keepass2android
|
||||
private bool _loadDbTaskOffline; //indicate if preloading was started with offline mode
|
||||
|
||||
private IOConnectionInfo _ioConnection;
|
||||
private String _keyFileOrProvider;
|
||||
private String _keyFile;
|
||||
bool _showPassword;
|
||||
|
||||
internal AppTask AppTask;
|
||||
@@ -130,27 +122,8 @@ namespace keepass2android
|
||||
private List<String> _pendingOtps = new List<string>();
|
||||
|
||||
|
||||
|
||||
KeyProviders KeyProviderType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_keyFileOrProvider == null)
|
||||
return KeyProviders.None;
|
||||
if (_keyFileOrProvider == KeyProviderIdOtp)
|
||||
return KeyProviders.Otp;
|
||||
if (_keyFileOrProvider == KeyProviderIdOtpRecovery)
|
||||
return KeyProviders.OtpRecovery;
|
||||
if (_keyFileOrProvider == KeyProviderIdChallenge)
|
||||
return KeyProviders.Challenge;
|
||||
if (_keyFileOrProvider == KeyProviderIdChallengeRecovery)
|
||||
return KeyProviders.ChalRecovery;
|
||||
if (_keyFileOrProvider == KeyProviderIdChallengeXC)
|
||||
return KeyProviders.ChallengeXC;
|
||||
return KeyProviders.KeyFile;
|
||||
}
|
||||
}
|
||||
|
||||
private HashSet<KeyProviders> KeyProviderTypes = new HashSet<KeyProviders>();
|
||||
|
||||
private bool _rememberKeyfile;
|
||||
ISharedPreferences _prefs;
|
||||
|
||||
@@ -253,7 +226,6 @@ namespace keepass2android
|
||||
|
||||
AppTask.TryGetFromActivityResult(data, ref AppTask);
|
||||
|
||||
//NOTE: original code from k eepassdroid used switch ((Android.App.Result)requestCode) { (but doesn't work here, although k eepassdroid works)
|
||||
switch(resultCode) {
|
||||
|
||||
case KeePass.ExitNormal: // Returned to this screen using the Back key
|
||||
@@ -271,13 +243,13 @@ namespace keepass2android
|
||||
// The database has already been locked, and the quick unlock screen will be shown if appropriate
|
||||
|
||||
_rememberKeyfile = _prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default)); //update value
|
||||
if ((KeyProviderType == KeyProviders.KeyFile) && (_rememberKeyfile))
|
||||
if (KeyProviderHasKeyFile() && (_rememberKeyfile))
|
||||
{
|
||||
//check if the keyfile was changed (by importing to internal directory)
|
||||
var newKeyFile = GetKeyFile(_ioConnection.Path);
|
||||
if (newKeyFile != _keyFileOrProvider)
|
||||
var newKeyProviderString = LoadKeyProviderStringForIoc(_ioConnection.Path);
|
||||
if (newKeyProviderString != GetKeyProviderString())
|
||||
{
|
||||
_keyFileOrProvider = newKeyFile;
|
||||
SetKeyProviderFromString(newKeyProviderString);
|
||||
UpdateKeyfileIocView();
|
||||
}
|
||||
}
|
||||
@@ -310,7 +282,7 @@ namespace keepass2android
|
||||
Handler handler = new Handler();
|
||||
OnFinish onFinish = new AfterLoad(handler, this, _ioConnection);
|
||||
_performingLoad = true;
|
||||
LoadDb task = new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, _keyFileOrProvider, onFinish);
|
||||
LoadDb task = new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, GetKeyProviderString(), onFinish);
|
||||
_loadDbFileTask = null; // prevent accidental re-use
|
||||
new ProgressTask(App.Kp2a, this, task).Run();
|
||||
}
|
||||
@@ -321,20 +293,20 @@ namespace keepass2android
|
||||
{
|
||||
IOConnectionInfo ioc = new IOConnectionInfo();
|
||||
SetIoConnectionFromIntent(ioc, data);
|
||||
_keyFileOrProvider = IOConnectionInfo.SerializeToString(ioc);
|
||||
_keyFile = IOConnectionInfo.SerializeToString(ioc);
|
||||
UpdateKeyfileIocView();
|
||||
}
|
||||
break;
|
||||
case (Result)FileStorageResults.FileUsagePrepared:
|
||||
if (requestCode == RequestCodePrepareDbFile)
|
||||
{
|
||||
if (KeyProviderType == KeyProviders.KeyFile)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.KeyFile))
|
||||
{
|
||||
|
||||
//if the user has not yet selected a keyfile, _keyFileOrProvider is empty
|
||||
if (string.IsNullOrEmpty(_keyFileOrProvider) == false)
|
||||
|
||||
//if the user has not yet selected a keyfile, _keyFile is empty
|
||||
if (string.IsNullOrEmpty(_keyFile) == false)
|
||||
{
|
||||
var iocKeyfile = IOConnectionInfo.UnserializeFromString(_keyFileOrProvider);
|
||||
var iocKeyfile = IOConnectionInfo.UnserializeFromString(_keyFile);
|
||||
|
||||
App.Kp2a.GetFileStorage(iocKeyfile)
|
||||
.PrepareFileUsage(new FileStorageSetupInitiatorActivity(this, OnActivityResult, null), iocKeyfile,
|
||||
@@ -428,16 +400,17 @@ namespace keepass2android
|
||||
else
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.bad_resp, ToastLength.Long).Show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AuxFileLoader GetAuxFileLoader()
|
||||
|
||||
|
||||
private AuxFileLoader GetAuxFileLoader()
|
||||
{
|
||||
if (_keyFileOrProvider == KeyProviderIdChallenge)
|
||||
{
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
|
||||
{
|
||||
return new ChallengeAuxFileLoader(this);
|
||||
}
|
||||
else
|
||||
@@ -448,8 +421,8 @@ namespace keepass2android
|
||||
private void UpdateKeyfileIocView()
|
||||
{
|
||||
//store keyfile in the view so that we can show the selected keyfile again if the user switches to another key provider and back to key file
|
||||
FindViewById<TextView>(Resource.Id.label_keyfilename).Tag = _keyFileOrProvider;
|
||||
if (string.IsNullOrEmpty(_keyFileOrProvider))
|
||||
FindViewById<TextView>(Resource.Id.label_keyfilename).Tag = _keyFile;
|
||||
if (string.IsNullOrEmpty(_keyFile))
|
||||
{
|
||||
FindViewById<TextView>(Resource.Id.filestorage_label).Visibility = ViewStates.Gone;
|
||||
FindViewById<ImageView>(Resource.Id.filestorage_logo).Visibility = ViewStates.Gone;
|
||||
@@ -457,7 +430,7 @@ namespace keepass2android
|
||||
|
||||
return;
|
||||
}
|
||||
var ioc = IOConnectionInfo.UnserializeFromString(_keyFileOrProvider);
|
||||
var ioc = IOConnectionInfo.UnserializeFromString(_keyFile);
|
||||
string displayPath = App.Kp2a.GetFileStorage(ioc).GetDisplayName(ioc);
|
||||
int protocolSeparatorPos = displayPath.IndexOf("://", StringComparison.Ordinal);
|
||||
string protocolId = protocolSeparatorPos < 0 ?
|
||||
@@ -531,7 +504,7 @@ namespace keepass2android
|
||||
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppGet, true);
|
||||
intent.PutExtra(FileStorageSelectionActivity.AllowThirdPartyAppSend, false);
|
||||
intent.PutExtra(FileStorageSetupDefs.ExtraIsForSave, false);
|
||||
intent.PutExtra(SelectStorageLocationActivity.ExtraKeyWritableRequirements, (int)SelectStorageLocationActivity.WritableRequirements.WriteDemanded);
|
||||
intent.PutExtra(SelectStorageLocationActivity.ExtraKeyWritableRequirements, (int)SelectStorageLocationActivityBase.WritableRequirements.WriteDemanded);
|
||||
Activity.StartActivityForResult(intent, RequestCodeSelectAuxFile);
|
||||
}
|
||||
else
|
||||
@@ -586,16 +559,7 @@ namespace keepass2android
|
||||
IOConnectionInfo iocAux = fileStorage.GetFilePath(parentPath, filename);
|
||||
return iocAux;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static IOConnectionInfo GetAuxFileIoc(KeyProviderQueryContext ctx)
|
||||
{
|
||||
IOConnectionInfo ioc = ctx.DatabaseIOInfo.CloneDeep();
|
||||
var iocAux = GetAuxFileIoc(ioc);
|
||||
|
||||
return iocAux;
|
||||
}
|
||||
|
||||
|
||||
protected override void HandleSuccess()
|
||||
{
|
||||
@@ -700,9 +664,7 @@ namespace keepass2android
|
||||
|
||||
int count = 1;
|
||||
|
||||
private DrawerLayout mDrawerLayout;
|
||||
//private RecyclerView mDrawerList;
|
||||
|
||||
|
||||
private string mDrawerTitle;
|
||||
private MeasuringRelativeLayout.MeasureArgs _measureArgs;
|
||||
private ActivityDesign _activityDesign;
|
||||
@@ -716,7 +678,7 @@ namespace keepass2android
|
||||
{
|
||||
PasswordActivity owner;
|
||||
|
||||
public MyActionBarDrawerToggle(PasswordActivity activity, DrawerLayout layout, int imgRes, int openRes, int closeRes)
|
||||
public MyActionBarDrawerToggle(PasswordActivity activity, DrawerLayout layout, int openRes, int closeRes)
|
||||
: base(activity, layout, openRes, closeRes)
|
||||
{
|
||||
owner = activity;
|
||||
@@ -822,19 +784,22 @@ namespace keepass2android
|
||||
if (keyFileFromIntent != null)
|
||||
{
|
||||
Kp2aLog.Log("try get keyfile from intent");
|
||||
_keyFileOrProvider = IOConnectionInfo.SerializeToString(IOConnectionInfo.FromPath(keyFileFromIntent));
|
||||
_keyFile = IOConnectionInfo.SerializeToString(IOConnectionInfo.FromPath(keyFileFromIntent));
|
||||
KeyProviderTypes.Clear();
|
||||
KeyProviderTypes.Add(KeyProviders.KeyFile);
|
||||
Kp2aLog.Log("try get keyfile from intent ok");
|
||||
}
|
||||
else
|
||||
{
|
||||
_keyFileOrProvider = null;
|
||||
}
|
||||
_keyFile = null;
|
||||
KeyProviderTypes.Clear();
|
||||
}
|
||||
_password = i.GetStringExtra(KeyPassword) ?? "";
|
||||
if (string.IsNullOrEmpty(_keyFileOrProvider))
|
||||
if (!KeyProviderTypes.Any())
|
||||
{
|
||||
_keyFileOrProvider = GetKeyFile(_ioConnection.Path);
|
||||
SetKeyProviderFromString(LoadKeyProviderStringForIoc(_ioConnection.Path));
|
||||
}
|
||||
if ((!string.IsNullOrEmpty(_keyFileOrProvider)) || (_password != ""))
|
||||
if ((!string.IsNullOrEmpty(_keyFile)) || (_password != ""))
|
||||
{
|
||||
_keepPasswordInOnResume = true;
|
||||
}
|
||||
@@ -853,7 +818,7 @@ namespace keepass2android
|
||||
|
||||
InitializeFilenameView();
|
||||
|
||||
if (KeyProviderType == KeyProviders.KeyFile)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.KeyFile))
|
||||
{
|
||||
UpdateKeyfileIocView();
|
||||
}
|
||||
@@ -905,8 +870,8 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
mDrawerTitle = this.Title;
|
||||
mDrawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
|
||||
mDrawerTitle = Title;
|
||||
FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
|
||||
var rootview = FindViewById<MeasuringRelativeLayout>(Resource.Id.relative_layout);
|
||||
rootview.ViewTreeObserver.GlobalLayout += (sender, args2) =>
|
||||
{
|
||||
@@ -924,16 +889,116 @@ namespace keepass2android
|
||||
rootview.MeasureEvent += (sender, args) =>
|
||||
{
|
||||
//Snackbar.Make(rootview, "height="+args.ActualHeight, Snackbar.LengthLong).Show();
|
||||
this._measureArgs = args;
|
||||
_measureArgs = args;
|
||||
};
|
||||
|
||||
if ((int)Build.VERSION.SdkInt >= 23)
|
||||
RequestPermissions(new[] { Manifest.Permission.UseFingerprint }, FingerprintPermissionRequestCode);
|
||||
|
||||
}
|
||||
const int FingerprintPermissionRequestCode = 99;
|
||||
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
|
||||
private const string Kp2aKeyProviderStringPrefix = "_KP2A_KEYTYPES:";
|
||||
|
||||
private string GetKeyProviderString()
|
||||
{
|
||||
if (!KeyProviderTypes.Any())
|
||||
return null;
|
||||
string result = Kp2aKeyProviderStringPrefix;
|
||||
foreach (KeyProviders type in KeyProviderTypes)
|
||||
{
|
||||
result += type.ToString();
|
||||
|
||||
if (type == KeyProviders.KeyFile)
|
||||
{
|
||||
result += WebUtility.UrlEncode(_keyFile) + ";";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void SetKeyProviderFromString(string keyProviderString)
|
||||
{
|
||||
KeyProviderTypes.Clear();
|
||||
if (string.IsNullOrEmpty(keyProviderString))
|
||||
{
|
||||
_keyFile = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyProviderString.StartsWith(Kp2aKeyProviderStringPrefix))
|
||||
{
|
||||
keyProviderString = keyProviderString.Substring(Kp2aKeyProviderStringPrefix.Length);
|
||||
foreach (string type in keyProviderString.Split(';'))
|
||||
{
|
||||
if (!type.Trim().Any())
|
||||
continue;
|
||||
if (type.StartsWith(KeyProviders.KeyFile.ToString()))
|
||||
{
|
||||
_keyFile = WebUtility.UrlDecode(type.Substring(KeyProviders.KeyFile.ToString().Length));
|
||||
KeyProviderTypes.Add(KeyProviders.KeyFile);
|
||||
continue;
|
||||
}
|
||||
foreach (KeyProviders providerType in Enum.GetValues(typeof(KeyProviders)))
|
||||
{
|
||||
if (type == providerType.ToString())
|
||||
{
|
||||
KeyProviderTypes.Add(providerType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//legacy mode
|
||||
_keyFile = null;
|
||||
|
||||
if (keyProviderString == KeyProviderIdOtp)
|
||||
KeyProviderTypes.Add(KeyProviders.Otp);
|
||||
else if (keyProviderString == KeyProviderIdOtpRecovery)
|
||||
KeyProviderTypes.Add(KeyProviders.OtpRecovery);
|
||||
else if (keyProviderString == KeyProviderIdChallenge)
|
||||
KeyProviderTypes.Add(KeyProviders.Challenge);
|
||||
else if (keyProviderString == KeyProviderIdChallengeRecovery)
|
||||
KeyProviderTypes.Add(KeyProviders.ChalRecovery);
|
||||
else if (keyProviderString == KeyProviderIdChallengeXC)
|
||||
KeyProviderTypes.Add(KeyProviders.ChallengeXC);
|
||||
else
|
||||
{
|
||||
KeyProviderTypes.Add(KeyProviders.KeyFile);
|
||||
_keyFile = keyProviderString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (KeyProviderTypes.Contains(KeyProviders.KeyFile))
|
||||
{
|
||||
//test if the filename is properly encoded.
|
||||
try
|
||||
{
|
||||
Kp2aLog.Log("test if stored filename is ok");
|
||||
IOConnectionInfo.UnserializeFromString(_keyFile);
|
||||
Kp2aLog.Log("...ok");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//it's not. This is probably because we're upgrading from app version <= 45
|
||||
//where the keyfile was stored plain text and not serialized
|
||||
Kp2aLog.Log("no, it's not: " + e.GetType().Name);
|
||||
var serializedKeyFile = IOConnectionInfo.SerializeToString(IOConnectionInfo.FromPath(_keyFile));
|
||||
Kp2aLog.Log("now it is!");
|
||||
_keyFile = serializedKeyFile;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int FingerprintPermissionRequestCode = 99;
|
||||
|
||||
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
|
||||
{
|
||||
if ((requestCode == FingerprintPermissionRequestCode) && (grantResults.Length > 0) && (grantResults[0] == Permission.Granted))
|
||||
{
|
||||
@@ -982,9 +1047,10 @@ namespace keepass2android
|
||||
{
|
||||
var masterPassword = _fingerprintDec.DecryptStored(Database.GetFingerprintPrefKey(_ioConnection));
|
||||
_password = FindViewById<EditText>(Resource.Id.password_edit).Text = masterPassword;
|
||||
FindViewById<EditText>(Resource.Id.password_edit).Enabled = false; //prevent accidental modification of password
|
||||
|
||||
}
|
||||
catch (Java.Security.GeneralSecurityException ex)
|
||||
}
|
||||
catch (Java.Security.GeneralSecurityException)
|
||||
{
|
||||
HandleFingerprintKeyInvalidated();
|
||||
return;
|
||||
@@ -992,8 +1058,9 @@ namespace keepass2android
|
||||
|
||||
btn.PostDelayed(() =>
|
||||
{
|
||||
//fire
|
||||
OnOk(true);
|
||||
//fire
|
||||
OnOk(true);
|
||||
FindViewById<EditText>(Resource.Id.password_edit).Enabled = true;
|
||||
}, 500);
|
||||
|
||||
}
|
||||
@@ -1011,7 +1078,7 @@ namespace keepass2android
|
||||
};
|
||||
FindViewById(Resource.Id.btn_nav_donate).Visibility =
|
||||
PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(this.GetString(Resource.String.NoDonateOption_key), false)
|
||||
.GetBoolean(GetString(Resource.String.NoDonateOption_key), false)
|
||||
? ViewStates.Gone
|
||||
: ViewStates.Visible;
|
||||
FindViewById(Resource.Id.btn_nav_about).Click += (sender, args) =>
|
||||
@@ -1059,7 +1126,7 @@ namespace keepass2android
|
||||
Resource.String.menu_close);
|
||||
|
||||
|
||||
_drawerLayout.SetDrawerListener(mDrawerToggle);
|
||||
_drawerLayout?.SetDrawerListener(mDrawerToggle);
|
||||
|
||||
|
||||
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
@@ -1126,9 +1193,10 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
//assume user wants to use OTP (for static password, they need to open KP2A first and select the key provider type, then see OnNewIntent)
|
||||
_keyFileOrProvider = KeyProviderIdOtp;
|
||||
KeyProviderTypes.Clear();
|
||||
KeyProviderTypes.Add(KeyProviders.Otp);
|
||||
|
||||
if (savedInstanceState == null) //only when not re-creating
|
||||
if (savedInstanceState == null) //only when not re-creating
|
||||
{
|
||||
//remember the OTP for later use
|
||||
_pendingOtps.Add(i.GetStringExtra(Intents.OtpExtraKey));
|
||||
@@ -1178,7 +1246,7 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
_keyFileOrProvider = GetKeyFile(_ioConnection.Path);
|
||||
SetKeyProviderFromString(LoadKeyProviderStringForIoc(_ioConnection.Path));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1241,33 +1309,58 @@ namespace keepass2android
|
||||
if (passwordModeSpinner != null)
|
||||
{
|
||||
UpdateKeyProviderUiState();
|
||||
passwordModeSpinner.SetSelection((int) KeyProviderType);
|
||||
|
||||
int spinnerPos = 0;
|
||||
if (KeyProviderTypes.Contains(KeyProviders.KeyFile))
|
||||
{
|
||||
if (KeyProviderTypes.Contains(KeyProviders.ChallengeXC))
|
||||
spinnerPos = 7;
|
||||
else spinnerPos = 1;
|
||||
}
|
||||
else if (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
spinnerPos = 2;
|
||||
else if (KeyProviderTypes.Contains(KeyProviders.OtpRecovery))
|
||||
spinnerPos = 3;
|
||||
else if (KeyProviderTypes.Contains(KeyProviders.Challenge))
|
||||
spinnerPos = 4;
|
||||
else if (KeyProviderTypes.Contains(KeyProviders.ChalRecovery))
|
||||
spinnerPos = 5;
|
||||
else if (KeyProviderTypes.Contains(KeyProviders.ChallengeXC))
|
||||
spinnerPos = 6;
|
||||
|
||||
passwordModeSpinner.SetSelection(spinnerPos);
|
||||
passwordModeSpinner.ItemSelected += (sender, args) =>
|
||||
{
|
||||
{
|
||||
KeyProviderTypes.Clear();
|
||||
_keyFile = null;
|
||||
switch (args.Position)
|
||||
{
|
||||
case 0:
|
||||
_keyFileOrProvider = null;
|
||||
break;
|
||||
case 1:
|
||||
//don't set to "" to prevent losing the filename. (ItemSelected is also called during recreation!)
|
||||
_keyFileOrProvider = (FindViewById(Resource.Id.label_keyfilename).Tag ?? "").ToString();
|
||||
//don't set to "" to prevent losing the filename. (ItemSelected is also called during recreation!)
|
||||
_keyFile = (FindViewById(Resource.Id.label_keyfilename).Tag ?? "").ToString();
|
||||
KeyProviderTypes.Add(KeyProviders.KeyFile);
|
||||
break;
|
||||
case 2:
|
||||
_keyFileOrProvider = KeyProviderIdOtp;
|
||||
break;
|
||||
KeyProviderTypes.Add(KeyProviders.Otp);
|
||||
break;
|
||||
case 3:
|
||||
_keyFileOrProvider = KeyProviderIdOtpRecovery;
|
||||
break;
|
||||
KeyProviderTypes.Add(KeyProviders.OtpRecovery);
|
||||
break;
|
||||
case 4:
|
||||
_keyFileOrProvider = KeyProviderIdChallenge;
|
||||
break;
|
||||
KeyProviderTypes.Add(KeyProviders.Challenge);
|
||||
break;
|
||||
case 5:
|
||||
_keyFileOrProvider = KeyProviderIdChallengeRecovery;
|
||||
break;
|
||||
KeyProviderTypes.Add(KeyProviders.ChalRecovery);
|
||||
break;
|
||||
case 6:
|
||||
_keyFileOrProvider = KeyProviderIdChallengeXC;
|
||||
break;
|
||||
KeyProviderTypes.Add(KeyProviders.ChallengeXC);
|
||||
break;
|
||||
case 7:
|
||||
KeyProviderTypes.Add(KeyProviders.ChallengeXC);
|
||||
KeyProviderTypes.Add(KeyProviders.KeyFile);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unexpected position " + args.Position + " / " +
|
||||
((ICursor) ((AdapterView) sender).GetItemAtPosition(args.Position)).GetString(1));
|
||||
@@ -1291,7 +1384,7 @@ namespace keepass2android
|
||||
_showPassword = savedInstanceState.GetBoolean(ShowpasswordKey, false);
|
||||
MakePasswordMaskedOrVisible();
|
||||
|
||||
_keyFileOrProvider = savedInstanceState.GetString(KeyFileOrProviderKey);
|
||||
SetKeyProviderFromString(savedInstanceState.GetString(KeyFileOrProviderKey));
|
||||
_password = FindViewById<EditText>(Resource.Id.password_edit).Text = savedInstanceState.GetString(PasswordKey);
|
||||
|
||||
_pendingOtps = new List<string>(savedInstanceState.GetStringArrayList(PendingOtpsKey));
|
||||
@@ -1319,77 +1412,66 @@ namespace keepass2android
|
||||
|
||||
private void UpdateOkButtonState()
|
||||
{
|
||||
bool enabled = false;
|
||||
switch (KeyProviderType)
|
||||
{
|
||||
case KeyProviders.None:
|
||||
enabled = true;
|
||||
break;
|
||||
case KeyProviders.KeyFile:
|
||||
enabled = _keyFileOrProvider != "" || _password != "";
|
||||
break;
|
||||
case KeyProviders.Otp:
|
||||
|
||||
enabled = true;
|
||||
if (_otpInfo == null)
|
||||
enabled = false;
|
||||
else
|
||||
{
|
||||
int c = 0;
|
||||
foreach (int otpId in _otpTextViewIds)
|
||||
{
|
||||
c++;
|
||||
var otpTextView = FindViewById<EditText>(otpId);
|
||||
if ((c <= _otpInfo.OtpsRequired) && (otpTextView.Text == ""))
|
||||
{
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case KeyProviders.OtpRecovery:
|
||||
case KeyProviders.ChalRecovery:
|
||||
enabled = FindViewById<EditText>(Resource.Id.pass_otpsecret).Text != "";
|
||||
break;
|
||||
case KeyProviders.ChallengeXC:
|
||||
enabled = true;
|
||||
break;
|
||||
case KeyProviders.Challenge:
|
||||
enabled = _challengeSecret != null;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
bool enabled = true;
|
||||
if (KeyProviderTypes.Contains(KeyProviders.KeyFile))
|
||||
enabled &= _keyFile != "" || _password != "";
|
||||
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
{
|
||||
if (_otpInfo == null)
|
||||
enabled = false;
|
||||
else
|
||||
{
|
||||
int c = 0;
|
||||
foreach (int otpId in _otpTextViewIds)
|
||||
{
|
||||
c++;
|
||||
var otpTextView = FindViewById<EditText>(otpId);
|
||||
if ((c <= _otpInfo.OtpsRequired) && (otpTextView.Text == ""))
|
||||
{
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (KeyProviderTypes.Contains(KeyProviders.OtpRecovery) || KeyProviderTypes.Contains(KeyProviders.ChalRecovery))
|
||||
{
|
||||
enabled &= FindViewById<EditText>(Resource.Id.pass_otpsecret).Text != "";
|
||||
}
|
||||
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
|
||||
enabled &= _challengeSecret != null;
|
||||
|
||||
FindViewById(Resource.Id.pass_ok).Enabled = enabled;
|
||||
|
||||
}
|
||||
|
||||
private void UpdateKeyProviderUiState()
|
||||
{
|
||||
FindViewById(Resource.Id.keyfileLine).Visibility = KeyProviderType == KeyProviders.KeyFile
|
||||
FindViewById(Resource.Id.keyfileLine).Visibility = KeyProviderHasKeyFile()
|
||||
? ViewStates.Visible
|
||||
: ViewStates.Gone;
|
||||
if (KeyProviderType == KeyProviders.KeyFile)
|
||||
if (KeyProviderHasKeyFile())
|
||||
{
|
||||
UpdateKeyfileIocView();
|
||||
}
|
||||
|
||||
FindViewById(Resource.Id.otpView).Visibility = KeyProviderType == KeyProviders.Otp
|
||||
FindViewById(Resource.Id.otpView).Visibility = KeyProviderTypes.Contains(KeyProviders.Otp)
|
||||
? ViewStates.Visible
|
||||
: ViewStates.Gone;
|
||||
|
||||
FindViewById(Resource.Id.otpSecretLine).Visibility = (KeyProviderType == KeyProviders.OtpRecovery || KeyProviderType == KeyProviders.ChalRecovery)
|
||||
FindViewById(Resource.Id.otpSecretLine).Visibility = (KeyProviderTypes.Contains(KeyProviders.OtpRecovery) || KeyProviderTypes.Contains(KeyProviders.ChalRecovery))
|
||||
? ViewStates.Visible
|
||||
: ViewStates.Gone;
|
||||
if (KeyProviderType == KeyProviders.Otp)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
{
|
||||
FindViewById(Resource.Id.otps_pending).Visibility = _pendingOtps.Count > 0 ? ViewStates.Visible : ViewStates.Gone;
|
||||
}
|
||||
|
||||
if (KeyProviderType == KeyProviders.Challenge)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
|
||||
{
|
||||
FindViewById (Resource.Id.otpView).Visibility = ViewStates.Visible;
|
||||
FindViewById(Resource.Id.otps_pending).Visibility = ViewStates.Gone;
|
||||
@@ -1397,7 +1479,12 @@ namespace keepass2android
|
||||
UpdateOkButtonState();
|
||||
}
|
||||
|
||||
private void PerformLoadDatabase()
|
||||
private bool KeyProviderHasKeyFile()
|
||||
{
|
||||
return KeyProviderTypes.Contains(KeyProviders.KeyFile);
|
||||
}
|
||||
|
||||
private void PerformLoadDatabase()
|
||||
{
|
||||
_currentlyWaitingKey = null;
|
||||
if (_performingLoad)
|
||||
@@ -1450,10 +1537,10 @@ namespace keepass2android
|
||||
|
||||
Handler handler = new Handler();
|
||||
OnFinish onFinish = new AfterLoad(handler, this, _ioConnection);
|
||||
LoadDb task = (KeyProviderType == KeyProviders.Otp)
|
||||
? new SaveOtpAuxFileAndLoadDb(App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, _keyFileOrProvider,
|
||||
LoadDb task = (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
? new SaveOtpAuxFileAndLoadDb(App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, GetKeyProviderString(),
|
||||
onFinish, this)
|
||||
: new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, _keyFileOrProvider, onFinish);
|
||||
: new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKey, GetKeyProviderString(), onFinish);
|
||||
_loadDbFileTask = null; // prevent accidental re-use
|
||||
|
||||
SetNewDefaultFile();
|
||||
@@ -1462,7 +1549,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(new Exception("cannot load database: "+e + ", c: " + (compositeKey != null) + (_ioConnection != null) + (_keyFileOrProvider != null), e));
|
||||
Kp2aLog.LogUnexpectedError(new Exception("cannot load database: "+e + ", c: " + (compositeKey != null) + (_ioConnection != null) + (_keyFile != null), e));
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -1474,13 +1561,13 @@ namespace keepass2android
|
||||
//no need to check for validity of password because if this method is called, the Ok button was enabled (i.e. there was a valid password)
|
||||
compositeKey = new CompositeKey();
|
||||
compositeKey.AddUserKey(new KcpPassword(_password));
|
||||
if (KeyProviderType == KeyProviders.KeyFile)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.KeyFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_keyFileOrProvider == "")
|
||||
if (_keyFile == "")
|
||||
throw new System.IO.FileNotFoundException();
|
||||
var ioc = IOConnectionInfo.UnserializeFromString(_keyFileOrProvider);
|
||||
var ioc = IOConnectionInfo.UnserializeFromString(_keyFile);
|
||||
using (var stream = App.Kp2a.GetFileStorage(ioc).OpenFileForRead(ioc))
|
||||
{
|
||||
byte[] keyfileData = StreamToMemoryStream(stream).ToArray();
|
||||
@@ -1500,7 +1587,7 @@ namespace keepass2android
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (KeyProviderType == KeyProviders.Otp)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1517,7 +1604,7 @@ namespace keepass2android
|
||||
}
|
||||
compositeKey.AddUserKey(new KcpCustomKey(OathHotpKeyProv.Name, _otpInfo.Secret, true));
|
||||
}
|
||||
else if ((KeyProviderType == KeyProviders.OtpRecovery) || (KeyProviderType == KeyProviders.ChalRecovery))
|
||||
if ((KeyProviderTypes.Contains(KeyProviders.OtpRecovery)) || (KeyProviderTypes.Contains(KeyProviders.ChalRecovery)))
|
||||
{
|
||||
Spinner stpDataFmtSpinner = FindViewById<Spinner>(Resource.Id.otpsecret_format_spinner);
|
||||
EditText secretEdit = FindViewById<EditText>(Resource.Id.pass_otpsecret);
|
||||
@@ -1533,11 +1620,11 @@ namespace keepass2android
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (KeyProviderType == KeyProviders.Challenge)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
|
||||
{
|
||||
compositeKey.AddUserKey(new KcpCustomKey(KeeChallengeProv.Name, _challengeSecret, true));
|
||||
}
|
||||
else if (KeyProviderType == KeyProviders.ChallengeXC)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.ChallengeXC))
|
||||
{
|
||||
_currentlyWaitingKey = new ChallengeXCKey(this, RequestCodeChallengeYubikey);
|
||||
compositeKey.AddUserKey(_currentlyWaitingKey);
|
||||
@@ -1624,7 +1711,13 @@ namespace keepass2android
|
||||
base.OnStart();
|
||||
_starting = true;
|
||||
|
||||
AppTask.CanActivateSearchViewOnStart = true;
|
||||
if (PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false))
|
||||
{
|
||||
CopyToClipboardService.ActivateKeyboard(this);
|
||||
}
|
||||
|
||||
AppTask.CanActivateSearchViewOnStart = true;
|
||||
DonateReminder.ShowDonateReminderIfAppropriate(this);
|
||||
|
||||
|
||||
@@ -1660,7 +1753,7 @@ namespace keepass2android
|
||||
AppTask.ToBundle(outState);
|
||||
outState.PutBoolean(ShowpasswordKey, _showPassword);
|
||||
|
||||
outState.PutString(KeyFileOrProviderKey, _keyFileOrProvider);
|
||||
outState.PutString(KeyFileOrProviderKey, GetKeyProviderString());
|
||||
outState.PutString(PasswordKey, _password);
|
||||
outState.PutStringArrayList(PendingOtpsKey, _pendingOtps);
|
||||
if (_otpInfo != null)
|
||||
@@ -1695,7 +1788,7 @@ namespace keepass2android
|
||||
{
|
||||
string otp = intent.GetStringExtra(Intents.OtpExtraKey);
|
||||
_keepPasswordInOnResume = true;
|
||||
if (this.KeyProviderType == KeyProviders.Otp)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
{
|
||||
|
||||
if (_otpInfo == null)
|
||||
@@ -1800,7 +1893,7 @@ namespace keepass2android
|
||||
|
||||
UpdateOkButtonState();
|
||||
|
||||
if (KeyProviderType == KeyProviders.Challenge)
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
|
||||
{
|
||||
FindViewById(Resource.Id.otpInitView).Visibility = _challengeSecret == null ? ViewStates.Visible : ViewStates.Gone;
|
||||
}
|
||||
@@ -1835,7 +1928,7 @@ namespace keepass2android
|
||||
if (_loadDbFileTask == null && _prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true))
|
||||
{
|
||||
// Create task to kick off file loading while the user enters the password
|
||||
_loadDbFileTask = Task.Factory.StartNew<MemoryStream>(PreloadDbFile);
|
||||
_loadDbFileTask = Task.Factory.StartNew(PreloadDbFile);
|
||||
_loadDbTaskOffline = App.Kp2a.OfflineMode;
|
||||
}
|
||||
}
|
||||
@@ -1860,7 +1953,7 @@ namespace keepass2android
|
||||
EditText pwd = (EditText)FindViewById(Resource.Id.password_edit);
|
||||
pwd.PostDelayed(() =>
|
||||
{
|
||||
InputMethodManager keyboard = (InputMethodManager)GetSystemService(Context.InputMethodService);
|
||||
InputMethodManager keyboard = (InputMethodManager)GetSystemService(InputMethodService);
|
||||
if (showKeyboard)
|
||||
keyboard.ShowSoftInput(pwd, 0);
|
||||
else
|
||||
@@ -1904,7 +1997,7 @@ namespace keepass2android
|
||||
{
|
||||
//exception can happen here if the app was restored from Google Backup (including preferences) but no fingerprint data is there.
|
||||
btn.SetImageResource(Resource.Drawable.ic_fingerprint_error);
|
||||
Kp2aLog.Log("failed to init fingerprint unlock:" + e.ToString());
|
||||
Kp2aLog.Log("failed to init fingerprint unlock:" + e);
|
||||
string error = GetString(Resource.String.FingerprintInitFailed) + " " +
|
||||
GetString(Resource.String.fingerprint_reenable2);
|
||||
|
||||
@@ -1942,32 +2035,12 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
private String GetKeyFile(String filename) {
|
||||
private String LoadKeyProviderStringForIoc(String filename) {
|
||||
if ( _rememberKeyfile ) {
|
||||
string keyfile = App.Kp2a.FileDbHelper.GetKeyFileForFile(filename);
|
||||
if (String.IsNullOrEmpty(keyfile))
|
||||
return null; //signal no key file
|
||||
|
||||
if (KeyProviderType == KeyProviders.KeyFile)
|
||||
{
|
||||
//test if the filename is properly encoded.
|
||||
try
|
||||
{
|
||||
Kp2aLog.Log("test if stored filename is ok");
|
||||
IOConnectionInfo.UnserializeFromString(keyfile);
|
||||
Kp2aLog.Log("...ok");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//it's not. This is probably because we're upgrading from app version <= 45
|
||||
//where the keyfile was stored plain text and not serialized
|
||||
Kp2aLog.Log("no, it's not: " + e.GetType().Name);
|
||||
var serializedKeyFile = IOConnectionInfo.SerializeToString(IOConnectionInfo.FromPath(keyfile));
|
||||
Kp2aLog.Log("now it is!");
|
||||
return serializedKeyFile;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return keyfile;
|
||||
} else {
|
||||
return null;
|
||||
@@ -2094,8 +2167,8 @@ namespace keepass2android
|
||||
{
|
||||
if (_act._prefs.GetBoolean(IoUtil.GetIocPrefKey(_ioConnection, "has_local_backup"), false))
|
||||
{
|
||||
Java.Lang.Object changeDb = _act.GetString(Resource.String.menu_change_db);
|
||||
Message += _act.GetString(Resource.String.HintLocalBackupOtherError, new Java.Lang.Object[] { changeDb });
|
||||
Object changeDb = _act.GetString(Resource.String.menu_change_db);
|
||||
Message += _act.GetString(Resource.String.HintLocalBackupOtherError, changeDb);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<application android:label="keepass2android"
|
||||
android:icon="@mipmap/ic_launcher_online"
|
||||
android:roundIcon="@mipmap/ic_launcher_online_round"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
>
|
||||
|
||||
<activity android:name="com.dropbox.core.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="124"
|
||||
android:versionName="1.06c"
|
||||
android:versionCode="127"
|
||||
android:versionName="1.06f"
|
||||
package="keepass2android.keepass2android"
|
||||
android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="26" />
|
||||
@@ -11,6 +11,8 @@
|
||||
<application android:label="keepass2android"
|
||||
android:icon="@mipmap/ic_launcher_online"
|
||||
android:roundIcon="@mipmap/ic_launcher_online_round"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
|
||||
>
|
||||
<activity android:name="com.dropbox.core.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
|
||||
<intent-filter>
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />
|
||||
<permission android:description="@string/permission_desc2" android:icon="@drawable/ic_launcher" android:label="KP2A entry search" android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" android:protectionLevel="signature" />
|
||||
<permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android_nonet.permission.Kp2aChooseAutofill" android:protectionLevel="signature" />
|
||||
<application android:label="keepass2android" android:icon="@mipmap/ic_launcher_offline">
|
||||
<application
|
||||
android:label="keepass2android"
|
||||
android:icon="@mipmap/ic_launcher_offline"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
>
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider" android:authorities="keepass2android.keepass2android_nonet.android-filechooser.localfile" android:exported="false" />
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android_nonet.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">
|
||||
|
||||
@@ -39,6 +39,26 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:hint="@string/hint_username" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/auth_mode_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sftp_auth_mode" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/sftp_auth_mode_spinner"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="-4dp"
|
||||
android:entries="@array/sftp_auth_modes" />
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/sftp_password"
|
||||
@@ -48,6 +68,11 @@
|
||||
android:singleLine="true"
|
||||
android:hint="@string/hint_pass"
|
||||
android:importantForAccessibility="no"/>
|
||||
<Button android:id="@+id/send_public_key_button"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/send_public_key" />
|
||||
|
||||
|
||||
<TextView android:id="@+id/initial_dir"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
android:icon="@drawable/ic_menu_view"
|
||||
app:showAsAction="ifRoom"
|
||||
/>
|
||||
<item android:id="@+id/menu_delete"
|
||||
android:icon="@drawable/ic_menu_delete"
|
||||
android:title="@string/menu_delete"
|
||||
app:showAsAction="ifRoom"
|
||||
/>
|
||||
<item android:id="@+id/menu_donate"
|
||||
android:title="@string/menu_donate"
|
||||
app:showAsAction="ifRoom"
|
||||
|
||||
@@ -917,6 +917,7 @@ Erstes öffentliches Release</string>
|
||||
<item>Passwort + Challenge-Response</item>
|
||||
<item>Passwort + Challenge-Response-Secret (Recovery-Modus)</item>
|
||||
<item>Passwort + Challenge-Response für Keepass XC</item>
|
||||
<item>Password + Schlüsseldatei + Challenge-Response für Keepass XC</item>
|
||||
</string-array>
|
||||
<string-array name="AcceptAllServerCertificates_options">
|
||||
<item>Fehler bei Zertifikatsvalidierung ignorieren</item>
|
||||
|
||||
@@ -114,8 +114,10 @@
|
||||
<string name="UseFileTransactions_key">UseFileTransactions</string>
|
||||
<string name="LockWhenScreenOff_key">LockWhenScreenOff</string>
|
||||
<string name="LockWhenNavigateBack_key">kp2a_switch_rootedLockWhenNavigateBack</string>
|
||||
<string name="UseKp2aKeyboardInKp2a_key">UseKp2aKeyboardInKp2a</string>
|
||||
|
||||
|
||||
<string name="NoDonateOption_key">NoDonateOption</string>
|
||||
<string name="NoDonateOption_key">NoDonateOption</string>
|
||||
<string name="NoDonationReminder_key">NoDonationReminder</string>
|
||||
|
||||
<string name="UseOfflineCache_key">UseOfflineCache</string>
|
||||
|
||||
@@ -346,6 +346,11 @@
|
||||
<string name="LockWhenNavigateBack_title">Lock when leaving app</string>
|
||||
<string name="LockWhenNavigateBack_summary">Lock the database when leaving the app by pressing the back button.</string>
|
||||
|
||||
<string name="UseKp2aKeyboardInKp2a_title">Use built-in keyboard inside Keepass2Android</string>
|
||||
<string name="UseKp2aKeyboardInKp2a_summary">If you do not trust your standard keyboard provider, check this option to use the built-in keyboard when entering your master password or editing entries.</string>
|
||||
|
||||
|
||||
|
||||
<string name="ActivateSearchViewOnStart_title">Activate search field on start</string>
|
||||
<string name="ActivateSearchViewOnStart_summary">Activates search field in the group view after unlocking or when searching for an entry</string>
|
||||
|
||||
@@ -510,6 +515,8 @@
|
||||
<string name="hint_sftp_port">port</string>
|
||||
<string name="initial_directory">Initial directory (optional):</string>
|
||||
<string name="enter_sftp_login_title">Enter SFTP login data:</string>
|
||||
<string name="sftp_auth_mode">Authentication mode</string>
|
||||
<string name="send_public_key">Send public key...</string>
|
||||
|
||||
<string name="enter_ftp_login_title">Enter FTP login data:</string>
|
||||
|
||||
@@ -1107,7 +1114,12 @@ Initial public release
|
||||
<item>Password + Challenge-Response</item>
|
||||
<item>Password + Challenge-Response secret (recovery mode)</item>
|
||||
<item>Password + Challenge-Response for Keepass XC</item>
|
||||
<item>Password + Key file + Challenge-Response for Keepass XC</item>
|
||||
</string-array>
|
||||
<string-array name="sftp_auth_modes">
|
||||
<item>Password</item>
|
||||
<item>Private/Public key</item>
|
||||
</string-array>
|
||||
<string-array name="AcceptAllServerCertificates_options">
|
||||
<item>Ignore certificate validation failures</item>
|
||||
<item>Warn when validation fails</item>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
@@ -200,6 +200,14 @@
|
||||
android:title="@string/ClearPasswordOnLeave_title"
|
||||
android:key="@string/ClearPasswordOnLeave_key" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
android:summary="@string/UseKp2aKeyboardInKp2a_summary"
|
||||
android:defaultValue="false"
|
||||
android:title="@string/UseKp2aKeyboardInKp2a_title"
|
||||
android:key="@string/UseKp2aKeyboardInKp2a_key" />
|
||||
|
||||
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen
|
||||
|
||||
@@ -586,7 +586,7 @@ namespace keepass2android
|
||||
new DropboxAppFolderFileStorage(Application.Context, this),
|
||||
new GoogleDriveFileStorage(Application.Context, this),
|
||||
new OneDriveFileStorage(Application.Context, this),
|
||||
new SftpFileStorage(this),
|
||||
new SftpFileStorage(Application.Context, this),
|
||||
new NetFtpFileStorage(Application.Context, this),
|
||||
new WebDavFileStorage(this),
|
||||
new PCloudFileStorage(Application.Context, this),
|
||||
|
||||
@@ -828,6 +828,10 @@
|
||||
<Folder Include="SupportLib\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AdalBindings\AdalBindings.csproj">
|
||||
<Project>{0b109c0e-0514-4340-8779-5bd6a0dde84e}</Project>
|
||||
<Name>AdalBindings</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
|
||||
<Project>{48574278-4779-4B3A-A9E4-9CF1BC285D0B}</Project>
|
||||
<Name>JavaFileStorageBindings</Name>
|
||||
@@ -1869,6 +1873,9 @@
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\vdots_bright.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\xml\network_security_config.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
|
||||
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
|
||||
@@ -1917,4 +1924,4 @@
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Animated.Vector.Drawable.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Animated.Vector.Drawable.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.v7.AppCompat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v7.AppCompat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v7.AppCompat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v7.AppCompat.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Design.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Design.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Design.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Design.targets')" />
|
||||
</Project>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user