Compare commits

..

154 Commits

Author SHA1 Message Date
Philipp Crocoll
26c37bcd2a fix implementation of yubikey secret reading 2025-04-15 12:44:43 +02:00
PhilippC
1980f05a7c Merge pull request #2844 from PhilippC/2837-improve-error-reporting
Improve error reporting and fix crash
2025-04-15 12:17:18 +02:00
Philipp Crocoll
dbf10ba9fb Improve error reporting: Extract original message when showing "Java exception messages" consistently. Improve error handling in deprecated OneDrive API stub and avoid crash by no-longer throwing in Main-thread methods. 2025-04-15 11:45:16 +02:00
PhilippC
4be18d8373 Merge pull request #2830 from PhilippC/754-crash-when-using-fingerprint-before-otp
Fix crash when combining biometric unlock and KeeChallenge/OTP.
2025-04-15 11:42:59 +02:00
Philipp Crocoll
8e256ac94d fix crash when combining biometric unlock and KeeChallenge/OTP. 2025-04-08 16:27:52 +02:00
Philipp Crocoll
65ff09f866 Manifest for 1.12-r4 2025-04-08 15:31:56 +02:00
Philipp Crocoll
8e9c2824cf add some files for building on Linux 2025-04-08 14:16:39 +02:00
PhilippC
92b8ff5c8d Merge pull request #2827 from PhilippC/2816-bug-yubikey-not-working-in-112
fix reading of cryptostream. Fixes Yubikey/KeeChallenge regression in 1.12-r1 .. 1.12-r3
2025-04-08 12:57:36 +02:00
PhilippC
223c3bfb8e Merge pull request #2826 from PhilippC/feature/snackbar-messages
use snackbars instead of toasts
2025-04-08 12:56:23 +02:00
PhilippC
b4e03a8374 Merge pull request #2797 from PhilippC/l10n_master3
New Crowdin updates
2025-04-08 12:41:50 +02:00
PhilippC
fb2df35d37 Merge pull request #2828 from PhilippC/2818-feat-new-color-scheme-too-beige-green
slightly adjust background color to become true gray.
2025-04-08 12:34:55 +02:00
Philipp Crocoll
345dad5d04 slightly adjust background color to become true gray. closes #2818 2025-04-08 12:34:07 +02:00
Philipp Crocoll
50d6598b02 fix reading of cryptostream. The implementation issue became a bug in .net8. Closes #2816 2025-04-08 12:25:29 +02:00
Philipp Crocoll
90f04b76f4 fix issue with MessagePresenter potentially crashing 2025-04-08 12:20:24 +02:00
Philipp Crocoll
8b4314c394 fix bug with messages not always showing as they should. 2025-04-08 11:25:43 +02:00
Philipp Crocoll
17241bc422 use snackbars instead of toasts (in most cases) 2025-04-08 10:37:40 +02:00
PhilippC
c4a73bf107 New translations strings.xml (Czech) 2025-04-04 15:32:59 +02:00
Philipp Crocoll
e76f3999b6 reduce logging verbosity of file provider 2025-04-01 15:36:39 +02:00
Philipp Crocoll
0567bfe645 fix wiki links 2025-04-01 12:42:43 +02:00
Philipp Crocoll
6043bdbc48 * restore some files which are link targets from within the app or the web. add links to the corresponding new wiki pages if possible. 2025-04-01 12:38:58 +02:00
PhilippC
4ba40ba24f New translations strings.xml (Slovenian) 2025-03-27 12:19:23 +01:00
PhilippC
e2711b709d New translations strings.xml (Portuguese, Brazilian) 2025-03-26 12:13:50 +01:00
PhilippC
4764b15e75 New translations strings.xml (Portuguese, Brazilian) 2025-03-26 09:06:54 +01:00
PhilippC
1b389ef12e New translations strings.xml (Japanese) 2025-03-26 09:06:43 +01:00
PhilippC
b32c2dbc7e New translations strings.xml (Czech) 2025-03-26 09:06:37 +01:00
PhilippC
f06937dab3 New translations strings.xml (French) 2025-03-26 09:06:32 +01:00
PhilippC
14efce62ff New translations strings.xml (Slovenian) 2025-03-26 09:06:29 +01:00
PhilippC
3c8b530e2e New translations strings.xml (Slovak) 2025-03-26 09:06:28 +01:00
PhilippC
9939e07b7d New translations strings.xml (Italian) 2025-03-26 09:06:27 +01:00
PhilippC
ecf416febc New translations strings.xml (German) 2025-03-26 09:06:25 +01:00
Philipp Crocoll
f949e6e389 add an item to the changelog for 1.12 2025-03-26 08:49:57 +01:00
Philipp Crocoll
15bf08f5e6 fix crash in NoSecureDisplayActivity by removing superfluous toolbar creation 2025-03-26 08:49:35 +01:00
Philipp Crocoll
fa69f38ab1 add some more error logging 2025-03-26 08:49:11 +01:00
Philipp Crocoll
d3b06080eb remove docs from repo. has been moved to https://github.com/PhilippC/keepass2android/wiki 2025-03-26 08:36:43 +01:00
PhilippC
749ab330ff Merge pull request #2815 from PhilippC/bugfix/list-onedrive-shares-failing
Improve OneDrive implementation
2025-03-25 17:01:01 +01:00
Philipp Crocoll
677c6555e8 this change fixes an issue with OneDrive: sometimes, the wrong DriveId was used to list the user's shares which was leading to an empty file browser screen. Also, files can be used if they are shared directly (not the parent folder) 2025-03-25 12:31:35 +01:00
PhilippC
c62f6ef139 Merge pull request #2814 from PhilippC/feature/otpauth-uris
Add support for otpauth:// URIs
2025-03-25 12:27:11 +01:00
Philipp Crocoll
0c34625782 Merge remote-tracking branch 'remotes/origin/master' into feature/otpauth-uris 2025-03-25 10:56:42 +01:00
Philipp Crocoll
e86fa6f9fa add support for otpauth:// URIs 2025-03-25 10:56:24 +01:00
PhilippC
e2e975f357 Merge pull request #2805 from PhilippC/feature/debug-improvements
Improve debugging experience
2025-03-25 10:53:02 +01:00
Philipp Crocoll
8eaf6d3f88 add comment in Makefile 2025-03-25 10:52:33 +01:00
PhilippC
1cb036941e New translations strings.xml (Vietnamese) 2025-03-23 09:12:18 +01:00
PhilippC
a53ff37e89 New translations strings.xml (Vietnamese) 2025-03-23 07:30:07 +01:00
PhilippC
dc3ee35c8b New translations strings.xml (Italian) 2025-03-21 14:54:31 +01:00
PhilippC
e05fe94650 New translations strings.xml (Italian) 2025-03-20 21:28:17 +01:00
PhilippC
b0cb0b06a2 New translations strings.xml (German) 2025-03-20 19:11:11 +01:00
PhilippC
a9fed1c203 Merge pull request #2804 from PhilippC/bugfix/gdrive-class-def-not-found
Bugfix/gdrive class def not found
2025-03-18 17:07:33 +01:00
Philipp Crocoll
6d8407676d add a custom "Kp2a debug" icon for distinguishability. remove an Assert we don't use and which should fire during debugging. 2025-03-18 16:43:47 +01:00
Philipp Crocoll
1157716c9c manifest for 1.12-r3 2025-03-18 16:35:58 +01:00
Philipp Crocoll
861615b7a4 update AndroidX packages and add missing dependencies to Guava and PlayServices.Auth. 2025-03-18 16:34:31 +01:00
Philipp Crocoll
e12d11264e switch to testing Google Drive 2025-03-18 16:32:55 +01:00
PhilippC
6d7b4810da New translations strings.xml (Hungarian) 2025-03-18 13:16:38 +01:00
PhilippC
585b747612 New translations strings.xml (Hungarian) 2025-03-18 11:35:13 +01:00
PhilippC
55887e1a89 New translations strings.xml (Slovak) 2025-03-17 18:31:07 +01:00
PhilippC
39a7a1298a New translations strings.xml (Romanian) 2025-03-14 09:08:28 +01:00
PhilippC
90059c5ae6 New translations strings.xml (Romanian) 2025-03-14 09:08:27 +01:00
PhilippC
ad63179484 New translations strings.xml (Romanian) 2025-03-14 07:51:48 +01:00
PhilippC
6eaba9d3a8 New translations strings.xml (Chinese Simplified) 2025-03-13 08:11:39 +01:00
PhilippC
11ce68902c New translations strings.xml (Slovenian) 2025-03-13 08:11:38 +01:00
PhilippC
70ca059e0f New translations strings.xml (Portuguese, Brazilian) 2025-03-12 00:48:40 +01:00
Philipp Crocoll
6588f40007 manifest for v1.12-r2 2025-03-11 18:31:06 +01:00
PhilippC
67aaba0656 Merge pull request #2787 from PhilippC/l10n_master3
New Crowdin updates
2025-03-11 16:59:24 +01:00
PhilippC
2d8eac4f12 Merge pull request #2796 from PhilippC/feature/improve-help-texts
improve help texts
2025-03-11 16:43:49 +01:00
Philipp Crocoll
00d822ad4b * show a toast when users without Play services are trying to scan a QR code (#2791)
* show a message informing that built-in Google Drive support is more and more restricted by Google (#2788)
2025-03-11 16:43:13 +01:00
PhilippC
5cf15b26b9 Merge pull request #2795 from PhilippC/bugfix/autofill-fixes
Autofill fixes
2025-03-11 16:37:31 +01:00
Philipp Crocoll
07f08a8851 autofill: avoid crash when looking up a null key.
closes https://github.com/PhilippC/keepass2android/issues/2362
2025-03-11 16:11:35 +01:00
Philipp Crocoll
d2e0ae6394 after updating to targetSdkVersion=34, an implicit mutable intent could lead to a crash.
closes https://github.com/PhilippC/keepass2android/issues/2790
2025-03-11 16:10:52 +01:00
PhilippC
cbae7c38cf New translations strings.xml (Romanian) 2025-03-07 12:55:01 +01:00
PhilippC
15656109bc New translations strings.xml (Romanian) 2025-03-07 11:03:36 +01:00
PhilippC
93e415120a New translations strings.xml (Slovak) 2025-03-06 13:19:21 +01:00
PhilippC
c47e7c03f9 New translations strings.xml (Portuguese, Brazilian) 2025-03-06 11:20:24 +01:00
PhilippC
125512d2c3 New translations strings.xml (French) 2025-03-05 23:47:24 +01:00
PhilippC
65b0d31762 New translations strings.xml (French) 2025-03-05 22:50:35 +01:00
PhilippC
9103529b64 New translations strings.xml (Japanese) 2025-03-05 15:46:39 +01:00
PhilippC
349952cb52 New translations strings.xml (Czech) 2025-03-05 15:46:38 +01:00
PhilippC
305cf6b050 New translations strings.xml (Slovenian) 2025-03-05 14:14:47 +01:00
PhilippC
78ff49a6d4 New translations strings.xml (Portuguese, Brazilian) 2025-03-04 15:38:10 +01:00
Philipp Crocoll
9cd8996aeb manifest and changelog for 1.12-r1 2025-03-04 15:01:19 +01:00
PhilippC
25232a4146 New translations strings.xml (Portuguese, Brazilian) 2025-03-04 14:29:54 +01:00
PhilippC
5266d2f985 New translations strings.xml (Romanian) 2025-03-04 13:19:32 +01:00
PhilippC
ae35d5873a Merge pull request #2785 from PhilippC/bugfix/webdav-fileselect-not-working-always
Bugfix: Webdav username and password could got lost during file selection
2025-03-04 12:25:26 +01:00
PhilippC
fe9aaa0d29 Merge pull request #2786 from PhilippC/bugfix/webdav-dialog-crashing
add a theme to SelectStorageLocationActivity
2025-03-04 12:16:08 +01:00
PhilippC
076bde7669 Merge pull request #2784 from PhilippC/l10n_master3
New Crowdin updates
2025-03-04 12:11:29 +01:00
Philipp Crocoll
592bee1ac1 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2025-03-04 11:58:13 +01:00
Philipp Crocoll
c9a7d56da4 Webdav username and password could got lost during file selection (seems to depend on server behavior in PROPFIND request). Fix this for these cases. 2025-03-04 11:55:10 +01:00
PhilippC
2157cc8e4a New translations strings.xml (Romanian) 2025-03-04 11:54:51 +01:00
Philipp Crocoll
2cd11ba50e add a theme to SelectStorageLocationActivity. without, the webdav credential dialog was crashing. 2025-02-25 16:15:45 +01:00
Philipp Crocoll
eddcedd00b manifest and changelog for 1.12-r0. Fix changelog to adhere to theme. 2025-02-25 13:02:29 +01:00
PhilippC
0d4fe11cfb Merge pull request #2772 from PhilippC/l10n_master3
New Crowdin updates
2025-02-25 11:07:18 +01:00
PhilippC
ecbf4e511d New translations strings.xml (Spanish) 2025-02-24 14:24:35 +01:00
PhilippC
16bbae832e New translations strings.xml (Slovenian) 2025-02-17 08:34:55 +01:00
PhilippC
571da788d0 New translations strings.xml (Slovak) 2025-02-14 22:47:24 +01:00
PhilippC
f2eed5ece0 New translations strings.xml (Slovak) 2025-02-14 21:28:37 +01:00
PhilippC
2c5516310f New translations strings.xml (Chinese Simplified) 2025-02-12 12:55:34 +01:00
PhilippC
5550dffab8 New translations strings.xml (Portuguese, Brazilian) 2025-02-11 23:57:51 +01:00
PhilippC
b9744dd6b5 New translations strings.xml (German) 2025-02-11 18:28:15 +01:00
PhilippC
82fedb3526 Merge pull request #2771 from PhilippC/l10n_master3
New Crowdin updates
2025-02-11 17:16:10 +01:00
PhilippC
cc4f0a3dec Merge pull request #2768 from PhilippC/update/upgrade-dropbox-sdk-to-7-0-0
upgrade Dropbox SDK to 7.0.0.
2025-02-11 17:06:30 +01:00
PhilippC
cdfa48d942 New translations strings.xml (German) 2025-02-11 16:48:42 +01:00
PhilippC
c4edc871b3 New translations strings.xml (German) 2025-02-11 16:43:20 +01:00
PhilippC
ed6d1d2aaf New translations strings.xml (German) 2025-02-11 16:43:03 +01:00
PhilippC
b0f56dbb2c New translations strings.xml (German) 2025-02-11 16:42:44 +01:00
PhilippC
c794efe899 New translations strings.xml (Yoruba) 2025-02-11 16:19:20 +01:00
PhilippC
c2fb4f103d New translations strings.xml (Vietnamese) 2025-02-11 16:19:15 +01:00
PhilippC
18b192bc42 New translations strings.xml (Hebrew) 2025-02-11 16:19:08 +01:00
PhilippC
522fc9816d New translations strings.xml (German) 2025-02-11 16:19:06 +01:00
PhilippC
3be4fb8460 New translations strings.xml (Romanian) 2025-02-11 16:19:02 +01:00
PhilippC
7ca07814bb New translations strings.xml (Yoruba) 2025-02-11 16:19:01 +01:00
PhilippC
aaea8ed956 New translations strings.xml (Vietnamese) 2025-02-11 16:18:57 +01:00
PhilippC
822ccdc349 New translations strings.xml (German) 2025-02-11 16:18:49 +01:00
PhilippC
dbc1b9553a New translations strings.xml (Yoruba) 2025-02-11 16:18:45 +01:00
PhilippC
04c5f08f5f New translations strings.xml (Norwegian Bokmal) 2025-02-11 16:18:44 +01:00
PhilippC
5c10385246 New translations strings.xml (Sinhala) 2025-02-11 16:18:43 +01:00
PhilippC
90f9b6f414 New translations strings.xml (Malayalam) 2025-02-11 16:18:42 +01:00
PhilippC
b555194d8e New translations strings.xml (Azerbaijani) 2025-02-11 16:18:41 +01:00
PhilippC
0e7c4eced7 New translations strings.xml (Norwegian Nynorsk) 2025-02-11 16:18:41 +01:00
PhilippC
816a40d0ec New translations strings.xml (Croatian) 2025-02-11 16:18:40 +01:00
PhilippC
75a819b7b4 New translations strings.xml (Persian) 2025-02-11 16:18:39 +01:00
PhilippC
cf0e5be55c New translations strings.xml (Indonesian) 2025-02-11 16:18:38 +01:00
PhilippC
492fb404fe New translations strings.xml (Portuguese, Brazilian) 2025-02-11 16:18:37 +01:00
PhilippC
6453d215eb New translations strings.xml (Galician) 2025-02-11 16:18:36 +01:00
PhilippC
35f13eff53 New translations strings.xml (Vietnamese) 2025-02-11 16:18:34 +01:00
PhilippC
fe2c5185eb New translations strings.xml (Chinese Traditional) 2025-02-11 16:18:33 +01:00
PhilippC
f1429c0d0d New translations strings.xml (Chinese Simplified) 2025-02-11 16:18:32 +01:00
PhilippC
d6e30b805d New translations strings.xml (Ukrainian) 2025-02-11 16:18:31 +01:00
PhilippC
e8aeaf71d4 New translations strings.xml (Turkish) 2025-02-11 16:18:30 +01:00
PhilippC
1500d635e9 New translations strings.xml (Swedish) 2025-02-11 16:18:29 +01:00
PhilippC
27798ea073 New translations strings.xml (Serbian (Cyrillic)) 2025-02-11 16:18:28 +01:00
PhilippC
891918269e New translations strings.xml (Slovenian) 2025-02-11 16:18:28 +01:00
PhilippC
0cf8ec67da New translations strings.xml (Slovak) 2025-02-11 16:18:27 +01:00
PhilippC
217a3d107d New translations strings.xml (Russian) 2025-02-11 16:18:26 +01:00
PhilippC
38a229cb78 New translations strings.xml (Portuguese) 2025-02-11 16:18:24 +01:00
PhilippC
0598d49ba0 New translations strings.xml (Polish) 2025-02-11 16:18:24 +01:00
PhilippC
f8f2dbc7f4 New translations strings.xml (Dutch) 2025-02-11 16:18:22 +01:00
PhilippC
7449d5dbb1 New translations strings.xml (Korean) 2025-02-11 16:18:22 +01:00
PhilippC
a890b0f66e New translations strings.xml (Japanese) 2025-02-11 16:18:21 +01:00
PhilippC
1647ed455e New translations strings.xml (Italian) 2025-02-11 16:18:20 +01:00
PhilippC
a383847d5b New translations strings.xml (Hungarian) 2025-02-11 16:18:19 +01:00
PhilippC
3fb2a824cf New translations strings.xml (Hebrew) 2025-02-11 16:18:18 +01:00
PhilippC
dd7579ce7c New translations strings.xml (Finnish) 2025-02-11 16:18:17 +01:00
PhilippC
49c51ceea4 New translations strings.xml (Basque) 2025-02-11 16:18:16 +01:00
PhilippC
a5370793cb New translations strings.xml (Greek) 2025-02-11 16:18:15 +01:00
PhilippC
6f72020607 New translations strings.xml (German) 2025-02-11 16:18:14 +01:00
PhilippC
6a7c61ea3c New translations strings.xml (Danish) 2025-02-11 16:18:13 +01:00
PhilippC
46c1854481 New translations strings.xml (Czech) 2025-02-11 16:18:12 +01:00
PhilippC
72030a4749 New translations strings.xml (Catalan) 2025-02-11 16:18:11 +01:00
PhilippC
1c18884527 New translations strings.xml (Bulgarian) 2025-02-11 16:18:10 +01:00
PhilippC
1c5c695f4f New translations strings.xml (Belarusian) 2025-02-11 16:18:09 +01:00
PhilippC
a1cef1ccda New translations strings.xml (Arabic) 2025-02-11 16:18:08 +01:00
PhilippC
4dfcbbf62a New translations strings.xml (Spanish) 2025-02-11 16:18:07 +01:00
PhilippC
d0e1a15673 New translations strings.xml (French) 2025-02-11 16:18:06 +01:00
PhilippC
8fc9324be5 New translations strings.xml (Romanian) 2025-02-11 16:18:05 +01:00
PhilippC
4f4724804e Merge pull request #2769 from PhilippC/bugfix/crowdin-config-fix
fix crowdin.yml file: adjust to renamed folder
2025-02-11 16:04:17 +01:00
Philipp Crocoll
533d92509f fix crowdin.yml file: adjust to renamed folder 2025-02-11 16:03:53 +01:00
158 changed files with 4489 additions and 2171 deletions

View File

@@ -20,6 +20,7 @@
# - nuget: restore NuGet packages
# - msbuild: build the project
# - apk: same as all
# - manifestlink: creates a symlink (to be used in building) to the AndroidManifest corresponding to the selected Flavor
#
# - distclean: run a 'git clean -xdff'. Remove everyhing that is not in the git tree.
# - clean: all clean_* targets below

View File

@@ -1,7 +1,7 @@
files:
- source: src/keepass2android/Resources/values/strings.xml
- source: src/keepass2android-app/Resources/values/strings.xml
translation: >-
/src/keepass2android/Resources/values-%two_letters_code%/%original_file_name%
/src/keepass2android-app/Resources/values-%two_letters_code%/%original_file_name%
translate_attributes: '0'
content_segmentation: '0'
languages_mapping:

View File

@@ -1,5 +0,0 @@
As of December 2017, Google does not accept the use of Accessibility services for anything except helping people with disabilities. This means that Keepass2Android can no longer provide the accessibility service based AutoFill feature. Otherwise, Google would remove Keepass2Android from Play Store.
If you want to continue using this feature, please [install the Accessibility service based AutoFill plugin](https://github.com/PhilippC/kp2a_accservice_autofill/releases/).
After installation, please enable the accessibility service "KP2A AutoFillPlugin" in the Android system settings. When trying to use the plugin for the first time, KP2A will ask you if the plugin may access the Keepass database. Please accept this to use the plugin.

View File

@@ -1,18 +0,0 @@
# Installing dictionaries
Keepass2Android will load dictionaries for your current language both from AnySoftKeyboard and from Hacker's keyboard.
* For AnySoftKeyboard dictionaries visit: [https://play.google.com/store/search?q=anysoftkeyboard+dictionary&c=apps](https://play.google.com/store/search?q=anysoftkeyboard+dictionary&c=apps)
* For Hacker's Keyboard dictionaries visit: [https://play.google.com/store/search?q=hacker%27s%20keyboard%20dictionary&c=apps](https://play.google.com/store/search?q=hacker%27s%20keyboard%20dictionary&c=apps)
# Automatic keyboard switching (requires ADB)
Starting with Keepass2Android 1.02-pre1, you can use the [KeyboardSwap Plugin](https://play.google.com/store/apps/details?id=keepass2android.plugin.keyboardswap2) to switch to the KP2A keyboard automatically instead of bringing up the Input method selection dialog (e.g. after using the Share URL feature). To setup the plugin please follow the instructions on [the PlayStore website](https://play.google.com/store/apps/details?id=keepass2android.plugin.keyboardswap2)
# Deprecated: Automatic keyboard switching on rooted devices
In order to automatically switch to the KP2A keyboard and back, you need to
* have a rooted device (per Android security policies)
* have at least KP2A version 0.9.3-pre2
* install the Secure Settings app with the "System+" module available in Secure Settings v. 1.3.4 and above. **Note:** This is no longer available for recent Android versions.
* Go to the KP2A keyboard settings. Enable auto-switch on rooted devices.
If you go to a website, select "Share URL" -> Keepass2Android, the keyboard should be switched as soon as you locate the entry or when it's found automatically.

View File

@@ -1,239 +0,0 @@
# How to build Keepass2Android
## Overview
Keepass2Android is a Mono for Android app. This means that you need Xamarin's Mono for Android to build it. However, it also uses several components written in Java, so there are also Android-Studio projects involved. To make things even worse, parts of the keyboard and kdb-library are written in native code.
To build KP2A from scratch, you need:
- Xamarin's Mono for Android (also included in Visual Studio)
- Android SDK & NDK
Prior to building Keepass2Android, you need to build some of its components (from command line). Then you can build the full project either through Visual Studio, or through command line.
By using the command line, you can build on Windows, macOS or Linux.
## Prerequisites
### Common to all architectures
- Install Android SDK & NDK (either manually with Google's [sdkmanager](https://developer.android.com/studio/command-line/sdkmanager), or through Android Studio). Visual Studio also installs a version of it, but in the end the directory must be writable and in a path without spaces (see below) so as to be able to build the components.
- Fetch the main repository of Keepass2Android and all submodules
- Note that VisualStudio can do this for you, otherwise run:
- `git submodule init && git submodule update`
### On Windows or macOS
- Install Visual Studio (for example 2019) with Xamarin.Android (ie. with capability to build Android apps). This should provide the needed tools like
- Xamarin.Android
- MSBuild
- Java JDK
- If you plan to build also from the command line:
- Install the MSVC build tools of visual studio. They provide the `vcvarsall.bat` file which among other things adds MSBuild to the PATH.
- Install [NuGet](https://www.nuget.org/downloads) to build also with "make". Alternatively, on Windows, if you use [chocolatey](https://chocolatey.org), run as administrator:
- `choco install nuget.commandline`
- Check that you have access to 'GNU make'.
- On Windows, it is usually not available by default. But the Android NDK provides it. You can find it in `%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make.exe`. Alternatively, on Windows, if you use [chocolatey](https://chocolatey.org), run as administrator:
- `choco install make`
- On macOS, it is usually only installed if you have developer command line tools installed or if you use [homebrew](https://brew.sh) or [macports](https://www.macports.org/). As an alternative it may be available in the Android NDK at `%ANDROID_NDK_ROOT%/prebuilt/darwin-x86_64/bin/make`.
### On Linux
- Install Java's JDK
- On Debian, for example: `apt install default-jdk-headless`.
- Install [Mono](https://www.mono-project.com/)
- This should provide `msbuild` & `xabuild` binary
- On Debian, after having added the repo from above, install with `apt install -t <repo_name> mono-devel msbuild`. A value for `<repo_name>` could be `stable-buster` for example, depending on which one you chose. You could also install the `mono-complete` package if you prefer.
- Install Xamarin.Android
- ~~Option 1: Use the mono-project [CI builds](https://dev.azure.com/xamarin/public/_build/latest?definitionId=48&branchName=main&stageName=Linux)~~ **NOTE:** KP2A now requires Xamarin.Android v13, which is newer than the current CI build; until a more recent CI build is available, this option is unfortunately no longer viable.
- Option 2: [Build it from source](https://github.com/xamarin/xamarin-android/blob/master/Documentation/README.md#building-from-source)
- Install NuGet package of your distribution
- On Debian/Ubuntu: `apt install nuget`
- Install [libzip](https://libzip.org/) for your distribution for some Xamarin.Android versions
- This may not be relevant anymore: for example, with Xamarin.Android 11.4.99. this is not needed.
- Some versions of Xamarin may require `libzip4`. If you are in this case:
- On Debian/Ubuntu, install it with `apt install libzip4`.
- Other distributions ship only `libzip5`. As a dirty workaround, it's possible to symlink `libzip.so.5` to `libzip.so.4`. Luckily, it appears to be working. For example:
- `sudo ln -s /usr/lib/libzip.so.5 /usr/lib/libzip.so.4`
- or `sudo ln -s /usr/lib64/libzip.so.5 /usr/lib/libzip.so.4`
## Building the required components:
This is done on the command line and requires the Android SDK & NDK and Java JDK.
### On Windows
- Setup your environment:
- Set these environment variables for Android's SDK & NDK
- `ANDROID_HOME` (for example `set ANDROID_HOME=C:\PATH\TO\android-sdk`)
- `ANDROID_SDK_ROOT` (for example `set ANDROID_SDK_ROOT=C:\PATH\TO\android-sdk`)
- `ANDROID_NDK_ROOT` (for example `set ANDROID_NDK_ROOT=C:\PATH\TO\android-sdk\ndk\version`)
**Note:** Care must be taken when setting the above variables to **not** include a trailing backslash in the path. A trailing backslash may cause `make` to fail.
**Note**: If the path to the Android SDK contains spaces, you **must** do one of these:
- either put the Android SDK into a path without spaces.
- or create a symlink to that path which doesn't contain spaces. Attention: this requires **administrator** priveleges. For example:
```
IF NOT EXIST C:\Android ( MKDIR C:\Android ) &&
MKLINK /D C:\Android\android-sdk "C:\Program Files (x86)\Android\android-sdk"
```
This is because [Android NDK doesn't support being installed in a path with spaces](https://github.com/android/ndk/issues/1400).
**Note**: The Android SDK path will require to be writeable because during the build, some missing components might be downloaded & installed.
- If you have "GNU make" available on your windows system, you may build by using the Makefile. You can also find a `make` executable in `%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make.exe`. To use it, see the instructions for Linux/macOS. Basically, just run `make` or `mingw32-make` depending on which distribution of GNU make for windows you have installed.
- Otherwise proceed as below:
1. Build argon2
```
cd src/java/argon2
%ANDROID_NDK_ROOT%/ndk-build.cmd
```
1. Build the other java components
```
cd src/build-scripts
build-java.bat
```
`build-java.bat` will call `gradlew` for several Java modules.
**Notes:**
- For building the java parts, it is suggested to keep a short name (e.g. "c:\projects\keepass2android") for the root project directory. Otherwise the Windows path length limit might be hit when building.
- Before building the java parts, make sure you have set the ANDROID_HOME variable or create a local.properties file inside the directories with a gradlew file. It is recommended to use the same SDK location as that of the Xamarin build.
- On some environments, `make` can fail to properly use the detected `MSBUILD` tools. This seems to be due to long pathnames and/or spaces in pathnames. It may be required to explicitly set the `MSBUILD` path using 8.3 "short" path notation:
- Determine the location of `MSBUILD` (e.g. `C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe`)
- [Generate the "short" path](https://superuser.com/a/728792) of that location (e.g.: `C:\PROGRA~1\MICROS~2\2022\COMMUN~1\MSBuild\Current\Bin\MSBuild.exe`)
- When running `make` specify the location of ``MSBUILD` explicitly (e.g.: `make MSBUILD="C:\PROGRA~1\MICROS~2\2022\COMMUN~1\MSBuild\Current\Bin\MSBuild.exe`
### On Linux/macOS
- Setup your environment:
- Set these environment variables for Android's SDK & NDK
- `ANDROID_HOME` (for example `export ANDROID_HOME=/path/to/android-sdk/`)
- `ANDROID_SDK_ROOT` (for example `export ANDROID_SDK_ROOT=/path/to/android-sdk/`)
- `ANDROID_NDK_ROOT` (for example `export ANDROID_NDK_ROOT=/path/to/android-sdk/ndk/version`)
- Update your PATH environment variable so that it can access `nuget`, `msbuild` or `xabuild` (for linux):
- On Linux:
- add `xabuild` to your path: `export PATH=/path/to/xamarin.android-oss/bin/Release/bin/:$PATH`
- On macOS:
- you may similarly need to add `msbuild` & `nuget` to your PATH.
- Start the build:
- This will use the Makefile at the root of the project (requires GNU make). To build everything (components & Keepass2Android APK) in a single command simply run:
```
make
```
- Otherwise, if you prefer to do step by step
1. Build argon2
```
make native
```
1. Build the other java components
```
make java
```
## Building Keepass2Android:
These are the basic steps to build Keepass2Android. You can also build Keepass2Android Offline. For this, configure the build by using the [Flavors](#Flavors).
### With Visual Studio
- On windows or on macOS open the src/KeePass.sln file with visual studio, and choose to build the project named 'keepass2android-app'
### Command Line
#### Windows, Macos & Linux
to build the APK, simply run:
```
make
```
or to skip building the APK:
```
make msbuild
```
## Where is the APK ?
The Apk can be installed on a device.
It is located in `src/keepass2android/bin/*/*-Signed.apk`
If you build with Visual Studio, the APK is not produced automatically. You need to perform some extra step. See the documentation of Visual Studio on how to proceed.
## Flavors
Keepass2Android is distributed in two flavors.
- Keepass2Android (aka `net`)
- Keepass2Android Offline (aka `nonet`)
The flavor is set through a MSBuild Property named "`Flavor`". The possible values are '`Net`' and '`NoNet`'.
The value of the Flavor property is used in 2 projects:
- `keepass2android-app` (in `src/keepass2android`)
- `Kp2aBusinessLogic` (in `src/keepass2android`)
Its value is set inside the `*.csproj` file (XML format) of each project in the `Project`/`PropertyGroup`/`Flavor` node.
By default its value is set to an empty string so that development is made with `AndroidManifest_debug.xml` on the '`net`' flavor.
This is the behaviour of the build system depending on the value of Flavor:
| Flavor | What is built | `AndroidManifest.xml` used |
| ----- | ----- | ----- |
| `` (empty string): This is the default value. | Keepass2Android | `AndroidManifest_debug.xml` |
| `Net` | Keepass2Android | `AndroidManifest_net.xml` |
| `NoNet` | Keepass2Android Offline | `AndroidManifest_nonet.xml` |
### Select/Change flavor:
When building, by default, the flavor is not set. So the value used is the value of the Flavor property in *.csproj file. This should result on doing a build of the 'net' flavor.
You can force the Flavor by setting the Flavor property.
Proceed this way:
#### Command line
##### Windows, Macos & Linux
To force building 'net' with `make`, run:
```
make Flavor=Net
```
To build 'nonet' with `make`, run:
```
make Flavor=NoNet
```
##### MSBuild
To build with MSBuild directly on the command line, set the flavor with `-p:Flavor=value` argument. For example:
```
MSBuild src/KeePass.sln ... -p:Flavor=NoNet
```
#### Visual Studio
When building with Visual Studio, edit the `*.csproj` file (XML format) and set the value in the `Project`/`PropertyGroup`/`Flavor` node. This is needed only for the projects that use the flavors.
**Note:** When switching between flavors, be sure to clean the previous build before.
## Makefile
It is possible to override the project's default 'Flavor' (Net, NoNet) and 'Configuration' (Release, Debug) by passing it as argument to `make`. See the header of the Makefile to see what can be done.

View File

@@ -1,118 +0,0 @@
<div class="wikidoc">
<h1>Comparison of Keepass apps for Android</h1>
<p>This page was created to give you a short overview of the features of Keepass2Android vs. Keepass2Android Offline. As Keepass2Android is based on Keepassdroid (by Brian Pellin), there are quite a few similarities here, as well, so we added Keepass2Android
vs. Keepassdroid comparison as well. &quot;Better&quot; properties are highlighted in bold. The page was created in 12/2013. If any information is out of date, please leave a note in the comments section.</p>
<table>
<tbody>
<tr>
<th>&nbsp;</th>
<th>
<h3>Keepass2Android</h3>
</th>
<th>
<h3>Keepass2Android Offline</h3>
</th>
<th>
<h3>Keepassdroid</h3>
</th>
</tr>
<tr>
<td><strong>Play Store link</strong></td>
<td><a href="https://play.google.com/store/apps/details?id=keepass2android.keepass2android">https://play.google.com/store/apps/details?id=keepass2android.keepass2android</a></td>
<td><a href="https://play.google.com/store/apps/details?id=keepass2android.keepass2android_nonet">https://play.google.com/store/apps/details?id=keepass2android.keepass2android_nonet</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.android.keepass">https://play.google.com/store/apps/details?id=com.android.keepass</a></td>
</tr>
<tr>
<td><strong>Technology</strong></td>
<td>Mono for Android, Java</td>
<td>Mono for Android, Java</td>
<td>Java</td>
</tr>
<tr>
<td><strong>Keepass 2.x (kdbx) support</strong></td>
<td><strong>write and read</strong></td>
<td><strong>write and read</strong></td>
<td>read (write in beta)</td>
</tr>
<tr>
<td><strong>Keepass 2.x feature support</strong></td>
<td><strong>Viewing and editing of tags, attachments, additional fields, TAN support</strong></td>
<td><strong>Viewing and editing of tags, attachments, additional fields, TAN support</strong></td>
<td>Edit standard fields only, no display/edit of attachments</td>
</tr>
<tr>
<td><strong>Keepass 1.x (kdb) support</strong></td>
<td>currently read-only</td>
<td>currently read-only</td>
<td><strong>yes</strong></td>
</tr>
<tr>
<td><strong>Storage locations</strong></td>
<td>SD Card,<strong> Cloud (Dropbox, Google Drive, OneDrive), Web (FTP/HTTP/HTTPS/WebDav), SFTP</strong></td>
<td>SD Card</td>
<td>SD Card</td>
</tr>
<tr>
<td><strong>File choosers</strong></td>
<td><strong>Internal or third party</strong></td>
<td><strong>Internal or third party</strong></td>
<td>Third party</td>
</tr>
<tr>
<td><strong>Required permissions</strong></td>
<td>Internet, SD card, Manage accounts</td>
<td><strong>SD card</strong></td>
<td><strong>SD card</strong></td>
</tr>
<tr>
<td><strong>Android 4.x style</strong></td>
<td><strong>yes</strong></td>
<td><strong>yes</strong></td>
<td>no</td>
</tr>
<tr>
<td><strong>Database locking</strong></td>
<td><strong>QuickUnlock</strong> or full lock</td>
<td><strong>QuickUnlock</strong> or full lock</td>
<td>Full lock only</td>
</tr>
<tr>
<td><strong>Browser integration</strong></td>
<td><strong>yes</strong></td>
<td><strong>yes</strong></td>
<td>no</td>
</tr>
<tr>
<td><strong>Secure keyboard</strong></td>
<td><strong>yes</strong></td>
<td><strong>yes</strong></td>
<td>no</td>
</tr>
<tr>
<td><strong>Database unlocking</strong></td>
<td><strong>password, keyfile, One-Time-Passwords (supports Yubikey NEO with NFC), KeeChallenge</strong></td>
<td><strong>password, keyfile, One-Time-Passwords (supports Yubikey NEO with NFC),&nbsp;KeeChallenge</strong></td>
<td>password, keyfile</td>
</tr>
<tr>
<td><strong>Keepass plugin compatibility</strong></td>
<td><strong>Twofish Cipher, KeeChallenge, TrayTOTP, KeeOTP</strong></td>
<td><strong>Twofish Cipher, KeeChallenge, TrayTOTP, KeeOTP</strong></td>
<td>Twofish Cipher</td>
</tr>
<tr>
<td><strong>Extensible with plugins</strong></td>
<td><strong>yes</strong></td>
<td><strong>yes</strong></td>
<td>no</td>
</tr>
<tr>
<td><strong>Database export</strong></td>
<td><strong>yes</strong></td>
<td><strong>yes</strong></td>
<td>no</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
</div><div class="ClearBoth"></div>

View File

@@ -1,125 +1 @@
**Note:** This is an incomplete and preliminary documentation. More documentation will be added as requests come in or when the app is more feature stable.
If you want, I'd be happy if you contribute texts for this place!
If you think something is missing in the documentation, please create an issue at https://github.com/PhilippC/keepass2android/issues
# What you should know and think about
If you store important information using Keepass2Android, you should know a little bit about what's going on:
* Keepass2Android stores your password in an encrypted file. It is *your responsibility* to backup this file regularly and safely.
* There is no way for anyone, including the app's author, to access the information stored in your password database without
* having the database file
* knowing the master password (and additional second factor if you chose one)
This means that **if you forget the master password, your database is lost**! So make sure you remember the password and retain any second factor method (if one is used).
* You might also want to think about:
* What happens if I have an accident? Should any trusted person be able to access my database?
* What happens if my phone gets lost or stolen? Do I know how to recover my database from a backup or the cloud?
# Getting started
## Opening an existing database
Many users are already using Keepass 2 on Windows and thus have their passwords stored in a Keepass database, typically a file with ending .kdbx. For opening such an existing database, there are two main options:
* You can open the file directly if it is located on a webserver or in the cloud. Use "Open Database" on the startscreen. By default, files from the cloud or servers are cached in the application's cache directory after loading them once. This allows to access your files even when you're offline.
* If you don't have your database stored on a webserver or in the cloud (or if you're using KP2A Offline) you need to copy your kdbx-Database to your phone. I suggest to use a sync tool like FolderSync. Such a tool copies your database to your local storage, so you always have it accessible. FolderSync can access your database if you have it on a network share or use any other common storage.
## Creating a new database
Select "Create new database" from the start screen. Tap the integrated help icons for more information. Note that by default, the database is created as a local file. Please consider making backups regularly or select a location in the cloud.
## 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 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 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
When you are in a text field, you can use the Android icon in the notification bar to switch to the KP2A keyboard. Hit the KP2A key to select an icon. After it's selected, hit the KP2A key again to enter the desired field.
## Creating a new account
Assume you want to create an account on a website. If you do not have a database yet, see above. As soon as you have a database, you may proceed as follows:
* Go to the website you want to create the account for
* Select Share/Share URL from the browser's menu and tap "Keepass2Android"
* Log in to your database (if it's not already unlocked)
* You will see the search result screen with "No search results"
* Tap "Create entry for URL"
* Choose the desired group, then tap the "+"-button to add an entry.
* Tap the "..." button next to the password field to launch the password generator, create your password and then select "Accept"
* Enter a name for the entry
* Enter the username you want to use for the entry
* Tap "Save" on the top
* You should see notifications like "Entry is available through KP2A keyboard" and/or "Copy username/password to clipboard". If not, view the new entry by clicking it.
* Return back to the browser.
* Use the notifications to enter your new credentials. See "Getting passwords into the password fields" for more details.
* If the user name you entered is not available or valid, choose a different one but copy it to clipboard. After creating the account, don't forget to update the new entry.
# Keepass2Android vs Keepass2Android Offline vs Keepassdroid
What's the difference between these apps? There is a short comparison on [Comparison of Keepass apps for Android](Comparison-of-Keepass-apps-for-Android.md) to help you pick the best for you!
# Advanced topics
## YubiKey NEO support for One-Time-Passwords
Please see the [How to use Keepass2Android with YubiKey NEO](How-to-use-Keepass2Android-with-YubiKey-NEO.md) page.
## Advanced usage of the Keepass2Android keyboard
Please see the [Advanced usage of the Keepass2Android keyboard](Advanced-usage-of-the-Keepass2Android-keyboard.md) page.
## Using Keepass2Android like an authenticator app to generate Time-based One-Time-Passwords (TOTPs)
Please see [Generating TOTPs with Keepass2Android](Generating-TOTPs.md)
# FAQ
## 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! [Key files](https://keepass.info/help/base/keys.html#keyfiles) can help with securing the database even more.
## Doesn't Keepass2Android create automatic backups?
Yes and no. Yes: Keepass2Android stores the last successfully opened file as a read-only backup locally on the phone (unless you disable this is in the settings). This should make sure that even if the file gets destroyed during a save operation or gets deleted by accident, you should always have a version that can be opened. (Don't mix this up with the internal file cache which is not meant as a backup and can easily be overwritten even with a corrupt file. This internal file cache is meant for providing writable access even when the original file is not reachable, e.g. when you're offline.)
No: The local backup has two shortcomings: It is only one backup and does not allow to revert to older versions. So if you deleted an entry from the database, it might be deleted in the local backup soon as well. The even more important shortcoming is that it is just a local backup. It won't help when your phone gets lost or broken. Please create additional backups on seperate storage!
## 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.
## I get a message "File is trashed" when reading or writing a file on Google Drive
This happens because ocaml-fuse (I guess you are on Linux  and use that) moves files to trash and then creates a new one instead of correctly updating the file on Google Drive (each file has a unique ID which Keepass2Android uses). Fortunately, this was fixed: https://github.com/astrada/google-drive-ocamlfuse/issues/494. After activating this option, please select "Change database" in KP2A, tap ,"Open file" and browse to the file on Google Drive again. After that, the message should no longer pop up.
## I get a message "The name must not be empty: null" when opening from Google Drive
Please follow these steps:
* select "Change database" on the password screen, then "Open database" and browse to your file again
* go to Android app settings and disable all permissions for the KP2A app. Then try again to open the database file.
* reboot the device
(Before running the following steps, make sure you don't have local changes in your database which have not been synchronized with Google Drive (this can happen if you worked offline). If you have, please open the database from the local cache and go to settings - database settings - export database and make a backup copy of the data.)
* clear KP2A's app cache in the Android settings
* uninstall & reinstall
One of these has helped all users so far, but unfortunately it's not totally clear to me why different steps are required (or nothing for most users).
# For developers
If you are interested in adding new features, you have two options:
Either your features can be implemented as a plug-in. Please see [How to create a plug-in?](How-to-create-a-plug-in_.md) for more information. Or you add the features directly in the source code of the projects and create a pull request.
If you want to build Keepass2Android, check the [build guide](Build.readme.md).
This page has been moved to the [wiki](https://github.com/PhilippC/keepass2android/wiki/Documentation)

View File

@@ -1,53 +1 @@
## TOTP in brief
TOTP stands for [Time-based One-Time Password algorithm](https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm) which is one of the most common way proposed by websites to do a [two-factor authentication (2FA)](https://en.wikipedia.org/wiki/Multi-factor_authentication).
On these websites, this option will often be mentioned in the 2FA configuration menu as things like "_use code generated by an application_", "_use [Google] Authenticator app_".
You're prompted to scan a QR code with the app, which essentially contains a code called "_seed_", usually with a form like "_AZER TYUI OPQS DFGH JKLM_", used to generate TOTPs. The seed can be also directly copied if there is no scanning option on the app.
Most common apps:
- Google Authenticator
- Authy
- Microsoft Authenticator
- FreeOTP
- LastPass Authenticator
## TOTP in KeePass and benefits
In KeePass (by Dominik Reichl) there is are several ways to enable this Authenticator app ability:
- built-in TOTP support: https://keepass.info/help/base/placeholders.html#otp
- [KeePassOTP plugin](https://keepass.info/plugins.html#kpotp)
- [KeeOtp plugin](https://keepass.info/plugins.html#keeotp)
- [KeeTrayTOTP plugin](https://keepass.info/plugins.html#keetraytotp) (note the name "_TrayTOTP_" on this one for later)
KeePassXC also supports TOTP: https://keepassxc.org/docs/KeePassXC_UserGuide#_adding_totp_to_an_entry
The greatest benefits are:
- the seed stays available contrary to the above apps (for which it's more or less hard to backup/restore/switch with another app)
- TOTPs are available wherever the KeePass database is available. But conceptually it's not really 2FA anymore (all things are stored in the same place).
The different implementations use different ways of storing the TOTP seed (or secret, or key) and optional settings (e.g. the length of the TOTP to generate) within an entry inside the kdbx database. Keepass2Android attempts to be able to read the different formats, but can only write one:
## TOTP in Keepass2Android
If you use any of the tools mentioned above, you can set up TOTP entries with them. Keepass2Android can read those entries and generate TOTPs if any of the following styles are used:
* Keepass2 style: used when there are TimeOtp-Secret(-XXX) fields in the entry
* KeeOtpPlugin style: used when there is an otp field containing a query string in the form of key=abc&step=X&size=Y (step and size are optional)
* KeeWebOtp/Key Uri Format style: used when entry contains a URL starting with otpauth://totp/, e.g. otpauth://totp/?secret=abc (https://github.com/google/google-authenticator/wiki/Key-Uri-Format)
* KeeTrayTotp style:
* requires a non-empty seed field (default key is "TOTP seed", can be changed in KP2A settings), value is base32 encoded data
* requires a non-empty settings field (default key is "TOTP Settings", can be changed as well), value is expected to be a csv-separated array with [Duration];Length(;TimeCorrectionURL). Length is either an integer value or "S" to indicate Steam encoding
In order to view the generated TOTP code in KP2A, open the corresponding entry. You can then
* use a dynamically generated field called "_TOTP_" containing the TOTP or
* use the "Copy TOTP" button on the system notification for the selected entry or
* switch to the KP2A keyboard and use the TOTP button to insert the TOTP value into the target app or browser
If you want to configure an entry to contain the TOTP fields, it is suggested to enter edit mode for the entry. Then click the "Configure TOTP" button. You can either enter the data manually or scan a QR code with the information.
### Spaces in otp field
Make sure that the URI doesn't contain spaces, otherwise KeePass2Android will fail to generate TOTPs as a space is an invalid character. If your URIs have spaces, check [this comment](https://github.com/PhilippC/keepass2android/issues/1248#issuecomment-628035961)._
This page has been moved to the [wiki](https://github.com/PhilippC/keepass2android/wiki/Generating-TOTPs)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

View File

@@ -1,157 +0,0 @@
# How to create a plug-in or connect from your app
Creating a plug-in for Keepass2Android or enabling your app to query credentials from Keepass2Android is pretty simple. Please follow the steps below to get started. In case you have any questions, please contact me.
## Preparations
First check out the source code and import the Keepass2AndroidPluginSDK from [https://github.com/PhilippC/keepass2android/tree/master/src/java/Keepass2AndroidPluginSDK2](https://github.com/PhilippC/keepass2android/tree/master/src/java/Keepass2AndroidPluginSDK2/) into your workspace. You should be able to build this library project.
Now add a reference to the PluginSDK library from your existing app or add a new plug-in app and then add the reference.
## Authorization
Keepass2Android stores very sensitive user data and therefore implements a plug-in authorization scheme based on broadcasts sent between the plug-in and the host app (=Keepass2Android or Keepass2Android Offline). Before your app/plug-in gets any information from KP2A, the user will have to grant your app/plug-in access to KP2A. As not every app/plug-in requires access to all information, you must specify which scopes are required by your app. The implemented scopes can be found in [https://github.com/PhilippC/keepass2android/tree/master/src/java/Keepass2AndroidPluginSDK2/src/keepass2android/pluginsdk/Strings.java](https://github.com/PhilippC/keepass2android/tree/master/src/java/Keepass2AndroidPluginSDK2/src/keepass2android/pluginsdk/Strings.java).
To tell Kp2a that you're a plug-in, you need to add a simple BroadcastReceiver like this:
```java
public class PluginAAccessReceiver extends keepass2android.pluginsdk.PluginAccessBroadcastReceiver
{
@Override
public ArrayList<String> getScopes() {
ArrayList<String> scopes = new ArrayList<String>();
scopes.add(Strings.SCOPE_DATABASE_ACTIONS);
scopes.add(Strings.SCOPE_CURRENT_ENTRY);
return scopes;
}
}
```
Here, you define the method getScopes where the list of scopes is created which must be granted by the user. The actual logic of the authorization process is implemented by the base class in the sdk.
In order to make this broadcast receiver visible to KP2A, add the following lines (probably with the name adapted to your class name) in the AndroidManifest.xml:
```xml
<receiver android:name="PluginAAccessReceiver" android:exported="true">
<intent-filter>
<action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
<action android:name="keepass2android.ACTION_RECEIVE_ACCESS" />
<action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
</intent-filter>
</receiver>
```
Please also add a few strings in your resource files (e.g. strings.xml) with the following keys:
```xml
<string name="kp2aplugin_title">The Great PluginA</string>
<string name="kp2aplugin_shortdesc">Test plugin to demonstrate how plugins work</string>
<string name="kp2aplugin_author">[your name here](your-name-here)</string>
```
These strings will be displayed to the user when KP2A asks if access should be granted.
## Modifying the entry view
You can add menu options for the full entry or for individual fields of the entry when displayed to the user. This is done, for example, by the QR plugin ([https://play.google.com/store/apps/details?id=keepass2android.plugin.qr](https://play.google.com/store/apps/details?id=keepass2android.plugin.qr)).
In addition, it is even possible to add new fields or modify existing fields. Please see the sample plugin "PluginA" for a simple example on how to do this:
[https://github.com/PhilippC/keepass2android-sampleplugin/blob/main/src/keepass2android/plugina/PluginAAccessReceiver.java](https://github.com/PhilippC/keepass2android-sampleplugin/blob/main/src/keepass2android/plugina/PluginAAccessReceiver.java)
## Querying credentials
KP2A 0.9.4 adds a great opportunity for third party apps: Instead of prompting the user to enter credentials or a passphrase, the app should try to get the data from KP2A if it is installed: If the user grants (or previously granted) access for the app, KP2A will automatically retrieve the matching entry. User action is only required if the KP2A database is locked (user will usually unlock it with the short QuickUnlock code) or if no matching entry is found (user can then create a new entry or select an existing one. in the latter case KP2A will offer to add entry information so that the entry will be found automatically next time).
To implement this, simply follow the steps descrIbed above in the sections Preparation and Authorization. Then, wherever appropriate in your app, do something like this:
```java
try
{
PlaceholderFragment.this.startActivityForResult(
Kp2aControl.getQueryEntryIntentForOwnPackage(),
1);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(
PlaceholderFragment.this.getActivity(),
"no KP2A host app found",
Toast.LENGTH_SHORT).show();
}
```
(of course you can use `PacketManager` to check if the intent can be started instead of catching the `Exception`).
Instead of querying credentials associated with your own app, you might want to query other credentials as well. instead of `KpControl.getQueryEntryIntentForOwnPackage()` use
`Kp2aControl.getQueryEntryIntent("google.com")`
This requires \{"SCOPE_QUERY_CREDENTIALS (whereas getQueryEntryIntentForOwnPackage() requires SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE)"\}.
The credential data can be retrieved in onActivityResult():
```java
if ((requestCode == 1) //queryEntry for own package
&& (resultCode == RESULT_OK)) // ensure user granted access and selected something
{
HashMap<String, String> credentials = Kp2aControl.getEntryFieldsFromIntent(data);
if (!credentials.isEmpty())
{
//here we go!
Toast.makeText(
getActivity(),
"retrieved credenitals! Username="+credentials.get(KeepassDefs.UserNameField),
Toast.LENGTH_LONG).show();
}
}
```
Note that you get access to all strings (Title, Username, Password, URL, Notes + any user defined strings) in the entry. This may be in intersting in combination with the following section:
## Storing data in KP2A
If you allow the user to set up an account in your app or create a password, e.g. for encryption, please add an option to store this data in the Keepass2Android database, as this will lead to great workflows for the user. It's as simple as
```java
try {
HashMap<String, String> fields = new HashMap<String, String>();
//standard fields
fields.put(KeepassDefs.TitleField, "plugin A");
fields.put(KeepassDefs.UserNameField, "John Doe");
fields.put(KeepassDefs.PasswordField, "top secret");
//associate entry with our app. If we would require the URL field for a web URL,
//this string could be added in any other (e.g. a custom) field
fields.put(KeepassDefs.UrlField, "androidapp://"+getActivity().getPackageName());
//custom field:
fields.put(PLUGIN_A_PASSPHRASE, "some long text");
//mark custom field as protected (i.e. display masked, enable memory protection in Keepass2)
ArrayList<String> protectedFields = new ArrayList<String>();
protectedFields.add(PLUGIN_A_PASSPHRASE);
//add to KP2A
PlaceholderFragment.this.startActivityForResult(
Kp2aControl.getAddEntryIntent(fields, protectedFields),
2);
} catch (ActivityNotFoundException e) {
Toast.makeText(
PlaceholderFragment.this.getActivity(),
"no KP2A host app found",
Toast.LENGTH_SHORT).show();
}
```
Note that this does not even require access authorization because the user will actively save the entry anyways (after selecting the group where to create it.)
## Get information about database actions
With {"SCOPE_DATABASE_ACTIONS"}, you will be informed when the user opens, closes, locks or unlocks the database including the file name information.
PluginA uses this to simply display a toast message in its ActionReceiver:
```java
@Override
protected void dbAction(DatabaseAction db) {
Log.d("PluginA", db.getAction() + " in file " + db.getFileDisplayName() + " ("+db.getFilePath()+")");
}
```
## Sample plugin
Most example code from above is taken from the simple sample plugin "PluginA" as can be found on [https://keepass2android.codeplex.com/SourceControl/latest#src/java/PluginA/](https://keepass2android.codeplex.com/SourceControl/latest#src/java/PluginA/)

View File

@@ -1,31 +0,0 @@
<div class="wikidoc">
<h1>How to use Keepass2Android with YubiKey NEO</h1>
<p>Please refer to the documentation on the Keepass website (<a href="http://keepass.info/help/kb/yubikey.html">http://keepass.info/help/kb/yubikey.html</a>) or the Yubico website (<a href="http://www.yubico.com/applications/password-management/consumer/keepass/">http://www.yubico.com/applications/password-management/consumer/keepass/</a>)
on how to set up a Keepass 2 database with Yubikey/OTP protection.<br>
<br>
After successful setup you should have the database file, e.g. yubi.kdbx, and the OTP auxiliary file, e.g. yubi.otp.xml, both in the same folder.<br>
<a href="How to use Keepass2Android with YubiKey NEO_OTPAuxFile_2.png"><img title="OTPAuxFile" src="How to use Keepass2Android with YubiKey NEO_OTPAuxFile_thumb.png" alt="OTPAuxFile" width="513" height="40" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p>Make sure you make <strong>both files</strong> available to Keepass2Android, e.g. by placing them both in your Dropbox.</p>
<p>Now you should check your NDEF setup of the Yubikey NEO. Therefore, go to the Tools menu in the Yubico Personalization Utility. Select the same slot as used for OTPs with Keepass 2. The default setting for NDEF type and payload should work. If you experience
problems, you may use the configuration as shown in this screenshot or simply press the &ldquo;Reset&rdquo; button:</p>
<p><a href="How to use Keepass2Android with YubiKey NEO_image_2.png"><img title="image" src="How to use Keepass2Android with YubiKey NEO_image_thumb.png" alt="image" width="760" height="622" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p><br>
<br>
In Keepass2Android, select &quot;Open file&quot; and locate your database file, e.g. yubi.kdbx.<br>
<br>
In the password screen under &quot;Select master key type&quot; select &quot;Password &#43; OTP&quot;.</p>
<p><a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-50_2.png"><img title="Screenshot_2013-12-13-06-38-50" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-50_thumb.png" alt="Screenshot_2013-12-13-06-38-50" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<p>Click &quot;Load auxiliary OTP file&quot;. This is required to load the information how many OTPs must be entered. As loading the file might require user action in some cases, this is not performed automatically.<br>
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-12_2.png"><img title="Screenshot_2013-12-13-06-38-12" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-12_thumb.png" alt="Screenshot_2013-12-13-06-38-12" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
After loading the OTP auxiliary file, you should see a few text fields for entering the OTPs. Now swipe your YubiKey NEO at the back of your Android device. If you have multiple apps which can handle NFC actions, you might be prompted to select which app to
use. Select Keepass2Android in this case. Swipe your YubiKey again until all OTP fields are filled. Note: You don't need to select the next text field, this is done automatically!<br>
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-36_2.png"><img title="Screenshot_2013-12-13-06-38-36" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-36_thumb.png" alt="Screenshot_2013-12-13-06-38-36" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
Don't forget to also enter your password and click OK. You will see the &ldquo;Saving auxiliary OTP file&hellip;&rdquo; dialog. Note that there is some encryption envolved which is probably fast on your PC but might take some time on your mobile device. You
can reduce the look-ahead window length to speed this up.<br>
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-39-47_2.png"><img title="Screenshot_2013-12-13-06-39-47" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-39-47_thumb.png" alt="Screenshot_2013-12-13-06-39-47" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
<h2>&nbsp;</h2>
<h2>A note about offline access</h2>
<p>If your database is stored in the cloud or on the web, you can still access it if you have enabled file caching (which is on by default). With OTPs, this becomes a little bit more complicated: If you repeatedly open your datbase while being offline, the
OTP counter stored on the Yubikey will be increased. Don&rsquo;t forget to synchronize the database (which will also synchronize the OTP auxiliary file) as soon as possible to avoid problems with accessing your database on other devices! If you often need
to open the database while you&rsquo;re offline, consider increasing the look-ahead window length!</p>
</div><div class="ClearBoth"></div>

View File

@@ -1,25 +0,0 @@
Keepass2Android's apk is pretty big, e.g. when comparing to Keepassdroid. The main difference is that Keepass2Android is built on Mono for Android. Mono is an open-source implementation of the Microsoft .Net Framework (installed on pretty much every Windows PC). On Windows, the .net framework requires several hundred MB (but only once, not for every application). On Android devices, Mono is not installed globally. Instead, it is packaged into every app. The more features from Mono are required, the bigger the package becomes.
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
Google libraries 0.8 MB
(for Drive support)
Resources Strings, Icons.. 2.1 MB
Password Font 0.2 MB
Java Code including Dropbox 1.1 MB
GDrive, SkyDrive
libraries
Keepass library 0.2 MB
Keepass2Android Code 0.3 MB
Java/Mono bindings 0.5 MB
rest 0.3 MB
TOTAL 13 MB
```

View File

@@ -1,20 +0,0 @@
Google has introduced the Android Autofill interface in Android 8. Keepass2Android supports this interface. In most Android apps and all Autofill-enabled browsers, this is the most convenient way of entering passwords. As soon as you focus a field, you will see a popup "Fill with Keepass2Android".
<img src="autofill-facebook.png" />
After clicking this popup, you can unlock your KP2A database. If automatic look up succeeds, KP2A will close automatically, if not you are prompted to select the entry you want to auto-fill. When returning to the target app, the fields should be filled automatically already.
As of January 2018, the following browsers are known to have Android Autofill support:
* Firefox Focus / Firefox Klar
* Opera Mini
These browsers do not (yet) have autofill support:
* Google Chrome
* Firefox for Android ([bugzilla entry](https://bugzilla.mozilla.org/show_bug.cgi?id=1352011))
* Brave-Browser
* Opera
Please use the Share-URL-feature and the built-in KP2A keyboard for these browsers.

View File

@@ -1,25 +1 @@
# Who we are
Philipp Crocoll
Wallonenstr. 4
76297 Stutensee
Germany
is the author of Keepass2Android and Keepass2Android Offline.
# What data is collected?
The contents of your password database is yours and is never collected by us. Keepass2Android stores this data on a location chosen by the user and encrypted in the Keepass database format. The app author does not have any access, neither to the files nor the contents. Depending on the user's choice of the storage location, the files may be stored on third-party servers like Dropbox or Google Drive.
Keepass2Android does not collect personal identifiable information. For debugging purposes, the user may activate creating a debug log. This collects data inside the app and is not accessible to any other app nor the author of the app, unless the user explicitly sends the debug log to the author. Debug logs usually do not contain personal identifiable information, except if such information is part of file or folder names. Debug logs will not be shared with third parties unless explicitly authorized by the sender.
# What Android permissions are required?
* **Internet** (Keepass2Android regular only): Required to allow the user to read/store password databases or key files on remote locations, e.g. Dropbox or via WebDav.
* **Contacts/Accounts** (Keepass2Android regular only): Required by the Google Drive SDK. If you want to access files on Google Drive, you are prompted to select one of the Google Accounts on your phone to use. The permission is required to query the list of Google accounts on the device. Keepass2Android does not access your personal contacts.
* **Storage**: Required to allow the user to read/store password databases or key files on the device locally.
* **Fingerprint/Biometric**: Required if you want to use biometric unlock.
* **Vibrate**: Required by the built-in keyboard (vibrate on key press)
* **Camera**: Required for scanning OTP QR Codes
* **Foreground service**: Required to keep the app alive for QuickUnlock (so you don't need to enter your full master password repeatedly)
This page has been moved to the [wiki](https://github.com/PhilippC/keepass2android/wiki/Privacy-Policy)

View File

@@ -2,8 +2,8 @@
# 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.
Keepass2Android is a password manager app. It allows to store and retrieve passwords and other sensitive information in a file called "database", secured with a strong key.
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 2.x and KeepassXC on PCs as well as many other KeePass ports for a variety of platforms.
# Where to get it?
Regular stable releases of Keepass2Android are available on [Google Play](https://play.google.com/store/apps/details?id=keepass2android.keepass2android).
@@ -17,11 +17,7 @@ Beta-releases can be obtained by opting in to the [Beta testing channel](https:/
* [Make a donation](http://philipp.crocoll.net/donate.php)
# How do I learn more?
Please see the [documentation](Documentation.md).
Please see the [wiki](https://github.com/PhilippC/keepass2android/wiki/Documentation) for further information.
# How do I build the project?
If you want to build Keepass2Android, check the [build guide](Build.readme.md).
The project homepage is https://philipp.crocoll.net/keepass2android/index.php
<img src="https://github.com/PhilippC/keepass2android/actions/workflows/build.yml/badge.svg" alt="build status" /> [Build status](https://github.com/PhilippC/keepass2android/actions)

View File

@@ -1,72 +0,0 @@
# SFTP Open/Create Database Credentials Documentation
## Basic Settings
* **Host** -- the hostname or IP address of the SFTP server to connect to
* **Port** -- the listening TCP port of the SFTP server to connect to (default: 22)
* **Username** -- the user/account name on the SFTP server that has access to the database
* **Initial directory** -- The path on the SFTP server that will be used as a starting point when choosing the remote database file
### Authentication Modes
#### Password
Authenticate using a password
* **Password** -- the password associated with **username** used to log into the SFTP server
#### K2A Private/Public Key
Authenticate using a private/public key pair that is generated internally by KP2A
* **SEND PUBLIC KEY...** -- Opens a standard Android "Share" screen containing the KP2A public key content. This allows for the public key to be sent via email, SMS, etc. This public key will need to be added to the SFTP server's user's "authorized keys" to allow private/public key authentication.
#### Custom Private Key
Authenticate using an existing private/public key pair. Use this option instead of *K2A Private/Public Key* if you wish to use a key pair that is already set up for this **username** on the SFTP server.
* **Selected private key** -- a combo-box containing a list of custom private keys that KP2A knows about, and a special `[Add new...]` option.
##### Add A New Private Key
* Select `[Add new...]`
* Enter a name for the new key in **New key name**
* Enter the private key contents (text) into **New key content**. **TIP:** The easiest way to accomplish this is to open the private key file in a text editor on the device, **Select All**, **Copy** to the clipboard, and paste it into **New key content**.
* Tap **SAVE PRIVATE KEY** to add the new key to the known list.
##### Use An Existing Private Key
* To use a private key that has already been imported into KP2A, simply select it from the list of keys.
##### Remove An Existing Key
* To remove a private that has been imported into KP2A, select it from the list and tap **DELETE PRIVATE KEY**.
A **key passphrase** can be supplied (if the key pair requires it)
## Advanced Settings
* **Connection timeout seconds** -- the number of seconds to wait for a connection to the server before giving up and considering the server as unavailable/unreachable
### Key Algorithm Manipulation
**NOTE: It is very rare that these fields need to be (or should be) specified. Use at your own risk!**
* **Key Exchange (KEX) Algorithm(s)** -- Explicitly set or modify the ordered list of Key Exchange algorithms that the SSH/SFTP client library will try to use
* **Server Host Key Algorithm(s)** -- Explicitly set or modify the ordered list of Server Host Key algorithms that the SSH/SFTP client library will try to use
#### How It Works
The SSH/SFTP client has a pre-defined ordered list of algorithm names that it will use to negotiate with the server to handle key exchange. In rare cases there are compatibility issues where Android OS has not properly implemented full support for algorithms listed. This can result in a connection failure, even if there is a suitable algorithm available (of lesser priority in the list).
The fields listed above allow these lists to be manipulated in the following ways to overcome/workaround such problems. The value is a comma-separated list of "algorithm spec" entries. Specs can be one of:
* Direct replacement of values -- Ex: `primary_alg,secondary_alg`
* Prepend to values -- Ex: `+try_first_alg`
* Append to values -- Ex: `try_last_alg+`
* Remove a specific value -- Ex: `-bad_alg`
* Remove values matching prefix -- Ex: `-bad_starting_with*`
* Remove values matching suffix -- Ex: `-*bad_ending_with`
* Remove values matching substring -- Ex: `-*bad_middle*`
* Remove values matching prefix and suffix -- Ex: `-alg_begin*end`
For example, assume the system's KEX algorithm list is:
`ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256`
These are various outcomes (user KEX field -> result):
* Prefix removal: `-ec*` --> `diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256`
* Suffix removal, appending: `-*256,+first_alg,almost_last_alg+,last_alg+` --> `first_alg,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,almost_last_alg,last_alg`
* Direct replacement: `first_alg,middle_alg,last_alg` --> `first_alg,middle_alg,last_alg`
## Selecting A Database
Once all applicable fields have been entered and/or options selected, tapping **OK** will attempt to connect to the SFTP server. First time connections may pop up a dialog window asking to accept the host's authenticity (tap **yes** if the host is trusted), as well as potentially creating a new `known_hosts` file (tap **yes** to do so). If the connection is successful, a remote file browser screen will open. Navigate and select the Keepass database to open.

View File

@@ -1 +0,0 @@
theme: jekyll-theme-slate

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -35,8 +35,6 @@ namespace KeePassLib.Cryptography
{
get
{
Debug.Assert(m_dicts.Count > 0); // Should be initialized
int iMaxLen = 0;
foreach(int iLen in m_dicts.Keys)
{

View File

@@ -445,6 +445,9 @@ namespace Kp2aAutofillParser
public static string ToCanonicalHint(string hint)
{
//avoid crash when looking up a null key
if (hint == null)
return "";
string canonicalHint;
if (!hintToCanonicalReplacement.TryGetValue(hint, out canonicalHint))
canonicalHint = hint;
@@ -841,6 +844,7 @@ namespace Kp2aAutofillParser
continue;
if (viewHints.Where(h => h != null).Select(AutofillHintsHelper.ToCanonicalHint).Intersect(_autofillHintsForLogin).Any())
{
AddFieldToHintMap(viewNode, viewHints.Where(h => h != null).Select(AutofillHintsHelper.ToCanonicalHint).ToHashSet().ToArray());
}

View File

@@ -29,6 +29,14 @@ namespace keepass2android
}
public enum MessageSeverity
{
Info,
Warning,
Error
}
/// <summary>
/// Interface through which Activities and the logic layer can access some app specific functionalities and Application static data
/// </summary>
@@ -102,10 +110,13 @@ namespace keepass2android
Context ctx,
string messageSuffix = "");
/// <summary>
/// Returns a Handler object which can run tasks on the UI thread
/// </summary>
Handler UiThreadHandler { get; }
void ShowMessage(Context ctx, int resourceId, MessageSeverity severity);
void ShowMessage(Context ctx, string text, MessageSeverity severity);
/// <summary>
/// Returns a Handler object which can run tasks on the UI thread
/// </summary>
Handler UiThreadHandler { get; }
IProgressDialog CreateProgressDialog(Context ctx);

View File

@@ -13,7 +13,7 @@ using Android.Content.PM;
using Android.OS;
using Android.Preferences;
using Java.IO;
using KeePass.Util;
using KeePassLib.Serialization;
using KeePassLib.Utility;
using File = System.IO.File;
@@ -121,7 +121,7 @@ namespace keepass2android.Io
var response = ex.Response as HttpWebResponse;
if ((response != null) && (response.StatusCode == HttpStatusCode.NotFound))
{
throw new FileNotFoundException(ex.Message, ioc.Path, ex);
throw new FileNotFoundException(ExceptionUtil.GetErrorMessage(ex), ioc.Path, ex);
}
if (ex.Status == WebExceptionStatus.TrustFailure)
{

View File

@@ -13,6 +13,7 @@ using Keepass2android.Javafilestorage;
#endif
using Exception = System.Exception;
using FileNotFoundException = Java.IO.FileNotFoundException;
using KeePass.Util;
namespace keepass2android.Io
{
@@ -42,7 +43,7 @@ namespace keepass2android.Io
}
catch (FileNotFoundException e)
{
throw new System.IO.FileNotFoundException(e.Message, e);
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
}
catch (Java.Lang.Exception e)
{
@@ -195,7 +196,7 @@ namespace keepass2android.Io
}
catch (FileNotFoundException e)
{
throw new System.IO.FileNotFoundException(e.Message, e);
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
}
catch (Java.Lang.Exception e)
{
@@ -214,7 +215,7 @@ namespace keepass2android.Io
}
catch (FileNotFoundException e)
{
throw new System.IO.FileNotFoundException(e.Message, e);
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
}
catch (Java.Lang.Exception e)
{
@@ -244,7 +245,7 @@ namespace keepass2android.Io
}
catch (FileNotFoundException e)
{
throw new System.IO.FileNotFoundException(e.Message, e);
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
}
catch (Java.Lang.Exception e)
{

View File

@@ -8,6 +8,7 @@ using Android.Content;
using Android.OS;
using FluentFTP;
using FluentFTP.Exceptions;
using KeePass.Util;
using KeePassLib;
using KeePassLib.Serialization;
using KeePassLib.Utility;
@@ -127,7 +128,7 @@ namespace keepass2android.Io
var ftpEx = (FtpCommandException) exception;
if (ftpEx.CompletionCode == "550")
throw new FileNotFoundException(exception.Message, exception);
throw new FileNotFoundException(ExceptionUtil.GetErrorMessage(exception), exception);
}
return exception;

View File

@@ -3,6 +3,7 @@ using System.Reflection;
using System.Text;
using Android.Content;
using Android.Util;
using KeePass.Util;
using keepass2android.Io.ItemLocation;
using KeePassLib.Serialization;
using KeePassLib.Utility;
@@ -522,10 +523,10 @@ namespace keepass2android.Io
{
if (e.IsMatch(GraphErrorCode.ItemNotFound.ToString()))
return new FileNotFoundException(e.Message);
return new FileNotFoundException(ExceptionUtil.GetErrorMessage(e));
if (e.Message.Contains("\n\n404 : ")
) //hacky solution to check for not found. errorCode was null in my tests so I had to find a workaround.
return new FileNotFoundException(e.Message);
return new FileNotFoundException(ExceptionUtil.GetErrorMessage(e));
return e;
}
@@ -1148,30 +1149,46 @@ namespace keepass2android.Io
});
}
string? driveId = parentPath.DriveId;
if ((string.IsNullOrEmpty(driveId)) && (drives?.Any() == true))
{
driveId = drives.First().Id;
}
if (!CanListShares)
return result;
var sharedWithMeResponse = await client.Drives[driveId].SharedWithMe.GetAsSharedWithMeGetResponseAsync();
foreach (DriveItem i in sharedWithMeResponse?.Value ?? [])
try
{
var oneDrive2ItemLocation = parentPath.BuildShare(i.RemoteItem.Id, i.RemoteItem.Name, i.RemoteItem.WebUrl, i.RemoteItem.ParentReference.DriveId);
FileDescription sharedFileEntry = new FileDescription()
string? driveId = parentPath.DriveId;
if (string.IsNullOrEmpty(driveId))
{
CanWrite = true, CanRead = true, DisplayName = i.Name,
IsDirectory = true,
Path = oneDrive2ItemLocation.ToString()
};
result.Add(sharedFileEntry);
driveId = (await client.Me.Drive.GetAsync()).Id;
}
if ((string.IsNullOrEmpty(driveId)) && (drives?.Any() == true))
{
driveId = drives.First().Id;
}
var sharedWithMeResponse = await client.Drives[driveId].SharedWithMe.GetAsSharedWithMeGetResponseAsync();
foreach (DriveItem i in sharedWithMeResponse?.Value ?? [])
{
var oneDrive2ItemLocation = parentPath.BuildShare(i.RemoteItem.Id, i.RemoteItem.Name, i.RemoteItem.WebUrl, i.RemoteItem.ParentReference.DriveId);
FileDescription sharedFileEntry = new FileDescription()
{
CanWrite = true,
CanRead = true,
DisplayName = i.Name,
IsDirectory = (i.Folder != null) || ((i.RemoteItem != null) && (i.RemoteItem.Folder != null)),
Path = oneDrive2ItemLocation.ToString()
};
result.Add(sharedFileEntry);
}
}
catch (Exception e)
{
logDebug("Failed to list shares: " + e);
}
return result;
}

View File

@@ -16,20 +16,32 @@ namespace keepass2android.Io
/// </summary>
public class OneDriveFileStorage: IFileStorage
{
public IEnumerable<string> SupportedProtocols
public OneDriveFileStorage(IKp2aApp app)
{
_app = app;
}
private readonly IKp2aApp _app;
public IEnumerable<string> SupportedProtocols
{
get
{
yield return "skydrive";
yield return "onedrive";
}
}
}
private Exception GetDeprecatedMessage()
string GetDeprecatedMessage()
{
return
"You have opened your file through a deprecated Microsoft API. Please select Change database, Open Database and then select OneDrive again.";
}
private Exception GetDeprecatedException()
{
return new Exception(
"You have opened your file through a deprecated Microsoft API. Please select Change database, Open Database and then select One Drive again.");
GetDeprecatedMessage());
}
public bool UserShouldBackup
@@ -39,133 +51,132 @@ namespace keepass2android.Io
public void Delete(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public string GetCurrentFileVersionFast(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public Stream OpenFileForRead(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public string GetFileExtension(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public bool RequiresCredentials(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
return false;
}
public void CreateDirectory(IOConnectionInfo ioc, string newDirName)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public FileDescription GetFileDescription(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public bool RequiresSetup(IOConnectionInfo ioConnection)
{
throw GetDeprecatedMessage();
return false;
}
public string IocToPath(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId)
{
throw GetDeprecatedMessage();
}
public void PrepareFileUsage(IFileStorageSetupInitiatorActivity activity, IOConnectionInfo ioc, int requestCode,
bool alwaysReturnSuccess)
{
throw GetDeprecatedMessage();
_app.ShowMessage(activity.Activity, GetDeprecatedMessage(), MessageSeverity.Error);
}
public void PrepareFileUsage(Context ctx, IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
}
public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
{
throw GetDeprecatedMessage();
}
public void OnResume(IFileStorageSetupActivity activity)
{
throw GetDeprecatedMessage();
}
public void OnStart(IFileStorageSetupActivity activity)
{
throw GetDeprecatedMessage();
}
public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
{
throw GetDeprecatedMessage();
}
public string GetDisplayName(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
return "File using deprecated Microsoft API. Please update.";
}
public string CreateFilePath(string parent, string newFilename)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public bool IsPermanentLocation(IOConnectionInfo ioc)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
public bool IsReadOnly(IOConnectionInfo ioc, OptionalOut<UiStringKey> reason = null)
{
throw GetDeprecatedMessage();
throw GetDeprecatedException();
}
}
}

View File

@@ -4,6 +4,7 @@ using Android.Content;
using Android.OS;
using Android.Widget;
using Java.Net;
using KeePass.Util;
using KeePassLib.Serialization;
using keepass2android.Io;
@@ -94,7 +95,7 @@ namespace keepass2android
}
if ((resultCode == Result.Canceled) && (data != null) && (data.HasExtra("EXTRA_ERROR_MESSAGE")))
{
ShowToast(data.GetStringExtra("EXTRA_ERROR_MESSAGE"));
ShowErrorToast(data.GetStringExtra("EXTRA_ERROR_MESSAGE"));
}
if (resultCode == Result.Ok)
@@ -150,7 +151,7 @@ namespace keepass2android
protected abstract void StartFileChooser(string path, int requestCode, bool isForSave);
protected abstract void ShowToast(string text);
protected abstract void ShowErrorToast(string text);
protected abstract void ShowInvalidSchemeMessage(string dataString);
@@ -208,7 +209,7 @@ namespace keepass2android
{
return () =>
{
ShowToast(_app.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message);
ShowErrorToast(_app.GetResourceString(UiStringKey.ErrorOcurred) + " " + ExceptionUtil.GetErrorMessage(e));
ReturnCancel();
};
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KeePass.Util
{
public class ExceptionUtil
{
public static string GetErrorMessage(Exception e)
{
string errorMessage = e.Message;
if (e is Java.Lang.Exception javaException)
{
errorMessage = javaException.LocalizedMessage ?? javaException.Message ?? errorMessage;
}
return errorMessage;
}
}
}

View File

@@ -5,6 +5,7 @@ using System.Security.Cryptography;
using System.Text;
using Android.App;
using Android.Content;
using KeePass.Util;
using KeePassLib.Cryptography;
using KeePassLib.Serialization;
using KeePassLib.Utility;
@@ -65,7 +66,7 @@ namespace keepass2android
}
catch (Exception e)
{
Finish(false, e.Message);
Finish(false, ExceptionUtil.GetErrorMessage(e));
}
}

View File

@@ -10,6 +10,7 @@ using Com.Keepassdroid.Database.Exception;
#endif
using Com.Keepassdroid.Database.Save;
using Java.Util;
using KeePass.Util;
using KeePassLib;
using KeePassLib.Cryptography;
using KeePassLib.Cryptography.Cipher;
@@ -82,15 +83,14 @@ namespace keepass2android
catch (Java.IO.FileNotFoundException e)
{
throw new FileNotFoundException(
e.Message, e);
ExceptionUtil.GetErrorMessage(e), e);
}
catch (Java.Lang.Exception e)
{
if (e.Message == "Invalid key!")
throw new InvalidCompositeKeyException();
throw new Exception(e.LocalizedMessage ??
e.Message ??
e.GetType().Name, e);
throw new Exception(ExceptionUtil.GetErrorMessage(e) ??
e.GetType().Name, e);
}
HashOfLastStream = hashingStream.Hash;

View File

@@ -6,6 +6,7 @@ using Android.App;
using Android.Content;
using KeePassLib.Serialization;
using keepass2android.Io;
using KeePass.Util;
namespace keepass2android
{
@@ -109,7 +110,7 @@ namespace keepass2android
catch (Exception e)
{
Kp2aLog.LogUnexpectedError(e);
Finish(false, e.Message);
Finish(false, ExceptionUtil.GetErrorMessage(e));
}
}

View File

@@ -21,6 +21,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Android.App;
using KeePass.Util;
using keepass2android.database.edit;
using KeePassLib;
using KeePassLib.Keys;
@@ -103,10 +104,10 @@ namespace keepass2android
}
catch (AggregateException e)
{
string message = e.Message;
string message = ExceptionUtil.GetErrorMessage(e);
foreach (var innerException in e.InnerExceptions)
{
message = innerException.Message;
message = ExceptionUtil.GetErrorMessage(innerException);
// Override the message shown with the last (hopefully most recent) inner exception
Kp2aLog.LogUnexpectedError(innerException);
}
@@ -116,14 +117,14 @@ namespace keepass2android
catch (DuplicateUuidsException e)
{
Kp2aLog.Log(e.ToString());
Finish(false, _app.GetResourceString(UiStringKey.DuplicateUuidsError) + " " + e.Message + _app.GetResourceString(UiStringKey.DuplicateUuidsErrorAdditional), false, Exception);
Finish(false, _app.GetResourceString(UiStringKey.DuplicateUuidsError) + " " + ExceptionUtil.GetErrorMessage(e) + _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 ?? (e is FileNotFoundException ? _app.GetResourceString(UiStringKey.FileNotFound) : "")), false, Exception);
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + (ExceptionUtil.GetErrorMessage(e) ?? (e is FileNotFoundException ? _app.GetResourceString(UiStringKey.FileNotFound) : "")), false, Exception);
return;
}

View File

@@ -130,24 +130,24 @@ namespace keepass2android
if ( !String.IsNullOrEmpty(message) ) {
Kp2aLog.Log("OnFinish message: " + message);
if (makeDialog && ctx != null)
{
try
{
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ctx);
builder.SetMessage(message)
.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ((Dialog)sender).Dismiss())
.Show();
{
try
{
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ctx);
builder.SetMessage(message)
.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ((Dialog)sender).Dismiss())
.Show();
}
catch (Exception)
{
Toast.MakeText(ctx, message, ToastLength.Long).Show();
}
}
{
Toast.MakeText(ctx, message, ToastLength.Long).Show();
}
}
else
Toast.MakeText(ctx ?? Application.Context, message, ToastLength.Long).Show();
}
}
}
}
}

View File

@@ -29,6 +29,7 @@ using KeePassLib.Utility;
using keepass2android.Io;
using Debug = System.Diagnostics.Debug;
using Exception = System.Exception;
using KeePass.Util;
namespace keepass2android
{
@@ -187,7 +188,7 @@ namespace keepass2android
}
*/
Kp2aLog.LogUnexpectedError(e);
Finish(false, e.Message);
Finish(false, ExceptionUtil.GetErrorMessage(e));
return;
}
}
@@ -222,8 +223,8 @@ namespace keepass2android
catch (Exception e)
{
Kp2aLog.LogUnexpectedError(e);
Kp2aLog.Log("Error in worker thread of SaveDb: " + e);
Finish(false, e.Message);
Kp2aLog.Log("Error in worker thread of SaveDb: " + ExceptionUtil.GetErrorMessage(e));
Finish(false, ExceptionUtil.GetErrorMessage(e));
}
});
@@ -233,7 +234,7 @@ namespace keepass2android
{
Kp2aLog.LogUnexpectedError(e);
Kp2aLog.Log("Error starting worker thread of SaveDb: "+e);
Finish(false, e.Message);
Finish(false, ExceptionUtil.GetErrorMessage(e));
}
}

25
src/build-scripts/build-java.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
set -e
#unset ANDROID_NDK_HOME ANDROID_NDK
pushd ../java/
pushd JavaFileStorageTest-AS
./gradlew assemble
popd
pushd KP2ASoftkeyboard_AS
./gradlew assemble
popd
pushd Keepass2AndroidPluginSDK2
./gradlew assemble
popd
pushd KP2AKdbLibrary
./gradlew assemble
popd
popd

View File

@@ -0,0 +1,6 @@
#!/bin/bash
set -e
pushd ../java/argon2
ndk-build
popd

View File

@@ -0,0 +1,29 @@
## Setup build environment
* install Android SDK
* install Android NDK
* install dotnet8
```
#from https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/sdk-8.0.407-linux-x64-binaries
wget https://download.visualstudio.microsoft.com/download/pr/9d07577e-f7bc-4d60-838d-f79c50b5c11a/459ef339396783db369e0432d6dc3d7e/dotnet-sdk-8.0.407-linux-x64.tar.gz
mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-8.0.407-linux-x64.tar.gz -C $HOME/dotnet
export DOTNET_ROOT=$HOME/dotnet
export PATH=$PATH:$HOME/dotnet
```
## Build Keepass2Android
```
git clone --recurse-submodules https://github.com/PhilippC/keepass2android.git
cd keepass2android/src/build-scripts
./build-java.sh && ./build-native.sh
cd ..
cp Kp2aBusinessLogic/Io/DropboxFileStorageKeysDummy.cs Kp2aBusinessLogic/Io/DropboxFileStorageKeys.cs
cd keepass2android-app
ln -s Manifests/AndroidManifest_debug.xml AndroidManifest.xml
dotnet workload restore
dotnet restore
dotnet build
```

View File

@@ -304,6 +304,11 @@ public class WebDavStorage extends JavaFileStorageBase {
//relative path:
e.path = buildPathFromHref(parentPath, r.href);
}
if ( (parentPath.indexOf("@") != -1) && (e.path.indexOf("@") == -1))
{
//username/password not contained in .href response. Add it back from parentPath:
e.path = parentPath.substring(0, parentPath.indexOf("@")+1) + e.path.substring(e.path.indexOf("://")+3);
}
if ((depth == 1) && e.isDirectory)
{

View File

@@ -113,4 +113,15 @@ extends Activity implements JavaFileStorage.FileStorageSetupActivity {
return state;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
MainActivity.storageToTest.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
}
}

View File

@@ -147,6 +147,7 @@ import java.util.List;
//import keepass2android.javafilestorage.DropboxCloudRailStorage;
import keepass2android.javafilestorage.DropboxV2Storage;
import keepass2android.javafilestorage.GoogleDriveAppDataFileStorage;
import keepass2android.javafilestorage.GoogleDriveFullFileStorage;
import keepass2android.javafilestorage.ICertificateErrorHandler;
import keepass2android.javafilestorage.JavaFileStorage;
import keepass2android.javafilestorage.JavaFileStorage.FileEntry;
@@ -547,7 +548,7 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
//storageToTest = new GoogleDriveAppDataFileStorage();
storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
@Override
public boolean onValidationError(String error) {
return false;
@@ -558,10 +559,11 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
return false;
}
});
*/
//storageToTest = new DropboxV2Storage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);
//storageToTest = new DropboxFileStorage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart);
//storageToTest = new DropboxAppFolderFileStorage(ctx,"ax0268uydp1ya57", "3s86datjhkihwyc", true);
storageToTest = new GoogleDriveFullFileStorage();
return storageToTest;
@@ -580,6 +582,8 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

View File

@@ -21,7 +21,7 @@
<!-- Title for Latin keyboard -->
<string name="english_ime_name">Keepass2Android-Tastatur</string>
<!-- Title for Latin keyboard settings activity / dialog -->
<string name="english_ime_settings">Keepass2Android-Tastatureinstellungen</string>
<string name="english_ime_settings">Android-Tastatureinstellungen</string>
<!-- Title for Latin keyboard input options dialog -->
<string name="english_ime_input_options">Eingabeoptionen</string>
<!-- Option to provide vibrate/haptic feedback on keypress -->
@@ -49,7 +49,7 @@
<!-- Description for text prediction -->
<string name="prediction_summary">Automatische Vervollständigung während der Eingabe aktivieren</string>
<!-- Dialog title for auto complete choices -->
<string name="auto_complete_dialog_title">Autom. vervollständigen</string>
<string name="auto_complete_dialog_title">Autovervollständigung</string>
<!-- Option to enable text prediction in landscape -->
<string name="prediction_landscape">Textfeld vergrößern</string>
<!-- Description for text prediction -->
@@ -62,7 +62,7 @@
<string name="auto_punctuate">Autom. Zeichensetzung</string>
<!-- Description for auto punctuate -->
<!-- Option to enable quick fixes -->
<string name="quick_fixes">Quick Fixes</string>
<string name="quick_fixes">Schnelle Korrektur</string>
<!-- Description for quick fixes -->
<string name="quick_fixes_summary">Korrigiert gängige Tippfehler</string>
<!-- Option to enable showing suggestions -->
@@ -74,7 +74,7 @@
<!-- Description for auto completion -->
<string name="auto_complete_summary">Leertaste und Interpunktion fügen autom. ein markiertes Wort ein</string>
<!-- Option to show/hide the settings key -->
<string name="prefs_settings_key">Einstellungstaste anz.</string>
<string name="prefs_settings_key">Einstellungs-Schlüssel anzeigen</string>
<!-- Array of the settings key mode values -->
<!-- Option to automatically decide to show/hide the settings key -->
<string name="settings_key_mode_auto_name">Automatisch</string>
@@ -112,7 +112,7 @@
<!-- Tip to long press on typed word to add to dictionary -->
<string name="tip_add_to_dictionary">Lange auf das Wort ganz links außen drücken, um es zum Wörterbuch hinzuzufügen</string>
<!-- Instruction to touch the bubble to continue -->
<string name="touch_to_continue">Diesen Hinweis berühren, um fortzufahren »</string>
<string name="touch_to_continue">Diesen Hinweis antippen, um fortzufahren.»</string>
<!-- Instruction to touch the bubble to start typing -->
<string name="touch_to_finish">Hier berühren, um diesen Hinweis zu schließen und mit dem Tippen zu beginnen!</string>
<!-- Tutorial tip 1 - The keyboard opens any time you touch a text field -->
@@ -138,7 +138,7 @@
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
<string name="label_symbol_key">\?123</string>
<!-- Label for "switch to numeric" key. Must be short to fit on key! -->
<string name="label_phone_key">Num</string>
<string name="label_phone_key">123</string>
<!-- Label for "switch to alphabetic" key. Must be short to fit on key! -->
<string name="label_alpha_key">ABC</string>
<!-- Label for ALT modifier key. Must be short to fit on key! -->
@@ -186,7 +186,7 @@
<!-- Short hint shown in candidate view to explain voice input. -->
<string name="voice_swipe_hint"><b>„Hinweis:“</b>„ Ziehen Sie zum Sprechen den Finger über die Tastatur.“</string>
<!-- Short hint shown in candidate view to explain that user can speak punctuation. -->
<string name="voice_punctuation_hint"><b>Hinweis:</b>Versuchen Sie beim nächsten Mal, Satzzeichen wie „Punkt“, „Komma“ oder „Fragezeichen“ per Sprachbefehl einzugeben.</string>
<string name="voice_punctuation_hint"><b>Hinweis: </b>Versuche beim nächsten Mal, Satzzeichen wie „Punkt“, „Komma“ oder „Fragezeichen“ per Sprachbefehl einzugeben.</string>
<!-- Label on button to stop recognition. Must be short to fit on button. -->
<string name="cancel">Abbrechen</string>
<!-- Label on button when an error occurs -->
@@ -216,7 +216,7 @@
<!-- appears above image showing the user to click on a TextView to show the IME -->
<string name="open_the_keyboard"><font size="17"><b>„Tastatur öffnen“\n</b></font><font size="3">\n</font>„Berühren Sie ein beliebiges Textfeld.“</string>
<!-- appears above the image showing the back button used to close the keyboard -->
<string name="close_the_keyboard"><font size="17"><b>Tastatur schließen\n</b></font><font size="3">\n</font>Drücken Sie die Zurücktaste.</string>
<string name="close_the_keyboard"><font size="17"><b>Tastatur schließen\n</b></font><font size="3">\n</font>Drücken die Zurück-Taste.</string>
<!-- appears above image showing how to use touch and hold -->
<string name="touch_and_hold"><font size="17"><b>„Für Optionen eine Taste berühren und gedrückt halten“\n</b></font><font size="3">\n</font>„Greifen Sie auf Satzzeichen und Akzente zu.“</string>
<!-- appears above image showing how to access keyboard settings -->

View File

@@ -19,71 +19,124 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title for Latin keyboard -->
<string name="english_ime_name">מקלדת של Keepass2Android</string>
<!-- Title for Latin keyboard settings activity / dialog -->
<string name="english_ime_settings">הגדרות של מקלדת אנדרואיד</string>
<!-- Title for Latin keyboard input options dialog -->
<string name="english_ime_input_options">אפשרויות קלט</string>
<!-- Option to provide vibrate/haptic feedback on keypress -->
<string name="vibrate_on_keypress">רטט בזמן לחיצה על כפתור</string>
<!-- Option to play back sound on keypress in soft keyboard -->
<string name="sound_on_keypress">צליל בזמן לחיצה על כפתור</string>
<!-- Option to pop up the character with a larger font above soft keyboard -->
<string name="popup_on_keypress">אות קופצת בלחיצה על כפתור</string>
<!-- Option to enable using nearby keys when correcting/predicting -->
<string name="hit_correction">תקן שגיאות הקלדה</string>
<!-- Description for hit_correction -->
<string name="hit_correction_summary">אפשר תיקון שגיאות קלט</string>
<!-- Option to enable using nearby keys when correcting/predicting in landscape-->
<string name="hit_correction_land">קלט שגוי במצג אופקי</string>
<!-- Description for hit_correction in landscape -->
<string name="hit_correction_land_summary">אפשר תיקון שגיאות קלט</string>
<!-- Option to automatically correct word on hitting space -->
<string name="auto_correction">הצעות של מילים</string>
<!-- Description for auto_correction -->
<string name="auto_correction_summary">תקן את המילה הקודמת אוטומטית</string>
<!-- Option to enable text prediction -->
<string name="prediction">הצעות של מילים</string>
<!-- Category title for text prediction -->
<string name="prediction_category">הגדרות של הצעות מילים</string>
<!-- Description for text prediction -->
<string name="prediction_summary">אפשר השלמה אוטומטית בזמן הקלדה</string>
<!-- Dialog title for auto complete choices -->
<string name="auto_complete_dialog_title">השלמה אוטומטית</string>
<!-- Option to enable text prediction in landscape -->
<string name="prediction_landscape">הגדל את השדה של הטקסט</string>
<!-- Description for text prediction -->
<string name="prediction_landscape_summary">הסתר הצעות מילים במצג לרוחב</string>
<!-- Option to enable auto capitalization of sentences -->
<string name="auto_cap">אות ראשית גדולה אוטומטיות</string>
<!-- Description for auto cap -->
<string name="auto_cap_summary">הגדל אוטומטית את האות הראשונה במשפט</string>
<!-- Option to enable auto punctuate -->
<string name="auto_punctuate">ניקוד אוטומטי</string>
<!-- Description for auto punctuate -->
<!-- Option to enable quick fixes -->
<string name="quick_fixes">תיקונים מהירים</string>
<!-- Description for quick fixes -->
<string name="quick_fixes_summary">מתקן טעויות נפוצות בהקלדה</string>
<!-- Option to enable showing suggestions -->
<string name="show_suggestions">הצג הצעות</string>
<!-- Description for show suggestions -->
<string name="show_suggestions_summary">הצג מילים מוצעות בזמן הקלדה</string>
<!-- Option to enable auto completion -->
<string name="auto_complete">השלמה אוטומטית</string>
<!-- Description for auto completion -->
<string name="auto_complete_summary">מקש רווח או מקש הניקוד אוטומטית מכניסים את המילה המודגשת</string>
<!-- Option to show/hide the settings key -->
<string name="prefs_settings_key">הצג כפתור הגדרות</string>
<!-- Array of the settings key mode values -->
<!-- Option to automatically decide to show/hide the settings key -->
<string name="settings_key_mode_auto_name">אוטומטי</string>
<!-- Option to always show the settings key -->
<string name="settings_key_mode_always_show_name">הצג תמיד</string>
<!-- Option to always hide the settings key -->
<string name="settings_key_mode_always_hide_name">הסתר תמיד</string>
<!-- Array of the settings key modes -->
<!-- Option to enable bigram completion -->
<string name="bigram_suggestion">הצעות bigram</string>
<!-- Description for auto completion -->
<string name="bigram_suggestion_summary">תשתמש במילה הקודמת כדי לשפר את ההצעה</string>
<!-- Array of prediction modes -->
<string-array name="prediction_modes">
<item>אף אחד</item>
<item>Basic</item>
<item>Advanced</item>
<item>בסיסי</item>
<item>מתקדם</item>
</string-array>
<!-- Don't translate -->
<!-- Don't translate -->
<!-- Don't translate -->
<!-- Indicates that a word has been added to the dictionary -->
<string name="added_word"><xliff:g id="word">%s</xliff:g> : נשמר</string>
<!-- Tip to long press on keys -->
<string name="tip_long_press">החזק כפתור כדי לראות סימנים מיוחדים (ø, ö, וכו\')</string>
<!-- Tip to dismiss keyboard -->
<string name="tip_dismiss">הקש על כפתור חזור \u21B6 כדי לסגור את המקלדת בכל שלב</string>
<!-- Tip to press ?123 to access numbers and symbols -->
<string name="tip_access_symbols">קבל גישה למספר ולסימנים</string>
<!-- Tip to long press on typed word to add to dictionary -->
<string name="tip_add_to_dictionary">גע והשאר את המילה הכי שמאלית לחוצה כדי להוסיף אותה למילון
</string>
<!-- Instruction to touch the bubble to continue -->
<string name="touch_to_continue">גע ברמז זה כדי להמשיך »</string>
<!-- Instruction to touch the bubble to start typing -->
<string name="touch_to_finish">גע פה כדי לסגור את הרמז הזה ותתחיל להקליד!</string>
<!-- Tutorial tip 1 - The keyboard opens any time you touch a text field -->
<string name="tip_to_open_keyboard"><b>המקלדת נפתחת בכל רגע שאתה נוגע בשדה עם טקסט</b></string>
<!-- Tutorial tip 2 - Touch and hold a key to view accents (examples) -->
<string name="tip_to_view_accents">&lt;b&gt;גע והחזק מקש כדי לראות סימנים\n(&lt;, &gt;, =, ; וכך הלאה)&lt;/b&gt;</string>
<!-- Tutorial tip 3 - How to switch to number/symbol keyboard -->
<string name="tip_to_open_symbols"><b>עבור למספרים וסימנים בעזרת לחיצה על מקש זה</b></string>
<!-- Tutorial tip 4 - How to switch back to alphabet keyboard -->
<string name="tip_to_close_symbols"><b>חזור להקליד אותיות בעזרת נגיעה על אותו המקש שוב</b></string>
<!-- Tutorial tip 5 - How to launch keyboard settings -->
<string name="tip_to_launch_settings"><b>גע והחזק מקש זה כדי לשנות את הגדרות המקלדת כגון השלמה אוטומטית</b></string>
<!-- Tutorial tip 6 - Done with the tutorial -->
<string name="tip_to_start_typing"><b>נסה זאת!</b></string>
<!-- Label for soft enter key when it performs GO action. Must be short to fit on key! -->
<string name="label_go_key">המשך</string>
<!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key! -->
<string name="label_next_key">הבא</string>
<!-- Label for soft enter key when it performs DONE action. Must be short to fit on key! -->
<string name="label_done_key">בוצע</string>
<!-- Label for soft enter key when it performs SEND action. Must be short to fit on key! -->
<string name="label_send_key">שלח</string>
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
<string name="label_symbol_key">\?123</string>
<!-- Label for "switch to numeric" key. Must be short to fit on key! -->
<string name="label_phone_key">123</string>
<!-- Label for "switch to alphabetic" key. Must be short to fit on key! -->
<string name="label_alpha_key">אבג</string>
<!-- Label for ALT modifier key. Must be short to fit on key! -->
<!-- Voice related labels -->
<!-- Title of the warning dialog that shows when a user initiates voice input for

View File

@@ -133,8 +133,11 @@
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
<string name="label_symbol_key">\?123</string>
<!-- Label for "switch to numeric" key. Must be short to fit on key! -->
<string name="label_phone_key">123</string>
<!-- Label for "switch to alphabetic" key. Must be short to fit on key! -->
<string name="label_alpha_key">ABC</string>
<!-- Label for ALT modifier key. Must be short to fit on key! -->
<string name="label_alt_key">ALT</string>
<!-- Voice related labels -->
<!-- Title of the warning dialog that shows when a user initiates voice input for
the first time. -->
@@ -182,6 +185,7 @@
<!-- Label on button to stop recognition. Must be short to fit on button. -->
<string name="cancel">Anulează</string>
<!-- Label on button when an error occurs -->
<string name="ok">Bine</string>
<!-- Preferences item for enabling speech input -->
<string name="voice_input">Intrare voce</string>
<!-- Array of Voice Input modes -->
@@ -213,10 +217,15 @@
<!-- appears above image showing how to access keyboard settings -->
<string name="keyboard_settings"><font size="17"><b>\"Setările tastaturii\"\n</b></font><font size="3">\n</font>\"Atingeţi şi ţineţi apăsată tasta \"<b>\"?123\"</b>\".\"</string>
<!-- popular web domains for the locale - most popular, displayed on the keyboard -->
<string name="popular_domain_0">".com"</string>
<!-- popular web domains for the locale - item 1, displayed in the popup -->
<string name="popular_domain_1">".net"</string>
<!-- popular web domains for the locale - item 2, displayed in the popup -->
<string name="popular_domain_2">".org"</string>
<!-- popular web domains for the locale - item 3, displayed in the popup -->
<string name="popular_domain_3">".gov"</string>
<!-- popular web domains for the locale - item 4, displayed in the popup -->
<string name="popular_domain_4">".edu"</string>
<!-- Menu item for launching Input method picker -->
<string name="selectInputMethod">Selectaţi metoda de introducere a textului</string>
<!-- Title for input language selection screen -->
@@ -240,4 +249,5 @@
<string name="subtype_mode_keyboard">tastatură</string>
<string name="subtype_mode_voice">voce</string>
<!-- Title for Latin keyboard debug settings activity / dialog -->
<string name="kp2a_nextfields"><![CDATA[>]]></string>
</resources>

View File

@@ -133,8 +133,11 @@
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
<string name="label_symbol_key">\?123</string>
<!-- Label for "switch to numeric" key. Must be short to fit on key! -->
<string name="label_phone_key">123</string>
<!-- Label for "switch to alphabetic" key. Must be short to fit on key! -->
<string name="label_alpha_key">ABC</string>
<!-- Label for ALT modifier key. Must be short to fit on key! -->
<string name="label_alt_key">ALT</string>
<!-- Voice related labels -->
<!-- Title of the warning dialog that shows when a user initiates voice input for
the first time. -->
@@ -182,6 +185,7 @@
<!-- Label on button to stop recognition. Must be short to fit on button. -->
<string name="cancel">Hủy bỏ</string>
<!-- Label on button when an error occurs -->
<string name="ok">OK</string>
<!-- Preferences item for enabling speech input -->
<string name="voice_input">Nhập liệu bằng giọng nói</string>
<!-- Array of Voice Input modes -->
@@ -213,10 +217,15 @@
<!-- appears above image showing how to access keyboard settings -->
<string name="keyboard_settings"><font size="17"><b>\"Cài đặt bàn phím\"\n</b></font><font size="3">\n</font>\"Chạm &amp; giữ phím \"<b>\"?123\"</b>\".\"</string>
<!-- popular web domains for the locale - most popular, displayed on the keyboard -->
<string name="popular_domain_0">".com"</string>
<!-- popular web domains for the locale - item 1, displayed in the popup -->
<string name="popular_domain_1">".net"</string>
<!-- popular web domains for the locale - item 2, displayed in the popup -->
<string name="popular_domain_2">".org"</string>
<!-- popular web domains for the locale - item 3, displayed in the popup -->
<string name="popular_domain_3">".gov"</string>
<!-- popular web domains for the locale - item 4, displayed in the popup -->
<string name="popular_domain_4">".edu"</string>
<!-- Menu item for launching Input method picker -->
<string name="selectInputMethod">Chọn phương thức nhập</string>
<!-- Title for input language selection screen -->
@@ -240,4 +249,5 @@
<string name="subtype_mode_keyboard">bàn phím</string>
<string name="subtype_mode_voice">thoại</string>
<!-- Title for Latin keyboard debug settings activity / dialog -->
<string name="kp2a_nextfields"><![CDATA[>]]></string>
</resources>

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2008, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Title for Latin keyboard -->
<!-- Title for Latin keyboard settings activity / dialog -->
<!-- Title for Latin keyboard input options dialog -->
<!-- Option to provide vibrate/haptic feedback on keypress -->
<!-- Option to play back sound on keypress in soft keyboard -->
<!-- Option to pop up the character with a larger font above soft keyboard -->
<!-- Option to enable using nearby keys when correcting/predicting -->
<!-- Description for hit_correction -->
<!-- Option to enable using nearby keys when correcting/predicting in landscape-->
<!-- Description for hit_correction in landscape -->
<!-- Option to automatically correct word on hitting space -->
<!-- Description for auto_correction -->
<!-- Option to enable text prediction -->
<!-- Category title for text prediction -->
<!-- Description for text prediction -->
<!-- Dialog title for auto complete choices -->
<!-- Option to enable text prediction in landscape -->
<!-- Description for text prediction -->
<!-- Option to enable auto capitalization of sentences -->
<!-- Description for auto cap -->
<!-- Option to enable auto punctuate -->
<!-- Description for auto punctuate -->
<!-- Option to enable quick fixes -->
<!-- Description for quick fixes -->
<!-- Option to enable showing suggestions -->
<!-- Description for show suggestions -->
<!-- Option to enable auto completion -->
<!-- Description for auto completion -->
<!-- Option to show/hide the settings key -->
<!-- Array of the settings key mode values -->
<!-- Option to automatically decide to show/hide the settings key -->
<!-- Option to always show the settings key -->
<!-- Option to always hide the settings key -->
<!-- Array of the settings key modes -->
<!-- Option to enable bigram completion -->
<!-- Description for auto completion -->
<!-- Array of prediction modes -->
<!-- Don't translate -->
<!-- Don't translate -->
<!-- Don't translate -->
<!-- Indicates that a word has been added to the dictionary -->
<!-- Tip to long press on keys -->
<!-- Tip to dismiss keyboard -->
<!-- Tip to press ?123 to access numbers and symbols -->
<!-- Tip to long press on typed word to add to dictionary -->
<!-- Instruction to touch the bubble to continue -->
<!-- Instruction to touch the bubble to start typing -->
<!-- Tutorial tip 1 - The keyboard opens any time you touch a text field -->
<!-- Tutorial tip 2 - Touch and hold a key to view accents (examples) -->
<!-- Tutorial tip 3 - How to switch to number/symbol keyboard -->
<!-- Tutorial tip 4 - How to switch back to alphabet keyboard -->
<!-- Tutorial tip 5 - How to launch keyboard settings -->
<!-- Tutorial tip 6 - Done with the tutorial -->
<!-- Label for soft enter key when it performs GO action. Must be short to fit on key! -->
<!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key! -->
<!-- Label for soft enter key when it performs DONE action. Must be short to fit on key! -->
<!-- Label for soft enter key when it performs SEND action. Must be short to fit on key! -->
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
<!-- Label for "switch to numeric" key. Must be short to fit on key! -->
<!-- Label for "switch to alphabetic" key. Must be short to fit on key! -->
<!-- Label for ALT modifier key. Must be short to fit on key! -->
<!-- Voice related labels -->
<!-- Title of the warning dialog that shows when a user initiates voice input for
the first time. -->
<!-- Message that gets put at the top of the warning dialog if the user is attempting to use
voice input in a currently unsupported locale. Voice input will work for such a user,
but it will only recognize them in English. -->
<!-- Message of the warning dialog that shows when a user initiates voice input for
the first time, or turns it on in settings. -->
<!-- An additional part of the warning dialog for voice input that only shows when the user
actually initiates voice input, rather than just turning it on in settings. -->
<!-- Message to show when user clicks the swiping hint (which says
"Swipe across keyboard to speak"). Also shown when enabling settings. -->
<!-- Short message to tell the user the system is ready for them to speak. -->
<!-- Short message shown after the user finishes speaking. -->
<!-- Short message shown before the user should speak. -->
<!-- Short message shown when a generic error occurs. -->
<!-- Short message shown for a network error. -->
<!-- Short message shown for a network error where the utterance was really long,
in which case we should suggest that the user speak less. -->
<!-- Short message shown for an audio error. -->
<!-- Short message shown for an error with the voice server. -->
<!-- Short message shown when no speech is heard. -->
<!-- Short message shown when the server couldn't parse any speech. -->
<!-- Short message shown when the user initiates voice and voice
search is not installed. -->
<!-- Short hint shown in candidate view to explain voice input. -->
<!-- Short hint shown in candidate view to explain that user can speak punctuation. -->
<!-- Label on button to stop recognition. Must be short to fit on button. -->
<!-- Label on button when an error occurs -->
<!-- Preferences item for enabling speech input -->
<!-- Array of Voice Input modes -->
<!-- Don't translate -->
<!-- Don't translate -->
<!-- Don't translate -->
<!-- Array of Voice Input modes summary -->
<!-- Press the "enter" key after the user speaks. Option on settings.-->
<!-- Press the "enter" key after the user speaks. Summary of option in settings.-->
<!-- IME Tutorial screen (ROMAN) -->
<!-- appears above image showing the user to click on a TextView to show the IME -->
<!-- appears above the image showing the back button used to close the keyboard -->
<!-- appears above image showing how to use touch and hold -->
<!-- appears above image showing how to access keyboard settings -->
<!-- popular web domains for the locale - most popular, displayed on the keyboard -->
<!-- popular web domains for the locale - item 1, displayed in the popup -->
<!-- popular web domains for the locale - item 2, displayed in the popup -->
<!-- popular web domains for the locale - item 3, displayed in the popup -->
<!-- popular web domains for the locale - item 4, displayed in the popup -->
<!-- Menu item for launching Input method picker -->
<!-- Title for input language selection screen -->
<!-- Title summary for input language selection screen -->
<!-- Add to dictionary hint -->
<!-- Inform the user that a particular language has an available dictionary -->
<!-- Preferences item for enabling to send user statistics to Google -->
<!-- Description for enabling to send user statistics to Google -->
<!-- Preferences item for enabling to correct suggestions by touching words you have typed -->
<!-- The summary for the preferences item for enabling to correct suggestions by touching words you have typed -->
<!-- Description for keyboard theme switcher -->
<!-- Title for Latin keyboard debug settings activity / dialog -->
</resources>

View File

@@ -64,8 +64,6 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
@Override
public boolean onCreate() {
Log.d("KP2A_FC_P", "onCreate");
BaseFileProviderUtils.registerProviderInfo(_ID,
getAuthority());
@@ -222,12 +220,12 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
try
{
checkConnection(uri);
Log.d("KP2A_FC_P", "checking connection for " + uri + " ok.");
if (Utils.doLog()) Log.d("KP2A_FC_P", "checking connection for " + uri + " ok.");
return null;
}
catch (Exception e)
{
Log.d("KP2A_FC_P","Check connection failed with: " + e.toString());
if (Utils.doLog()) Log.d("KP2A_FC_P","Check connection failed with: " + e.toString());
MatrixCursor matrixCursor = new MatrixCursor(BaseFileProviderUtils.CONNECTION_CHECK_CURSOR_COLUMNS);
RowBuilder newRow = matrixCursor.newRow();
@@ -255,7 +253,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
}
catch (FileNotFoundException ex)
{
Log.d("KP2A_FC_P","File not found. Ignore.");
if (Utils.doLog()) Log.d("KP2A_FC_P","File not found. Ignore.");
return;
}
@@ -276,8 +274,8 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
MatrixCursor matrixCursor = null;
String lastPathSegment = uri.getLastPathSegment();
Log.d("KP2A_FC_P", "lastPathSegment:" + lastPathSegment);
if (Utils.doLog()) Log.d("KP2A_FC_P", "lastPathSegment:" + lastPathSegment);
if (BaseFile.CMD_CANCEL.equals(lastPathSegment)) {
int taskId = ProviderUtils.getIntQueryParam(uri,
@@ -361,7 +359,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
} else if (BaseFile.CMD_CHECK_CONNECTION.equals(lastPathSegment))
{
Log.d("KP2A_FC_P","Check connection...");
if (Utils.doLog()) Log.d("KP2A_FC_P","Check connection...");
return getCheckConnectionCursor(uri);
}
@@ -470,7 +468,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
String displayName = getFileEntryCached(dirName).displayName;
newRow.add(displayName);
Log.d(CLASSNAME, "Returning name " + displayName+" for " +dirName);
if (Utils.doLog()) Log.d(CLASSNAME, "Returning name " + displayName+" for " +dirName);
}
}
@@ -690,7 +688,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
}
catch (Exception e)
{
Log.d("KP2A_FC_P", "sortFiles() >> "+e);
if (Utils.doLog()) Log.d("KP2A_FC_P", "sortFiles() >> "+e);
throw e;
}
}// sortFiles()
@@ -777,14 +775,14 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
path = removeTrailingSlash(path);
if (path.indexOf("://") == -1)
{
Log.d("KP2A_FC_P", "invalid path: " + path);
if (Utils.doLog()) Log.d("KP2A_FC_P", "invalid path: " + path);
return null;
}
String pathWithoutProtocol = path.substring(path.indexOf("://") + 3);
int lastSlashPos = path.lastIndexOf("/");
if (pathWithoutProtocol.indexOf("/") == -1)
{
Log.d("KP2A_FC_P", "parent of " + path + " is null");
if (Utils.doLog()) Log.d("KP2A_FC_P", "parent of " + path + " is null");
return null;
}
else
@@ -793,7 +791,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
if (params != null) {
parent += params;
}
Log.d("KP2A_FC_P", "parent of " + path +" is " + parent);
if (Utils.doLog()) Log.d("KP2A_FC_P", "parent of " + path +" is " + parent);
return parent;
}
}

View File

@@ -56,15 +56,15 @@
<string name="afc_title_sort_by">Sortieren nach…</string>
<string name="afc_yesterday">Gestern</string>
<plurals name="afc_title_choose_directories">
<item quantity="one">Ordner wählen </item>
<item quantity="other">Verzeichnisse wählen&#8230;</item>
<item quantity="one">Ordner wählen…</item>
<item quantity="other">Verzeichnisse wählen</item>
</plurals>
<plurals name="afc_title_choose_files">
<item quantity="one">Datei wählen …</item>
<item quantity="other">Dateien wählen …</item>
</plurals>
<plurals name="afc_title_choose_files_directories">
<item quantity="one">Datei/Ordner wählen </item>
<item quantity="one">Datei/Ordner wählen…</item>
<item quantity="other">Dateien/Ordner wählen …</item>
</plurals>
</resources>

View File

@@ -55,4 +55,19 @@
<string name="afc_title_size">Dimensiune</string>
<string name="afc_title_sort_by">Sortează după…</string>
<string name="afc_yesterday">Ieri</string>
<plurals name="afc_title_choose_directories">
<item quantity="one">Alege dosarul…</item>
<item quantity="few">Alege dosarele…</item>
<item quantity="other">Alege dosarele…</item>
</plurals>
<plurals name="afc_title_choose_files">
<item quantity="one">Alege fișierul…</item>
<item quantity="few">Alege fișierele…</item>
<item quantity="other">Alege fișierele…</item>
</plurals>
<plurals name="afc_title_choose_files_directories">
<item quantity="one">Alege fișierul/dosarul…</item>
<item quantity="few">Alege fișierele/dosarele…</item>
<item quantity="other">Alege fișierele/dosarele…</item>
</plurals>
</resources>

View File

@@ -56,12 +56,12 @@
<string name="afc_title_sort_by">Sắp xếp theo…</string>
<string name="afc_yesterday">Hôm qua</string>
<plurals name="afc_title_choose_directories">
<item quantity="other">Chọn thư mục&#8230;</item>
<item quantity="other">Chọn thư mục</item>
</plurals>
<plurals name="afc_title_choose_files">
<item quantity="other">Chọn tập tin&#8230;</item>
<item quantity="other">Chọn tệp…</item>
</plurals>
<plurals name="afc_title_choose_files_directories">
<item quantity="other">Chọn tập tin / thư mục&#8230;</item>
<item quantity="other">Chọn tệp/thư mục…</item>
</plurals>
</resources>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<resources></resources>

View File

@@ -59,7 +59,7 @@ namespace keepass2android
}
catch (ActivityNotFoundException)
{
Toast.MakeText(Context, Resource.String.no_url_handler, ToastLength.Long).Show();
App.Kp2a.ShowMessage(Context, Resource.String.no_url_handler, MessageSeverity.Error);
}
};
@@ -71,7 +71,7 @@ namespace keepass2android
}
catch (ActivityNotFoundException)
{
Toast.MakeText(Context, Resource.String.no_url_handler, ToastLength.Long).Show();
App.Kp2a.ShowMessage(Context, Resource.String.no_url_handler, MessageSeverity.Error);
}
};
FindViewById(Resource.Id.translate).Click += delegate
@@ -82,7 +82,7 @@ namespace keepass2android
}
catch (ActivityNotFoundException)
{
Toast.MakeText(Context, Resource.String.no_url_handler, ToastLength.Long).Show();
App.Kp2a.ShowMessage(Context, Resource.String.no_url_handler, MessageSeverity.Error);
}
}; FindViewById(Resource.Id.donate).Click += delegate
{

View File

@@ -14,9 +14,11 @@ using Android.Runtime;
using Android.Text;
using Android.Text.Method;
using Android.Text.Util;
using Android.Util;
using Android.Views;
using Android.Webkit;
using Android.Widget;
using AndroidX.Core.Content;
using Google.Android.Material.Dialog;
using keepass2android;
@@ -29,7 +31,16 @@ namespace keepass2android
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ctx);
builder.SetTitle(ctx.GetString(Resource.String.ChangeLog_title));
List<string> changeLog = new List<string>{
BuildChangelogString(ctx, new List<int>{Resource.Array.ChangeLog_1_11,Resource.Array.ChangeLog_1_11_net}, "1.11"),
BuildChangelogString(ctx, new List<int>{Resource.Array.ChangeLog_1_12
#if !NoNet
,Resource.Array.ChangeLog_1_12_net
#endif
}, "1.12"),
BuildChangelogString(ctx, new List<int>{Resource.Array.ChangeLog_1_11
#if !NoNet
,Resource.Array.ChangeLog_1_11_net
#endif
}, "1.11"),
BuildChangelogString(ctx, Resource.Array.ChangeLog_1_10, "1.10"),
BuildChangelogString(ctx, Resource.Array.ChangeLog_1_09e, "1.09e"),
BuildChangelogString(ctx, Resource.Array.ChangeLog_1_09d, "1.09d"),
@@ -99,32 +110,28 @@ namespace keepass2android
warning = ctx.GetString(Resource.String.PreviewWarning);
}
builder.SetPositiveButton(Android.Resource.String.Ok, (dlgSender, dlgEvt) => {((AlertDialog)dlgSender).Dismiss(); });
builder.SetPositiveButton(Android.Resource.String.Ok, (dlgSender, dlgEvt) => {((AndroidX.AppCompat.App.AlertDialog)dlgSender).Dismiss(); });
builder.SetCancelable(false);
WebView wv = new WebView(ctx);
wv.SetBackgroundColor(Color.White);
wv.LoadDataWithBaseURL(null, GetLog(changeLog, warning, ctx), "text/html", "UTF-8", null);
//builder.SetMessage("");
builder.SetView(wv);
Dialog dialog = builder.Create();
dialog.DismissEvent += (sender, e) =>
dialog.DismissEvent += (sender, e) =>
{
onDismiss();
};
dialog.Show();
/*TextView message = (TextView)dialog.FindViewById(Android.Resource.Id.Message);
message.TextFormatted = Html.FromHtml(ConcatChangeLog(ctx, changeLog.ToArray()));
message.AutoLinkMask=MatchOptions.WebUrls;*/
wv.SetBackgroundColor(Color.Transparent);
wv.LoadDataWithBaseURL(null, GetLog(changeLog, warning, dialog.Context), "text/html", "UTF-8", null);
dialog.Show();
}
private static string BuildChangelogString(Context ctx, int changeLogResId, string version)
private static string BuildChangelogString(Context ctx, int changeLogResId, string version)
{
return BuildChangelogString(ctx, new List<int>() { changeLogResId }, version);
@@ -150,32 +157,44 @@ namespace keepass2android
}
private const string HtmlStart = @"<html>
private const string HtmlEnd = @"</body>
</html>";
private static string GetLog(List<string> changeLog, string warning, Context ctx)
{
string secondaryColor = "31628D";
string onSurfaceColor = "171D1E";
if (((int)ctx.Resources.Configuration.UiMode & (int)UiMode.NightMask) == (int)UiMode.NightYes)
{
secondaryColor = "99CBFF";
onSurfaceColor = "E1E4D6";
}
string HtmlStart = @"<html>
<head>
<style type='text/css'>
a { color:#000000 }
a { color:#"+ onSurfaceColor + @" }
div.title {
color:287AA9;
color:"+ secondaryColor+@";
font-size:1.2em;
font-weight:bold;
margin-top:1em;
margin-bottom:0.5em;
text-align:center }
div.subtitle {
color:287AA9;
color:"+ secondaryColor+@";
font-size:0.8em;
margin-bottom:1em;
text-align:center }
div.freetext { color:#000000 }
div.list { color:#000000 }
div.freetext { color:#"+ onSurfaceColor + @" }
div.list { color:#"+ onSurfaceColor + @" }
</style>
</head>
<body>";
private const string HtmlEnd = @"</body>
</html>";
private static string GetLog(List<string> changeLog, string warning, Context ctx)
{
StringBuilder sb = new StringBuilder(HtmlStart);
StringBuilder sb = new StringBuilder(HtmlStart);
if (!string.IsNullOrEmpty(warning))
{
sb.Append(warning);

View File

@@ -183,7 +183,7 @@ namespace keepass2android
// Verify that a password or keyfile is set
if (password.Length == 0 && !keyfileCheckbox.Checked)
{
Toast.MakeText(this, Resource.String.error_nopass, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.error_nopass, MessageSeverity.Error);
return;
}
@@ -207,7 +207,7 @@ namespace keepass2android
}
catch (Exception)
{
Toast.MakeText(this, Resource.String.error_adding_keyfile, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.error_adding_keyfile, MessageSeverity.Error);
return;
}
}
@@ -235,7 +235,7 @@ namespace keepass2android
if (! pass.Equals(confpass))
{
// Passwords do not match
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.error_pass_match, MessageSeverity.Error);
return false;
}
return true;

View File

@@ -28,7 +28,7 @@ namespace keepass2android
}
catch (Exception e)
{
Finish(false, e.Message);
Finish(false, Util.GetErrorMessage(e));
}
}

View File

@@ -41,7 +41,7 @@ namespace keepass2android
string requestedUrl = Intent.GetStringExtra(ChooseForAutofillActivityBase.ExtraQueryString);
if (requestedUrl == null)
{
Toast.MakeText(this, "Cannot execute query for null.", ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, "Cannot execute query for null.", MessageSeverity.Error);
RestartApp();
return;
}

View File

@@ -78,7 +78,7 @@ namespace keepass2android
var task = new EntryActivity.WriteBinaryTask(_activity, App.Kp2a, new ActionOnFinish(_activity, (success, message, activity) =>
{
if (!success)
Toast.MakeText(activity, message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(activity, message, MessageSeverity.Error);
}
), ((EntryActivity)_activity).Entry.Binaries.Get(_binaryToSave), ioc);
ProgressTask pt = new ProgressTask(App.Kp2a, _activity, task);
@@ -107,8 +107,8 @@ namespace keepass2android
public const int requestCodeBinaryFilename = 42376;
public const int requestCodeSelFileStorageForWriteAttachment = 42377;
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
public static void Launch(Activity act, PwEntry pw, int pos, AppTask appTask, ActivityFlags? flags = null, int historyIndex=-1)
{
@@ -767,9 +767,9 @@ namespace keepass2android
if (parent == null || (parent.Exists() && !parent.IsDirectory))
{
Toast.MakeText(this,
App.Kp2a.ShowMessage(this,
Resource.String.error_invalid_path,
ToastLength.Long).Show();
MessageSeverity.Error);
return null;
}
@@ -778,9 +778,9 @@ namespace keepass2android
// Create parent directory
if (!parent.Mkdirs())
{
Toast.MakeText(this,
App.Kp2a.ShowMessage(this,
Resource.String.error_could_not_create_parent,
ToastLength.Long).Show();
MessageSeverity.Error);
return null;
}
@@ -794,18 +794,18 @@ namespace keepass2android
}
catch (Exception exWrite)
{
Toast.MakeText(this,
App.Kp2a.ShowMessage(this,
GetString(Resource.String.SaveAttachment_Failed, new Java.Lang.Object[] {filename})
+ exWrite.Message, ToastLength.Long).Show();
+ Util.GetErrorMessage(exWrite), MessageSeverity.Error);
return null;
}
finally
{
MemUtil.ZeroByteArray(pbData);
}
Toast.MakeText(this,
App.Kp2a.ShowMessage(this,
GetString(Resource.String.SaveAttachment_doneMessage, new Java.Lang.Object[] {filename}),
ToastLength.Short).Show();
MessageSeverity.Info);
return Uri.Parse("content://" + AttachmentContentProvider.Authority + "/"
+ filename);
}
@@ -838,7 +838,7 @@ namespace keepass2android
catch (ActivityNotFoundException)
{
//ignore
Toast.MakeText(this, "Couldn't open file", ToastLength.Short).Show();
App.Kp2a.ShowMessage(this, "Couldn't open file", MessageSeverity.Error);
}
}
@@ -1305,7 +1305,7 @@ namespace keepass2android
}
catch (Exception ex)
{
Finish(false, ex.Message);
Finish(false, Util.GetErrorMessage(ex));
}
@@ -1558,7 +1558,7 @@ namespace keepass2android
}
catch (ActivityNotFoundException)
{
Toast.MakeText(this, Resource.String.no_url_handler, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.no_url_handler, MessageSeverity.Error);
}
return true;
}

View File

@@ -37,6 +37,7 @@ using System.Net;
using System.Text;
using Android.Content.Res;
using Android.Database;
using Android.Gms.Common;
using Android.Gms.Tasks;
using Android.Graphics;
using Android.Graphics.Drawables;
@@ -63,10 +64,10 @@ namespace keepass2android
{
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Theme = "@style/Kp2aTheme_ActionBar")]
public class EntryEditActivity : LockCloseActivity {
public const String KeyEntry = "entry";
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
public const String KeyEntry = "entry";
public const String KeyParent = "parent";
public const String KeyTemplateUuid = "KeyTemplateUuid";
@@ -714,7 +715,7 @@ namespace keepass2android
}
catch(Exception exAttach)
{
Toast.MakeText(this, GetString(Resource.String.AttachFailed)+" "+exAttach.Message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, GetString(Resource.String.AttachFailed)+" "+ Util.GetErrorMessage(exAttach), MessageSeverity.Error);
}
State.EntryModified = true;
PopulateBinaries();
@@ -832,7 +833,7 @@ namespace keepass2android
string s = Util.GetFilenameFromInternalFileChooser(data, this);
if (s == null)
{
Toast.MakeText(this, "No URI retrieved.", ToastLength.Short).Show();
App.Kp2a.ShowMessage(this, "No URI retrieved.", MessageSeverity.Error);
return;
}
uri = Uri.Parse(s);
@@ -1138,7 +1139,7 @@ namespace keepass2android
}
else
{
Toast.MakeText(this, "did not find target field", ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, "did not find target field", MessageSeverity.Error);
}
@@ -1155,6 +1156,13 @@ namespace keepass2android
dlgView.FindViewById<Button>(Resource.Id.totp_scan).Click += async (object o, EventArgs args) =>
{
if (GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this) != ConnectionResult.Success)
{
App.Kp2a.ShowMessage(this, Resource.String.qr_scanning_error_no_google_play_services,
MessageSeverity.Error);
return;
}
GmsBarcodeScannerOptions options = new GmsBarcodeScannerOptions.Builder()
.SetBarcodeFormats(Barcode.FormatQrCode)
.Build();
@@ -1171,12 +1179,12 @@ namespace keepass2android
}
else
{
Toast.MakeText(this, "Scanned code should contain an otpauth:// text.", ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, "Scanned code should contain an otpauth:// text.", MessageSeverity.Warning);
}
}))
.AddOnFailureListener(new FailureListener((e) =>
{
Console.WriteLine($"Scan failed: {e.Message}");
Console.WriteLine($"Scan failed: {Util.GetErrorMessage(e)}");
}));
@@ -1496,7 +1504,7 @@ namespace keepass2android
// Require title
String title = Util.GetEditText(this, Resource.Id.entry_title);
if ( title.Length == 0 ) {
Toast.MakeText(this, Resource.String.error_title_required, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.error_title_required, MessageSeverity.Error);
return false;
}
@@ -1506,7 +1514,7 @@ namespace keepass2android
DateTime newExpiry = new DateTime();
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.GetEditText(this,Resource.Id.entry_expires), out newExpiry)))
{
Toast.MakeText(this, Resource.String.error_invalid_expiry_date, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.error_invalid_expiry_date, MessageSeverity.Error);
return false;
}
State.Entry.ExpiryTime = newExpiry.ToUniversalTime();
@@ -1520,13 +1528,13 @@ namespace keepass2android
string key = keyView.Text;
if (String.IsNullOrEmpty(key)) {
Toast.MakeText(this, Resource.String.error_string_key, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.error_string_key, MessageSeverity.Error);
return false;
}
if (allKeys.Contains(key))
{
Toast.MakeText(this, GetString(Resource.String.error_string_duplicate_key, new Object[]{key}), ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, GetString(Resource.String.error_string_duplicate_key, new Object[]{key}), MessageSeverity.Error);
return false;
}

View File

@@ -29,9 +29,9 @@ namespace keepass2android
var exportDb = new ExportDatabaseActivity.ExportDb(_activity, App.Kp2a, new ActionOnFinish(_activity, (success, message, activity) =>
{
if (!success)
Toast.MakeText(activity, message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(activity, message, MessageSeverity.Error);
else
Toast.MakeText(activity, _activity.GetString(Resource.String.export_database_successful), ToastLength.Long).Show();
App.Kp2a.ShowMessage(activity, _activity.GetString(Resource.String.export_database_successful), MessageSeverity.Info);
activity.Finish();
}
), _ffp, ioc);
@@ -140,7 +140,7 @@ namespace keepass2android
}
catch (Exception ex)
{
Finish(false, ex.Message);
Finish(false, Util.GetErrorMessage(ex));
}

View File

@@ -107,7 +107,7 @@ namespace keepass2android
{
if (!success)
{
Toast.MakeText(activity, messageOrFilename, ToastLength.Long).Show();
App.Kp2a.ShowMessage(activity, messageOrFilename, MessageSeverity.Error);
return;
}
SaveFile(new IOConnectionInfo { Path = FileSelectHelper.ConvertFilenameToIocPath(messageOrFilename) });

View File

@@ -115,6 +115,7 @@ namespace keepass2android
string keyContent = keyContentTxt.Text;
string toastMsg = null;
MessageSeverity severity = MessageSeverity.Info;
if (!string.IsNullOrEmpty(keyName) && !string.IsNullOrEmpty(keyContent))
{
try
@@ -127,8 +128,10 @@ namespace keepass2android
catch (Exception e)
{
toastMsg = ctx.GetString(Resource.String.private_key_save_failed,
new Java.Lang.Object[] { e.Message });
}
new Java.Lang.Object[] { Util.GetErrorMessage(e)});
severity = MessageSeverity.Error;
}
}
else
{
@@ -136,7 +139,7 @@ namespace keepass2android
}
if (toastMsg!= null) {
Toast.MakeText(_activity, toastMsg, ToastLength.Long).Show();
App.Kp2a.ShowMessage(_activity, toastMsg, severity);
}
UpdatePrivateKeyNames(keyNamesAdapter, fileStorage, ctx);
@@ -153,7 +156,7 @@ namespace keepass2android
int msgId = deleted ? Resource.String.private_key_delete : Resource.String.private_key_delete_failed;
string msg = ctx.GetString(msgId, new Java.Lang.Object[] { keyName });
Toast.MakeText(_activity, msg, ToastLength.Long).Show();
App.Kp2a.ShowMessage(_activity, msg, deleted ? MessageSeverity.Info :MessageSeverity.Error);
UpdatePrivateKeyNames(keyNamesAdapter, fileStorage, ctx);
keySpinner.SetSelection(SftpKeySpinnerCreateNewIdx);
@@ -581,9 +584,9 @@ namespace keepass2android
// Make sure file name exists
if (filename.Length == 0)
{
Toast.MakeText(_activity,
App.Kp2a.ShowMessage(_activity,
Resource.String.error_filename_required,
ToastLength.Long).Show();
MessageSeverity.Error);
return false;
}
@@ -604,9 +607,9 @@ namespace keepass2android
}
catch (NoFileStorageFoundException)
{
Toast.MakeText(_activity,
App.Kp2a.ShowMessage(_activity,
"Unexpected scheme in "+filename,
ToastLength.Long).Show();
MessageSeverity.Error);
return false;
}
@@ -620,9 +623,9 @@ namespace keepass2android
if (parent == null || (parent.Exists() && !parent.IsDirectory))
{
Toast.MakeText(_activity,
App.Kp2a.ShowMessage(_activity,
Resource.String.error_invalid_path,
ToastLength.Long).Show();
MessageSeverity.Error);
return false;
}
@@ -631,9 +634,9 @@ namespace keepass2android
// Create parent dircetory
if (!parent.Mkdirs())
{
Toast.MakeText(_activity,
App.Kp2a.ShowMessage(_activity,
Resource.String.error_could_not_create_parent,
ToastLength.Long).Show();
MessageSeverity.Error);
return false;
}
@@ -643,11 +646,11 @@ namespace keepass2android
}
catch (Java.IO.IOException ex)
{
Toast.MakeText(
App.Kp2a.ShowMessage(
_activity,
_activity.GetText(Resource.String.error_file_not_create) + " "
+ ex.LocalizedMessage,
ToastLength.Long).Show();
MessageSeverity.Error);
return false;
}
@@ -700,7 +703,7 @@ namespace keepass2android
_activity.StartActivityForResult(i, _requestCode);
#else
Toast.MakeText(LocaleManager.LocalizedAppContext, "File chooser is excluded!", ToastLength.Long).Show();
App.Kp2a.ShowMessage(LocaleManager.LocalizedAppContext, "File chooser is excluded!", MessageSeverity.Error);
#endif
return true;
}
@@ -782,7 +785,7 @@ namespace keepass2android
{
if (!success)
{
Toast.MakeText(newActivity, messageOrFilename, ToastLength.Long).Show();
App.Kp2a.ShowMessage(newActivity, messageOrFilename, MessageSeverity.Error);
return;
}
var ioc = new IOConnectionInfo { Path = ConvertFilenameToIocPath(messageOrFilename) };

View File

@@ -251,7 +251,7 @@ namespace keepass2android
catch (Exception e)
{
CheckCurrentRadioButton();
Toast.MakeText(this, e.ToString(), ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, e.ToString(), MessageSeverity.Error);
FindViewById(Resource.Id.radio_buttons).Visibility = ViewStates.Visible;
FindViewById(Resource.Id.fingerprint_auth_container).Visibility = ViewStates.Gone;
}

View File

@@ -543,7 +543,7 @@ namespace keepass2android
}
catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Util.GetErrorMessage(e), MessageSeverity.Error);
}
return password;

View File

@@ -56,6 +56,8 @@ namespace keepass2android
public const int RequestCodeActivateRealSearch = 12366;
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
static readonly Dictionary<int /*resource id*/, int /*prio*/> bottomBarElementsPriority = new Dictionary<int, int>()
{
{ Resource.Id.cancel_insert_element, 20 },
@@ -927,7 +929,7 @@ namespace keepass2android
{
((GroupBaseActivity)activity)?.StopMovingElements();
if (!String.IsNullOrEmpty(message))
Toast.MakeText(activity, message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(activity, message, MessageSeverity.Error);
}));
var progressTask = new ProgressTask(App.Kp2a, this, moveElement);
progressTask.Run();
@@ -1328,7 +1330,7 @@ namespace keepass2android
{
Handler.Post(() =>
{
Toast.MakeText(ActiveActivity ?? LocaleManager.LocalizedAppContext, "Unrecoverable error: " + Message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(ActiveActivity ?? LocaleManager.LocalizedAppContext, "Unrecoverable error: " + Message, MessageSeverity.Error);
});
App.Kp2a.Lock(false);

View File

@@ -111,9 +111,10 @@ namespace keepass2android
SetResult (Result.Ok, intent);
Finish ();
} else {
Toast.MakeText (this, Resource.String.error_no_name, ToastLength.Long).Show ();
}
} else
{
App.Kp2a.ShowMessage(this, Resource.String.error_no_name, MessageSeverity.Error);
}
};
if (Intent.HasExtra(KeyGroupUuid))

View File

@@ -185,48 +185,56 @@ namespace keepass2android
public override View GetView(int position, View convertView, ViewGroup parent)
{
View currView;
if(convertView == null)
{
LayoutInflater li = (LayoutInflater) _act.GetSystemService(LayoutInflaterService);
currView = li.Inflate(Resource.Layout.icon, null);
}
else
{
currView = convertView;
}
TextView tv = (TextView) currView.FindViewById(Resource.Id.icon_text);
ImageView iv = (ImageView) currView.FindViewById(Resource.Id.icon_image);
if (position < (int)PwIcon.Count)
{
tv.Text = "" + position;
var drawable = App.Kp2a.CurrentDb .DrawableFactory.GetIconDrawable(_act, App.Kp2a.CurrentDb.KpDatabase, (KeePassLib.PwIcon) position, null, false);
drawable = new BitmapDrawable(Util.DrawableToBitmap(drawable));
iv.SetImageDrawable(drawable);
//App.Kp2a.GetDb().DrawableFactory.AssignDrawableTo(iv, _act, App.Kp2a.GetDb().KpDatabase, (KeePassLib.PwIcon) position, null, false);
try
{
View currView;
if (convertView == null)
{
LayoutInflater li = (LayoutInflater)_act.GetSystemService(LayoutInflaterService);
currView = li.Inflate(Resource.Layout.icon, null);
}
else
{
currView = convertView;
}
TextView tv = (TextView)currView.FindViewById(Resource.Id.icon_text);
ImageView iv = (ImageView)currView.FindViewById(Resource.Id.icon_image);
if (
PreferenceManager.GetDefaultSharedPreferences(currView.Context)
.GetString("IconSetKey", currView.Context.PackageName) == currView.Context.PackageName)
{
Android.Graphics.PorterDuff.Mode mMode = Android.Graphics.PorterDuff.Mode.SrcAtop;
Color color = new Color(189, 189, 189);
iv.SetColorFilter(color, mMode);
}
}
else
{
int pos = position - (int)PwIcon.Count;
var icon = _db.CustomIcons[pos];
tv.Text = pos.ToString();
iv.SetColorFilter(null);
iv.SetImageBitmap(icon.Image);
}
if (position < (int)PwIcon.Count)
{
tv.Text = "" + position;
var drawable = App.Kp2a.CurrentDb.DrawableFactory.GetIconDrawable(_act, App.Kp2a.CurrentDb.KpDatabase, (KeePassLib.PwIcon)position, null, false);
drawable = new BitmapDrawable(Util.DrawableToBitmap(drawable));
iv.SetImageDrawable(drawable);
//App.Kp2a.GetDb().DrawableFactory.AssignDrawableTo(iv, _act, App.Kp2a.GetDb().KpDatabase, (KeePassLib.PwIcon) position, null, false);
return currView;
if (PreferenceManager.GetDefaultSharedPreferences(currView.Context)
.GetString("IconSetKey", currView.Context.PackageName) == currView.Context.PackageName)
{
Android.Graphics.PorterDuff.Mode mMode = Android.Graphics.PorterDuff.Mode.SrcAtop;
Color color = new Color(189, 189, 189);
iv.SetColorFilter(color, mMode);
}
}
else
{
int pos = position - (int)PwIcon.Count;
var icon = _db.CustomIcons[pos];
tv.Text = pos.ToString();
iv.SetColorFilter(null);
iv.SetImageBitmap(icon.Image);
}
return currView;
}
catch (System.Exception e)
{
Kp2aLog.LogUnexpectedError(e);
throw;
}
}
public bool IsCustomIcon(int position)

View File

@@ -316,7 +316,7 @@ namespace keepass2android
try { ck.AddUserKey(new KcpKeyFile(strAbs)); }
catch (InvalidOperationException)
{
Toast.MakeText(LocaleManager.LocalizedAppContext,Resource.String.error_adding_keyfile,ToastLength.Long).Show();
App.Kp2a.ShowMessage(LocaleManager.LocalizedAppContext,Resource.String.error_adding_keyfile, MessageSeverity.Error);
return false;
}
catch (Exception) { throw; }

View File

@@ -146,7 +146,16 @@ namespace KeeChallenge
{
using (CryptoStream csDecrypt = (CryptoStream)aes.DecryptStream(msDecrypt, key, inf.IV))
{
csDecrypt.Read(secret, 0, secret.Length);
//read the secret from the stream
int totalBytesRead = 0;
int bytesRead = csDecrypt.Read(secret, totalBytesRead, secret.Length - totalBytesRead);
while (bytesRead > 0 && totalBytesRead < secret.Length)
{
totalBytesRead += bytesRead;
bytesRead = csDecrypt.Read(secret, totalBytesRead, secret.Length - totalBytesRead);
}
csDecrypt.Close();
}
msDecrypt.Close();

View File

@@ -21,8 +21,10 @@ using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Google.Android.Material.Dialog;
using keepass2android;
using keepass2android.Utils;
namespace keepass2android
{
@@ -76,19 +78,34 @@ namespace keepass2android
base.OnPause();
TimeoutHelper.Pause(this);
}
App.Kp2a.MessagePresenter = new NonePresenter();
}
protected override void OnDestroy()
{
base.OnDestroy();
GC.Collect();
}
protected override void OnResume() {
base.OnResume();
TimeoutHelper.Resume(this);
}
protected override void OnResume()
{
base.OnResume();
TimeoutHelper.Resume(this);
var snackbarAnchorView = SnackbarAnchorView;
if (snackbarAnchorView != null)
{
App.Kp2a.MessagePresenter = new ChainedSnackbarPresenter(snackbarAnchorView);
}
else
{
App.Kp2a.MessagePresenter = new ToastPresenter();
}
}
protected virtual View? SnackbarAnchorView => null;
public const int RequestCodeChallengeYubikey = 793;

View File

@@ -47,8 +47,8 @@
<permission android:description="@string/permission_desc2" android:icon="@drawable/ic_notify_locked" android:label="KP2A entry search" android:name="keepass2android.keepass2android_debug.permission.KP2aInternalSearch" android:protectionLevel="signature" />
<permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android_debug.permission.Kp2aChooseAutofill" android:protectionLevel="signature" />
<application
android:icon="@mipmap/ic_launcher_online"
android:roundIcon="@mipmap/ic_launcher_online_round"
android:icon="@mipmap/ic_launcher_debug"
android:roundIcon="@mipmap/ic_launcher_debug_round"
android:networkSecurityConfig="@xml/network_security_config"
>
<meta-data
@@ -243,6 +243,15 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="otpauth"/>
<data android:host="totp"/>
<data android:host="hotp"/>
</intent-filter>
</activity>
<uses-library android:required="false" android:name="com.sec.android.app.multiwindow" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="200"
android:versionName="1.11-r0"
android:versionCode="205"
android:versionName="1.12-r4"
package="keepass2android.keepass2android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
@@ -255,7 +255,14 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
x
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="otpauth"/>
<data android:host="totp"/>
<data android:host="hotp"/>
</intent-filter>
</activity>
<uses-library android:required="false" android:name="com.sec.android.app.multiwindow" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />

View File

@@ -236,6 +236,14 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="otpauth"/>
<data android:host="totp"/>
<data android:host="hotp"/>
</intent-filter>
</activity>
<uses-library android:required="false" android:name="com.sec.android.app.multiwindow" />
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />

View File

@@ -145,7 +145,7 @@ namespace keepass2android
catch (Exception e)
{
Kp2aLog.LogUnexpectedError(e);
Toast.MakeText(this, "No Yubikey OTP found!", ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, "No Yubikey OTP found!", MessageSeverity.Error);
Finish();
return;
}

View File

@@ -48,11 +48,6 @@ namespace keepass2android
Finish();
};
var toolbar = FindViewById<AndroidX.AppCompat.Widget.Toolbar>(Resource.Id.mytoolbar);
SetSupportActionBar(toolbar);
SupportActionBar.Title = AppNames.AppName;
}
protected override void OnResume()

View File

@@ -0,0 +1,24 @@
using Android.Content.PM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace keepass2android
{
[Activity(Label = AppNames.AppName,
MainLauncher = false,
Theme = "@style/Kp2aTheme_BlueNoActionBar",
Exported = true)]
///For autofill, we sometimes need to pass an intent to an inline presentation which never gets fired. We use this as a dummy activity.
public class NullActivity: Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
Kp2aLog.Log("NullActivity.OnCreate - this is unexpected.");
base.OnCreate(savedInstanceState);
Finish();
}
}
}

View File

@@ -66,6 +66,7 @@ using Exception = System.Exception;
using String = System.String;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
using AndroidX.Core.Content;
using Google.Android.Material.Snackbar;
namespace keepass2android
{
@@ -309,7 +310,7 @@ namespace keepass2android
catch (Exception e)
{
Kp2aLog.Log(e.ToString());
Toast.MakeText(this, "Error: " + e.Message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, "Error: " + Util.GetErrorMessage(e), MessageSeverity.Error);
return;
}
@@ -328,8 +329,7 @@ namespace keepass2android
ChallengeInfo temp = _challengeProv.Encrypt(_challengeSecret);
if (!temp.Save(_otpAuxIoc))
{
Toast.MakeText(this, Resource.String.ErrorUpdatingChalAuxFile, ToastLength.Long)
.Show();
App.Kp2a.ShowMessage(this, Resource.String.ErrorUpdatingChalAuxFile, MessageSeverity.Error);
return false;
}
@@ -348,7 +348,7 @@ namespace keepass2android
}
else
{
Toast.MakeText(this, Resource.String.bad_resp, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.bad_resp, MessageSeverity.Error);
}
}
}
@@ -458,7 +458,7 @@ namespace keepass2android
}
else
{
Toast.MakeText(Activity,GetErrorMessage(), ToastLength.Long).Show();
App.Kp2a.ShowMessage(Activity,GetErrorMessage(), MessageSeverity.Error);
}
return;
@@ -957,7 +957,7 @@ namespace keepass2android
{
btn.SetImageResource(Resource.Drawable.baseline_fingerprint_24);
}, 1300);
Toast.MakeText(this, message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, message, MessageSeverity.Error);
}
public void OnBiometricAttemptFailed(string message)
@@ -996,8 +996,12 @@ namespace keepass2android
btn.PostDelayed(() =>
{
//fire
OnOk(true);
//fire if everything else is ready
if (FindViewById(Resource.Id.pass_ok).Enabled)
{
OnOk(true);
}
FindViewById<EditText>(Resource.Id.password_edit).Enabled = true;
}, 500);
@@ -1036,7 +1040,7 @@ namespace keepass2android
if (_appnameclickCount == 6)
{
Kp2aLog.LogUnexpectedError(new Exception("some blabla"));
Toast.MakeText(this, "Once again and the app will crash.", ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, "Once again and the app will crash.", MessageSeverity.Warning);
}
if (_appnameclickCount == 7)
@@ -1123,7 +1127,7 @@ namespace keepass2android
//For security reasons: discard the OTP (otherwise the user might not select a database now and forget
//about the OTP, but it would still be stored in the Intents and later be passed to PasswordActivity again.
Toast.MakeText(this, GetString(Resource.String.otp_discarded_because_no_db), ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, GetString(Resource.String.otp_discarded_because_no_db), MessageSeverity.Warning);
GoToFileSelectActivity();
return false;
}
@@ -1400,7 +1404,7 @@ namespace keepass2android
string errorMessage;
if (!CreateCompositeKey(out compositeKey, out errorMessage)) return (() =>
{
Toast.MakeText(this, errorMessage, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, errorMessage, MessageSeverity.Warning);
_performingLoad = false;
});
return () => { PerformLoadDatabaseWithCompositeKey(compositeKey); };
@@ -1481,7 +1485,7 @@ namespace keepass2android
catch (Exception e)
{
Kp2aLog.LogUnexpectedError(e);
errorMessage = e.Message;
errorMessage = Util.GetErrorMessage(e);
return false;
}
}
@@ -1668,7 +1672,7 @@ namespace keepass2android
//did we find a field?
if (!foundEmptyField)
{
Toast.MakeText(this, GetString(Resource.String.otp_discarded_no_space), ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, GetString(Resource.String.otp_discarded_no_space), MessageSeverity.Error);
}
}
@@ -1729,80 +1733,128 @@ namespace keepass2android
UsedFingerprintUnlock = false;
}
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
protected override void OnResume()
{
base.OnResume();
_activityDesign.ReapplyTheme();
{
base.OnResume();
_activityDesign.ReapplyTheme();
Kp2aLog.Log("starting: " + _starting + ", Finishing: " + IsFinishing + ", _performingLoad: " + _performingLoad);
Kp2aLog.Log("starting: " + _starting + ", Finishing: " + IsFinishing + ", _performingLoad: " +
_performingLoad);
CheckBox cbOfflineMode = (CheckBox)FindViewById(Resource.Id.work_offline);
App.Kp2a.OfflineMode = cbOfflineMode.Checked = App.Kp2a.OfflineModePreference; //this won't overwrite new user settings because every change is directly saved in settings
LinearLayout offlineModeContainer = FindViewById<LinearLayout>(Resource.Id.work_offline_container);
var cachingFileStorage = App.Kp2a.GetFileStorage(_ioConnection) as CachingFileStorage;
if ((cachingFileStorage != null) && cachingFileStorage.IsCached(_ioConnection))
{
offlineModeContainer.Visibility = ViewStates.Visible;
}
else
{
offlineModeContainer.Visibility = ViewStates.Gone;
App.Kp2a.OfflineMode = false;
}
CheckBox cbOfflineMode = (CheckBox)FindViewById(Resource.Id.work_offline);
App.Kp2a.OfflineMode =
cbOfflineMode.Checked =
App.Kp2a
.OfflineModePreference; //this won't overwrite new user settings because every change is directly saved in settings
LinearLayout offlineModeContainer = FindViewById<LinearLayout>(Resource.Id.work_offline_container);
var cachingFileStorage = App.Kp2a.GetFileStorage(_ioConnection) as CachingFileStorage;
if ((cachingFileStorage != null) && cachingFileStorage.IsCached(_ioConnection))
{
offlineModeContainer.Visibility = ViewStates.Visible;
}
else
{
offlineModeContainer.Visibility = ViewStates.Gone;
App.Kp2a.OfflineMode = false;
}
View killButton = FindViewById(Resource.Id.kill_app);
if (PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean(GetString(Resource.String.show_kill_app_key), false))
{
killButton.Click += (sender, args) =>
{
_killOnDestroy = true;
View killButton = FindViewById(Resource.Id.kill_app);
if (PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean(GetString(Resource.String.show_kill_app_key), false))
{
killButton.Click += (sender, args) =>
{
_killOnDestroy = true;
SetResult(Result.Canceled);
Finish();
Finish();
};
killButton.Visibility = ViewStates.Visible;
};
killButton.Visibility = ViewStates.Visible;
}
else
{
killButton.Visibility = ViewStates.Gone;
}
}
else
{
killButton.Visibility = ViewStates.Gone;
}
TryGetOtpFromClipboard();
TryGetOtpFromClipboard();
if (!_keepPasswordInOnResume)
{
if (
_lastOnPauseTime < DateTime.Now - TimeSpan.FromSeconds(5) //only clear when user left the app for more than 5 seconds (allows to use Yubiclip, also allows to switch shortly to another app)
&&
PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean(GetString(Resource.String.ClearPasswordOnLeave_key), true))
{
ClearEnteredPassword();
}
if (!_keepPasswordInOnResume)
{
if (
_lastOnPauseTime <
DateTime.Now -
TimeSpan.FromSeconds(
5) //only clear when user left the app for more than 5 seconds (allows to use Yubiclip, also allows to switch shortly to another app)
&&
PreferenceManager.GetDefaultSharedPreferences(this)
.GetBoolean(GetString(Resource.String.ClearPasswordOnLeave_key), true))
{
ClearEnteredPassword();
}
}
}
_keepPasswordInOnResume = false;
_keepPasswordInOnResume = false;
MakePasswordMaskedOrVisible();
MakePasswordMaskedOrVisible();
UpdateOkButtonState();
UpdateOkButtonState();
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
{
FindViewById(Resource.Id.otpInitView).Visibility = _challengeSecret == null ? ViewStates.Visible : ViewStates.Gone;
}
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
{
FindViewById(Resource.Id.otpInitView).Visibility =
_challengeSecret == null ? ViewStates.Visible : ViewStates.Gone;
}
/*
Snackbar snackbar = Snackbar
.Make(FindViewById(Resource.Id.main_content),
"snack snack snack snack snack snack snack snack snack snack snack snack snack snack snacksnack snack snacksnack snack snacksnack snack snack snack snack snack snack snack snack snack snack snack snack snack snack snacksnack snack snacksnack snack snacksnack snack snack snack snack snacksnack snack snack ",
Snackbar.LengthLong);
snackbar.SetTextMaxLines(5);
snackbar.SetBackgroundTint(GetColor(Resource.Color.md_theme_secondaryContainer));
snackbar.SetTextColor(GetColor(Resource.Color.md_theme_onSecondaryContainer));
snackbar.SetAction("dismiss",
view => snackbar.SetBackgroundTint(GetColor(Resource.Color.md_theme_surfaceContainer)));
//use !IsFinishing to make sure we're not starting another activity when we're already finishing (e.g. due to TaskComplete in OnActivityResult)
//use !performingLoad to make sure we're not already loading the database (after ActivityResult from File-Prepare-Activity; this would cause _loadDbFileTask to exist when we reload later!)
if ( !IsFinishing && !_performingLoad)
snackbar.Show();
new Handler().PostDelayed(() =>
{
Snackbar snackbar2 = Snackbar
.Make(FindViewById(Resource.Id.main_content), "snack snack snack ",
Snackbar.LengthLong);
snackbar2.SetTextMaxLines(5);
snackbar2.SetBackgroundTint(GetColor(Resource.Color.md_theme_errorContainer));
snackbar2.SetTextColor(GetColor(Resource.Color.md_theme_onErrorContainer));
snackbar2.Show();
}, 1500);
new Handler().PostDelayed(() =>
{
Snackbar snackbar2 = Snackbar
.Make(FindViewById(Resource.Id.main_content), "snack snack warn ",
Snackbar.LengthLong);
snackbar2.SetTextMaxLines(5);
snackbar2.SetBackgroundTint(GetColor(Resource.Color.md_theme_inverseSurface));
snackbar2.SetTextColor(GetColor(Resource.Color.md_theme_inverseOnSurface));
snackbar2.Show();
}, 2500);*/
//use !IsFinishing to make sure we're not starting another activity when we're already finishing (e.g. due to TaskComplete in OnActivityResult)
//use !performingLoad to make sure we're not already loading the database (after ActivityResult from File-Prepare-Activity; this would cause _loadDbFileTask to exist when we reload later!)
if ( !IsFinishing && !_performingLoad)
{
@@ -1954,7 +2006,7 @@ namespace keepass2android
btn.Tag = error;
Toast.MakeText(this, Resource.String.fingerprint_reenable2, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, Resource.String.fingerprint_reenable2, MessageSeverity.Error);
_biometricDec = null;
return false;
@@ -2024,7 +2076,7 @@ namespace keepass2android
/*
private void errorMessage(CharSequence text)
{
Toast.MakeText(this, text, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, text, MessageSeverity.Error);
}
*/
@@ -2084,7 +2136,9 @@ namespace keepass2android
_act.LoadingErrorCount++;
}
if ((Exception != null) && (Exception.Message == KeePassLib.Resources.KLRes.FileCorrupted))
if ((Exception != null) && (Exception.Message == KeePassLib.Resources.KLRes.FileCorrupted))
{
Message = _act.GetString(Resource.String.CorruptDatabaseHelp);
}
@@ -2150,7 +2204,8 @@ namespace keepass2android
}
else
{
DisplayMessage(_act);
MessageSeverity severity = Success ? MessageSeverity.Info : MessageSeverity.Error;
App.Kp2a.ShowMessage(_act, Message, severity);
if (Success)
{
_act.LaunchNextActivity();
@@ -2218,7 +2273,7 @@ namespace keepass2android
{
Kp2aLog.LogUnexpectedError(e);
ShowError( _act.GetString(Resource.String.ErrorUpdatingOtpAuxFile) + " " + e.Message);
ShowError( _act.GetString(Resource.String.ErrorUpdatingOtpAuxFile) + " " + Util.GetErrorMessage(e));
}
@@ -2234,7 +2289,7 @@ namespace keepass2android
private void ShowError(string message)
{
App.Kp2a.ShowToast(message);
App.Kp2a.ShowToast(message, MessageSeverity.Error);
}
}
private class PasswordActivityBroadcastReceiver : BroadcastReceiver

View File

@@ -128,11 +128,11 @@ namespace keepass2android
Kp2aLog.LogUnexpectedError(e);
}
if (String.IsNullOrEmpty(_requestedUrl))
Toast.MakeText(this, GetString(Resource.String.query_credentials, new Java.Lang.Object[] {pluginDisplayName}), ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, GetString(Resource.String.query_credentials, new Java.Lang.Object[] {pluginDisplayName}), MessageSeverity.Info);
else
Toast.MakeText(this,
App.Kp2a.ShowMessage(this,
GetString(Resource.String.query_credentials_for_url,
new Java.Lang.Object[] { pluginDisplayName, _requestedUrl }), ToastLength.Long).Show(); ;
new Java.Lang.Object[] { pluginDisplayName, _requestedUrl }), MessageSeverity.Info); ;
}
private void StartQuery()

View File

@@ -35,6 +35,7 @@ using KeePassLib;
using KeePassLib.Serialization;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
using AndroidX.Core.Content;
using keepass2android.Utils;
namespace keepass2android
{
@@ -203,7 +204,7 @@ namespace keepass2android
btn.SetImageResource(Resource.Drawable.baseline_fingerprint_24);
}, 1300);
Toast.MakeText(this, message, ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, message, MessageSeverity.Error);
}
@@ -325,7 +326,7 @@ namespace keepass2android
{
Kp2aLog.Log("QuickUnlock not successful!");
App.Kp2a.Lock(false);
Toast.MakeText(this, GetString(Resource.String.QuickUnlock_fail), ToastLength.Long).Show();
App.Kp2a.ShowMessage(this, GetString(Resource.String.QuickUnlock_fail), MessageSeverity.Error);
Finish();
}
@@ -383,8 +384,9 @@ namespace keepass2android
{
base.OnResume();
_design.ReapplyTheme();
CheckIfUnloaded();
App.Kp2a.MessagePresenter = new ChainedSnackbarPresenter(FindViewById(Resource.Id.main_content));
CheckIfUnloaded();
InitFingerprintUnlock();
@@ -449,7 +451,8 @@ namespace keepass2android
protected override void OnPause()
{
if (_biometryIdentifier != null)
App.Kp2a.MessagePresenter = new NonePresenter();
if (_biometryIdentifier != null)
{
Kp2aLog.Log("FP: Stop listening");
_biometryIdentifier.StopListening();

View File

@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ScrollView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/entry_scroll"
android:background="?android:attr/colorBackground"
@@ -267,4 +273,5 @@
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
</ScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">التعليقات</string>
<string name="AboutText">Keepass2Android هو مدير كلمات سر يتيح القراءة والكتابة على قواعد بيانات KeePass 2.x على نظام الـAndroid.</string>
@@ -121,6 +121,7 @@
<string name="entry_user_name">اسم المستخدم</string>
<string name="entry_extra_strings">حقول النص الإضافية</string>
<string name="entry_binaries">المرفقات</string>
<string name="entry_history"></string>
<string name="error_can_not_handle_uri">Keepass2Android لا يمكنه التعامل مع هذا الرابط.</string>
<string name="error_could_not_create_group">خطأ في إنشاء المجموعة.</string>
<string name="error_could_not_create_parent">تعذر إنشاء المجلد الأصل.</string>
@@ -150,6 +151,7 @@
<string name="hint_keyfile">ملف المفتاح</string>
<string name="hint_length">الطول</string>
<string name="hint_pass">كلمة السر</string>
<string name="hint_keyfile_path"></string>
<string name="hint_login_pass">كلمة السر</string>
<string name="hint_title">الإسم</string>
<string name="hint_url">الرابط</string>
@@ -752,6 +754,5 @@
<string name="AutofillWarning_Intro">أنت على وشك إدراج بيانات اعتماد للنطاق \"%1$s\" في التطبيق \"%2$s\".</string>
<string name="AutofillWarning_FillDomainInUntrustedApp">إذا كنت تثق في \"%2$s\" بالانتماء إلى \"%1$s\" أو كنت تثق في التطبيق \"%2$s\" لعدم إساءة استخدام بيانات الاعتماد (e. . لأنه تطبيق متصفح موثوق به)، من المفضل المتابعة. إذا لم يكن الأمر كذلك ، يرجى الإلغاء .</string>
<string name="AutofillWarning_trustAsBrowser">قبول دائمًا في \"%1$s\"</string>
<string name="english_ime_settings">إعدادات لوحة مفاتيح Keepass2Android</string>
</resources>
<string name="english_ime_settings">إعدادات لوحة مفاتيح Keepass2Android</string>
</resources>

View File

@@ -1,6 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Əks əlaqə</string>
<string name="CreditsTextSFTP">SFTP dəstəyi, JCraft, Inc. tərəfindən yaradılmış JSch kitabxanası altında BSD lisenziyası ilə həyata keçirilmişdir.</string>
<string name="accept">Qəbul et</string>
<string name="deny">Rədd et</string>
<string name="add_entry">Qeyd əlavə et</string>
@@ -18,6 +19,7 @@
<string name="app_timeout">Tətbiq istifadə vaxtı</string>
<string name="show_kill_app">Bağla düyməsi</string>
<string name="kill_app_label">Tətbiqi bağla</string>
<string name="show_kill_app_summary">Şifrə ekranında tətbiq prosesini öldürmək üçün bir düymə göstərin (paranoid istifadəçilər üçün).</string>
<string name="application">Tətbiq</string>
<string name="application_settings">Tətbiq tənzimləmələri</string>
<string name="ShowGroupnameInSearchResult_title">Qrup adını axtarış nəticələrində göstər</string>
@@ -82,6 +84,5 @@
<string name="AutofillWarning_title">Təhlükəsizlik xəbərdarlığı: Tanınmayan domen/tətbiq bağlantısı</string>
<string name="AutofillWarning_Intro">\"%2$s\" tətbiqinə \"%1$s\" domeni üçün kimlik məlumatlarını daxil edirsiniz.</string>
<string name="AutofillWarning_trustAsBrowser">\"%1$s\" səyyahında həmişə qəbul et</string>
<string name="english_ime_settings">Android klaviatura tənzimləmələri</string>
</resources>
<string name="english_ime_settings">Android klaviatura tənzimləmələri</string>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Зваротная сувязь</string>
<string name="AboutText">Keepass2Android - кіраўнік пароляў для Android з паўнавартаснай падтрымкай базаў даных KeePass 2.x.</string>
@@ -401,6 +401,14 @@
<string name="ShowSeparateNotifications_summary">Паказваць асобныя апавяшчэнні для капіявання імя карыстальніка і пароля ў буфер абмену і актывацыі клавіятуры.</string>
<string name="AccServiceAutoFill_prefs">Адмысловая служба аўтазапаўнення</string>
<string name="AutoFill_prefs">Служба аўтазапаўнення</string>
<string name="AutoFillTotp_prefs_ShowNotification_summary">Пры аўтазапаўненні запісу з дапамогай TOTP паказваць апавяшчэнне з кнопкай \"Скапіяваць TOTP\".</string>
<string name="AutoFillTotp_prefs_ShowNotification_title">Паказваць апавяшчэнне пра запіс</string>
<string name="AutoFillTotp_prefs_title">Аўтазапаўненне запісаў TOTP</string>
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_title">Скапіяваць TOTP у буфер абмену</string>
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_summary">Пры аўтазапаўненні запісу з дапамогай TOTP капіяваць TOTP у буфер абмену</string>
<string name="AutoFillTotp_prefs_ActivateKeyboard_summary">Пры аўтазапаўненні запісу з дапамогай TOTP актываваць убудаваную клавіятуру. Клавіятура мае кнопку TOTP.</string>
<string name="AutoFillTotp_prefs_ActivateKeyboard_title">Актываваць убудаваную клавіятуру</string>
<string name="TotpCopiedToClipboard">TOTP скапіяваны ў буфер абмену</string>
<string name="ShowKp2aKeyboardNotification_title">Апавяшчэнні клавіятуры KP2A </string>
<string name="ShowKp2aKeyboardNotification_summary">Зрабіць увесь запіс даступным праз клавіятуру KP2A (рэкамендуецца).</string>
<string name="OpenKp2aKeyboardAutomatically_title">Пераключыць клавіятуру</string>
@@ -514,7 +522,17 @@
<string name="private_key_info">Каб захаваць, увядзіце назву ключа і змесціва</string>
<string name="private_key_delete">Выдаліць прыватны ключ: %1$s</string>
<string name="private_key_delete_failed">НЕ ЎДАЛОСЯ выдаліць прыватны ключ: %1$s</string>
<string name="save_key">Захаваць прыватны ключ</string>
<string name="delete_key">Выдаліць прыватны ключ</string>
<string name="private_key_select">Абраць прыватны ключ</string>
<string name="private_key_create_new">[Дадаць новы...]</string>
<string name="hint_sftp_key_passphrase">Падпольная фраза ключа (неабавязкова)</string>
<string name="sftp_kex_title">Алгарытм(ы) абмену ключамі (KEX) (неабавязкова)</string>
<string name="hint_sftp_kex">Падзеленыя коскамі значэнні</string>
<string name="sftp_shk_title">Алгарытм(ы) ключа хоста сервера (неабавязкова)</string>
<string name="hint_sftp_shk">Падзеленыя коскамі значэнні</string>
<string name="enter_ftp_login_title">Увядзіце даныя для ўваходу на сервер FTP:</string>
<string name="enter_mega_login_title">Увядзіце даныя для ўваходу ў свой акаўнт MEGA:</string>
<string name="select_storage_type">Абярыце тып сховішча:</string>
<string name="filestoragename_file">Лакальны файл</string>
<string name="filestoragename_androidget">Узяць з іншай праграмы</string>
@@ -528,13 +546,19 @@
<string name="filestoragename_dropboxKP2A">Dropbox (каталог KP2A)</string>
<string name="filestoragehelp_dropboxKP2A">Калі вы хочаце даць KP2A доступ да ўсяго сховішча Dropbox, абярыце гэты параметр. Праграма будзе запытваць доступ толькі да каталога Apps/Keepass2Android. Гэта асабліва пасуе пры стварэнні новай базы даных. Калі ў вас ужо ёсць база даных, абярыце гэты параметр, каб стварыць каталог, перамясціце ў яго файл базы даных, а пасля зноў абярыце гэты параметр, каб адкрыць файл.</string>
<string name="filestoragename_gdrive">Google Drive</string>
<string name="filestoragename_gdriveKP2A">Google Drive (файлы KP2A)</string>
<string name="filestoragehelp_gdriveKP2A">Калі вы не хочаце даваць KP2A поўны доступ да Google Drive, вы можаце абраць гэты варыянт. Звярніце ўвагу на тое, што спачатку вам трэба стварыць файл базы даных, бо праграма не бачыць наяўныя файлы. Таксама вы можаце абраць гэты параметр на экране \"Стварыць базу даных\" або, калі вы ўжо адкрылі базу даных, вы можаце экспартаваць базу даных, абраўшы гэты параметр.</string>
<string name="filestoragename_pcloud">PCloud (каталог KP2A)</string>
<string name="filestoragehelp_pcloud">Гэты тып сховішча запытвае доступ толькі да каталога pCloud \"Праграмы/Keepass2Android\". Калі вы хочаце выкарыстоўваць наяўную базу даных з акаўнта pCloud, то пераканайцеся, што файл знаходзіцца ў каталозе pCloud.</string>
<string name="filestoragename_pcloudall">PCloud (поўны доступ)</string>
<string name="filestoragename_onedrive">OneDrive</string>
<string name="filestoragename_onedrive2">OneDrive</string>
<string name="filestoragename_onedrive2_full">Усе файлы і агульныя файлы</string>
<string name="filestoragename_onedrive2_myfiles">Мае файлы</string>
<string name="filestoragename_onedrive2_appfolder">Каталог праграмы Keepass2Android</string>
<string name="filestoragename_sftp">SFTP (перадача файлаў па SSH)</string>
<string name="filestoragename_mega">MEGA</string>
<string name="filestoragehelp_mega">Звярніце ўвагу: каб працаваць належным чынам, Keepass2Android павінен спампаваць спіс усіх файлаў у вашым акаўнце Mega. Па гэтай прычыне апрацоўванне акаўнтаў з вялікай колькасцю файлаў можа быць павольным.</string>
<string name="filestoragename_content">Сістэмны сродак для выбару файлаў</string>
<string name="filestorage_setup_title">Ініцыялізацыя доступу да файла</string>
<string name="database_location">Размяшчэнне базы даных</string>
@@ -572,12 +596,14 @@
<string name="CouldntLoadChalAuxFile_Hint">Усталюйце ўбудову KeeChallenge для KeePass 2.x (PC), каб наладзіць базу даных для працы з запытамі-адказамі!</string>
<string name="ErrorUpdatingChalAuxFile">Не атрымалася абнавіць дапаможны файл OTP (аднаразовых пароляў)!</string>
<string name="TrayTotp_SeedField_title">Назва поля пачатковага значэння TOTP</string>
<string name="TOTP">TOTP</string>
<string name="TrayTotp_SeedField_summary">Калі вы выкарыстоўваеце ўбудову Keepass 2 \"TrayTotp\" са змененымі наладамі, увядзіце назву поля для поля пачатковага значэння ў адпаведнасці з наладамі PC.</string>
<string name="TrayTotp_SettingsField_title">Назва поля налад TOTP</string>
<string name="TrayTotp_SettingsField_summary">Увядзіце сюды назву поля для налад TrayTotp.</string>
<string name="TrayTotp_prefs">TrayTotp</string>
<string name="DebugLog_prefs_prefs">Файл журнала для адладкі</string>
<string name="DebugLog_title">Выкарыстоўваць файл журнала</string>
<string name="FtpDebug_title">Журнал адладжвання FTP/SFTP</string>
<string name="DebugLog_summary">Запісваць выходныя даныя праграмы ў лакальны файл журнала</string>
<string name="DebugLog_send">Адправіць журнал адладкі…</string>
<string name="loading">Загрузка…</string>
@@ -663,6 +689,8 @@
<string name="child_db_Enabled_title">Адкрываць аўтаматычна</string>
<string name="database_file_heading">Файл базы даных</string>
<string name="if_device_text">Уключыць для %1$s</string>
<string name="restore_history">Аднавіць гэтую версію</string>
<string name="remove_history">Выдаліць гэтую версію</string>
<string name="DbUnlockedChannel_name">База даных разблакаваная</string>
<string name="DbUnlockedChannel_desc">Апавяшчэнне пра разблакаванне базы даных</string>
<string name="DbQuicklockedChannel_name">Хуткае разблакаванне</string>
@@ -774,8 +802,8 @@
</string-array>
<string-array name="sftp_auth_modes">
<item>Пароль</item>
<item>KP2A Private/Public key</item>
<item>Custom Private key</item>
<item>Прыватны або публічны ключ KP2A</item>
<item>Адвольны прыватны ключ</item>
</string-array>
<string-array name="AcceptAllServerCertificates_options">
<item>Не зважаць на памылкі праверкі сертыфіката</item>
@@ -793,6 +821,11 @@
<string name="autofill_enable_for">Уключыць аўтазапаўненне для %1$s</string>
<string name="invalid_link_association">Не атрымалася звязаць дамен %1$s з праграмай %2$s</string>
<string name="enable_fingerprint_hint">Праграма Keepass2Android выявіла абсталяванне для распазнавання біяметрычных даных. Хочаце ўключыць для гэтай базы даных разблакаванне з дапамогай біяметрычных даных?</string>
<string name="post_notifications_dialog_title">Дазволіць апавяшчэнні</string>
<string name="post_notifications_dialog_message">Keepass2Android можа паказваць апавяшчэнні з кнопкамі для капіявання пароляў і TOTP у буфер абмену або для вываду ўбудаванай клавіятуры. Гэта карысна для перадачы значэнняў у іншыя праграмы без паўторнага пераключэння на Keepass2Android. Хочаце ўключыць такія апавяшчэнні?</string>
<string name="post_notifications_dialog_allow">Дазволіць апавяшчэнні</string>
<string name="post_notifications_dialog_disable">Адключыць гэтую функцыю</string>
<string name="post_notifications_dialog_notnow">Пазней</string>
<string name="understand">Зразумела</string>
<string name="dont_show_again">Больш не паказваць</string>
<string name="masterkey_infotext_head">Вы памятаеце свой галоўны пароль?</string>
@@ -811,6 +844,5 @@
<string name="AutofillWarning_Intro">Вы хочаце ўставіць уліковыя даныя для дамена \"%1$s\" у праграму \"%2$s\".</string>
<string name="AutofillWarning_FillDomainInUntrustedApp">Калі ёсць упэўненасць, што \"%2$s\" належыць \"%1$s\" або вы давяраеце \"%2$s\", не злоўжывайце ўліковымі данымі (напрыклад, гэта давераная праграма браўзера). Калі ўсё добра, можна працягнуць. Калі не, скасуйце.</string>
<string name="AutofillWarning_trustAsBrowser">Заўсёды ўхваляць у \"%1$s\"</string>
<string name="english_ime_settings">Налады клавіятуры Android</string>
</resources>
<string name="english_ime_settings">Налады клавіятуры Android</string>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Отзив</string>
<string name="AboutText">Keepass2Android е мениджър за пароли който осигурява достъп четене/записване до KeePass 2.x база данни на Android.</string>
@@ -463,6 +463,5 @@
<item>KP2A Private/Public key</item>
<item>Custom Private key</item>
</string-array>
<string name="english_ime_settings">Настройки на клавиатурата на Keepass2Android</string>
</resources>
<string name="english_ime_settings">Настройки на клавиатурата на Keepass2Android</string>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Suggeriments</string>
<string name="AboutText">Keepass2Android és una implementació per Android de KeePass password manager.</string>
@@ -151,6 +151,7 @@
<string name="hint_keyfile">arxiu clau</string>
<string name="hint_length">longitud</string>
<string name="hint_pass">contrasenya</string>
<string name="hint_keyfile_path">Ubicació de Clau privada SSH</string>
<string name="hint_login_pass">Contrasenya</string>
<string name="hint_title">nom</string>
<string name="hint_url">URL</string>
@@ -171,6 +172,10 @@
<string name="MaskedPassword">*****</string>
<string name="maskpass_title">Emmascara contrasenya</string>
<string name="maskpass_summary">Amaga les contrasenyes per defecte</string>
<string name="masktotp_title">Màscara de camp TOTP</string>
<string name="masktotp_summary">Oculta el camp TOTP, per defecte </string>
<string name="NoAutofillDisabling_title">Sense opció per deshabilitar la funció d\'autoomplir</string>
<string name="NoAutofillDisabling_summary">Si s\'activa, l\'aplicació no mostrarà l\'opció per deshabilitar autoomplir d\'algunes entrades específiques.</string>
<string name="menu_about">Sobre</string>
<string name="menu_change_key">Canvia Clau Mestra</string>
<string name="menu_copy_pass">Copia contrasenya</string>
@@ -231,6 +236,7 @@
<string name="saving_database">Guardant la base de dades…</string>
<string name="exporting_database">Exportant la base de dades…</string>
<string name="export_database_successful">Base de dades exportada amb èxit!</string>
<string name="export_keyfile_successful">Fitxer contrasenya exportat amb èxit!</string>
<string name="space">Espai</string>
<string name="search_label">Cerca</string>
<string name="show_password">Mostra contrasenya</string>
@@ -240,16 +246,24 @@
<string name="sort_moddate">Ordenar per data modificació</string>
<string name="sort_default">Mantenir l\'ordre per defecte</string>
<string name="special">Especial</string>
<string name="special_extended">Afegit especial.</string>
<string name="at_least_one_from_each_group">Almenys un de cada grup</string>
<string name="exclude_lookalike">Exclou lletres paregudes</string>
<string name="password_generation_profile">Perfil</string>
<string name="save_password_generation_profile_text">Introdueix el nom del perfil a desar. Introdueix un nom existent per reemplaçar-ho.</string>
<string name="hint_wordcount">Comptador de paraules de la contrasenya</string>
<string name="hint_wordseparator">Separador de paraules</string>
<string-array name="PasswordGeneratorModes">
<item>Contrasenya</item>
<item>Passphrase</item>
<item>Passphrase + Password</item>
<item>Contrasenya</item>
<item>Frase de contrasenya + Contrasenya</item>
</string-array>
<string-array name="PasswordGeneratorCaseModes">
<item>minúscules</item>
<item>MAJÚSCULES</item>
<item>First Character Uppercase</item>
<item>Primer caràcter en majúscules</item>
</string-array>
<string name="custom_settings">Configuració personalitzada</string>
<string name="search_hint">Trobar el que</string>
<string name="search_results">Resultats de cerca</string>
<string name="search_in">Cerca a</string>
@@ -267,18 +281,23 @@
<string name="author">Keepass2Android és desenvolupat per Philipp Crocoll.</string>
<string name="further_authors">Gràcies a les aportacions de codi de %1$s.</string>
<string name="designers">Gràcies a les aportacions de disseny icona i disseny per %1$s.</string>
<string name="supporters">Gràcies al suport financer de %1$s.</string>
<string name="credit_plugin1">El Plugin de xifratge Twofish per Keepass va ser desenvolupat per Scott Greenberg i està inclòs en KP2A.</string>
<string name="credit_android_filechooser">androide-filechooser va ser desenvolupat per Hai bisó</string>
<string name="credit_keyboard">El teclat de l\'KP2A es basa en el teclat de Gingerbread del projecte de font oberta Android i utilitza el codi del Gesto de Conectors del teclat Hacker per Klaus Weidner.</string>
<string name="please_note">Tingueu en compte</string>
<string name="contributors">Contribuïdors</string>
<string name="regular_expression">Expressió regular</string>
<string name="AlwaysMergeOnConflict_title">Sempre mescla en cas de conflicte</string>
<string name="AlwaysMergeOnConflict_summary">Quan Keepass2Android detecti que el fitxer remot ha sigut modificat, mescla els canvis locals amb els remots.</string>
<string name="TanExpiresOnUse_title">TAN expira en ús</string>
<string name="TanExpiresOnUse_summary">Marca entrades TAN caducades quan siguin utilitzades</string>
<string name="ShowUsernameInList_title">Mostra nom d\'usuari en llista</string>
<string name="ShowUsernameInList_summary">Mostrar noms d\'usuari sota títols d\'entrada. Útil per a comptes múltiples o TANs.</string>
<string name="RememberRecentFiles_title">Recordeu les bases de dades</string>
<string name="RememberRecentFiles_summary">Recordeu les bases de dades recentment obertes i mostrar-les en la pantalla de d\'obrir base de dades.</string>
<string name="InlineSuggestions_title">Integra amb el teclat</string>
<string name="requires_android11">Requereix Android 11 o superior</string>
<string name="kp2a_findUrl">Trobar contrasenya</string>
<string name="excludeExpiredEntries">Excloure les entrades caducats</string>
<string name="search_options">Opcions</string>
@@ -324,6 +343,11 @@
<string name="protection">Camp protegit</string>
<string name="add_binary">Afegir el fitxer adjunt...</string>
<string name="add_extra_string">Afegir la cadena addicional</string>
<string name="configure_totp">Configura TOTP</string>
<string name="totp_secret_key">Clau secreta</string>
<string name="totp_encoding_custom">Configuració personalitzada del testimoni</string>
<string name="totp_length">Longitud del codi</string>
<string name="totp_scan">Escaneja un codi QR</string>
<string name="delete_extra_string">Suprimir la corda addicional</string>
<string name="database_loaded_quickunlock_enabled">%1$s: bloquejat. DesbloqueigRàpid activat.</string>
<string name="database_loaded_unlocked">%1$s: desbloquejat.</string>
@@ -382,6 +406,7 @@
<string name="ShowUnlockedNotification_summary">Mostra una icona de notificació mentre la base de dades està desbloquejada.</string>
<string name="IconVisibilityInfo_Android8_text">Android 8 ha introduït un nou comportament de les notificacions. Si voleu amagar la icona de les notificacions de Keepass2Android, si us plau, s\'ha de fer a través de la configuració del sistema. Estableix la importància de la categoria de les notificacions al Mínim.</string>
<string name="IconVisibilityInfo_Android8_btnSettings">Obrir la configuració</string>
<string name="PostNotificationsPermissionInfo_text">Keepass2Android pot mostrar una notificació mentre la teva base de dades estigui desbloquejada. Perquè açò funcioni, dona permís.</string>
<string name="DontCare">No m\'importa</string>
<string name="DocumentAccessRevoked">L\'arxiu ja no és accessible a Keepass2Android. O ha sigut eliminat o els permisos d\'accés han estat revocats. Si us plau utilitzeu re-obre l\'arxiu, per exemple, utilitzant el canvi de base de dades.</string>
<string name="PreloadDatabaseEnabled_title">Pre-carregar el fitxer de base de dades</string>
@@ -467,6 +492,12 @@
<string name="enter_sftp_login_title">Introduir dades de connexió SFTP:</string>
<string name="sftp_auth_mode">Mode d\'autenticació</string>
<string name="send_public_key">Enviar clau pública...</string>
<string name="save_key">Desa la clau privada</string>
<string name="delete_key">Elimina la clau privada</string>
<string name="private_key_select">Seleccioneu la clau privada</string>
<string name="private_key_create_new">[Afegeix nova...]</string>
<string name="hint_sftp_kex">Noms/Especificacions separats per comes</string>
<string name="hint_sftp_shk">Noms/Especificacions separats per comes</string>
<string name="enter_ftp_login_title">Introduir dades de connexió FTP:</string>
<string name="select_storage_type">Seleccioneu el tipus d\'emmagatzematge:</string>
<string name="filestoragename_file">Fitxer local</string>
@@ -481,12 +512,16 @@
<string name="filestoragename_dropboxKP2A">Dropbox (carpeta de KP2A)</string>
<string name="filestoragehelp_dropboxKP2A">Si no voleu donar accés KP2A al seu Dropbox complet, heu de seleccionar aquesta opció. Es sol·licitarà només l\'accés a la carpeta Apps/Keepass2Android. Això és especialment adequat quan es crea una nova base de dades. Si ja teniu una base de dades, feu clic a aquesta opció per crear la carpeta, a continuació, posar el seu arxiu dins la carpeta (des del seu PC) i llavors seleccioni aquesta opció de nou per obrir l\'arxiu.</string>
<string name="filestoragename_gdrive">Google Drive</string>
<string name="filestoragename_gdriveKP2A">Google Drive (Fitxers KP2A)</string>
<string name="filestoragename_pcloud">PCloud (Carpeta KP2A)</string>
<string name="filestoragename_pcloudall">PCloud (Accés complet)</string>
<string name="filestoragename_onedrive">OneDrive</string>
<string name="filestoragename_onedrive2">OneDrive</string>
<string name="filestoragename_onedrive2_full">Tots els fitxers i fitxers compartits</string>
<string name="filestoragename_onedrive2_myfiles">Els meus fitxers</string>
<string name="filestoragename_onedrive2_appfolder">Carpeta de l\'aplicació Keepass2Android</string>
<string name="filestoragename_sftp">SFTP (SSH Transferència de fitxer)</string>
<string name="filestoragename_mega">MEGA</string>
<string name="filestoragename_content">Selector d\'arxiu de sistema</string>
<string name="filestorage_setup_title">Inicialització d\'accés a arxiu</string>
<string name="database_location">Localització de la base de dades</string>
@@ -720,6 +755,5 @@
<string name="switch_ime_text">Si us plau, activa el teclat Keepass2Android.</string>
<string name="switch_ime_reopen">Reintenta</string>
<string name="AutofillWarning_trustAsBrowser">Acceptar sempre en \"%1$s\"</string>
<string name="english_ime_settings">Configuració del teclat d\'Keepass2Android</string>
</resources>
<string name="english_ime_settings">Configuració del teclat d\'Keepass2Android</string>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Zpětná vazba</string>
<string name="AboutText">Keepass2Android je správce hesel pro práci se soubory KeePass 2.x. na platformě Android.</string>
@@ -546,6 +546,7 @@
<string name="filestoragename_dropboxKP2A">Dropbox (KP2A složka)</string>
<string name="filestoragehelp_dropboxKP2A">Pokud nechcete, aby měl KP2A plný přístup k vašemu Dropbox účtu, může vybrat tuto možnost. Bude vyžadován pouze přístup ke složce Apps/Keepass2Android. Toto je vhodné zejména při vytváření nové databáze. Pokud již máte databázi, zvolte na tuto možnost pro vytvoření složky, poté umístěte soubor (z PC) do této složky a zvolte tuto možnost znovu pro otevření souboru.</string>
<string name="filestoragename_gdrive">Google Drive</string>
<string name="filestoragehelp_gdrive">Upozornění: Společnost Google omezuje přístup k Disku Google z aplikací pro stále více uživatelů. Pokud vestavěná implementace Disku Google nefunguje, použijte místo toho systémový výběr souborů a vyberte Disk Google tam!</string>
<string name="filestoragename_gdriveKP2A">Google Drive (KP2A soubory)</string>
<string name="filestoragehelp_gdriveKP2A">Nechcete-li dát aplikaci KeePass2Android přístup k celému vašemu Google Drive, použijte tuto možnost. Upozorňujeme, že nejprve musíte vytvořit soubor s databází položek, existující soubory nejsou viditelné pro aplikaci. Toto můžete udělat z obrazovky Vytvořit databázi, nebo exportem právě otevřené databáze, volbou této možnosti</string>
<string name="filestoragename_pcloud">PCloud (složka KP2A)</string>
@@ -717,6 +718,20 @@
<string name="EntryChannel_desc">Upozornění pro usnadnění přístupu k momentálně zvolené položce.</string>
<string name="CloseDbAfterFailedAttempts">Zavřít databázi po třech neúspěšných pokusech o odemknutí.</string>
<string name="WarnFingerprintInvalidated">Varování! Biometrické ověření může být zneplatněno Androidem, např. po přidání nového otisku prstu do nastavení zařízení. Ujistěte se, že vždy víte, jak odemknout pomocí hlavního hesla!</string>
<string-array name="ChangeLog_1_12">
<item>Aktualizováno z Xamarin Android na .net 8</item>
<item>Aktualizováno na Target SDK 34</item>
<item>Aktualizováno na uživatelské rozhraní Material 3</item>
<item>Vylepšení automatického vyplňování pro práci s aplikacemi Compose</item>
<item>Oprava přiřazování názvů hostitelů v automatickém vyplňování a vyhledávání</item>
<item>Oprava problému s generátorem hesel</item>
</string-array>
<string-array name="ChangeLog_1_12_net">
<item>Aktualizováno OneDrive SDK na verzi 5.68</item>
<item>Aktualizováno Dropbox SDK na verzi 7.0.0</item>
<item>Aktualizován Gradle, NewtonsoftJson, FluentFTP, MegaApiClient a okhttp</item>
<item>Oprava chyby ve výběru souborů WebDav</item>
</string-array>
<string-array name="ChangeLog_1_11">
<item>Přidána plovoucí akční tlačítka pro vyhledávání a přehled TOTP (pokud jsou přítomny položky TOTP).</item>
<item>Vylepšeno zobrazení polí TOTP přidáním indikátoru časového limitu a jeho výraznějším zobrazením.</item>
@@ -1150,6 +1165,8 @@ První veřejné vydání
<string name="AutofillWarning_Intro">Chystáte se vložit přihlašovací údaje pro doménu \"%1$s\" do aplikace \"%2$s\".</string>
<string name="AutofillWarning_FillDomainInUntrustedApp">Pokud věříte že \"%2$s\" patří k \"%1$s\", nebo důvěřujete \"%2$s\" že nezneužije přihlašovací údaje (např. pokud se jedná o důvěryhodný prohlížeč), můžete pokračovat. Pokud tomu tak není, zrušte prosím tuto akci.</string>
<string name="AutofillWarning_trustAsBrowser">Přijmout vždy v \"%1$s\"</string>
<string name="english_ime_settings">Nastavení klávesnice Keepass2Android</string>
</resources>
<string name="kp2a_switch_on_sendgodone">Přepnout zpět po dokončení</string>
<string name="kp2a_switch_on_sendgodone_summary">Přepnout zpět při stisknutí tlačítka odeslat/pokračovat/ukončit</string>
<string name="qr_scanning_error_no_google_play_services">Skenování QR kódu vyžaduje služby Google Play. Nainstalujte nebo aktualizujte služby Google Play ve svém zařízení.</string>
<string name="english_ime_settings">Nastavení klávesnice Keepass2Android</string>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Tilbagemelding</string>
<string name="AboutText">Keepass2Android er en adgangskodehåndterings-app, der giver læse-/skriveadgang til KeePass 2.x-databaser på Android.</string>
@@ -818,6 +818,5 @@
<string name="AutofillWarning_Intro">Du er ved at indsætte legitimationsoplysninger for domæne \"%1$s\" i appen \"%2$s\".</string>
<string name="AutofillWarning_FillDomainInUntrustedApp">Hvis du stoler på at \"%2$s\" tilhører \"%1$s\", eller du stoler på at app\'en \"%2$s\" ikke misbruger legitimationsoplysningerne (f.eks. fordi det er en betroet browser app), er det ok at fortsætte. Ellers bedes du annullere.</string>
<string name="AutofillWarning_trustAsBrowser">Accepter altid i \"%1$s\"</string>
<string name="english_ime_settings">Indstillinger for Keepass2Android-tastatur</string>
</resources>
<string name="english_ime_settings">Indstillinger for Keepass2Android-tastatur</string>
</resources>

View File

@@ -1,10 +1,10 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Feedback</string>
<string name="AboutText">Keepass2Android ist ein Passwortmanager mit Lese- und Schreib-Zugriff auf KeePass 2.x Datenbanken.</string>
<string name="AboutText">Keepass2Android ist ein Passwortmanager, der KeePass 2.x-Datenbanken verwalten kann.</string>
<string name="CreditsText">Die Benutzeroberfläche basiert auf einem Port von Keepassdroid (entwickelt von Brian Pellin) nach Mono for Android. Der Code für die Datenbank-Operationen nutzt eine angepasste Version einer Bibliothek aus KeePass (entwickelt von Dominik Reichl).
Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die Google durchgeführt und zur Verfügung gestellt hat; er wird nach den Bedingungen der Creative Commons 3.0 Attribution License genutzt.</string>
<string name="CreditsTextSFTP">SFTP-Unterstützung ist implementiert unter Nutzung der JSch-Bibliothek (BSD-Lizenz), erstellt durch JCraft, Inc.</string>
<string name="CreditsTextSFTP">SFTP-Unterstützung ist implementiert unter Verwendung der JSch-Bibliothekvmit BSD-Lizenz der Fa. JCraft Inc.</string>
<string name="CreditsIcons">Das Hammer-Icon wurde von John Caserta (Noun Project) erstellt. Das Pinguin-Icon wurde von Adriano Emerick (Noun Project) erstellt. Das Feder-Icon wurde von Jon Testa (Noun Project) erstellt. Das Apfel-Icon wurde von Ava Rowell (Noun Project) erstellt. Das Bild-Icon stammt von https://icons8.com/icon/5570/Picture.</string>
<string name="accept">Akzeptieren</string>
<string name="deny">Verweigern</string>
@@ -28,7 +28,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
<string name="application">Anwendung</string>
<string name="application_settings">Anwendungseinstellungen</string>
<string name="ShowGroupnameInSearchResult_title">Gruppennamen im Suchergebnis anzeigen</string>
<string name="ShowGroupnameInSearchResult_resume">Gruppennamen unter den Eintragstiteln im Suchergebnis anzeigen. Nützlich, wenn es mehrere Einträge mit dem selben Namen gibt.</string>
<string name="ShowGroupnameInSearchResult_resume">Gruppennamen unter den Eintragstiteln im Suchergebnis anzeigen. Nützlich, wenn es mehrere Einträge mit demselben Namen gibt.</string>
<string name="NavigationToGroupCompleted_message">Angezeigte Gruppe ist jetzt: %1$s</string>
<string name="AutofillDisabledQueriesPreference_title">Deaktivierte AutoFill-Ziele</string>
<string name="AutofillDisabledQueriesPreference_summary">Zeigt eine Liste von Apps und Webseiten, für die AutoFill deaktiviert ist.</string>
@@ -123,7 +123,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
<string name="entry_extra_strings">Zusätzliche Felder</string>
<string name="entry_binaries">Datei-Anhänge</string>
<string name="entry_history">Vorherige Versionen</string>
<string name="error_can_not_handle_uri">Keepass2Android kann diese Adresse nicht verarbeiten.</string>
<string name="error_can_not_handle_uri">Keepass2Android kann diese URI nicht verarbeiten.</string>
<string name="error_could_not_create_group">Fehler beim Erstellen der Gruppe.</string>
<string name="error_could_not_create_parent">Verzeichnis konnte nicht erstellt werden.</string>
<string name="error_database_exists">Diese Datei existiert bereits.</string>
@@ -295,7 +295,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
<string name="TanExpiresOnUse_title">TAN verfällt bei Verwendung</string>
<string name="TanExpiresOnUse_summary">TAN-Einträge als abgelaufen markieren, wenn sie verwendet werden</string>
<string name="ShowUsernameInList_title">Benutzernamen in Liste anzeigen</string>
<string name="ShowUsernameInList_summary">Zeige Benutzernamen unter den Titeln der Einträge. Hilfreich bei mehreren Accounts für einen Dienst oder bei TANs.</string>
<string name="ShowUsernameInList_summary">Benutzernamen unter den Eintragstiteln anzeigen. Nützlich für mehrere Konten bei einem Dienst oder für TANs.</string>
<string name="RememberRecentFiles_title">Datenbanken merken</string>
<string name="RememberRecentFiles_summary">Dateinamen der bisher geöffneten Datenbanken speichern und im Bildschirm zum Öffnen der Datenbank anzeigen.</string>
<string name="NoDalVerification_title">Keine Digital-Asset-Link-Verifikation</string>
@@ -642,7 +642,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
<string name="FileReadOnlyTitle">Datenbank ist schreibgeschützt</string>
<string name="FileReadOnlyMessagePre">Keepass2Android hat die aktuelle Datenbank im schreibgeschützten Modus geöffnet.</string>
<string name="ReadOnlyReason_PreKitKat">Es scheint, dass die Datei von einer externen Anwendung aus geöffnet wurde. Über diesen Weg ist das Schreiben nicht möglich. Wenn Änderungen an der Datenbank vorgenommen werden sollen, bitte die Datenbank schließen und „Datenbank wechseln“ wählen. Danach die Datei über eine der verfügbaren Optionen öffnen, sofern möglich.</string>
<string name="ReadOnlyReason_ReadOnlyFlag">Datei ist schreibgeschützt. Diese Attribut entfernen, wenn Änderungen an der Datenbank vorgenommen werden sollen.</string>
<string name="ReadOnlyReason_ReadOnlyFlag">Datei ist schreibgeschützt. Dieses Attribut entfernen, wenn Änderungen an der Datenbank vorgenommen werden sollen.</string>
<string name="ReadOnlyReason_ReadOnlyKitKat">Das Speichern ist aufgrund von Einschränkungen, die in Android KitKat eingeführt wurden, nicht möglich. Wenn Änderungen an der Datenbank vorgenommen werden sollen, bitte die Datenbank schließen und „Datenbank wechseln“ wählen. Danach die Datei über die systeminterne Dateiauswahl öffnen.</string>
<string name="ReadOnlyReason_LocalBackup">Lokale Sicherungskopien können nicht bearbeitet werden. Du kannst über \"Datenbank-Einstellungen\" - \"Datenbank exportieren\" dieses Backup an einen anderen Ort exportieren und dann von dort öffnen. Dann kannst du auch wieder Änderungen vornehmen.</string>
<string name="AddCustomIcon">Icon aus Datei hinzufügen...</string>
@@ -716,6 +716,20 @@ Anbei einige Tipps, die bei der Diagnose des Problems helfen können:\n
<string name="EntryChannel_desc">Benachrichtigung zum schnellen Zugriff auf den aktuell gewählten Eintrag.</string>
<string name="CloseDbAfterFailedAttempts">Datenbank nach drei fehlgeschlagenen biometrischen Entsperrversuchen schließen.</string>
<string name="WarnFingerprintInvalidated">Achtung! Die biometrische Authentifizierung kann von Android ungültig gemacht werden, z. B. nach dem Hinzufügen eines neuen Fingerabdrucks in den Geräteeinstellungen. Bitte sicherstellen, dass jederzeit klar ist, wie mit dem eigenen Hauptpasswort entsperrt werden kann!</string>
<string-array name="ChangeLog_1_12">
<item>Upgraded from Xamarin Android to .net 8</item>
<item>Upgrade auf Target-SDK 34</item>
<item>Upgraded to Material 3 user interface</item>
<item>Improve autofill to work with Compose apps</item>
<item>Fix hostname matching in autofill and search</item>
<item>Fix issue with password generator</item>
</string-array>
<string-array name="ChangeLog_1_12_net">
<item>OneDrive SDK auf Version 5.68 aktualisiert</item>
<item>Dropbox SDK auf Version 7.0.0 aktualisiert</item>
<item>Gradle, NewtonsoftJson, FluentFTP, MegaApiClient und okhttp aktualisiert</item>
<item>Bugfix in WebDav-Dateiauswahl</item>
</string-array>
<string-array name="ChangeLog_1_11">
<item>Buttons für die Suche und eine TOTP-Übersicht hinzugefügt (falls TOTP-Einträge vorhanden sind)</item>
<item>Darstellung von TOTP-Feldern verbessert: Timeout-Anzeige hinzugefügt und besser sichtbar gemacht.</item>
@@ -1134,8 +1148,8 @@ Erstes öffentliches Release</string>
<string name="backup_infotext_head">Gibt es eine Sicherung der Datenbank?</string>
<string name="backup_infotext_main">Keepass2Android speichert die Passwörter in einer Datei an einem frei wählbarem Speicherort.Ist sichergestellt, dass die Datei auch dann noch verfügbar ist, wenn das Telefon verloren geht oder gestohlen wird, oder wenn die Datei zerstört oder gelöscht wird? Bitte sicherstellen, dass immer eine aktuelle Kopie an einem sichern Ort aufbewahrt wird!</string>
<string name="backup_infotext_note">Um jetzt eine Sicherung zu erstellen, nach %1$s &gt; %2$s &gt; %3$s gehen.</string>
<string name="emergency_infotext_head">Ist man auf Notfälle vorbereitet?</string>
<string name="emergency_infotext_main">Wurde schon einmal darüber nachgedacht, was passiert, wenn man keinen Zugriff mehr zu seiner Passwortdatenbank hat? Was ist, wenn man einen Unfall hat? Es ist eine vernünftige Maßnahme, den Hauptschlüssel für Notfälle an eine vertrauenswürdige Person weiterzugeben. Andernfalls hat niemand Zugang zu den Passwörtern.</string>
<string name="emergency_infotext_head">Hast du für Notfälle vorgesorgt?</string>
<string name="emergency_infotext_main">Hast du je darüber nachgedacht, was passiert, wenn du nicht mehr auf deine Passwort-Datenbank zugreifen kannst? Was, wenn du einen Unfall hast? Ein bewährtes Verfahren ist, einer vertrauenswürdigen Person dein Masterpasswort für Notfälle mitzuteilen. Ansonsten wird niemand auf deine Passwörter Zugriff haben.</string>
<string name="no_secure_display">Der aktuell gültige Bildschirm ist nicht als sicher eingestuft. Das bedeutet, dass Bildschirmfotos von anderen Anwendungen erstellt werden könnten. Keepass2Android ist so konfiguriert, dass sensible Informationen nur auf sicheren Bildschirmen angezeigt werden. Bitte zu einem sicheren Bildschirm wechseln (z. B. durch Abklemmen eines HDMI-Monitors) oder die App-Einstellungen ändern.</string>
<string name="disable_secure_screen_check">Diese Nachricht deaktivieren</string>
<string name="switch_ime_text">Bitte die Keepass2Android-Tastatur aktivieren.</string>
@@ -1144,6 +1158,8 @@ Erstes öffentliches Release</string>
<string name="AutofillWarning_Intro">Hiermit werden Anmeldeinformationen für die Domäne „%1$s“ in die Anwendung „%2$s“ eingefügt.</string>
<string name="AutofillWarning_FillDomainInUntrustedApp">Wenn darauf vertraut wird, dass „%2$s“ zu „%1$s“ gehört, oder wenn darauf vertraut wird, dass die App „%2$s“ die Anmeldeinformationen nicht missbraucht (z. B. weil es sich um eine vertrauenswürdige Browser-App handelt), kann fortgefahren werden. Falls nicht, bitte abbrechen.</string>
<string name="AutofillWarning_trustAsBrowser">Für „%1$s“ immer akzeptieren</string>
<string name="english_ime_settings">Keepass2Android-Tastatureinstellungen</string>
</resources>
<string name="kp2a_switch_on_sendgodone">Tastatur zurückwechseln wenn fertig</string>
<string name="kp2a_switch_on_sendgodone_summary">Beim Drücken von Senden/Los/Fertig zurückschalten</string>
<string name="qr_scanning_error_no_google_play_services">QR-Code-Scannen erfordert Google Play-Dienste. Bitte installiere oder aktualisiere Google Play-Dienste auf deinem Gerät.</string>
<string name="english_ime_settings">Android-Tastatureinstellungen</string>
</resources>

View File

@@ -1,4 +1,4 @@
<?xml version='1.0' encoding='utf-8'?>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_feedback">Σχόλια</string>
<string name="AboutText">Το KP2A είναι ένας διαχειριστής συνθηματικών, που παρέχει την δυνατότητα ανάγνωσης/εγγραφής σε βάσεις δεδομένων του KeePass 2.x στο Android.</string>
@@ -865,6 +865,5 @@
<string name="AutofillWarning_Intro">Πρόκειται να εισάγετε διαπιστευτήρια για τον τομέα \"%1$s\" στην εφαρμογή \"%2$s\".</string>
<string name="AutofillWarning_FillDomainInUntrustedApp">Εάν εμπιστεύεστε ότι το \"%2$s\" ανήκει στο \"%1$s\" ή εμπιστεύεστε ότι η εφαρμογή \"%2$s\" δεν καταχράται τα διαπιστευτήρια (πχ. επειδή είναι μια αξιόπιστη εφαρμογή περιήγησης), είναι εντάξει να συνεχίσετε. Αν όχι, ακυρώστε.</string>
<string name="AutofillWarning_trustAsBrowser">Αποδοχή πάντα στο \"%1$s\"</string>
<string name="english_ime_settings">Ρυθμίσεις πληκτρολογίου Android</string>
</resources>
<string name="english_ime_settings">Ρυθμίσεις πληκτρολογίου Android</string>
</resources>

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