diff --git a/.gitignore b/.gitignore index af8e3100..42b39152 100644 --- a/.gitignore +++ b/.gitignore @@ -153,3 +153,4 @@ intermediates /src/java/Kp2aAccServiceLib/app/app.iml /src/java/Kp2aAccServiceLib/gradle adbprompt.ps1 +/src/java/KP2ASoftkeyboard_AS/build/android-profile/*.rawproto diff --git a/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj b/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj index 3fe01d37..3956876e 100644 --- a/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj +++ b/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj @@ -10,7 +10,7 @@ AndroidFileChooserBinding AndroidFileChooserBinding 512 - v6.0 + v8.0 True diff --git a/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj b/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj index 65d58114..7433f4f8 100644 --- a/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj +++ b/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj @@ -11,7 +11,7 @@ JavaFileStorageBindings 512 True - v6.0 + v8.0 true diff --git a/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj b/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj index a0ed90dd..3ff0ddff 100644 --- a/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj +++ b/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj @@ -10,7 +10,7 @@ KP2AKdbLibraryBinding KP2AKdbLibraryBinding 512 - v6.0 + v8.0 True diff --git a/src/KeePass.sln b/src/KeePass.sln index 4c59d566..dc4bfbc0 100644 --- a/src/KeePass.sln +++ b/src/KeePass.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2009 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}" EndProject @@ -27,6 +27,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.FtpClient.Androi EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aAutofillBinding", "Kp2aAutofillBinding\Kp2aAutofillBinding.csproj", "{39D433EC-253C-44D8-89A0-85C06A41FB8C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aAutofillLib", "Kp2aAutofillLib\Kp2aAutofillLib.csproj", "{612D3DD7-995B-4484-8D40-1607889EF0B8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutofillTestApp", "AutofillTestApp\AutofillTestApp.csproj", "{C75CFA4A-F969-4E27-B9AC-A73706B10E39}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -283,10 +289,97 @@ 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 + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Win32.ActiveCfg = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|Win32.Build.0 = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|x64.ActiveCfg = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Debug|x64.Build.0 = Debug|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Any CPU.Build.0 = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Win32.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|Win32.Build.0 = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|x64.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.Release|x64.Build.0 = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {39D433EC-253C-44D8-89A0-85C06A41FB8C}.ReleaseNoNet|x64.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Win32.ActiveCfg = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|Win32.Build.0 = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|x64.ActiveCfg = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Debug|x64.Build.0 = Debug|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Any CPU.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Win32.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|Win32.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|x64.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.Release|x64.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {612D3DD7-995B-4484-8D40-1607889EF0B8}.ReleaseNoNet|x64.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Win32.ActiveCfg = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Win32.Build.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|Win32.Deploy.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|x64.ActiveCfg = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|x64.Build.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Debug|x64.Deploy.0 = Debug|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Any CPU.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Any CPU.Deploy.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Win32.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Win32.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|Win32.Deploy.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|x64.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|x64.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.Release|x64.Deploy.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Any CPU.Deploy.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|Win32.Deploy.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|x64.Build.0 = Release|Any CPU + {C75CFA4A-F969-4E27-B9AC-A73706B10E39}.ReleaseNoNet|x64.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2B48EDA2-ABCE-4DB5-A609-DFDF5FAAE767} + EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 $0.DotNetNamingPolicy = $1 diff --git a/src/KeePassLib2Android/KeePassLib2Android.csproj b/src/KeePassLib2Android/KeePassLib2Android.csproj index abda7528..d3029e5f 100644 --- a/src/KeePassLib2Android/KeePassLib2Android.csproj +++ b/src/KeePassLib2Android/KeePassLib2Android.csproj @@ -12,7 +12,7 @@ Resources\Resource.designer.cs Resource KeePassLib2Android - v6.0 + v8.0 True 8482b288 diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj index 50b23c77..c3b7bb60 100644 --- a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj +++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj @@ -12,7 +12,7 @@ 512 Resources\Resource.Designer.cs Off - v6.0 + v8.0 true 06ffb71c diff --git a/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj b/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj index 8d8c5fae..df9c7b3b 100644 --- a/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj +++ b/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj @@ -11,7 +11,7 @@ Resources Kp2aKeyboardBinding True - v6.0 + v8.0 True diff --git a/src/PluginSdkBinding/PluginSdkBinding.csproj b/src/PluginSdkBinding/PluginSdkBinding.csproj index 1dc53f91..ad38386a 100644 --- a/src/PluginSdkBinding/PluginSdkBinding.csproj +++ b/src/PluginSdkBinding/PluginSdkBinding.csproj @@ -11,7 +11,7 @@ PluginSdkBinding 512 True - v6.0 + v8.0 true @@ -53,8 +53,8 @@ - - Jars\app-debug.aar + + Jars\Keepass2AndroidPluginSDK2-debug.aar diff --git a/src/SamsungPass b/src/SamsungPass index 95bc88e1..53d6fee0 160000 --- a/src/SamsungPass +++ b/src/SamsungPass @@ -1 +1 @@ -Subproject commit 95bc88e1826f64ccb9fb7e68d7f77edb12ac73ef +Subproject commit 53d6fee0e227aa10b37649836fb8676d842180a5 diff --git a/src/TwofishCipher/TwofishCipher.csproj b/src/TwofishCipher/TwofishCipher.csproj index 48337a23..2368da5f 100644 --- a/src/TwofishCipher/TwofishCipher.csproj +++ b/src/TwofishCipher/TwofishCipher.csproj @@ -13,7 +13,7 @@ Resources\Resource.Designer.cs Off True - v6.0 + v8.0 true diff --git a/src/ZlibAndroid/ZlibAndroid.csproj b/src/ZlibAndroid/ZlibAndroid.csproj index d2238c67..76403f80 100644 --- a/src/ZlibAndroid/ZlibAndroid.csproj +++ b/src/ZlibAndroid/ZlibAndroid.csproj @@ -13,7 +13,7 @@ Assets True ZlibAndroid - v6.0 + v8.0 true diff --git a/src/java/JavaFileStorageTest-AS/build.gradle b/src/java/JavaFileStorageTest-AS/build.gradle index dc21c09e..2189cb68 100644 --- a/src/java/JavaFileStorageTest-AS/build.gradle +++ b/src/java/JavaFileStorageTest-AS/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.2' + classpath 'com.android.tools.build:gradle:3.0.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/src/java/JavaFileStorageTest-AS/gradle/wrapper/gradle-wrapper.properties b/src/java/JavaFileStorageTest-AS/gradle/wrapper/gradle-wrapper.properties index 1ef1f1f2..10b45347 100644 --- a/src/java/JavaFileStorageTest-AS/gradle/wrapper/gradle-wrapper.properties +++ b/src/java/JavaFileStorageTest-AS/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon May 22 10:43:15 CEST 2017 +#Mon Dec 18 11:13:13 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip diff --git a/src/java/Keepass2AndroidPluginSDK2/app/build.gradle b/src/java/Keepass2AndroidPluginSDK2/app/build.gradle index c6a22a32..1e620b4c 100644 --- a/src/java/Keepass2AndroidPluginSDK2/app/build.gradle +++ b/src/java/Keepass2AndroidPluginSDK2/app/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' android { compileSdkVersion 'Google Inc.:Google APIs:23' - buildToolsVersion '23.0.1' + buildToolsVersion '26.0.2' defaultConfig { minSdkVersion 8 diff --git a/src/java/Keepass2AndroidPluginSDK2/app/src/main/AndroidManifest.xml b/src/java/Keepass2AndroidPluginSDK2/app/src/main/AndroidManifest.xml index 91aef12e..1a0bef65 100644 --- a/src/java/Keepass2AndroidPluginSDK2/app/src/main/AndroidManifest.xml +++ b/src/java/Keepass2AndroidPluginSDK2/app/src/main/AndroidManifest.xml @@ -10,7 +10,6 @@ diff --git a/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-hdpi/ic_launcher.png b/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-hdpi/ic_launcher.png deleted file mode 100644 index 96a442e5..00000000 Binary files a/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-mdpi/ic_launcher.png b/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-mdpi/ic_launcher.png deleted file mode 100644 index 359047df..00000000 Binary files a/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-xhdpi/ic_launcher.png b/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-xhdpi/ic_launcher.png deleted file mode 100644 index 71c6d760..00000000 Binary files a/src/java/Keepass2AndroidPluginSDK2/app/src/main/res/drawable-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/java/Keepass2AndroidPluginSDK2/build.gradle b/src/java/Keepass2AndroidPluginSDK2/build.gradle index 88d246d4..4f430187 100644 --- a/src/java/Keepass2AndroidPluginSDK2/build.gradle +++ b/src/java/Keepass2AndroidPluginSDK2/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.2.3' + classpath 'com.android.tools.build:gradle:2.2.1' } } diff --git a/src/java/Keepass2AndroidPluginSDK2/gradle/wrapper/gradle-wrapper.properties b/src/java/Keepass2AndroidPluginSDK2/gradle/wrapper/gradle-wrapper.properties index 0c71e760..76a0a412 100644 --- a/src/java/Keepass2AndroidPluginSDK2/gradle/wrapper/gradle-wrapper.properties +++ b/src/java/Keepass2AndroidPluginSDK2/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Mon Dec 18 11:08:40 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml index 4300cd26..97491d7d 100644 --- a/src/keepass2android/Resources/values/strings.xml +++ b/src/keepass2android/Resources/values/strings.xml @@ -1030,4 +1030,7 @@ Initial public release Make sure this works on your system and consider using the built-in keyboard if not. Description provided by the plugin: + Fill with Keepass2Android + Could not associate web domain %1$s with app %2$s + diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj index c9228c12..bbd12639 100644 --- a/src/keepass2android/keepass2android.csproj +++ b/src/keepass2android/keepass2android.csproj @@ -15,10 +15,10 @@ keepass2android OnLoad Properties\AndroidManifest.xml - v6.0 + v8.0 1G - true + false 9e78b013 @@ -41,10 +41,12 @@ armeabi,armeabi-v7a,x86 false SdkOnly - False + false False false true + false + false full @@ -185,6 +187,16 @@ + + + + + + + + + + @@ -1723,6 +1735,12 @@ + + + + + + diff --git a/src/keepass2android/services/AutofillBase/AutofillFieldMetadata.cs b/src/keepass2android/services/AutofillBase/AutofillFieldMetadata.cs new file mode 100644 index 00000000..0ba9593c --- /dev/null +++ b/src/keepass2android/services/AutofillBase/AutofillFieldMetadata.cs @@ -0,0 +1,101 @@ +using System; +using Android.App.Assist; +using Android.Service.Autofill; +using Android.Views; +using Android.Views.Autofill; + +namespace keepass2android.services.AutofillBase +{ + /// + /// A stripped down version of a {@link ViewNode} that contains only autofill-relevant metadata. It + /// also contains a {@code mSaveType} flag that is calculated based on the {@link ViewNode}]'s + /// autofill hints. + /// + public class AutofillFieldMetadata + { + public SaveDataType SaveType { get; set; } + + public string[] AutofillHints { get; set; } + + public AutofillId AutofillId { get; } + public AutofillType AutofillType { get; } + string[] AutofillOptions { get; } + public bool Focused { get; } + + public AutofillFieldMetadata(AssistStructure.ViewNode view) + { + AutofillId = view.AutofillId; + AutofillType = view.AutofillType; + AutofillOptions = view.GetAutofillOptions(); + Focused = view.IsFocused; + //TODO port and use AutoFillHints + SetHints(AutofillHelper.FilterForSupportedHints(view.GetAutofillHints())); + } + + void SetHints(string[] value) + { + AutofillHints = value; + UpdateSaveTypeFromHints(); + } + + /// + /// When the ViewNode is a list that the user needs to choose a string from (i.e. a + /// spinner), this is called to return the index of a specific item in the list. + /// + /// The autofill option index. + /// Value. + public int GetAutofillOptionIndex(String value) + { + for (int i = 0; i < AutofillOptions.Length; i++) + { + if (AutofillOptions[i].Equals(value)) + { + return i; + } + } + return -1; + } + + void UpdateSaveTypeFromHints() + { + SaveType = 0; + if (AutofillHints == null) + { + return; + } + foreach (var hint in AutofillHints) + { + switch (hint) + { + case View.AutofillHintCreditCardExpirationDate: + case View.AutofillHintCreditCardExpirationDay: + case View.AutofillHintCreditCardExpirationMonth: + case View.AutofillHintCreditCardExpirationYear: + case View.AutofillHintCreditCardNumber: + case View.AutofillHintCreditCardSecurityCode: + SaveType |= SaveDataType.CreditCard; + break; + case View.AutofillHintEmailAddress: + SaveType |= SaveDataType.EmailAddress; + break; + case View.AutofillHintPhone: + case View.AutofillHintName: + SaveType |= SaveDataType.Generic; + break; + case View.AutofillHintPassword: + SaveType |= SaveDataType.Password; + SaveType &= ~SaveDataType.EmailAddress; + SaveType &= ~SaveDataType.Username; + break; + case View.AutofillHintPostalAddress: + case View.AutofillHintPostalCode: + SaveType |= SaveDataType.Address; + break; + case View.AutofillHintUsername: + SaveType |= SaveDataType.Username; + break; + } + } + } + } +} diff --git a/src/keepass2android/services/AutofillBase/AutofillFieldMetadataCollection.cs b/src/keepass2android/services/AutofillBase/AutofillFieldMetadataCollection.cs new file mode 100644 index 00000000..96ac5b7f --- /dev/null +++ b/src/keepass2android/services/AutofillBase/AutofillFieldMetadataCollection.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using Android.Service.Autofill; +using Android.Views.Autofill; + +namespace keepass2android.services.AutofillBase +{ + /// + /// Data structure that stores a collection of AutofillFieldMetadatas. Contains all of the + /// client's View hierarchy autofill-relevant metadata. + /// + public class AutofillFieldMetadataCollection + { + List AutofillIds = new List(); + Dictionary> AutofillHintsToFieldsMap = new Dictionary>(); + public List AllAutofillHints { get; } + public List FocusedAutofillHints { get; } + int Size = 0; + public SaveDataType SaveType { get; set; } + + public AutofillFieldMetadataCollection() + { + SaveType = 0; + FocusedAutofillHints = new List(); + AllAutofillHints = new List(); + } + + public void Add(keepass2android.services.AutofillBase.AutofillFieldMetadata autofillFieldMetadata) + { + SaveType |= autofillFieldMetadata.SaveType; + Size++; + AutofillIds.Add(autofillFieldMetadata.AutofillId); + var hintsList = autofillFieldMetadata.AutofillHints; + AllAutofillHints.AddRange(hintsList); + if (autofillFieldMetadata.Focused) + { + FocusedAutofillHints.AddRange(hintsList); + } + foreach (var hint in autofillFieldMetadata.AutofillHints) + { + if (!AutofillHintsToFieldsMap.ContainsKey(hint)) + { + AutofillHintsToFieldsMap.Add(hint, new List()); + } + AutofillHintsToFieldsMap[hint].Add(autofillFieldMetadata); + } + } + + public AutofillId[] GetAutofillIds() + { + return AutofillIds.ToArray(); + } + + public List GetFieldsForHint(String hint) + { + return AutofillHintsToFieldsMap[hint]; + } + + + } +} diff --git a/src/keepass2android/services/AutofillBase/AutofillHelper.cs b/src/keepass2android/services/AutofillBase/AutofillHelper.cs new file mode 100644 index 00000000..22005b33 --- /dev/null +++ b/src/keepass2android/services/AutofillBase/AutofillHelper.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using Android.Content; +using Android.Service.Autofill; +using Android.Util; +using Android.Views; +using Android.Widget; +using FilledAutofillFieldCollection = keepass2android.services.AutofillBase.model.FilledAutofillFieldCollection; + +//TODO compare port +namespace keepass2android.services.AutofillBase +{ + /// + /// This is a class containing helper methods for building Autofill Datasets and Responses. + /// + public class AutofillHelper + { + /// + /// Wraps autofill data in a LoginCredential Dataset object which can then be sent back to the + /// client View. + /// + /// The dataset. + /// Context. + /// Autofill fields. + /// Filled autofill field collection. + /// If set to true dataset auth. + public static Dataset NewDataset(Context context, + keepass2android.services.AutofillBase.AutofillFieldMetadataCollection autofillFields, FilledAutofillFieldCollection filledAutofillFieldCollection, bool datasetAuth, IAutofillIntentBuilder intentBuilder) + { + var datasetName = filledAutofillFieldCollection.DatasetName; + if (datasetName != null) + { + Dataset.Builder datasetBuilder; + if (datasetAuth) + { + datasetBuilder = new Dataset.Builder + (NewRemoteViews(context.PackageName, datasetName, + Resource.Drawable.ic_launcher)); + IntentSender sender = intentBuilder.GetAuthIntentSenderForDataset(context, datasetName); + datasetBuilder.SetAuthentication(sender); + } + else + { + datasetBuilder = new Dataset.Builder + (NewRemoteViews(context.PackageName, datasetName, + Resource.Drawable.ic_launcher)); + } + var setValueAtLeastOnce = filledAutofillFieldCollection.ApplyToFields(autofillFields, datasetBuilder); + if (setValueAtLeastOnce) + { + return datasetBuilder.Build(); + } + } + return null; + } + + public static RemoteViews NewRemoteViews(string packageName, string remoteViewsText,int drawableId) + { + RemoteViews presentation = new RemoteViews(packageName, Resource.Layout.autofill_service_list_item); + presentation.SetTextViewText(Resource.Id.text, remoteViewsText); + presentation.SetImageViewResource(Resource.Id.icon, drawableId); + return presentation; + } + + /// + /// Wraps autofill data in a Response object (essentially a series of Datasets) which can then + /// be sent back to the client View. + /// + /// The response. + /// Context. + /// If set to true dataset auth. + /// Autofill fields. + /// Client form data map. + /// + public static FillResponse NewResponse(Context context, bool datasetAuth, keepass2android.services.AutofillBase.AutofillFieldMetadataCollection autofillFields, Dictionary clientFormDataMap, IAutofillIntentBuilder intentBuilder) + { + var responseBuilder = new FillResponse.Builder(); + if (clientFormDataMap != null) + { + var datasetNames = clientFormDataMap.Keys; + foreach (var datasetName in datasetNames) + { + var filledAutofillFieldCollection = clientFormDataMap[datasetName]; + if (filledAutofillFieldCollection != null) + { + var dataset = NewDataset(context, autofillFields, filledAutofillFieldCollection, datasetAuth, intentBuilder); + if (dataset != null) + { + responseBuilder.AddDataset(dataset); + } + } + } + } + if (autofillFields.SaveType != 0) + { + var autofillIds = autofillFields.GetAutofillIds(); + responseBuilder.SetSaveInfo + (new SaveInfo.Builder(autofillFields.SaveType, autofillIds).Build()); + return responseBuilder.Build(); + } + else + { + Log.Debug(CommonUtil.Tag, "These fields are not meant to be saved by autofill."); + return null; + } + } + + public static string[] FilterForSupportedHints(string[] hints) + { + var filteredHints = new string[hints.Length]; + int i = 0; + foreach (var hint in hints) + { + if (IsValidHint(hint)) + { + filteredHints[i++] = hint; + } + else + { + Log.Debug(CommonUtil.Tag, "Invalid autofill hint: " + hint); + } + } + var finalFilteredHints = new string[i]; + Array.Copy(filteredHints, 0, finalFilteredHints, 0, i); + return finalFilteredHints; + } + + public static bool IsValidHint(String hint) + { + switch (hint) + { + case View.AutofillHintCreditCardExpirationDate: + case View.AutofillHintCreditCardExpirationDay: + case View.AutofillHintCreditCardExpirationMonth: + case View.AutofillHintCreditCardExpirationYear: + case View.AutofillHintCreditCardNumber: + case View.AutofillHintCreditCardSecurityCode: + case View.AutofillHintEmailAddress: + case View.AutofillHintPhone: + case View.AutofillHintName: + case View.AutofillHintPassword: + case View.AutofillHintPostalAddress: + case View.AutofillHintPostalCode: + case View.AutofillHintUsername: + return true; + default: + return false; + } + } + } +} diff --git a/src/keepass2android/services/AutofillBase/AutofillServiceBase.cs b/src/keepass2android/services/AutofillBase/AutofillServiceBase.cs new file mode 100644 index 00000000..9050110b --- /dev/null +++ b/src/keepass2android/services/AutofillBase/AutofillServiceBase.cs @@ -0,0 +1,101 @@ +using System; +using Android.Content; +using Android.OS; +using Android.Runtime; +using Android.Service.Autofill; +using Android.Util; + +namespace keepass2android.services.AutofillBase +{ + public interface IAutofillIntentBuilder + { + IntentSender GetAuthIntentSenderForResponse(Context context); + IntentSender GetAuthIntentSenderForDataset(Context context, string dataset); + } + + public abstract class AutofillServiceBase: AutofillService, IAutofillIntentBuilder + { + public AutofillServiceBase() + { + + } + + public AutofillServiceBase(IntPtr javaReference, JniHandleOwnership transfer) + : base(javaReference, transfer) + { + } + + + public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) + { + Log.Debug(CommonUtil.Tag, "onFillRequest"); + var structure = request.FillContexts[request.FillContexts.Count - 1].Structure; + + //TODO package signature verification? + + var clientState = request.ClientState; + Log.Debug(CommonUtil.Tag, "onFillRequest(): data=" + CommonUtil.BundleToString(clientState)); + + + cancellationSignal.CancelEvent += (sender, e) => { + Log.Warn(CommonUtil.Tag, "Cancel autofill not implemented yet."); + }; + // Parse AutoFill data in Activity + var parser = new StructureParser(this, structure); + try + { + parser.ParseForFill(); + } + catch (Java.Lang.SecurityException e) + { + Log.Warn(CommonUtil.Tag, "Security exception handling request"); + callback.OnFailure(e.Message); + return; + } + + keepass2android.services.AutofillBase.AutofillFieldMetadataCollection autofillFields = parser.AutofillFields; + var responseBuilder = new FillResponse.Builder(); + // Check user's settings for authenticating Responses and Datasets. + bool responseAuth = true; + var autofillIds = autofillFields.GetAutofillIds(); + if (responseAuth && autofillIds.Length != 0) + { + // If the entire Autofill Response is authenticated, AuthActivity is used + // to generate Response. + var sender = GetAuthIntentSenderForResponse(this); + var presentation = keepass2android.services.AutofillBase.AutofillHelper + .NewRemoteViews(PackageName, GetString(Resource.String.autofill_sign_in_prompt), + Resource.Drawable.ic_launcher); + responseBuilder + .SetAuthentication(autofillIds, sender, presentation); + callback.OnSuccess(responseBuilder.Build()); + } + else + { + var datasetAuth = true; + var response = keepass2android.services.AutofillBase.AutofillHelper.NewResponse(this, datasetAuth, autofillFields, null, this); + callback.OnSuccess(response); + } + } + + public override void OnSaveRequest(SaveRequest request, SaveCallback callback) + { + //TODO implement + callback.OnFailure("not implemented"); + } + + + public override void OnConnected() + { + Log.Debug(CommonUtil.Tag, "onConnected"); + } + + public override void OnDisconnected() + { + Log.Debug(CommonUtil.Tag, "onDisconnected"); + } + + public abstract IntentSender GetAuthIntentSenderForResponse(Context context); + public abstract IntentSender GetAuthIntentSenderForDataset(Context context, string dataset); + } +} diff --git a/src/keepass2android/services/AutofillBase/CommonUtil.cs b/src/keepass2android/services/AutofillBase/CommonUtil.cs new file mode 100644 index 00000000..c6305eea --- /dev/null +++ b/src/keepass2android/services/AutofillBase/CommonUtil.cs @@ -0,0 +1,47 @@ +using System; +using System.Text; +using Android.OS; +using Java.Util; + +namespace keepass2android.services.AutofillBase +{ + public class CommonUtil + { + public const string Tag = "Kp2aAutofill"; + public const bool Debug = true; + public const string EXTRA_DATASET_NAME = "dataset_name"; + public const string EXTRA_FOR_RESPONSE = "for_response"; + + static void BundleToString(StringBuilder builder, Bundle data) + { + var keySet = data.KeySet(); + builder.Append("[Bundle with ").Append(keySet.Count).Append(" keys:"); + foreach (var key in keySet) + { + builder.Append(' ').Append(key).Append('='); + Object value = data.Get(key); + if (value is Bundle) + { + BundleToString(builder, (Bundle)value); + } + else + { + builder.Append((value is Object[]) + ? Arrays.ToString((bool[])value) : value); + } + } + builder.Append(']'); + } + + public static string BundleToString(Bundle data) + { + if (data == null) + { + return "N/A"; + } + StringBuilder builder = new StringBuilder(); + BundleToString(builder, data); + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/src/keepass2android/services/AutofillBase/Kp2aDigitalAssetLinksDataSource.cs b/src/keepass2android/services/AutofillBase/Kp2aDigitalAssetLinksDataSource.cs new file mode 100644 index 00000000..511edada --- /dev/null +++ b/src/keepass2android/services/AutofillBase/Kp2aDigitalAssetLinksDataSource.cs @@ -0,0 +1,30 @@ +using Android.Content; + +namespace keepass2android.services.AutofillBase +{ + + internal class Kp2aDigitalAssetLinksDataSource + { + private static Kp2aDigitalAssetLinksDataSource instance; + + private Kp2aDigitalAssetLinksDataSource() { } + + public static Kp2aDigitalAssetLinksDataSource Instance + { + get + { + if (instance == null) + { + instance = new Kp2aDigitalAssetLinksDataSource(); + } + return instance; + } + } + + public bool IsValid(Context context, string webDomain, string packageName) + { + //TODO implement + return true; + } + } +} \ No newline at end of file diff --git a/src/keepass2android/services/AutofillBase/StructureParser.cs b/src/keepass2android/services/AutofillBase/StructureParser.cs new file mode 100644 index 00000000..90444137 --- /dev/null +++ b/src/keepass2android/services/AutofillBase/StructureParser.cs @@ -0,0 +1,115 @@ +using System; +using Android.App.Assist; +using Android.Content; +using Android.Util; +using FilledAutofillFieldCollection = keepass2android.services.AutofillBase.model.FilledAutofillFieldCollection; + +namespace keepass2android.services.AutofillBase +{ + /// + /// Parser for an AssistStructure object. This is invoked when the Autofill Service receives an + /// AssistStructure from the client Activity, representing its View hierarchy. In this sample, it + /// parses the hierarchy and collects autofill metadata from {@link ViewNode}s along the way. + /// + public sealed class StructureParser + { + public Context mContext { get; } + public keepass2android.services.AutofillBase.AutofillFieldMetadataCollection AutofillFields { get; set; } + AssistStructure Structure; + public FilledAutofillFieldCollection ClientFormData { get; set; } + + public StructureParser(Context context, AssistStructure structure) + { + mContext = context; + Structure = structure; + AutofillFields = new keepass2android.services.AutofillBase.AutofillFieldMetadataCollection(); + } + + public void ParseForFill() + { + Parse(true); + } + + public void ParseForSave() + { + Parse(false); + } + + /// + /// Traverse AssistStructure and add ViewNode metadata to a flat list. + /// + /// The parse. + /// If set to true for fill. + void Parse(bool forFill) + { + Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, "Parsing structure for " + Structure.ActivityComponent); + var nodes = Structure.WindowNodeCount; + ClientFormData = new FilledAutofillFieldCollection(); + String webDomain = null; + for (int i = 0; i < nodes; i++) + { + var node = Structure.GetWindowNodeAt(i); + var view = node.RootViewNode; + ParseLocked(forFill, view, ref webDomain); + } + if (!string.IsNullOrEmpty(webDomain)) + { + String packageName = Structure.ActivityComponent.PackageName; + bool valid = Kp2aDigitalAssetLinksDataSource.Instance.IsValid(mContext, webDomain, packageName); + if (!valid) + { + throw new Java.Lang.SecurityException(mContext.GetString( + Resource.String.invalid_link_association, webDomain, packageName)); + } + Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, $"Domain {webDomain} is valid for {packageName}"); + } + else + { + Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, "no web domain"); + } + } + + void ParseLocked(bool forFill, AssistStructure.ViewNode viewNode, ref string validWebdomain) + { + String webDomain = viewNode.WebDomain; + if (webDomain != null) + { + Log.Debug(keepass2android.services.AutofillBase.CommonUtil.Tag, $"child web domain: {webDomain}"); + if (!string.IsNullOrEmpty(validWebdomain)) + { + if (webDomain == validWebdomain) + { + throw new Java.Lang.SecurityException($"Found multiple web domains: valid= {validWebdomain}, child={webDomain}"); + } + } + else + { + validWebdomain = webDomain; + } + } + + if (viewNode.GetAutofillHints() != null && viewNode.GetAutofillHints().Length > 0) + { + if (forFill) + { + AutofillFields.Add(new keepass2android.services.AutofillBase.AutofillFieldMetadata(viewNode)); + } + else + { + //TODO implement + throw new NotImplementedException("TODO: Port and use AutoFill hints"); + //ClientFormData.Add(new FilledAutofillField(viewNode)); + } + } + var childrenSize = viewNode.ChildCount; + if (childrenSize > 0) + { + for (int i = 0; i < childrenSize; i++) + { + ParseLocked(forFill, viewNode.GetChildAt(i), ref validWebdomain); + } + } + } + + } +} diff --git a/src/keepass2android/services/AutofillBase/model/FilledAutofillField.cs b/src/keepass2android/services/AutofillBase/model/FilledAutofillField.cs new file mode 100644 index 00000000..f135a03e --- /dev/null +++ b/src/keepass2android/services/AutofillBase/model/FilledAutofillField.cs @@ -0,0 +1,84 @@ +using Android.App.Assist; +using Android.Views.Autofill; + +namespace keepass2android.services.AutofillBase.model +{ + /// + /// JSON serializable data class containing the same data as an {@link AutofillValue}. + /// + public class FilledAutofillField + { + public string TextValue { get; set; } + public long? DateValue { get; set; } + public bool? ToggleValue { get; set; } + + /// + /// Does not need to be serialized into persistent storage, so it's not exposed. + /// + /// The autofill hints. + public string[] AutofillHints { get; set; } + + public FilledAutofillField() + {} + + public FilledAutofillField(AssistStructure.ViewNode viewNode) + { + AutofillHints = AutofillHelper.FilterForSupportedHints(viewNode.GetAutofillHints()); + + //TODO port updated FilledAutofillField? + AutofillValue autofillValue = viewNode.AutofillValue; + if (autofillValue != null) + { + if (autofillValue.IsList) + { + string[] autofillOptions = viewNode.GetAutofillOptions(); + int index = autofillValue.ListValue; + if (autofillOptions != null && autofillOptions.Length > 0) + { + TextValue = autofillOptions[index]; + } + } + else if (autofillValue.IsDate) + { + DateValue = autofillValue.DateValue; + } + else if (autofillValue.IsText) + { + // Using toString of AutofillValue.getTextValue in order to save it to + // SharedPreferences. + TextValue = autofillValue.TextValue; + } + } + } + + public bool IsNull() + { + return TextValue == null && DateValue == null && ToggleValue == null; + } + + public override bool Equals(object obj) + { + if (this == obj) return true; + if (obj == null || GetType() != obj.GetType()) return false; + + FilledAutofillField that = (FilledAutofillField)obj; + + if (TextValue != null ? !TextValue.Equals(that.TextValue) : that.TextValue != null) + return false; + if (DateValue != null ? !DateValue.Equals(that.DateValue) : that.DateValue != null) + return false; + return ToggleValue != null ? ToggleValue.Equals(that.ToggleValue) : that.ToggleValue == null; + } + + public override int GetHashCode() + { + unchecked + { + var result = TextValue != null ? TextValue.GetHashCode() : 0; + result = 31 * result + (DateValue != null ? DateValue.GetHashCode() : 0); + result = 31 * result + (ToggleValue != null ? ToggleValue.GetHashCode() : 0); + return result; + } + } + } +} diff --git a/src/keepass2android/services/AutofillBase/model/FilledAutofillFieldCollection.cs b/src/keepass2android/services/AutofillBase/model/FilledAutofillFieldCollection.cs new file mode 100644 index 00000000..320ce1ce --- /dev/null +++ b/src/keepass2android/services/AutofillBase/model/FilledAutofillFieldCollection.cs @@ -0,0 +1,137 @@ +using System.Collections.Generic; +using Android.Service.Autofill; +using Android.Util; +using Android.Views; +using Android.Views.Autofill; + +namespace keepass2android.services.AutofillBase.model +{ + /// + /// FilledAutofillFieldCollection is the model that holds all of the data on a client app's page, + /// plus the dataset name associated with it. + /// + public class FilledAutofillFieldCollection + { + public Dictionary HintMap { get; set; } + public string DatasetName { get; set; } + + public FilledAutofillFieldCollection(Dictionary hintMap, string datasetName = "") + { + HintMap = hintMap; + DatasetName = datasetName; + } + + public FilledAutofillFieldCollection() : this(new Dictionary()) + {} + + /// + /// Adds a filledAutofillField to the collection, indexed by all of its hints. + /// + /// The add. + /// Filled autofill field. + public void Add(keepass2android.services.AutofillBase.model.FilledAutofillField filledAutofillField) + { + string[] autofillHints = filledAutofillField.AutofillHints; + //TODO apply W3C transformation + foreach (string hint in autofillHints) + { + HintMap.Add(hint, filledAutofillField); + } + } + + /// + /// Populates a Dataset.Builder with appropriate values for each AutofillId + /// in a AutofillFieldMetadataCollection. + /// + /// In other words, it constructs an autofill Dataset.Builder + /// by applying saved values (from this FilledAutofillFieldCollection) + /// to Views specified in a AutofillFieldMetadataCollection, which represents the current + /// page the user is on. + /// + /// true, if to fields was applyed, false otherwise. + /// Autofill field metadata collection. + /// Dataset builder. + public bool ApplyToFields(AutofillFieldMetadataCollection autofillFieldMetadataCollection, + Dataset.Builder datasetBuilder) + { + bool setValueAtLeastOnce = false; + List allHints = autofillFieldMetadataCollection.AllAutofillHints; + for (int hintIndex = 0; hintIndex < allHints.Count; hintIndex++) + { + string hint = allHints[hintIndex]; + List fillableAutofillFields = autofillFieldMetadataCollection.GetFieldsForHint(hint); + if (fillableAutofillFields == null) + { + continue; + } + for (int autofillFieldIndex = 0; autofillFieldIndex < fillableAutofillFields.Count; autofillFieldIndex++) + { + keepass2android.services.AutofillBase.model.FilledAutofillField filledAutofillField = HintMap[hint]; + if (filledAutofillField == null) + { + continue; + } + AutofillFieldMetadata autofillFieldMetadata = fillableAutofillFields[autofillFieldIndex]; + var autofillId = autofillFieldMetadata.AutofillId; + var autofillType = autofillFieldMetadata.AutofillType; + switch (autofillType) + { + case AutofillType.List: + var listValue = autofillFieldMetadata.GetAutofillOptionIndex(filledAutofillField.TextValue); + if (listValue != -1) + { + datasetBuilder.SetValue(autofillId, AutofillValue.ForList(listValue)); + setValueAtLeastOnce = true; + } + break; + case AutofillType.Date: + var dateValue = filledAutofillField.DateValue; + datasetBuilder.SetValue(autofillId, AutofillValue.ForDate((long)dateValue)); + setValueAtLeastOnce = true; + break; + case AutofillType.Text: + var textValue = filledAutofillField.TextValue; + if (textValue != null) + { + datasetBuilder.SetValue(autofillId, AutofillValue.ForText(textValue)); + setValueAtLeastOnce = true; + } + break; + case AutofillType.Toggle: + var toggleValue = filledAutofillField.ToggleValue; + if (toggleValue != null) + { + datasetBuilder.SetValue(autofillId, AutofillValue.ForToggle(toggleValue.Value)); + setValueAtLeastOnce = true; + } + break; + default: + Log.Warn(CommonUtil.Tag, "Invalid autofill type - " + autofillType); + break; + } + } + } + return setValueAtLeastOnce; + } + + /// + /// Takes in a list of autofill hints (`autofillHints`), usually associated with a View or set of + /// Views. Returns whether any of the filled fields on the page have at least 1 of these + /// `autofillHint`s. + /// + /// true, if with hints was helpsed, false otherwise. + /// Autofill hints. + public bool HelpsWithHints(List autofillHints) + { + for (int i = 0; i < autofillHints.Count; i++) + { + var autofillHint = autofillHints[i]; + if (HintMap.ContainsKey(autofillHint) && !HintMap[autofillHint].IsNull()) + { + return true; + } + } + return false; + } + } +} diff --git a/src/keepass2android/services/Kp2aAutofillService.cs b/src/keepass2android/services/Kp2aAutofillService.cs new file mode 100644 index 00000000..7cb1cfbf --- /dev/null +++ b/src/keepass2android/services/Kp2aAutofillService.cs @@ -0,0 +1,38 @@ +using System; +using Android; +using Android.App; +using Android.Content; +using Android.Runtime; +using AutofillServiceBase = keepass2android.services.AutofillBase.AutofillServiceBase; + +namespace keepass2android.services +{ + [Service(Label = "Keepass2Android Autofill Service", Permission=Manifest.Permission.BindAutofillService)] + [IntentFilter(new [] {"android.service.autofill.AutofillService"})] + [MetaData("android.autofill", Resource = "@xml/autofillservice")] + [Register("keepass2android.services.Kp2aAutofillService")] + public class Kp2aAutofillService: AutofillServiceBase + { + public Kp2aAutofillService() + { + + } + + public Kp2aAutofillService(IntPtr javaReference, JniHandleOwnership transfer) + : base(javaReference, transfer) + { + } + + public override IntentSender GetAuthIntentSenderForResponse(Context context) + { + Intent intent = new Intent(context, typeof(KeePass)); + return PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.CancelCurrent).IntentSender; + } + + public override IntentSender GetAuthIntentSenderForDataset(Context context, string dataset) + { + //TODO implement + return GetAuthIntentSenderForResponse(context); + } + } +} \ No newline at end of file diff --git a/src/netftpandroid b/src/netftpandroid index 62733d71..040e8bbe 160000 --- a/src/netftpandroid +++ b/src/netftpandroid @@ -1 +1 @@ -Subproject commit 62733d714fec6a2806daced432230998eabca29f +Subproject commit 040e8bbe564bd140203255e11c86c01c2f7c1892