Compare commits

..

124 Commits

Author SHA1 Message Date
J-Jamet
7182c2e66d Merge branch 'release/2.5RC1' 2020-04-12 20:32:03 +02:00
J-Jamet
503316bc70 Fix navigation bar color for light theme 2020-04-12 20:08:39 +02:00
J-Jamet
d5af59f2c7 Merge branch 'translations' into release/2.5RC1 2020-04-12 20:03:44 +02:00
J-Jamet
cb3ac1ad3a version 2.5RC1 2020-04-12 19:36:51 +02:00
J-Jamet
e161080e4c Fix special button 2020-04-11 17:36:24 +02:00
J-Jamet
ceab7f917b Upgrade CHANGELOG 2020-04-11 16:21:27 +02:00
J-Jamet
41d8066c4c Fix autofill bad recognition for key-value format #513 2020-04-11 16:16:50 +02:00
J-Jamet
e373cbd776 File manager explanation link 2020-04-11 12:23:46 +02:00
J-Jamet
05ea6b6b10 Change background color and fix bottom button 2020-04-10 20:37:56 +02:00
J-Jamet
28eed3ae71 New file selection layout 2020-04-10 20:15:08 +02:00
Mert Sezer
535c67ac9b Translated using Weblate (Turkish)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-10 16:09:45 +02:00
J-Jamet
68027a6e15 Linkfy notes #426 2020-04-10 13:22:26 +02:00
J-Jamet
12dea6b499 Add new autofill hint for username 2020-04-10 12:32:38 +02:00
J-Jamet
d8bd078a02 Fix custom fields duplication #257 2020-04-10 11:32:23 +02:00
J-Jamet
439bc109b0 Update CHANGELOG 2020-04-09 21:42:16 +02:00
J-Jamet
b1ec93ceb5 Add navigation bar color #510 2020-04-09 21:38:32 +02:00
J-Jamet
44b9aa0e48 Style black as separate file 2020-04-09 21:31:48 +02:00
J-Jamet
0a59063027 Add scrollbar in nodes list 2020-04-09 20:33:12 +02:00
Oğuz Ersen
5db4608abd Translated using Weblate (Turkish)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-09 06:45:37 +02:00
J-Jamet
6ece2aa6cb Add autofill web domain and app id 2020-04-08 20:50:28 +02:00
J-Jamet
95ee45f666 Merge branch 'feature/Autofill_Domain' into develop 2020-04-08 17:55:42 +02:00
J-Jamet
556e90b8d8 Fix autofill response 2020-04-08 17:17:29 +02:00
J-Jamet
42841e6247 Setting for autofill automatic search 2020-04-08 16:55:30 +02:00
J-Jamet
324c82248a Refactor magikeyboard settings and add autofill settings 2020-04-08 15:44:14 +02:00
J-Jamet
94f5a47918 Catch exception during autofill parse 2020-04-08 14:11:18 +02:00
J-Jamet
3f70990956 Better autofill workflow and add autofill icon for each entry 2020-04-08 13:02:15 +02:00
J-Jamet
d77635e572 Fix autofill auto search 2020-04-07 21:01:26 +02:00
solokot
0f26f1b751 Translated using Weblate (Russian)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2020-04-07 01:36:50 +02:00
J-Jamet
456bc22138 Encapsulate search methods and search without UI 2020-04-06 21:43:55 +02:00
J-Jamet
b6fe91e396 Fix small warning 2020-04-06 21:36:50 +02:00
J-Jamet
0fb4d26949 Add auto search info 2020-04-06 17:36:51 +02:00
J-Jamet
3b3583a416 Retrieve application id and domain 2020-04-06 11:41:16 +02:00
J-Jamet
cac1d576c8 Upgrade Autofill algorithm 2020-04-06 10:33:44 +02:00
J-Jamet
9cba0d0a48 Message to indicate file revoked 2020-04-06 10:12:09 +02:00
J-Jamet
3bf11e9dc0 Remove unused import 2020-04-06 09:41:02 +02:00
Fabio Iacovino
edbb160ac6 Translated using Weblate (Italian)
Currently translated at 90.4% (388 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-04-06 00:22:25 +02:00
WaldiS
ee111dc63c Translated using Weblate (Polish)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2020-04-05 17:58:26 +02:00
Filippo De Bortoli
b06edb756a Translated using Weblate (Italian)
Currently translated at 89.7% (385 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-04-05 17:13:40 +02:00
anonymous
fd745494e0 Translated using Weblate (Italian)
Currently translated at 89.7% (385 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-04-05 17:13:40 +02:00
Fabio Iacovino
702bf3f479 Translated using Weblate (Italian)
Currently translated at 89.7% (385 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-04-05 17:13:40 +02:00
Fabio Iacovino
6adc02a91f Translated using Weblate (Italian)
Currently translated at 85.3% (366 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-04-05 17:07:29 +02:00
anonymous
55bae5a130 Translated using Weblate (Italian)
Currently translated at 85.3% (366 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-04-05 17:07:29 +02:00
Filippo De Bortoli
1aae817b17 Translated using Weblate (Italian)
Currently translated at 85.3% (366 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-04-05 17:07:29 +02:00
Oğuz Ersen
8afc8c23fb Translated using Weblate (Turkish)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-05 03:01:39 +02:00
Allan Nordhøy
36e473b139 Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.6% (329 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nb_NO/
2020-04-05 03:01:38 +02:00
Allan Nordhøy
e529723f86 Translated using Weblate (English)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/en/
2020-04-05 03:01:38 +02:00
Dwhite Reeves
6c5112c142 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2020-04-05 03:01:38 +02:00
Allan Nordhøy
77ac68a603 Translated using Weblate (Dutch)
Currently translated at 77.6% (333 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nl/
2020-04-05 03:01:37 +02:00
Éfrit
e816f40872 Translated using Weblate (French)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2020-04-05 03:01:37 +02:00
zeritti
65313f114b Translated using Weblate (Czech)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2020-04-05 03:01:37 +02:00
J-Jamet
ef1f1342f5 Upgrade CHANGELOG 2020-04-04 18:49:22 +02:00
J-Jamet
9205fe6c08 Merge branch 'feature/Lock_Button' into develop 2020-04-04 18:43:03 +02:00
J-Jamet
75df3e81fe Fix style 2020-04-04 18:42:35 +02:00
J-Jamet
47fffbadb5 Setting to show the lock button 2020-04-04 18:25:48 +02:00
J-Jamet
78354473fa Fix lock button color and education screen 2020-04-04 17:53:04 +02:00
J-Jamet
8d7efb44b5 Change lock button color 2020-04-03 22:21:50 +02:00
J-Jamet
cab00b3d8c Change lock button color 2020-04-03 22:18:33 +02:00
Mert Sezer
8efab01336 Translated using Weblate (Turkish)
Currently translated at 99.5% (427 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-03 21:41:26 +02:00
Oğuz Ersen
66feb8beb4 Translated using Weblate (Turkish)
Currently translated at 99.5% (427 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-03 21:41:26 +02:00
Mert Sezer
ca4cccffeb Translated using Weblate (Turkish)
Currently translated at 99.3% (426 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-03 21:40:34 +02:00
Oğuz Ersen
51b1760c50 Translated using Weblate (Turkish)
Currently translated at 99.3% (426 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-03 21:40:33 +02:00
J-Jamet
42e1bda365 Change lock button color 2020-04-03 21:32:32 +02:00
J-Jamet
194b6b557a Add lock button elevation and border 2020-04-03 21:17:38 +02:00
Dwhite Reeves
e7bc439997 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2020-04-03 15:44:41 +02:00
Allan Nordhøy
ef76cce0ac Translated using Weblate (Romanian)
Currently translated at 95.3% (409 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ro/
2020-04-03 13:26:34 +02:00
Allan Nordhøy
63eec6d969 Translated using Weblate (Turkish)
Currently translated at 96.9% (416 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-03 13:26:34 +02:00
WaldiS
719ae74c06 Translated using Weblate (Polish)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/pl/
2020-04-03 13:26:33 +02:00
Mert Sezer
37cf424eb8 Translated using Weblate (Turkish)
Currently translated at 96.9% (416 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-01 17:46:51 +02:00
anonymous
3a87f7ba9d Translated using Weblate (Turkish)
Currently translated at 96.9% (416 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/tr/
2020-04-01 17:46:50 +02:00
J-Jamet
275428d825 First commit for new lock button 2020-04-01 14:57:31 +02:00
Pavel Borecki
7b9dac86ca Translated using Weblate (Czech)
Currently translated at 96.7% (415 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/cs/
2020-04-01 03:28:42 +02:00
J-Jamet
46496ee2cc Merge branch 'damoasda-translation-update' into develop 2020-03-31 21:58:21 +02:00
J-Jamet
110cc402cc Add keyfile selection view 2020-03-31 21:48:51 +02:00
J-Jamet
587f006259 Long click to use GET_CONTENT 2020-03-31 19:46:43 +02:00
Moasda
ec45c0df81 Translated using Weblate (German)
Currently translated at 99.7% (428 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-30 22:24:51 +02:00
jan madsen
dc575aeca4 Translated using Weblate (Danish)
Currently translated at 98.3% (422 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/da/
2020-03-30 22:24:51 +02:00
Herbert Reiter
a3f790f000 Fix inconsistencies with translation arguments (e.g. %1$s), escape % character 2020-03-30 22:08:50 +02:00
Herbert Reiter
4e9e188d02 Add and fix German translations 2020-03-30 22:03:09 +02:00
J-Jamet
abb17efae4 Merge branch 'feature/File_Manager_Access' into develop 2020-03-30 18:17:24 +02:00
Hosted Weblate
16be990502 Merge branch 'origin/master' into Weblate. 2020-03-30 08:48:35 +02:00
anonymous
d1a496f9a3 Translated using Weblate (German)
Currently translated at 99.7% (428 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-30 03:17:18 +02:00
Allan Nordhøy
cd730fcfef Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.9% (330 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/nb_NO/
2020-03-29 23:06:21 +02:00
Moasda
1b65bf665b Translated using Weblate (German)
Currently translated at 99.7% (428 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-29 23:06:21 +02:00
J-Jamet
6f4735790c Fix autofill for Android app #502 2020-03-29 22:00:24 +02:00
J-Jamet
040666f89d Merge branch 'develop' of github.com:Kunzisoft/KeePassDX into develop 2020-03-29 20:19:42 +02:00
J-Jamet
227cb800c3 Merge branch 'damoasda-readme-fix' 2020-03-29 16:15:44 +02:00
Herbert Reiter
0052569a14 Fix FAQ link to wiki page 2020-03-29 15:41:49 +02:00
J-Jamet
f7561c4888 Upgrade to version 2.5beta31 2020-03-29 15:22:34 +02:00
Destiny Li
92200f19e7 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/zh_Hans/
2020-03-29 14:09:36 +02:00
Éfrit
4c01f18a62 Translated using Weblate (French)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/fr/
2020-03-29 14:09:36 +02:00
anonymous
a6ce3e49fe Translated using Weblate (German)
Currently translated at 99.5% (427 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-29 14:09:36 +02:00
Oliver
1b3a5d1bf6 Translated using Weblate (German)
Currently translated at 99.5% (427 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-29 14:09:35 +02:00
J-Jamet
db7bdc63c8 Fix #501 2020-03-28 18:13:09 +01:00
J-Jamet
7aca550f02 Merge branch 'develop' into feature/File_Manager_Access 2020-03-28 17:47:14 +01:00
J-Jamet
b60980b3fd Upgrade to 2.5beta31 2020-03-28 17:46:50 +01:00
J-Jamet
b578c2c584 Add write permission 2020-03-28 17:30:57 +01:00
solokot
fc45bd624e Translated using Weblate (Russian)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2020-03-27 20:06:43 +01:00
anonymous
17be3d9d2c Translated using Weblate (Russian)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2020-03-27 20:03:48 +01:00
solokot
5b3a38a7bc Translated using Weblate (Russian)
Currently translated at 100.0% (429 of 429 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/ru/
2020-03-27 20:03:47 +01:00
Hosted Weblate
4403835d50 Merge branch 'origin/master' into Weblate. 2020-03-27 18:36:55 +01:00
C. Rüdinger
b7a3d3eb46 Translated using Weblate (German)
Currently translated at 99.5% (424 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-27 18:36:54 +01:00
J-Jamet
29846b22fe Merge tag '2.5beta30' into develop
2.5beta30
2020-03-27 18:13:28 +01:00
J-Jamet
32d235e8c7 Merge branch 'release/2.5beta30' 2020-03-27 18:13:21 +01:00
J-Jamet
cb982b3513 Fix strong tag 2020-03-27 17:53:42 +01:00
J-Jamet
d7ed6c26dd Merge branch 'develop' into translations 2020-03-27 17:49:29 +01:00
J-Jamet
8ff19f7e68 First string pass according to #460 2020-03-27 17:43:31 +01:00
J-Jamet
729e062c3a Add error when create database file 2020-03-27 17:12:54 +01:00
J-Jamet
7d0340ac07 Upgrade CHANGELOG 2020-03-27 16:57:35 +01:00
J-Jamet
01960e74c1 Fix check file ANR #494 2020-03-27 16:36:57 +01:00
anonymous
8e40250985 Translated using Weblate (German)
Currently translated at 96.4% (411 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-27 00:46:37 +01:00
C. Rüdinger
8ae2edb61a Translated using Weblate (German)
Currently translated at 96.4% (411 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-27 00:46:37 +01:00
J-Jamet
0baa7bcbf1 Change discard button 2020-03-26 16:36:17 +01:00
J-Jamet
fffee48918 Upgrade version to 2.5beta30 2020-03-26 14:50:20 +01:00
J-Jamet
515abb6e14 Better UUID view 2020-03-26 14:45:51 +01:00
J-Jamet
6c1c3ff87f New method to wait 1.5 seconds after screen turns off 2020-03-26 13:38:20 +01:00
J-Jamet
5b65575c7a Add comment to ignore autocomplete off 2020-03-26 12:57:24 +01:00
J-Jamet
0f258fc5f8 Upgrade autofill algorithm 2020-03-26 12:47:32 +01:00
anonymous
206bc661dc Translated using Weblate (German)
Currently translated at 96.2% (410 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/de/
2020-03-25 23:44:32 +01:00
J-Jamet
d0e35b109e Revert : Fix Nextcloud File Upload conflict #497 2020-03-25 22:48:15 +01:00
J-Jamet
61769c4f20 Fix Nextcloud File Upload conflict #497 2020-03-25 21:07:36 +01:00
Hosted Weblate
95778ee5f4 Merge branch 'origin/master' into Weblate. 2020-03-25 12:21:35 +01:00
anonymous
155030fdca Translated using Weblate (Italian)
Currently translated at 79.5% (339 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-03-25 12:21:35 +01:00
Filippo De Bortoli
98237ef76c Translated using Weblate (Italian)
Currently translated at 79.5% (339 of 426 strings)

Translation: KeePass DX/Strings
Translate-URL: https://hosted.weblate.org/projects/keepass-dx/strings/it/
2020-03-25 12:21:34 +01:00
J-Jamet
f0a7b38199 Merge tag '2.5beta29' into develop
2.5beta29
2020-03-25 12:06:20 +01:00
116 changed files with 2020 additions and 1025 deletions

View File

@@ -1,3 +1,19 @@
KeePassDX(2.5beta31)
* Add write permission to keep compatibility with old file managers
* Fix autofill for apps
* Auto search for autofill
* New keyfile input
* Icon to hide keyfile input
* New lock button
* Setting to hide lock button in user interface
* Clickable links in notes
* Fix autofill for key-value pairs
KeePassDX(2.5beta30)
* Fix Lock after screen off (wait 1.5 seconds)
* Upgrade autofill algorithm
* Fix ANR during file verifications
KeePassDX(2.5beta29)
* Upgrade autofill algorithm
* Delete registered KeyFile after save new credentials

View File

@@ -53,9 +53,9 @@ You can contribute in different ways to help us on our work.
alt="Get it on Google Play"
height="80">](https://play.google.com/store/apps/details?id=com.kunzisoft.keepass.free)
## F.A.Q.
## Frequently Asked Questions
Other questions? You can read the [F.A.Q.](https://github.com/Kunzisoft/KeePassDX/wiki/F.A.Q.)
Other questions? You can read the [FAQ](https://github.com/Kunzisoft/KeePassDX/wiki/FAQ)
## Other devices

View File

@@ -11,8 +11,8 @@ android {
applicationId "com.kunzisoft.keepass"
minSdkVersion 14
targetSdkVersion 29
versionCode = 29
versionName = "2.5beta29"
versionCode = 31
versionName = "2.5RC1"
multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests"
@@ -97,6 +97,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.biometric:biometric:1.0.1'
implementation "androidx.core:core-ktx:1.2.0"
// To upgrade with style
implementation 'com.google.android.material:material:1.0.0'

View File

@@ -15,7 +15,6 @@
<uses-permission
android:name="android.permission.VIBRATE"/>
<uses-permission
android:maxSdkVersion="18"
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
@@ -138,12 +137,12 @@
<activity android:name="com.kunzisoft.keepass.autofill.AutofillLauncherActivity"
android:configChanges="keyboardHidden" />
<activity android:name="com.kunzisoft.keepass.settings.SettingsAdvancedUnlockActivity" />
<activity android:name="com.kunzisoft.keepass.settings.SettingsAutofillActivity" />
<activity android:name="com.kunzisoft.keepass.settings.AutofillSettingsActivity" />
<activity android:name="com.kunzisoft.keepass.magikeyboard.KeyboardLauncherActivity"
android:label="@string/keyboard_name"
android:exported="true">
</activity>
<activity android:name="com.kunzisoft.keepass.settings.MagikIMESettings"
<activity android:name="com.kunzisoft.keepass.settings.MagikeyboardSettingsActivity"
android:label="@string/keyboard_setting_label">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

View File

@@ -52,7 +52,6 @@ import com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_DELETE_ENTRY_HISTORY
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_RESTORE_ENTRY_HISTORY
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.settings.SettingsAutofillActivity
import com.kunzisoft.keepass.tasks.AttachmentFileBinderManager
import com.kunzisoft.keepass.timeout.ClipboardHelper
import com.kunzisoft.keepass.timeout.TimeoutHelper
@@ -73,6 +72,7 @@ class EntryActivity : LockingActivity() {
private var historyView: View? = null
private var entryContentsView: EntryContentsView? = null
private var entryProgress: ProgressBar? = null
private var lockView: View? = null
private var toolbar: Toolbar? = null
private var mDatabase: Database? = null
@@ -124,6 +124,11 @@ class EntryActivity : LockingActivity() {
entryContentsView = findViewById(R.id.entry_contents)
entryContentsView?.applyFontVisibilityToFields(PreferencesUtil.fieldFontIsInVisibility(this))
entryProgress = findViewById(R.id.entry_progress)
lockView = findViewById(R.id.lock_button)
lockView?.setOnClickListener {
lockAndExit()
}
// Init the clipboard helper
clipboardHelper = ClipboardHelper(this)
@@ -148,6 +153,13 @@ class EntryActivity : LockingActivity() {
override fun onResume() {
super.onResume()
// Show the lock button
lockView?.visibility = if (PreferencesUtil.showLockDatabaseButton(this)) {
View.VISIBLE
} else {
View.GONE
}
// Get Entry from UUID
try {
val keyEntry: NodeId<UUID>? = intent.getParcelableExtra(KEY_ENTRY)
@@ -462,8 +474,7 @@ class EntryActivity : LockingActivity() {
getString(R.string.entry_user_name)))
},
{
// Launch autofill settings
startActivity(Intent(this@EntryActivity, SettingsAutofillActivity::class.java))
performedNextEducation(entryActivityEducation, menu)
})
if (!entryCopyEducationPerformed) {
@@ -526,10 +537,6 @@ class EntryActivity : LockingActivity() {
!mReadOnly && mAutoSaveEnable)
}
}
R.id.menu_lock -> {
lockAndExit()
return true
}
R.id.menu_save_database -> {
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
}

View File

@@ -81,6 +81,7 @@ class EntryEditActivity : LockingActivity(),
private var entryEditContentsView: EntryEditContentsView? = null
private var entryEditAddToolBar: ActionMenuView? = null
private var saveView: View? = null
private var lockView: View? = null
// Education
private var entryEditActivityEducation: EntryEditActivityEducation? = null
@@ -112,6 +113,12 @@ class EntryEditActivity : LockingActivity(),
.show(supportFragmentManager, "DatePickerFragment")
}
}
lockView = findViewById(R.id.lock_button)
lockView?.setOnClickListener {
lockAndExit()
}
// Focus view to reinitialize timeout
resetAppTimeoutWhenViewFocusedOrChanged(entryEditContentsView)
@@ -241,6 +248,16 @@ class EntryEditActivity : LockingActivity(),
}
}
override fun onResume() {
super.onResume()
lockView?.visibility = if (PreferencesUtil.showLockDatabaseButton(this)) {
View.VISIBLE
} else {
View.GONE
}
}
private fun populateViewsWithEntry(newEntry: Entry) {
// Don't start the field reference manager, we want to see the raw ref
mDatabase?.stopManageEntry(newEntry)
@@ -416,10 +433,6 @@ class EntryEditActivity : LockingActivity(),
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_lock -> {
lockAndExit()
return true
}
R.id.menu_save_database -> {
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
}
@@ -509,7 +522,7 @@ class EntryEditActivity : LockingActivity(),
AlertDialog.Builder(this)
.setMessage(R.string.discard_changes)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok) { _, _ ->
.setPositiveButton(R.string.discard) { _, _ ->
super@EntryEditActivity.onBackPressed()
}.create().show()
}

View File

@@ -26,15 +26,14 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator
@@ -47,9 +46,11 @@ import com.kunzisoft.keepass.activities.stylish.StylishActivity
import com.kunzisoft.keepass.adapters.FileDatabaseHistoryAdapter
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.autofill.AutofillHelper.KEY_SEARCH_INFO
import com.kunzisoft.keepass.database.action.ProgressDialogThread
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.education.FileDatabaseSelectActivityEducation
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_TASK
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.utils.*
@@ -61,7 +62,8 @@ class FileDatabaseSelectActivity : StylishActivity(),
AssignMasterKeyDialogFragment.AssignPasswordDialogListener {
// Views
private var fileListContainer: View? = null
private var coordinatorLayout: CoordinatorLayout? = null
private var fileManagerExplanationButton: View? = null
private var createButtonView: View? = null
private var openDatabaseButtonView: View? = null
@@ -82,12 +84,17 @@ class FileDatabaseSelectActivity : StylishActivity(),
mFileDatabaseHistoryAction = FileDatabaseHistoryAction.getInstance(applicationContext)
setContentView(R.layout.activity_file_selection)
fileListContainer = findViewById(R.id.container_file_list)
coordinatorLayout = findViewById(R.id.activity_file_selection_coordinator_layout)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
toolbar.title = ""
setSupportActionBar(toolbar)
fileManagerExplanationButton = findViewById(R.id.file_manager_explanation_button)
fileManagerExplanationButton?.setOnClickListener {
UriUtil.gotoUrl(this, R.string.file_manager_explanation_url)
}
// Create button
createButtonView = findViewById(R.id.create_database_button)
if (allowCreateDocumentByStorageAccessFramework(packageManager)) {
@@ -102,8 +109,13 @@ class FileDatabaseSelectActivity : StylishActivity(),
createButtonView?.setOnClickListener { createNewFile() }
mOpenFileHelper = OpenFileHelper(this)
openDatabaseButtonView = findViewById(R.id.open_database_button)
openDatabaseButtonView?.setOnClickListener(mOpenFileHelper?.openFileOnClickViewListener)
openDatabaseButtonView = findViewById(R.id.open_keyfile_button)
openDatabaseButtonView?.apply {
mOpenFileHelper?.openFileOnClickViewListener?.let {
setOnClickListener(it)
setOnLongClickListener(it)
}
}
// History list
val fileDatabaseHistoryRecyclerView = findViewById<RecyclerView>(R.id.file_list)
@@ -118,7 +130,6 @@ class FileDatabaseSelectActivity : StylishActivity(),
databaseFileUri,
UriUtil.parse(fileDatabaseHistoryEntityToOpen.keyFileUri))
}
updateFileListVisibility()
}
mAdapterDatabaseHistory?.setOnFileDatabaseHistoryDeleteListener { fileDatabaseHistoryToDelete ->
// Remove from app database
@@ -127,7 +138,6 @@ class FileDatabaseSelectActivity : StylishActivity(),
fileHistoryDeleted?.let { databaseFileHistoryDeleted ->
mAdapterDatabaseHistory?.deleteDatabaseFileHistory(databaseFileHistoryDeleted)
mAdapterDatabaseHistory?.notifyDataSetChanged()
updateFileListVisibility()
}
}
true
@@ -179,7 +189,9 @@ class FileDatabaseSelectActivity : StylishActivity(),
private fun fileNoFoundAction(e: FileNotFoundException) {
val error = getString(R.string.file_not_found_content)
Snackbar.make(activity_file_selection_coordinator_layout, error, Snackbar.LENGTH_LONG).asError().show()
coordinatorLayout?.let {
Snackbar.make(it, error, Snackbar.LENGTH_LONG).asError().show()
}
Log.e(TAG, error, e)
}
@@ -207,7 +219,8 @@ class FileDatabaseSelectActivity : StylishActivity(),
try {
PasswordActivity.launchForAutofillResult(this@FileDatabaseSelectActivity,
databaseUri, keyFile,
assistStructure)
assistStructure,
intent.getParcelableExtra(KEY_SEARCH_INFO))
} catch (e: FileNotFoundException) {
fileNoFoundAction(e)
}
@@ -219,16 +232,21 @@ class FileDatabaseSelectActivity : StylishActivity(),
private fun launchGroupActivity(readOnly: Boolean) {
EntrySelectionHelper.doEntrySelectionAction(intent,
{
GroupActivity.launch(this@FileDatabaseSelectActivity, readOnly)
GroupActivity.launch(this@FileDatabaseSelectActivity,
readOnly)
},
{
GroupActivity.launchForKeyboardSelection(this@FileDatabaseSelectActivity, readOnly)
GroupActivity.launchForKeyboardSelection(this@FileDatabaseSelectActivity,
readOnly)
// Do not keep history
finish()
},
{ assistStructure ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
GroupActivity.launchForAutofillResult(this@FileDatabaseSelectActivity, assistStructure, readOnly)
GroupActivity.launchForAutofillResult(this@FileDatabaseSelectActivity,
assistStructure,
intent.getParcelableExtra(KEY_SEARCH_INFO),
readOnly)
}
})
}
@@ -240,25 +258,6 @@ class FileDatabaseSelectActivity : StylishActivity(),
overridePendingTransition(0, 0)
}
private fun updateExternalStorageWarning() {
// To show errors
var warning = -1
val state = Environment.getExternalStorageState()
if (state == Environment.MEDIA_MOUNTED_READ_ONLY) {
warning = R.string.read_only_warning
} else if (state != Environment.MEDIA_MOUNTED) {
warning = R.string.warning_unmounted
}
val labelWarningView = findViewById<TextView>(R.id.label_warning)
if (warning != -1) {
labelWarningView.setText(warning)
labelWarningView.visibility = View.VISIBLE
} else {
labelWarningView.visibility = View.INVISIBLE
}
}
override fun onResume() {
val database = Database.getInstance()
if (database.loaded) {
@@ -267,8 +266,6 @@ class FileDatabaseSelectActivity : StylishActivity(),
super.onResume()
updateExternalStorageWarning()
// Construct adapter with listeners
if (PreferencesUtil.showRecentFiles(this)) {
mFileDatabaseHistoryAction?.getAllFileDatabaseHistories { databaseFileHistoryList ->
@@ -278,20 +275,17 @@ class FileDatabaseSelectActivity : StylishActivity(),
// Show only uri accessible
historyList.filter {
if (hideBrokenLocations) {
UriUtil.parse(it.databaseUri)?.let { historyUri ->
UriUtil.isUriAccessible(contentResolver, historyUri)
} ?: false
FileDatabaseInfo(this@FileDatabaseSelectActivity,
it.databaseUri).exists
} else
true
})
mAdapterDatabaseHistory?.notifyDataSetChanged()
updateFileListVisibility()
}
}
} else {
mAdapterDatabaseHistory?.clearDatabaseFileHistoryList()
mAdapterDatabaseHistory?.notifyDataSetChanged()
updateFileListVisibility()
}
// Register progress task
@@ -313,13 +307,6 @@ class FileDatabaseSelectActivity : StylishActivity(),
outState.putParcelable(EXTRA_DATABASE_URI, mDatabaseFileUri)
}
private fun updateFileListVisibility() {
if (mAdapterDatabaseHistory?.itemCount == 0)
fileListContainer?.visibility = View.INVISIBLE
else
fileListContainer?.visibility = View.VISIBLE
}
override fun onAssignKeyDialogPositiveClick(
masterPasswordChecked: Boolean, masterPassword: String?,
keyFileChecked: Boolean, keyFile: Uri?) {
@@ -369,10 +356,13 @@ class FileDatabaseSelectActivity : StylishActivity(),
if (mDatabaseFileUri != null) {
AssignMasterKeyDialogFragment.getInstance(true)
.show(supportFragmentManager, "passwordDialog")
} else {
val error = getString(R.string.error_create_database)
coordinatorLayout?.let {
Snackbar.make(it, error, Snackbar.LENGTH_LONG).asError().show()
}
Log.e(TAG, error)
}
// else {
// TODO Show error
// }
}
}
@@ -447,10 +437,13 @@ class FileDatabaseSelectActivity : StylishActivity(),
*/
@RequiresApi(api = Build.VERSION_CODES.O)
fun launchForAutofillResult(activity: Activity, assistStructure: AssistStructure) {
fun launchForAutofillResult(activity: Activity,
assistStructure: AssistStructure,
searchInfo: SearchInfo?) {
AutofillHelper.startActivityForAutofillResult(activity,
Intent(activity, FileDatabaseSelectActivity::class.java),
assistStructure)
assistStructure,
searchInfo)
}
}
}

View File

@@ -62,6 +62,7 @@ import com.kunzisoft.keepass.database.element.node.Type
import com.kunzisoft.keepass.education.GroupActivityEducation
import com.kunzisoft.keepass.icons.assignDatabaseIcon
import com.kunzisoft.keepass.magikeyboard.MagikIME
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_COPY_NODES_TASK
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_GROUP_TASK
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_DELETE_NODES_TASK
@@ -89,6 +90,7 @@ class GroupActivity : LockingActivity(),
// Views
private var coordinatorLayout: CoordinatorLayout? = null
private var lockView: View? = null
private var toolbar: Toolbar? = null
private var searchTitleView: View? = null
private var toolbarAction: ToolbarAction? = null
@@ -134,6 +136,11 @@ class GroupActivity : LockingActivity(),
groupNameView = findViewById(R.id.group_name)
toolbarAction = findViewById(R.id.toolbar_action)
modeTitleView = findViewById(R.id.mode_title_view)
lockView = findViewById(R.id.lock_button)
lockView?.setOnClickListener {
lockAndExit()
}
toolbar?.title = ""
setSupportActionBar(toolbar)
@@ -347,7 +354,7 @@ class GroupActivity : LockingActivity(),
// If it's a search
if (Intent.ACTION_SEARCH == intent.action) {
val searchString = intent.getStringExtra(SearchManager.QUERY)?.trim { it <= ' ' } ?: ""
return mDatabase?.search(searchString)
return mDatabase?.createVirtualGroupFromSearch(searchString)
}
// else a real group
else {
@@ -486,7 +493,7 @@ class GroupActivity : LockingActivity(),
// Build response with the entry selected
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && mDatabase != null) {
mDatabase?.let { database ->
AutofillHelper.buildResponseWhenEntrySelected(this@GroupActivity,
AutofillHelper.buildResponse(this@GroupActivity,
entryVersioned.getEntryInfo(database))
}
}
@@ -632,6 +639,13 @@ class GroupActivity : LockingActivity(),
override fun onResume() {
super.onResume()
// Show the lock button
lockView?.visibility = if (PreferencesUtil.showLockDatabaseButton(this)) {
View.VISIBLE
} else {
View.GONE
}
// Refresh the elements
assignGroupViewElements()
// Refresh suggestions to change preferences
@@ -753,12 +767,11 @@ class GroupActivity : LockingActivity(),
if (!sortMenuEducationPerformed) {
// lockMenuEducationPerformed
toolbar != null
&& toolbar!!.findViewById<View>(R.id.menu_lock) != null
&& groupActivityEducation.checkAndPerformedLockMenuEducation(
toolbar!!.findViewById(R.id.menu_lock),
val lockButtonView = findViewById<View>(R.id.lock_button_icon)
lockButtonView != null
&& groupActivityEducation.checkAndPerformedLockMenuEducation(lockButtonView,
{
onOptionsItemSelected(menu.findItem(R.id.menu_lock))
lockAndExit()
},
{
performedNextEducation(groupActivityEducation, menu)
@@ -777,10 +790,6 @@ class GroupActivity : LockingActivity(),
R.id.menu_search ->
//onSearchRequested();
return true
R.id.menu_lock -> {
lockAndExit()
return true
}
R.id.menu_save_database -> {
mProgressDialogThread?.startDatabaseSave(!mReadOnly)
return true
@@ -956,27 +965,41 @@ class GroupActivity : LockingActivity(),
private const val SEARCH_FRAGMENT_TAG = "SEARCH_FRAGMENT_TAG"
private const val OLD_GROUP_TO_UPDATE_KEY = "OLD_GROUP_TO_UPDATE_KEY"
private fun buildIntent(context: Context, group: Group?, readOnly: Boolean,
private fun buildIntent(context: Context,
group: Group?,
searchInfo: SearchInfo?,
readOnly: Boolean,
intentBuildLauncher: (Intent) -> Unit) {
val intent = Intent(context, GroupActivity::class.java)
if (group != null) {
intent.putExtra(GROUP_ID_KEY, group.nodeId)
}
if (searchInfo != null) {
intent.action = Intent.ACTION_SEARCH
val searchQuery = searchInfo.webDomain ?: searchInfo.applicationId
intent.putExtra(SearchManager.QUERY, searchQuery)
}
ReadOnlyHelper.putReadOnlyInIntent(intent, readOnly)
intentBuildLauncher.invoke(intent)
}
private fun checkTimeAndBuildIntent(activity: Activity, group: Group?, readOnly: Boolean,
private fun checkTimeAndBuildIntent(activity: Activity,
group: Group?,
searchInfo: SearchInfo?,
readOnly: Boolean,
intentBuildLauncher: (Intent) -> Unit) {
if (TimeoutHelper.checkTimeAndLockIfTimeout(activity)) {
buildIntent(activity, group, readOnly, intentBuildLauncher)
buildIntent(activity, group, searchInfo, readOnly, intentBuildLauncher)
}
}
private fun checkTimeAndBuildIntent(context: Context, group: Group?, readOnly: Boolean,
private fun checkTimeAndBuildIntent(context: Context,
group: Group?,
searchInfo: SearchInfo?,
readOnly: Boolean,
intentBuildLauncher: (Intent) -> Unit) {
if (TimeoutHelper.checkTime(context)) {
buildIntent(context, group, readOnly, intentBuildLauncher)
buildIntent(context, group, searchInfo, readOnly, intentBuildLauncher)
}
}
@@ -985,11 +1008,9 @@ class GroupActivity : LockingActivity(),
* Standard Launch
* -------------------------
*/
@JvmOverloads
fun launch(context: Context,
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
checkTimeAndBuildIntent(context, null, null, readOnly) { intent ->
context.startActivity(intent)
}
}
@@ -1000,10 +1021,9 @@ class GroupActivity : LockingActivity(),
* -------------------------
*/
// TODO implement pre search to directly open the direct group
fun launchForKeyboardSelection(context: Context,
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(context)) {
checkTimeAndBuildIntent(context, null, readOnly) { intent ->
checkTimeAndBuildIntent(context, null, null, readOnly) { intent ->
EntrySelectionHelper.startActivityForEntrySelection(context, intent)
}
}
@@ -1013,14 +1033,13 @@ class GroupActivity : LockingActivity(),
* Autofill Launch
* -------------------------
*/
// TODO implement pre search to directly open the direct group
@RequiresApi(api = Build.VERSION_CODES.O)
fun launchForAutofillResult(activity: Activity,
assistStructure: AssistStructure,
searchInfo: SearchInfo? = null,
readOnly: Boolean = PreferencesUtil.enableReadOnlyDatabase(activity)) {
checkTimeAndBuildIntent(activity, null, readOnly) { intent ->
AutofillHelper.startActivityForAutofillResult(activity, intent, assistStructure)
checkTimeAndBuildIntent(activity, null, searchInfo, readOnly) { intent ->
AutofillHelper.startActivityForAutofillResult(activity, intent, assistStructure, searchInfo)
}
}
}

View File

@@ -23,6 +23,7 @@ import android.app.Activity
import android.app.assist.AssistStructure
import android.app.backup.BackupManager
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -32,13 +33,11 @@ import android.text.TextWatcher
import android.util.Log
import android.view.*
import android.view.inputmethod.EditorInfo.IME_ACTION_DONE
import android.widget.Button
import android.widget.CompoundButton
import android.widget.EditText
import android.widget.TextView
import android.widget.*
import androidx.annotation.RequiresApi
import androidx.appcompat.widget.Toolbar
import androidx.biometric.BiometricManager
import androidx.core.app.ActivityCompat
import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.DuplicateUuidDialog
@@ -50,11 +49,13 @@ import com.kunzisoft.keepass.activities.stylish.StylishActivity
import com.kunzisoft.keepass.app.database.CipherDatabaseEntity
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.autofill.AutofillHelper.KEY_SEARCH_INFO
import com.kunzisoft.keepass.biometric.AdvancedUnlockedManager
import com.kunzisoft.keepass.database.action.ProgressDialogThread
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.exception.DuplicateUuidDatabaseException
import com.kunzisoft.keepass.education.PasswordActivityEducation
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_LOAD_TASK
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.CIPHER_ENTITY_KEY
import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.DATABASE_URI_KEY
@@ -66,6 +67,7 @@ import com.kunzisoft.keepass.utils.FileDatabaseInfo
import com.kunzisoft.keepass.utils.MenuUtil
import com.kunzisoft.keepass.utils.UriUtil
import com.kunzisoft.keepass.view.AdvancedUnlockInfoView
import com.kunzisoft.keepass.view.KeyFileSelectionView
import com.kunzisoft.keepass.view.asError
import kotlinx.android.synthetic.main.activity_password.*
import java.io.FileNotFoundException
@@ -77,7 +79,7 @@ open class PasswordActivity : StylishActivity() {
private var containerView: View? = null
private var filenameView: TextView? = null
private var passwordView: EditText? = null
private var keyFileView: EditText? = null
private var keyFileSelectionView: KeyFileSelectionView? = null
private var confirmButtonView: Button? = null
private var checkboxPasswordView: CompoundButton? = null
private var checkboxKeyFileView: CompoundButton? = null
@@ -92,6 +94,7 @@ open class PasswordActivity : StylishActivity() {
private var mRememberKeyFile: Boolean = false
private var mOpenFileHelper: OpenFileHelper? = null
private var mPermissionAsked = false
private var readOnly: Boolean = false
private var mForceReadOnly: Boolean = false
set(value) {
@@ -123,18 +126,23 @@ open class PasswordActivity : StylishActivity() {
confirmButtonView = findViewById(R.id.activity_password_open_button)
filenameView = findViewById(R.id.filename)
passwordView = findViewById(R.id.password)
keyFileView = findViewById(R.id.pass_keyfile)
keyFileSelectionView = findViewById(R.id.keyfile_selection)
checkboxPasswordView = findViewById(R.id.password_checkbox)
checkboxKeyFileView = findViewById(R.id.keyfile_checkox)
checkboxDefaultDatabaseView = findViewById(R.id.default_database)
advancedUnlockInfoView = findViewById(R.id.biometric_info)
infoContainerView = findViewById(R.id.activity_password_info_container)
mPermissionAsked = savedInstanceState?.getBoolean(KEY_PERMISSION_ASKED) ?: mPermissionAsked
readOnly = ReadOnlyHelper.retrieveReadOnlyFromInstanceStateOrPreference(this, savedInstanceState)
val browseView = findViewById<View>(R.id.open_database_button)
mOpenFileHelper = OpenFileHelper(this@PasswordActivity)
browseView.setOnClickListener(mOpenFileHelper!!.openFileOnClickViewListener)
keyFileSelectionView?.apply {
mOpenFileHelper?.openFileOnClickViewListener?.let {
setOnClickListener(it)
setOnLongClickListener(it)
}
}
passwordView?.setOnEditorActionListener(onEditorActionListener)
passwordView?.addTextChangedListener(object : TextWatcher {
@@ -147,17 +155,6 @@ open class PasswordActivity : StylishActivity() {
checkboxPasswordView?.isChecked = true
}
})
keyFileView?.setOnEditorActionListener(onEditorActionListener)
keyFileView?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
if (editable.toString().isNotEmpty() && checkboxKeyFileView?.isChecked != true)
checkboxKeyFileView?.isChecked = true
}
})
enableButtonOnCheckedChangeListener = CompoundButton.OnCheckedChangeListener { _, _ ->
enableOrNotTheConfirmationButton()
@@ -260,16 +257,38 @@ open class PasswordActivity : StylishActivity() {
private fun launchGroupActivity() {
EntrySelectionHelper.doEntrySelectionAction(intent,
{
GroupActivity.launch(this@PasswordActivity, readOnly)
GroupActivity.launch(this@PasswordActivity,
readOnly)
},
{
GroupActivity.launchForKeyboardSelection(this@PasswordActivity, readOnly)
GroupActivity.launchForKeyboardSelection(this@PasswordActivity,
readOnly)
// Do not keep history
finish()
},
{ assistStructure ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
GroupActivity.launchForAutofillResult(this@PasswordActivity, assistStructure, readOnly)
val searchInfo: SearchInfo? = intent.getParcelableExtra(KEY_SEARCH_INFO)
AutofillHelper.checkAutoSearchInfo(this,
Database.getInstance(),
searchInfo,
{ items ->
// Response is build
AutofillHelper.buildResponse(this, items)
finish()
},
{
// Here no search info found
GroupActivity.launchForAutofillResult(this@PasswordActivity,
assistStructure,
null,
readOnly)
},
{
// Simply close if database not opened, normally not happened
finish()
}
)
}
})
}
@@ -285,11 +304,12 @@ open class PasswordActivity : StylishActivity() {
}
override fun onResume() {
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
if (Database.getInstance().loaded)
launchGroupActivity()
mRememberKeyFile = PreferencesUtil.rememberKeyFileLocations(this)
// If the database isn't accessible make sure to clear the password field, if it
// was saved in the instance state
if (Database.getInstance().loaded) {
@@ -305,6 +325,7 @@ open class PasswordActivity : StylishActivity() {
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putBoolean(KEY_PERMISSION_ASKED, mPermissionAsked)
mDatabaseKeyFileUri?.let {
outState.putString(KEY_KEYFILE, it.toString())
}
@@ -313,7 +334,15 @@ open class PasswordActivity : StylishActivity() {
}
private fun initUriFromIntent() {
mForceReadOnly = !UriUtil.isUriWritable(mDatabaseFileUri)
/*
// "canXrite" doesn't work with Google Drive, don't really know why?
mForceReadOnly = mDatabaseFileUri?.let {
!FileDatabaseInfo(this, it).canWrite
} ?: false
*/
mForceReadOnly = mDatabaseFileUri?.let {
!FileDatabaseInfo(this, it).exists
} ?: true
// Post init uri with KeyFile if needed
if (mRememberKeyFile && (mDatabaseKeyFileUri == null || mDatabaseKeyFileUri.toString().isEmpty())) {
@@ -339,7 +368,7 @@ open class PasswordActivity : StylishActivity() {
// Define Key File text
if (mRememberKeyFile) {
populateKeyFileTextView(keyFileUri?.toString())
populateKeyFileTextView(keyFileUri)
}
// Define listeners for default database checkbox and validate button
@@ -453,13 +482,13 @@ open class PasswordActivity : StylishActivity() {
}
}
private fun populateKeyFileTextView(text: String?) {
if (text == null || text.isEmpty()) {
keyFileView?.setText("")
private fun populateKeyFileTextView(uri: Uri?) {
if (uri == null || uri.toString().isEmpty()) {
keyFileSelectionView?.uri = null
if (checkboxKeyFileView?.isChecked == true)
checkboxKeyFileView?.isChecked = false
} else {
keyFileView?.setText(text)
keyFileSelectionView?.uri = uri
if (checkboxKeyFileView?.isChecked != true)
checkboxKeyFileView?.isChecked = true
}
@@ -480,7 +509,7 @@ open class PasswordActivity : StylishActivity() {
private fun verifyCheckboxesAndLoadDatabase(cipherDatabaseEntity: CipherDatabaseEntity? = null) {
val password: String? = passwordView?.text?.toString()
val keyFile: Uri? = UriUtil.parse(keyFileView?.text?.toString())
val keyFile: Uri? = keyFileSelectionView?.uri
verifyCheckboxesAndLoadDatabase(password, keyFile, cipherDatabaseEntity)
}
@@ -493,7 +522,7 @@ open class PasswordActivity : StylishActivity() {
}
private fun verifyKeyFileCheckboxAndLoadDatabase(password: String?) {
val keyFile: Uri? = UriUtil.parse(keyFileView?.text?.toString())
val keyFile: Uri? = keyFileSelectionView?.uri
verifyKeyFileCheckbox(keyFile)
loadDatabase(mDatabaseFileUri, password, mDatabaseKeyFileUri)
}
@@ -565,11 +594,42 @@ open class PasswordActivity : StylishActivity() {
super.onCreateOptionsMenu(menu)
launchEducation(menu)
launchEducation(menu) {
launchCheckPermission()
}
return true
}
// Check permission
private fun launchCheckPermission() {
val writePermission = android.Manifest.permission.WRITE_EXTERNAL_STORAGE
val permissions = arrayOf(writePermission)
if (Build.VERSION.SDK_INT >= 23
&& !readOnly
&& !mPermissionAsked) {
mPermissionAsked = true
// Check self permission to show or not the dialog
if (toolbar != null
&& ActivityCompat.checkSelfPermission(this, writePermission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, permissions, WRITE_EXTERNAL_STORAGE_REQUEST)
}
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
WRITE_EXTERNAL_STORAGE_REQUEST -> {
if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE))
Toast.makeText(this, R.string.read_only_warning, Toast.LENGTH_LONG).show()
}
}
}
}
// To fix multiple view education
private var performedEductionInProgress = false
private fun launchEducation(menu: Menu, onEducationFinished: (()-> Unit)? = null) {
@@ -672,7 +732,7 @@ open class PasswordActivity : StylishActivity() {
) { uri ->
if (uri != null) {
mDatabaseKeyFileUri = uri
populateKeyFileTextView(uri.toString())
populateKeyFileTextView(uri)
}
}
}
@@ -697,6 +757,8 @@ open class PasswordActivity : StylishActivity() {
private const val KEY_PASSWORD = "password"
private const val KEY_LAUNCH_IMMEDIATELY = "launchImmediately"
private const val KEY_PERMISSION_ASKED = "KEY_PERMISSION_ASKED"
private const val WRITE_EXTERNAL_STORAGE_REQUEST = 647
private fun buildAndLaunchIntent(activity: Activity, databaseFile: Uri, keyFile: Uri?,
intentBuildLauncher: (Intent) -> Unit) {
@@ -751,13 +813,15 @@ open class PasswordActivity : StylishActivity() {
activity: Activity,
databaseFile: Uri,
keyFile: Uri?,
assistStructure: AssistStructure?) {
assistStructure: AssistStructure?,
searchInfo: SearchInfo?) {
if (assistStructure != null) {
buildAndLaunchIntent(activity, databaseFile, keyFile) { intent ->
AutofillHelper.startActivityForAutofillResult(
activity,
intent,
assistStructure)
assistStructure,
searchInfo)
}
} else {
launch(activity, databaseFile, keyFile)

View File

@@ -35,7 +35,7 @@ import android.widget.CompoundButton
import android.widget.TextView
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.OpenFileHelper
import com.kunzisoft.keepass.utils.UriUtil
import com.kunzisoft.keepass.view.KeyFileSelectionView
class AssignMasterKeyDialogFragment : DialogFragment() {
@@ -51,9 +51,8 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
private var passwordRepeatTextInputLayout: TextInputLayout? = null
private var passwordRepeatView: TextView? = null
private var keyFileTextInputLayout: TextInputLayout? = null
private var keyFileCheckBox: CompoundButton? = null
private var keyFileView: TextView? = null
private var keyFileSelectionView: KeyFileSelectionView? = null
private var mListener: AssignPasswordDialogListener? = null
@@ -69,16 +68,6 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
}
}
private val keyFileTextWatcher = object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
keyFileCheckBox?.isChecked = true
}
}
interface AssignPasswordDialogListener {
fun onAssignKeyDialogPositiveClick(masterPasswordChecked: Boolean, masterPassword: String?,
keyFileChecked: Boolean, keyFile: Uri?)
@@ -121,13 +110,14 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
passwordRepeatTextInputLayout = rootView?.findViewById(R.id.password_repeat_input_layout)
passwordRepeatView = rootView?.findViewById(R.id.pass_conf_password)
keyFileTextInputLayout = rootView?.findViewById(R.id.keyfile_input_layout)
keyFileCheckBox = rootView?.findViewById(R.id.keyfile_checkox)
keyFileView = rootView?.findViewById(R.id.pass_keyfile)
keyFileSelectionView = rootView?.findViewById(R.id.keyfile_selection)
mOpenFileHelper = OpenFileHelper(this)
rootView?.findViewById<View>(R.id.open_database_button)?.setOnClickListener { view ->
mOpenFileHelper?.openFileOnClickViewListener?.onClick(view) }
keyFileSelectionView?.apply {
setOnClickListener(mOpenFileHelper?.openFileOnClickViewListener)
setOnLongClickListener(mOpenFileHelper?.openFileOnClickViewListener)
}
val dialog = builder.create()
@@ -176,14 +166,12 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
// To check checkboxes if a text is present
passwordView?.addTextChangedListener(passwordTextWatcher)
keyFileView?.addTextChangedListener(keyFileTextWatcher)
}
override fun onPause() {
super.onPause()
passwordView?.removeTextChangedListener(passwordTextWatcher)
keyFileView?.removeTextChangedListener(keyFileTextWatcher)
}
private fun verifyPassword(): Boolean {
@@ -216,11 +204,11 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
if (keyFileCheckBox != null
&& keyFileCheckBox!!.isChecked) {
UriUtil.parse(keyFileView?.text?.toString())?.let { uri ->
keyFileSelectionView?.uri?.let { uri ->
mKeyFile = uri
} ?: run {
error = true
keyFileTextInputLayout?.error = getString(R.string.error_nokeyfile)
keyFileSelectionView?.error = getString(R.string.error_nokeyfile)
}
}
return error
@@ -265,8 +253,7 @@ class AssignMasterKeyDialogFragment : DialogFragment() {
) { uri ->
uri?.let { pathUri ->
keyFileCheckBox?.isChecked = true
keyFileView?.text = pathUri.toString()
keyFileSelectionView?.uri = pathUri
}
}
}

View File

@@ -52,15 +52,23 @@ class OpenFileHelper {
this.fragment = context
}
inner class OpenFileOnClickViewListener : View.OnClickListener {
inner class OpenFileOnClickViewListener : View.OnClickListener, View.OnLongClickListener {
override fun onClick(v: View) {
private fun onAbstractClick(longClick: Boolean = false) {
try {
if (longClick) {
try {
openActivityWithActionGetContent()
} catch (e: Exception) {
openActivityWithActionOpenDocument()
}
} else {
try {
openActivityWithActionOpenDocument()
} catch (e: Exception) {
openActivityWithActionGetContent()
}
}
} catch (e: Exception) {
Log.e(TAG, "Enable to start the file picker activity", e)
// Open browser dialog
@@ -68,6 +76,15 @@ class OpenFileHelper {
showBrowserDialog()
}
}
override fun onClick(v: View) {
onAbstractClick()
}
override fun onLongClick(v: View?): Boolean {
onAbstractClick(true)
return true
}
}
@SuppressLint("InlinedApi")

View File

@@ -84,24 +84,25 @@ class FileDatabaseHistoryAdapter(private val context: Context)
// File path
holder.filePath.text = UriUtil.decode(fileDatabaseInfo.fileUri?.toString())
if (fileDatabaseInfo.dataAccessible()) {
if (fileDatabaseInfo.exists) {
holder.fileInformation.clearColorFilter()
} else {
holder.fileInformation.setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY)
}
// Modification
if (fileDatabaseInfo.lastModificationAccessible()) {
holder.fileModification.text = fileDatabaseInfo.getModificationString()
fileDatabaseInfo.getModificationString()?.let {
holder.fileModification.text = it
holder.fileModification.visibility = View.VISIBLE
} else {
} ?: run {
holder.fileModification.visibility = View.GONE
}
// Size
if (fileDatabaseInfo.sizeAccessible()) {
holder.fileSize.text = fileDatabaseInfo.getSizeString()
fileDatabaseInfo.getSizeString()?.let {
holder.fileSize.text = it
holder.fileSize.visibility = View.VISIBLE
} else {
} ?: run {
holder.fileSize.visibility = View.GONE
}

View File

@@ -28,8 +28,14 @@ import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.cursor.EntryCursorKDB
import com.kunzisoft.keepass.database.cursor.EntryCursorKDBX
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.Entry
import com.kunzisoft.keepass.database.element.Group
import com.kunzisoft.keepass.database.element.database.DatabaseKDB
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.icons.assignDatabaseIcon
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.view.strikeOut
@@ -69,8 +75,7 @@ class SearchEntryCursorAdapter(private val context: Context,
}
override fun bindView(view: View, context: Context, cursor: Cursor) {
database.getEntryFrom(cursor)?.let { currentEntry ->
getEntryFrom(cursor)?.let { currentEntry ->
val viewHolder = view.tag as ViewHolder
// Assign image
@@ -98,14 +103,46 @@ class SearchEntryCursorAdapter(private val context: Context,
}
}
private class ViewHolder {
internal var imageViewIcon: ImageView? = null
internal var textViewTitle: TextView? = null
internal var textViewSubTitle: TextView? = null
private fun getEntryFrom(cursor: Cursor): Entry? {
return database.createEntry()?.apply {
database.startManageEntry(this)
entryKDB?.let { entryKDB ->
(cursor as EntryCursorKDB).populateEntry(entryKDB, database.iconFactory)
}
entryKDBX?.let { entryKDBX ->
(cursor as EntryCursorKDBX).populateEntry(entryKDBX, database.iconFactory)
}
database.stopManageEntry(this)
}
}
override fun runQueryOnBackgroundThread(constraint: CharSequence): Cursor? {
return database.searchEntries(context, constraint.toString())
return searchEntries(context, constraint.toString())
}
private fun searchEntries(context: Context, query: String): Cursor? {
var cursorKDB: EntryCursorKDB? = null
var cursorKDBX: EntryCursorKDBX? = null
if (database.type == DatabaseKDB.TYPE)
cursorKDB = EntryCursorKDB()
if (database.type == DatabaseKDBX.TYPE)
cursorKDBX = EntryCursorKDBX()
val searchGroup = database.createVirtualGroupFromSearch(query, SearchHelper.MAX_SEARCH_ENTRY)
if (searchGroup != null) {
// Search in hide entries but not meta-stream
for (entry in searchGroup.getFilteredChildEntries(*Group.ChildFilter.getDefaults(context))) {
entry.entryKDB?.let {
cursorKDB?.addEntry(it)
}
entry.entryKDBX?.let {
cursorKDBX?.addEntry(it)
}
}
}
return cursorKDB ?: cursorKDBX
}
fun getEntryFromPosition(position: Int): Entry? {
@@ -113,9 +150,14 @@ class SearchEntryCursorAdapter(private val context: Context,
val cursor = this.cursor
if (cursor.moveToFirst() && cursor.move(position)) {
pwEntry = database.getEntryFrom(cursor)
pwEntry = getEntryFrom(cursor)
}
return pwEntry
}
private class ViewHolder {
internal var imageViewIcon: ImageView? = null
internal var textViewTitle: TextView? = null
internal var textViewSubTitle: TextView? = null
}
}

View File

@@ -31,9 +31,17 @@ import android.view.autofill.AutofillManager
import android.view.autofill.AutofillValue
import android.widget.RemoteViews
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.icons.assignDatabaseIcon
import com.kunzisoft.keepass.model.EntryInfo
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.timeout.TimeoutHelper
@RequiresApi(api = Build.VERSION_CODES.O)
@@ -42,6 +50,7 @@ object AutofillHelper {
private const val AUTOFILL_RESPONSE_REQUEST_CODE = 8165
private const val ASSIST_STRUCTURE = AutofillManager.EXTRA_ASSIST_STRUCTURE
const val KEY_SEARCH_INFO = "KEY_SEARCH_INFO"
fun retrieveAssistStructure(intent: Intent?): AssistStructure? {
intent?.let {
@@ -62,11 +71,28 @@ object AutofillHelper {
return ""
}
private fun buildDataset(context: Context,
internal fun addHeader(responseBuilder: FillResponse.Builder,
packageName: String,
webDomain: String?,
applicationId: String?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (webDomain != null) {
responseBuilder.setHeader(RemoteViews(packageName, R.layout.item_autofill_web_domain).apply {
setTextViewText(R.id.autofill_web_domain_text, webDomain)
})
} else if (applicationId != null) {
responseBuilder.setHeader(RemoteViews(packageName, R.layout.item_autofill_app_id).apply {
setTextViewText(R.id.autofill_app_id_text, applicationId)
})
}
}
}
internal fun buildDataset(context: Context,
entryInfo: EntryInfo,
struct: StructureParser.Result): Dataset? {
val title = makeEntryTitle(entryInfo)
val views = newRemoteViews(context.packageName, title)
val views = newRemoteViews(context, title, entryInfo.icon)
val builder = Dataset.Builder(views)
builder.setId(entryInfo.id)
@@ -86,9 +112,16 @@ object AutofillHelper {
}
/**
* Method to hit when right key is selected
* Build the Autofill response for one entry
*/
fun buildResponseWhenEntrySelected(activity: Activity, entryInfo: EntryInfo) {
fun buildResponse(activity: Activity, entryInfo: EntryInfo) {
buildResponse(activity, ArrayList<EntryInfo>().apply { add(entryInfo) })
}
/**
* Build the Autofill response for many entry
*/
fun buildResponse(activity: Activity, entriesInfo: List<EntryInfo>) {
var setResultOk = false
activity.intent?.extras?.let { extras ->
if (extras.containsKey(ASSIST_STRUCTURE)) {
@@ -96,8 +129,9 @@ object AutofillHelper {
StructureParser(structure).parse()?.let { result ->
// New Response
val responseBuilder = FillResponse.Builder()
val dataset = buildDataset(activity, entryInfo, result)
responseBuilder.addDataset(dataset)
entriesInfo.forEach {
responseBuilder.addDataset(buildDataset(activity, it, result))
}
val mReplyIntent = Intent()
Log.d(activity.javaClass.name, "Successed Autofill auth.")
mReplyIntent.putExtra(
@@ -115,12 +149,48 @@ object AutofillHelper {
}
}
/**
* Utility method to perform actions if item is found or not after an auto search in [database]
*/
fun checkAutoSearchInfo(context: Context,
database: Database,
searchInfo: SearchInfo?,
onItemsFound: (items: List<EntryInfo>) -> Unit,
onItemNotFound: () -> Unit,
onDatabaseClosed: () -> Unit) {
if (database.loaded && TimeoutHelper.checkTime(context)) {
var searchWithoutUI = false
if (PreferencesUtil.isAutofillAutoSearchEnable(context)
&& searchInfo != null) {
// If search provide results
database.createVirtualGroupFromSearch(searchInfo, SearchHelper.MAX_SEARCH_ENTRY)?.let { searchGroup ->
if (searchGroup.getNumberOfChildEntries() > 0) {
searchWithoutUI = true
onItemsFound.invoke(
searchGroup.getChildEntriesInfo(database))
}
}
}
if (!searchWithoutUI) {
onItemNotFound.invoke()
}
} else {
onDatabaseClosed.invoke()
}
}
/**
* Utility method to start an activity with an Autofill for result
*/
fun startActivityForAutofillResult(activity: Activity, intent: Intent, assistStructure: AssistStructure) {
fun startActivityForAutofillResult(activity: Activity,
intent: Intent,
assistStructure: AssistStructure,
searchInfo: SearchInfo?) {
EntrySelectionHelper.addEntrySelectionModeExtraInIntent(intent)
intent.putExtra(ASSIST_STRUCTURE, assistStructure)
searchInfo?.let {
intent.putExtra(KEY_SEARCH_INFO, it)
}
activity.startActivityForResult(intent, AUTOFILL_RESPONSE_REQUEST_CODE)
}
@@ -139,9 +209,18 @@ object AutofillHelper {
}
}
private fun newRemoteViews(packageName: String, remoteViewsText: String): RemoteViews {
val presentation = RemoteViews(packageName, R.layout.item_autofill_service)
presentation.setTextViewText(R.id.text, remoteViewsText)
private fun newRemoteViews(context: Context,
remoteViewsText: String,
remoteViewsIcon: IconImage? = null): RemoteViews {
val presentation = RemoteViews(context.packageName, R.layout.item_autofill_entry)
presentation.setTextViewText(R.id.autofill_entry_text, remoteViewsText)
if (remoteViewsIcon != null) {
presentation.assignDatabaseIcon(context,
R.id.autofill_entry_icon,
Database.getInstance().drawFactory,
remoteViewsIcon,
ContextCompat.getColor(context, R.color.green))
}
return presentation
}
}

View File

@@ -31,7 +31,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.kunzisoft.keepass.activities.FileDatabaseSelectActivity
import com.kunzisoft.keepass.activities.GroupActivity
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.timeout.TimeoutHelper
import com.kunzisoft.keepass.model.SearchInfo
@RequiresApi(api = Build.VERSION_CODES.O)
class AutofillLauncherActivity : AppCompatActivity() {
@@ -40,13 +40,31 @@ class AutofillLauncherActivity : AppCompatActivity() {
// Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE)
val assistStructure = AutofillHelper.retrieveAssistStructure(intent)
if (assistStructure != null) {
if (Database.getInstance().loaded && TimeoutHelper.checkTime(this))
// Build search param
val searchInfo = SearchInfo().apply {
applicationId = intent.getStringExtra(KEY_SEARCH_APPLICATION_ID)
webDomain = intent.getStringExtra(KEY_SEARCH_DOMAIN)
}
// If database is open
AutofillHelper.checkAutoSearchInfo(this,
Database.getInstance(),
searchInfo,
{ items ->
// Items found
AutofillHelper.buildResponse(this, items)
finish()
},
{
// Show the database UI to select the entry
GroupActivity.launchForAutofillResult(this,
assistStructure)
else {
},
{
// If database not open
FileDatabaseSelectActivity.launchForAutofillResult(this,
assistStructure)
assistStructure, searchInfo)
}
)
} else {
setResult(Activity.RESULT_CANCELED)
finish()
@@ -62,10 +80,20 @@ class AutofillLauncherActivity : AppCompatActivity() {
companion object {
fun getAuthIntentSenderForResponse(context: Context): IntentSender {
val intent = Intent(context, AutofillLauncherActivity::class.java)
private const val KEY_SEARCH_APPLICATION_ID = "KEY_SEARCH_APPLICATION_ID"
private const val KEY_SEARCH_DOMAIN = "KEY_SEARCH_DOMAIN"
fun getAuthIntentSenderForResponse(context: Context,
searchInfo: SearchInfo? = null): IntentSender {
return PendingIntent.getActivity(context, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT).intentSender
// Doesn't work with Parcelable (don't know why?)
Intent(context, AutofillLauncherActivity::class.java).apply {
searchInfo?.let {
putExtra(KEY_SEARCH_APPLICATION_ID, it.applicationId)
putExtra(KEY_SEARCH_DOMAIN, it.webDomain)
}
},
PendingIntent.FLAG_CANCEL_CURRENT).intentSender
}
}
}

View File

@@ -22,31 +22,78 @@ package com.kunzisoft.keepass.autofill
import android.os.Build
import android.os.CancellationSignal
import android.service.autofill.*
import androidx.annotation.RequiresApi
import android.util.Log
import android.widget.RemoteViews
import androidx.annotation.RequiresApi
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.model.SearchInfo
@RequiresApi(api = Build.VERSION_CODES.O)
class KeeAutofillService : AutofillService() {
override fun onFillRequest(request: FillRequest, cancellationSignal: CancellationSignal,
override fun onFillRequest(request: FillRequest,
cancellationSignal: CancellationSignal,
callback: FillCallback) {
val fillContexts = request.fillContexts
val latestStructure = fillContexts[fillContexts.size - 1].structure
cancellationSignal.setOnCancelListener { Log.w(TAG, "Cancel autofill.") }
val responseBuilder = FillResponse.Builder()
// Check user's settings for authenticating Responses and Datasets.
val parseResult = StructureParser(latestStructure).parse()
parseResult?.allAutofillIds()?.let { autofillIds ->
StructureParser(latestStructure).parse()?.let { parseResult ->
val searchInfo = SearchInfo().apply {
applicationId = parseResult.applicationId
webDomain = parseResult.domain
}
AutofillHelper.checkAutoSearchInfo(this,
Database.getInstance(),
searchInfo,
{ items ->
val responseBuilder = FillResponse.Builder()
AutofillHelper.addHeader(responseBuilder, packageName,
parseResult.domain, parseResult.applicationId)
items.forEach {
responseBuilder.addDataset(AutofillHelper.buildDataset(this, it, parseResult))
}
callback.onSuccess(responseBuilder.build())
},
{
// Show UI if no search result
showUIForEntrySelection(parseResult, searchInfo, callback)
},
{
// Show UI if database not open
showUIForEntrySelection(parseResult, searchInfo, callback)
}
)
}
}
private fun showUIForEntrySelection(parseResult: StructureParser.Result,
searchInfo: SearchInfo,
callback: FillCallback) {
parseResult.allAutofillIds().let { autofillIds ->
if (autofillIds.isNotEmpty()) {
// If the entire Autofill Response is authenticated, AuthActivity is used
// to generate Response.
val sender = AutofillLauncherActivity.getAuthIntentSenderForResponse(this)
val presentation = RemoteViews(packageName, R.layout.item_autofill_service_unlock)
responseBuilder.setAuthentication(autofillIds, sender, presentation)
val sender = AutofillLauncherActivity.getAuthIntentSenderForResponse(this,
searchInfo)
val responseBuilder = FillResponse.Builder()
val remoteViewsUnlock: RemoteViews = if (!parseResult.domain.isNullOrEmpty()) {
RemoteViews(packageName, R.layout.item_autofill_unlock_web_domain).apply {
setTextViewText(R.id.autofill_web_domain_text, parseResult.domain)
}
} else if (!parseResult.applicationId.isNullOrEmpty()) {
RemoteViews(packageName, R.layout.item_autofill_unlock_app_id).apply {
setTextViewText(R.id.autofill_app_id_text, parseResult.applicationId)
}
} else {
RemoteViews(packageName, R.layout.item_autofill_unlock)
}
responseBuilder.setAuthentication(autofillIds, sender, remoteViewsUnlock)
callback.onSuccess(responseBuilder.build())
}
}

View File

@@ -20,6 +20,7 @@ package com.kunzisoft.keepass.autofill
import android.app.assist.AssistStructure
import android.os.Build
import android.text.InputType
import androidx.annotation.RequiresApi
import android.util.Log
import android.view.View
@@ -34,20 +35,17 @@ import java.util.*
internal class StructureParser(private val structure: AssistStructure) {
private var result: Result? = null
private var usernameCandidate: AutofillId? = null
private var lockHint: Boolean = false
fun parse(): Result? {
try {
result = Result()
result?.apply {
usernameCandidate = null
mainLoop@ for (i in 0 until structure.windowNodeCount) {
val windowNode = structure.getWindowNodeAt(i)
/*
title.add(windowNode.title)
windowNode.rootViewNode.webDomain?.let {
webDomain.add(it)
}
*/
applicationId = windowNode.title.toString().split("/")[0]
Log.d(TAG, "Autofill applicationId: $applicationId")
if (parseViewNode(windowNode.rootViewNode))
break@mainLoop
}
@@ -57,28 +55,43 @@ internal class StructureParser(private val structure: AssistStructure) {
}
// Return the result only if password field is retrieved
return if (result?.passwordId != null)
return if (result?.usernameId != null
&& result?.passwordId != null)
result
else
null
} catch (e: Exception) {
return null
}
}
private fun parseViewNode(node: AssistStructure.ViewNode): Boolean {
if (node.autofillId != null) {
// Get the domain of a web app
node.webDomain?.let {
result?.domain = it
Log.d(TAG, "Autofill domain: $it")
}
// Only parse visible nodes
if (node.visibility == View.VISIBLE) {
if (node.autofillId != null
&& node.autofillType == View.AUTOFILL_TYPE_TEXT) {
// Parse methods
val hints = node.autofillHints
if (hints != null && hints.isNotEmpty()) {
if (parseNodeByAutofillHint(node))
return true
} else {
if (parseNodeByHtmlAttributes(node))
} else if (parseNodeByHtmlAttributes(node))
return true
else if (parseNodeByAndroidInput(node))
return true
}
}
// Recursive method to process each node
for (i in 0 until node.childCount) {
if (parseViewNode(node.getChildAt(i)))
return true
}
}
return false
}
@@ -86,27 +99,25 @@ internal class StructureParser(private val structure: AssistStructure) {
val autofillId = node.autofillId
node.autofillHints?.forEach {
when {
it.toLowerCase(Locale.ENGLISH) == View.AUTOFILL_HINT_USERNAME
|| it.toLowerCase(Locale.ENGLISH) == View.AUTOFILL_HINT_EMAIL_ADDRESS
|| it.toLowerCase(Locale.ENGLISH) == View.AUTOFILL_HINT_PHONE -> {
it.equals(View.AUTOFILL_HINT_USERNAME, true)
|| it.equals(View.AUTOFILL_HINT_EMAIL_ADDRESS, true)
|| it.equals(View.AUTOFILL_HINT_PHONE, true)
|| it.equals("usernameOrEmail", true)-> {
result?.usernameId = autofillId
Log.d(TAG, "Autofill username hint")
}
it.toLowerCase(Locale.ENGLISH) == View.AUTOFILL_HINT_PASSWORD
|| it.toLowerCase(Locale.ENGLISH).contains("password") -> {
it.equals(View.AUTOFILL_HINT_PASSWORD, true)
|| it.contains("password", true) -> {
result?.passwordId = autofillId
Log.d(TAG, "Autofill password hint")
return true
}
it.toLowerCase(Locale.ENGLISH) == "off" -> {
Log.d(TAG, "Autofill OFF hint")
lockHint = true
return false
}
it.toLowerCase(Locale.ENGLISH) == "on" -> {
Log.d(TAG, "Autofill ON hint")
if (parseNodeByHtmlAttributes(node))
return true
// Ignore autocomplete="off"
// https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
it.equals("off", true) ||
it.equals("on", true) -> {
Log.d(TAG, "Autofill web hint")
return parseNodeByHtmlAttributes(node)
}
else -> Log.d(TAG, "Autofill unsupported hint $it")
}
@@ -115,8 +126,6 @@ internal class StructureParser(private val structure: AssistStructure) {
}
private fun parseNodeByHtmlAttributes(node: AssistStructure.ViewNode): Boolean {
if (lockHint)
return false
val autofillId = node.autofillId
val nodHtml = node.htmlInfo
when (nodHtml?.tag?.toLowerCase(Locale.ENGLISH)) {
@@ -127,15 +136,16 @@ internal class StructureParser(private val structure: AssistStructure) {
when (pairAttribute.second.toLowerCase(Locale.ENGLISH)) {
"tel", "email" -> {
result?.usernameId = autofillId
Log.d(TAG, "Autofill username type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
Log.d(TAG, "Autofill username web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
}
"text" -> {
usernameCandidate = autofillId
Log.d(TAG, "Autofill type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
Log.d(TAG, "Autofill username candidate web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
}
"password" -> {
result?.passwordId = autofillId
Log.d(TAG, "Autofill password type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
Log.d(TAG, "Autofill password web type: ${node.htmlInfo?.tag} ${node.htmlInfo?.attributes}")
return true
}
}
}
@@ -146,8 +156,57 @@ internal class StructureParser(private val structure: AssistStructure) {
return false
}
private fun parseNodeByAndroidInput(node: AssistStructure.ViewNode): Boolean {
val autofillId = node.autofillId
val inputType = node.inputType
if (inputType and InputType.TYPE_CLASS_TEXT != 0) {
when {
inputType and InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS != 0 -> {
result?.usernameId = autofillId
Log.d(TAG, "Autofill username android type: $inputType")
}
inputType and InputType.TYPE_TEXT_VARIATION_NORMAL != 0 ||
inputType and InputType.TYPE_NUMBER_VARIATION_NORMAL != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_PERSON_NAME != 0 -> {
usernameCandidate = autofillId
Log.d(TAG, "Autofill username candidate android type: $inputType")
}
inputType and InputType.TYPE_TEXT_VARIATION_PASSWORD != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD != 0 ||
inputType and InputType.TYPE_NUMBER_VARIATION_PASSWORD != 0 -> {
result?.passwordId = autofillId
Log.d(TAG, "Autofill password android type: $inputType")
return true
}
inputType and InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_FILTER != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_PHONETIC != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_URI != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != 0 ||
inputType and InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD != 0 -> {
// Type not used
}
else -> {
Log.d(TAG, "Autofill unknown android type: $inputType")
usernameCandidate = autofillId
}
}
}
return false
}
@RequiresApi(api = Build.VERSION_CODES.O)
internal class Result {
var applicationId: String? = null
var domain: String? = null
set(value) {
if (field == null)
field = value
}
var usernameId: AutofillId? = null
set(value) {
if (field == null)

View File

@@ -20,15 +20,11 @@
package com.kunzisoft.keepass.database.element
import android.content.ContentResolver
import android.content.Context
import android.content.res.Resources
import android.database.Cursor
import android.net.Uri
import android.util.Log
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
import com.kunzisoft.keepass.database.action.node.NodeHandler
import com.kunzisoft.keepass.database.cursor.EntryCursorKDB
import com.kunzisoft.keepass.database.cursor.EntryCursorKDBX
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
import com.kunzisoft.keepass.database.element.database.DatabaseKDB
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX
@@ -49,6 +45,7 @@ import com.kunzisoft.keepass.database.file.output.DatabaseOutputKDB
import com.kunzisoft.keepass.database.file.output.DatabaseOutputKDBX
import com.kunzisoft.keepass.database.search.SearchHelper
import com.kunzisoft.keepass.icons.IconDrawableFactory
import com.kunzisoft.keepass.model.SearchInfo
import com.kunzisoft.keepass.stream.readBytes4ToInt
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
import com.kunzisoft.keepass.utils.SingletonHolder
@@ -137,6 +134,9 @@ class Database {
val version: String
get() = mDatabaseKDB?.version ?: mDatabaseKDBX?.version ?: "-"
val type: Class<*>?
get() = mDatabaseKDB?.javaClass ?: mDatabaseKDBX?.javaClass
val allowDataCompression: Boolean
get() = mDatabaseKDBX != null
@@ -397,54 +397,17 @@ class Database {
false
}
@JvmOverloads
fun search(str: String, max: Int = Integer.MAX_VALUE): Group? {
return mSearchHelper?.search(this, str, max)
fun createVirtualGroupFromSearch(searchQuery: String, max: Int = Integer.MAX_VALUE): Group? {
return mSearchHelper?.createVirtualGroupWithSearchResult(this, searchQuery, max)
}
fun searchEntries(context: Context, query: String): Cursor? {
var cursorKDB: EntryCursorKDB? = null
var cursorKDBX: EntryCursorKDBX? = null
if (mDatabaseKDB != null)
cursorKDB = EntryCursorKDB()
if (mDatabaseKDBX != null)
cursorKDBX = EntryCursorKDBX()
val searchResult = search(query, SearchHelper.MAX_SEARCH_ENTRY)
if (searchResult != null) {
// Search in hide entries but not meta-stream
for (entry in searchResult.getFilteredChildEntries(*Group.ChildFilter.getDefaults(context))) {
entry.entryKDB?.let {
cursorKDB?.addEntry(it)
}
entry.entryKDBX?.let {
cursorKDBX?.addEntry(it)
}
}
}
return cursorKDB ?: cursorKDBX
}
fun getEntryFrom(cursor: Cursor): Entry? {
val iconFactory = mDatabaseKDB?.iconFactory ?: mDatabaseKDBX?.iconFactory ?: IconImageFactory()
return createEntry()?.apply {
startManageEntry(this)
mDatabaseKDB?.let {
entryKDB?.let { entryKDB ->
(cursor as EntryCursorKDB).populateEntry(entryKDB, iconFactory)
}
}
mDatabaseKDBX?.let {
entryKDBX?.let { entryKDBX ->
(cursor as EntryCursorKDBX).populateEntry(entryKDBX, iconFactory)
}
}
stopManageEntry(this)
}
fun createVirtualGroupFromSearch(searchInfo: SearchInfo, max: Int = Integer.MAX_VALUE): Group? {
val query = (if (searchInfo.webDomain != null)
searchInfo.webDomain
else
searchInfo.applicationId)
?: return null
return mSearchHelper?.createVirtualGroupWithSearchResult(this, query, max)
}
@Throws(DatabaseOutputException::class)

View File

@@ -398,6 +398,7 @@ class Entry : Node, EntryVersionedInterface<Group> {
database?.startManageEntry(this)
entryInfo.id = nodeId.toString()
entryInfo.title = title
entryInfo.icon = icon
entryInfo.username = username
entryInfo.password = password
entryInfo.url = url

View File

@@ -28,6 +28,7 @@ import com.kunzisoft.keepass.database.element.group.GroupVersionedInterface
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
import com.kunzisoft.keepass.database.element.node.*
import com.kunzisoft.keepass.model.EntryInfo
import com.kunzisoft.keepass.settings.PreferencesUtil
import java.util.*
import kotlin.collections.ArrayList
@@ -251,6 +252,14 @@ class Group : Node, GroupVersionedInterface<Group, Entry> {
ArrayList()
}
fun getChildEntriesInfo(database: Database): List<EntryInfo> {
val entriesInfo = ArrayList<EntryInfo>()
getChildEntries().forEach { entry ->
entriesInfo.add(entry.getEntryInfo(database))
}
return entriesInfo
}
fun getFilteredChildEntries(vararg filter: ChildFilter): List<Entry> {
val withoutMetaStream = filter.contains(ChildFilter.META_STREAM)
val showExpiredEntries = !filter.contains(ChildFilter.EXPIRED)

View File

@@ -26,7 +26,6 @@ import com.kunzisoft.keepass.database.element.entry.EntryKDB
import com.kunzisoft.keepass.database.element.group.GroupKDB
import com.kunzisoft.keepass.database.element.node.NodeIdInt
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
import com.kunzisoft.keepass.database.element.node.NodeVersioned
import com.kunzisoft.keepass.database.element.security.EncryptionAlgorithm
import com.kunzisoft.keepass.stream.NullOutputStream
import java.io.IOException
@@ -262,6 +261,7 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
}
companion object {
val TYPE = DatabaseKDB::class.java
const val BACKUP_FOLDER_TITLE = "Backup"
private const val BACKUP_FOLDER_UNDEFINED_ID = -1

View File

@@ -29,7 +29,8 @@ import com.kunzisoft.keepass.crypto.engine.CipherEngine
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
import com.kunzisoft.keepass.crypto.keyDerivation.KdfFactory
import com.kunzisoft.keepass.crypto.keyDerivation.KdfParameters
import com.kunzisoft.keepass.database.element.*
import com.kunzisoft.keepass.database.element.DateInstant
import com.kunzisoft.keepass.database.element.DeletedObject
import com.kunzisoft.keepass.database.element.database.DatabaseKDB.Companion.BACKUP_FOLDER_TITLE
import com.kunzisoft.keepass.database.element.entry.EntryKDBX
import com.kunzisoft.keepass.database.element.group.GroupKDBX
@@ -551,6 +552,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
}
companion object {
val TYPE = DatabaseKDBX::class.java
private val TAG = DatabaseKDBX::class.java.name
private const val DEFAULT_HISTORY_MAX_ITEMS = 10 // -1 unlimited

View File

@@ -26,7 +26,6 @@ import com.kunzisoft.keepass.database.element.Group
import com.kunzisoft.keepass.database.search.iterator.EntrySearchStringIterator
import com.kunzisoft.keepass.database.search.iterator.EntrySearchStringIteratorKDB
import com.kunzisoft.keepass.database.search.iterator.EntrySearchStringIteratorKDBX
import java.util.*
class SearchHelper(private val isOmitBackup: Boolean) {
@@ -36,22 +35,19 @@ class SearchHelper(private val isOmitBackup: Boolean) {
private var incrementEntry = 0
fun search(database: Database, qStr: String, max: Int): Group? {
fun createVirtualGroupWithSearchResult(database: Database, searchQuery: String, max: Int): Group? {
val searchGroup = database.createGroup()
searchGroup?.title = "\"" + qStr + "\""
searchGroup?.title = "\"" + searchQuery + "\""
// Search all entries
val loc = Locale.getDefault()
val finalQStr = qStr.toLowerCase(loc)
incrementEntry = 0
database.rootGroup?.doForEachChild(
object : NodeHandler<Entry>() {
override fun operate(node: Entry): Boolean {
if (incrementEntry >= max)
return false
if (entryContainsString(node, finalQStr, loc)) {
if (entryContainsString(node, searchQuery)) {
searchGroup?.addChildEntry(node)
incrementEntry++
}
@@ -73,7 +69,7 @@ class SearchHelper(private val isOmitBackup: Boolean) {
return searchGroup
}
private fun entryContainsString(entry: Entry, searchString: String, locale: Locale): Boolean {
private fun entryContainsString(entry: Entry, searchString: String): Boolean {
// Entry don't contains string if the search string is empty
if (searchString.isEmpty())
@@ -90,14 +86,13 @@ class SearchHelper(private val isOmitBackup: Boolean) {
iterator?.let {
while (it.hasNext()) {
val str = it.next()
if (str.isNotEmpty()) {
if (str.toLowerCase(locale).contains(searchString)) {
val currentString = it.next()
if (currentString.isNotEmpty()
&& currentString.contains(searchString, true)) {
return true
}
}
}
}
return false
}
}

View File

@@ -39,7 +39,7 @@ constructor(private val mEntry: EntryKDB,
title -> mEntry.title
url -> mEntry.url
username -> mEntry.username
comment -> mEntry.notes
notes -> mEntry.notes
else -> ""
}
}
@@ -73,7 +73,7 @@ constructor(private val mEntry: EntryKDB,
title -> mSearchParameters.searchInTitles
url -> mSearchParameters.searchInUrls
username -> mSearchParameters.searchInUserNames
comment -> mSearchParameters.searchInNotes
notes -> mSearchParameters.searchInNotes
else -> true
}
@@ -88,7 +88,7 @@ constructor(private val mEntry: EntryKDB,
private const val title = 0
private const val url = 1
private const val username = 2
private const val comment = 3
private const val notes = 3
private const val maxEntries = 4
}

View File

@@ -22,16 +22,16 @@ package com.kunzisoft.keepass.icons
import android.content.Context
import android.content.res.ColorStateList
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.*
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import androidx.core.content.res.ResourcesCompat
import androidx.core.widget.ImageViewCompat
import android.util.Log
import android.widget.ImageView
import android.widget.RemoteViews
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.widget.ImageViewCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.icon.IconImageCustom
@@ -70,6 +70,23 @@ class IconDrawableFactory {
}
}
/**
* Utility method to assign a drawable to a RemoteView and tint it
*/
fun assignDrawableToRemoteViews(superDrawable: SuperDrawable,
remoteViews: RemoteViews,
imageId: Int,
tintColor: Int = Color.BLACK) {
val bitmap = superDrawable.drawable.toBitmap()
// Tint bitmap if it's not a custom icon
if (!superDrawable.custom) {
Canvas(bitmap).drawBitmap(bitmap, 0.0F, 0.0F, Paint().apply {
colorFilter = PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)
})
}
remoteViews.setImageViewBitmap(imageId, bitmap)
}
/**
* Get the [SuperDrawable] [icon] (from cache, or build it and add it to the cache if not exists yet), then [tint] it with [tintColor] if needed
*/
@@ -233,7 +250,6 @@ class IconDrawableFactory {
*/
fun ImageView.assignDefaultDatabaseIcon(iconFactory: IconDrawableFactory, tintColor: Int = Color.WHITE) {
IconPackChooser.getSelectedIconPack(context)?.let { selectedIconPack ->
iconFactory.assignDrawableToImageView(
iconFactory.getIconSuperDrawable(context,
selectedIconPack.defaultIconId,
@@ -249,9 +265,10 @@ fun ImageView.assignDefaultDatabaseIcon(iconFactory: IconDrawableFactory, tintCo
/**
* Assign a database [icon] to an ImageView and tint it with [tintColor] if needed
*/
fun ImageView.assignDatabaseIcon(iconFactory: IconDrawableFactory, icon: IconImage, tintColor: Int = Color.WHITE) {
fun ImageView.assignDatabaseIcon(iconFactory: IconDrawableFactory,
icon: IconImage,
tintColor: Int = Color.WHITE) {
IconPackChooser.getSelectedIconPack(context)?.let { selectedIconPack ->
iconFactory.assignDrawableToImageView(
iconFactory.getIconSuperDrawable(context,
icon,
@@ -263,3 +280,19 @@ fun ImageView.assignDatabaseIcon(iconFactory: IconDrawableFactory, icon: IconIma
tintColor)
}
}
fun RemoteViews.assignDatabaseIcon(context: Context,
imageId: Int,
iconFactory: IconDrawableFactory,
icon: IconImage,
tintColor: Int = Color.BLACK) {
iconFactory.assignDrawableToRemoteViews(
iconFactory.getIconSuperDrawable(context,
icon,
24,
true,
tintColor),
this,
imageId,
tintColor)
}

View File

@@ -21,6 +21,7 @@ package com.kunzisoft.keepass.model
import android.os.Parcel
import android.os.Parcelable
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.otp.OtpElement
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
import java.util.*
@@ -29,6 +30,7 @@ class EntryInfo : Parcelable {
var id: String = ""
var title: String = ""
var icon: IconImage? = null
var username: String = ""
var password: String = ""
var url: String = ""
@@ -41,6 +43,7 @@ class EntryInfo : Parcelable {
private constructor(parcel: Parcel) {
id = parcel.readString() ?: id
title = parcel.readString() ?: title
icon = parcel.readParcelable(IconImage::class.java.classLoader)
username = parcel.readString() ?: username
password = parcel.readString() ?: password
url = parcel.readString() ?: url
@@ -56,6 +59,7 @@ class EntryInfo : Parcelable {
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(id)
parcel.writeString(title)
parcel.writeParcelable(icon, flags)
parcel.writeString(username)
parcel.writeString(password)
parcel.writeString(url)

View File

@@ -0,0 +1,42 @@
package com.kunzisoft.keepass.model
import android.os.Parcel
import android.os.Parcelable
class SearchInfo : Parcelable {
var applicationId: String? = null
var webDomain: String? = null
constructor()
private constructor(parcel: Parcel) {
val readAppId = parcel.readString()
applicationId = if (readAppId.isNullOrEmpty()) null else readAppId
val readDomain = parcel.readString()
webDomain = if (readDomain.isNullOrEmpty()) null else readDomain
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(applicationId ?: "")
parcel.writeString(webDomain ?: "")
}
companion object {
@JvmField
val CREATOR: Parcelable.Creator<SearchInfo> = object : Parcelable.Creator<SearchInfo> {
override fun createFromParcel(parcel: Parcel): SearchInfo {
return SearchInfo(parcel)
}
override fun newArray(size: Int): Array<SearchInfo?> {
return arrayOfNulls(size)
}
}
}
}

View File

@@ -74,7 +74,7 @@ object OtpEntryFields {
// [^&=\s]+=[^&=\s]+(&[^&=\s]+=[^&=\s]+)*
private const val validKeyValue = "[^&=\\s]+"
private const val validKeyValuePair = "$validKeyValue=$validKeyValue"
private const val validKeyValueRegex = "$validKeyValuePair&($validKeyValuePair)*"
private const val validKeyValueRegex = "$validKeyValuePair(&$validKeyValuePair)*"
/**
* Parse fields of an entry to retrieve an OtpElement
@@ -243,21 +243,18 @@ object OtpEntryFields {
val plainText = getField(OTP_FIELD)
if (plainText != null && plainText.isNotEmpty()) {
if (Pattern.matches(validKeyValueRegex, plainText)) {
try {
return try {
// KeeOtp string format
val query = breakDownKeyValuePairs(plainText)
var secretString = query[SEED_KEY]
if (secretString == null)
secretString = ""
otpElement.setBase32Secret(secretString)
otpElement.setBase32Secret(query[SEED_KEY] ?: "")
otpElement.digits = query[DIGITS_KEY]?.toIntOrNull() ?: OTP_DEFAULT_DIGITS
otpElement.period = query[STEP_KEY]?.toIntOrNull() ?: TOTP_DEFAULT_PERIOD
otpElement.type = OtpType.TOTP
return true
true
} catch (exception: Exception) {
return false
false
}
} else {
// Malformed

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2019 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.settings
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.widget.Toolbar
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.stylish.StylishActivity
class AutofillSettingsActivity : StylishActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_toolbar)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
toolbar.setTitle(R.string.autofill_preference_title)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, AutofillSettingsFragment())
.commit()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> onBackPressed()
}
return super.onOptionsItemSelected(item)
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 Jeremy Jamet / Kunzisoft.
* Copyright 2020 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
@@ -20,16 +20,14 @@
package com.kunzisoft.keepass.settings
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceFragmentCompat
class SettingsAutofillActivity : SettingsActivity() {
import com.kunzisoft.keepass.R
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mTimeoutEnable = false
}
class AutofillSettingsFragment : PreferenceFragmentCompat() {
override fun retrieveMainFragment(): Fragment {
return NestedSettingsFragment.newInstance(NestedSettingsFragment.Screen.FORM_FILLING)
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
// Load the preferences from an XML resource
setPreferencesFromResource(R.xml.preferences_autofill, rootKey)
}
}

View File

@@ -26,7 +26,7 @@ import android.view.MenuItem
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.stylish.StylishActivity
class MagikIMESettings : StylishActivity() {
class MagikeyboardSettingsActivity : StylishActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -39,7 +39,7 @@ class MagikIMESettings : StylishActivity() {
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, MagikIMESettingsFragment())
.replace(R.id.fragment_container, MagikeyboardSettingsFragment())
.commit()
}
}

View File

@@ -24,7 +24,7 @@ import androidx.preference.PreferenceFragmentCompat
import com.kunzisoft.keepass.R
class MagikIMESettingsFragment : PreferenceFragmentCompat() {
class MagikeyboardSettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
// Load the preferences from an XML resource

View File

@@ -24,7 +24,6 @@ import android.os.Bundle
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
import com.kunzisoft.keepass.database.element.Database
class MainPreferenceFragment : PreferenceFragmentCompat() {

View File

@@ -160,12 +160,7 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
}
findPreference<Preference>(getString(R.string.magic_keyboard_preference_key))?.setOnPreferenceClickListener {
startActivity(Intent(context, MagikIMESettings::class.java))
false
}
findPreference<Preference>(getString(R.string.clipboard_explanation_key))?.setOnPreferenceClickListener {
UriUtil.gotoUrl(context!!, R.string.clipboard_explanation_url)
startActivity(Intent(context, MagikeyboardSettingsActivity::class.java))
false
}
@@ -174,6 +169,16 @@ class NestedAppSettingsFragment : NestedSettingsFragment() {
false
}
findPreference<Preference>(getString(R.string.settings_autofill_key))?.setOnPreferenceClickListener {
startActivity(Intent(context, AutofillSettingsActivity::class.java))
false
}
findPreference<Preference>(getString(R.string.clipboard_explanation_key))?.setOnPreferenceClickListener {
UriUtil.gotoUrl(context!!, R.string.clipboard_explanation_url)
false
}
// Present in two places
allowCopyPassword()
}

View File

@@ -31,7 +31,6 @@ import com.kunzisoft.androidclearchroma.ChromaUtil
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.dialogs.AssignMasterKeyDialogFragment
import com.kunzisoft.keepass.activities.helpers.ReadOnlyHelper
import com.kunzisoft.keepass.activities.lock.lock
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
@@ -551,14 +550,10 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
val settingActivity = activity as SettingsActivity?
when (item.itemId) {
R.id.menu_lock -> {
settingActivity?.lock()
return true
}
return when (item.itemId) {
R.id.menu_save_database -> {
settingActivity?.mProgressDialogThread?.startDatabaseSave(!mDatabaseReadOnly)
return true
true
}
else -> {
@@ -566,7 +561,7 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
settingActivity?.let {
MenuUtil.onDefaultMenuOptionsItemSelected(it, item, mDatabaseReadOnly, true)
}
return super.onOptionsItemSelected(item)
super.onOptionsItemSelected(item)
}
}
}

View File

@@ -199,6 +199,12 @@ object PreferencesUtil {
context.resources.getBoolean(R.bool.lock_database_back_root_default))
}
fun showLockDatabaseButton(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.lock_database_show_button_key),
context.resources.getBoolean(R.bool.lock_database_show_button_default))
}
fun isAutoSaveDatabaseEnabled(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.enable_auto_save_database_key),
@@ -348,4 +354,10 @@ object PreferencesUtil {
return prefs.getBoolean(context.getString(R.string.keyboard_key_sound_key),
context.resources.getBoolean(R.bool.keyboard_key_sound_default))
}
fun isAutofillAutoSearchEnable(context: Context): Boolean {
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
return prefs.getBoolean(context.getString(R.string.autofill_auto_search_key),
context.resources.getBoolean(R.bool.autofill_auto_search_default))
}
}

View File

@@ -26,6 +26,8 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import android.widget.ImageView
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.fragment.app.Fragment
@@ -47,6 +49,7 @@ open class SettingsActivity
private var coordinatorLayout: CoordinatorLayout? = null
private var toolbar: Toolbar? = null
private var lockView: View? = null
companion object {
@@ -84,6 +87,11 @@ open class SettingsActivity
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
lockView = findViewById(R.id.lock_button)
lockView?.setOnClickListener {
lockAndExit()
}
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, retrieveMainFragment())
@@ -154,6 +162,23 @@ open class SettingsActivity
keyFile: Uri?) {
}
private fun hideOrShowLockButton(key: NestedSettingsFragment.Screen) {
if (PreferencesUtil.showLockDatabaseButton(this)) {
when (key) {
NestedSettingsFragment.Screen.DATABASE,
NestedSettingsFragment.Screen.DATABASE_MASTER_KEY,
NestedSettingsFragment.Screen.DATABASE_SECURITY -> {
lockView?.visibility = View.VISIBLE
}
else -> {
lockView?.visibility = View.GONE
}
}
} else {
lockView?.visibility = View.GONE
}
}
override fun onBackPressed() {
// this if statement is necessary to navigate through nested and main fragments
if (supportFragmentManager.backStackEntryCount == 0) {
@@ -162,6 +187,7 @@ open class SettingsActivity
supportFragmentManager.popBackStack()
}
toolbar?.setTitle(R.string.settings)
hideOrShowLockButton(NestedSettingsFragment.Screen.APPLICATION)
}
private fun replaceFragment(key: NestedSettingsFragment.Screen) {
@@ -173,6 +199,7 @@ open class SettingsActivity
.commit()
toolbar?.title = NestedSettingsFragment.retrieveTitle(resources, key)
hideOrShowLockButton(key)
}
override fun onNestedPreferenceSelected(key: NestedSettingsFragment.Screen) {

View File

@@ -19,12 +19,15 @@
*/
package com.kunzisoft.keepass.utils
import android.app.AlarmManager
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Context.ALARM_SERVICE
import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import android.os.Build
import android.util.Log
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.Database
@@ -42,26 +45,34 @@ const val REMOVE_ENTRY_MAGIKEYBOARD_ACTION = "com.kunzisoft.keepass.REMOVE_ENTRY
class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
private val screenOffHandler = Handler()
private var screenOffRunnable: Runnable? = null
var mLockPendingIntent: PendingIntent? = null
override fun onReceive(context: Context, intent: Intent) {
screenOffRunnable?.let { runnable ->
screenOffHandler.removeCallbacks(runnable)
}
// If allowed, lock and exit
if (!TimeoutHelper.temporarilyDisableTimeout) {
intent.action?.let {
when (it) {
Intent.ACTION_SCREEN_ON -> {
cancelLockPendingIntent(context)
}
Intent.ACTION_SCREEN_OFF -> {
if (PreferencesUtil.isLockDatabaseWhenScreenShutOffEnable(context)) {
screenOffRunnable = Runnable {
lockAction.invoke()
}
mLockPendingIntent = PendingIntent.getBroadcast(context,
4575,
Intent(intent).apply {
action = LOCK_ACTION
},
0)
// Launch the effective action after a small time
screenOffHandler.postDelayed(screenOffRunnable!!,
context.getString(R.string.timeout_screen_off).toLong())
val first: Long = System.currentTimeMillis() + context.getString(R.string.timeout_screen_off).toLong()
val alarmManager = context.getSystemService(ALARM_SERVICE) as AlarmManager?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager?.setExact(AlarmManager.RTC_WAKEUP, first, mLockPendingIntent)
} else {
alarmManager?.set(AlarmManager.RTC_WAKEUP, first, mLockPendingIntent)
}
} else {
cancelLockPendingIntent(context)
}
}
LOCK_ACTION,
@@ -71,6 +82,14 @@ class LockReceiver(var lockAction: () -> Unit) : BroadcastReceiver() {
}
}
}
private fun cancelLockPendingIntent(context: Context) {
mLockPendingIntent?.let {
val alarmManager = context.getSystemService(ALARM_SERVICE) as AlarmManager?
alarmManager?.cancel(mLockPendingIntent)
mLockPendingIntent = null
}
}
}
fun Context.registerLockReceiver(lockReceiver: LockReceiver?,

View File

@@ -21,25 +21,77 @@ package com.kunzisoft.keepass.utils
import android.content.Context
import android.net.Uri
import android.text.format.Formatter
import androidx.documentfile.provider.DocumentFile
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
import com.kunzisoft.keepass.settings.PreferencesUtil
import java.io.Serializable
import java.text.DateFormat
import java.util.*
class FileDatabaseInfo : FileInfo {
class FileDatabaseInfo : Serializable {
constructor(context: Context, fileUri: Uri): super(context, fileUri)
private var context: Context
private var documentFile: DocumentFile? = null
var fileUri: Uri?
private set
constructor(context: Context, filePath: String): super(context, filePath)
constructor(context: Context, fileUri: Uri) {
this.context = context
this.fileUri = fileUri
init()
}
constructor(context: Context, filePath: String) {
this.context = context
this.fileUri = UriUtil.parse(filePath)
init()
}
fun init() {
documentFile = UriUtil.getFileData(context, fileUri)
}
var exists: Boolean = false
get() {
return documentFile?.exists() ?: field
}
private set
var canRead: Boolean = false
get() {
return documentFile?.canRead() ?: field
}
private set
var canWrite: Boolean = false
get() {
return documentFile?.canWrite() ?: field
}
private set
fun getModificationString(): String? {
return documentFile?.lastModified()?.let {
DateFormat.getDateTimeInstance()
.format(Date(it))
}
}
fun getSizeString(): String? {
return documentFile?.let {
Formatter.formatFileSize(context, it.length())
}
}
fun retrieveDatabaseAlias(alias: String): String {
return when {
alias.isNotEmpty() -> alias
PreferencesUtil.isFullFilePathEnable(context) -> filePath ?: ""
else -> fileName ?: ""
PreferencesUtil.isFullFilePathEnable(context) -> fileUri?.path ?: ""
else -> if (exists) documentFile?.name ?: "" else fileUri?.path ?: ""
}
}
fun retrieveDatabaseTitle(titleCallback: (String)->Unit) {
fileUri?.let { fileUri ->
FileDatabaseHistoryAction.getInstance(context.applicationContext)
.getFileDatabaseHistory(fileUri) { fileDatabaseHistoryEntity ->
@@ -48,5 +100,4 @@ class FileDatabaseInfo : FileInfo {
}
}
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright 2019 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.utils
import android.content.Context
import android.net.Uri
import android.text.format.Formatter
import java.io.Serializable
import java.text.DateFormat
import java.util.*
open class FileInfo : Serializable {
var context: Context
var fileUri: Uri?
var filePath: String? = null
var fileName: String? = ""
var lastModification = Date(0L)
var size: Long = 0L
constructor(context: Context, fileUri: Uri) {
this.context = context
this.fileUri = fileUri
init()
}
constructor(context: Context, filePath: String) {
this.context = context
this.fileUri = UriUtil.parse(filePath)
init()
}
fun init() {
this.filePath = fileUri?.path
UriUtil.getFileData(context, fileUri)?.let { file ->
size = file.length()
fileName = file.name
lastModification = Date(file.lastModified())
}
if (fileName == null || fileName!!.isEmpty()) {
fileName = filePath
}
}
fun lastModificationAccessible(): Boolean {
return lastModification.after(Date(0L))
}
fun sizeAccessible(): Boolean {
return size != 0L
}
fun dataAccessible(): Boolean {
return UriUtil.isUriAccessible(context.contentResolver, fileUri)
}
fun getModificationString(): String {
return DateFormat.getDateTimeInstance()
.format(lastModification)
}
fun getSizeString(): String {
return Formatter.formatFileSize(context, size)
}
}

View File

@@ -24,7 +24,6 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.documentfile.provider.DocumentFile
import com.kunzisoft.keepass.R
@@ -37,26 +36,6 @@ import java.util.*
object UriUtil {
fun isUriAccessible(contentResolver: ContentResolver, fileUri: Uri?): Boolean {
if (fileUri == null)
return false
return try {
//https://developer.android.com/reference/android/content/res/AssetFileDescriptor
contentResolver.openInputStream(fileUri)?.close()
true
} catch (e: Exception) {
Log.e(UriUtil.javaClass.name, "Unable to access uri $fileUri : ${e.message}")
false
}
}
fun isUriWritable(fileUri: Uri?): Boolean {
if (fileUri == null)
return false
// TODO Uri writeable detection
return true
}
fun getFileData(context: Context, fileUri: Uri?): DocumentFile? {
if (fileUri == null)
return null

View File

@@ -20,6 +20,7 @@ package com.kunzisoft.keepass.view
import android.content.Context
import android.graphics.Color
import android.text.util.Linkify
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
@@ -71,8 +72,8 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
private val urlContainerView: View
private val urlView: TextView
private val commentContainerView: View
private val commentView: TextView
private val notesContainerView: View
private val notesView: TextView
private val extrasContainerView: View
private val extrasView: ViewGroup
@@ -120,8 +121,8 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
urlContainerView = findViewById(R.id.entry_url_container)
urlView = findViewById(R.id.entry_url)
commentContainerView = findViewById(R.id.entry_notes_container)
commentView = findViewById(R.id.entry_notes)
notesContainerView = findViewById(R.id.entry_notes_container)
notesView = findViewById(R.id.entry_notes)
extrasContainerView = findViewById(R.id.extra_strings_container)
extrasView = findViewById(R.id.extra_strings)
@@ -289,15 +290,17 @@ class EntryContentsView @JvmOverloads constructor(context: Context,
fun assignComment(comment: String?) {
if (comment != null && comment.isNotEmpty()) {
commentContainerView.visibility = View.VISIBLE
commentView.apply {
notesContainerView.visibility = View.VISIBLE
notesView.apply {
text = comment
if (fontInVisibility)
applyFontVisibility()
}
try {
Linkify.addLinks(notesView, Linkify.ALL)
} catch (e: Exception) {}
} else {
commentContainerView.visibility = View.GONE
notesContainerView.visibility = View.GONE
}
}

View File

@@ -200,6 +200,7 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
val customFieldsArray = ArrayList<Field>()
// Add extra fields from views
entryExtraFieldsContainer.let {
try {
for (i in 0 until it.childCount) {
val view = it.getChildAt(i) as EntryEditCustomField
val key = view.label
@@ -207,6 +208,9 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
val protect = view.isProtected
customFieldsArray.add(Field(key, ProtectedString(protect, value)))
}
} catch (exception: Exception) {
// Extra field container contains another type of view
}
}
return customFieldsArray
}
@@ -215,12 +219,15 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
* Add a new view to fill in the information of the customized field and focus it
*/
fun addEmptyCustomField() {
// Fix current custom field before adding a new one
if (isValid()) {
val entryEditCustomField = EntryEditCustomField(context).apply {
setFontVisibility(fontInVisibility)
requestFocus()
}
entryExtraFieldsContainer.addView(entryEditCustomField)
}
}
/**
* Update a custom field or create a new one if doesn't exists
@@ -254,26 +261,34 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
* @return ErrorValidation An error with a message or a validation without message
*/
fun isValid(): Boolean {
var isValid = true
// Validate password
if (entryPasswordView.text.toString() != entryConfirmationPasswordView.text.toString()) {
entryPasswordLayoutView.error = context.getString(R.string.error_pass_match)
isValid = false
return false
} else {
entryPasswordLayoutView.error = null
}
// Validate extra fields
entryExtraFieldsContainer.let {
try {
val customFieldLabelSet = HashSet<String>()
for (i in 0 until it.childCount) {
val entryEditCustomField = it.getChildAt(i) as EntryEditCustomField
if (customFieldLabelSet.contains(entryEditCustomField.label)) {
entryEditCustomField.setError(R.string.error_label_exists)
return false
}
customFieldLabelSet.add(entryEditCustomField.label)
if (!entryEditCustomField.isValid()) {
isValid = false
return false
}
}
} catch (exception: Exception) {
return false
}
return isValid
}
return true
}
}

View File

@@ -30,6 +30,7 @@ import android.widget.CompoundButton
import android.widget.EditText
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.annotation.StringRes
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.element.security.ProtectedString
@@ -84,14 +85,20 @@ class EntryEditCustomField @JvmOverloads constructor(context: Context,
fun isValid(): Boolean {
// Validate extra field
if (label.isEmpty()) {
labelLayoutView.error = context.getString(R.string.error_string_key)
setError(R.string.error_string_key)
return false
} else {
labelLayoutView.error = null
setError(null)
}
return true
}
fun setError(@StringRes errorId: Int?) {
labelLayoutView.error = if (errorId == null) null else {
context.getString(errorId)
}
}
fun setFontVisibility(applyFontVisibility: Boolean) {
if (applyFontVisibility)
valueView.applyFontVisibility()

View File

@@ -0,0 +1,60 @@
package com.kunzisoft.keepass.view
import android.content.Context
import android.net.Uri
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.documentfile.provider.DocumentFile
import com.google.android.material.textfield.TextInputLayout
import com.kunzisoft.keepass.R
class KeyFileSelectionView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0)
: ConstraintLayout(context, attrs, defStyle) {
private var mUri: Uri? = null
private val keyFileNameInputLayout: TextInputLayout
private val keyFileNameView: TextView
private val keyFileOpenView: ImageView
init {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?
inflater?.inflate(R.layout.view_keyfile_selection, this)
keyFileNameInputLayout = findViewById(R.id.input_entry_keyfile)
keyFileNameView = findViewById(R.id.keyfile_name)
keyFileOpenView = findViewById(R.id.keyfile_open_button)
}
override fun setOnClickListener(l: OnClickListener?) {
super.setOnClickListener(l)
keyFileNameView.setOnClickListener(l)
}
override fun setOnLongClickListener(l: OnLongClickListener?) {
super.setOnLongClickListener(l)
keyFileNameView.setOnLongClickListener(l)
}
var error: CharSequence?
get() = keyFileNameInputLayout.error
set(value) {
keyFileNameInputLayout.error = value
}
var uri: Uri?
get() {
return mUri
}
set(value) {
mUri = value
keyFileNameView.text = value?.let {
DocumentFile.fromSingleUri(context, value)?.name ?: ""
} ?: ""
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorPrimaryDark" android:state_pressed="true" />
<item android:color="@color/grey_dark" android:state_enabled="false" />
<item android:color="?android:windowBackground" android:state_enabled="true" />
</selector>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="@color/white"
tools:targetApi="lollipop">
<item>
<shape>
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<solid android:color="?android:attr/windowBackground"/>
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="@color/white"
tools:targetApi="lollipop">
<item>
<shape>
<stroke
android:width="1dp"
android:color="?android:attr/textColorPrimary" />
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<solid
android:color="@color/transparent"/>
</shape>
</item>
</ripple>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true">
<shape>
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<padding
android:left="4dp"
android:right="12dp"
android:top="18dp"
android:bottom="8dp"/>
<solid android:color="@color/grey_dark"/>
</shape>
</item>
<item>
<shape>
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<padding
android:left="4dp"
android:right="12dp"
android:top="18dp"
android:bottom="8dp"/>
<solid android:color="@color/grey"/>
</shape>
</item>
</selector>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/white">
<item>
<shape>
<stroke
android:width="1dp"
android:color="@color/green" />
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<solid
android:color="@color/transparent"/>
</shape>
</item>
</selector>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M4,8h4L8,4L4,4v4zM10,20h4v-4h-4v4zM4,20h4v-4L4,16v4zM4,14h4v-4L4,10v4zM10,14h4v-4h-4v4zM16,4v4h4L20,4h-4zM10,8h4L14,4h-4v4zM16,14h4v-4h-4v4zM16,20h4v-4h-4v4z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z"/>
</vector>

View File

@@ -20,6 +20,7 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/toolbar_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -31,7 +32,6 @@
android:layout_height="@dimen/toolbar_parallax_height">
<com.google.android.material.appbar.CollapsingToolbarLayout
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -126,4 +126,10 @@
</androidx.core.widget.NestedScrollView>
<include
layout="@layout/view_button_lock"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="start|bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -102,6 +102,12 @@
</androidx.core.widget.NestedScrollView>
<include
layout="@layout/view_button_lock"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="start|bottom" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/entry_edit_validate"
android:layout_width="match_parent"

View File

@@ -24,45 +24,40 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:importantForAutofill="noExcludeDescendants"
android:background="?attr/colorPrimaryDark"
tools:targetApi="o">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/content_description_background"
android:background="@drawable/background_repeat"/>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/activity_file_selection_coordinator_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@drawable/background_repeat"
android:backgroundTint="?attr/colorPrimary"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/file_selection_buttons_container">
<androidx.core.widget.NestedScrollView
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_parallax_height">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<LinearLayout
android:id="@+id/file_selection_title_container"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
app:layout_collapseMode="parallax"
android:layout_gravity="center_horizontal|bottom"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent"
android:paddingLeft="24dp"
android:paddingStart="24dp"
android:paddingRight="24dp"
android:paddingEnd="24dp"
android:paddingTop="48dp"
android:paddingBottom="24dp"
android:layout_marginBottom="36dp">
android:paddingBottom="48dp">
<TextView
android:id="@+id/file_selection_title_part_1"
android:layout_width="wrap_content"
@@ -110,62 +105,48 @@
android:gravity="center"
android:text="@string/app_name_part3"/>
</LinearLayout>
<TextView android:id="@+id/label_warning"
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginStart="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:layout_marginEnd="@dimen/default_margin"
android:layout_marginBottom="@dimen/default_margin"
android:gravity="center"
android:textColor="?attr/textColorInverse"
app:layout_constraintTop_toBottomOf="@+id/file_selection_title_container"
android:visibility="gone" />
<LinearLayout
android:id="@+id/container_file_list"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_margin="24dp"
android:elevation="6dp"
android:background="?attr/colorPrimaryDark"
android:visibility="invisible"
app:layout_constraintWidth_percent="@dimen/content_percent"
app:layout_constraintTop_toBottomOf="@+id/label_warning"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:orientation="vertical">
<TextView
android:id="@+id/file_list_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
style="@style/KeepassDXStyle.TextAppearance.Title"
android:background="?attr/colorPrimary"
android:textColor="?android:attr/textColorHintInverse"
android:text="@string/open_recent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/file_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
android:background="?attr/colorPrimary" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="?attr/toolbarAppearance"
app:layout_constraintTop_toTopOf="parent"
android:elevation="4dp"
android:background="@color/transparent"
android:theme="?attr/toolbarAppearance"
app:layout_collapseMode="pin"
android:popupTheme="?attr/toolbarPopupAppearance" />
<FrameLayout
android:layout_width="48dp"
android:layout_height="?attr/actionBarSize"
android:padding="12dp"
android:elevation="4dp"
android:layout_gravity="top|start"
app:layout_collapseMode="pin">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/file_manager_explanation_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_folder_open_white_24dp"
app:tint="?android:attr/textColorHintInverse"
android:contentDescription="@string/about"/>
</FrameLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/file_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="insideOverlay"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<FrameLayout
android:id="@+id/file_selection_buttons_container"
@@ -182,7 +163,7 @@
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/open_database_button"
android:id="@+id/open_keyfile_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/select_database_file"
@@ -210,6 +191,11 @@
android:paddingEnd="24dp"
android:text="@string/create_keepass_file"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_gravity="top"
android:background="?attr/colorPrimaryDark"/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -140,12 +140,19 @@
android:background="?android:attr/windowBackground" />
</LinearLayout>
<include
layout="@layout/view_button_lock"
android:layout_width="48dp"
android:layout_height="48dp"
app:layout_anchor="@+id/node_list_container"
app:layout_anchorGravity="start|bottom" />
<com.kunzisoft.keepass.view.AddNodeButtonView
android:id="@+id/add_node_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@+id/node_list_container"
app:layout_anchorGravity="right|bottom" />
app:layout_anchorGravity="end|bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.kunzisoft.keepass.view.ToolbarAction

View File

@@ -162,58 +162,33 @@
</RelativeLayout>
<!-- File Input -->
<RelativeLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container_key_file"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/keyfile_checkox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:paddingBottom="20dp"
android:contentDescription="@string/content_description_keyfile_checkbox"
android:focusable="false"
android:layout_alignBottom="@+id/input_entry_keyfile"
android:gravity="center_vertical"/>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/input_entry_keyfile"
android:layout_width="wrap_content"
<com.kunzisoft.keepass.view.KeyFileSelectionView
android:id="@+id/keyfile_selection"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/keyfile_checkox"
app:layout_constraintEnd_toEndOf="parent"
android:importantForAccessibility="no"
android:importantForAutofill="no"
android:layout_toEndOf="@+id/keyfile_checkox"
android:layout_toRightOf="@+id/keyfile_checkox"
android:layout_toLeftOf="@+id/open_database_button"
android:layout_toStartOf="@+id/open_database_button">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/pass_keyfile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:hint="@string/entry_keyfile"
android:inputType="textUri"
android:importantForAccessibility="no"
android:importantForAutofill="no"
android:imeOptions="actionDone"
android:maxLines="1"/>
</com.google.android.material.textfield.TextInputLayout>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/open_database_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:layout_alignBottom="@+id/input_entry_keyfile"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:contentDescription="@string/content_description_open_file"
android:focusable="true"
android:src="@drawable/ic_folder_white_24dp"
android:tint="?attr/colorAccent"/>
</RelativeLayout>
android:importantForAutofill="no" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -239,7 +214,7 @@
android:paddingEnd="24dp"
android:paddingRight="24dp"
style="@style/KeepassDXStyle.TextAppearance.TinyText"
android:text="@string/warning_database_read_only"
android:text="@string/warning_database_link_revoked"
android:textColor="?attr/textColorInverse"
android:background="?attr/colorAccent"
app:layout_constraintBottom_toTopOf="@+id/activity_password_info_delimiter"

View File

@@ -17,8 +17,9 @@
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
-->
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/toolbar_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -38,4 +39,12 @@
android:layout_height="match_parent" />
</LinearLayout>
<include
layout="@layout/view_button_lock"
android:layout_width="48dp"
android:layout_height="48dp"
android:visibility="gone"
android:layout_gravity="start|bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -44,6 +44,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/nodes_list"
android:contentDescription="@string/content_description_node_children"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground" />

View File

@@ -109,44 +109,14 @@
android:layout_height="wrap_content"
android:text="@string/entry_keyfile"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/open_database_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:contentDescription="@string/content_description_open_file"
android:layout_alignTop="@+id/keyfile_input_layout"
android:layout_alignBottom="@+id/keyfile_input_layout"
android:padding="12dp"
android:src="@drawable/ic_folder_white_24dp"
android:tint="?attr/colorAccent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/keyfile_input_layout"
<com.kunzisoft.keepass.view.KeyFileSelectionView
android:id="@+id/keyfile_selection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/open_database_button"
android:layout_toStartOf="@+id/open_database_button"
android:importantForAccessibility="no"
android:importantForAutofill="no"
app:passwordToggleEnabled="true"
app:passwordToggleTint="?attr/colorAccent">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/pass_keyfile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAccessibility="no"
android:importantForAutofill="no"
android:hint="@string/hint_keyfile"
android:maxLines="1"
android:singleLine="true"/>
</com.google.android.material.textfield.TextInputLayout>
</RelativeLayout>
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/keyfile_checkox"
app:layout_constraintEnd_toEndOf="parent" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/green"
android:minHeight="24dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/autofill_app_id_icon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="center"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:contentDescription="@string/about"
android:src="@drawable/ic_apps_white_24dp"/>
<TextView
android:id="@+id/autofill_app_id_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textColor="@color/white"
android:layout_gravity="center"
android:paddingRight="12dp"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingStart="12dp" />
</LinearLayout>

View File

@@ -22,7 +22,7 @@
android:orientation="horizontal">
<ImageView
android:id="@+id/icon"
android:id="@+id/autofill_entry_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@@ -30,17 +30,17 @@
android:layout_marginEnd="12dp"
android:layout_marginLeft="12dp"
android:layout_marginStart="12dp"
android:src="@drawable/ic_key_white_24dp"
android:tint="@color/green"/>
android:contentDescription="@string/content_description_entry_icon"
android:src="@drawable/ic_key_white_24dp" />
<TextView
android:id="@+id/text"
android:id="@+id/autofill_entry_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingRight="12dp"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingStart="12dp"
android:paddingLeft="0dp"
android:paddingStart="0dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall" />
</LinearLayout>

View File

@@ -16,32 +16,27 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
android:minHeight="48dp"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:contentDescription="@string/app_name"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="@string/autofill_sign_in_prompt"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:layout_gravity="center"
android:paddingRight="12dp"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingStart="12dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall" />
</LinearLayout>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
layout="@layout/item_autofill_app_id"/>
<include
layout="@layout/item_autofill_unlock"/>
</LinearLayout>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
layout="@layout/item_autofill_web_domain"/>
<include
layout="@layout/item_autofill_unlock"/>
</LinearLayout>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?><!--
* Copyright (C) 2017 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/green"
android:minHeight="24dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/autofill_web_domain_icon"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_gravity="center"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:contentDescription="@string/about"
android:src="@drawable/ic_web_white_24dp"/>
<TextView
android:id="@+id/autofill_web_domain_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textColor="@color/white"
android:layout_gravity="center"
android:paddingRight="12dp"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingStart="12dp" />
</LinearLayout>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout
android:id="@+id/lock_button"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/lock_button_background"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="-2dp"
android:layout_marginLeft="-2dp"
android:layout_marginBottom="-2dp"
tools:targetApi="lollipop"
android:elevation="4dp"
style="@style/KeepassDXStyle.Special.Button.Background"
android:layout_gravity="bottom|start"
android:contentDescription="@string/menu_lock" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/lock_button_stroke"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="-2dp"
android:layout_marginLeft="-2dp"
android:layout_marginBottom="-2dp"
tools:targetApi="lollipop"
android:elevation="4dp"
style="@style/KeepassDXStyle.Special.Button.Stroke"
android:layout_gravity="bottom|start"
android:contentDescription="@string/menu_lock" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/lock_button_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:paddingBottom="6dp"
android:paddingTop="16dp"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingEnd="12dp"
android:paddingRight="12dp"
tools:targetApi="lollipop"
android:elevation="4dp"
android:src="@drawable/ic_lock_white_24dp"
android:tint="?android:attr/textColorPrimary"
android:layout_gravity="bottom|start"
android:contentDescription="@string/menu_lock" />
</FrameLayout>

View File

@@ -424,6 +424,16 @@
android:layout_height="wrap_content"
android:text="@string/entry_UUID"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/entry_UUID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.LabelTextStyle" />
</HorizontalScrollView>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -434,21 +444,6 @@
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TextEntryItem" />
</HorizontalScrollView>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_marginEnd="12dp"
android:layout_marginRight="12dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/entry_UUID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true"
style="@style/KeepassDXStyle.TextAppearance.TinyText"
android:textColor="?attr/colorAccent"/>
</HorizontalScrollView>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container_key_file"
android:layout_marginBottom="@dimen/default_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="noExcludeDescendants"
tools:ignore="UnusedAttribute">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/input_entry_keyfile"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:passwordToggleEnabled="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/keyfile_open_button">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/keyfile_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:hint="@string/entry_keyfile"
android:inputType="textPassword"
android:focusable="false"
android:cursorVisible="false"
android:focusableInTouchMode="false"
android:imeOptions="actionDone"
android:maxLines="1"/>
</com.google.android.material.textfield.TextInputLayout>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/keyfile_open_button"
android:layout_width="48dp"
android:layout_height="48dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:padding="12dp"
android:contentDescription="@string/content_description_open_file"
android:focusable="true"
android:background="@drawable/background_item_selection"
android:src="@drawable/ic_folder_white_24dp"
android:tint="?attr/colorAccent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -19,11 +19,6 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_lock"
android:icon="@drawable/ic_lock_white_24dp"
android:title="@string/menu_lock"
android:orderInCategory="81"
app:showAsAction="always" />
<item android:id="@+id/menu_save_database"
android:icon="@drawable/ic_save_white_24dp"
android:title="@string/menu_save_database"

View File

@@ -166,13 +166,11 @@
<string name="menu_open_file_read_and_write">قابل للتعديل</string>
<string name="select_database_file">فتح قاعدة بيانات موجودة</string>
<string name="create_keepass_file">انشاء قاعدة بيانات</string>
<string name="open_recent">قواعد البيانات الاخيرة</string>
<string name="omit_backup_search_title">لا تبحثفي مدخلات النسخ الاحتياطي</string>
<string name="progress_title">قيد العمل…</string>
<string name="read_only_warning">KeePassDX يحتاج صلاحية الكتابة من اجل تعديل قاعدة البيانات.</string>
<string name="encryption_explanation">خوارزمية تشفير جميع البيانات.</string>
<string name="unsupported_db_version">قاعدة بيانات غير مدعومة.</string>
<string name="warning_unmounted">اربط بطاقة الذاكرة لإنشاء او تحميل قاعدة بيانات.</string>
<string name="build_label">بناء %1$s</string>
<string name="encrypted_value_stored">تم حفظ كلمة السر المشفرة</string>
<string name="no_credentials_stored">قاعدة البيانات لا تمتلك كلمة سر.</string>

View File

@@ -107,7 +107,6 @@
<string name="never">Mai</string>
<string name="no_results">Cap resultat de cerca</string>
<string name="no_url_handler">Sense gestor per aquesta url.</string>
<string name="open_recent">Obre base de dades recent :</string>
<string name="omit_backup_search_title">No cerquis entrades a còpia de seguretat ni paperera</string>
<string name="omit_backup_search_summary">Omet els grups \'Còpia de seguretat\' i paperera dels resultats de cerca</string>
<string name="progress_create">Creant nova base de dades&#8230;</string>
@@ -128,7 +127,6 @@
<string name="underline">Subratllat</string>
<string name="unsupported_db_version">Versió de la base de dades no suportada.</string>
<string name="uppercase">Majúscules</string>
<string name="warning_unmounted">La teva tarja SD no està muntada al teu dispositiu. No podràs carregar ni guardar una base de dades.</string>
<string name="version_label">Versió %1$s</string>
<string name="education_unlock_summary">Introdueix una contrasenya i/o un arxiu clau per desbloquejar la base de dades.</string>

View File

@@ -113,7 +113,6 @@
<string name="never">Nikdy</string>
<string name="no_results">Žádné výsledky hledání</string>
<string name="no_url_handler">Pro otevření tohoto URL nainstalujte webový prohlížeč.</string>
<string name="open_recent">Nedávno otevřené databáze</string>
<string name="omit_backup_search_title">Neprohledávat položky v záloze</string>
<string name="omit_backup_search_summary">Vynechat skupiny „Záloha“ a \"Koš\" z výsledků vyhledávání</string>
<string name="progress_create">Vytvářím novou databázi…</string>
@@ -137,7 +136,6 @@
<string name="unsupported_db_version">Nepodporovaná verze databáze.</string>
<string name="uppercase">Velká písmena</string>
<string name="version_label">Verze %1$s</string>
<string name="warning_unmounted">Připojit paměťovou kartu pro založení a otevření databáze.</string>
<string name="education_unlock_summary">Databázi odemknete zadáním hesla a/nebo souboru s klíčem.
\n
\nNezapomeňte si po každé úpravě zazálohovat kopii svého .kdbx souboru na bezpečné místo.</string>
@@ -197,8 +195,8 @@
<string name="sort_last_access_time">Přístup</string>
<string name="warning">Varování</string>
<string name="warning_password_encoding">Nepoužívejte v hesle pro databázový soubor znaky mimo znakovou sadu Latin-1 (nepoužívejte znaky s diakritikou).</string>
<string name="warning_empty_password">Opravdu chcete ponechat databázi nechráněnou (bez hesla)?</string>
<string name="warning_no_encryption_key">Opravdu nechcete používat šifrovací klíč?</string>
<string name="warning_empty_password">Pokračovat bez ochrany odemknutím heslem\?</string>
<string name="warning_no_encryption_key">Pokračovat bez šifrovacího klíče\?</string>
<string name="configure_biometric">Biometrická pobídka je zařízením podporována, ale není nastavena.</string>
<string name="open_biometric_prompt_unlock_database">Otevři biometrickou pobídku k otevření databáze</string>
<string name="encrypted_value_stored">Šifrované heslo uloženo</string>
@@ -231,7 +229,7 @@
<string name="biometric_unlock_enable_summary">Nechá otevřít databázi snímáním biometrického údaje</string>
<string name="biometric_delete_all_key_title">Smazat šifrovací klíče</string>
<string name="biometric_delete_all_key_summary">Smazat všechny šifrovací klíče související s biometrickým rozlišením</string>
<string name="biometric_delete_all_key_warning">Opravdu chcete smazat všechny klíče související s biometrickým rozlišením\?</string>
<string name="biometric_delete_all_key_warning">Smazat všechny šifrovací klíče související s biometrickým rozlišením\?</string>
<string name="unavailable_feature_text">Tuto funkci se nedaří spustit.</string>
<string name="unavailable_feature_version">Verze %1$s vámi používaného systému Android nevyhovuje minimální verzi %2$s.</string>
<string name="unavailable_feature_hardware">Hardware nebyl rozpoznán.</string>
@@ -280,7 +278,7 @@
<string name="education_biometric_summary">Propojte své heslo a otisk prstu pro rychlé odemykání databáze.</string>
<string name="education_entry_edit_title">Upravit položku</string>
<string name="education_entry_edit_summary">Přidejte ke své položce vlastní kolonky. Společná data mohou být sdílena mezi více různými kolonkami.</string>
<string name="education_generate_password_title">Vytvořte k záznamu silné heslo.</string>
<string name="education_generate_password_title">Vytvořit silné heslo</string>
<string name="education_generate_password_summary">Vygenerujte silné heslo pro svou položku, definujte je podle kritérií formuláře, a nezapomeňte na bezpečné heslo.</string>
<string name="education_entry_new_field_title">Přidat vlastní kolonky</string>
<string name="education_entry_new_field_summary">Registrovat další kolonku, zadat hodnotu a volitelně ji ochránit.</string>
@@ -407,7 +405,7 @@
<string name="menu_security_settings">Nastavení zabezpečení</string>
<string name="menu_master_key_settings">Nastavení hlavního klíče</string>
<string name="contains_duplicate_uuid">Databáze obsahuje duplikátní UUID.</string>
<string name="contains_duplicate_uuid_procedure">Prověřením toho dialogu opraví KeePassDX chybu (založením nového UUID pro duplikáty) a bude pokračovat.</string>
<string name="contains_duplicate_uuid_procedure">Opravit chybu založením nového UUID pro duplikáty a pokračovat\?</string>
<string name="database_opened">Databáze otevřena</string>
<string name="clipboard_explanation_summary">Kopírujte pole záznamů pomocí schránky Vašeho zařízení</string>
<string name="advanced_unlock_explanation_summary">K snadnějšímu otevření databáze použijte pokročilé odemknutí</string>
@@ -433,24 +431,24 @@
<string name="menu_save_database">Uložit databázi</string>
<string name="menu_empty_recycle_bin">Vysypat koš</string>
<string name="command_execution">Provádím příkaz…</string>
<string name="warning_permanently_delete_nodes">Jste si jisti, že chcete natrvalo smazat vybrané uzly\?</string>
<string name="warning_permanently_delete_nodes">Natrvalo smazat vybrané uzly\?</string>
<string name="keystore_not_accessible">Úložiště klíčů není řádně inicializováno.</string>
<string name="credential_before_click_biometric_button">Zadejte heslo než kliknete na tlačítko biometriky.</string>
<string name="recycle_bin_group_title">Skupina Koš</string>
<string name="enable_auto_save_database_title">Uložit databázi automaticky</string>
<string name="enable_auto_save_database_summary">Automaticky uloží databázi po důležité akci (pouze v režimu \"Zápis\")</string>
<string name="enable_auto_save_database_summary">Uložit databázi po každé důležité akci (v režimu \"Zápis\")</string>
<string name="entry_attachments">Připojené soubory</string>
<string name="menu_restore_entry_history">Obnovit historii</string>
<string name="menu_delete_entry_history">Smazat historii</string>
<string name="keyboard_auto_go_action_title">Akce auto-klíče</string>
<string name="keyboard_auto_go_action_summary">Automatická akce klíče Jít po stisknutí klíče Pole</string>
<string name="keyboard_auto_go_action_summary">Akce klíče \"Jít\" po stisknutí klíče \"Položka\"</string>
<string name="download_attachment">Stáhnout %1$s</string>
<string name="download_initialization">Zahajuji…</string>
<string name="download_progression">Probíhá: %1$d%</string>
<string name="download_progression">Probíhá: %1$d&#37;</string>
<string name="download_finalization">Dokončuji…</string>
<string name="download_complete">Ukončeno! Klepnout pro otevření souboru.</string>
<string name="hide_expired_entries_title">Skrýt propadlé záznamy</string>
<string name="hide_expired_entries_summary">Propadlé záznamy budou skryty</string>
<string name="hide_expired_entries_summary">Propadlé záznamy jsou skryty</string>
<string name="contact">Kontakt</string>
<string name="contribution">Příspěvky</string>
<string name="feedback">Feedback</string>
@@ -465,7 +463,14 @@
<string name="hide_broken_locations_title">Skrýt špatné odkazy na databáze</string>
<string name="hide_broken_locations_summary">Skrýt špatné odkazy v seznamu nedávných databází</string>
<string name="warning_database_read_only">Udělit právo zápisu pro uložení změn v databázi</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft je &lt;strong&gt;otevřený software&lt;/strong&gt; a &lt;strong&gt;bey reklam&lt;/strong&gt;.
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft je &lt;strong&gt;svobodný software&lt;/strong&gt; a &lt;strong&gt;bey reklam&lt;/strong&gt;.
\nJe poskytován jak je, pod licencí &lt;strong&gt;GPLv3&lt;/strong&gt;, bez jakékoli záruky.</string>
<string name="html_about_contribution">Abychom si &lt;strong&gt;udrželi svoji svobodu&lt;/strong&gt;, &lt;strong&gt;opravili chyby&lt;/strong&gt;,&lt;strong&gt;doplnili funkce&lt;/strong&gt; a &lt;strong&gt;byli vždy aktivní&lt;/strong&gt;, počítáme s Vaším &lt;strong&gt;přispěním&lt;/strong&gt;.</string>
<string name="error_create_database">Nedaří se vytvořit soubor s databází.</string>
<string name="entry_add_attachment">Přidat přílohu</string>
<string name="discard">Zahodit</string>
<string name="discard_changes">Zahodit změny\?</string>
<string name="validate">Ověřit</string>
<string name="education_setup_OTP_summary">Nastavit správu One-Time hesla (HOTP / TOTP) pro založení tokenu požadovaného pro dvoufázové ověření (2FA).</string>
<string name="education_setup_OTP_title">Nastavit OTP</string>
</resources>

View File

@@ -112,7 +112,6 @@
<string name="never">Aldrig</string>
<string name="no_results">Ingen søgeresultater</string>
<string name="no_url_handler">Installer en web-browser til at åbne URL.</string>
<string name="open_recent">Seneste databaser</string>
<string name="omit_backup_search_title">Gennemsøg ikke backup poster</string>
<string name="omit_backup_search_summary">Udelader \"Sikkerhedskopiering\" og \"Papirkurv\" - grupper fra søgeresultater</string>
<string name="progress_create">Opretter ny database…</string>
@@ -135,7 +134,6 @@
<string name="underline">Understregning</string>
<string name="unsupported_db_version">Database-versionen er ikke understøttet.</string>
<string name="uppercase">Store bogstaver</string>
<string name="warning_unmounted">Monter hukommelseskortet for at oprette eller indlæse en database.</string>
<string name="version_label">Version %1$s</string>
<string name="education_unlock_summary">Angiv en adgangskode og/eller en nøglefil til at låse databasen op.
\n
@@ -197,7 +195,7 @@
<string name="warning">Advarsel</string>
<string name="warning_password_encoding">Undgå adgangskodetegn uden for tekstkodningsformatet i databasefilen (ukendte tegn konverteres til samme bogstav).</string>
<string name="warning_empty_password">Bekræft brug af ingen adgangskode til beskyttelse mod oplåsning\?</string>
<string name="warning_no_encryption_key">Bekræft ingen brug af en krypteringsnøgle?</string>
<string name="warning_no_encryption_key">Fortsæt uden krypteringsnøgle\?</string>
<string name="configure_biometric">Biometrisk prompt understøttes, men er ikke konfigureret.</string>
<string name="open_biometric_prompt_unlock_database">Åbn den biometriske prompt for at låse databasen op</string>
<string name="encrypted_value_stored">Krypteret adgangskode er gemt</string>
@@ -230,7 +228,7 @@
<string name="biometric_unlock_enable_summary">Lader dig scanne din biometrisk for at åbne databasen</string>
<string name="biometric_delete_all_key_title">Slet krypteringsnøgler</string>
<string name="biometric_delete_all_key_summary">Slet alle krypteringsnøgler, der er relateret til fingeraftryk</string>
<string name="biometric_delete_all_key_warning">Bekræft sletning af alle nøgler, der er relateret til fingeraftryksgenkendelse\?</string>
<string name="biometric_delete_all_key_warning">Slet alle nøgler, der er relateret til fingeraftryksgenkendelse\?</string>
<string name="unavailable_feature_text">Funktionen kunne ikke startes.</string>
<string name="unavailable_feature_version">Android-version %1$s opfylder ikke minimum versionskrav %2$s.</string>
<string name="unavailable_feature_hardware">Kunne ikke finde den tilsvarende hardware.</string>
@@ -279,7 +277,7 @@
<string name="education_biometric_summary">Link adgangskoden til det scannede fingeraftryk for hurtigt at låse databasen op.</string>
<string name="education_entry_edit_title">Rediger posten</string>
<string name="education_entry_edit_summary">Rediger post med brugerdefinerede felter. Pool data kan refereres mellem forskellige indtastningsfelter.</string>
<string name="education_generate_password_title">Opret en stærk adgangskode til posten.</string>
<string name="education_generate_password_title">Opret en stærk adgangskode</string>
<string name="education_generate_password_summary">Generer en stærk kodeord til at forbinde elementet, definer det i henhold til kriteriet for formularen og glem ikke et sikkert kodeord.</string>
<string name="education_entry_new_field_title">Tilføj brugerdefinerede felter</string>
<string name="education_entry_new_field_summary">Registrer et ekstra felt, tilføj en værdi og beskyt det eventuelt.</string>
@@ -323,7 +321,7 @@
<string name="keyboard_label">Magikeyboard (KeePassDX)</string>
<string name="keyboard_setting_label">Magikeyboard indstillinger</string>
<string name="keyboard_entry_category">Post</string>
<string name="keyboard_entry_timeout_title">Timeout</string>
<string name="keyboard_entry_timeout_title">Udløbstid</string>
<string name="keyboard_notification_entry_title">Meddelelsesinfo</string>
<string name="keyboard_notification_entry_summary">Vis en meddelelse, når en post er til rådighed</string>
<string name="keyboard_notification_entry_content_title_text">Post</string>
@@ -375,7 +373,7 @@
<string name="error_create_database_file">Kan ikke oprette database med denne adgangskode og nøglefil.</string>
<string name="menu_advanced_unlock_settings">Avanceret oplåsning</string>
<string name="biometric_prompt_store_credential_title">Gem biometrisk genkendelse</string>
<string name="biometric_prompt_store_credential_message">ADVARSEL: Brug af biometrisk genkendelse fritager ikke for at kende hovedadgangskode.</string>
<string name="biometric_prompt_store_credential_message">Advarsel: hovedadgangskoden skal stadig huskes, hvis der bruges biometrisk genkendelse.</string>
<string name="biometric_prompt_extract_credential_title">Åbn database med biometrisk genkendelse</string>
<string name="biometric_prompt_extract_credential_message">Uddrag databasens legitimationsoplysninger med biometriske data</string>
<string name="biometric">Biometrisk</string>
@@ -406,7 +404,7 @@
<string name="menu_security_settings">Sikkerhedsindstillinger</string>
<string name="menu_master_key_settings">Indstillinger for hovednøgle</string>
<string name="contains_duplicate_uuid">Databasen indeholder dublerede UUID\'er.</string>
<string name="contains_duplicate_uuid_procedure">Ved at godkende dialogboksen, vil KeePassDX løse problemet (ved at generere nye UUID\'er for dubletter) og fortsætte.</string>
<string name="contains_duplicate_uuid_procedure">Løs problemet ved at generere nye UUID\'er for dubletter til at fortsætte\?</string>
<string name="database_opened">Database åbnet</string>
<string name="clipboard_explanation_summary">Kopier indtastningsfelter ved hjælp af enhedens udklipsholder</string>
<string name="advanced_unlock_explanation_summary">Brug avanceret oplåsning for at gøre det lettere at åbne en database</string>
@@ -432,12 +430,12 @@
<string name="menu_save_database">Gem database</string>
<string name="menu_empty_recycle_bin">Tøm papirkurven</string>
<string name="command_execution">Udfører kommandoen…</string>
<string name="warning_permanently_delete_nodes">Bekræft sletning ad de markerede noder permanent\?</string>
<string name="warning_permanently_delete_nodes">Slet markerede noder permanent\?</string>
<string name="keystore_not_accessible">Nøglelageret er ikke korrekt initialiseret.</string>
<string name="credential_before_click_biometric_button">Skriv adgangskoden, før der klikkes på den biometriske knap.</string>
<string name="recycle_bin_group_title">Papirkurvsgruppe</string>
<string name="enable_auto_save_database_title">Gem automatisk database</string>
<string name="enable_auto_save_database_summary">Gem automatisk databasen efter en vigtig handling (kun i tilstanden \"Modificerbar\")</string>
<string name="enable_auto_save_database_summary">Gem databasen efter hver en vigtig handling (i tilstanden \"Modificerbar\")</string>
<string name="entry_attachments">Vedhæftninger</string>
<string name="menu_restore_entry_history">Gendan historik</string>
<string name="menu_delete_entry_history">Slet historik</string>
@@ -445,11 +443,11 @@
<string name="keyboard_auto_go_action_summary">Handling af Gå-tasten udføres automatisk, efter der er trykket på en Felt nøgle</string>
<string name="download_attachment">Hent %1$s</string>
<string name="download_initialization">Initialiserer…</string>
<string name="download_progression">I gang: %1$d%</string>
<string name="download_progression">I gang: %1$d&#37;</string>
<string name="download_finalization">Færdiggørelse…</string>
<string name="download_complete">Komplet! Tryk for at åbne filen.</string>
<string name="hide_expired_entries_title">Skjul udløbne poster</string>
<string name="hide_expired_entries_summary">Udløbne poster vil blive skjult</string>
<string name="hide_expired_entries_summary">Udløbne poster er skjult</string>
<string name="contact">Kontakt</string>
<string name="contribution">Bidrag</string>
<string name="feedback">Tilbagemelding</string>
@@ -467,4 +465,11 @@
<string name="hide_broken_locations_title">Skjule brudte databaselinks</string>
<string name="hide_broken_locations_summary">Skjul brudte links på listen over seneste databaser</string>
<string name="warning_database_read_only">Giv fil skriveadgang for at gemme databasændringer</string>
<string name="education_setup_OTP_summary">Opsætning af engangsadgangskodestyring (HOTP / TOTP) for at generere et token anmodet om tofaktorautentisering (2FA).</string>
<string name="education_setup_OTP_title">Opsætning af OTP</string>
<string name="error_create_database">Databasefilen kunne ikke oprettes.</string>
<string name="entry_add_attachment">Tilføj vedhæng</string>
<string name="discard">Kassér</string>
<string name="discard_changes">Kasser ændringer\?</string>
<string name="validate">Valider</string>
</resources>

View File

@@ -20,8 +20,11 @@
Translations from BoDEAN
Translations from Matthias Dill
Translations from David Ramiro
--><resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="feedback">Feedback</string>
-->
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="contact">Kontakt</string>
<string name="contribution">Mitwirken</string>
<string name="feedback">Rückmeldung</string>
<string name="homepage">Webseite</string>
<string name="about_description">Android-Implementierung des Passwortmanagers KeePass</string>
<string name="accept">Akzeptieren</string>
@@ -47,7 +50,8 @@
<string name="decrypting_db">Entschlüsselung der Datenbankinhalte…</string>
<string name="default_checkbox">Als Standard-Datenbank verwenden</string>
<string name="digits">Zahlen</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft. Alle Rechte vorbehalten. Die Nutzung der Software erfolgt auf eigene Verantwortung und ohne jegliche Garantie. Die Applikation ist frei und wird unter den Bedingungen der GNU GPL Version 3 (oder später) verbreitet und lizenziert.</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft ist &lt;strong&gt;quelloffen&lt;/strong&gt; und &lt;strong&gt;ohne Werbung&lt;/strong&gt;.\nDie Nutzung der Software erfolgt auf eigene Verantwortung und ohne jegliche Garantie. Die Applikation wird unter den Bedingungen der &lt;strong&gt;GPLv3&lt;/strong&gt; lizenziert.</string>
<string name="html_about_contribution">Damit wir &lt;strong&gt;unsere Unabhängigkeit erhalten&lt;/strong&gt;, &lt;strong&gt;Fehler korrigieren&lt;/strong&gt;, &lt;strong&gt;Funktionen hinzufügen&lt;/strong&gt; und &lt;strong&gt;weiterhin aktiv bleiben&lt;/strong&gt; können, zählen wir auf Ihren &lt;strong&gt;Beitrag&lt;/strong&gt;.</string>
<string name="select_database_file">Vorhandene Datenbank öffnen</string>
<string name="entry_accessed">Letzter Zugriff</string>
<string name="entry_cancel">Abbrechen</string>
@@ -118,9 +122,10 @@
<string name="never">Nie</string>
<string name="no_results">Keine Suchergebnisse</string>
<string name="no_url_handler">Bitte einen Webbrowser installieren, um diese URL zu öffnen.</string>
<string name="open_recent">Zuletzt geöffnete Datenbanken</string>
<string name="omit_backup_search_title">Papierkorb/Sicherungen nicht durchsuchen</string>
<string name="omit_backup_search_summary">Die Gruppen „Sicherung“ und „Papierkorb“ werden bei der Suche nicht berücksichtigt</string>
<string name="auto_focus_search_title">Schnellsuche</string>
<string name="auto_focus_search_summary">Beim Öffnen einer Datenbank eine Suche veranlassen</string>
<string name="progress_create">Neue Datenbank anlegen…</string>
<string name="progress_title">Ausführen…</string>
<string name="protection">Sicherheit</string>
@@ -144,7 +149,6 @@
<string name="uppercase">Großbuchstaben</string>
<string name="warning">Warnung</string>
<string name="warning_password_encoding">Passwortzeichen in der Datenbank vermeiden, die kein Text-Encoding-Format besitzen (nicht erkannte Zeichen werden in denselben Buchstaben umgewandelt).</string>
<string name="warning_unmounted">Die Speicher einbinden, um eine Datenbank erstellen oder laden zu können.</string>
<string name="version_label">Version %1$s</string>
<string name="education_unlock_summary">Geben Sie das Passwort und/oder die Schlüsseldatei ein, um Ihre Datenbank zu entsperren.
\n
@@ -175,7 +179,6 @@
<string name="lock_database_screen_off_title">Bildschirmsperre</string>
<string name="lock_database_screen_off_summary">Datenbank sperren, wenn der Bildschirm ausgeschaltet wird</string>
<string name="create_keepass_file">Neue Datenbank erstellen</string>
<string name="style_choose_title">App-Design</string>
<string name="assign_master_key">Hauptschlüssel zuweisen</string>
<string name="path">Pfad</string>
<string name="file_name">Dateiname</string>
@@ -195,7 +198,6 @@
<string name="general">Allgemein</string>
<string name="open_biometric_prompt_store_credential">Biometrische Abfrage öffnen, um Anmeldedaten zu speichern.</string>
<string name="no_credentials_stored">Diese Datenbank hat noch kein Passwort.</string>
<string name="style_choose_summary">App-Design, das in der App genutzt wird</string>
<string name="encryption">Verschlüsselung</string>
<string name="key_derivation_function">Schlüsselableitungsfunktion</string>
<string name="extended_ASCII">Erweiterte ASCII</string>
@@ -266,10 +268,10 @@
<string name="education_biometric_summary">Verknüpft Ihr Passwort mit Ihrer gescannten Biometrie, um Ihre Datenbank schnell zu entsperren.</string>
<string name="education_entry_edit_title">Eintrag bearbeiten</string>
<string name="education_entry_edit_summary">Bearbeiten Sie Ihren Eintrag mit persönlichen Feldern. Persönliche Felder können mit Querverweisen aus anderen Einträgen ergänzt werden.</string>
<string name="education_generate_password_title">Ein starkes Passwort für den Eintrag erstellen.</string>
<string name="education_generate_password_title">Ein starkes Passwort erstellen</string>
<string name="education_generate_password_summary">Erzeugung eines starken Passworts, das mit dem Eintrag verknüpft wird, nach Kriterien, die einfach in einem Formular festgelegt werden. Dabei an die Passwortsicherheit denken.</string>
<string name="education_entry_new_field_title">Benutzerdefinierte Felder hinzufügen</string>
<string name="education_entry_new_field_summary">Ein wichtiges, nicht mitgeliefertes Feld erfassen, indem ein neues Feld ausgefüllt wird, das sich auch schützen lässt.</string>
<string name="education_entry_new_field_summary">Tragen Sie ein zusätzliches Feld ein, fügen Sie einen Wert hinzu und schützen Sie es optional.</string>
<string name="education_unlock_title">Die Datenbank entsperren</string>
<string name="education_field_copy_title">Ein Feld kopieren</string>
<string name="education_field_copy_summary">Kopierte Felder können an beliebiger Stelle eingefügt werden.
@@ -281,24 +283,24 @@
<string name="education_sort_summary">Auswählen, wie Einträge und Gruppen sortiert werden.</string>
<string name="education_donation_title">Mitmachen</string>
<string name="education_donation_summary">Mithelfen, um Stabilität und Sicherheit zu verbessern und weitere Funktionen zu ermöglichen.</string>
<string name="html_text_ad_free">Anders als viele andere Passwortmanager ist dieser &lt;strong&gt;werbefrei&lt;/strong&gt;, &lt;strong&gt;quelloffen&lt;/strong&gt; und unter <stark>Copyleft lizenziert</stark>. &lt;strong&gt;Es werden keine persönlichen Daten gesammelt&lt;/strong&gt;, in welcher Form auch immer, egal welche Version (kostenlos oder pro) Sie verwenden.</string>
<string name="html_text_ad_free">Anders als viele andere Passwortmanager ist dieser &lt;strong&gt;werbefrei&lt;/strong&gt;, &lt;strong&gt;quelloffen&lt;/strong&gt; und unter &lt;strong&gt;Copyleft lizenziert&lt;/strong&gt;. Es werden keine persönlichen Daten gesammelt, in welcher Form auch immer, egal welche Version (kostenlos oder pro) Sie verwenden.</string>
<string name="html_text_buy_pro">Mit dem Kauf der Pro-Version erhält man Zugang zu dieser &lt;strong&gt;visuellen Funktion&lt;/strong&gt; und unterstützt insbesondere &lt;strong&gt;die Umsetzung gemeinschaftlicher Projektarbeiten.&lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Dieser &lt;strong&gt;visuelle Stil&lt;/strong&gt; wurde wegen Ihrer Großzügigkeit freigeschaltet.</string>
<string name="html_text_donation">Um unsere Freiheit zu bewahren und immer aktiv zu bleiben, zählen wir auf Ihren &lt;strong&gt;Beitrag.&lt;/strong&gt;</string>
<string name="html_text_dev_feature">Diese Funktion ist &lt;strong&gt;in Entwicklung&lt;/strong&gt; und erfordert &lt;strong&gt;Ihren Beitrag&lt;/strong&gt;, um bald verfügbar zu sein.</string>
<string name="html_text_dev_feature_buy_pro">Durch den Kauf der &lt;strong&gt;Pro-Version&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">Durch Ihr &lt;strong&gt;Mitwirken&lt;/strong&gt;,</string>
<string name="html_text_dev_feature_encourage">du bestärkst die Entwickler:innen, &lt;strong&gt;neue Funktionen&lt;/strong&gt; einzuführen und gemäß deinen&lt;strong&gt; Anmerkungen &lt;strong&gt;Fehler auszumerzen&lt;/strong&gt;.&lt;strong&gt;neue Funktionen&lt;/strong&gt; einzuführen und gemäß Ihren Anmerkungen &lt;strong&gt;Fehler auszumerzen&lt;/strong&gt;.</string>
<string name="html_text_dev_feature_encourage">Sie ermutigen die Entwickler:innen, &lt;strong&gt;neue Funktionen&lt;/strong&gt; einzuführen und gemäß Ihren Anmerkungen &lt;strong&gt;Fehler zu beheben&lt;/strong&gt;.</string>
<string name="html_text_dev_feature_thanks">Vielen Dank für Ihre Unterstützung.</string>
<string name="html_text_dev_feature_work_hard">Wir bemühen uns, diese Funktion bald zu veröffentlichen.</string>
<string name="html_text_dev_feature_upgrade">Vergessen Sie nicht, Ihre App aktuell zu halten indem sie neue Versionen installieren.</string>
<string name="html_text_dev_feature_upgrade">Vergessen Sie nicht, Ihre App aktuell zu halten, indem Sie neue Versionen installieren.</string>
<string name="download">Download</string>
<string name="contribute">Unterstützen</string>
<string name="encryption_chacha20">ChaCha20</string>
<string name="kdf_AES">AES</string>
<string name="kdf_Argon2">Argon2</string>
<string name="icon_pack_choose_title">Symbolepaket</string>
<string name="icon_pack_choose_summary">In der App verwendetes Symbolepaket</string>
<string name="icon_pack_choose_title">Symbolpaket</string>
<string name="icon_pack_choose_summary">In der App verwendetes Symbolpaket</string>
<string name="error_move_folder_in_itself">Eine Gruppe kann nicht in sich selbst verschoben werden.</string>
<string name="menu_copy">Kopieren</string>
<string name="menu_move">Verschieben</string>
@@ -344,6 +346,14 @@
<string name="keyboard_key_vibrate_title">Vibrierende Tastendrücke</string>
<string name="keyboard_key_sound_title">Hörbare Tastendrücke</string>
<string name="selection_mode">Auswahlmodus</string>
<string name="remember_database_locations_title">Speicherort der Datenbanken</string>
<string name="remember_database_locations_summary">Speicherort der Datenbanken merken</string>
<string name="remember_keyfile_locations_title">Speicherort der Schlüsseldateien</string>
<string name="remember_keyfile_locations_summary">Speicherort der Schlüssel zu Datenbanken merken</string>
<string name="show_recent_files_title">Zuletzt verwendete Dateien anzeigen</string>
<string name="show_recent_files_summary">Speicherort zuletzt verwendeter Datenbanken anzeigen</string>
<string name="hide_broken_locations_title">Defekte Datenbankverknüpfungen ausblenden</string>
<string name="hide_broken_locations_summary">Nicht funktionierende Verknüpfungen in der Liste der zuletzt verwendeten Datenbanken ausblenden</string>
<string name="do_not_kill_app">Nicht die App beenden…</string>
<string name="lock_database_back_root_summary">Datenbank sperren, wenn auf dem Hauptbildschirm der Zurück-Button gedrückt wird</string>
<string name="clear_clipboard_notification_title">Beim Schließen löschen</string>
@@ -410,7 +420,7 @@
<string name="menu_security_settings">Sicherheits-Einstellungen</string>
<string name="menu_master_key_settings">Hauptschlüssel-Einstellungen</string>
<string name="contains_duplicate_uuid">Die Datenbank enthält UUID-Duplikate.</string>
<string name="contains_duplicate_uuid_procedure">Durch die Validierung dieses Dialogs wird KeePassDX das Problem (durch Erzeugung neuer UUIDs für Duplikate) beheben und weiter ausgeführt.</string>
<string name="contains_duplicate_uuid_procedure">Problem lösen, indem neue UUIDs für Duplikate generiert werden und danach fortfahren\?</string>
<string name="database_opened">Datenbank geöffnet</string>
<string name="clipboard_explanation_summary">Eintragsfelder mithilfe der Zwischenablage des Geräts kopieren</string>
<string name="advanced_unlock_explanation_summary">Erweitertes Entsperren verwenden, um eine Datenbank einfacher zu öffnen.</string>
@@ -441,7 +451,7 @@
<string name="credential_before_click_biometric_button">Geben Sie das Passwort ein, bevor Sie auf den Biometrie-Button klicken.</string>
<string name="recycle_bin_group_title">Papierkorb-Gruppe</string>
<string name="enable_auto_save_database_title">Datenbank automatisch speichern</string>
<string name="enable_auto_save_database_summary">Automatisches Speichern der Datenbank nach einer wichtigen Aktion (nur im Modus \"Bearbeiten\")</string>
<string name="enable_auto_save_database_summary">Automatisches Speichern der Datenbank nach einer wichtigen Aktion (im Modus \"Bearbeiten\")</string>
<string name="entry_attachments">Anhänge</string>
<string name="menu_restore_entry_history">Historie wiederherstellen</string>
<string name="menu_delete_entry_history">Historie löschen</string>
@@ -450,8 +460,27 @@
<string name="download_attachment">%1$s herunterladen</string>
<string name="download_initialization">Initialisieren…</string>
<string name="download_progression">Fortschritt: %1$d&#37;</string>
<string name="download_finalization">Fertigstellung</string>
<string name="download_finalization">Fertigstellen</string>
<string name="download_complete">Vollständig! Tippen Sie, um die Datei zu öffnen.</string>
<string name="hide_expired_entries_title">Abgelaufene Einträge ausblenden</string>
<string name="hide_expired_entries_summary">Abgelaufene Einträge werden ausgeblendet</string>
<string name="style_choose_title">App-Design</string>
<string name="style_choose_summary">App-Design, das in der App genutzt wird</string>
<string-array name="list_style_names">
<item>Hell</item>
<item>Dunkel</item>
<item>Schwarz</item>
<item>Klassisch Dunkel</item>
<item>Himmel und Meer</item>
<item>Roter Vulkan</item>
<item>Purple Pro</item>
</string-array>
<string name="warning_database_read_only">Datei Schreibrechte gewähren, um Datenbankänderungen zu speichern</string>
<string name="education_setup_OTP_summary">Einrichten einer Einmal-Passwortverwaltung (HOTP / TOTP), um ein Token zu generieren, das für die Zwei-Faktor-Authentifizierung (2FA) angefordert wird.</string>
<string name="education_setup_OTP_title">Einrichten von OTP</string>
<string name="error_create_database">Es ist nicht möglich, eine Datenbankdatei zu erstellen.</string>
<string name="entry_add_attachment">Anhang hinzufügen</string>
<string name="discard">Verwerfen</string>
<string name="discard_changes">Änderungen verwerfen\?</string>
<string name="validate">Validieren</string>
</resources>

View File

@@ -113,7 +113,6 @@
<string name="never">Ποτέ</string>
<string name="no_results">Δεν βρέθηκαν αποτελέσματα αναζήτησης</string>
<string name="no_url_handler">Εγκαταστήστε ένα πρόγραμμα περιήγησης για να ανοίξετε αυτήν τη διεύθυνση URL.</string>
<string name="open_recent">Πρόσφατες βάσεις δεδομένων</string>
<string name="omit_backup_search_title">Να μην γίνει αναζήτηση μέσα από τις καταχωρήσεις αντιγραφών ασφαλείας</string>
<string name="omit_backup_search_summary">Παράληψη ομάδας \"Αντίγραφο Ασφαλείας\" και \"Κάδος Ανακύκλωσης\" από τα αποτελέσματα αναζήτησης</string>
<string name="progress_create">Δημιουργία νέας βάσης δεδομένων…</string>
@@ -136,7 +135,6 @@
<string name="underline">Υπογράμμιση</string>
<string name="unsupported_db_version">Μη υποστηριζόμενη έκδοση βάσης δεδομένων.</string>
<string name="uppercase">Κεφαλαία</string>
<string name="warning_unmounted">Μοντάρετε την κάρτα μνήμης για να δημιουργήσετε ή να φορτώσετε μια βάση δεδομένων.</string>
<string name="version_label">Έκδοση %1$s</string>
<string name="education_unlock_summary">Καταχωρίστε τον κωδικό πρόσβασης και /ή το αρχείο-κλειδί για να ξεκλειδώσετε τη βάση δεδομένων σας.
\n

View File

@@ -105,7 +105,6 @@
<string name="never">Nunca</string>
<string name="no_results">Sin resultado de búsqueda</string>
<string name="no_url_handler">Instale un navegador web para abrir este URL.</string>
<string name="open_recent">Bases de datos recientes</string>
<string name="omit_backup_search_title">No buscar en las entradas de respaldo</string>
<string name="omit_backup_search_summary">Omite los grupos «Respaldo» y «Papelera de reciclaje» de los resultados de búsqueda</string>
<string name="progress_create">Creando nueva base de datos…</string>
@@ -125,7 +124,6 @@
<string name="underline">Subrayado</string>
<string name="unsupported_db_version">No se admite esta versión de la base de datos.</string>
<string name="uppercase">Mayúsculas</string>
<string name="warning_unmounted">Monte la tarjeta SD para crear o cargar una base de datos.</string>
<string name="version_label">Versión %1$s</string>
<string name="education_unlock_summary">Introduzca una contraseña y/o un archivo de clave para desbloquear su base de datos.</string>
<string-array name="timeout_options">

View File

@@ -115,7 +115,6 @@
<string name="never">Inoiz ez</string>
<string name="no_results">Emaitzarik gabeko bilaketa</string>
<string name="no_url_handler">URL kudatzeko euskarririk ez.</string>
<string name="open_recent">Duela gutxiko datubasea ireki :</string>
<string name="omit_backup_search_title">Ez bilatu segurtasun kopiaren sarreretan</string>
<string name="omit_backup_search_summary">Kendu segurtasun kopien taldea bilaketen emaitzetatik (.kdb fitxategie dagokie bakarrik)</string>
<string name="progress_create">Datubase berria sortzen…</string>
@@ -137,7 +136,6 @@
<string name="underline">Azpimarratu</string>
<string name="unsupported_db_version">Euskarririk gabeko datubase bertsioa.</string>
<string name="uppercase">Maiuskulak</string>
<string name="warning_unmounted">Une honetan zure sd txartela ez dago montatua zure dispositiboan. Ezingo duzu zure datubasea kargatu edo sortu.</string>
<string name="version_label">Bertsioa %1$s</string>
<string name="education_unlock_summary">Sartu pasahitz eta / edo gako fitxategi bat zure datubasea desblokeatzeko.</string>

View File

@@ -114,7 +114,6 @@
<string name="never">Ei koskaan</string>
<string name="no_results">Ei hakutuloksia</string>
<string name="no_url_handler">Tälle URL:lle ei ole käsittelijää.</string>
<string name="open_recent">Avaa viimeisin salasanatietokanta :</string>
<string name="omit_backup_search_title">Älä etsi varmuuskopioista eikä roskakorista</string>
<string name="omit_backup_search_summary">Poista \'Varmuuskopiot\' ja roskakori hakutuloksista</string>
<string name="progress_create">Luodaan uutta tietokantaa&#8230;</string>
@@ -136,7 +135,6 @@
<string name="underline">Alleviivattu</string>
<string name="unsupported_db_version">Ei-tuettu salasanatietokannan versio.</string>
<string name="uppercase">Isot kirjaimet</string>
<string name="warning_unmounted">SD-korttia ei löydy. Et voi ladata tai tallentaa salasanatietokantaa.</string>
<string name="version_label">Versio %1$s</string>
<string name="education_unlock_summary">Syötä salasana ja/tai avaintiedosto avataksesi tietokantasi.</string>

View File

@@ -16,7 +16,8 @@
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
--><resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
-->
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="feedback">Commentaires</string>
<string name="homepage">Page daccueil</string>
<string name="about_description">Implémentation Android du gestionnaire de mots de passe KeePass</string>
@@ -49,7 +50,7 @@
<string name="decrypting_db">Déchiffrement du contenu de la base de données…</string>
<string name="default_checkbox">Utiliser comme base de données par défaut</string>
<string name="digits">Chiffres</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft est &lt;strong&gt;libre&lt;/strong&gt; et &lt;strong&gt;sans publicité&lt;/strong&gt;. \nIl est fourni tel quel, sous la licence &lt;strong&gt;GPLv3&lt;/strong&gt;, sans aucune garantie.</string>
<string name="html_about_licence"> Key Derivation Functions </string>
<string name="entry_accessed">Dernier accès</string>
<string name="entry_cancel">Annuler</string>
<string name="entry_notes">Notes</string>
@@ -123,7 +124,6 @@
<string name="no_results">Aucun résultat</string>
<string name="no_url_handler">Installer un navigateur Web pour ouvrir cette URL.</string>
<string name="select_database_file">Ouvrir une base de données existante</string>
<string name="open_recent">Bases de données récentes</string>
<string name="omit_backup_search_title">Ne pas rechercher dans les entrées sauvegardées</string>
<string name="omit_backup_search_summary">Omet les groupes «Sauvegarde» et «Corbeille» des résultats de recherche</string>
<string name="progress_create">Création dune nouvelle base de données…</string>
@@ -162,9 +162,8 @@
<string name="uppercase">Majuscules</string>
<string name="warning">Alerte</string>
<string name="warning_password_encoding">Éviter les caractères en dehors du format de codage de caractères du fichier de base de données (les caractères non reconnus sont convertis en une même lettre).</string>
<string name="warning_unmounted">Monter la carte mémoire pour créer ou charger une base de données.</string>
<string name="warning_empty_password">Ne voulez-vous vraiment aucune protection de déverrouillage par mot de passe\?</string>
<string name="warning_no_encryption_key">Êtes-vous sûr de ne vouloir utiliser aucune clé de chiffrement\?</string>
<string name="warning_empty_password">Continuer sans protection de déverrouillage par mot de passe\?</string>
<string name="warning_no_encryption_key">Continuer sans clé de chiffrement\?</string>
<string name="version_label">Version %1$s</string>
<string name="configure_biometric">La reconnaissance biométrique est prise en charge mais nest pas configurée.</string>
<string name="open_biometric_prompt_unlock_database">Ouvrir linvite biométrique pour déverrouiller la base de données</string>
@@ -198,7 +197,7 @@
<string name="biometric_unlock_enable_summary">Permet de numériser votre empreinte biométrique pour ouvrir la base de données</string>
<string name="biometric_delete_all_key_title">Supprimer les clés de chiffrement</string>
<string name="biometric_delete_all_key_summary">Supprime toutes les clés de chiffrement liées à la reconnaissance biométrique</string>
<string name="biometric_delete_all_key_warning">Êtes-vous sûr de vouloir supprimer toutes les clés liées à la reconnaissance biométrique\?</string>
<string name="biometric_delete_all_key_warning">Supprimer toutes les clés de chiffrement liées à la reconnaissance biométrique\?</string>
<string name="unavailable_feature_text">Impossible de démarrer cette fonctionnalité.</string>
<string name="unavailable_feature_version">Votre version dAndroid %1$s est inférieure à la version minimale %2$s requise.</string>
<string name="unavailable_feature_hardware">Impossible de trouver le matériel correspondant.</string>
@@ -243,7 +242,7 @@
<string name="education_biometric_summary">Associe votre mot de passe à votre empreinte biométrique numérisée pour déverrouiller rapidement votre base de données.</string>
<string name="education_entry_edit_title">Modifier lentrée</string>
<string name="education_entry_edit_summary">Modifie votre entrée avec des champs personnalisés. La collection des données peut être référencée entre différents champs de lentrée.</string>
<string name="education_generate_password_title">Créer un mot de passe fort pour votre entrée.</string>
<string name="education_generate_password_title">Créer un mot de passe fort</string>
<string name="education_generate_password_summary">Générez un mot de passe fort à associer avec votre entrée, définissez-le facilement en fonction des critères du formulaire et noubliez pas de sécuriser votre mot de passe.</string>
<string name="education_entry_new_field_title">Ajoutez des champs personnalisés</string>
<string name="education_entry_new_field_summary">Enregistrez un champ additionnel, ajoutez une valeur et facultativement le protéger.</string>
@@ -416,7 +415,7 @@
<string name="menu_security_settings">Paramètres de sécurité</string>
<string name="menu_master_key_settings">Paramètres de la clé maîtresse</string>
<string name="contains_duplicate_uuid">La base de données contient des doublons dUUID.</string>
<string name="contains_duplicate_uuid_procedure">En validant cette boîte de dialogue, KeePassDX corrigera le problème (en générant de nouveaux UUID pour les doublons) et continuera.</string>
<string name="contains_duplicate_uuid_procedure">Résoudre le problème en générant de nouveaux UUID pour les doublons et continuer\?</string>
<string name="database_opened">Base de données ouverte</string>
<string name="clipboard_explanation_summary">Copie les champs dune entrée à laide du presse-papier de votre appareil</string>
<string name="advanced_unlock_explanation_summary">Utilise le déverrouillage avancé pour ouvrir plus facilement une base de données</string>
@@ -442,24 +441,24 @@
<string name="menu_save_database">Enregistrer la base de données</string>
<string name="menu_empty_recycle_bin">Vider la corbeille</string>
<string name="command_execution">Exécution de la commande…</string>
<string name="warning_permanently_delete_nodes">Êtes-vous sûr de vouloir supprimer définitivement les nœuds sélectionnés\?</string>
<string name="warning_permanently_delete_nodes">Supprimer définitivement les nœuds sélectionnés\?</string>
<string name="keystore_not_accessible">Le magasin de clés nest pas correctement initialisé.</string>
<string name="credential_before_click_biometric_button">Saisissez le mot de passe avant de cliquer sur le bouton biométrique.</string>
<string name="recycle_bin_group_title">Groupe de la corbeille</string>
<string name="enable_auto_save_database_title">Enregistrement automatique de la base de données</string>
<string name="enable_auto_save_database_summary">Enregistre automatiquement la base de données après une action importante (uniquement en mode «Modifiable»)</string>
<string name="enable_auto_save_database_summary">Enregistre la base de données après chaque action importante (en mode « Modifiable »)</string>
<string name="entry_attachments">Attachements</string>
<string name="menu_restore_entry_history">Restaurer l\'historique</string>
<string name="menu_delete_entry_history">Effacer l\'historique</string>
<string name="keyboard_auto_go_action_title">Action de touche auto</string>
<string name="keyboard_auto_go_action_summary">Action de la touche Go effectuée automatiquement après avoir appuyé sur une touche de champ</string>
<string name="keyboard_auto_go_action_summary">Action de la touche « Go » après avoir appuyé sur une touche « Champ »</string>
<string name="download_attachment">Téléchargement %1$s</string>
<string name="download_initialization">Initialisation…</string>
<string name="download_progression">En cours : %1$d%</string>
<string name="download_progression">En cours : %1$d&#37;</string>
<string name="download_finalization">Finalisation…</string>
<string name="download_complete">Terminé ! Appuyer pour ouvrir le fichier.</string>
<string name="hide_expired_entries_title">Masquer les entrées expirées</string>
<string name="hide_expired_entries_summary">Les entrées expirées seront masquées</string>
<string name="hide_expired_entries_summary">Les entrées expirées sont cachées</string>
<string name="contact">Contact</string>
<string name="contribution">Contribution</string>
<string name="html_about_contribution">Afin de &lt;strong&gt;garder notre liberté&lt;/strong&gt;, &lt;strong&gt;corriger les bugs&lt;/strong&gt;, &lt;strong&gt;ajouter des fonctionnalités&lt;/strong&gt; et &lt;strong&gt;être toujours actif&lt;/strong&gt;, nous comptons sur votre &lt;strong&gt;contribution&lt;/strong&gt;.</string>
@@ -474,4 +473,11 @@
<string name="hide_broken_locations_title">Masquer les liens rompus de base de données</string>
<string name="hide_broken_locations_summary">Masquer les liens rompus dans la liste des bases de données récentes</string>
<string name="warning_database_read_only">Accorder un accès en écriture au fichier pour enregistrer les modifications de la base de données</string>
<string name="education_setup_OTP_summary">Définir le mot de passe à usage unique (temporel ou évènementiel) pour générer un jeton demandé par lauthentification à deux facteurs (A2F).</string>
<string name="education_setup_OTP_title">Définir lOTP</string>
<string name="error_create_database">Impossible de créer le fichier de base de données.</string>
<string name="entry_add_attachment">Ajouter une pièce jointe</string>
<string name="discard">Abandonner</string>
<string name="discard_changes">Abandonner les modifications\?</string>
<string name="validate">Valider</string>
</resources>

View File

@@ -132,7 +132,6 @@
<string name="no_url_handler">Instalirajte web preglednik da bi ste otvorili ovaj URL.</string>
<string name="select_database_file">Otvori postojeću bazu podataka</string>
<string name="create_keepass_file">Kreiraj novu bazu podataka</string>
<string name="open_recent">Nedavne baze podataka</string>
<string name="omit_backup_search_title">Ne pretražuj kopije unosa</string>
<string name="progress_create">Kreiranje nove baze podataka…</string>
<string name="protection">Zaštita</string>

View File

@@ -114,7 +114,6 @@
<string name="never">Soha</string>
<string name="no_results">Nincs találat</string>
<string name="no_url_handler">Telepítsen egy webböngészőt az URL megnyitásához.</string>
<string name="open_recent">Korábbi adatbázisok</string>
<string name="omit_backup_search_title">Ne keressen a biztonsági mentésekben</string>
<string name="omit_backup_search_summary">A „Biztonsági mentés” csoport kihagyása a keresésből (csak a .kdb fájlokra érvényes)</string>
<string name="progress_create">Új adatbázis létrehozása…</string>
@@ -140,7 +139,6 @@
<string name="uppercase">Nagybetűs</string>
<string name="warning">Figyelmeztetés</string>
<string name="warning_password_encoding">Kerülje a Latin-1 karakterkészlettől eltérő jelszókaraktereket a .kbd fájlokban, mert ugyanarra a betűre lesznek átalakítva.</string>
<string name="warning_unmounted">Csatolja az SD kártyát, hogy adatbázist hozzon létre vagy töltsön be.</string>
<string name="version_label">Verzió: %1$s</string>
<string name="configure_biometric">Az ujjlenyomat-leolvasás támogatott, de nincs beállítva.</string>
<string name="open_biometric_prompt_unlock_database">Ujjlenyomat-leolvasás</string>

View File

@@ -27,7 +27,7 @@
<string name="add_group">Aggiungi gruppo</string>
<string name="encryption_algorithm">Algoritmo di cifratura</string>
<string name="app_timeout">Scadenza app</string>
<string name="app_timeout_summary">Inattività prima del blocco dell\'app</string>
<string name="app_timeout_summary">Tempo di inattività prima del blocco dell\'app</string>
<string name="application">App</string>
<string name="menu_app_settings">Impostazioni app</string>
<string name="brackets">Parentesi</string>
@@ -44,7 +44,7 @@
<string name="decrypting_db">Decodifica contenuto database…</string>
<string name="default_checkbox">Usa come database predefinito</string>
<string name="digits">Numeri</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft è un programma &lt;strong&gt;open source&lt;/strong&gt; e &lt;strong&gt;senza pubblicità&lt;/strong&gt;.
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft è un programma &lt;strong&gt;libero&lt;/strong&gt; e &lt;strong&gt;senza pubblicità&lt;/strong&gt;.
\nViene distribuito sotto le condizioni della licenza &lt;strong&gt;GPL versione 3&lt;/strong&gt; o successiva, senza alcuna garanzia.</string>
<string name="entry_notes">Note</string>
<string name="select_database_file">Apri un database esistente</string>
@@ -78,13 +78,13 @@
<string name="file_not_found_content">File non trovato. Prova a riaprirlo dal tuo gestore di file.</string>
<string name="file_browser">Gestore file</string>
<string name="generate_password">Genera password</string>
<string name="hint_conf_pass">conferma password</string>
<string name="hint_generated_password">password generata</string>
<string name="hint_conf_pass">Conferma password</string>
<string name="hint_generated_password">Password generata</string>
<string name="hint_group_name">Nome gruppo</string>
<string name="hint_keyfile">file chiave</string>
<string name="hint_length">lunghezza</string>
<string name="hint_keyfile">File chiave</string>
<string name="hint_length">Lunghezza</string>
<string name="password">Password</string>
<string name="hint_pass">password</string>
<string name="hint_pass">Password</string>
<string name="install_from_play_store">Installa dal Play Store</string>
<string name="install_from_f_droid">Installa dal F-Droid</string>
<string name="invalid_credentials">Non è possibile leggere le credenziali. Se questo dovesse riaccadere, il file del databese potrebbe essere corrotto.</string>
@@ -115,7 +115,6 @@
<string name="never">Mai</string>
<string name="no_results">Nessun risultato di ricerca</string>
<string name="no_url_handler">Installa un browser web per aprire questo URL.</string>
<string name="open_recent">Database recenti</string>
<string name="omit_backup_search_title">Non cercare nelle voci di backup</string>
<string name="omit_backup_search_summary">Ometti i gruppi \"Backup\" e \"Cestino\" dai risultati di ricerca</string>
<string name="progress_create">Creazione nuovo database…</string>
@@ -139,12 +138,11 @@
<string name="uppercase">Maiuscole</string>
<string name="warning">Attenzione</string>
<string name="warning_password_encoding">Evita password con caratteri al di fuori del formato di codifica del testo nel file di database (i caratteri non riconosciuti vengono convertiti nella stessa lettera).</string>
<string name="warning_unmounted">Monta la scheda SD per creare o caricare un database.</string>
<string name="version_label">Versione %1$s</string>
<string name="configure_biometric">La scansione di impronte è supportata ma non impostata.</string>
<string name="open_biometric_prompt_unlock_database">Scansione impronte</string>
<string name="encrypted_value_stored">Password criptata salvata</string>
<string name="biometric_invalid_key">Lettura dell\'impronta fallita. Ripristina la tua password.</string>
<string name="biometric_invalid_key">Impossibile leggere la chiave biometrica. Eliminala e ripeti la procedura di riconoscimento.</string>
<string name="biometric_scanning_error">Problema impronta: %1$s</string>
<string name="open_biometric_prompt_store_credential">Usa l\'impronta per salvare questa password</string>
<string name="no_credentials_stored">Questo database non ha ancora alcuna password.</string>
@@ -200,8 +198,8 @@
<string name="sort_creation_time">Creazione</string>
<string name="sort_last_modify_time">Modifica</string>
<string name="sort_last_access_time">Accesso</string>
<string name="warning_empty_password">Vuoi veramente che non ci sia una password di sblocco\?</string>
<string name="warning_no_encryption_key">Sei sicuro di non volere usare una chiave di cifratura?</string>
<string name="warning_empty_password">Continuare senza aver impostato una password di sblocco \?</string>
<string name="warning_no_encryption_key">Continuare senza una chiave di cifratura\?</string>
<string name="biometric_not_recognized">Impronta non riconosciuta</string>
<string name="database_history">Cronologia</string>
<string name="menu_appearance_settings">Aspetto</string>
@@ -223,10 +221,10 @@
<string name="lock_database_screen_off_summary">Blocca il database quando lo schermo è spento</string>
<string name="advanced_unlock">Impronta digitale</string>
<string name="biometric_unlock_enable_title">Scansione di impronte</string>
<string name="biometric_unlock_enable_summary">Consente la scansione di impronte per aprire il database</string>
<string name="biometric_unlock_enable_summary">Consente la scansione biometrica per aprire il database</string>
<string name="biometric_delete_all_key_title">Elimina chiavi di cifratura</string>
<string name="biometric_delete_all_key_summary">Elimina tutte le chiavi di cifratura relative al riconoscimento dell\'impronta</string>
<string name="biometric_delete_all_key_warning">Sei sicuro di volere eliminare tutte le chiavi relative alle impronte?</string>
<string name="biometric_delete_all_key_warning">Eliminare tutte le chiavi di cifrature associate al riconoscimento biometrico \?</string>
<string name="unavailable_feature_text">Impossibile avviare questa funzione.</string>
<string name="unavailable_feature_version">La tua versione di Android %1$s non è la minima %2$s richiesta.</string>
<string name="unavailable_feature_hardware">L\'hardware relativo non è stato trovato.</string>
@@ -236,8 +234,8 @@
<string name="create_keepass_file">Crea un nuovo database</string>
<string name="full_file_path_enable_title">Percorso file</string>
<string name="full_file_path_enable_summary">Visualizza il percorso file completo</string>
<string name="recycle_bin_title">Usa il cestino</string>
<string name="recycle_bin_summary">Sposta gruppi ed elementi nel cestino prima di eliminare</string>
<string name="recycle_bin_title">Uso del Cestino</string>
<string name="recycle_bin_summary">Sposta i gruppi e le voci nel gruppo \"Cestino\" prima di eliminarlo</string>
<string name="monospace_font_fields_enable_title">Carattere campi</string>
<string name="monospace_font_fields_enable_summary">Cambia il carattere usato nei campi per una migliore visibilità</string>
<string name="allow_copy_password_title">Fiducia appunti</string>
@@ -347,7 +345,7 @@
<string name="keyboard_key_sound_title">Suono alla pressione</string>
<string name="selection_mode">Modalità selezione</string>
<string name="do_not_kill_app">Non terminare l\'app…</string>
<string name="lock_database_back_root_title">Premere Indietro sulla schermata principale per bloccare</string>
<string name="lock_database_back_root_title">Premere \'\'Indietro\'\' per bloccare</string>
<string name="lock_database_back_root_summary">Bloccare il database quando l\'utente preme il pulsante Indietro nella schermata principale</string>
<string name="clear_clipboard_notification_title">Pulisci alla chiusura</string>
<string name="clear_clipboard_notification_summary">Chiudere il database alla chiusura della notifica</string>
@@ -390,21 +388,66 @@
<string name="otp_digits">Cifre</string>
<string name="otp_algorithm">Algoritmo</string>
<string name="entry_otp">Password usa e getta</string>
<string name="error_invalid_OTP">Segreto della password usa e getta non valido</string>
<string name="error_disallow_no_credentials">" Impostare almeno una credenziale."</string>
<string name="error_invalid_OTP">Segreto per password usa e getta (OTP) non valido.</string>
<string name="error_disallow_no_credentials">Impostare almeno una credenziale.</string>
<string name="error_copy_group_here">Non puoi copiare un gruppo qui.</string>
<string name="error_otp_secret_key">La chiave segreta deve essere nel formato Base32</string>
<string name="error_otp_secret_key">La chiave segreta deve essere nel formato Base32.</string>
<string name="error_otp_counter">Il contatore deve essere tra %1$d e %2$d.</string>
<string name="error_otp_period">Il periodo deve essere tra %1$d e %2$d secondi.</string>
<string name="error_otp_digits">Il token deve contenere tra %1$d e %2$d cifre.</string>
<string name="invalid_db_same_uuid">%1$s con le stesse credenziali univoche %2$s è già esistente.</string>
<string name="creating_database">Sto creando il database...</string>
<string name="creating_database">Sto creando il database</string>
<string name="menu_security_settings">Impostazioni di sicurezza</string>
<string name="contains_duplicate_uuid">Il databse contiene identificativi univoci univerali duplicati.</string>
<string name="error_save_database">Non è possibile salvare il database.</string>
<string name="menu_save_database">Salva il database</string>
<string name="menu_empty_recycle_bin">Svuota il cestino</string>
<string name="command_execution">Esecuzione del comando...</string>
<string name="warning_permanently_delete_nodes">Sei sicuro di voler eliminare definitivamente i nodi selezionati\?</string>
<string name="command_execution">Esecuzione del comando</string>
<string name="warning_permanently_delete_nodes">Vuoi eliminare definitivamente i nodi selezionati\?</string>
<string name="entry_attachments">Allegati</string>
<string name="auto_focus_search_summary">Richiedi una ricerca quando un database viene aperto</string>
<string name="auto_focus_search_title">Ricerca rapida</string>
<string name="menu_delete_entry_history">Cancella cronologia</string>
<string name="menu_restore_entry_history">Ripristina cronologia</string>
<string name="html_about_contribution">Per poter &lt;strong&gt;mantenere la nostra libertà&lt;/strong&gt;, &lt;strong&gt;risolvere bug&lt;/strong&gt;, &lt;strong&gt;aggiungere funzionalità&lt;/strong&gt; ed &lt;strong&gt;essere sempre attivi&lt;/strong&gt;, facciamo affidamento sul tuo &lt;strong&gt;contributo&lt;/strong&gt;.</string>
<string name="contact">Contatto</string>
<string name="biometric_prompt_extract_credential_title">Apri il database con il riconoscimento biometrico</string>
<string name="biometric_prompt_store_credential_title">Salva il riconoscimento biometrico</string>
<string name="keystore_not_accessible">Il keystore non è inizializzato correttamente.</string>
<string name="menu_master_key_settings">Impostazioni della chiave principale</string>
<string name="master_key">Chiave principale</string>
<string name="contribution">Contribuisci</string>
<string name="biometric_prompt_store_credential_message">Attenzione: Devi comunque ricordarti la password principale anche se usi il riconoscimento biometrico.</string>
<string name="warning_database_read_only">Garantisci il permesso di scrittura per salvare i cambiamenti del database</string>
<string name="hide_broken_locations_summary">Nascondi link corrotti nella lista dei database recenti</string>
<string name="hide_broken_locations_title">Nascondi i link di database corrotti</string>
<string name="show_recent_files_summary">Mostra le posizioni dei database recenti</string>
<string name="show_recent_files_title">Mostra file recenti</string>
<string name="remember_keyfile_locations_title">Salva la posizione dei keyfile</string>
<string name="remember_database_locations_summary">Ricorda la posizione dei database</string>
<string name="remember_database_locations_title">Salva posizione dei database</string>
<string name="contains_duplicate_uuid_procedure">Per continuare, risolvi il problema generando nuovi UUIDs per i duplicati \?</string>
<string name="error_create_database">Impossibile creare il file del database.</string>
<string name="entry_add_attachment">Aggiungi allegato</string>
<string name="discard">Scarta</string>
<string name="discard_changes">Scartare i cambiamenti\?</string>
<string name="validate">Convalida</string>
<string name="max_history_size_title">Dimensione massima</string>
<string name="max_history_items_title">Numero massimo</string>
<string name="biometric_auto_open_prompt_title">Apri automaticamente prompt biometrico</string>
<string name="max_history_size_summary">Limita la dimensione (in byte) della cronologia per voce</string>
<string name="max_history_items_summary">Limita il numero di elementi della cronologia per voce</string>
<string name="recycle_bin_group_title">Gruppo cestino</string>
<string name="database_data_compression_summary">La compressione dei dati riduce le dimensioni del database.</string>
<string name="database_data_compression_title">Compressione dati</string>
<string name="biometric_auto_open_prompt_summary">Apri automaticamente il prompt biometrico quando viene definita una chiave biometrica per un database</string>
<string name="advanced_unlock_explanation_summary">Utilizza lo sblocco avanzato per aprire il database più facilmente</string>
<string name="clipboard_explanation_summary">Copia i campi di immissione utilizzando gli appunti del tuo dispositivo</string>
<string name="database_opened">Database aperto</string>
<string name="biometric">Biometrico</string>
<string name="credential_before_click_biometric_button">Digitare la password prima di fare clic sul pulsante biometrico.</string>
<string name="biometric_prompt_extract_credential_message">Estrai le credenziali del database con dati biometrici</string>
<string name="settings_database_force_changing_master_key_title">Forza rinnovo</string>
<string name="settings_database_recommend_changing_master_key_summary">Consigliato cambiare la chiave principale (giorni)</string>
<string name="settings_database_recommend_changing_master_key_title">Rinnovo raccomandato</string>
</resources>

View File

@@ -111,7 +111,6 @@
<string name="never">אף פעם</string>
<string name="no_results">אין תוצאות חיפוש</string>
<string name="no_url_handler">אין מטפל לכתובת url זו.</string>
<string name="open_recent">פתח מסד נתונים אחרון :</string>
<string name="omit_backup_search_title">אל תחפש ערכי גיבוי</string>
<string name="omit_backup_search_summary">הורד את קבוצת \"גיבוי\" מתוצאות חיפוש (תואם רק לקבצי kdb)</string>
<string name="progress_create">צור מסד נתונים חדש…</string>
@@ -130,7 +129,6 @@
<string name="underline">קו תחתון</string>
<string name="unsupported_db_version">גרסת מסד נתונים לא נתמכת.</string>
<string name="uppercase">רישית</string>
<string name="warning_unmounted">כרטיס ה-SD במצב לקריאה בלבד. אתה לא תוכל לשמור או ליצור במסד הנתונים.</string>
<string name="version_label">גרסה %1$s</string>
<string name="education_unlock_summary">הזן סיסמה ו/או קובץ מפתח כדי לפתוח את מסד הנתונים.</string>
<string-array name="timeout_options">

View File

@@ -103,7 +103,6 @@
<string name="never">期限なし</string>
<string name="no_results">検索結果に該当するものはありません。</string>
<string name="no_url_handler">このURLを処理できません。</string>
<string name="open_recent">以前使用したデータベースを開く:</string>
<string name="omit_backup_search_title">検索対象から除外</string>
<string name="omit_backup_search_summary">\"バックアップ\"と\"ごみ箱\"を検索対象から除外します</string>
<string name="progress_create">データベースファイルを作成中…</string>
@@ -123,7 +122,6 @@
<string name="underline">アンダーライン (_)</string>
<string name="unsupported_db_version">このバージョンのデータベースはサポートされていません。</string>
<string name="uppercase">英数大文字</string>
<string name="warning_unmounted">SDカードがマウントされていません。データベースの読込や作成ができません。</string>
<string name="version_label">バージョン %1$s</string>
<string name="education_unlock_summary">データベースに設定したパスワードを入力するかキーファイルを選択してください。</string>
<string-array name="timeout_options">

View File

@@ -137,7 +137,6 @@
<string name="no_url_handler">이 URL을 열기 위해 웹 브라우저를 설치하십시오.</string>
<string name="select_database_file">가지고 있는 데이터베이스 열기</string>
<string name="create_keepass_file">새 데이터베이스 생성</string>
<string name="open_recent">최근 데이터베이스</string>
<string name="omit_backup_search_title">백업 항목 검색하지 않기</string>
<string name="progress_create">새 데이터베이스 생성 중…</string>
<string name="progress_title">작업 중…</string>

View File

@@ -86,7 +86,6 @@
<string name="lowercase">Mažosios raidės</string>
<string name="minus">Minusas</string>
<string name="underline">Pabraukimas</string>
<string name="open_recent">Atidaryti naujausią duomenų bazę </string>
<string name="default_checkbox">Naudoti šią duomenų bazę kaip numatytąją</string>
<string name="hide_password_summary">Slėpti slaptažodžius pagal nutylėjimą</string>
<string name="invalid_algorithm">Neteisingas algoritmas.</string>

View File

@@ -94,7 +94,6 @@
<string name="never">Nekad</string>
<string name="no_results">Nav meklēšanas rezultātu</string>
<string name="no_url_handler">Neizdevās atvērt saiti.</string>
<string name="open_recent">Atvērt pēdējo datu bāzi :</string>
<string name="omit_backup_search_title">Nemeklēt kopijās un atkritnē</string>
<string name="omit_backup_search_summary">Izlaist kopijas un atkritni no meklēšanas rezultātiem</string>
<string name="progress_create">Izveido jaunu datu bāzi…</string>
@@ -116,7 +115,6 @@
<string name="underline">Pasvītrojums</string>
<string name="unsupported_db_version">Neatbalstīta datu bāzes versija.</string>
<string name="uppercase">Lielie burti</string>
<string name="warning_unmounted">Nav SD kartes. Darbības ar datu bāzi nav iespējamas.</string>
<string name="version_label">Versija %1$s</string>
<string name="education_unlock_summary">Ievadiet paroli/atslēgas failu, lai atbloķētu savu datu bāzi.</string>

View File

@@ -16,7 +16,8 @@
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
--><resources>
-->
<resources>
<string name="feedback">Tilbakemelding</string>
<string name="homepage">Hjemmeside</string>
<string name="about_description">Android-implementasjon av KeePass-passordsbehandleren</string>
@@ -48,7 +49,8 @@
<string name="decrypting_db">Dekrypterer databaseinnhold…</string>
<string name="default_checkbox">Bruk dette som forvalgt database</string>
<string name="digits">Siffer</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft kommer uten noen form for garanti. Dette er fri programvare, og du er velkommen til å redistribuere det i henhold til vilkårene i GPL versjon 3 eller senere.</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft er &lt;strong&gt;fri programvare&lt;/strong&gt;, og &lt;strong&gt;reklamefritt&lt;/strong&gt;.
\nDet tilbys som det er, i hendhold til &lt;strong&gt;GPL versjon 3 eller senere&lt;/strong&gt;, uten noen garantier.</string>
<string name="entry_accessed">Brukt</string>
<string name="entry_cancel">Avbryt</string>
<string name="entry_notes">Kommentarer</string>
@@ -135,7 +137,6 @@
<string name="no_results">Ingen søkeresultater</string>
<string name="no_url_handler">Kan ikke håndtere denne nettadressen.</string>
<string name="select_database_file">Velg en eksisterende database</string>
<string name="open_recent">Nylige databaser</string>
<string name="omit_backup_search_title">Ikke søk gjennom sikkerhetskopioppføringer</string>
<string name="omit_backup_search_summary">Utelat \"Sikkerhetskopi\"-gruppen fra søkeresultater (har kunn innvirkning på .kdb-filer)</string>
<string name="progress_create">Oppretter ny database…</string>
@@ -174,7 +175,6 @@
<string name="uppercase">Store bokstaver</string>
<string name="warning">Advarsel</string>
<string name="warning_password_encoding">Unngå passordtegn utenfor tekstkodingsformat i databasefil (ukjente tegn blir konvertert til samme bokstav).</string>
<string name="warning_unmounted">SD-kortet ditt er ikke montert på enheten din. Du vil ikke kunne laste inne eller opprette din database.</string>
<string name="warning_empty_password">Ønsker du virkelig å bruke en tom streng som ditt passord?</string>
<string name="warning_no_encryption_key">Er du sikker på at du ønsker å bruke en krypteringsnøkkel?</string>
<string name="version_label">Versjon %1$s</string>
@@ -382,8 +382,8 @@
<string name="error_disallow_no_credentials">Minst én identitetsdetalj må angis.</string>
<string name="error_copy_group_here">Du kan ikke kopiere en gruppe hit.</string>
<string name="error_otp_secret_key">Hemmelig nøkkel må være i Base32-format.</string>
<string name="error_otp_digits">"Symbolet må inneholde %1$d til %2$d siffer."</string>
<string name="invalid_db_same_uuid">%1$d med samme UUID %2$s finnes allerede.</string>
<string name="error_otp_digits">Symbolet må inneholde %1$d til %2$d siffer.</string>
<string name="invalid_db_same_uuid">%1$s med samme UUID %2$s finnes allerede.</string>
<string name="creating_database">Oppretter database…</string>
<string name="menu_security_settings">Sikkerhetsinnstillinger</string>
<string name="menu_master_key_settings">Hovednøkkelinnstillinger</string>
@@ -408,4 +408,8 @@
<string name="download_finalization">Fullfører…</string>
<string name="download_complete">Fullført. Trykk for å åpne filen.</string>
<string name="hide_expired_entries_title">Skjul utløpte oppføringer</string>
<string name="auto_focus_search_title">Hurtigsøk</string>
<string name="entry_add_attachment">Legg til vedlegg</string>
<string name="contribution">Bidrag</string>
<string name="contact">Kontakt</string>
</resources>

View File

@@ -105,7 +105,6 @@
<string name="never">Nooit</string>
<string name="no_results">Geen zoekresultaten</string>
<string name="no_url_handler">Installeer een webbrowser om deze URL te openen.</string>
<string name="open_recent">Recente databanken</string>
<string name="omit_backup_search_title">Back-upitems niet doorzoeken</string>
<string name="omit_backup_search_summary">Hiermee worden groepen \"Back-up\" en \"Prullenbak\" uit de zoekresultaten weggelaten</string>
<string name="progress_create">Bezig met creëren van nieuwe databank…</string>
@@ -125,7 +124,6 @@
<string name="underline">Onderstrepen</string>
<string name="unsupported_db_version">Niet-ondersteunde databankversie.</string>
<string name="uppercase">Hoofdletters</string>
<string name="warning_unmounted">Koppel de SD-kaart aan om een databank te creëren of laden.</string>
<string name="version_label">Versie %1$s</string>
<string name="education_unlock_summary">Geef het wachtwoord en/of sleutelbestand op om je databank te ontgrendelen.
\n
@@ -278,7 +276,7 @@
<string name="education_new_node_summary">Voeg items toe om je digitale identiteiten te beheren.
\n
\nVoeg groepen toe (groepen zijn gelijk aan mappen) om items in je databank te organiseren.</string>
<string name="education_search_title">"Doorzoek al je items"</string>
<string name="education_search_title">Doorzoek al je items</string>
<string name="education_search_summary">Doorzoek items op titel, gebruikersnaam of andere velden om wachtwoorden te vinden.</string>
<string name="education_biometric_title">Ontgrendel de databank met je vingerafdruk</string>
<string name="education_biometric_summary">Koppel je wachtwoord en vingerafdruk om de databank snel te ontgrendelen.</string>

View File

@@ -104,7 +104,6 @@
<string name="never">Aldri</string>
<string name="no_results">Ingen søkjeresultat</string>
<string name="no_url_handler">Ingen behandlar for denne adressa.</string>
<string name="open_recent">Opna nyleg brukt database :</string>
<string name="omit_backup_search_title">Søk ikkje i kopipostane eller søppelbøtta</string>
<string name="omit_backup_search_summary">Søkjeresultatet inneheld ikkje oppføringar frå \'Backup\' eller søppelbøtta</string>
<string name="progress_create">Lager ny database …</string>
@@ -124,7 +123,6 @@
<string name="underline">Understreking</string>
<string name="unsupported_db_version">Kan ikkje bruka databaseutgåva.</string>
<string name="uppercase">Store bokstavar</string>
<string name="warning_unmounted">SD-kortet er ikkje montert i eininga di. Du kan verken henta eller laga databasen din.</string>
<string name="version_label">Utgåve %1$s</string>
<string name="education_unlock_summary">Skriv inn passordet og/eller nøkkelfil for å låsa opp databasen.</string>

View File

@@ -102,7 +102,6 @@
<string name="never">Nigdy</string>
<string name="no_results">Brak wyników wyszukiwania</string>
<string name="no_url_handler">Zainstaluj przeglądarkę internetową, aby otworzyć ten adres URL.</string>
<string name="open_recent">Ostatnio używana baza danych</string>
<string name="omit_backup_search_title">Nie wyszukuj wpisów kopii zapasowej</string>
<string name="omit_backup_search_summary">Pomija grupy \"Kopia zapasowa\" i \"Kosz\" z wyników wyszukiwania</string>
<string name="progress_create">Tworzenie nowej bazy danych…</string>
@@ -122,7 +121,6 @@
<string name="underline">Podkreślenie</string>
<string name="unsupported_db_version">Nieobsługiwana wersja bazy danych.</string>
<string name="uppercase">Wielkie litery</string>
<string name="warning_unmounted">Zainstaluj kartę pamięci, aby utworzyć lub załadować bazę danych.</string>
<string name="education_unlock_summary">prowadź hasło i/lub plik klucza, aby odblokować bazę danych.
\n
\nUtwórz kopię zapasową pliku bazy danych w bezpiecznym miejscu po każdej zmianie.</string>
@@ -152,8 +150,9 @@
<string name="clipboard_error">Niektóre urządzenia nie pozwalają aplikacjom korzystać ze schowka.</string>
<string name="clipboard_error_clear">Nie można wyczyścić schowka</string>
<string name="clipboard_swipe_clean">Przesuń, by wyczyścić schowek</string>
<string name="html_about_licence">KeePassDX © %1 $d Kunzisoft jest &lt;strong&gt;open source&lt;/strong&gt; i &lt;strong&gt;bez reklam&lt;/strong&gt;.
<string name="html_about_licence">KeePassDX © %1 $d Kunzisoft jest &lt;strong&gt;wolnym programem&lt;/strong&gt; i &lt;strong&gt;bez reklam&lt;/strong&gt;.
\nJest on dostarczany w stanie, zgodnie z licencją &lt;strong&gt;GPLv3&lt;/strong&gt; bez żadnych gwarancji.</string>
>>>>>>> translations
<string name="entry_not_found">Nie znaleziono danych wejściowych.</string>
<string name="error_load_database">Nie można załadować bazy danych.</string>
<string name="error_load_database_KDF_memory">Nie można załadować klucza. Spróbuj zmniejszyć użycie pamięć KDF.</string>
@@ -196,8 +195,8 @@
<string name="warning_password_encoding">Unikaj znaków hasła spoza formatu kodowania tekstu w pliku bazy danych (nierozpoznane znaki są konwertowane na tę samą literę).</string>
<string name="sort_recycle_bin_bottom">Kosz na dole</string>
<string name="sort_title">Tytuł</string>
<string name="warning_empty_password">Czy naprawdę nie chcesz ochrony przed odblokowaniem hasła\?</string>
<string name="warning_no_encryption_key">Czy na pewno nie chcesz używać żadnego klucza szyfrowania?</string>
<string name="warning_empty_password">Kontynuować bez ochrony odblokowującej hasło\?</string>
<string name="warning_no_encryption_key">Kontynuować bez klucza szyfrowania\?</string>
<string name="version_label">Wersja %1$s</string>
<string name="configure_biometric">Skanowanie odcisków palców jest obsługiwane, ale nie skonfigurowane.</string>
<string name="encrypted_value_stored">Zapisano zaszyfrowane hasło</string>
@@ -232,7 +231,7 @@
<string name="biometric_unlock_enable_summary">Umożliwia zeskanowanie danych biometrycznych w celu otwarcia bazy danych</string>
<string name="biometric_delete_all_key_title">Usuń klucze szyfrowania</string>
<string name="biometric_delete_all_key_summary">Usuń wszystkie klucze szyfrowania związane z rozpoznawaniem linii papilarnych</string>
<string name="biometric_delete_all_key_warning">Czy na pewno chcesz usunąć wszystkie klucze związane z rozpoznawaniem linii papilarnych\?</string>
<string name="biometric_delete_all_key_warning">Czy usunąć wszystkie klucze szyfrowania związane z rozpoznawaniem biometrycznym\?</string>
<string name="unavailable_feature_text">Nie można uruchomić tej funkcji.</string>
<string name="unavailable_feature_version">Twoja wersja Androida %1$s nie spełnia wymaganej minimalnej wersji %2$s.</string>
<string name="unavailable_feature_hardware">Nie można znaleźć odpowiedniego sprzętu.</string>
@@ -281,7 +280,7 @@
<string name="education_biometric_summary">Połącz swoje hasło z zeskanowanym odciskiem palca, aby szybko odblokować bazę danych.</string>
<string name="education_entry_edit_title">Edytuj wpis</string>
<string name="education_entry_edit_summary">Edytuj swój wpis za pomocą pól niestandardowych. Dane puli mogą być przywoływane między różnymi polami wprowadzania.</string>
<string name="education_generate_password_title">Utwórz silne hasło do swojego wpisu.</string>
<string name="education_generate_password_title">Utwórz silne hasło</string>
<string name="education_generate_password_summary">Wygeneruj silne hasło, które będzie kojarzyć się z Twoim wpisem, łatwo zdefiniuj je zgodnie z kryteriami formularza i nie zapomnij o bezpiecznym haśle.</string>
<string name="education_entry_new_field_title">Dodaj niestandardowe pola</string>
<string name="education_entry_new_field_summary">Zarejestruj dodatkowe pole, dodaj wartość i opcjonalnie chroń je.</string>
@@ -420,7 +419,7 @@
<string name="error_otp_period">Okres musi wynosić od %1$d do %2$d sekund.</string>
<string name="error_otp_digits">Token musi zawierać cyfry od %1$d do %2$d.</string>
<string name="invalid_db_same_uuid">%1$s o tym samym identyfikatorze UUID %2$s już istnieje.</string>
<string name="contains_duplicate_uuid_procedure">Weryfikując to okno dialogowe, KeePassDX rozwiąże problem (poprzez wygenerowanie nowych UUID dla duplikatów) i będzie kontynuował.</string>
<string name="contains_duplicate_uuid_procedure">Rozwiązać problem poprzez stworzenie nowych identyfikatory UUID duplikatów, aby kontynuować\?</string>
<string name="clipboard_explanation_summary">Skopiuj pola wprowadzania danych za pomocą schowka urządzenia</string>
<string name="advanced_unlock_explanation_summary">Użyj zaawansowanego odblokowywania w celu łatwiejszego otwierania bazy danych</string>
<string name="database_data_compression_summary">Kompresja danych zmniejsza rozmiar bazy danych.</string>
@@ -433,24 +432,24 @@
<string name="menu_save_database">Zapisz bazę danych</string>
<string name="menu_empty_recycle_bin">Opróżnij kosz</string>
<string name="command_execution">Wykonywanie polecenia…</string>
<string name="warning_permanently_delete_nodes">Czy na pewno chcesz trwale usunąć wybrane węzły\?</string>
<string name="warning_permanently_delete_nodes">Czy trwale usunąć wybrane węzły\?</string>
<string name="keystore_not_accessible">Magazyn kluczy nie został poprawnie zainicjowany.</string>
<string name="credential_before_click_biometric_button">Wpisz hasło przed kliknięciem przycisku biometrycznego.</string>
<string name="recycle_bin_group_title">Kosz grupy</string>
<string name="enable_auto_save_database_title">Automatycznie zapisuj bazę danych</string>
<string name="enable_auto_save_database_summary">Automatycznie zapisz bazę danych po ważnym działaniu (tylko w trybie „Modyfikowalnym”)</string>
<string name="enable_auto_save_database_summary">Zapisz bazę danych po każdym ważnym działaniu (w trybie „Modyfikowalnym”)</string>
<string name="entry_attachments">Załączniki</string>
<string name="menu_restore_entry_history">Przywróć historię</string>
<string name="menu_delete_entry_history">Usuń historię</string>
<string name="keyboard_auto_go_action_title">Automatyczne działanie klucza</string>
<string name="keyboard_auto_go_action_summary">Działanie klawisza Go wykonywane jest automatycznie po naciśnięciu klawisza Field</string>
<string name="keyboard_auto_go_action_summary">Akcja klawisza „Idź” po naciśnięciu klawisza „Pole”</string>
<string name="download_attachment">Pobierz %1$s</string>
<string name="download_initialization">Inicjowanie…</string>
<string name="download_progression">W trakcie realizacji: %1$d%</string>
<string name="download_progression">W trakcie realizacji: %1$d&#37;</string>
<string name="download_finalization">Kończę…</string>
<string name="download_complete">Kompletny! Stuknij, aby otworzyć plik.</string>
<string name="hide_expired_entries_title">Ukryj wygasłe wpisy</string>
<string name="hide_expired_entries_summary">Wygasłe wpisy zostaną ukryte</string>
<string name="hide_expired_entries_summary">Wygasłe wpisy są ukryte</string>
<string name="contact">Kontakt</string>
<string name="html_about_contribution">Aby &lt;strong&gt;zachować naszą wolność&lt;/strong&gt;, &lt;strong&gt;sprawdzać błędy&lt;/strong&gt;, &lt;strong&gt;dodać funkcje&lt;/strong&gt; i &lt;strong&gt;by być zawsze aktywnym&lt;/strong&gt;, liczymy na twój &lt;strong&gt;wkład&lt;/strong&gt;.</string>
<string name="auto_focus_search_title">Szybkie wyszukiwanie</string>
@@ -465,4 +464,11 @@
<string name="hide_broken_locations_summary">Ukryj uszkodzone łącza na liście najnowszych baz danych</string>
<string name="warning_database_read_only">Przyznaj dostęp do zapisu pliku, aby zapisać zmiany w bazie danych</string>
<string name="contribution">Wkład</string>
<string name="education_setup_OTP_summary">Skonfiguruj zarządzanie hasłem jednorazowym (HOTP / TOTP), aby wygenerować token wymagany do uwierzytelniania dwuskładnikowego (2FA).</string>
<string name="education_setup_OTP_title">Konfiguracja OTP</string>
<string name="error_create_database">Nie można utworzyć pliku bazy danych.</string>
<string name="entry_add_attachment">Dodaj załącznik</string>
<string name="discard">Odrzuć</string>
<string name="discard_changes">Odrzucić zmiany\?</string>
<string name="validate">Walidacja</string>
</resources>

View File

@@ -103,7 +103,6 @@
<string name="never">Nunca</string>
<string name="no_results">Sem resultados na busca</string>
<string name="no_url_handler">Instale um navegador para abrir esta URL.</string>
<string name="open_recent">Bancos de dados recentes</string>
<string name="omit_backup_search_title">Não procurar por entradas no backup ou na lixeira</string>
<string name="omit_backup_search_summary">Omite os grupos \"Backup\" e \"Lixeira\" dos resultados da busca</string>
<string name="progress_create">Criando novo banco de dados…</string>
@@ -123,7 +122,6 @@
<string name="underline">Sublinhado</string>
<string name="unsupported_db_version">Versão de banco de dados não suportada.</string>
<string name="uppercase">Letras maiúsculas</string>
<string name="warning_unmounted">Monte o cartão SD para criar ou abrir um banco de dados.</string>
<string name="version_label">Versão %1$s</string>
<string name="education_unlock_summary">Entre com a senha e/ou com o caminho para o arquivo-chave do banco de dados.
\n

View File

@@ -115,7 +115,6 @@
<string name="never">Nunca</string>
<string name="no_results">A pesquisa não obteve resultados</string>
<string name="no_url_handler">Instale um navegador para abrir esta URL.</string>
<string name="open_recent">Bancos de dados recentes</string>
<string name="omit_backup_search_title">Não procurar por entradas no backup ou na lixeira</string>
<string name="omit_backup_search_summary">Omite os grupos \"Backup\" e \"Lixeira\" dos resultados da busca</string>
<string name="progress_create">A criar nova base de dados…</string>
@@ -141,7 +140,6 @@
<string name="uppercase">Maiúsculas</string>
<string name="warning">Aviso</string>
<string name="warning_password_encoding">Evite caracteres fora do formato de codificação do ficheiro do banco (todos os caracteres não reconhecidos são convertidos para a mesma letra).</string>
<string name="warning_unmounted">Monte o cartão SD para criar ou abrir um banco de dados.</string>
<string name="version_label">Versão %1$s</string>
<string name="education_unlock_summary">Entre com a palavra-passe e/ou com o caminho para o ficheiro-chave do banco de dados.
\n

View File

@@ -43,7 +43,7 @@
<string name="content_description_update_from_list">Actualizați</string>
<string name="content_description_remove_from_list">Elimina</string>
<string name="content_description_keyboard_close_fields">Câmpuri închise</string>
<string name="select_to_copy">%1$s is either \\\"Nume\\\" si \\\"Parola\\\".</string>
<string name="select_to_copy">Selectați pentru a copia %1$s în clipboard</string>
<string name="retrieving_db_key">Obtinerea cheii bazei de date…</string>
<string name="database">Baza de date</string>
<string name="decrypting_db">Decriptarea continutului bazei de date.…</string>
@@ -167,16 +167,15 @@
<string name="minus">Minus</string>
<string name="never">Niciodata</string>
<string name="no_results">Nu există Rezultate</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft is &lt;strong&gt;sursa deschisa&lt;strong&gt; and &lt;strong&gt;fara publicitate&lt;strong&gt;.
\nEste prevăzut așa cum este, sub &lt;strong&gt;GPLv3&lt;strong&gt; licenta,fara nici un fel de garantie.</string>
<string name="html_about_contribution">In oridine sa &lt;strong&gt;pastram libertatea noastra &lt;strong&gt;, &lt;strong&gt;fix bugs&lt;strong&gt;, &lt;strong&gt;adăugați funcții&lt;strong&gt; si&lt;strong&gt;sa fie intotdeauna activ&lt;strong&gt;", ne bazam pe "&lt;strong&gt;contributie.&lt;strong&gt;</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft is &lt;strong&gt;sursa deschisa&lt;strong&gt; and &lt;strong&gt;fara publicitate&lt;/strong&gt;.
\nEste prevăzut așa cum este, sub &lt;strong&gt;GPLv3&lt;/strong&gt; licenta, fara nici un fel de garantie.</string>
<string name="html_about_contribution">In oridine sa &lt;strong&gt;pastram libertatea noastra&lt;/strong&gt;, &lt;strong&gt;fix bugs&lt;/strong&gt;, &lt;strong&gt;adăugați funcții&lt;/strong&gt; si&lt;strong&gt;sa fie intotdeauna activ&lt;strong&gt;, ne bazam pe &lt;strong&gt;contributie&lt;/strong&gt;.</string>
<string name="hide_password_title">Ascundeți parolele</string>
<string name="hide_password_summary">Mascați parolele (***) în mod implicit</string>
<string name="about">Despre</string>
<string name="no_url_handler">Instalați un browser web pentru a deschide această adresă URL.</string>
<string name="select_database_file">Deschide baza de date existentă</string>
<string name="create_keepass_file">Creați o bază de date nouă</string>
<string name="open_recent">Baze de date recente</string>
<string name="progress_create">Crearea noii baze de date …</string>
<string name="progress_title">Lucrând …</string>
<string name="protection">Protecție</string>
@@ -217,7 +216,6 @@
<string name="uppercase">Cu majuscule</string>
<string name="warning">Avertizare</string>
<string name="warning_password_encoding">Evitați caracterele parole în afara formatului de codare a textului în fișierul bazei de date (caracterele nerecunoscute sunt convertite în aceeași literă).</string>
<string name="warning_unmounted">Montați cardul de memorie pentru a crea sau încărca o bază de date.</string>
<string name="warning_empty_password">Chiar nu doriți nicio protecție de deblocare a parolei\?</string>
<string name="warning_no_encryption_key">Ești sigur că nu vrei să folosești nicio cheie de criptare\?</string>
<string name="warning_permanently_delete_nodes">Sigur doriți să ștergeți definitiv nodurile selectate\?</string>
@@ -394,7 +392,7 @@
<string name="html_text_buy_pro">Cumpărând versiunea pro, veți avea acces la acest &lt;strong&gt; stil vizual &lt;/strong&gt; și vă va ajuta în special &lt;strong&gt; implementarea proiectelor comunitare. &lt;/strong&gt;</string>
<string name="html_text_feature_generosity">Acest &lt;strong&gt; stil vizual &lt;/strong&gt; este disponibil datorită generozității tale.</string>
<string name="html_text_donation">Pentru a ne păstra libertatea și pentru a fi mereu activi, ne bazăm pe contribuția dvs. &lt;strong&gt;. &lt;/strong&gt;</string>
<string name="html_text_dev_feature">Această caracteristică este &lt;strong&gt; în curs de dezvoltare &lt;/strong&gt; și necesită ca contribuția dvs &lt;strong&gt; să fie disponibilă în curând.</string>
<string name="html_text_dev_feature">Această caracteristică este &lt;strong&gt; în curs de dezvoltare&lt;/strong&gt; și necesită ca &lt;strong&gt;contribuția&lt;/strong&gt; dvs să fie disponibilă în curând.</string>
<string name="html_text_dev_feature_buy_pro">Cumpărând versiunea &lt;strong&gt; pro &lt;/strong&gt;,</string>
<string name="html_text_dev_feature_contibute">Prin &lt;strong&gt; contribuție &lt;/strong&gt;,</string>
<string name="html_text_dev_feature_encourage">încurajezi dezvoltatorii să creeze &lt;strong&gt; funcții noi &lt;/strong&gt; și să &lt;strong&gt; remedieze erori &lt;/strong&gt; în conformitate cu observațiile tale.</string>
@@ -405,7 +403,7 @@
<string name="contribute">Contribuie</string>
<string name="download_attachment">Descărcați %1$s</string>
<string name="download_initialization">Inițializare …</string>
<string name="download_progression">In progress: %1$d%</string>
<string name="download_progression">In progress: %1$d&#37;</string>
<string name="download_finalization">Finalizare …</string>
<string name="download_complete">Complet! Atingeți pentru a deschide fișierul.</string>
<string name="encryption_rijndael">Rijndael (AES)</string>

View File

@@ -43,7 +43,7 @@
<string name="decrypting_db">Расшифровка базы…</string>
<string name="default_checkbox">База по умолчанию</string>
<string name="digits">Цифры</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft с &lt;strong&gt;открытым исходным кодом&lt;/strong&gt; и &lt;strong&gt;без рекламы&lt;/strong&gt;.
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft — это &lt;strong&gt;свободное программное обеспечение&lt;/strong&gt; и &lt;strong&gt;без рекламы&lt;/strong&gt;.
\nРаспространяется под лицензией &lt;strong&gt;GPLv3&lt;/strong&gt; без каких-либо гарантий.</string>
<string name="select_database_file">Открыть существующую базу</string>
<string name="entry_accessed">Доступ</string>
@@ -115,7 +115,6 @@
<string name="never">Никогда</string>
<string name="no_results">Совпадения не найдены</string>
<string name="no_url_handler">Установите браузер, чтобы открыть этот URL.</string>
<string name="open_recent">Недавно открытые базы</string>
<string name="omit_backup_search_title">Не искать в резервных копиях</string>
<string name="omit_backup_search_summary">Не искать в группах \"Резервирование\" и \"Корзина\"</string>
<string name="progress_create">Создание новой базы…</string>
@@ -141,7 +140,6 @@
<string name="uppercase">ЗАГЛАВНЫЕ</string>
<string name="warning">Внимание</string>
<string name="warning_password_encoding">Избегайте использования в пароле символов вне кодировки текста в файле базы, так как эти символы будут преобразованы в одинаковый символ.</string>
<string name="warning_unmounted">Подключите хранилище для создания или загрузки базы.</string>
<string name="version_label">Версия %1$s</string>
<string name="configure_biometric">Биометрия поддерживается, но не настроена.</string>
<string name="open_biometric_prompt_unlock_database">Ожидание биометрического ключа для разблокировки базы</string>
@@ -205,8 +203,8 @@
<string name="sort_groups_before">Сначала группы</string>
<string name="sort_recycle_bin_bottom">\"Корзина\" внизу</string>
<string name="sort_title">Название записи</string>
<string name="warning_empty_password">Вы действительно не хотите использовать пароль для защиты базы\?</string>
<string name="warning_no_encryption_key">Вы действительно не хотите использовать ключ шифрования?</string>
<string name="warning_empty_password">Продолжить без пароля для защиты базы\?</string>
<string name="warning_no_encryption_key">Продолжить без ключа шифрования\?</string>
<string name="biometric_not_recognized">Биометрический ключ не распознан</string>
<string name="database_history">История</string>
<string name="menu_appearance_settings">Внешний вид</string>
@@ -232,7 +230,7 @@
<string name="biometric_unlock_enable_summary">Включить разблокировку базы при помощи биометрического ключа</string>
<string name="biometric_delete_all_key_title">Удалить ключи шифрования</string>
<string name="biometric_delete_all_key_summary">Удалить все ключи шифрования, связанные с распознаванием биометрического ключа</string>
<string name="biometric_delete_all_key_warning">Вы уверены, что хотите удалить все ключи, связанные с биометрическим ключом\?</string>
<string name="biometric_delete_all_key_warning">Удалить все ключи шифрования, связанные с биометрическим распознаванием\?</string>
<string name="unavailable_feature_text">Невозможно запустить эту функцию.</string>
<string name="unavailable_feature_version">Ваша версия Android %1$s ниже минимально необходимой %2$s.</string>
<string name="unavailable_feature_hardware">Соответствующее оборудование не найдено.</string>
@@ -281,7 +279,7 @@
<string name="education_search_summary">Ищите записи по названию, имени или другим полям для быстрого доступа к своим паролям.</string>
<string name="education_entry_edit_title">Редактируйте записи</string>
<string name="education_entry_edit_summary">Редактируйте записи с настраиваемыми полями. Возможны перекрёстные ссылки между полями разных записей.</string>
<string name="education_generate_password_title">Создайте надёжный пароль для записи.</string>
<string name="education_generate_password_title">Создайте надёжный пароль</string>
<string name="education_generate_password_summary">Создайте надёжный пароль, связанный с записью, легко настраиваемый под критерии формы. И не забудьте главный пароль от базы.</string>
<string name="education_entry_new_field_title">Добавляйте настраиваемые поля</string>
<string name="education_entry_new_field_summary">Зарегистрируйте дополнительное поле, добавьте значение и при необходимости защитите его.</string>
@@ -388,14 +386,14 @@
<string name="security">Безопасность</string>
<string name="entry_history">История</string>
<string name="entry_setup_otp">Настройка одноразового пароля</string>
<string name="otp_type">Тип одноразового пароля</string>
<string name="otp_type">Тип OTP</string>
<string name="otp_secret">Секретный ключ</string>
<string name="otp_period">Время (в секундах)</string>
<string name="otp_counter">Счётчик</string>
<string name="otp_digits">Цифры</string>
<string name="otp_algorithm">Алгоритм</string>
<string name="entry_otp">Одноразовый пароль</string>
<string name="error_invalid_OTP">Недействительный секретный ключ одноразового пароля.</string>
<string name="entry_otp">OTP</string>
<string name="error_invalid_OTP">Некорректный OTP.</string>
<string name="error_disallow_no_credentials">Должен быть установлен, по крайней мере, один пароль.</string>
<string name="error_copy_group_here">Вы не можете копировать группу сюда.</string>
<string name="error_otp_secret_key">Секретный ключ должен быть в формате BASE32.</string>
@@ -407,7 +405,7 @@
<string name="menu_security_settings">Настройки безопасности</string>
<string name="menu_master_key_settings">Настройки главного пароля</string>
<string name="contains_duplicate_uuid">База содержит повторяющиеся UUID.</string>
<string name="contains_duplicate_uuid_procedure">Если вы разрешите, KeePassDX исправит проблему (путём создания новых UUID для дубликатов) и продолжит работу.</string>
<string name="contains_duplicate_uuid_procedure">Исправить проблему путём создания новых UUID для дубликатов и продолжить работу\?</string>
<string name="database_opened">База открыта</string>
<string name="clipboard_explanation_summary">Копирование полей ввода с помощью буфера обмена устройства</string>
<string name="advanced_unlock_explanation_summary">Использовать дополнительную разблокировку для более лёгкого открытия базы данных</string>
@@ -433,20 +431,20 @@
<string name="menu_save_database">Сохранить базу</string>
<string name="menu_empty_recycle_bin">Очистить \"корзину\"</string>
<string name="command_execution">Выполнение команды…</string>
<string name="warning_permanently_delete_nodes">Вы уверены, что хотите навсегда удалить выбранные узлы\?</string>
<string name="warning_permanently_delete_nodes">Безвозвратно удалить выбранные узлы\?</string>
<string name="keystore_not_accessible">Хранилище ключей не инициализировано должным образом.</string>
<string name="credential_before_click_biometric_button">Введите пароль перед нажатием кнопки биометрии.</string>
<string name="recycle_bin_group_title">Группа \"корзины\"</string>
<string name="enable_auto_save_database_title">Автосохранение базы</string>
<string name="enable_auto_save_database_summary">Автоматическое сохранение базы после каждого важного действия (только в \"режиме записи\")</string>
<string name="enable_auto_save_database_summary">Сохранять базу после каждого важного действия (в \"режиме записи\")</string>
<string name="entry_attachments">Вложения</string>
<string name="menu_restore_entry_history">Восстановить историю</string>
<string name="menu_delete_entry_history">Удалить историю</string>
<string name="keyboard_auto_go_action_title">Автоматическое действие кнопки</string>
<string name="keyboard_auto_go_action_summary">Выполнять команду \"Ввод\" автоматически после нажатия кнопки заполнения поля</string>
<string name="keyboard_auto_go_action_summary">Выполнять команду \"Ввод\" после нажатия кнопки заполнения поля</string>
<string name="download_attachment">Скачать %1$s</string>
<string name="download_initialization">Инициализация…</string>
<string name="download_progression">Выполнение: %1$d%</string>
<string name="download_progression">Выполнение: %1$d&#37;</string>
<string name="download_finalization">Завершение…</string>
<string name="download_complete">Готово! Нажмите, чтобы открыть файл.</string>
<string name="hide_expired_entries_title">Скрывать устаревшие записи</string>
@@ -465,4 +463,11 @@
<string name="hide_broken_locations_title">Скрывать отсутствующие</string>
<string name="hide_broken_locations_summary">Не показывать неработающие ссылки в списке последних открытых баз</string>
<string name="warning_database_read_only">Необходимо разрешение на запись в файл для сохранения изменений базы</string>
<string name="validate">Проверить</string>
<string name="discard_changes">Отменить изменения\?</string>
<string name="discard">Отменить</string>
<string name="entry_add_attachment">Добавить вложение</string>
<string name="error_create_database">Невозможно создать файл базы.</string>
<string name="education_setup_OTP_title">Настройте OTP</string>
<string name="education_setup_OTP_summary">Настройте управление одноразовыми паролями (HOTP / TOTP) для создания токена, запрашиваемого при двухфакторной аутентификации (2FA).</string>
</resources>

View File

@@ -103,7 +103,6 @@
<string name="never">Nikdy</string>
<string name="no_results">Žiadne výsledky hľadania</string>
<string name="no_url_handler">Žiaden manažér pre url.</string>
<string name="open_recent">Otvoriť poslednú databázu :</string>
<string name="omit_backup_search_title">Neprehľadávať položky</string>
<string name="omit_backup_search_summary">Vynechať skupinu \'Backup\' a Recycle Bin z výsledkov hľadania</string>
<string name="progress_create">Vytváram novú databázu…</string>
@@ -123,7 +122,6 @@
<string name="underline">Podčiarknuté</string>
<string name="unsupported_db_version">Nepodporovaná verzia databázy.</string>
<string name="uppercase">Veľké písmená</string>
<string name="warning_unmounted">Vaša SD karta nie je momentálne pripojená k zariadeniu. Nemôžete načítať, alebo vytvoriť databázu.</string>
<string name="version_label">Version %1$s</string>
<string name="education_unlock_summary">Vložte heslo a / alebo keyfile pre odomknutie databázy.</string>
<string-array name="timeout_options">

View File

@@ -114,7 +114,6 @@
<string name="never">Aldrig</string>
<string name="no_results">Inget sökresultat</string>
<string name="no_url_handler">Installera en webbläsare för att öppna denna URL.</string>
<string name="open_recent">Senast öppnade databaser</string>
<string name="omit_backup_search_title">Sök inte efter backup-poster</string>
<string name="omit_backup_search_summary">Utelämnar poster i grupperna \"Backup\" och \"Papperskorg\"</string>
<string name="progress_create">Skapar ny databas…</string>
@@ -136,7 +135,6 @@
<string name="underline">Understreck</string>
<string name="unsupported_db_version">Databasversionen stöds ej.</string>
<string name="uppercase">Versaler</string>
<string name="warning_unmounted">Montera SD-kortet för att skapa eller ladda in en databas.</string>
<string name="version_label">Version %1$s</string>
<string name="education_unlock_summary">Ange lösenord och/eller nyckelfil för att öppna databasen.
\n

View File

@@ -16,7 +16,8 @@
You should have received a copy of the GNU General Public License
along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
--><resources>
-->
<resources>
<string name="feedback">Geri Bildirim</string>
<string name="homepage">Ana sayfa</string>
<string name="about_description">KeePass parola yöneticisinin Android uygulaması</string>
@@ -64,7 +65,8 @@
<string name="decrypting_db">Veritabanı içeriği deşifre ediliyor…</string>
<string name="default_checkbox">Varsayılan veritabanı olarak kullan</string>
<string name="digits">Rakamlar</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft kesinlikle bir garanti vermez. Bu, libre yazılımıdır ve GPL sürüm 3 veya üzeri şartlar altında yeniden dağıtmanız mümkündür.</string>
<string name="html_about_licence">KeePassDX © %1$d Kunzisoft &lt;strong&gt;özgür yazılımdır&lt;/strong&gt; ve &lt;strong&gt;reklam içermez&lt;/strong&gt;.
\n&lt;strong&gt;GPLv3&lt;/strong&gt; lisansı altında sağlanmaktadır, herhangi bir garanti vermez.</string>
<string name="entry_expires">Süre sonu</string>
<string name="entry_keyfile">Anahtar dosya</string>
<string name="error_arc4">Arcfour akış şifresi desteklenmiyor.</string>
@@ -76,7 +78,7 @@
<string name="error_pass_gen_type">En az bir parola oluşturma türü seçilmelidir.</string>
<string name="error_pass_match">Parolalar uyuşmuyor.</string>
<string name="error_rounds_too_large">\"Dönüşüm turları\" çok yüksek. 2147483648\'e ayarlayın.</string>
<string name="error_string_key">Her dizenin bir alan adı olmalıdır.</string>
<string name="error_string_key">Her dizginin bir alan adı olmalıdır.</string>
<string name="error_wrong_length">\"Uzunluk\" alanına pozitif bir tam sayı girin.</string>
<string name="error_autofill_enable_service">Otomatik doldurma hizmeti etkinleştirilemedi.</string>
<string name="error_move_folder_in_itself">Bir grubu kendine taşıyamazsın.</string>
@@ -135,7 +137,6 @@
<string name="no_url_handler">Bu URL\'u açmak için bir web tarayıcısı yükleyin.</string>
<string name="select_database_file">Mevcut veritabanını</string>
<string name="create_keepass_file">Yeni veritabanı oluştur</string>
<string name="open_recent">Son veritabanları</string>
<string name="omit_backup_search_title">Yedek girişleri arama</string>
<string name="omit_backup_search_summary">Arama sonuçlarından \"Yedekleme\" ve \"Geri dönüşüm kutusu\" gruplarını atlar</string>
<string name="progress_create">Yeni veritabanı oluştur…</string>
@@ -175,9 +176,8 @@
<string name="uppercase">Büyük harf</string>
<string name="warning">Uyarı</string>
<string name="warning_password_encoding">Veritabanı dosyasındaki metin kodlama formatının dışındaki parola karakterlerinden kaçının (tanınmayan karakterler benzer harfe dönüştürülür).</string>
<string name="warning_unmounted">Bir veritabanı oluşturmak veya yüklemek için hafıza kartını takın.</string>
<string name="warning_empty_password">Gerçekten parolasız açma koruması mı istiyorsunuz\?</string>
<string name="warning_no_encryption_key">Herhangi bir şifreleme anahtarı kullanmak istemediğinize emin misiniz\?</string>
<string name="warning_empty_password">Parola kilidi koruması olmadan devam edilsin mi\?</string>
<string name="warning_no_encryption_key">Şifreleme anahtarı olmadan devam edilsin mi\?</string>
<string name="version_label">Sürüm %1$s</string>
<string name="build_label">Yapı %1$s</string>
<string name="configure_biometric">Parmak izi taraması desteklenir, ancak kurulmaz.</string>
@@ -212,7 +212,7 @@
<string name="biometric_unlock_enable_summary">Veritabanını açmak için biyometriklerinizi taramanızı sağlar</string>
<string name="biometric_delete_all_key_title">Şifreleme anahtarlarını silin</string>
<string name="biometric_delete_all_key_summary">Parmak izi tanıma ile ilgili tüm şifreleme anahtarlarını silin</string>
<string name="biometric_delete_all_key_warning">Parmak izi tanıma ile ilgili tüm tuşları silmek istediğinizden emin misiniz\?</string>
<string name="biometric_delete_all_key_warning">Biyometrik tanıma ile ilgili tüm şifreleme anahtarları silinsin mi\?</string>
<string name="unavailable_feature_text">Bu özellik başlatılamadı.</string>
<string name="unavailable_feature_version">Android sürümünüz %1$s, gerekli minimum %2$s sürümünü karşılamıyor.</string>
<string name="unavailable_feature_hardware">İlgili donanım bulunamadı.</string>
@@ -278,10 +278,10 @@
<string name="education_biometric_summary">Veritabanınızı hızlıca açmak için parolanızı taranan parmak izinize bağlayın.</string>
<string name="education_entry_edit_title">Girdiyi düzenle</string>
<string name="education_entry_edit_summary">Girdinizi özel alanlarla düzenleyin. Havuz verileri farklı giriş alanları arasında referans alınabilir.</string>
<string name="education_generate_password_title">Girdiniz için güçlü bir parola oluşturun.</string>
<string name="education_generate_password_title">Güçlü bir parola oluşturun</string>
<string name="education_generate_password_summary">Girişinizle ilişkilendirmek için güçlü bir şifre oluşturun, formun kriterlerine göre kolayca tanımlayın ve güvenli şifreyi unutmayın.</string>
<string name="education_entry_new_field_title">Özel alanlar ekle</string>
<string name="education_entry_new_field_summary">Ayrıca koruyabileceğiniz yeni bir formu doldurarak temel bir tedarik edilmemiş alanı kaydedin.</string>
<string name="education_entry_new_field_summary">Ek bir alan kaydedin, bir değer ekleyin ve isteğe bağlı olarak koruyun.</string>
<string name="education_unlock_title">Veritabanınızın kilidini açın</string>
<string name="education_unlock_summary">Veritabanınızın kilidini açmak için parola ve/veya anahtar dosya girin.
\n
@@ -301,7 +301,7 @@
<string name="education_sort_summary">Girdilerin ve grupların nasıl sıralandığını seçin.</string>
<string name="education_donation_title">Katıl</string>
<string name="education_donation_summary">Daha fazla özellik ekleyerek istikrarı, güvenliği artırmaya yardımcı olun.</string>
<string name="html_text_ad_free">Birçok parola yönetimi uygulamasının aksine, bu uygulama &lt;strong&gt;reklam içermez&lt;/strong&gt;, &lt;strong&gt;ık kaynaklı&lt;/strong&gt; ve &lt;strong&gt;copyleft lisanslıdır&lt;/strong&gt;. Hangi sürümü (ücretsiz veya profesyonel) kullanırsanız kullanın, herhangi bir biçimde &lt;strong&gt;kişisel veri toplanmamaktadır&lt;/strong&gt;.</string>
<string name="html_text_ad_free">Birçok parola yönetimi uygulamasının aksine, bu uygulama &lt;strong&gt;reklam içermez&lt;/strong&gt;, &lt;strong&gt; copyleft lisanslı özgür yazılımdır&lt;/strong&gt; ve hangi sürümü kullanırsanız kullanın, sunucularında kişisel veri toplamaz.</string>
<string name="html_text_buy_pro">Profesyonel sürümü satın alarak, bu &lt;strong&gt;görsel stile&lt;/strong&gt; erişebilecek ve özellikle &lt;strong&gt;topluluk projelerinin gerçekleştirilmesine&lt;/strong&gt; yardımcı olacaksınız.</string>
<string name="html_text_feature_generosity">Bu &lt;strong&gt;görsel stil&lt;/strong&gt;, cömertliğiniz sayesinde kullanılabilir.</string>
<string name="html_text_donation">Özgürlüğümüzü korumak ve daima aktif olmak için &lt;strong&gt;katkılarınıza&lt;/strong&gt; güveniyoruz</string>
@@ -390,7 +390,7 @@
<string name="menu_security_settings">Güvenlik ayarları</string>
<string name="menu_master_key_settings">Ana anahtar ayarları</string>
<string name="contains_duplicate_uuid">Veritabanı tekrarlanan UUID\'ler içermektedir.</string>
<string name="contains_duplicate_uuid_procedure">Bu iletişim kutusunu doğrulayarak, KeePassDX sorunu çözecek (tekrarlananlar için yeni UUID\'ler oluşturarak) ve devam edecektir.</string>
<string name="contains_duplicate_uuid_procedure">Tekrarlananlar için yeni UUID\'ler oluşturarak sorunu çöz ve devam et\?</string>
<string name="database_opened">Veritabanııldı</string>
<string name="clipboard_explanation_summary">Cihazınızın panosunu kullanarak giriş alanlarını kopyala</string>
<string name="advanced_unlock_explanation_summary">Veritabanını daha kolay açmak için gelişmiş kilit açma özelliğini kullan</string>
@@ -404,29 +404,29 @@
<string name="settings_database_recommend_changing_master_key_summary">Ana anahtarın değiştirilmesini öner (gün)</string>
<string name="settings_database_force_changing_master_key_title">Yenilemeyi zorla</string>
<string name="settings_database_force_changing_master_key_summary">Ana anahtarın değiştirilmesini gerektir (gün)</string>
<string name="settings_database_force_changing_master_key_next_time_title">Bir dahaki sefere yenilemeyi zorla</string>
<string name="settings_database_force_changing_master_key_next_time_title">Bir dahaki sefere yenilemeye zorla</string>
<string name="settings_database_force_changing_master_key_next_time_summary">Bir dahaki sefere ana anahtarı değiştirmeyi gerektirir (bir kez)</string>
<string name="database_default_username_title">Varsayılan kullanıcı adı</string>
<string name="database_custom_color_title">Özel veritabanı rengi</string>
<string name="compression">Sıkıştırma</string>
<string name="compression_none">Yok</string>
<string name="compression_gzip">gzip</string>
<string name="device_keyboard_setting_title">Cihaz klavye Ayarları</string>
<string name="device_keyboard_setting_title">Cihaz klavye ayarları</string>
<string name="error_save_database">Veritabanı kaydedilemedi.</string>
<string name="menu_save_database">Veritabanını kaydet</string>
<string name="menu_empty_recycle_bin">Geri dönüşüm kutusunu boşalt</string>
<string name="command_execution">Komut çalıştırılıyor…</string>
<string name="warning_permanently_delete_nodes">Seçili düğümleri kalıcı olarak silmek istediğinizden emin misiniz\?</string>
<string name="warning_permanently_delete_nodes">Seçilen düğümler kalıcı olarak silinsin mi\?</string>
<string name="keystore_not_accessible">Anahtar deposu düzgün bir şekilde başlatılmadı.</string>
<string name="credential_before_click_biometric_button">Biyometrik butona tıklamadan önce şifreyi yazın.</string>
<string name="recycle_bin_group_title">Geri dönüşüm kutusu grubu</string>
<string name="enable_auto_save_database_title">Veritabanını otomatik kaydet</string>
<string name="enable_auto_save_database_summary">Önemli bir işlemden sonra veritabanını otomatik olarak kaydet (yalnızca \"Değiştirilebilir\" modunda)</string>
<string name="enable_auto_save_database_summary">Her önemli işlemden sonra veri tabanını kaydet (\"Değiştirilebilir\" modda)</string>
<string name="entry_attachments">Ekler</string>
<string name="menu_restore_entry_history">Geçmişi geri yükle</string>
<string name="menu_delete_entry_history">Geçmişi sil</string>
<string name="keyboard_auto_go_action_title">Otomatik tuş eylemi</string>
<string name="keyboard_auto_go_action_summary">Alan tuşuna bastıktan sonra otomatik olarak gerçekleştirilen Git tuşunun eylemi</string>
<string name="keyboard_auto_go_action_summary">\"Alan\" tuşuna bastıktan sonra \"Git\" tuşu eylemi</string>
<string name="download_attachment">İndir %1$s</string>
<string name="download_initialization">Başlatılıyor…</string>
<string name="download_progression">Devam ediyor: %1$d&#37;</string>
@@ -434,4 +434,25 @@
<string name="download_complete">Tamamlandı! Dosyayı açmak için dokunun.</string>
<string name="hide_expired_entries_title">Süresi dolmuş girdileri gizle</string>
<string name="hide_expired_entries_summary">Süresi dolmuş girdiler gizlenecek</string>
<string name="warning_database_read_only">Veritabanı değişikliklerini kaydetmek için dosya yazma erişimi ver</string>
<string name="hide_broken_locations_summary">Son veritabanları listesindeki bozuk bağlantıları gizle</string>
<string name="hide_broken_locations_title">Bozuk veritabanı bağlantılarını gizle</string>
<string name="show_recent_files_summary">Son veritabanlarının konumlarını göster</string>
<string name="show_recent_files_title">Son dosyaları göster</string>
<string name="remember_keyfile_locations_summary">Veri tabanını anahtar dosyalarının konumunu hatırla</string>
<string name="remember_keyfile_locations_title">Anahtar dosyalarının konumlarını kaydet</string>
<string name="remember_database_locations_summary">Veri tabanlarının konumlarını hatırla</string>
<string name="remember_database_locations_title">Veri tabanlarının konumlarını kaydet</string>
<string name="auto_focus_search_summary">Veri tabanını açarken arama iste</string>
<string name="auto_focus_search_title">Hızlı arama</string>
<string name="contribution">Katkı</string>
<string name="contact">İletişim</string>
<string name="education_setup_OTP_summary">İki öğeli kimlik doğrulaması (2FA) için istenen bir belirteç oluşturmak için Bir Kerelik Parola yönetimini (HOTP / TOTP) ayarlayın.</string>
<string name="education_setup_OTP_title">OTP ayarla</string>
<string name="error_create_database">Veritabanı dosyası oluşturulamıyor.</string>
<string name="html_about_contribution">&lt;strong&gt;Özgürlüğümüzü korumak&lt;/strong&gt;, &lt;strong&gt;hataları düzeltmek&lt;/strong&gt;, &lt;strong&gt;özellikler eklemek&lt;/strong&gt; ve &lt;strong&gt;her zaman etkin olmak&lt;/strong&gt; için, &lt;strong&gt;desteğinize&lt;/strong&gt; güveniyoruz.</string>
<string name="entry_add_attachment">Ek ekle</string>
<string name="discard">Vazgeç</string>
<string name="discard_changes">Değişikliklerden vazgeç\?</string>
<string name="validate">Doğrula</string>
</resources>

View File

@@ -104,7 +104,6 @@
<string name="never">Ніколи</string>
<string name="no_results">Нічого не знайдено.</string>
<string name="no_url_handler">Нема програми для опрацювання цього посилання.</string>
<string name="open_recent">Відкрити останню базу даних :</string>
<string name="omit_backup_search_title">Не шукати записів з резервного копіювання та кошиків</string>
<string name="omit_backup_search_summary">Пропустити групу \'Резервна копія\' та Кошик серед результатів пошуку</string>
<string name="progress_create">Створення нової бази даних&#8230;</string>
@@ -124,7 +123,6 @@
<string name="underline">Підкреслення</string>
<string name="unsupported_db_version">Непідтримувана версія бази даних.</string>
<string name="uppercase">Верхній регістр</string>
<string name="warning_unmounted">Ваша карта пам’яті зараз не змонтована на телефоні. Ви не зможете завантажити або створити базу даних.</string>
<string name="version_label">Версія %1$s</string>
<string name="education_unlock_summary">Введіть пароль і/або файл ключа для відкриття бази даних.</string>

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