Merge commit 'cc8cea00491016abea0332799e7f85072a076014' into nonet

# Resolved Conflicts:
#	src/KeePass.sln
#	src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
#	src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj
#	src/keepass2android/Properties/AndroidManifest_nonet.xml
#	src/keepass2android/keepass2android.csproj
This commit is contained in:
Philipp Crocoll
2019-10-21 10:42:39 +02:00
756 changed files with 35608 additions and 9656 deletions

9
.gitignore vendored
View File

@@ -160,3 +160,12 @@ src/java/Keepass2AndroidPluginSDK2/build/generated/mockable-Google-Inc.-Google-A
/src/.vs
/src/JavaFileStorageBindings/Jars/JavaFileStorage-release.aar
/src/PluginSdkBinding/Jars/app-debug.aar
/src/java/KP2AKdbLibrary/libs/arm64-v8a/libfinal-key.so
/src/java/KP2AKdbLibrary/libs/x86_64/libfinal-key.so
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/arm64-v8a/libkp2akeyboard_jni.so
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/armeabi-v7a/libkp2akeyboard_jni.so
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/x86/libkp2akeyboard_jni.so
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/x86_64/libkp2akeyboard_jni.so
/src/java/KP2AKdbLibrary/app/build
/src/java/KP2ASoftkeyboard_AS/app/.cxx
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs

3
.gitmodules vendored
View File

@@ -4,3 +4,6 @@
[submodule "src/netftpandroid"]
path = src/netftpandroid
url = https://github.com/PhilippC/netftpandroid.git
[submodule "src/java/argon2/phc-winner-argon2"]
path = src/java/argon2/phc-winner-argon2
url = https://github.com/P-H-C/phc-winner-argon2

View File

@@ -4,3 +4,7 @@ files:
/src/keepass2android/Resources/values-%two_letters_code%/%original_file_name%
translate_attributes: '0'
content_segmentation: '0'
languages_mapping:
two_letters_code:
zh-CN: zh
zh-TW: zh-rTW

View File

@@ -28,14 +28,14 @@ Select "Create new database" from the start screen. Tap the integrated help icon
## Getting passwords into password fields
There are many ways how to enter the passwords from your database in the corresponding fields. By default, the clipboard as well as the KP2A keyboard are activated in the settings:
* The KP2A keyboard is the recommended way because it's safe against clipboard loggers: Whenever you select an entry, the KP2A keyboard notification will appear in the notification bar. Click it to activate the keyboard. (The first time you do this, you are required to enable the keyboard in the system settings. This must be done by the user for Android security reasons.) As soon as it's activated, you can tap a field where you want to enter data from the selected entry. The KP2A keyboard will come up. Click the KP2A key (on the bottom left) to select whether you want to enter Username/password etc. When you're done, click the Keyboard key (next to the KP2A key) to switch back to your favorite keyboard.
* You can enable the Keepass2Android Autofill service in the system's accessibility settings which allows to fill data using Android's accessibility system. This works with many apps including Chrome browser but is not supported for Firefox on Android.
* The clipboard based approach can be used as well: Pull the notification bar down and select "Copy username/password to clipboard". Then long-tap the field where you want to paste the data. A small "paste" button should come up. Note, however, that information in the clipboard can be monitored by all apps on your device.
* You can enable the Keepass2Android Autofill service in the system's Autofill settings (Android 8+) which allows to fill data using Android's accessibility system. This works with many apps including Firefox browser but is not supported for Chrome (when writing this).
* The clipboard based approach can be used as well: Pull the notification bar down and select "Copy username/password to clipboard". Then long-tap the field where you want to paste the data. A small "paste" button should come up. Note, however, that information in the clipboard can be monitored by all apps on your device and clearing the clipboard is not always possible.
These options can be used in different workflows:
### Browser-based workflow
If you are browsing the web and need to enter crendentials for a webpage, a simple and powerful workflow is to use the "Share URL" option from the browser's menu. Then select Keepass2Android (or KP2A Offline). Open your database (if it's not already opened) and select the entry you want to enter (if KP2A did not already select the appropriate entry). Use the built-in keyboard or the clipboard to enter the password.
### Autofill service based workflow
If you have enabled the autofill service and open a (supported) app with a password field, a notification appears in the notification bar. Select this notification to select the appropriate entry. When you return to the app, the password and user field should be filled already.
If you have enabled the autofill service and open a (supported) app with a password field, a dropdown appears. Select "Fill with Keepass2Android" to select the appropriate entry. When you return to the app, the password and user field should be filled already.
### KP2A based workflow for websites
Open KP2A, open your database, select your entry (in this step, the notification bar items should show up already). Now click the URL link of the entry to open a browser window with the website. Use one of the methods described above to enter the credentials.
### KP2A Keyboard based workflow
@@ -70,14 +70,28 @@ Please see the [Advanced usage of the Keepass2Android keyboard](Advanced-usage-o
# FAQ
* Should I use the KP2A keyboard for entering passwords?
## Should I use the KP2A keyboard for entering passwords?
The KP2A keyboard is meant to quickly "paste" or "type" values from your database to any text fields by using the KP2A icon. The QUERTY keyboard is just for convenience (if you just have the KP2A keyboard activated and need to enter a few letters). However, every other (trustworthy) keyboard is ok as well to enter sensitive information: Keyboard's aren't unsafe in Android. Only the clipboard is. Thus, the KP2A keyboard allows to get information out of the database without using the clipboard.
**You can use any keyboard when you enter the main database password**
* Is it safe to store my kdbx file in the cloud?
While it may happen that someone gets access to your kdbx file in the cloud, there is still no need to worry: the purpose of encryption is to protect the data even in case someone gets the kdbx file! As long as you are using a safe master key, you're safe!
## Is it safe to store my kdbx file in the cloud?
While it may happen that someone gets access to your kdbx file in the cloud, there is still no need to worry: the purpose of encryption is to protect the data even in case someone gets the kdbx file! As long as you are using a safe master key, you're safe! [Key files](https://keepass.info/help/base/keys.html#keyfiles) can help with securing the database even more.
* Why is Keepass2Android so big?
## How do I backup the database?
If you have stored your database on the cloud, you might rely on your cloud storage providers backups. Make sure they allow you to revert to older revisions in case the file gets corrupted for some reason.
If you are working with a local database file, make sure you create regular backups. I suggest you have an aumotated mechanism, e.g. with FolderSync (Lite) which can copy local files from your device to other locations, e.g. your PC in a local network. You can also use USB or tools like MyPhoneExploror to transfer data to your PC. Or, you use a removable storage like an SD card which you keep in a safe place after making the backup.
In all cases, you need to verify that your backup is readable! It's even best to test this on another device (e.g. a PC), so you simulate the case that you may lose your phone.
## I can open my database with fingerprint, but don't remember my master password!
It's time for action! As soon as possible, select Settings - Database - Export and choose unencrypted XML (don't put this on the cloud but on a local file). Transfer this file to a PC and import it to a new kdbx file, e.g. with Keepass2. Choose a new master password and make sure you don't forget this password!
## How can I transfer data from one device to another?
* If you are about to get a new Android device, you should make sure you're not losing your passwords in the transition! The first thing you need to make sure is that you can access your .kdbx file (which stores the passwords) on the new device. If it is already stored in the cloud, you only need to make sure you know how to setup the cloud storage on the new device (it might require a password, so make sure you have access to that!).
* If the .kdbx-file is stored locally on the old device, make sure you have an up-to-date backup (see above). You can then transfer that backup copy to the new device. (Note: transferring via USB causes data corruption in some cases, use MyPhoneExplorer or similar tools to be sure this does not happen.)
* If you are securing your password database with a keyfile, also transfer this key file to the new device.
* If you are opening your database with a fingerprint, make sure you also know the master password because fingerprint will not be available immediately on the new device.
## Why is Keepass2Android's apk so big?
Please see [Keepass2Android Apk](Keepass2Android-Apk.md) for more information.
# For developers

View File

@@ -2,7 +2,7 @@ Keepass2Android's apk is pretty big, e.g. when comparing to Keepassdroid. The ma
Here's a list of what is contained in the Keepass2Android 0.9.1 application package:
{{
```
Mono for Android
.net dlls 5.0 MB
Runtime 2.5 MB
@@ -22,4 +22,4 @@ Java/Mono bindings 0.5 MB
rest 0.3 MB
TOTAL 13 MB
}}
```

View File

@@ -1,3 +1,6 @@
<h1 align="center"><img src="/src/keepass2android/Resources/mipmap-xxxhdpi/ic_launcher_online.png" align="center" width="100" alt="Keepass2Android Logo">Keepass2Android</h1>
# What is Keepass2Android?
Keepass2Android is a password manager app. It allows to store and retrieve passwords and other sensitive information in a file called "database". This database is secured with a so-called master password. The master password typically is a strong password and can be complemented with a second factor for additional security.
The password database file can be synchronized across different devices. This works best using one of the built-in cloud storage options, but can also be performed with third-party apps. Keepass2Android is compatible with Keepass 1 and Keepass 2 on Windows and KeepassX on Linux.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View 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>

View File

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

View File

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

View File

@@ -0,0 +1,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")]

View File

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

View File

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

View File

@@ -0,0 +1,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>

View File

@@ -10,8 +10,8 @@
<RootNamespace>AndroidFileChooserBinding</RootNamespace>
<AssemblyName>AndroidFileChooserBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

Binary file not shown.

View File

@@ -10,8 +10,9 @@
<RootNamespace>JavaFileStorageBindings</RootNamespace>
<AssemblyName>JavaFileStorageBindings</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidClassParser>class-parse</AndroidClassParser>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -60,7 +61,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,10 +82,10 @@
</XamarinComponentReference>
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\okhttp-digest-1.7.jar" />
<ProjectReference Include="..\PCloudBindings\PCloudBindings.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\gson-2.3.1.jar" />
<EmbeddedReferenceJar Include="Jars\okhttp-digest-1.7.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\msa-auth-0.8.6\classes-msa-auth.jar" />
@@ -141,13 +141,16 @@
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\jackson-core-2.7.4.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedJar Include="Jars\dropbox-core-sdk-3.0.3.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\okhttp-3.9.0.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\okio-1.13.0.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedJar Include="Jars\dropbox-core-sdk-3.1.1.jar" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\gson-2.8.1.jar" />
</ItemGroup>
</Project>

View File

@@ -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']" />

View File

@@ -10,8 +10,8 @@
<RootNamespace>KP2AKdbLibraryBinding</RootNamespace>
<AssemblyName>KP2AKdbLibraryBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -52,10 +52,11 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<LibraryProjectZip Include="..\java\KP2AKdbLibrary\app\build\outputs\aar\app-debug.aar">
<Link>Jars\app-debug.aar</Link>
</LibraryProjectZip>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />
<EmbeddedNativeLibrary Include="libs\armeabi-v7a\libfinal-key.so" />
<EmbeddedNativeLibrary Include="libs\armeabi\libfinal-key.so" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Transforms\Metadata.xml">
@@ -65,9 +66,7 @@
<TransformFile Include="Transforms\EnumMethods.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedJar Include="..\java\KP2AKdbLibrary\bin\kp2akdblibrary.jar">
<Link>Jars\kp2akdblibrary.jar</Link>
</EmbeddedJar>
<Folder Include="libs\" />
</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.

View File

@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZlibAndroid", "ZlibAndroid\
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}") = "PCloudBindings", "PCloudBindings\PCloudBindings.csproj", "{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -147,6 +149,30 @@ Global
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Win32.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|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}.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 = 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
@@ -243,6 +269,30 @@ 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
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -21,7 +21,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using keepass2android;
#if KeePassUAP
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
@@ -144,6 +144,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
ulong uNumRounds)
{
Kp2aLog.Log("Warning: transforming key managed. Expect this to be slow!");
#if KeePassUAP
KeyParameter kp = new KeyParameter(pbKeySeed32);
AesEngine aes = new AesEngine();

View File

@@ -20,6 +20,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace KeePassLib.Cryptography.KeyDerivation
@@ -127,8 +128,44 @@ namespace KeePassLib.Cryptography.KeyDerivation
byte[] pbSecretKey = p.GetByteArray(ParamSecretKey);
byte[] pbAssocData = p.GetByteArray(ParamAssocData);
if (pbSecretKey != null) {
throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbSecretKey");
}
if (pbAssocData != null) {
throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbAssocData");
}
/*
byte[] pbRet = Argon2d(pbMsg, pbSalt, uPar, uMem, uIt,
32, v, pbSecretKey, pbAssocData);
*/
IntPtr msgPtr = Marshal.AllocHGlobal(pbMsg.Length);
IntPtr saltPtr = Marshal.AllocHGlobal(pbSalt.Length);
IntPtr retPtr = Marshal.AllocHGlobal(32);
Marshal.Copy(pbMsg, 0, msgPtr, pbMsg.Length);
Marshal.Copy(pbSalt, 0, saltPtr, pbSalt.Length);
const UInt32 Argon2_d = 0;
int ret = argon2_hash(
(UInt32)uIt, (UInt32)(uMem / 1024), uPar,
msgPtr, (IntPtr)pbMsg.Length,
saltPtr, (IntPtr)pbSalt.Length,
retPtr, (IntPtr)32,
(IntPtr)0, (IntPtr)0, Argon2_d, v);
if (ret != 0) {
throw new Exception("argon2_hash failed with " + ret);
}
byte[] pbRet = new byte[32];
Marshal.Copy(retPtr, pbRet, 0, 32);
Marshal.FreeHGlobal(msgPtr);
Marshal.FreeHGlobal(saltPtr);
Marshal.FreeHGlobal(retPtr);
if(uMem > (100UL * 1024UL * 1024UL)) GC.Collect();
return pbRet;
@@ -143,5 +180,14 @@ namespace KeePassLib.Cryptography.KeyDerivation
MaxIterations, uMilliseconds, true);
return p;
}
[DllImport("argon2")]
static extern int argon2_hash(
UInt32 t_cost, UInt32 m_cost, UInt32 parallelism,
IntPtr pwd, IntPtr pwdlen,
IntPtr salt, IntPtr saltlen,
IntPtr hash, IntPtr hashlen,
IntPtr encoded, IntPtr encodedlen,
UInt32 type, UInt32 version);
}
}

View File

@@ -12,8 +12,8 @@
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
<AndroidResgenClass>Resource</AndroidResgenClass>
<AssemblyName>KeePassLib2Android</AssemblyName>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<NuGetPackageImportStamp>8482b288</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

View File

@@ -38,9 +38,11 @@ namespace KeePassLib.Keys
get;
}
// /// <summary>
// /// Clear the key and securely erase all security-critical information.
// /// </summary>
// void Clear();
// /// <summary>
// /// Clear the key and securely erase all security-critical information.
// /// </summary>
// void Clear();
uint GetMinKdbxVersion();
}
}

View File

@@ -45,7 +45,12 @@ namespace KeePassLib.Keys
get { return m_pbKey; }
}
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash)
public uint GetMinKdbxVersion()
{
return 0;
}
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash)
{
Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName");
Debug.Assert(pbKeyData != null); if(pbKeyData == null) throw new ArgumentNullException("pbKeyData");

View File

@@ -64,7 +64,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; }
}
public IOConnectionInfo Ioc
public uint GetMinKdbxVersion()
{
return 0;
}
public IOConnectionInfo Ioc
{
get { return m_ioc; }
}

View File

@@ -53,7 +53,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; }
}
public KcpPassword(byte[] pbPasswordUtf8)
public uint GetMinKdbxVersion()
{
return 0;
}
public KcpPassword(byte[] pbPasswordUtf8)
{
SetKey(pbPasswordUtf8);
}

View File

@@ -21,7 +21,6 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Security;
#if !KeePassUAP
@@ -60,7 +59,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; }
}
/// <summary>
public uint GetMinKdbxVersion()
{
return 0;
}
/// <summary>
/// Construct a user account key.
/// </summary>
public KcpUserAccount()
@@ -73,26 +77,7 @@ namespace KeePassLib.Keys
// m_pbKeyData = null;
// }
private static string GetUserKeyFilePath(bool bCreate)
{
#if KeePassRT
string strUserDir = Windows.Storage.ApplicationData.Current.RoamingFolder.Path;
#else
string strUserDir = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
#endif
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
strUserDir += PwDefs.ShortProductName;
if (bCreate && !Directory.Exists(strUserDir))
Directory.CreateDirectory(strUserDir);
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
return strUserDir + UserKeyFileName;
}
private static byte[] LoadUserKey(bool bShowWarning)
private static byte[] LoadUserKey(bool bShowWarning)
{
byte[] pbKey = null;

View File

@@ -85,8 +85,8 @@ namespace keepass2android
{
if (!File.Exists(LogFilename))
{
File.Create(LogFilename);
_logToFile = true;
File.Create(LogFilename).Dispose();
_logToFile = true;
}
@@ -100,8 +100,7 @@ namespace keepass2android
int count = 0;
while (File.Exists(LogFilename + "." + count))
count++;
if (count > 0)
File.Move(LogFilename, LogFilename + "." + count);
File.Move(LogFilename, LogFilename + "." + count);
}

View File

@@ -302,7 +302,7 @@ namespace KeePassLib.Native
}
catch (Exception e)
{
Kp2aLog.Log(e.Message);
Kp2aLog.Log(e.ToString());
return false;
}

View File

@@ -485,12 +485,6 @@ namespace KeePassLib
set { m_pbHashOfLastIO = value; }
}
public bool UseFileTransactions
{
get { return m_bUseFileTransactions; }
set { m_bUseFileTransactions = value; }
}
public bool UseFileLocks
{
get { return m_bUseFileLocks; }
@@ -593,7 +587,7 @@ namespace KeePassLib
/// </summary>
/// <param name="ioConnection">IO connection of the new database.</param>
/// <param name="pwKey">Key to open the database.</param>
public void New(IOConnectionInfo ioConnection, CompositeKey pwKey)
public void New(IOConnectionInfo ioConnection, CompositeKey pwKey, string filenameWithoutPathAndExt)
{
Debug.Assert(ioConnection != null);
if(ioConnection == null) throw new ArgumentNullException("ioConnection");
@@ -608,26 +602,11 @@ namespace KeePassLib
m_bDatabaseOpened = true;
m_bModified = true;
m_pgRootGroup = new PwGroup(true, true,
UrlUtil.StripExtension(UrlUtil.GetFileName(ioConnection.Path)),
m_pgRootGroup = new PwGroup(true, true, filenameWithoutPathAndExt,
PwIcon.FolderOpen);
m_pgRootGroup.IsExpanded = true;
}
/// <summary>
/// Open a database. The URL may point to any supported data source.
/// </summary>
/// <param name="ioSource">IO connection to load the database from.</param>
/// <param name="pwKey">Key used to open the specified database.</param>
/// <param name="slLogger">Logger, which gets all status messages.</param>
public void Open(IOConnectionInfo ioSource, CompositeKey pwKey,
IStatusLogger slLogger, IDatabaseFormat format)
{
Open(IOConnection.OpenRead(ioSource), UrlUtil.StripExtension(
UrlUtil.GetFileName(ioSource.Path)), ioSource, pwKey, slLogger, format);
}
/// <summary>
/// Open a database. The URL may point to any supported data source.
@@ -675,37 +654,7 @@ namespace KeePassLib
throw;
}
}
/// <summary>
/// Save the currently opened database. The file is written to the location
/// it has been opened from.
/// </summary>
/// <param name="slLogger">Logger that recieves status information.</param>
public void Save(IStatusLogger slLogger)
{
Debug.Assert(!HasDuplicateUuids());
FileLock fl = null;
if(m_bUseFileLocks) fl = new FileLock(m_ioSource);
try
{
FileTransactionEx ft = new FileTransactionEx(m_ioSource,
m_bUseFileTransactions);
Stream s = ft.OpenWrite();
KdbxFile kdb = new KdbxFile(this);
kdb.Save(s, null, KdbpFile.GetFormatToUse(m_ioSource), slLogger);
ft.CommitWrite();
m_pbHashOfLastIO = kdb.HashOfFileOnDisk;
m_pbHashOfFileOnDisk = kdb.HashOfFileOnDisk;
Debug.Assert(m_pbHashOfFileOnDisk != null);
}
finally { if(fl != null) fl.Dispose(); }
m_bModified = false;
}
/// <summary>
/// Save the currently opened database. The file is written to the given stream which is expected to be the original location.
@@ -723,46 +672,6 @@ namespace KeePassLib
m_bModified = false;
}
/// <summary>
/// Save the currently opened database to a different location. If
/// <paramref name="bIsPrimaryNow" /> is <c>true</c>, the specified
/// location is made the default location for future saves
/// using <c>SaveDatabase</c>.
/// </summary>
/// <param name="ioConnection">New location to serialize the database to.</param>
/// <param name="bIsPrimaryNow">If <c>true</c>, the new location is made the
/// standard location for the database. If <c>false</c>, a copy of the currently
/// opened database is saved to the specified location, but it isn't
/// made the default location (i.e. no lock files will be moved for
/// example).</param>
/// <param name="slLogger">Logger that recieves status information.</param>
public void SaveAs(IOConnectionInfo ioConnection, bool bIsPrimaryNow,
IStatusLogger slLogger)
{
Debug.Assert(ioConnection != null);
if(ioConnection == null) throw new ArgumentNullException("ioConnection");
IOConnectionInfo ioCurrent = m_ioSource; // Remember current
m_ioSource = ioConnection;
byte[] pbHashCopy = m_pbHashOfFileOnDisk;
try { this.Save(slLogger); }
catch(Exception)
{
m_ioSource = ioCurrent; // Restore
m_pbHashOfFileOnDisk = pbHashCopy;
m_pbHashOfLastIO = null;
throw;
}
if(!bIsPrimaryNow)
{
m_ioSource = ioCurrent; // Restore
m_pbHashOfFileOnDisk = pbHashCopy;
}
}
/// <summary>
/// Closes the currently opened database. No confirmation message is shown

View File

@@ -360,5 +360,12 @@ namespace KeePassLib.Serialization
m_ioCredProtMode = IOCredProtMode.None;
}
}
public bool IsSameFileAs(IOConnectionInfo other)
{
if (other == null)
return false;
return Path == other.Path && UserName == other.UserName;
}
}
}

View File

@@ -581,7 +581,7 @@ namespace KeePassLib.Serialization
return vEntries; */
PwDatabase pd = new PwDatabase();
pd.New(new IOConnectionInfo(), new CompositeKey());
pd.New(new IOConnectionInfo(), new CompositeKey(), "");
KdbxFile f = new KdbxFile(pd);
f.Load(msData, KdbxFormat.PlainXml, null);

View File

@@ -1048,7 +1048,7 @@ namespace KeePassLib.Serialization
return true; */
PwDatabase pd = new PwDatabase();
pd.New(new IOConnectionInfo(), new CompositeKey());
pd.New(new IOConnectionInfo(), new CompositeKey(), "");
PwGroup pg = pd.RootGroup;
if (pg == null) { Debug.Assert(false); return false; }

View File

@@ -23,6 +23,7 @@ using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Xml;
@@ -126,8 +127,8 @@ namespace KeePassLib.Serialization
/// </summary>
private const uint FileVersion32 = 0x00040000;
internal const uint FileVersion32_4 = 0x00040000; // First of 4.x series
internal const uint FileVersion32_3 = 0x00030001; // Old format 3.1
public const uint FileVersion32_4 = 0x00040000; // First of 4.x series
public const uint FileVersion32_3 = 0x00030001; // Old format 3.1
private const uint FileVersionCriticalMask = 0xFFFF0000;
@@ -372,16 +373,19 @@ namespace KeePassLib.Serialization
{
if(m_uForceVersion != 0) return m_uForceVersion;
// See also KeePassKdb2x3.Export (KDBX 3.1 export module)
AesKdf kdfAes = new AesKdf();
// See also KeePassKdb2x3.Export (KDBX 3.1 export module)
uint minVersionForKeys = m_pwDatabase.MasterKey.UserKeys.Select(key => key.GetMinKdbxVersion()).Max();
AesKdf kdfAes = new AesKdf();
if(!kdfAes.Uuid.Equals(m_pwDatabase.KdfParameters.KdfUuid))
return FileVersion32;
return Math.Max(FileVersion32, minVersionForKeys);
if(m_pwDatabase.PublicCustomData.Count > 0)
return FileVersion32;
return Math.Max(FileVersion32, minVersionForKeys);
bool bCustomData = false;
bool bCustomData = false;
GroupHandler gh = delegate(PwGroup pg)
{
if(pg == null) { Debug.Assert(false); return true; }
@@ -396,9 +400,10 @@ namespace KeePassLib.Serialization
};
gh(m_pwDatabase.RootGroup);
m_pwDatabase.RootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh);
if(bCustomData) return FileVersion32;
if(bCustomData)
return Math.Max(FileVersion32, minVersionForKeys);
return FileVersion32_3; // KDBX 3.1 is sufficient
return Math.Max(FileVersion32_3, minVersionForKeys); ; // KDBX 3.1 is sufficient
}
private void ComputeKeys(out byte[] pbCipherKey, int cbCipherKey,

View File

@@ -26,10 +26,10 @@ namespace KeePassLib.Serialization
/// <summary>
/// Determines whether the database pointed to by the specified ioc should be (de)serialised in default (xml) or protocol buffers format.
/// </summary>
public static KdbxFormat GetFormatToUse(IOConnectionInfo ioc)
public static KdbxFormat GetFormatToUse(string fileExt)
{
// If the filename ends in .kdbp, use ProtocolBuffers format.
return UrlUtil.GetExtension(UrlUtil.GetFileName(ioc.Path)).Equals(KdbpFile.FileNameExtension, StringComparison.OrdinalIgnoreCase) ? KdbxFormat.ProtocolBuffers : KdbxFormat.Default;
return fileExt.Equals(KdbpFile.FileNameExtension, StringComparison.OrdinalIgnoreCase) ? KdbxFormat.ProtocolBuffers : KdbxFormat.Default;
}
public static void WriteDocument(PwDatabase database, Stream stream, byte[] protectedStreamKey, byte[] hashOfHeader)

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using keepass2android.Io;
using KeePassLib;
using KeePassLib.Interfaces;
using KeePassLib.Utility;
namespace keepass2android
{
public class ElementAndDatabaseId
{
private const char Separator = '+';
public ElementAndDatabaseId(Database db, IStructureItem element)
{
DatabaseId = db.IocAsHexString();
ElementIdString = element.Uuid.ToHexString();
}
public ElementAndDatabaseId(string fullId)
{
string[] parts = fullId.Split(Separator);
if (parts.Length != 2)
throw new Exception("Invalid full id " + fullId);
DatabaseId = parts[0];
ElementIdString = parts[1];
}
public string DatabaseId { get; set; }
public string ElementIdString { get; set; }
public PwUuid ElementId { get { return new PwUuid(MemUtil.HexStringToByteArray(ElementIdString));} }
public string FullId
{
get { return DatabaseId + Separator + ElementIdString; }
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Android.App;
@@ -9,6 +10,7 @@ using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
using keepass2android.Io;
using KeePassLib.Interfaces;
#if !NoNet
using Keepass2android.Javafilestorage;
#endif
@@ -33,31 +35,41 @@ namespace keepass2android
/// This also contains methods which are UI specific and should be replacable for testing.
public interface IKp2aApp : ICertificateValidationHandler
{
/// <summary>
/// Locks the currently open database, quicklocking if available (unless false is passed for allowQuickUnlock)
/// </summary>
void LockDatabase(bool allowQuickUnlock = true);
/// <summary>
/// Locks all currently open databases, quicklocking if available (unless false is passed for allowQuickUnlock)
/// </summary>
void Lock(bool allowQuickUnlock);
/// <summary>
/// Loads the specified data as the currently open database, as unlocked.
/// </summary>
void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compKey,
ProgressDialogStatusLogger statusLogger, IDatabaseFormat databaseFormat);
/// <summary>
/// Returns the current database
/// </summary>
Database GetDb();
/// <summary>
/// Loads the specified data as the currently open database, as unlocked.
/// </summary>
Database LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compKey, ProgressDialogStatusLogger statusLogger, IDatabaseFormat databaseFormat, bool makeCurrent);
/// <summary>
/// Tell the app that the file from ioc was opened with keyfile.
/// </summary>
void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, string displayName = "");
HashSet<PwGroup> DirtyGroups { get; }
void MarkAllGroupsAsDirty();
/// <summary>
/// Returns the current database
/// </summary>
Database CurrentDb { get; }
IEnumerable<Database> OpenDatabases { get; }
void CloseDatabase(Database db);
Database FindDatabaseForElement(IStructureItem element);
/// <summary>
/// Tell the app that the file from ioc was opened with keyfile.
/// </summary>
void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, bool updateTimestamp, string displayName = "");
/// <summary>
/// Creates a new database and returns it
/// </summary>
Database CreateNewDatabase();
Database CreateNewDatabase(bool makeCurrent);
/// <summary>
/// Returns the user-displayable string identified by stringKey
@@ -76,7 +88,8 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx);
Context ctx,
string messageSuffix = "");
/// <summary>
/// Asks the user the question "messageKey" with the options Yes/No/Cancel, but the yes/no strings can be selected freely, calls the handler corresponding to the answer.
@@ -86,7 +99,8 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx);
Context ctx,
string messageSuffix = "");
/// <summary>
/// Returns a Handler object which can run tasks on the UI thread
@@ -111,6 +125,10 @@ namespace keepass2android
bool CheckForDuplicateUuids { get; }
#if !NoNet
ICertificateErrorHandler CertificateErrorHandler { get; }
#endif
}
}

View File

@@ -82,7 +82,12 @@ namespace keepass2android.Io
UrlUtil.GetFileName(ioc.Path));
}
public bool RequiresCredentials(IOConnectionInfo ioc)
public string GetFileExtension(IOConnectionInfo ioc)
{
return UrlUtil.GetExtension(ioc.Path);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return false;
}
@@ -207,8 +212,7 @@ namespace keepass2android.Io
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
{
//TODO: required for OTP Aux file retrieval
throw new NotImplementedException();
return IoUtil.GetParentPath(ioc);
}
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)

View File

@@ -12,13 +12,10 @@ using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Preferences;
using Android.Support.V13.App;
using Android.Support.V4.App;
using Java.IO;
using Java.Util;
using Android.Support.V4;
using KeePassLib.Serialization;
using KeePassLib.Utility;
using ActivityCompat = Android.Support.V13.App.ActivityCompat;
using File = System.IO.File;
using FileNotFoundException = System.IO.FileNotFoundException;
using IOException = System.IO.IOException;
@@ -204,7 +201,12 @@ namespace keepass2android.Io
}
public bool RequiresCredentials(IOConnectionInfo ioc)
public string GetFileExtension(IOConnectionInfo ioc)
{
return UrlUtil.GetExtension(ioc.Path);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return (!ioc.IsLocalFile()) && (ioc.CredSaveMode != IOCredSaveMode.SaveCred);
}
@@ -255,7 +257,8 @@ namespace keepass2android.Io
if (ioc.IsLocalFile())
{
bool requiresPermission = !(ioc.Path.StartsWith(activity.Activity.FilesDir.CanonicalPath)
|| ioc.Path.StartsWith(IoUtil.GetInternalDirectory(activity.Activity).CanonicalPath));
|| ioc.Path.StartsWith(IoUtil.GetInternalDirectory(activity.Activity).CanonicalPath)
|| ioc.Path.StartsWith(IoUtil.GetInternalDirectory(activity.Activity).CanonicalPath));
var extDirectory = activity.Activity.GetExternalFilesDir(null);
if ((extDirectory != null) && (ioc.Path.StartsWith(extDirectory.CanonicalPath)))

View File

@@ -65,22 +65,28 @@ namespace keepass2android.Io
protected readonly OfflineSwitchableFileStorage _cachedStorage;
private readonly ICacheSupervisor _cacheSupervisor;
private readonly string _streamCacheDir;
private readonly string _legacyCacheDir;
private readonly string _cacheDir;
public CachingFileStorage(IFileStorage cachedStorage, string cacheDir, ICacheSupervisor cacheSupervisor)
public CachingFileStorage(IFileStorage cachedStorage, Context cacheDirContext, ICacheSupervisor cacheSupervisor)
{
_cachedStorage = new OfflineSwitchableFileStorage(cachedStorage);
_cacheSupervisor = cacheSupervisor;
_streamCacheDir = cacheDir + Java.IO.File.Separator + "OfflineCache" + Java.IO.File.Separator;
if (!Directory.Exists(_streamCacheDir))
Directory.CreateDirectory(_streamCacheDir);
}
_legacyCacheDir = cacheDirContext.CacheDir.Path + Java.IO.File.Separator + "OfflineCache" + Java.IO.File.Separator;
if (!Directory.Exists(_legacyCacheDir))
Directory.CreateDirectory(_legacyCacheDir);
_cacheDir = IoUtil.GetInternalDirectory(cacheDirContext).Path + Java.IO.File.Separator + "OfflineCache" + Java.IO.File.Separator;
if (!Directory.Exists(_cacheDir))
Directory.CreateDirectory(_cacheDir);
}
public void ClearCache()
{
IoUtil.DeleteDir(new Java.IO.File(_streamCacheDir), true);
}
IoUtil.DeleteDir(new Java.IO.File(_legacyCacheDir), true);
IoUtil.DeleteDir(new Java.IO.File(_cacheDir), true);
}
public IEnumerable<string> SupportedProtocols { get { return _cachedStorage.SupportedProtocols; } }
@@ -105,7 +111,11 @@ namespace keepass2android.Io
{
SHA256Managed sha256 = new SHA256Managed();
string iocAsHexString = MemUtil.ByteArrayToHexString(sha256.ComputeHash(Encoding.Unicode.GetBytes(ioc.Path.ToCharArray())))+".cache";
return _streamCacheDir + iocAsHexString;
if (File.Exists(_legacyCacheDir + iocAsHexString))
return _legacyCacheDir + iocAsHexString;
return _cacheDir + iocAsHexString;
}
public bool IsCached(IOConnectionInfo ioc)
@@ -168,7 +178,9 @@ namespace keepass2android.Io
if (!IsCached(ioc))
throw;
Kp2aLog.Log("couldn't open from remote " + ioc.Path);
#if DEBUG
Kp2aLog.Log("couldn't open from remote " + ioc.Path);
#endif
Kp2aLog.Log(ex.ToString());
_cacheSupervisor.CouldntOpenFromRemote(ioc, ex);
@@ -436,7 +448,12 @@ namespace keepass2android.Io
return _cachedStorage.GetFilenameWithoutPathAndExt(ioc);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
public string GetFileExtension(IOConnectionInfo ioc)
{
return _cachedStorage.GetFileExtension(ioc);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return _cachedStorage.RequiresCredentials(ioc);
}

View File

@@ -2,12 +2,12 @@ namespace keepass2android.Io
{
public partial class DropboxFileStorage
{
private const string AppKey = "";
private const string AppSecret = "";
private const string AppKey = "dummy";
private const string AppSecret = "dummy";
}
public partial class DropboxAppFolderFileStorage
{
private const string AppKey = "";
private const string AppSecret = "";
private const string AppKey = "dummy";
private const string AppSecret = "dummy";
}
}
}

View File

@@ -88,11 +88,13 @@ namespace keepass2android.Io
IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction);
string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc);
/// <summary>
/// Returns true if the the given ioc must be filled with username/password
/// </summary>
bool RequiresCredentials(IOConnectionInfo ioc);
string GetFileExtension(IOConnectionInfo ioc);
/// <summary>
/// Returns true if the the given ioc must be filled with username/password
/// </summary>
bool RequiresCredentials(IOConnectionInfo ioc);
/// <summary>
/// Creates the directory described by ioc

View File

@@ -128,10 +128,12 @@ namespace keepass2android.Io
}
//creates a local ioc where the sourceIoc can be stored to
public static IOConnectionInfo GetInternalIoc(IOConnectionInfo sourceIoc, Context ctx)
public static IOConnectionInfo GetInternalIoc(IOConnectionInfo sourceIoc, Context ctx, IKp2aApp app)
{
Java.IO.File internalDirectory = IoUtil.GetInternalDirectory(ctx);
string targetPath = UrlUtil.GetFileName(sourceIoc.Path);
var filestorage = app.GetFileStorage(sourceIoc);
string targetPath = filestorage.GetFilenameWithoutPathAndExt(sourceIoc);
targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray());
if (targetPath == "")
targetPath = "internal";
@@ -153,7 +155,7 @@ namespace keepass2android.Io
public static IOConnectionInfo ImportFileToInternalDirectory(IOConnectionInfo sourceIoc, Context ctx, IKp2aApp app)
{
var targetIoc = GetInternalIoc(sourceIoc, ctx);
var targetIoc = GetInternalIoc(sourceIoc, ctx, app);
IoUtil.Copy(targetIoc, sourceIoc, app);

View File

@@ -177,7 +177,12 @@ namespace keepass2android.Io
_jfs.GetFilename(IocToPath(ioc)));
}
public bool RequiresCredentials(IOConnectionInfo ioc)
public string GetFileExtension(IOConnectionInfo ioc)
{
return UrlUtil.GetExtension(ioc.Path);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return false;
}
@@ -233,7 +238,6 @@ namespace keepass2android.Io
public FileDescription GetFileDescription(IOConnectionInfo ioc)
{
Kp2aLog.Log("GetFileDescription "+ioc.Path);
try
{
return ConvertToFileDescription(Jfs.GetFileEntry(IocToPath(ioc)));
@@ -302,7 +306,9 @@ namespace keepass2android.Io
public void OnResume(IFileStorageSetupActivity activity)
{
#if DEBUG
Kp2aLog.Log("JFS/OnResume Ioc.Path=" +activity.Ioc.Path+". Path="+((IJavaFileStorageFileStorageSetupActivity)activity).Path);
#endif
_jfs.OnResume(((IJavaFileStorageFileStorageSetupActivity) activity));
}
@@ -366,4 +372,4 @@ namespace keepass2android.Io
}
}
#endif
}
}

View File

@@ -314,7 +314,12 @@ namespace keepass2android.Io
UrlUtil.GetFileName(ioc.Path));
}
public bool RequiresCredentials(IOConnectionInfo ioc)
public string GetFileExtension(IOConnectionInfo ioc)
{
return UrlUtil.GetExtension(ioc.Path);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return false;
}

View File

@@ -78,7 +78,12 @@ namespace keepass2android.Io
return _baseStorage.GetFilenameWithoutPathAndExt(ioc);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
public string GetFileExtension(IOConnectionInfo ioc)
{
return _baseStorage.GetFileExtension(ioc);
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
return _baseStorage.RequiresCredentials(ioc);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
namespace keepass2android.Io.ItemLocation
{
public abstract class OneDrive2PrefixContainer
{
public abstract string Onedrive2ProtocolId { get; }
public string Onedrive2Prefix { get { return Onedrive2ProtocolId + "://"; } }
}
//for permissions including all my files and all shared files
public class OneDrive2FullPrefixContainer : OneDrive2PrefixContainer
{
public override string Onedrive2ProtocolId { get { return "onedrive2_full"; }}
}
//for permissions including all my files
public class OneDrive2MyFilesPrefixContainer : OneDrive2PrefixContainer
{
public override string Onedrive2ProtocolId { get { return "onedrive2_myfiles"; } }
}
//for permissions to app folder only
public class OneDrive2AppFolderPrefixContainer : OneDrive2PrefixContainer
{
public override string Onedrive2ProtocolId { get { return "onedrive2_appfolder"; } }
}
}

View File

@@ -0,0 +1,23 @@
using Android.Content;
#if !EXCLUDE_JAVAFILESTORAGE
namespace keepass2android.Io
{
public partial class PCloudFileStorage: JavaFileStorage
{
private const string ClientId = "CkRWTQXY6Lm";
public PCloudFileStorage(Context ctx, IKp2aApp app) :
base(new Keepass2android.Javafilestorage.PCloudFileStorage(ctx, ClientId), app)
{
}
public override bool UserShouldBackup
{
get { return false; }
}
}
}
#endif

View File

@@ -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)
{
}

View File

@@ -30,7 +30,8 @@ namespace keepass2android.Io
yield return "http";
yield return "https";
yield return "owncloud";
}
yield return "nextcloud";
}
}
public override bool UserShouldBackup
@@ -38,12 +39,15 @@ namespace keepass2android.Io
get { return true; }
}
public static string Owncloud2Webdav(string owncloudUrl)
public static string owncloudPrefix = "owncloud://";
public static string nextcloudPrefix = "nextcloud://";
public static string Owncloud2Webdav(string owncloudUrl, string prefix)
{
string owncloudPrefix = "owncloud://";
if (owncloudUrl.StartsWith(owncloudPrefix))
if (owncloudUrl.StartsWith(prefix))
{
owncloudUrl = owncloudUrl.Substring(owncloudPrefix.Length);
owncloudUrl = owncloudUrl.Substring(prefix.Length);
}
if (!owncloudUrl.Contains("://"))
owncloudUrl = "https://" + owncloudUrl;

View File

@@ -12,8 +12,8 @@
<FileAlignment>512</FileAlignment>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
@@ -55,42 +55,12 @@
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
<Reference Include="Xamarin.Android.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Core.Common.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Arch.Lifecycle.Runtime, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Annotations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Annotations.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Compat.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Core.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.UI.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Core.Utils, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.Utils.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Fragment, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Fragment.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Media.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Media.Compat.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.v13, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.v13.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.v13.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="database\CheckDatabaseForChanges.cs" />
<Compile Include="database\edit\AddTemplateEntries.cs" />
<Compile Include="database\edit\CopyEntry.cs" />
<Compile Include="database\edit\DeleteMultipleItems.cs" />
<Compile Include="database\edit\DeleteMultipleItemsFromOneDatabase.cs" />
<Compile Include="database\edit\EditGroup.cs" />
<Compile Include="database\edit\MoveElements.cs" />
<Compile Include="database\KdbDatabaseFormat.cs" />
@@ -102,6 +72,7 @@
<Compile Include="DataExchange\Formats\KeePassKdb2x.cs" />
<Compile Include="DataExchange\Formats\KeePassXml2x.cs" />
<Compile Include="DataExchange\PwExportInfo.cs" />
<Compile Include="ElementAndDatabaseId.cs" />
<Compile Include="Io\AndroidContentStorage.cs" />
<Compile Include="Io\BuiltInFileStorage.cs" />
<Compile Include="Io\CachingFileStorage.cs" />
@@ -111,6 +82,7 @@
<Compile Include="Io\IFileStorage.cs" />
<Compile Include="Io\IoUtil.cs" />
<Compile Include="Io\OfflineSwitchableFileStorage.cs" />
<Compile Include="IProgressDialog.cs" />
<Compile Include="PreferenceKey.cs" />
<Compile Include="SelectStorageLocationActivityBase.cs" />
@@ -119,15 +91,15 @@
<Compile Include="database\edit\ActionOnFinish.cs" />
<Compile Include="database\edit\AddEntry.cs" />
<Compile Include="database\edit\AddGroup.cs" />
<Compile Include="database\edit\CreateDb.cs" />
<Compile Include="database\edit\CreateDB.cs" />
<Compile Include="database\edit\DeleteEntry.cs" />
<Compile Include="database\edit\DeleteGroup.cs" />
<Compile Include="database\edit\DeleteRunnable.cs" />
<Compile Include="database\edit\FileOnFinish.cs" />
<Compile Include="database\edit\LoadDb.cs" />
<Compile Include="database\edit\LoadDB.cs" />
<Compile Include="database\edit\OnFinish.cs" />
<Compile Include="database\edit\RunnableOnFinish.cs" />
<Compile Include="database\edit\SaveDb.cs" />
<Compile Include="database\edit\SaveDB.cs" />
<Compile Include="database\edit\SetPassword.cs" />
<Compile Include="database\edit\UpdateEntry.cs" />
<Compile Include="IKp2aApp.cs" />
@@ -154,6 +126,7 @@
<Project>{70D3844A-D9FA-4A64-B205-A84C6A822196}</Project>
<Name>KP2AKdbLibraryBinding</Name>
</ProjectReference>
<ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj">
<Project>{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}</Project>
<Name>TwofishCipher</Name>
@@ -163,34 +136,113 @@
<Folder Include="Resources\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.Android.Arch.Core.Common">
<Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Arch.Core.Runtime">
<Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Arch.Lifecycle.Common">
<Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Arch.Lifecycle.LiveData">
<Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Arch.Lifecycle.LiveData.Core">
<Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Arch.Lifecycle.Runtime">
<Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Arch.Lifecycle.ViewModel">
<Version>1.1.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Animated.Vector.Drawable">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Annotations">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.AsyncLayoutInflater">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Collections">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Compat">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.CoordinaterLayout">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Core.UI">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Core.Utils">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.CursorAdapter">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.CustomTabs">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.CustomView">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.DocumentFile">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.DrawerLayout">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Fragment">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Interpolator">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Loader">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.LocalBroadcastManager">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Media.Compat">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Print">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.SlidingPaneLayout">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.SwipeRefreshLayout">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.v13">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.v4">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.Vector.Drawable">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.VersionedParcelable">
<Version>28.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Android.Support.ViewPager">
<Version>28.0.0.1</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets'))" />
</Target>
<Import Project="..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" />
<Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" />
<Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.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">

View File

@@ -52,7 +52,8 @@ namespace keepass2android
public void UpdateMessage (String message)
{
_message = message;
Kp2aLog.Log("status message: " + message);
_message = message;
if ( _app!= null && _progressDialog != null && _handler != null ) {
_handler.Post(() => {_progressDialog.SetMessage(message); } );
}
@@ -60,6 +61,7 @@ namespace keepass2android
public void UpdateSubMessage(String submessage)
{
Kp2aLog.Log("status submessage: " + submessage);
_submessage = submessage;
if (_app != null && _progressDialog != null && _handler != null)
{

View File

@@ -23,7 +23,7 @@ namespace keepass2android
/// <summary>
/// EqualityComparer implementation to compare PwGroups based on their Id
/// </summary>
class PwGroupEqualityFromIdComparer: IEqualityComparer<PwGroup>
public class PwGroupEqualityFromIdComparer: IEqualityComparer<PwGroup>
{
#region IEqualityComparer implementation
public bool Equals (PwGroup x, PwGroup y)

View File

@@ -103,7 +103,7 @@ namespace keepass2android
PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch) {IsVirtual = true};
if (String.IsNullOrWhiteSpace(host))
return pgResults;
foreach (PwEntry entry in database.Entries.Values)
foreach (PwEntry entry in database.EntriesById.Values)
{
string otherUrl = entry.Strings.ReadSafe(PwDefs.UrlField);
otherUrl = SprEngine.Compile(otherUrl, new SprContext(entry, database.KpDatabase, SprCompileFlags.References));

View File

@@ -86,6 +86,8 @@ namespace keepass2android
ReadOnlyReason_PreKitKat,
ReadOnlyReason_ReadOnlyFlag,
ReadOnlyReason_ReadOnlyKitKat,
ReadOnlyReason_LocalBackup
ReadOnlyReason_LocalBackup,
Ok,
cancel
}
}

View File

@@ -25,9 +25,7 @@ using KeePass.Util.Spr;
using KeePassLib;
using KeePassLib.Collections;
using KeePassLib.Cryptography;
using KeePassLib.Delegates;
using KeePassLib.Security;
using KeePassLib.Utility;
namespace KeePass.Util
@@ -89,41 +87,8 @@ namespace KeePass.Util
return str;
}
*/
private static string ReplaceHmacOtpPlaceholder(string strText,
SprContext ctx)
{
PwEntry pe = ctx.Entry;
PwDatabase pd = ctx.Database;
if((pe == null) || (pd == null)) return strText;
string str = strText;
const string strHmacOtpPlh = @"{HMACOTP}";
if(str.IndexOf(strHmacOtpPlh, StrUtil.CaseIgnoreCmp) >= 0)
{
const string strKeyField = "HmacOtp-Secret";
const string strCounterField = "HmacOtp-Counter";
byte[] pbSecret = StrUtil.Utf8.GetBytes(pe.Strings.ReadSafe(
strKeyField));
string strCounter = pe.Strings.ReadSafe(strCounterField);
ulong uCounter;
ulong.TryParse(strCounter, out uCounter);
string strValue = HmacOtp.Generate(pbSecret, uCounter, 6, false, -1);
pe.Strings.Set(strCounterField, new ProtectedString(false,
(uCounter + 1).ToString()));
pd.Modified = true;
str = StrUtil.ReplaceCaseInsensitive(str, strHmacOtpPlh, strValue);
}
return str;
}
public static bool EntriesHaveSameParent(PwObjectList<PwEntry> v)
public static bool EntriesHaveSameParent(PwObjectList<PwEntry> v)
{
if(v == null) { Debug.Assert(false); return true; }
if(v.UCount == 0) return true;

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Identity.Client" publicKeyToken="0a613f4dd989e8ae" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.4.0.0" newVersion="4.4.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -29,7 +29,7 @@ namespace keepass2android
{
try
{
IOConnectionInfo ioc = _app.GetDb().Ioc;
IOConnectionInfo ioc = _app.CurrentDb.Ioc;
IFileStorage fileStorage = _app.GetFileStorage(ioc);
if (fileStorage is CachingFileStorage)
{
@@ -49,7 +49,7 @@ namespace keepass2android
hashingRemoteStream.CopyTo(remoteData);
hashingRemoteStream.Close();
if (!MemUtil.ArraysEqual(_app.GetDb().KpDatabase.HashOfFileOnDisk, hashingRemoteStream.Hash))
if (!MemUtil.ArraysEqual(_app.CurrentDb.KpDatabase.HashOfFileOnDisk, hashingRemoteStream.Hash))
{
_app.TriggerReload(_context);
Finish(true);

View File

@@ -26,6 +26,7 @@ using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
using keepass2android.Io;
using KeePassLib.Interfaces;
using KeePassLib.Utility;
using Exception = System.Exception;
using String = System.String;
@@ -33,27 +34,23 @@ using String = System.String;
namespace keepass2android
{
public class Database {
public Dictionary<PwUuid, PwGroup> Groups = new Dictionary<PwUuid, PwGroup>(new PwUuidEqualityComparer());
public Dictionary<PwUuid, PwEntry> Entries = new Dictionary<PwUuid, PwEntry>(new PwUuidEqualityComparer());
public HashSet<PwGroup> Dirty = new HashSet<PwGroup>(new PwGroupEqualityFromIdComparer());
public class Database
{
public HashSet<IStructureItem> Elements = new HashSet<IStructureItem>();
public Dictionary<PwUuid, PwGroup> GroupsById = new Dictionary<PwUuid, PwGroup>(new PwUuidEqualityComparer());
public Dictionary<PwUuid, PwEntry> EntriesById = new Dictionary<PwUuid, PwEntry>(new PwUuidEqualityComparer());
public PwGroup Root;
public PwDatabase KpDatabase;
public IOConnectionInfo Ioc
{
get
{
return KpDatabase == null ? null : KpDatabase.IOConnectionInfo;
return KpDatabase?.IOConnectionInfo;
}
}
/// <summary>
/// Information about the last opened entry. Includes the entry but also transformed fields.
/// </summary>
public PwEntryOutput LastOpenedEntry { get; set; }
/// <summary>
/// if an OTP key was used, this property tells the location of the OTP auxiliary file.
/// Must be set after loading.
@@ -73,31 +70,14 @@ namespace keepass2android
_app = app;
CanWrite = true; //default
}
private bool _loaded;
private bool _reloadRequested;
private IDatabaseFormat _databaseFormat = new KdbxDatabaseFormat(KdbxFormat.Default);
private IDatabaseFormat _databaseFormat = new KdbxDatabaseFormat(KdbxFormat.Default);
public bool ReloadRequested
{
get { return _reloadRequested; }
set { _reloadRequested = value; }
}
public bool ReloadRequested { get; set; }
public bool Loaded {
get { return _loaded;}
set { _loaded = value; }
}
public bool DidOpenFileChange()
public bool DidOpenFileChange()
{
if (Loaded == false)
{
return false;
}
return _app.GetFileStorage(Ioc).CheckForFileChangeFast(Ioc, LastFileVersion);
}
@@ -112,32 +92,20 @@ namespace keepass2android
Stream s = databaseData ?? fileStorage.OpenFileForRead(iocInfo);
var fileVersion = _app.GetFileStorage(iocInfo).GetCurrentFileVersionFast(iocInfo);
PopulateDatabaseFromStream(pwDatabase, s, iocInfo, compositeKey, status, databaseFormat);
try
{
LastFileVersion = fileVersion;
LastFileVersion = fileVersion;
status.UpdateSubMessage("");
status.UpdateSubMessage("");
Root = pwDatabase.RootGroup;
PopulateGlobals(Root);
Root = pwDatabase.RootGroup;
PopulateGlobals(Root);
KpDatabase = pwDatabase;
SearchHelper = new SearchDbHelper(app);
KpDatabase = pwDatabase;
SearchHelper = new SearchDbHelper(app);
_databaseFormat = databaseFormat;
_databaseFormat = databaseFormat;
CanWrite = databaseFormat.CanWrite && !fileStorage.IsReadOnly(iocInfo);
Loaded = true;
}
catch (Exception)
{
Clear();
throw;
}
CanWrite = databaseFormat.CanWrite && !fileStorage.IsReadOnly(iocInfo);
}
/// <summary>
@@ -219,8 +187,7 @@ namespace keepass2android
public void SaveData() {
KpDatabase.UseFileTransactions = _app.GetBooleanPreference(PreferenceKey.UseFileTransactions);
using (IWriteTransaction trans = _app.GetFileStorage(Ioc).OpenWriteTransaction(Ioc, KpDatabase.UseFileTransactions))
using (IWriteTransaction trans = _app.GetFileStorage(Ioc).OpenWriteTransaction(Ioc, _app.GetBooleanPreference(PreferenceKey.UseFileTransactions)))
{
DatabaseFormat.Save(KpDatabase, trans.OpenFile());
@@ -239,14 +206,18 @@ namespace keepass2android
{
if (checkForDuplicateUuids)
{
if (Entries.ContainsKey(e.Uuid))
if (EntriesById.ContainsKey(e.Uuid))
{
throw new DuplicateUuidsException("Same UUID for entries '"+Entries[e.Uuid].Strings.ReadSafe(PwDefs.TitleField)+"' and '"+e.Strings.ReadSafe(PwDefs.TitleField)+"'.");
throw new DuplicateUuidsException("Same UUID for entries '"+EntriesById[e.Uuid].Strings.ReadSafe(PwDefs.TitleField)+"' and '"+e.Strings.ReadSafe(PwDefs.TitleField)+"'.");
}
}
Entries [e.Uuid] = e;
EntriesById [e.Uuid] = e;
Elements.Add(e);
}
GroupsById[currentGroup.Uuid] = currentGroup;
Elements.Add(currentGroup);
foreach (PwGroup g in childGroups)
{
if (checkForDuplicateUuids)
@@ -258,7 +229,6 @@ namespace keepass2android
}
* */
}
Groups[g.Uuid] = g;
PopulateGlobals(g);
}
}
@@ -266,33 +236,15 @@ namespace keepass2android
{
PopulateGlobals(currentGroup, _app.CheckForDuplicateUuids);
}
public void Clear() {
_loaded = false;
Groups.Clear();
Entries.Clear();
Dirty.Clear();
DrawableFactory.Clear();
Root = null;
KpDatabase = null;
CanWrite = true;
_reloadRequested = false;
OtpAuxFileIoc = null;
LastOpenedEntry = null;
}
public void MarkAllGroupsAsDirty() {
foreach ( PwGroup group in Groups.Values ) {
Dirty.Add(group);
}
}
public void UpdateGlobals()
{
EntriesById.Clear();
GroupsById.Clear();
Elements.Clear();
PopulateGlobals(Root);
}
}
[Serializable]

View File

@@ -216,9 +216,16 @@ namespace keepass2android
private DateTime JavaTimeToCSharp(long javatime)
{
try
{
var utcTime = new DateTime(1970, 1, 1).AddMilliseconds(javatime);
return TimeZoneInfo.ConvertTimeFromUtc(utcTime, TimeZoneInfo.Local);
}
catch (ArgumentOutOfRangeException)
{
return DateTime.MinValue;
}
var utcTime = new DateTime(1970, 1, 1).AddMilliseconds(javatime);
return TimeZoneInfo.ConvertTimeFromUtc(utcTime, TimeZoneInfo.Local);
}
#endif

View File

@@ -14,13 +14,13 @@ namespace keepass2android
public class PwEntryOutput
{
private readonly PwEntry _entry;
private readonly PwDatabase _db;
private readonly Database _db;
private readonly ProtectedStringDictionary _outputStrings = new ProtectedStringDictionary();
/// <summary>
/// Constructs the PwEntryOutput by replacing the placeholders
/// </summary>
public PwEntryOutput(PwEntry entry, PwDatabase db)
public PwEntryOutput(PwEntry entry, Database db)
{
_entry = entry;
_db = db;
@@ -34,7 +34,7 @@ namespace keepass2android
string GetStringAndReplacePlaceholders(string key)
{
String value = Entry.Strings.ReadSafe(key);
value = SprEngine.Compile(value, new SprContext(Entry, _db, SprCompileFlags.All));
value = SprEngine.Compile(value, new SprContext(Entry, _db.KpDatabase, SprCompileFlags.All));
return value;
}

View File

@@ -26,7 +26,7 @@ namespace keepass2android
{
try
{
IOConnectionInfo ioc = _app.GetDb().Ioc;
IOConnectionInfo ioc = _app.CurrentDb.Ioc;
IFileStorage fileStorage = _app.GetFileStorage(ioc);
if (!(fileStorage is CachingFileStorage))
{
@@ -70,10 +70,12 @@ namespace keepass2android
Finish(true, _app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully));
}
_saveDb = null;
}), false, remoteData);
}), _app.CurrentDb, false, remoteData);
_saveDb.Run();
_app.GetDb().MarkAllGroupsAsDirty();
_app.CurrentDb.UpdateGlobals();
_app.MarkAllGroupsAsDirty();
}
else
{
@@ -103,6 +105,7 @@ namespace keepass2android
}
catch (Exception e)
{
Kp2aLog.LogUnexpectedError(e);
Finish(false, e.Message);
}

View File

@@ -24,7 +24,7 @@ namespace keepass2android
public class AddEntry : RunnableOnFinish {
protected Database Db
{
get { return _app.GetDb(); }
get { return _app.CurrentDb; }
}
private readonly IKp2aApp _app;
@@ -37,13 +37,13 @@ namespace keepass2android
return new AddEntry(ctx, app, entry, parentGroup, finish);
}
protected AddEntry(Activity ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish):base(ctx, finish) {
public AddEntry(Activity ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish):base(ctx, finish) {
_ctx = ctx;
_parentGroup = parentGroup;
_app = app;
_entry = entry;
_onFinishToRun = new AfterAdd(ctx, app.GetDb(), entry, OnFinishToRun);
_onFinishToRun = new AfterAdd(ctx, app.CurrentDb, entry, app,OnFinishToRun);
}
@@ -60,7 +60,7 @@ namespace keepass2android
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun);
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun);
save.SetStatusLogger(StatusLogger);
save.Run();
}
@@ -68,12 +68,13 @@ namespace keepass2android
private class AfterAdd : OnFinish {
private readonly Database _db;
private readonly PwEntry _entry;
private readonly IKp2aApp _app;
public AfterAdd(Activity activity, Database db, PwEntry entry, OnFinish finish):base(activity, finish) {
public AfterAdd(Activity activity, Database db, PwEntry entry, IKp2aApp app, OnFinish finish):base(activity, finish) {
_db = db;
_entry = entry;
}
_app = app;
}
@@ -83,11 +84,12 @@ namespace keepass2android
PwGroup parent = _entry.ParentGroup;
// Mark parent group dirty
_db.Dirty.Add(parent);
_app.DirtyGroups.Add(parent);
// Add entry to global
_db.Entries[_entry.Uuid] = _entry;
_db.EntriesById[_entry.Uuid] = _entry;
_db.Elements.Add(_entry);
} else
{
StatusLogger.UpdateMessage(UiStringKey.UndoingChanges);

View File

@@ -26,13 +26,16 @@ namespace keepass2android
public class AddGroup : RunnableOnFinish {
internal Database Db
{
get { return _app.GetDb(); }
get { return _app.CurrentDb; }
}
private IKp2aApp _app;
public IKp2aApp App { get => _app; }
private IKp2aApp _app;
private readonly String _name;
private readonly int _iconId;
private readonly PwUuid _groupCustomIconId;
internal PwGroup Group;
public PwGroup Group;
internal PwGroup Parent;
protected bool DontSave;
readonly Activity _ctx;
@@ -67,9 +70,11 @@ namespace keepass2android
Group.CustomIconUuid = _groupCustomIconId;
}
Parent.AddGroup(Group, true);
_app.CurrentDb.GroupsById[Group.Uuid] = Group;
_app.CurrentDb.Elements.Add(Group);
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, DontSave);
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, DontSave);
save.SetStatusLogger(StatusLogger);
save.Run();
}
@@ -86,13 +91,15 @@ namespace keepass2android
if ( Success ) {
// Mark parent group dirty
_addGroup.Db.Dirty.Add(_addGroup.Parent);
_addGroup.App.DirtyGroups.Add(_addGroup.Parent);
// Add group to global list
_addGroup.Db.Groups[_addGroup.Group.Uuid] = _addGroup.Group;
_addGroup.Db.GroupsById[_addGroup.Group.Uuid] = _addGroup.Group;
_addGroup.Db.Elements.Add(_addGroup.Group);
} else {
StatusLogger.UpdateMessage(UiStringKey.UndoingChanges);
_addGroup.Parent.Groups.Remove(_addGroup.Group);
}
base.Run();

View File

@@ -28,7 +28,7 @@ namespace keepass2android
{
public class AddTemplateEntries : RunnableOnFinish {
class TemplateEntry
public class TemplateEntry
{
public UiStringKey Title { get; set; }
public PwIcon Icon { get; set; }
@@ -47,11 +47,12 @@ namespace keepass2android
void AddToEntry(IKp2aApp app, PwEntry entry, int position);
}
internal enum FieldType
public enum FieldType
{
Inline, ProtectedInline
}
internal enum SpecialFieldKey
public enum SpecialFieldKey
{
ExpDate, OverrideUrl, Tags
}
@@ -125,7 +126,7 @@ namespace keepass2android
protected Database Db
{
get { return _app.GetDb(); }
get { return _app.CurrentDb; }
}
private readonly IKp2aApp _app;
@@ -140,7 +141,7 @@ namespace keepass2android
//_onFinishToRun = new AfterAdd(this, OnFinishToRun);
}
static readonly List<TemplateEntry> TemplateEntries = new List<TemplateEntry>()
public static readonly List<TemplateEntry> TemplateEntries = new List<TemplateEntry>()
{
new TemplateEntry()
{
@@ -285,12 +286,23 @@ namespace keepass2android
};
public static bool ContainsAllTemplates(IKp2aApp app)
public static bool ContainsAllTemplates(Database db)
{
return TemplateEntries.All(t => app.GetDb().Entries.ContainsKey(t.Uuid));
return TemplateEntries.All(t =>
{
string hexId = t.Uuid.ToHexString();
return db.EntriesById.Any(kvp => kvp.Key.Equals(t.Uuid) ||
kvp.Value.Strings.ReadSafe(TemplateIdStringKey) == hexId);
});
}
public override void Run() {
public static string TemplateIdStringKey
{
get { return "KP2A_TemplateId"; }
}
public override void Run() {
StatusLogger.UpdateMessage(UiStringKey.AddingEntry);
List<PwEntry> addedEntries;
@@ -298,10 +310,10 @@ namespace keepass2android
if (addedEntries.Any())
{
_app.GetDb().Dirty.Add(templateGroup);
_app.DirtyGroups.Add(templateGroup);
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun);
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun);
save.SetStatusLogger(StatusLogger);
save.Run();
}
@@ -315,26 +327,28 @@ namespace keepass2android
}
PwGroup templateGroup;
if (!_app.GetDb().Groups.TryGetValue(_app.GetDb().KpDatabase.EntryTemplatesGroup, out templateGroup))
if (!_app.CurrentDb.GroupsById.TryGetValue(_app.CurrentDb.KpDatabase.EntryTemplatesGroup, out templateGroup))
{
//create template group
templateGroup = new PwGroup(true, true, _app.GetResourceString(UiStringKey.TemplateGroupName), PwIcon.Folder);
_app.GetDb().KpDatabase.RootGroup.AddGroup(templateGroup, true);
_app.GetDb().KpDatabase.EntryTemplatesGroup = templateGroup.Uuid;
_app.GetDb().KpDatabase.EntryTemplatesGroupChanged = DateTime.Now;
_app.GetDb().Dirty.Add(_app.GetDb().KpDatabase.RootGroup);
_app.GetDb().Groups[templateGroup.Uuid] = templateGroup;
_app.CurrentDb.KpDatabase.RootGroup.AddGroup(templateGroup, true);
_app.CurrentDb.KpDatabase.EntryTemplatesGroup = templateGroup.Uuid;
_app.CurrentDb.KpDatabase.EntryTemplatesGroupChanged = DateTime.Now;
_app.DirtyGroups.Add(_app.CurrentDb.KpDatabase.RootGroup);
_app.CurrentDb.GroupsById[templateGroup.Uuid] = templateGroup;
_app.CurrentDb.Elements.Add(templateGroup);
}
addedEntries = new List<PwEntry>();
foreach (var template in TemplateEntries)
{
if (_app.GetDb().Entries.ContainsKey(template.Uuid))
if (_app.CurrentDb.EntriesById.ContainsKey(template.Uuid))
continue;
PwEntry entry = CreateEntry(template);
templateGroup.AddEntry(entry, true);
addedEntries.Add(entry);
_app.GetDb().Entries[entry.Uuid] = entry;
_app.CurrentDb.EntriesById[entry.Uuid] = entry;
}
return templateGroup;
}
@@ -373,8 +387,12 @@ namespace keepass2android
base.Run();
}
}
public static bool IsTemplateId(PwUuid pwUuid)
{
return TemplateEntries.Any(te => te.Uuid.Equals(pwUuid));
}
}
}

View File

@@ -27,23 +27,22 @@ namespace keepass2android
{
public class CreateDb : RunnableOnFinish {
private const ulong DefaultEncryptionRounds = PwDefs.DefaultKeyEncryptionRounds;
private readonly IOConnectionInfo _ioc;
private readonly IOConnectionInfo _ioc;
private readonly bool _dontSave;
private readonly Activity _ctx;
private readonly IKp2aApp _app;
private CompositeKey _key;
private readonly bool _makeCurrent;
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(ctx, finish) {
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, bool makeCurrent): base(ctx, finish) {
_ctx = ctx;
_ioc = ioc;
_dontSave = dontSave;
_app = app;
_makeCurrent = makeCurrent;
_app = app;
}
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key)
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key, bool makeCurrent)
: base(ctx, finish)
{
_ctx = ctx;
@@ -51,12 +50,13 @@ namespace keepass2android
_dontSave = dontSave;
_app = app;
_key = key;
_makeCurrent = makeCurrent;
}
public override void Run() {
StatusLogger.UpdateMessage(UiStringKey.progress_create);
Database db = _app.CreateNewDatabase();
Database db = _app.CreateNewDatabase(_makeCurrent);
db.KpDatabase = new KeePassLib.PwDatabase();
@@ -65,7 +65,7 @@ namespace keepass2android
_key = new CompositeKey(); //use a temporary key which should be changed after creation
}
db.KpDatabase.New(_ioc, _key);
db.KpDatabase.New(_ioc, _key, _app.GetFileStorage(_ioc).GetFilenameWithoutPathAndExt(_ioc));
db.KpDatabase.KdfParameters = (new AesKdf()).GetDefaultParameters();
db.KpDatabase.Name = "Keepass2Android Password Database";
@@ -74,7 +74,6 @@ namespace keepass2android
// Set Database state
db.Root = db.KpDatabase.RootGroup;
db.Loaded = true;
db.SearchHelper = new SearchDbHelper(_app);
// Add a couple default groups
@@ -88,12 +87,14 @@ namespace keepass2android
addTemplates.AddTemplates(out addedEntries);
// Commit changes
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, _dontSave);
SaveDb save = new SaveDb(_ctx, _app, db, OnFinishToRun, _dontSave);
save.SetStatusLogger(StatusLogger);
_onFinishToRun = null;
save.Run();
db.UpdateGlobals();
}
}

View File

@@ -31,7 +31,7 @@ namespace keepass2android
public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish):base(activiy, finish, app) {
Ctx = activiy;
Db = app.GetDb();
Db = app.FindDatabaseForElement(entry);
_entry = entry;
}
@@ -40,7 +40,7 @@ namespace keepass2android
{
get
{
return App.GetDb().DatabaseFormat.CanRecycle && CanRecycleGroup(_entry.ParentGroup);
return Db.DatabaseFormat.CanRecycle && CanRecycleGroup(_entry.ParentGroup);
}
}

View File

@@ -47,7 +47,7 @@ namespace keepass2android
*/
private void SetMembers(Activity activity, IKp2aApp app, PwGroup group, bool dontSave)
{
base.SetMembers(activity, app.GetDb());
base.SetMembers(activity, app.FindDatabaseForElement(group));
_group = group;
DontSave = dontSave;
@@ -58,7 +58,7 @@ namespace keepass2android
{
get
{
return App.GetDb().DatabaseFormat.CanRecycle && CanRecycleGroup(_group);
return Db.DatabaseFormat.CanRecycle && CanRecycleGroup(_group);
}
}

View File

@@ -7,12 +7,12 @@ using KeePassLib.Interfaces;
namespace keepass2android
{
public class DeleteMultipleItems : DeleteRunnable
public class DeleteMultipleItemsFromOneDatabase : DeleteRunnable
{
private readonly List<IStructureItem> _elementsToDelete;
private readonly bool _canRecycle;
public DeleteMultipleItems(Activity activity, Database db, List<IStructureItem> elementsToDelete, OnFinish finish, IKp2aApp app)
public DeleteMultipleItemsFromOneDatabase(Activity activity, Database db, List<IStructureItem> elementsToDelete, OnFinish finish, IKp2aApp app)
: base(activity, finish, app)
{
_elementsToDelete = elementsToDelete;
@@ -21,12 +21,13 @@ namespace keepass2android
//determine once. The property is queried for each delete operation, but might return false
//after one entry/group is deleted (and thus in recycle bin and thus can't be recycled anymore)
_canRecycle = DetermineCanRecycle();
ShowDatabaseIocInStatus = true;
}
private bool DetermineCanRecycle()
{
Android.Util.Log.Debug("KP2A", "CanRecycle?");
if (!App.GetDb().DatabaseFormat.CanRecycle)
if (!Db.DatabaseFormat.CanRecycle)
{
Android.Util.Log.Debug("KP2A", "CanRecycle? No because of DB format.");
return false;

View File

@@ -100,7 +100,8 @@ namespace keepass2android
};
Db.KpDatabase.RootGroup.AddGroup(pgRecycleBin, true);
Db.Groups[pgRecycleBin.Uuid] = pgRecycleBin;
Db.GroupsById[pgRecycleBin.Uuid] = pgRecycleBin;
Db.Elements.Add(pgRecycleBin);
Db.KpDatabase.RecycleBinUuid = pgRecycleBin.Uuid;
bGroupListUpdateRequired = true;
@@ -121,24 +122,27 @@ namespace keepass2android
public void Start()
{
if (CanRecycle)
string messageSuffix = ShowDatabaseIocInStatus ? "(" + App.GetFileStorage(Db.Ioc).GetDisplayName(Db.Ioc) + ")" : "";
if (CanRecycle)
{
App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title,
QuestionRecycleResourceId,
(dlgSender, dlgEvt) =>
{
DeletePermanently = true;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
DeletePermanently = true;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
},
(dlgSender, dlgEvt) =>
{
DeletePermanently = false;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
DeletePermanently = false;
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
},
(dlgSender, dlgEvt) => { },
Ctx);
Ctx, messageSuffix);
@@ -149,12 +153,12 @@ namespace keepass2android
QuestionNoRecycleResourceId,
(dlgSender, dlgEvt) =>
{
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
},
null,
(dlgSender, dlgEvt) => { },
Ctx);
Ctx, messageSuffix);
}
@@ -182,7 +186,8 @@ namespace keepass2android
PwDeletedObject pdo = new PwDeletedObject(pe.Uuid, dtNow);
pd.DeletedObjects.Add(pdo);
touchedGroups.Add(pgParent);
Db.Entries.Remove(pe.Uuid);
Db.EntriesById.Remove(pe.Uuid);
Db.Elements.Remove(pe);
}
else // Recycle
{
@@ -215,31 +220,41 @@ namespace keepass2android
if (success)
{
foreach (var g in touchedGroups)
Db.Dirty.Add(g);
App.DirtyGroups.Add(g);
foreach (var g in permanentlyDeletedGroups)
{
//remove groups from global lists if present there
Db.Dirty.Remove(g);
Db.Groups.Remove(g.Uuid);
//remove groups from global lists if present there
App.DirtyGroups.Remove(g);
Db.GroupsById.Remove(g.Uuid);
Db.Elements.Remove(g);
}
}
else
{
// Let's not bother recovering from a failure to save. It is too much work.
App.LockDatabase(false);
App.Lock(false);
}
}, OnFinishToRun);
// Commit database
SaveDb save = new SaveDb(Ctx, App, OnFinishToRun, false);
save.SetStatusLogger(StatusLogger);
SaveDb save = new SaveDb(Ctx, App, Db, OnFinishToRun, false);
save.ShowDatabaseIocInStatus = ShowDatabaseIocInStatus;
save.SetStatusLogger(StatusLogger);
save.Run();
}
protected abstract void PerformDelete(List<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
public bool ShowDatabaseIocInStatus
{
get;
set;
}
protected abstract void PerformDelete(List<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
public abstract UiStringKey StatusMessage { get; }

View File

@@ -26,9 +26,12 @@ namespace keepass2android
public class EditGroup : RunnableOnFinish {
internal Database Db
{
get { return _app.GetDb(); }
get { return _app.FindDatabaseForElement(Group); }
}
private IKp2aApp _app;
public IKp2aApp App { get => _app; }
private IKp2aApp _app;
private readonly String _name;
private readonly PwIcon _iconId;
private readonly PwUuid _customIconId;
@@ -57,7 +60,7 @@ namespace keepass2android
Group.Touch(true);
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun);
SaveDb save = new SaveDb(_ctx, _app, Db, OnFinishToRun);
save.SetStatusLogger(StatusLogger);
save.Run();
}
@@ -76,10 +79,10 @@ namespace keepass2android
if ( Success ) {
// Mark parent group dirty
_editGroup.Db.Dirty.Add(_editGroup.Group.ParentGroup);
_editGroup.App.DirtyGroups.Add(_editGroup.Group.ParentGroup);
} else
{
_editGroup._app.LockDatabase(false);
_editGroup._app.Lock(false);
}
base.Run();

View File

@@ -21,6 +21,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Android.App;
using keepass2android.database.edit;
using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
@@ -36,20 +37,25 @@ namespace keepass2android
private readonly bool _rememberKeyfile;
IDatabaseFormat _format;
public LoadDb(Activity activity, IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish): base(activity, finish)
public LoadDb(Activity activity, IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish, bool updateLastUsageTimestamp, bool makeCurrent): base(activity, finish)
{
_app = app;
_ioc = ioc;
_databaseData = databaseData;
_compositeKey = compositeKey;
_keyfileOrProvider = keyfileOrProvider;
_updateLastUsageTimestamp = updateLastUsageTimestamp;
_makeCurrent = makeCurrent;
_rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);
_rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile);
}
public override void Run()
protected bool success = false;
private bool _updateLastUsageTimestamp;
private readonly bool _makeCurrent;
public override void Run()
{
try
{
@@ -76,8 +82,12 @@ namespace keepass2android
}
//ok, try to load the database. Let's start with Kdbx format and retry later if that is the wrong guess:
_format = new KdbxDatabaseFormat(KdbpFile.GetFormatToUse(_ioc));
_format = new KdbxDatabaseFormat(KdbpFile.GetFormatToUse(_app.GetFileStorage(_ioc).GetFileExtension(_ioc)));
TryLoad(databaseStream);
success = true;
}
catch (Exception e)
{
@@ -89,7 +99,7 @@ namespace keepass2android
{
Kp2aLog.Log("KeyFileException");
Finish(false, /*TODO Localize: use Keepass error text KPRes.KeyFileError (including "or invalid format")*/
_app.GetResourceString(UiStringKey.keyfile_does_not_exist), Exception);
_app.GetResourceString(UiStringKey.keyfile_does_not_exist), false, Exception);
}
catch (AggregateException e)
{
@@ -100,20 +110,20 @@ namespace keepass2android
// Override the message shown with the last (hopefully most recent) inner exception
Kp2aLog.LogUnexpectedError(innerException);
}
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + message, Exception);
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + message, false, Exception);
return;
}
catch (DuplicateUuidsException e)
{
Kp2aLog.Log(e.ToString());
Finish(false, _app.GetResourceString(UiStringKey.DuplicateUuidsError) + " " + e.Message + _app.GetResourceString(UiStringKey.DuplicateUuidsErrorAdditional), Exception);
Finish(false, _app.GetResourceString(UiStringKey.DuplicateUuidsError) + " " + e.Message + _app.GetResourceString(UiStringKey.DuplicateUuidsErrorAdditional), false, Exception);
return;
}
catch (Exception e)
{
if (!(e is InvalidCompositeKeyException))
Kp2aLog.LogUnexpectedError(e);
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, Exception);
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message, false, Exception);
return;
}
@@ -125,7 +135,7 @@ namespace keepass2android
/// </summary>
public Exception Exception { get; set; }
private void TryLoad(MemoryStream databaseStream)
Database TryLoad(MemoryStream databaseStream)
{
//create a copy of the stream so we can try again if we get an exception which indicates we should change parameters
//This is not optimal in terms of (short-time) memory usage but is hard to avoid because the Keepass library closes streams also in case of errors.
@@ -138,19 +148,16 @@ namespace keepass2android
//now let's go:
try
{
_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
Database newDb = _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format, _makeCurrent);
Kp2aLog.Log("LoadDB OK");
//make sure the stored access time for the actual file is more recent than that of its backup
Thread.Sleep(10);
SaveFileData(_ioc, _keyfileOrProvider);
Finish(true, _format.SuccessMessage);
return newDb;
}
catch (OldFormatException)
{
_format = new KdbDatabaseFormat(_app);
TryLoad(databaseStream);
return TryLoad(databaseStream);
}
catch (InvalidCompositeKeyException)
{
@@ -162,7 +169,7 @@ namespace keepass2android
//retry without password:
_compositeKey.RemoveUserKey(passwordKey);
//retry:
TryLoad(databaseStream);
return TryLoad(databaseStream);
}
else throw;
}
@@ -175,7 +182,7 @@ namespace keepass2android
{
keyfileOrProvider = "";
}
_app.StoreOpenedFileAsRecent(ioc, keyfileOrProvider);
_app.StoreOpenedFileAsRecent(ioc, keyfileOrProvider, _updateLastUsageTimestamp);
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Android.App;
@@ -50,10 +51,19 @@ namespace keepass2android.database.edit
}
HashSet<Database> removeDatabases = new HashSet<Database>();
Database addDatabase = _app.FindDatabaseForElement(_targetGroup);
if (addDatabase == null)
{
Finish(false, "Did not find target database. Did you lock it?");
return;
}
foreach (var elementToMove in _elementsToMove)
{
_app.GetDb().Dirty.Add(elementToMove.ParentGroup);
_app.DirtyGroups.Add(elementToMove.ParentGroup);
PwGroup pgParent = elementToMove.ParentGroup;
if (pgParent != _targetGroup)
@@ -63,8 +73,14 @@ namespace keepass2android.database.edit
PwEntry entry = elementToMove as PwEntry;
if (entry != null)
{
var dbRem = _app.FindDatabaseForElement(entry);
removeDatabases.Add(dbRem);
dbRem.EntriesById.Remove(entry.Uuid);
dbRem.Elements.Remove(entry);
pgParent.Entries.Remove(entry);
_targetGroup.AddEntry(entry, true, true);
addDatabase.EntriesById.Add(entry.Uuid, entry);
addDatabase.Elements.Add(entry);
}
else
{
@@ -74,27 +90,60 @@ namespace keepass2android.database.edit
Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
return;
}
var dbRem = _app.FindDatabaseForElement(@group);
if (dbRem == null)
{
Finish(false, "Did not find source database. Did you lock it?");
return;
}
dbRem.GroupsById.Remove(group.Uuid);
dbRem.Elements.Remove(group);
removeDatabases.Add(dbRem);
pgParent.Groups.Remove(group);
_targetGroup.AddGroup(group, true, true);
addDatabase.GroupsById.Add(group.Uuid, group);
addDatabase.Elements.Add(group);
}
}
}
}
_onFinishToRun = new ActionOnFinish(ActiveActivity, (success, message, activity) =>
{
if (!success)
{ // Let's not bother recovering from a failure.
_app.LockDatabase(false);
}
}, OnFinishToRun);
// Save
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, false);
save.SetStatusLogger(StatusLogger);
save.Run();
//first save the database where we added the elements
var allDatabasesToSave = new List<Database> {addDatabase};
//then all databases where we removed elements:
removeDatabases.RemoveWhere(db => db == addDatabase);
allDatabasesToSave.AddRange(removeDatabases);
int indexToSave = 0;
bool allSavesSuccess = true;
void ContinueSave(bool success, string message, Activity activeActivity)
{
allSavesSuccess &= success;
indexToSave++;
if (indexToSave == allDatabasesToSave.Count)
{
OnFinishToRun.SetResult(allSavesSuccess);
OnFinishToRun.Run();
return;
}
SaveDb saveDb = new SaveDb(_ctx, _app, allDatabasesToSave[indexToSave], new ActionOnFinish(activeActivity, ContinueSave), false);
saveDb.SetStatusLogger(StatusLogger);
saveDb.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
saveDb.Run();
}
SaveDb save = new SaveDb(_ctx, _app, allDatabasesToSave[0], new ActionOnFinish(ActiveActivity, ContinueSave), false);
save.SetStatusLogger(StatusLogger);
save.ShowDatabaseIocInStatus = allDatabasesToSave.Count > 1;
save.Run();
}
}
}

View File

@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System;
using Android;
using Android.App;
using Android.Content;
using Android.OS;
@@ -28,8 +29,14 @@ namespace keepass2android
protected bool Success;
protected String Message;
protected Exception Exception;
protected OnFinish BaseOnFinish;
protected bool ImportantMessage
{
get;
set;
}
protected OnFinish BaseOnFinish;
protected Handler Handler;
private ProgressDialogStatusLogger _statusLogger = new ProgressDialogStatusLogger(); //default: no logging but not null -> can be used whenever desired
private Activity _activeActivity;
@@ -77,20 +84,22 @@ namespace keepass2android
Handler = null;
}
public void SetResult(bool success, string message, Exception exception) {
public void SetResult(bool success, string message, bool importantMessage, Exception exception) {
Success = success;
Message = message;
ImportantMessage = importantMessage;
Exception = exception;
}
public void SetResult(bool success) {
public void SetResult(bool success) {
Success = success;
}
public virtual void Run() {
if (BaseOnFinish == null) return;
// Pass on result on call finish
BaseOnFinish.SetResult(Success, Message, Exception);
BaseOnFinish.SetResult(Success, Message, ImportantMessage, Exception);
if ( Handler != null ) {
Handler.Post(BaseOnFinish.Run);
@@ -100,14 +109,31 @@ namespace keepass2android
}
protected void DisplayMessage(Context ctx) {
DisplayMessage(ctx, Message);
DisplayMessage(ctx, Message, ImportantMessage);
}
public static void DisplayMessage(Context ctx, string message)
public static void DisplayMessage(Context ctx, string message, bool makeDialog)
{
if ( !String.IsNullOrEmpty(message) ) {
Kp2aLog.Log("OnFinish message: "+message);
Toast.MakeText(ctx ?? Application.Context, message, ToastLength.Long).Show();
Kp2aLog.Log("OnFinish message: " + message);
if (makeDialog && ctx != null)
{
try
{
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.SetMessage(message)
.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ((Dialog)sender).Dismiss())
.Show();
}
catch (Exception)
{
Toast.MakeText(ctx, message, ToastLength.Long).Show();
}
}
else
Toast.MakeText(ctx ?? Application.Context, message, ToastLength.Long).Show();
}
}
}

View File

@@ -50,9 +50,9 @@ namespace keepass2android
}
}
protected void Finish(bool result, String message, Exception exception = null) {
protected void Finish(bool result, String message, bool importantMessage = false, Exception exception = null) {
if ( OnFinishToRun != null ) {
OnFinishToRun.SetResult(result, message, exception);
OnFinishToRun.SetResult(result, message, importantMessage, exception);
OnFinishToRun.Run();
}
}

View File

@@ -34,7 +34,8 @@ namespace keepass2android
public class SaveDb : RunnableOnFinish {
private readonly IKp2aApp _app;
private readonly bool _dontSave;
private readonly Database _db;
private readonly bool _dontSave;
/// <summary>
/// stream for reading the data from the original file. If this is set to a non-null value, we know we need to sync
@@ -43,9 +44,10 @@ namespace keepass2android
private readonly Context _ctx;
private Thread _workerThread;
public SaveDb(Activity ctx, IKp2aApp app, OnFinish finish, bool dontSave)
public SaveDb(Activity ctx, IKp2aApp app, Database db, OnFinish finish, bool dontSave)
: base(ctx, finish)
{
_db = db;
_ctx = ctx;
_app = app;
_dontSave = dontSave;
@@ -59,46 +61,55 @@ namespace keepass2android
/// <param name="finish"></param>
/// <param name="dontSave"></param>
/// <param name="streamForOrigFile">Stream for reading the data from the (changed) original location</param>
public SaveDb(Activity ctx, IKp2aApp app, OnFinish finish, bool dontSave, Stream streamForOrigFile)
public SaveDb(Activity ctx, IKp2aApp app, OnFinish finish, Database db, bool dontSave, Stream streamForOrigFile)
: base(ctx, finish)
{
_db = db;
_ctx = ctx;
_app = app;
_dontSave = dontSave;
_streamForOrigFile = streamForOrigFile;
}
public SaveDb(Activity ctx, IKp2aApp app, OnFinish finish)
public SaveDb(Activity ctx, IKp2aApp app, Database db, OnFinish finish)
: base(ctx, finish)
{
_ctx = ctx;
_app = app;
_dontSave = false;
_db = db;
_dontSave = false;
}
public override void Run ()
public bool ShowDatabaseIocInStatus { get; set; }
public override void Run ()
{
if (!_dontSave)
{
try
{
if (_app.GetDb().CanWrite == false)
if (_db.CanWrite == false)
{
//this should only happen if there is a problem in the UI so that the user sees an edit interface.
Finish(false,"Cannot save changes. File is read-only!");
return;
}
StatusLogger.UpdateMessage(UiStringKey.saving_database);
IOConnectionInfo ioc = _app.GetDb().Ioc;
string message = _app.GetResourceString(UiStringKey.saving_database);
if (ShowDatabaseIocInStatus)
message += " (" + _app.GetFileStorage(_db.Ioc).GetDisplayName(_db.Ioc) + ")";
StatusLogger.UpdateMessage(message);
IOConnectionInfo ioc = _db.Ioc;
IFileStorage fileStorage = _app.GetFileStorage(ioc);
if (_streamForOrigFile == null)
{
if ((!_app.GetBooleanPreference(PreferenceKey.CheckForFileChangesOnSave))
|| (_app.GetDb().KpDatabase.HashOfFileOnDisk == null)) //first time saving
|| (_db.KpDatabase.HashOfFileOnDisk == null)) //first time saving
{
PerformSaveWithoutCheck(fileStorage, ioc);
Finish(true);
@@ -109,8 +120,8 @@ namespace keepass2android
if (
(_streamForOrigFile != null)
|| fileStorage.CheckForFileChangeFast(ioc, _app.GetDb().LastFileVersion) //first try to use the fast change detection
|| (FileHashChanged(ioc, _app.GetDb().KpDatabase.HashOfFileOnDisk) == FileHashChange.Changed) //if that fails, hash the file and compare:
|| fileStorage.CheckForFileChangeFast(ioc, _db.LastFileVersion) //first try to use the fast change detection
|| (FileHashChanged(ioc, _db.KpDatabase.HashOfFileOnDisk) == FileHashChange.Changed) //if that fails, hash the file and compare:
)
{
@@ -128,6 +139,7 @@ namespace keepass2android
//small.
MergeIn(fileStorage, ioc);
PerformSaveWithoutCheck(fileStorage, ioc);
_db.UpdateGlobals();
Finish(true);
};
RunInWorkerThread(runHandler);
@@ -217,13 +229,13 @@ namespace keepass2android
StatusLogger.UpdateSubMessage(_app.GetResourceString(UiStringKey.SynchronizingDatabase));
PwDatabase pwImp = new PwDatabase();
PwDatabase pwDatabase = _app.GetDb().KpDatabase;
pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey);
PwDatabase pwDatabase = _db.KpDatabase;
pwImp.New(new IOConnectionInfo(), pwDatabase.MasterKey, _app.GetFileStorage(ioc).GetFilenameWithoutPathAndExt(ioc));
pwImp.MemoryProtection = pwDatabase.MemoryProtection.CloneDeep();
pwImp.MasterKey = pwDatabase.MasterKey;
var stream = GetStreamForBaseFile(fileStorage, ioc);
_app.GetDb().DatabaseFormat.PopulateDatabaseFromStream(pwImp, stream, null);
_db.DatabaseFormat.PopulateDatabaseFromStream(pwImp, stream, null);
pwDatabase.MergeIn(pwImp, PwMergeMethod.Synchronize, null);
@@ -249,8 +261,8 @@ namespace keepass2android
private void PerformSaveWithoutCheck(IFileStorage fileStorage, IOConnectionInfo ioc)
{
StatusLogger.UpdateSubMessage("");
_app.GetDb().SaveData();
_app.GetDb().LastFileVersion = fileStorage.GetCurrentFileVersionFast(ioc);
_db.SaveData();
_db.LastFileVersion = fileStorage.GetCurrentFileVersionFast(ioc);
}
public byte[] HashOriginalFile(IOConnectionInfo iocFile)

View File

@@ -52,7 +52,7 @@ namespace keepass2android
public override void Run ()
{
StatusLogger.UpdateMessage(UiStringKey.SettingPassword);
PwDatabase pm = _app.GetDb().KpDatabase;
PwDatabase pm = _app.CurrentDb.KpDatabase;
CompositeKey newKey = new CompositeKey ();
if (String.IsNullOrEmpty (_password) == false) {
newKey.AddUserKey (new KcpPassword (_password));
@@ -74,7 +74,7 @@ namespace keepass2android
// Save Database
_onFinishToRun = new AfterSave(ActiveActivity, previousKey, previousMasterKeyChanged, pm, OnFinishToRun);
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, _dontSave);
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, _dontSave);
save.SetStatusLogger(StatusLogger);
save.Run();
}

View File

@@ -36,7 +36,7 @@ namespace keepass2android
public override void Run() {
// Commit to disk
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun);
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun);
save.SetStatusLogger(StatusLogger);
save.Run();
}
@@ -59,7 +59,7 @@ namespace keepass2android
if ( parent != null ) {
// Mark parent group dirty
_app.GetDb().Dirty.Add(parent);
_app.DirtyGroups.Add(parent);
}

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Xamarin.Android.Arch.Core.Common" version="1.0.0" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Arch.Lifecycle.Common" version="1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Arch.Lifecycle.Runtime" version="1.0.0" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Annotations" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Core.UI" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Core.Utils" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Fragment" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.Media.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.v13" version="26.1.0.1" targetFramework="monoandroid81" />
<package id="Xamarin.Android.Support.v4" version="23.1.1.0" targetFramework="MonoAndroid50" />
</packages>

View File

@@ -10,8 +10,8 @@
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<AssemblyName>Kp2aKeyboardBinding</AssemblyName>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
@@ -63,6 +63,8 @@
<TransformFile Include="Transforms\EnumMethods.xml" />
<TransformFile Include="Transforms\Metadata.xml" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildExtensionsPath)\Novell\Xamarin.Android.Bindings.targets" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
<ItemGroup>
<Folder Include="libs\" />
</ItemGroup>
</Project>

View File

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

View File

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

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,75 @@
<?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>
<ProjectGuid>{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}</ProjectGuid>
<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>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</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>0</WarningLevel>
<AndroidLinkMode>None</AndroidLinkMode>
</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>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseNoNet|AnyCPU'">
<OutputPath>bin\ReleaseNoNet\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<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\pcloud-sdk-android-1.1.0.aar" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Transforms\Metadata.xml" />
<TransformFile Include="Transforms\EnumFields.xml" />
<TransformFile Include="Transforms\EnumMethods.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\pcloud-sdk-java-core-1.1.0.jar" />
</ItemGroup>
</Project>

View 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("PCloudBindings")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PCloudBindings")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
<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.pcloud.sdk']" />
</metadata>

View File

@@ -11,7 +11,7 @@
<AssemblyName>PluginSdkBinding</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -53,8 +53,8 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\app-release.aar">
<Link>Jars\app-release.aar</Link>
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\Keepass2AndroidPluginSDK2-release.aar">
<Link>Jars\Keepass2AndroidPluginSDK2-release.aar</Link>
</LibraryProjectZip>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />

View File

@@ -12,8 +12,8 @@
<FileAlignment>512</FileAlignment>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

View File

@@ -11,9 +11,9 @@
<AndroidResgenClass>Resource</AndroidResgenClass>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
<AssemblyName>ZlibAndroid</AssemblyName>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

Some files were not shown because too many files have changed in this diff Show More