Compare commits

..

819 Commits

Author SHA1 Message Date
Philipp Crocoll
0ce77a2729 1.07-r1 2019-08-05 07:20:44 +02:00
Philipp Crocoll
b0f61038e3 fix potential crash in Google Drive storage 2019-04-10 06:01:22 +02:00
Philipp Crocoll
d0749324c9 Merge remote-tracking branch 'remotes/origin/l10n_master'
# Resolved Conflicts:
#	src/keepass2android/Resources/values-da/strings.xml
#	src/keepass2android/Resources/values-de/strings.xml
#	src/keepass2android/Resources/values-nl/strings.xml
#	src/keepass2android/Resources/values-ru/strings.xml
2019-04-01 10:36:15 +02:00
PhilippC
a43f72d18a New translations strings.xml (German) 2019-04-01 10:29:58 +02:00
PhilippC
3d691088be New translations strings.xml (Portuguese, Brazilian) 2019-04-01 10:29:53 +02:00
Philipp Crocoll
bca3becadb improved language in resource strings 2019-04-01 10:21:50 +02:00
PhilippC
d937fbe7ad New translations strings.xml (Danish) 2019-04-01 04:10:10 +02:00
PhilippC
c13e00871d New translations strings.xml (Danish) 2019-04-01 03:50:10 +02:00
PhilippC
b5b716da4c New translations strings.xml (Danish) 2019-04-01 03:30:09 +02:00
PhilippC
45d2a8e0b2 New translations strings.xml (Danish) 2019-04-01 03:20:10 +02:00
PhilippC
d47c948699 New translations strings.xml (Danish) 2019-04-01 03:10:11 +02:00
PhilippC
fdf36babba New translations strings.xml (Danish) 2019-04-01 03:00:12 +02:00
PhilippC
d47411264e New translations strings.xml (Danish) 2019-04-01 02:50:11 +02:00
PhilippC
b9ebad7942 New translations strings.xml (Danish) 2019-04-01 02:40:09 +02:00
PhilippC
2878cc1cb5 New translations strings.xml (Danish) 2019-04-01 02:10:11 +02:00
PhilippC
9277d76f37 New translations strings.xml (Danish) 2019-04-01 02:00:21 +02:00
PhilippC
b7b1301334 New translations strings.xml (Turkish) 2019-03-31 14:10:11 +02:00
PhilippC
954dd73ffa New translations strings.xml (Turkish) 2019-03-31 14:00:12 +02:00
PhilippC
7aeab98c5b New translations strings.xml (Portuguese) 2019-03-30 00:00:10 +01:00
PhilippC
51123d60d3 New translations strings.xml (Portuguese) 2019-03-29 23:50:11 +01:00
PhilippC
395d4b5a97 New translations strings.xml (Hungarian) 2019-03-29 15:00:15 +01:00
PhilippC
654f025f64 New translations strings.xml (Hungarian) 2019-03-29 14:50:11 +01:00
PhilippC
8a9ccea5d3 New translations strings.xml (Hungarian) 2019-03-29 14:40:11 +01:00
PhilippC
92e00075c6 New translations strings.xml (Hungarian) 2019-03-29 14:30:11 +01:00
PhilippC
624e78e734 New translations strings.xml (Hungarian) 2019-03-29 14:20:11 +01:00
PhilippC
76bb8822fa New translations strings.xml (Hungarian) 2019-03-29 14:10:09 +01:00
PhilippC
e3cba097fa New translations strings.xml (Hungarian) 2019-03-29 14:00:13 +01:00
PhilippC
c812fca8c1 New translations strings.xml (Hungarian) 2019-03-29 13:50:10 +01:00
PhilippC
f86f4ee18c New translations strings.xml (Hungarian) 2019-03-29 13:20:09 +01:00
PhilippC
dafed9786e New translations strings.xml (Hungarian) 2019-03-29 13:10:10 +01:00
PhilippC
cd3a119053 New translations strings.xml (Hungarian) 2019-03-29 13:00:14 +01:00
PhilippC
f143a171aa New translations strings.xml (Hungarian) 2019-03-29 12:50:13 +01:00
PhilippC
ee93d7df82 New translations strings.xml (Hungarian) 2019-03-29 12:40:11 +01:00
PhilippC
61a3bcc53d New translations strings.xml (Hungarian) 2019-03-29 12:30:12 +01:00
PhilippC
17a46eb92c New translations strings.xml (Hungarian) 2019-03-29 12:00:11 +01:00
PhilippC
14b121a8ba New translations strings.xml (Danish) 2019-03-29 01:50:11 +01:00
PhilippC
41b57417e5 New translations strings.xml (Russian) 2019-03-28 20:10:13 +01:00
PhilippC
bb492c3043 New translations strings.xml (Slovak) 2019-03-28 18:50:14 +01:00
PhilippC
b683dca67c New translations strings.xml (Slovak) 2019-03-28 18:40:11 +01:00
PhilippC
b6e6024bda New translations strings.xml (German) 2019-03-28 15:30:31 +01:00
PhilippC
2b3a95e21d New translations strings.xml (German) 2019-03-28 15:20:13 +01:00
PhilippC
de9c27f1f5 New translations strings.xml (Portuguese, Brazilian) 2019-03-28 13:40:13 +01:00
PhilippC
85c9cb26b1 New translations strings.xml (Portuguese, Brazilian) 2019-03-28 13:30:13 +01:00
PhilippC
8ffa27e93d New translations strings.xml (Italian) 2019-03-28 13:20:19 +01:00
PhilippC
ea743fc2c5 New translations strings.xml (Portuguese, Brazilian) 2019-03-28 13:20:13 +01:00
PhilippC
7fab9aab00 New translations strings.xml (Italian) 2019-03-28 13:10:18 +01:00
PhilippC
444e224d41 New translations strings.xml (Portuguese, Brazilian) 2019-03-28 13:10:12 +01:00
PhilippC
9fde19f1ce New translations strings.xml (Portuguese) 2019-03-28 12:20:22 +01:00
PhilippC
4e085b5dca New translations strings.xml (Italian) 2019-03-28 12:20:16 +01:00
PhilippC
06ab58cc07 New translations strings.xml (Danish) 2019-03-28 11:50:12 +01:00
PhilippC
9dae1746ec New translations strings.xml (Danish) 2019-03-28 11:30:11 +01:00
PhilippC
db87191f1f New translations strings.xml (Danish) 2019-03-28 11:20:10 +01:00
PhilippC
76abe79b6d New translations strings.xml (Japanese) 2019-03-28 10:30:12 +01:00
PhilippC
970bc29e01 New translations strings.xml (Japanese) 2019-03-28 10:20:13 +01:00
PhilippC
79a3262659 New translations strings.xml (French) 2019-03-28 10:10:11 +01:00
PhilippC
3add6d64ef New translations strings.xml (French) 2019-03-28 09:50:12 +01:00
PhilippC
43168b18d1 New translations strings.xml (French) 2019-03-28 09:40:11 +01:00
PhilippC
6970b42456 New translations strings.xml (Polish) 2019-03-28 09:10:17 +01:00
PhilippC
a545b96601 New translations strings.xml (Spanish) 2019-03-28 09:10:11 +01:00
PhilippC
59b66409e8 New translations strings.xml (Chinese Traditional) 2019-03-28 09:00:13 +01:00
PhilippC
25c50bbcaf New translations strings.xml (Chinese Traditional) 2019-03-28 08:50:09 +01:00
PhilippC
a9a5df00d2 New translations strings.xml (German) 2019-03-28 08:40:09 +01:00
PhilippC
5f4d9c29dc New translations strings.xml (German) 2019-03-28 08:10:09 +01:00
PhilippC
31e158e39b New translations strings.xml (Ukrainian) 2019-03-28 08:00:10 +01:00
PhilippC
25af5844be New translations strings.xml (German) 2019-03-28 07:50:10 +01:00
PhilippC
f79bb49af1 New translations strings.xml (Slovenian) 2019-03-28 07:30:19 +01:00
PhilippC
2756bae656 New translations strings.xml (Italian) 2019-03-28 07:30:14 +01:00
PhilippC
b574b55f84 New translations strings.xml (Dutch) 2019-03-28 07:30:09 +01:00
PhilippC
76ef1c4033 New translations strings.xml (Dutch) 2019-03-28 07:20:09 +01:00
PhilippC
409deaee9d New translations strings.xml (Italian) 2019-03-28 07:10:16 +01:00
PhilippC
8396e18283 New translations strings.xml (Dutch) 2019-03-28 07:10:10 +01:00
PhilippC
5e952e06ff New translations strings.xml (Italian) 2019-03-28 07:00:12 +01:00
PhilippC
7b6dc3d773 New translations strings.xml (Italian) 2019-03-28 06:50:10 +01:00
PhilippC
1759b67921 New translations strings.xml (Ukrainian) 2019-03-28 06:10:10 +01:00
PhilippC
1307b0e5d1 New translations strings.xml (Ukrainian) 2019-03-28 05:50:10 +01:00
PhilippC
c1af6994bf New translations strings.xml (Ukrainian) 2019-03-28 05:40:09 +01:00
PhilippC
d09c15e5b8 New translations strings.xml (Chinese Simplified) 2019-03-28 05:30:23 +01:00
PhilippC
ea98b170d9 New translations strings.xml (Russian) 2019-03-28 05:30:17 +01:00
PhilippC
c67f4e45c7 New translations strings.xml (Ukrainian) 2019-03-28 05:30:11 +01:00
PhilippC
c21a5afe94 New translations strings.xml (Chinese Simplified) 2019-03-28 05:20:15 +01:00
PhilippC
49de16f0f3 New translations strings.xml (Russian) 2019-03-28 05:20:09 +01:00
PhilippC
6d60afadf4 New translations strings.xml (Chinese Simplified) 2019-03-28 05:10:09 +01:00
PhilippC
c6751af075 New translations strings.xml (Vietnamese) 2019-03-28 05:02:50 +01:00
PhilippC
d41aa389a7 New translations strings.xml (Dutch) 2019-03-28 05:02:46 +01:00
PhilippC
f95986fd7a New translations strings.xml (Czech) 2019-03-28 05:02:40 +01:00
PhilippC
ac522bce43 New translations strings.xml (Croatian) 2019-03-28 05:02:34 +01:00
PhilippC
6e0729c3b3 New translations strings.xml (Chinese Traditional) 2019-03-28 05:02:30 +01:00
PhilippC
9ce674da2b New translations strings.xml (Chinese Simplified) 2019-03-28 05:02:26 +01:00
PhilippC
da8a8e7e77 New translations strings.xml (Catalan) 2019-03-28 05:02:22 +01:00
PhilippC
566a1088bd New translations strings.xml (Bulgarian) 2019-03-28 05:02:16 +01:00
PhilippC
11f1f07653 New translations strings.xml (Finnish) 2019-03-28 05:02:11 +01:00
PhilippC
45194bb26f New translations strings.xml (Basque) 2019-03-28 05:02:05 +01:00
PhilippC
1f6440189f New translations strings.xml (Russian) 2019-03-28 05:01:59 +01:00
PhilippC
60e98d87d8 New translations strings.xml (Danish) 2019-03-28 05:01:54 +01:00
PhilippC
f560124088 New translations strings.xml (German) 2019-03-28 05:01:48 +01:00
PhilippC
7521d0b787 New translations strings.xml (Portuguese, Brazilian) 2019-03-28 05:01:45 +01:00
PhilippC
c45e52f571 New translations strings.xml (Ukrainian) 2019-03-28 04:45:19 +01:00
PhilippC
275920e5be New translations strings.xml (Greek) 2019-03-28 04:45:16 +01:00
PhilippC
7045c6ee8d New translations strings.xml (Turkish) 2019-03-28 04:45:11 +01:00
PhilippC
7a7b65e8c6 New translations strings.xml (Azerbaijani) 2019-03-28 04:45:04 +01:00
PhilippC
261526b4d1 New translations strings.xml (Arabic) 2019-03-28 04:44:58 +01:00
PhilippC
bc74c91a2c New translations strings.xml (French) 2019-03-28 04:44:53 +01:00
PhilippC
ab47543df0 New translations strings.xml (Hebrew) 2019-03-28 04:44:47 +01:00
PhilippC
3a601468a9 New translations strings.xml (Swedish) 2019-03-28 04:44:42 +01:00
PhilippC
f2002e2b90 New translations strings.xml (Slovenian) 2019-03-28 04:44:38 +01:00
PhilippC
29031167d6 New translations strings.xml (Slovak) 2019-03-28 04:44:32 +01:00
PhilippC
7305ac47c3 New translations strings.xml (Serbian (Cyrillic)) 2019-03-28 04:44:26 +01:00
PhilippC
2aec6c9e4b New translations strings.xml (Romanian) 2019-03-28 04:44:22 +01:00
PhilippC
5a2cdf3cda New translations strings.xml (Portuguese) 2019-03-28 04:44:18 +01:00
PhilippC
a943df63fc New translations strings.xml (Polish) 2019-03-28 04:44:13 +01:00
PhilippC
ca771abebe New translations strings.xml (Galician) 2019-03-28 04:44:07 +01:00
PhilippC
010db6148d New translations strings.xml (Persian) 2019-03-28 04:44:01 +01:00
PhilippC
8f065f480c New translations strings.xml (Norwegian Bokmal) 2019-03-28 04:43:57 +01:00
PhilippC
f163f9382f New translations strings.xml (Korean) 2019-03-28 04:43:52 +01:00
PhilippC
e752244b5f New translations strings.xml (Japanese) 2019-03-28 04:43:47 +01:00
PhilippC
4bbb958a05 New translations strings.xml (Italian) 2019-03-28 04:43:43 +01:00
PhilippC
d1ddfed8dd New translations strings.xml (Indonesian) 2019-03-28 04:43:39 +01:00
PhilippC
bdb39f203a New translations strings.xml (Hungarian) 2019-03-28 04:43:34 +01:00
PhilippC
1bcb6aabe7 New translations strings.xml (Norwegian Nynorsk) 2019-03-28 04:43:30 +01:00
PhilippC
90b09b0f7e New translations strings.xml (Spanish) 2019-03-28 04:43:26 +01:00
Philipp Crocoll
4e6e0a0e73 improve English texts 2019-03-28 04:42:40 +01:00
Philipp Crocoll
ad4c764adb fix potential crashes when database has been closed and recreating activities 2019-03-28 04:42:24 +01:00
PhilippC
2265432ec4 New translations strings.xml (German) 2019-03-28 04:40:11 +01:00
PhilippC
bb45e60a3f New translations strings.xml (French) 2019-03-27 22:20:09 +01:00
PhilippC
b1ff92d63e New translations strings.xml (French) 2019-03-27 22:10:15 +01:00
Philipp Crocoll
016864edfc fix potential crash 2019-03-27 19:20:16 +01:00
PhilippC
dc5133e676 New translations strings.xml (Greek) 2019-03-27 01:00:12 +01:00
PhilippC
1fbd10c918 New translations strings.xml (Greek) 2019-03-27 00:50:09 +01:00
PhilippC
4cd219ab32 New translations strings.xml (Greek) 2019-03-27 00:40:10 +01:00
PhilippC
871e84fec9 New translations strings.xml (Greek) 2019-03-27 00:30:11 +01:00
PhilippC
08ce132587 New translations strings.xml (Greek) 2019-03-27 00:20:09 +01:00
PhilippC
4c58d8df72 New translations strings.xml (Greek) 2019-03-27 00:10:11 +01:00
PhilippC
bf554d2417 New translations strings.xml (Greek) 2019-03-27 00:00:09 +01:00
PhilippC
631cd8e35f New translations strings.xml (Greek) 2019-03-26 23:50:12 +01:00
PhilippC
f46c4d8054 New translations strings.xml (Russian) 2019-03-26 22:50:10 +01:00
PhilippC
0010713b78 New translations strings.xml (Russian) 2019-03-26 22:40:13 +01:00
PhilippC
f5bfd4f8f2 New translations strings.xml (Russian) 2019-03-26 22:30:09 +01:00
PhilippC
6d04d2f579 New translations strings.xml (Russian) 2019-03-26 22:20:10 +01:00
PhilippC
0d3cef1626 New translations strings.xml (Chinese Traditional) 2019-03-25 18:50:10 +01:00
PhilippC
4d251becb0 New translations strings.xml (Chinese Traditional) 2019-03-25 18:40:09 +01:00
PhilippC
372d4c4bf3 New translations strings.xml (Slovenian) 2019-03-25 11:20:12 +01:00
PhilippC
2dbda89973 New translations strings.xml (German) 2019-03-25 11:12:54 +01:00
PhilippC
2f55bbddd8 New translations strings.xml (Portuguese) 2019-03-25 11:11:54 +01:00
PhilippC
928773b183 New translations strings.xml (German) 2019-03-25 10:50:13 +01:00
PhilippC
bc9803cbc4 New translations strings.xml (German) 2019-03-25 10:40:10 +01:00
Philipp Crocoll
fca8f5efbc remove unused strings 2019-03-25 10:34:19 +01:00
PhilippC
f09fe4f7e2 New translations strings.xml (German) 2019-03-25 10:30:12 +01:00
PhilippC
de3bc0ff6c New translations strings.xml (Japanese) 2019-03-25 10:20:11 +01:00
Philipp Crocoll
c4a1b6a82e avoid opening password activity when database is already open, closes https://github.com/PhilippC/keepass2android/issues/706 2019-03-25 10:10:19 +01:00
PhilippC
bd08dd54e2 New translations strings.xml (Chinese Traditional) 2019-03-25 09:33:14 +01:00
PhilippC
b1f93fdb75 New translations strings.xml (Chinese Simplified) 2019-03-25 09:33:07 +01:00
PhilippC
51599b3f1a New translations strings.xml (Catalan) 2019-03-25 09:33:02 +01:00
PhilippC
1b753877a9 New translations strings.xml (Finnish) 2019-03-25 09:32:55 +01:00
PhilippC
d33ffa9d22 New translations strings.xml (Portuguese, Brazilian) 2019-03-25 09:32:36 +01:00
PhilippC
df710e523a New translations strings.xml (Turkish) 2019-03-25 09:32:23 +01:00
PhilippC
7d218e0706 New translations strings.xml (Slovenian) 2019-03-25 09:31:57 +01:00
PhilippC
88127a4858 New translations strings.xml (Slovak) 2019-03-25 09:31:51 +01:00
PhilippC
63f2a6f902 New translations strings.xml (Japanese) 2019-03-25 09:31:14 +01:00
Philipp Crocoll
d8286eb639 Merge branch 'l10n_master' of https://github.com/PhilippC/keepass2android
# Resolved Conflicts:
#	src/keepass2android/Resources/values-cs/strings.xml
#	src/keepass2android/Resources/values-da/strings.xml
#	src/keepass2android/Resources/values-de/strings.xml
#	src/keepass2android/Resources/values-hu/strings.xml
#	src/keepass2android/Resources/values-nl/strings.xml
#	src/keepass2android/Resources/values-pl/strings.xml
#	src/keepass2android/Resources/values-ru/strings.xml
#	src/keepass2android/Resources/values-tr/strings.xml
2019-03-25 09:27:27 +01:00
PhilippC
668fa46a98 New translations strings.xml (Slovenian) 2019-03-25 09:15:11 +01:00
PhilippC
e16a671a26 New translations strings.xml (Portuguese) 2019-03-25 09:14:56 +01:00
Philipp Crocoll
7f89ef358c Merge branch 'master' of https://github.com/PhilippC/keepass2android 2019-03-25 09:10:05 +01:00
Philipp Crocoll
e0df319279 try to proceed to password activity also if file storage setup is required, closes https://github.com/PhilippC/keepass2android/issues/416 2019-03-25 09:09:55 +01:00
Philipp Crocoll
61c7a260b4 improve child database configuration activity 2019-03-25 09:08:48 +01:00
Philipp Crocoll
f26fce63ad avoid crash when ROM does not support fingerprint encryption, closes https://github.com/PhilippC/keepass2android/issues/155 2019-03-25 09:08:32 +01:00
Philipp Crocoll
74c3c96b43 Merge branch 'master' of c:/ph/keepass2android 2019-03-25 09:05:39 +01:00
PhilippC
765b020152 New translations strings.xml (Chinese Traditional) 2019-03-25 05:30:11 +01:00
PhilippC
59c05235f6 New translations strings.xml (Chinese Traditional) 2019-03-25 05:20:10 +01:00
PhilippC
92a4131c88 New translations strings.xml (Chinese Traditional) 2019-03-25 05:10:12 +01:00
Philipp Crocoll
540e14bbe7 1.07-pre8 2019-03-24 20:27:35 +01:00
PhilippC
0ebd355edd New translations strings.xml (Slovak) 2019-03-23 23:10:10 +01:00
PhilippC
68d4dfed04 New translations strings.xml (Slovenian) 2019-03-23 19:40:09 +01:00
PhilippC
37a482d2e4 New translations strings.xml (Slovenian) 2019-03-23 19:30:09 +01:00
PhilippC
b79cc65728 New translations strings.xml (Japanese) 2019-03-23 16:10:10 +01:00
PhilippC
78977c7e31 New translations strings.xml (Japanese) 2019-03-23 16:00:11 +01:00
PhilippC
1957fc5345 New translations strings.xml (Turkish) 2019-03-23 07:50:09 +01:00
PhilippC
49cefff75d New translations strings.xml (Turkish) 2019-03-23 07:30:08 +01:00
PhilippC
2ebb145b7b New translations strings.xml (Turkish) 2019-03-23 07:20:17 +01:00
PhilippC
0a6f1394e4 New translations strings.xml (Turkish) 2019-03-23 07:10:11 +01:00
PhilippC
1310913281 New translations strings.xml (Slovenian) 2019-03-22 20:40:10 +01:00
PhilippC
c245c5ade3 New translations strings.xml (Slovenian) 2019-03-22 20:20:10 +01:00
PhilippC
9e6f45a59b New translations strings.xml (Slovenian) 2019-03-22 20:00:18 +01:00
PhilippC
f6a78c8890 New translations strings.xml (Slovenian) 2019-03-22 16:00:15 +01:00
PhilippC
76717fa3cb New translations strings.xml (Slovenian) 2019-03-22 13:10:10 +01:00
PhilippC
a19230393d New translations strings.xml (Chinese Simplified) 2019-03-22 08:00:13 +01:00
PhilippC
0b89969a33 New translations strings.xml (Chinese Simplified) 2019-03-22 07:50:10 +01:00
PhilippC
bbe97230d2 New translations strings.xml (German) 2019-03-22 05:40:10 +01:00
PhilippC
ee0161737c New translations strings.xml (Catalan) 2019-03-22 05:20:10 +01:00
Philipp Crocoll
e7e0b91703 fix potential crash when changing offline cache preference 2019-03-22 04:59:44 +01:00
PhilippC
dbcdf71bbe New translations strings.xml (French) 2019-03-21 21:50:12 +01:00
PhilippC
779615c09a New translations strings.xml (Finnish) 2019-03-21 06:20:11 +01:00
PhilippC
1c3a1ce53c New translations strings.xml (Finnish) 2019-03-21 06:10:09 +01:00
PhilippC
981c524e3f New translations strings.xml (Croatian) 2019-03-21 05:22:26 +01:00
PhilippC
44a7d68f31 New translations strings.xml (Chinese Traditional) 2019-03-21 05:22:22 +01:00
PhilippC
ae858e3dc4 New translations strings.xml (Chinese Simplified) 2019-03-21 05:22:17 +01:00
PhilippC
22fd23a31d New translations strings.xml (Catalan) 2019-03-21 05:22:13 +01:00
PhilippC
2babe87d6d New translations strings.xml (Russian) 2019-03-21 05:21:59 +01:00
PhilippC
95a8b3fe34 New translations strings.xml (German) 2019-03-21 05:21:50 +01:00
PhilippC
32c526a26a New translations strings.xml (Portuguese, Brazilian) 2019-03-21 05:21:46 +01:00
Philipp Crocoll
b2adfad2ee catch potential file not found exceptions 2019-03-21 04:27:44 +01:00
Philipp Crocoll
ee5a8534a7 catch all exceptions when stopping fingerprint, maybe there is a java exception 2019-03-21 04:15:04 +01:00
Philipp Crocoll
80ba3b969d allow to turn off saving of credentials through Autofill for the whole app. Closes https://github.com/PhilippC/keepass2android/issues/488. Allow to re-enable disabled autofill targets in the app preferences. Closes https://github.com/PhilippC/keepass2android/issues/715 2019-03-21 04:13:29 +01:00
Philipp Crocoll
83bd6911c8 Merge branch 'master' of c:/ph/keepass2android 2019-03-19 22:08:28 +01:00
Philipp Crocoll
6c66f6199c 1.07-pre7 2019-03-19 22:08:19 +01:00
Philipp Crocoll
c11731541c reenable search suggestion listener 2019-03-19 22:07:38 +01:00
PhilippC
609593ebd0 New translations strings.xml (French) 2019-03-19 21:51:42 +01:00
PhilippC
85b867a5ca New translations strings.xml (Slovak) 2019-03-19 21:51:27 +01:00
PhilippC
a3690051eb New translations strings.xml (Portuguese) 2019-03-19 21:51:15 +01:00
PhilippC
ecb44a2611 New translations strings.xml (Polish) 2019-03-19 21:51:08 +01:00
PhilippC
7898ea9ba7 New translations strings.xml (Japanese) 2019-03-19 21:50:50 +01:00
PhilippC
90a2029f3d New translations strings.xml (Italian) 2019-03-19 21:50:45 +01:00
PhilippC
1d9a9ea658 New translations strings.xml (Hungarian) 2019-03-19 21:50:36 +01:00
PhilippC
e88f80eda3 New translations strings.xml (Spanish) 2019-03-19 21:50:27 +01:00
Philipp Crocoll
025e2f415d improve logging output 2019-03-19 21:49:04 +01:00
Philipp Crocoll
e113ca79de add missing file 2019-03-19 21:23:50 +01:00
Philipp Crocoll
f988c44440 update changelog 2019-03-19 21:20:07 +01:00
Philipp Crocoll
37cda26e27 fix potential crashes in AutoFill service 2019-03-19 21:13:16 +01:00
Philipp Crocoll
65c2da9afa implement really hacky workaround for another crash on Samsung devices with Android 9 2019-03-19 20:58:37 +01:00
Philipp Crocoll
434b7b756b Merge branch 'master' of c:/ph/keepass2android 2019-03-18 05:51:54 +01:00
Philipp Crocoll
9dfcab6c1c 1.07-pre6 2019-03-18 05:50:56 +01:00
Philipp Crocoll
9f39f4e377 set NoHistory flag for SwitchImeActivity, improves switching back to KP2A 2019-03-18 05:44:01 +01:00
Philipp Crocoll
58da4284ac Merge branch 'master' of c:/ph/keepass2android
# Resolved Conflicts:
#	src/keepass2android/Properties/AndroidManifest_net.xml
#	src/keepass2android/Resources/values/strings.xml
2019-03-18 05:12:05 +01:00
Philipp Crocoll
55787ff6cf fix crash on Samsung devices with Android 9, fix problem with bringing up keyboard 2019-03-18 05:09:20 +01:00
Philipp Crocoll
3b93610e43 fix crash when sending debug log (closes https://github.com/PhilippC/keepass2android/issues/264) 2019-03-18 05:08:34 +01:00
Philipp Crocoll
40f3066ee0 avoid potential crashes when opening child databases (caused by network on main thread or URLs without username/password), fixes https://github.com/PhilippC/keepass2android/issues/728 2019-03-18 03:56:34 +01:00
PhilippC
2108aac41c New translations strings.xml (Russian) 2019-03-15 10:50:12 +01:00
PhilippC
68f8300395 New translations strings.xml (Russian) 2019-03-15 10:40:10 +01:00
PhilippC
325a61912e New translations strings.xml (Russian) 2019-03-15 10:30:10 +01:00
PhilippC
7363c88fce New translations strings.xml (Russian) 2019-03-15 10:20:09 +01:00
PhilippC
0b0f95c65c New translations strings.xml (Danish) 2019-03-14 18:20:18 +01:00
PhilippC
354675f1e5 New translations strings.xml (German) 2019-03-13 14:50:13 +01:00
PhilippC
7a769f283b New translations strings.xml (German) 2019-03-13 14:40:14 +01:00
PhilippC
3dc67d5978 New translations strings.xml (Portuguese, Brazilian) 2019-03-12 15:40:09 +01:00
PhilippC
d3a0d71857 New translations strings.xml (Portuguese, Brazilian) 2019-03-12 15:30:16 +01:00
PhilippC
72f7534a5f New translations strings.xml (Portuguese, Brazilian) 2019-03-12 15:20:13 +01:00
PhilippC
27a733cbed New translations strings.xml (Portuguese, Brazilian) 2019-03-12 15:10:13 +01:00
Philipp Crocoll
92a0ce98bb make nfc implementation compatible to Yubikey NEO 5 (closes https://github.com/PhilippC/keepass2android/issues/564) 2019-03-11 11:46:02 +01:00
Philipp Crocoll
84c9632508 using public suffix to determine canonical domains which fixes the aliexpress issue (fixes https://github.com/PhilippC/keepass2android/issues/711) 2019-03-11 10:56:55 +01:00
Philipp Crocoll
22c2b406db more attempts to get OneDrive for business working 2019-03-11 09:43:42 +01:00
PhilippC
bc374a1317 New translations strings.xml (Spanish) 2019-03-11 09:10:09 +01:00
Philipp Crocoll
0bf82a999a don't refuse to load databases with invalid times 2019-03-11 02:52:56 +01:00
PhilippC
453a8459ac New translations strings.xml (Turkish) 2019-03-10 01:20:10 +01:00
PhilippC
53f6ddad22 New translations strings.xml (Ukrainian) 2019-03-09 22:10:08 +01:00
PhilippC
14bd128931 New translations strings.xml (Greek) 2019-03-08 23:30:11 +01:00
PhilippC
b0b8daa03d New translations strings.xml (Greek) 2019-03-08 23:20:08 +01:00
PhilippC
940cd70f64 New translations strings.xml (Spanish) 2019-03-08 08:40:09 +01:00
PhilippC
d8cdef0622 New translations strings.xml (Spanish) 2019-03-08 08:30:12 +01:00
PhilippC
44a7cfe32e New translations strings.xml (Spanish) 2019-03-08 08:20:09 +01:00
PhilippC
8584352e21 New translations strings.xml (Turkish) 2019-03-07 12:50:10 +01:00
PhilippC
1c39d027e0 New translations strings.xml (Turkish) 2019-03-07 12:40:12 +01:00
PhilippC
ce82e2cdcf New translations strings.xml (Arabic) 2019-03-06 07:30:10 +01:00
PhilippC
a8492f75cd New translations strings.xml (Arabic) 2019-03-06 07:20:10 +01:00
PhilippC
03afb38aa3 New translations strings.xml (Portuguese) 2019-03-04 19:20:10 +01:00
PhilippC
acc2acce2c New translations strings.xml (Portuguese) 2019-03-04 18:50:08 +01:00
PhilippC
3a612864f8 New translations strings.xml (Portuguese) 2019-03-04 18:40:09 +01:00
PhilippC
7e1789a3f4 New translations strings.xml (Slovak) 2019-03-03 13:10:10 +01:00
PhilippC
69dea794e1 New translations strings.xml (Dutch) 2019-03-02 14:50:08 +01:00
PhilippC
4e024bd8b1 New translations strings.xml (Dutch) 2019-03-02 14:40:10 +01:00
PhilippC
6078e511aa New translations strings.xml (Dutch) 2019-03-02 14:30:09 +01:00
PhilippC
58574cd824 New translations strings.xml (Spanish) 2019-02-27 14:30:11 +01:00
PhilippC
635fa99cf2 New translations strings.xml (Spanish) 2019-02-27 14:00:12 +01:00
PhilippC
074d71cef7 New translations strings.xml (Spanish) 2019-02-27 09:20:12 +01:00
PhilippC
027075b1b2 New translations strings.xml (Czech) 2019-02-24 00:00:09 +01:00
PhilippC
898ad42f96 New translations strings.xml (Czech) 2019-02-23 23:50:10 +01:00
PhilippC
c87ffeff71 New translations strings.xml (Japanese) 2019-02-22 11:20:10 +01:00
PhilippC
40f0744adc New translations strings.xml (Japanese) 2019-02-22 11:10:09 +01:00
PhilippC
eba555f260 New translations strings.xml (Japanese) 2019-02-22 11:00:12 +01:00
PhilippC
e7db208a40 New translations strings.xml (Russian) 2019-02-20 20:40:11 +01:00
PhilippC
69399bb328 New translations strings.xml (Italian) 2019-02-18 20:20:14 +01:00
PhilippC
749e928d66 New translations strings.xml (Italian) 2019-02-18 20:10:09 +01:00
PhilippC
a3b8690609 New translations strings.xml (Polish) 2019-02-18 12:40:12 +01:00
PhilippC
340e6794ca New translations strings.xml (German) 2019-02-17 02:50:09 +01:00
PhilippC
7a23152cee New translations strings.xml (German) 2019-02-17 02:40:09 +01:00
PhilippC
d00f71884a New translations strings.xml (German) 2019-02-17 02:30:11 +01:00
PhilippC
587014159d New translations strings.xml (Chinese Simplified) 2019-02-16 15:20:11 +01:00
PhilippC
e2cb3691e4 New translations strings.xml (Chinese Simplified) 2019-02-16 15:10:09 +01:00
PhilippC
a40be3b658 New translations strings.xml (Chinese Simplified) 2019-02-16 13:50:08 +01:00
PhilippC
598d7c699a New translations strings.xml (Chinese Simplified) 2019-02-16 13:40:11 +01:00
PhilippC
23c9b9f2d9 New translations strings.xml (Norwegian Bokmal) 2019-02-15 08:50:09 +01:00
PhilippC
22aeff708a New translations strings.xml (Chinese Simplified) 2019-02-14 08:10:11 +01:00
PhilippC
e9b7b935ee New translations strings.xml (Chinese Simplified) 2019-02-14 08:00:15 +01:00
PhilippC
eb0d9ec482 New translations strings.xml (Chinese Simplified) 2019-02-14 07:50:11 +01:00
PhilippC
cfd0d72100 New translations strings.xml (Polish) 2019-02-11 20:00:15 +01:00
PhilippC
f615dc265a New translations strings.xml (Polish) 2019-02-11 19:50:12 +01:00
PhilippC
53c4971c4e New translations strings.xml (Polish) 2019-02-11 19:40:12 +01:00
PhilippC
3a98fa9f53 New translations strings.xml (Japanese) 2019-02-11 08:20:11 +01:00
PhilippC
6ed5386c12 New translations strings.xml (German) 2019-02-11 04:10:09 +01:00
PhilippC
a998a7f92b New translations strings.xml (German) 2019-02-11 04:00:09 +01:00
PhilippC
3218989b13 New translations strings.xml (German) 2019-02-11 03:50:09 +01:00
PhilippC
3aff954063 New translations strings.xml (Catalan) 2019-02-09 16:20:09 +01:00
PhilippC
11e824c133 New translations strings.xml (Catalan) 2019-02-09 16:10:09 +01:00
PhilippC
a26662a813 New translations strings.xml (Catalan) 2019-02-09 10:10:10 +01:00
PhilippC
007838197b New translations strings.xml (Catalan) 2019-02-09 10:00:09 +01:00
PhilippC
0ad82d5b91 New translations strings.xml (Catalan) 2019-02-09 09:10:08 +01:00
PhilippC
52e47a62d2 New translations strings.xml (Korean) 2019-02-08 17:40:11 +01:00
PhilippC
cbaaf3ee54 New translations strings.xml (Chinese Traditional) 2019-02-08 16:10:12 +01:00
PhilippC
26f26ee35d New translations strings.xml (Chinese Traditional) 2019-02-08 16:00:13 +01:00
PhilippC
0102ac77e3 New translations strings.xml (Chinese Traditional) 2019-02-08 15:50:10 +01:00
PhilippC
d24101bee2 New translations strings.xml (Chinese Traditional) 2019-02-08 15:40:11 +01:00
PhilippC
36cced5ce7 New translations strings.xml (Chinese Traditional) 2019-02-08 15:30:13 +01:00
PhilippC
87eb537ebe New translations strings.xml (French) 2019-02-07 00:40:11 +01:00
PhilippC
86fdc17d2a New translations strings.xml (Slovak) 2019-02-06 21:21:11 +01:00
PhilippC
bd8763c62f New translations strings.xml (Portuguese, Brazilian) 2019-02-06 21:20:54 +01:00
Philipp Crocoll
bc917d41ad 1.07-pre5 2019-02-06 21:13:59 +01:00
Philipp Crocoll
68b60b427a fix missing native keytransform, closes #630 2019-02-06 21:13:46 +01:00
PhilippC
c9e64c53ec New translations strings.xml (Slovak) 2019-02-06 16:10:18 +01:00
PhilippC
6ba6c6bac7 New translations strings.xml (Slovak) 2019-02-06 16:00:26 +01:00
PhilippC
f2967e1d8f New translations strings.xml (Slovak) 2019-02-06 15:50:13 +01:00
PhilippC
60783ca88e New translations strings.xml (Slovak) 2019-02-06 15:40:12 +01:00
PhilippC
8d7c1371df New translations strings.xml (Vietnamese) 2019-02-06 15:33:16 +01:00
PhilippC
090bfe9091 New translations strings.xml (Basque) 2019-02-06 15:33:10 +01:00
PhilippC
3ad2ba9f33 New translations strings.xml (Bulgarian) 2019-02-06 15:33:05 +01:00
PhilippC
1036def599 New translations strings.xml (Catalan) 2019-02-06 15:33:00 +01:00
PhilippC
2acad69940 New translations strings.xml (Chinese Simplified) 2019-02-06 15:32:56 +01:00
PhilippC
1f18011a5b New translations strings.xml (Chinese Traditional) 2019-02-06 15:32:51 +01:00
PhilippC
3da63b378c New translations strings.xml (Croatian) 2019-02-06 15:32:45 +01:00
PhilippC
0852aa7429 New translations strings.xml (Czech) 2019-02-06 15:32:39 +01:00
PhilippC
8a863ca636 New translations strings.xml (Danish) 2019-02-06 15:32:33 +01:00
PhilippC
83db5c205d New translations strings.xml (Finnish) 2019-02-06 15:32:26 +01:00
PhilippC
760e73959c New translations strings.xml (French) 2019-02-06 15:32:22 +01:00
PhilippC
e516e06a53 New translations strings.xml (Galician) 2019-02-06 15:32:16 +01:00
PhilippC
a954461be3 New translations strings.xml (German) 2019-02-06 15:32:12 +01:00
PhilippC
5998369af6 New translations strings.xml (Greek) 2019-02-06 15:32:06 +01:00
PhilippC
f41a2604c4 New translations strings.xml (Azerbaijani) 2019-02-06 15:31:57 +01:00
PhilippC
6fc578d286 New translations strings.xml (Hebrew) 2019-02-06 15:31:51 +01:00
PhilippC
f2604a5fec New translations strings.xml (Indonesian) 2019-02-06 15:31:47 +01:00
PhilippC
642026156a New translations strings.xml (Italian) 2019-02-06 15:31:41 +01:00
PhilippC
708c511a98 New translations strings.xml (Japanese) 2019-02-06 15:31:35 +01:00
PhilippC
2c75b5886f New translations strings.xml (Korean) 2019-02-06 15:31:30 +01:00
PhilippC
0ef7f5a955 New translations strings.xml (Russian) 2019-02-06 15:31:20 +01:00
PhilippC
28856c01cd New translations strings.xml (Serbian (Cyrillic)) 2019-02-06 15:31:09 +01:00
PhilippC
a47bd03e94 New translations strings.xml (Slovak) 2019-02-06 15:31:01 +01:00
PhilippC
c5551ddeb5 New translations strings.xml (Slovenian) 2019-02-06 15:30:57 +01:00
PhilippC
020f274ef3 New translations strings.xml (Spanish) 2019-02-06 15:30:51 +01:00
PhilippC
e2f8f04ace New translations strings.xml (Swedish) 2019-02-06 15:30:45 +01:00
PhilippC
6d61d885c1 New translations strings.xml (Turkish) 2019-02-06 15:30:39 +01:00
PhilippC
e98cd16032 New translations strings.xml (Ukrainian) 2019-02-06 15:30:33 +01:00
PhilippC
4ec8bdda2f New translations strings.xml (Hungarian) 2019-02-06 15:30:29 +01:00
PhilippC
16df1624f8 New translations strings.xml (Arabic) 2019-02-06 15:30:20 +01:00
PhilippC
cb978e012b New translations strings.xml (Portuguese) 2019-02-06 06:20:56 +01:00
PhilippC
b7ea02696b New translations strings.xml (Polish) 2019-02-06 06:20:51 +01:00
PhilippC
49cb8874ca New translations strings.xml (Persian) 2019-02-06 06:20:46 +01:00
PhilippC
1384256d87 New translations strings.xml (Norwegian Nynorsk) 2019-02-06 06:20:41 +01:00
PhilippC
705b2fcd9a New translations strings.xml (Norwegian Bokmal) 2019-02-06 06:20:38 +01:00
PhilippC
906ca77973 New translations strings.xml (Romanian) 2019-02-06 06:20:34 +01:00
PhilippC
7dc5c734d0 New translations strings.xml (Dutch) 2019-02-06 06:20:29 +01:00
Philipp Crocoll
a3c1e311f7 1.07-pre4 2019-02-06 06:15:33 +01:00
Philipp Crocoll
4d246a250d remove AdalBindings project 2019-02-06 06:15:20 +01:00
Philipp Crocoll
8d2c41f558 fix duplicate string resource id 2019-02-06 06:14:49 +01:00
PhilippC
3b06c4c14a New translations strings.xml (Chinese Traditional) 2019-02-05 20:03:10 +01:00
PhilippC
f98dcb813d New translations strings.xml (Finnish) 2019-02-05 20:02:56 +01:00
PhilippC
17cf31e8cf New translations strings.xml (Portuguese, Brazilian) 2019-02-05 20:02:13 +01:00
PhilippC
6771c378bf New translations strings.xml (Russian) 2019-02-05 20:02:09 +01:00
Philipp Crocoll
013aa4d071 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2019-02-05 19:55:58 +01:00
PhilippC
b887e16628 Merge pull request #515 from PhilippC/l10n_master
New Crowdin translations
2019-02-05 19:55:45 +01:00
PhilippC
7774ed65bd Merge branch 'master' into l10n_master 2019-02-05 19:55:11 +01:00
PhilippC
c85f996aa3 New translations strings.xml (Portuguese) 2019-02-05 19:51:56 +01:00
Philipp Crocoll
64d9cc00d1 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2019-02-05 19:46:56 +01:00
Philipp Crocoll
a0efbecee4 Forward to Search results directly when multiple databases open, closes https://github.com/PhilippC/keepass2android/issues/642 2019-02-05 12:15:22 +01:00
Philipp Crocoll
cceb4c6677 increase timeout (https://github.com/PhilippC/keepass2android/issues/339). still todo: test how KP2A behaves on write errors. 2019-02-05 12:14:52 +01:00
Philipp Crocoll
66e448a648 avoid using a deprecated method, might help with https://github.com/PhilippC/keepass2android/issues/653 2019-02-05 11:08:38 +01:00
Philipp Crocoll
eb134fd41a NfcOtpActivity is back - this time with app link enabled (allows users to enter https://keepass2android.crocoll.net/neo/ as NDEF payload and should work on all recent Android devices with NFC). Closes #603 2019-02-05 10:36:08 +01:00
Philipp Crocoll
857d6f9008 reset cancellation signal when cancelled. might fix https://github.com/PhilippC/keepass2android/issues/560 (cannot reproduce, so user must test) 2019-02-05 10:04:10 +01:00
PhilippC
32396c4534 Merge pull request #654 from Small-Ku/master
Update crowdin.yml for better Chinese localiztion
2019-02-05 06:38:57 +01:00
Philipp Crocoll
2df46b6647 improve language in some strings 2019-02-05 06:29:01 +01:00
Philipp Crocoll
9f6ad37547 Revert "failing attempt to integrate ADAL authentication (for OneDrive for business)"
This reverts commit 6b69ad20ad.
2019-02-05 06:28:40 +01:00
PhilippC
65955843e5 New translations strings.xml (Dutch) 2019-01-26 15:40:08 +01:00
PhilippC
9e9b5fb9dd New translations strings.xml (Polish) 2019-01-19 14:10:09 +01:00
PhilippC
f96fc67bc2 New translations strings.xml (Russian) 2019-01-15 13:50:14 +01:00
PhilippC
07ebd0b4ca New translations strings.xml (Russian) 2019-01-15 13:40:10 +01:00
PhilippC
64e955c512 New translations strings.xml (Japanese) 2019-01-14 13:50:11 +01:00
PhilippC
161753b195 New translations strings.xml (Japanese) 2019-01-14 13:40:15 +01:00
PhilippC
f92adb847a New translations strings.xml (Japanese) 2019-01-14 13:30:13 +01:00
PhilippC
98f780c277 New translations strings.xml (Portuguese, Brazilian) 2019-01-14 03:20:08 +01:00
PhilippC
3c512e74db New translations strings.xml (Portuguese, Brazilian) 2019-01-14 03:10:08 +01:00
PhilippC
9b752dd28f New translations strings.xml (Portuguese, Brazilian) 2019-01-14 03:00:11 +01:00
PhilippC
3cf2719c29 New translations strings.xml (Croatian) 2019-01-07 07:30:10 +01:00
PhilippC
be420c0394 New translations strings.xml (Croatian) 2019-01-07 07:20:08 +01:00
PhilippC
1b1d995b9d New translations strings.xml (Russian) 2019-01-03 16:50:10 +01:00
PhilippC
6410f41fa2 New translations strings.xml (Italian) 2019-01-02 15:50:09 +01:00
PhilippC
f90a45b1e6 New translations strings.xml (Italian) 2019-01-02 15:40:08 +01:00
PhilippC
9ca5569122 New translations strings.xml (Slovak) 2019-01-02 12:20:08 +01:00
Philipp Crocoll
a6b4a35973 added OneDriveStorage2 based on Graph SDK 2018-12-30 07:53:29 +01:00
PhilippC
06cb6bac3e New translations strings.xml (Turkish) 2018-12-28 10:50:11 +01:00
PhilippC
5241aeea9f New translations strings.xml (Turkish) 2018-12-28 10:40:09 +01:00
Philipp Crocoll
6b69ad20ad failing attempt to integrate ADAL authentication (for OneDrive for business) 2018-12-27 21:46:11 +01:00
PhilippC
a79d2ec323 New translations strings.xml (Catalan) 2018-12-27 21:40:08 +01:00
PhilippC
209a0fe2da New translations strings.xml (Catalan) 2018-12-27 21:30:10 +01:00
Small_Ku
277f439f70 Update crowdin.yml
for Chinese translation
2018-12-27 00:05:15 +08:00
PhilippC
d9f29fdcaa New translations strings.xml (Danish) 2018-12-26 06:50:08 +01:00
PhilippC
a9141d3fe2 New translations strings.xml (Danish) 2018-12-26 06:40:08 +01:00
PhilippC
4ce55e88fa New translations strings.xml (Danish) 2018-12-26 06:30:08 +01:00
PhilippC
c930d388dc New translations strings.xml (Finnish) 2018-12-25 10:30:25 +01:00
PhilippC
12c7911cf4 New translations strings.xml (Finnish) 2018-12-25 10:20:18 +01:00
PhilippC
06377ff497 New translations strings.xml (Finnish) 2018-12-25 10:10:08 +01:00
PhilippC
7a1938e515 New translations strings.xml (Finnish) 2018-12-25 10:00:09 +01:00
PhilippC
445166d220 New translations strings.xml (Danish) 2018-12-25 08:10:08 +01:00
PhilippC
3963501d0c New translations strings.xml (Danish) 2018-12-25 08:00:09 +01:00
PhilippC
acb51d7859 New translations strings.xml (Spanish) 2018-12-23 19:50:09 +01:00
PhilippC
4dbfb76ced Merge pull request #628 from Skycoder42/master
Correctly extract protected fields from intent (Fixes #627)
2018-12-23 07:27:32 +01:00
Philipp Crocoll
4188464652 change "application" to "app" in english strings 2018-12-23 07:09:17 +01:00
PhilippC
fb552a8d62 New translations strings.xml (Chinese Simplified) 2018-12-23 02:40:09 +01:00
PhilippC
c998e4e34f New translations strings.xml (Chinese Simplified) 2018-12-23 02:30:09 +01:00
PhilippC
ab46015a5a New translations strings.xml (Chinese Simplified) 2018-12-23 02:20:09 +01:00
PhilippC
dd10740bf2 New translations strings.xml (German) 2018-12-22 13:40:08 +01:00
PhilippC
44f26685e4 New translations strings.xml (German) 2018-12-22 13:30:08 +01:00
PhilippC
3caa56ae8c New translations strings.xml (French) 2018-12-21 16:30:09 +01:00
PhilippC
1ca4fbb078 New translations strings.xml (Czech) 2018-12-18 23:40:10 +01:00
PhilippC
bdf5270fa0 New translations strings.xml (Czech) 2018-12-18 19:30:09 +01:00
PhilippC
e3e865b108 New translations strings.xml (Czech) 2018-12-18 19:20:09 +01:00
PhilippC
33f3736798 New translations strings.xml (Czech) 2018-12-18 19:10:11 +01:00
PhilippC
a86fbcee44 New translations strings.xml (Czech) 2018-12-18 19:00:13 +01:00
PhilippC
cdbf8a2811 New translations strings.xml (Czech) 2018-12-18 18:50:09 +01:00
PhilippC
da4fae4e04 New translations strings.xml (Czech) 2018-12-18 18:40:10 +01:00
PhilippC
ddeefc4ab6 New translations strings.xml (Chinese Traditional) 2018-12-17 19:20:11 +01:00
PhilippC
33702064a5 New translations strings.xml (French) 2018-12-17 12:40:10 +01:00
PhilippC
b72995c8bf New translations strings.xml (Chinese Simplified) 2018-12-17 12:20:16 +01:00
PhilippC
868eb1c4fb New translations strings.xml (Catalan) 2018-12-17 12:20:10 +01:00
PhilippC
d93140efc6 New translations strings.xml (Chinese Traditional) 2018-12-17 12:12:20 +01:00
PhilippC
0f59d46ede New translations strings.xml (Croatian) 2018-12-17 12:12:14 +01:00
PhilippC
812b5f22f9 New translations strings.xml (Czech) 2018-12-17 12:12:10 +01:00
PhilippC
d1b5feae0d New translations strings.xml (Danish) 2018-12-17 12:12:05 +01:00
PhilippC
0861fa9e03 New translations strings.xml (Dutch) 2018-12-17 12:12:00 +01:00
PhilippC
c3fe9f513d New translations strings.xml (Finnish) 2018-12-17 12:11:56 +01:00
PhilippC
b513669f4d New translations strings.xml (French) 2018-12-17 12:11:49 +01:00
PhilippC
1ad74fdacc New translations strings.xml (Galician) 2018-12-17 12:11:44 +01:00
PhilippC
9a24ede989 New translations strings.xml (German) 2018-12-17 12:11:40 +01:00
PhilippC
7ea8dfa8ce New translations strings.xml (Greek) 2018-12-17 12:11:35 +01:00
PhilippC
670068eeba New translations strings.xml (Hungarian) 2018-12-17 12:11:28 +01:00
PhilippC
70310f1970 New translations strings.xml (Indonesian) 2018-12-17 12:11:19 +01:00
PhilippC
4463c148a5 New translations strings.xml (Japanese) 2018-12-17 12:11:15 +01:00
PhilippC
c982b45134 New translations strings.xml (Korean) 2018-12-17 12:11:10 +01:00
PhilippC
d209a2c7f8 New translations strings.xml (Norwegian Bokmal) 2018-12-17 12:11:05 +01:00
PhilippC
75c73193a2 New translations strings.xml (Portuguese, Brazilian) 2018-12-17 12:10:59 +01:00
PhilippC
fc99f6774d New translations strings.xml (Romanian) 2018-12-17 12:10:54 +01:00
PhilippC
d40fab86c9 New translations strings.xml (Slovak) 2018-12-17 12:10:45 +01:00
PhilippC
5c0520e093 New translations strings.xml (Slovenian) 2018-12-17 12:10:41 +01:00
PhilippC
1bb9ead202 New translations strings.xml (Spanish) 2018-12-17 12:10:36 +01:00
PhilippC
3afd8915f0 New translations strings.xml (Swedish) 2018-12-17 12:10:32 +01:00
PhilippC
ba3f2d2823 New translations strings.xml (Turkish) 2018-12-17 12:10:28 +01:00
PhilippC
24989d80ac New translations strings.xml (Ukrainian) 2018-12-17 12:10:22 +01:00
PhilippC
d2c16158cc New translations strings.xml (Vietnamese) 2018-12-17 12:10:17 +01:00
PhilippC
8514fd6266 New translations strings.xml (Italian) 2018-12-17 12:10:13 +01:00
Philipp Crocoll
30d1534c01 show save errors as dialogs, closes #339 2018-12-17 12:09:31 +01:00
PhilippC
4f0800d4fc New translations strings.xml (Portuguese) 2018-12-17 12:00:49 +01:00
PhilippC
41fa396318 New translations strings.xml (Polish) 2018-12-17 12:00:45 +01:00
PhilippC
d94af84002 New translations strings.xml (Persian) 2018-12-17 12:00:41 +01:00
PhilippC
63b92cc35a New translations strings.xml (Russian) 2018-12-17 12:00:31 +01:00
PhilippC
3238d9fbc5 New translations strings.xml (Arabic) 2018-12-17 12:00:26 +01:00
Philipp Crocoll
780d4c95fe improve message when file is readonly, closes #521 2018-12-17 11:47:24 +01:00
PhilippC
c3b27c75bf New translations strings.xml (Chinese Traditional) 2018-12-17 11:40:08 +01:00
PhilippC
23c7031672 New translations strings.xml (Chinese Traditional) 2018-12-17 11:30:11 +01:00
PhilippC
9e98d09a93 New translations strings.xml (Chinese Traditional) 2018-12-17 11:20:11 +01:00
Philipp Crocoll
06e64f7347 more autofill logging 2018-12-17 11:12:07 +01:00
Philipp Crocoll
92594db78d automatically fill in OTPs copied from Yubiclip. closes #603 and closes #564 2018-12-17 11:11:56 +01:00
PhilippC
c574f2d6bd New translations strings.xml (Chinese Traditional) 2018-12-17 11:10:11 +01:00
PhilippC
ee156cbfd6 New translations strings.xml (Chinese Traditional) 2018-12-17 10:50:09 +01:00
PhilippC
73d12daf04 New translations strings.xml (Chinese Traditional) 2018-12-17 10:40:09 +01:00
Philipp Crocoll
e4179a934b fix wrong time display when editing expiration date, fixes #634 2018-12-17 10:03:43 +01:00
Philipp Crocoll
afd309d9a8 work on reducing popups for autofill/allow to disable autofill for query. not yet fully functional. refers to #455. 2018-12-17 10:03:02 +01:00
PhilippC
1a24b00c5e New translations strings.xml (Italian) 2018-12-17 09:40:08 +01:00
PhilippC
445e4d8b31 New translations strings.xml (Italian) 2018-12-17 09:30:34 +01:00
PhilippC
224ca98d0e New translations strings.xml (Swedish) 2018-12-16 23:50:10 +01:00
PhilippC
13419c9fb7 New translations strings.xml (Croatian) 2018-12-16 22:10:12 +01:00
PhilippC
00646bc84b New translations strings.xml (Croatian) 2018-12-16 22:00:13 +01:00
PhilippC
cb4b686335 New translations strings.xml (Dutch) 2018-12-16 14:10:09 +01:00
PhilippC
5e900b62c8 New translations strings.xml (Ukrainian) 2018-12-12 09:00:09 +01:00
PhilippC
74c94d37e5 New translations strings.xml (French) 2018-12-11 21:40:08 +01:00
PhilippC
588814d1a6 New translations strings.xml (Portuguese) 2018-12-11 21:30:12 +01:00
PhilippC
572b858f81 New translations strings.xml (Portuguese) 2018-12-11 21:20:10 +01:00
PhilippC
1a9fc48490 New translations strings.xml (Japanese) 2018-12-11 05:30:09 +01:00
PhilippC
2dd131e6c3 New translations strings.xml (Portuguese, Brazilian) 2018-12-11 00:10:08 +01:00
Philipp Crocoll
d1ad2a681f Autofill: fill emailAddress fields with username 2018-12-10 11:24:40 +01:00
Philipp Crocoll
e2e7666c4f fix incorrect webDomain checking, fixes https://github.com/PhilippC/keepass2android/issues/592 2018-12-10 11:23:44 +01:00
Philipp Crocoll
665639fdca fix switching keyboards not working in Android 9: fixes https://github.com/PhilippC/keepass2android/issues/530 2018-12-10 09:52:23 +01:00
Philipp Crocoll
8bb930c1fc make kdb library "embedded jar" instead of "inputjar" to fix issue with native key transform not working. -> 1.07-pre3 2018-12-10 09:50:26 +01:00
PhilippC
b3b9d8d105 New translations strings.xml (Catalan) 2018-12-09 17:30:10 +01:00
PhilippC
82c409252b New translations strings.xml (Polish) 2018-12-09 15:30:18 +01:00
PhilippC
14c63a03c4 New translations strings.xml (Chinese Simplified) 2018-12-09 15:30:14 +01:00
PhilippC
0c7ad8b16c New translations strings.xml (Catalan) 2018-12-09 15:30:10 +01:00
PhilippC
1bf2d8219a New translations strings.xml (Chinese Traditional) 2018-12-09 14:42:11 +01:00
PhilippC
a72264ef36 New translations strings.xml (Croatian) 2018-12-09 14:42:06 +01:00
PhilippC
1acc399568 New translations strings.xml (Czech) 2018-12-09 14:42:00 +01:00
PhilippC
160960437c New translations strings.xml (Danish) 2018-12-09 14:41:56 +01:00
PhilippC
61992adcca New translations strings.xml (Dutch) 2018-12-09 14:41:52 +01:00
PhilippC
10e0ae8200 New translations strings.xml (Finnish) 2018-12-09 14:41:47 +01:00
PhilippC
eb58b8576e New translations strings.xml (French) 2018-12-09 14:41:43 +01:00
PhilippC
9b4d2d6ed7 New translations strings.xml (Galician) 2018-12-09 14:41:38 +01:00
PhilippC
6417e9dec5 New translations strings.xml (German) 2018-12-09 14:41:33 +01:00
PhilippC
f5ac217f13 New translations strings.xml (Greek) 2018-12-09 14:41:29 +01:00
PhilippC
a3d3b14dd1 New translations strings.xml (Bulgarian) 2018-12-09 14:41:21 +01:00
PhilippC
8fccce8684 New translations strings.xml (Hungarian) 2018-12-09 14:41:17 +01:00
PhilippC
4a847cd74a New translations strings.xml (Italian) 2018-12-09 14:41:11 +01:00
PhilippC
f4c1db39ad New translations strings.xml (Japanese) 2018-12-09 14:41:07 +01:00
PhilippC
d9ff177427 New translations strings.xml (Korean) 2018-12-09 14:41:02 +01:00
PhilippC
95e3566c5f New translations strings.xml (Norwegian Bokmal) 2018-12-09 14:40:57 +01:00
PhilippC
76e02ff514 New translations strings.xml (Romanian) 2018-12-09 14:40:52 +01:00
PhilippC
8aca9a2d82 New translations strings.xml (Serbian (Cyrillic)) 2018-12-09 14:40:47 +01:00
PhilippC
3abab2072a New translations strings.xml (Slovak) 2018-12-09 14:40:42 +01:00
PhilippC
ca9e479dc5 New translations strings.xml (Slovenian) 2018-12-09 14:40:38 +01:00
PhilippC
4d230a7b3e New translations strings.xml (Spanish) 2018-12-09 14:40:34 +01:00
PhilippC
974cc59e6c New translations strings.xml (Swedish) 2018-12-09 14:40:31 +01:00
PhilippC
9f09b144f0 New translations strings.xml (Turkish) 2018-12-09 14:40:26 +01:00
PhilippC
9d4dad5fee New translations strings.xml (Ukrainian) 2018-12-09 14:40:22 +01:00
PhilippC
46ffa93d93 New translations strings.xml (Vietnamese) 2018-12-09 14:40:19 +01:00
PhilippC
8b709bc070 New translations strings.xml (Indonesian) 2018-12-09 14:40:14 +01:00
PhilippC
c1284c760a New translations strings.xml (Basque) 2018-12-09 14:40:09 +01:00
PhilippC
6529a94d3a New translations strings.xml (Portuguese) 2018-12-09 08:30:39 +01:00
PhilippC
f5e91a0524 New translations strings.xml (Polish) 2018-12-09 08:30:35 +01:00
PhilippC
f63bd3016b New translations strings.xml (Norwegian Nynorsk) 2018-12-09 08:30:28 +01:00
PhilippC
09cd590796 New translations strings.xml (Russian) 2018-12-09 08:30:24 +01:00
PhilippC
da728c4039 New translations strings.xml (Arabic) 2018-12-09 08:30:20 +01:00
Philipp Crocoll
14b7b8cec1 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-12-09 08:23:18 +01:00
Philipp Crocoll
3695c04933 avoid endless loops trying to open databases when loading fails. changelog 1.07-pre2 for release. 2018-12-09 08:22:45 +01:00
Philipp Crocoll
f0f3bb6ede more logging regarding key transformation 2018-12-09 08:21:25 +01:00
Philipp Crocoll
7824326c5b fix typo in string 2018-12-09 08:21:03 +01:00
Philipp Crocoll
a65d263ae2 manifest for 1.07-pre2 2018-12-09 08:20:50 +01:00
PhilippC
f3e628be6b New translations strings.xml (Polish) 2018-12-09 02:10:10 +01:00
PhilippC
62e8dc7767 New translations strings.xml (Polish) 2018-12-09 02:00:09 +01:00
PhilippC
8e8cfa704a New translations strings.xml (Polish) 2018-12-09 01:50:08 +01:00
PhilippC
8b2eff0194 New translations strings.xml (Polish) 2018-12-09 01:40:08 +01:00
PhilippC
d4d063b97a New translations strings.xml (Polish) 2018-12-09 01:30:08 +01:00
PhilippC
d5ec33e1bd New translations strings.xml (Polish) 2018-12-09 01:20:09 +01:00
PhilippC
0726f22ec7 New translations strings.xml (Polish) 2018-12-09 01:00:12 +01:00
PhilippC
531ab93388 New translations strings.xml (Polish) 2018-12-09 00:50:08 +01:00
Philipp Crocoll
a7ad00d402 fix incorrect expiration time in EntryEditActivity, fixes #634 2018-12-08 17:44:02 +01:00
PhilippC
1f18848b4e New translations strings.xml (French) 2018-12-08 17:30:08 +01:00
PhilippC
38179d9ce3 New translations strings.xml (Chinese Simplified) 2018-12-07 08:10:10 +01:00
PhilippC
b86c493cf8 New translations strings.xml (Slovak) 2018-12-04 22:20:13 +01:00
PhilippC
0cc2df85da New translations strings.xml (Catalan) 2018-12-03 21:30:10 +01:00
Skycoder42
3157bac5f6 Add missing import 2018-12-03 18:40:01 +01:00
Skycoder42
5cb1709f5d Correctly extract protected fields from intent
Fixes #627
2018-12-03 18:37:36 +01:00
PhilippC
e6834b13a5 New translations strings.xml (Azerbaijani) 2018-12-03 11:52:59 +01:00
PhilippC
8a17daa002 New translations strings.xml (Chinese Traditional) 2018-12-03 11:52:08 +01:00
PhilippC
1b09189195 New translations strings.xml (Portuguese, Brazilian) 2018-12-03 11:50:50 +01:00
Philipp Crocoll
7f21fa2c40 added ConfigChanges flags to all activities which could potentially show the ykDroid dialog to reduce the chance of activity recreation (this is considered a workaround, waiting for the solution at https://github.com/pp3345/ykDroid/issues/8) 2018-12-03 11:37:08 +01:00
PhilippC
e0e4fc85f7 New translations strings.xml (Vietnamese) 2018-12-01 21:20:08 +01:00
PhilippC
b3e57db9f8 New translations strings.xml (Portuguese) 2018-12-01 00:40:08 +01:00
PhilippC
f8d93a5de7 New translations strings.xml (Portuguese) 2018-12-01 00:30:08 +01:00
PhilippC
c5423ac650 New translations strings.xml (German) 2018-11-29 09:20:13 +01:00
PhilippC
6e93d17d14 New translations strings.xml (German) 2018-11-29 09:10:15 +01:00
PhilippC
127bc1be5c New translations strings.xml (Chinese Simplified) 2018-11-28 03:20:14 +01:00
PhilippC
8136b09992 New translations strings.xml (Ukrainian) 2018-11-27 14:20:09 +01:00
PhilippC
2ffac3268e New translations strings.xml (Ukrainian) 2018-11-27 14:00:12 +01:00
PhilippC
c7056e9d40 New translations strings.xml (Ukrainian) 2018-11-27 13:50:10 +01:00
PhilippC
3fb8b4e7ff New translations strings.xml (Russian) 2018-11-26 21:50:09 +01:00
PhilippC
c728a7802d New translations strings.xml (Russian) 2018-11-26 21:40:09 +01:00
PhilippC
e7d3049456 New translations strings.xml (Russian) 2018-11-26 21:30:09 +01:00
PhilippC
316675c77e New translations strings.xml (Russian) 2018-11-26 21:20:09 +01:00
PhilippC
c836d3de71 New translations strings.xml (Russian) 2018-11-26 21:00:14 +01:00
PhilippC
230429135a New translations strings.xml (Russian) 2018-11-26 20:40:08 +01:00
PhilippC
0be8092382 New translations strings.xml (Russian) 2018-11-26 20:30:09 +01:00
PhilippC
eb2019e568 New translations strings.xml (Russian) 2018-11-26 20:20:12 +01:00
PhilippC
bffbb17271 New translations strings.xml (Spanish) 2018-11-26 09:30:11 +01:00
PhilippC
16b997096d New translations strings.xml (Spanish) 2018-11-26 09:20:10 +01:00
PhilippC
3b23f2a4ed New translations strings.xml (Hungarian) 2018-11-25 03:40:09 +01:00
PhilippC
87f86fd2e8 New translations strings.xml (Slovak) 2018-11-23 20:10:07 +01:00
PhilippC
396509579a New translations strings.xml (Slovak) 2018-11-23 20:00:09 +01:00
PhilippC
91175f19c4 New translations strings.xml (Catalan) 2018-11-23 17:50:09 +01:00
PhilippC
7c22ca0f91 New translations strings.xml (Catalan) 2018-11-23 17:40:18 +01:00
PhilippC
5eb416d8d9 New translations strings.xml (Turkish) 2018-11-22 20:32:03 +01:00
PhilippC
12e374bd2f New translations strings.xml (Turkish) 2018-11-22 20:20:15 +01:00
PhilippC
9b50f0e77c New translations strings.xml (German) 2018-11-21 23:00:10 +01:00
PhilippC
6aa89287b1 New translations strings.xml (German) 2018-11-21 22:50:14 +01:00
PhilippC
4b9ebdc87c New translations strings.xml (French) 2018-11-21 22:20:11 +01:00
PhilippC
336b45667e New translations strings.xml (Russian) 2018-11-21 12:50:09 +01:00
PhilippC
3c33a1126b New translations strings.xml (Russian) 2018-11-21 12:40:10 +01:00
Philipp Crocoll
836cdfb16c move CurrentlyWaitingKey to App instead of activity to survive activity recreation. Avoid activity recreation when plugging in Yubikey. Fixes #609. 2018-11-21 03:01:43 +01:00
Philipp Crocoll
8512bae997 make sure we always save database as KDBX4 when using ChallengeXCKey (for compatibility with KeepassXC), closes #596 2018-11-20 06:08:30 +01:00
PhilippC
6fbe8c5dee New translations strings.xml (German) 2018-11-20 05:00:11 +01:00
Philipp Crocoll
2132ea416b notify about unconfigured child databases. finishes implementation of child databases, thus closes #174 2018-11-20 04:54:45 +01:00
PhilippC
24081b9223 New translations strings.xml (Chinese Simplified) 2018-11-19 20:11:57 +01:00
PhilippC
220cc98559 New translations strings.xml (Portuguese, Brazilian) 2018-11-19 20:10:49 +01:00
Philipp Crocoll
ef8b9b0685 allow to open AutoOpenEntries manually if they are not "Enabled" (but "Visible"). Don't suggest to configure fingerprint unlock for child databases. 2018-11-19 20:03:53 +01:00
PhilippC
e8dd47369c New translations strings.xml (Portuguese) 2018-11-19 19:20:09 +01:00
PhilippC
537eaddecd New translations strings.xml (Portuguese) 2018-11-19 19:10:09 +01:00
Philipp Crocoll
183c171da6 first version of KeeAutoExec functionality in Keepass2Android 2018-11-19 19:06:12 +01:00
Philipp Crocoll
58c6114840 fix potentially incorrect display of storage type in EntryEditActivity 2018-11-18 13:33:19 +01:00
Philipp Crocoll
df5162ce56 implemented first version of AutoOpen entry editing 2018-11-18 03:56:49 +01:00
PhilippC
ae61fe892d New translations strings.xml (Persian) 2018-11-15 20:50:08 +01:00
PhilippC
a78de3b4b9 New translations strings.xml (Persian) 2018-11-15 20:40:10 +01:00
PhilippC
f26a864e83 New translations strings.xml (Persian) 2018-11-15 20:30:14 +01:00
PhilippC
0e0b03e6f2 New translations strings.xml (Persian) 2018-11-15 20:20:11 +01:00
Philipp Crocoll
e5595f13eb intermediate commit, starting to implement edit GUI for AutoOpen entries (does not compile) 2018-11-15 19:14:10 +01:00
PhilippC
1b12c16685 New translations strings.xml (Turkish) 2018-11-14 08:30:11 +01:00
PhilippC
048055daac New translations strings.xml (Turkish) 2018-11-14 08:10:11 +01:00
Philipp Crocoll
f2590f1fed Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-11-13 22:00:06 +01:00
Philipp Crocoll
2eb7b22100 start implementing the GUI for editing AutoOpen entries 2018-11-13 21:57:43 +01:00
PhilippC
f169750d1a New translations strings.xml (French) 2018-11-13 20:50:12 +01:00
PhilippC
fbb361fa7a New translations strings.xml (Swedish) 2018-11-13 18:10:13 +01:00
PhilippC
902faca13c New translations strings.xml (Italian) 2018-11-13 17:20:16 +01:00
PhilippC
7e476a5785 New translations strings.xml (Italian) 2018-11-13 17:10:18 +01:00
PhilippC
c78c5aad02 New translations strings.xml (Italian) 2018-11-13 17:00:22 +01:00
PhilippC
42c49645da New translations strings.xml (Catalan) 2018-11-13 17:00:18 +01:00
Philipp Crocoll
9427fb9ecc merge KeeAutoExec extension from https://sourceforge.net/p/keepass/discussion/329220/thread/509d35a111/#f70b 2018-11-12 09:47:38 +01:00
PhilippC
61878f293f New translations strings.xml (Chinese Traditional) 2018-11-12 09:12:42 +01:00
PhilippC
2bd1727076 New translations strings.xml (Croatian) 2018-11-12 09:12:37 +01:00
PhilippC
f0fbf7bf8b New translations strings.xml (Czech) 2018-11-12 09:12:31 +01:00
PhilippC
4a1fccc395 New translations strings.xml (Danish) 2018-11-12 09:12:27 +01:00
PhilippC
54c0497933 New translations strings.xml (Dutch) 2018-11-12 09:12:23 +01:00
PhilippC
49a99e9f15 New translations strings.xml (Finnish) 2018-11-12 09:12:16 +01:00
PhilippC
134fd5b2c2 New translations strings.xml (French) 2018-11-12 09:12:12 +01:00
PhilippC
696f9b3550 New translations strings.xml (Galician) 2018-11-12 09:12:06 +01:00
PhilippC
aeda42cb71 New translations strings.xml (German) 2018-11-12 09:11:59 +01:00
PhilippC
7ba8400c38 New translations strings.xml (Greek) 2018-11-12 09:11:55 +01:00
PhilippC
02f10f07e8 New translations strings.xml (Bulgarian) 2018-11-12 09:11:46 +01:00
PhilippC
83cc32afaa New translations strings.xml (Hungarian) 2018-11-12 09:11:41 +01:00
PhilippC
5b8382643a New translations strings.xml (Italian) 2018-11-12 09:11:35 +01:00
PhilippC
003cb8719a New translations strings.xml (Japanese) 2018-11-12 09:11:28 +01:00
PhilippC
c625ebc128 New translations strings.xml (Korean) 2018-11-12 09:11:23 +01:00
PhilippC
89c0b02327 New translations strings.xml (Norwegian Bokmal) 2018-11-12 09:11:17 +01:00
PhilippC
94bb17a301 New translations strings.xml (Romanian) 2018-11-12 09:11:11 +01:00
PhilippC
4f29b921e5 New translations strings.xml (Serbian (Cyrillic)) 2018-11-12 09:11:06 +01:00
PhilippC
8d5dbb0f3d New translations strings.xml (Slovak) 2018-11-12 09:11:02 +01:00
PhilippC
db321e45da New translations strings.xml (Slovenian) 2018-11-12 09:10:57 +01:00
PhilippC
8e254a341c New translations strings.xml (Spanish) 2018-11-12 09:10:53 +01:00
PhilippC
847a52ab08 New translations strings.xml (Swedish) 2018-11-12 09:10:47 +01:00
PhilippC
94e69e4e84 New translations strings.xml (Turkish) 2018-11-12 09:10:41 +01:00
PhilippC
8834526cac New translations strings.xml (Ukrainian) 2018-11-12 09:10:36 +01:00
PhilippC
788365687e New translations strings.xml (Vietnamese) 2018-11-12 09:10:31 +01:00
PhilippC
4c3d328140 New translations strings.xml (Indonesian) 2018-11-12 09:10:25 +01:00
PhilippC
2588f74f7c New translations strings.xml (Basque) 2018-11-12 09:10:20 +01:00
PhilippC
b70a4ef428 Merge pull request #612 from adorokhine/gradle-build
Add Gradle build config to PluginQR and update to match source conventions.
2018-11-12 09:08:02 +01:00
PhilippC
026a903251 New translations strings.xml (Portuguese) 2018-11-11 07:40:47 +01:00
PhilippC
3557113ed8 New translations strings.xml (Polish) 2018-11-11 07:40:42 +01:00
PhilippC
acd8c27a13 New translations strings.xml (Persian) 2018-11-11 07:40:38 +01:00
PhilippC
3c186eb113 New translations strings.xml (Norwegian Nynorsk) 2018-11-11 07:40:34 +01:00
PhilippC
841eb34224 New translations strings.xml (Russian) 2018-11-11 07:40:29 +01:00
PhilippC
ef583ba7ec New translations strings.xml (Arabic) 2018-11-11 07:40:23 +01:00
Alexander Dorokhine
fa0e06df75 Add Gradle build config to PluginQR and update it to match new source conventions.
Version code is bumped because there was a minor code change to avoid a
fatal lint error complaining about a memory leak.

Fixes #489.
2018-11-10 22:34:05 -08:00
Philipp Crocoll
c26ee7271b Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-11-11 06:36:40 +01:00
Philipp Crocoll
f37c0a9124 allow opening several databases which contain elements with same IDs (required as KeepassHttp stores their settings in an entry with a fixed ID) 2018-11-11 06:35:06 +01:00
Philipp Crocoll
80fbd656a7 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2018-11-08 05:44:21 +01:00
Philipp Crocoll
3fb5749c86 avoid leakage of IOC username/password to logcat/debuglog for some protocols 2018-11-08 05:44:04 +01:00
PhilippC
1692130559 Merge pull request #608 from jakseb/patch-1
Fix formatting in docs/Keepass2Android-Apk.md
2018-11-08 04:41:00 +01:00
Sebastian Jakubiak
cf77a9eae2 Fix formatting in docs/Keepass2Android-Apk.md 2018-11-06 20:28:42 +01:00
PhilippC
26151af48a New translations strings.xml (Swedish) 2018-11-05 18:00:14 +01:00
PhilippC
c3b858f0fd New translations strings.xml (Swedish) 2018-11-05 17:50:08 +01:00
PhilippC
914e788ad8 New translations strings.xml (Swedish) 2018-11-05 17:40:09 +01:00
PhilippC
074178621c Merge pull request #604 from gilbsgilbs/fix-pcloud-filenames
Fix PCloud not overwriting uploaded files.
2018-11-03 19:21:16 +01:00
Gilbert Gilb's
25d1b6b695 Fix PCloud not overwriting uploaded files.
When uploading an existing file into PCloud, it appends a version number
by default (e.g. "MyDb (2).kdbx", "MyDb (3).kdbx" and so on). This
behavior is not desirable in K2PA case. The workaroundfor this is to upload
the file with a temporary name and then rename it to its final name.
This may also avoid corruption with failed uploads depending on how
PCloud handles uploads.

See https://github.com/PhilippC/keepass2android/issues/512#issuecomment-435475365
2018-11-02 23:30:59 +01:00
PhilippC
f121c73c4b New translations strings.xml (Azerbaijani) 2018-10-30 20:20:09 +01:00
PhilippC
3f79e7677c New translations strings.xml (Italian) 2018-10-29 12:50:10 +01:00
PhilippC
ca573f27be New translations strings.xml (Italian) 2018-10-29 11:30:08 +01:00
PhilippC
056a3342bf New translations strings.xml (Italian) 2018-10-29 11:20:10 +01:00
PhilippC
eaa661cf09 New translations strings.xml (Italian) 2018-10-29 11:10:11 +01:00
Philipp Crocoll
b2d791d6ea acknowledge gilbsgilbs for pcloud implementation 2018-10-29 08:39:05 +01:00
Philipp Crocoll
f1ea1935c5 Changelog and manifest for 1.07-pre1 2018-10-28 15:35:40 +01:00
Philipp Crocoll
d9c101debe remove NfcOtpActivity: not working with current multi-db approach, but also not working since Android has App links 2018-10-28 07:17:45 +01:00
PhilippC
e3a720a69d New translations strings.xml (Dutch) 2018-10-26 22:20:10 +02:00
Philipp Crocoll
4f3f18a0ad bug fixes and improvements after adding multi-database support 2018-10-25 06:03:08 +02:00
PhilippC
10a3a8324b New translations strings.xml (Russian) 2018-10-22 16:30:09 +02:00
Philipp Crocoll
a2dab72b25 first version to have multiple databases open at the same time. needs testing and bug fixing. 2018-10-16 06:33:00 +02:00
PhilippC
ca0a381d8c New translations strings.xml (Turkish) 2018-10-11 15:40:08 +02:00
PhilippC
a503e85a57 New translations strings.xml (Turkish) 2018-10-11 15:30:09 +02:00
PhilippC
0d668561b4 New translations strings.xml (Turkish) 2018-10-11 15:20:11 +02:00
PhilippC
c8d39a2c15 New translations strings.xml (Polish) 2018-10-10 17:40:08 +02:00
PhilippC
6146ac90c1 New translations strings.xml (Polish) 2018-10-10 17:30:13 +02:00
PhilippC
2bb00c948d New translations strings.xml (Polish) 2018-10-10 15:00:08 +02:00
PhilippC
01eadd986c New translations strings.xml (Spanish) 2018-10-07 19:30:09 +02:00
PhilippC
b482ea4ecc New translations strings.xml (Chinese Simplified) 2018-10-07 03:40:09 +02:00
PhilippC
19bb98c857 New translations strings.xml (Chinese Simplified) 2018-10-07 03:30:10 +02:00
PhilippC
225afb85e4 New translations strings.xml (Chinese Simplified) 2018-10-07 03:20:08 +02:00
PhilippC
2873ffdff7 New translations strings.xml (Spanish) 2018-10-05 19:30:09 +02:00
PhilippC
52ba506138 Merge pull request #579 from Zeustopher/patch-1
Added Logo to README.md
2018-10-05 05:56:43 +02:00
PhilippC
798f70a706 New translations strings.xml (Spanish) 2018-10-05 05:50:08 +02:00
Christopher Nash
d731d55a7a Added Logo to README.md
Added the Keepass2Android Logo to README.md to give it a little more "flare" when viewing it on Github.
2018-10-04 14:28:19 -06:00
PhilippC
1bfcea0227 New translations strings.xml (Spanish) 2018-10-04 18:20:10 +02:00
PhilippC
71a307bfef New translations strings.xml (German) 2018-10-01 15:30:06 +02:00
PhilippC
7a16a8eaff New translations strings.xml (German) 2018-10-01 15:20:07 +02:00
PhilippC
c1c2ccd940 New translations strings.xml (Russian) 2018-10-01 12:50:06 +02:00
Philipp Crocoll
8a993b7dcb rename StackDbActivity 2018-10-01 11:25:52 +02:00
Philipp Crocoll
977393a9aa refactoring, remove Loaded property from database. instead, make GetDb() return null if database is not loaded. 2018-10-01 11:12:37 +02:00
Philipp Crocoll
4f36de9900 refactoring: introduce StackBaseActivity which replaces PasswordActivity in its role as stack base and orchestrating activity. This is in preparation to allow multiple open databases. 2018-10-01 10:21:28 +02:00
PhilippC
ef658eb4cd New translations strings.xml (Ukrainian) 2018-09-29 14:40:05 +02:00
PhilippC
6f77577482 New translations strings.xml (Ukrainian) 2018-09-29 14:30:05 +02:00
Philipp Crocoll
bfdb1a8f62 disable notification badges ("1" icons) 2018-09-26 05:51:12 +02:00
PhilippC
0935d70ae4 New translations strings.xml (Slovak) 2018-09-23 12:40:06 +02:00
PhilippC
24e4e2b960 New translations strings.xml (Slovak) 2018-09-23 12:30:05 +02:00
PhilippC
e608d7463e New translations strings.xml (Catalan) 2018-09-23 12:20:05 +02:00
PhilippC
47453f1471 New translations strings.xml (Catalan) 2018-09-23 12:10:06 +02:00
PhilippC
362780f59a New translations strings.xml (French) 2018-09-21 14:00:06 +02:00
PhilippC
a2a511b3c0 New translations strings.xml (Vietnamese) 2018-09-21 13:50:38 +02:00
PhilippC
78cde8ab62 New translations strings.xml (Indonesian) 2018-09-21 13:50:35 +02:00
PhilippC
46b779c9d5 New translations strings.xml (Hungarian) 2018-09-21 13:50:32 +02:00
PhilippC
23129bf95a New translations strings.xml (Hebrew) 2018-09-21 13:50:29 +02:00
PhilippC
fba137bb3f New translations strings.xml (Greek) 2018-09-21 13:50:27 +02:00
PhilippC
e50a73b4bf New translations strings.xml (German) 2018-09-21 13:50:24 +02:00
PhilippC
31afe11d0e New translations strings.xml (Galician) 2018-09-21 13:50:21 +02:00
PhilippC
5dc1d047ac New translations strings.xml (French) 2018-09-21 13:50:18 +02:00
PhilippC
19e0cf406c New translations strings.xml (Finnish) 2018-09-21 13:50:15 +02:00
PhilippC
0bc1eece0a New translations strings.xml (Dutch) 2018-09-21 13:50:12 +02:00
PhilippC
f2e93e915b New translations strings.xml (Czech) 2018-09-21 13:50:09 +02:00
PhilippC
8db6a99194 New translations strings.xml (Croatian) 2018-09-21 13:50:06 +02:00
Philipp Crocoll
1490ebce03 minor refactoring 2018-09-21 06:26:04 +02:00
Philipp Crocoll
cd189e01dc use internal directory for offline caching. this reduces the likelihood of data loss. Users need to disable and then re-enable file caching to make sure all files are cached in the new directory. closes #83 https://github.com/PhilippC/keepass2android/issues/83 2018-09-18 06:18:17 +02:00
PhilippC
15467248ee New translations strings.xml (Chinese Simplified) 2018-09-18 04:31:09 +02:00
PhilippC
23008ab5b8 New translations strings.xml (Catalan) 2018-09-18 04:31:07 +02:00
PhilippC
041fbb10a1 New translations strings.xml (Bulgarian) 2018-09-18 04:31:04 +02:00
PhilippC
9ba0e59df5 New translations strings.xml (Danish) 2018-09-18 04:31:01 +02:00
PhilippC
0bb9f57919 New translations strings.xml (Basque) 2018-09-18 04:30:59 +02:00
PhilippC
106da869c1 New translations strings.xml (Italian) 2018-09-18 04:30:56 +02:00
PhilippC
d34a3352f2 New translations strings.xml (Korean) 2018-09-18 04:30:54 +02:00
PhilippC
4b5c922f11 New translations strings.xml (Ukrainian) 2018-09-18 04:30:52 +02:00
PhilippC
aacb415364 New translations strings.xml (Turkish) 2018-09-18 04:30:49 +02:00
PhilippC
bdc8bcfe5c New translations strings.xml (Swedish) 2018-09-18 04:30:46 +02:00
PhilippC
154238edf0 New translations strings.xml (Spanish) 2018-09-18 04:30:43 +02:00
PhilippC
eba789c200 New translations strings.xml (Slovenian) 2018-09-18 04:30:41 +02:00
PhilippC
63cb67a03c New translations strings.xml (Slovak) 2018-09-18 04:30:38 +02:00
PhilippC
1c299c6d5d New translations strings.xml (Serbian (Cyrillic)) 2018-09-18 04:30:36 +02:00
PhilippC
486c5310d7 New translations strings.xml (Japanese) 2018-09-18 04:30:34 +02:00
PhilippC
5ef4a97d5f New translations strings.xml (Russian) 2018-09-18 04:30:31 +02:00
PhilippC
03adb8f730 New translations strings.xml (Portuguese, Brazilian) 2018-09-18 04:30:29 +02:00
PhilippC
abdcd0b3f0 Merge pull request #555 from tobiasKaminsky/ncNaming
NextCloud -> Nextcloud
2018-09-18 04:29:26 +02:00
Philipp Crocoll
6e225808a9 add support for Binary Resource dictionaries of AnySoftKeyboard, fixes #245 2018-09-18 04:27:07 +02:00
tobiasKaminsky
382c96f587 NextCloud -> Nextcloud 2018-09-17 16:08:24 +02:00
PhilippC
80cb0119c7 New translations strings.xml (Portuguese) 2018-09-17 13:00:39 +02:00
PhilippC
e7bc5072c0 New translations strings.xml (Polish) 2018-09-17 13:00:36 +02:00
PhilippC
a65057679c New translations strings.xml (Persian) 2018-09-17 13:00:32 +02:00
PhilippC
025186d22f New translations strings.xml (Norwegian Bokmal) 2018-09-17 13:00:27 +02:00
PhilippC
e17217206f New translations strings.xml (Romanian) 2018-09-17 13:00:24 +02:00
PhilippC
c64ca44457 New translations strings.xml (Arabic) 2018-09-17 13:00:21 +02:00
PhilippC
c6e9a16274 Merge pull request #553 from PhilippC/1.07
1.07
2018-09-17 12:56:40 +02:00
Philipp Crocoll
2dc125e0ce allow to save attachments to deliberate storages, closes #346 2018-09-17 12:56:10 +02:00
Philipp Crocoll
9c88ce213b make nextcloud support explicit (closes https://github.com/PhilippC/keepass2android/issues/256) 2018-09-17 11:34:36 +02:00
PhilippC
f945380a87 New translations strings.xml (Chinese Traditional) 2018-09-17 11:11:12 +02:00
PhilippC
bb9664eafc New translations strings.xml (Japanese) 2018-09-17 11:10:38 +02:00
PhilippC
eaca802ecc New translations strings.xml (Portuguese, Brazilian) 2018-09-17 11:10:33 +02:00
PhilippC
2e6ca574b6 Merge pull request #552 from PhilippC/1.07
1.07
2018-09-17 11:03:58 +02:00
Philipp Crocoll
026de5dd4e no longer provide a system-wide file chooser, closes #541 2018-09-17 10:48:18 +02:00
Philipp Crocoll
262897fbf6 add preference option to disable auto-return from queries with only one matching result (closes https://github.com/PhilippC/keepass2android/issues/544) 2018-09-17 10:32:41 +02:00
Philipp Crocoll
304a9d90d0 allow to open Autofill settings also if service is enabled 2018-09-17 10:31:21 +02:00
Philipp Crocoll
91e1674833 make sure dialog asking overwrite/append of attachments is shown by moving code to OnResume. fixes https://github.com/PhilippC/keepass2android/issues/342 2018-09-17 10:11:03 +02:00
PhilippC
d4c61ce932 New translations strings.xml (Catalan) 2018-09-16 16:10:05 +02:00
PhilippC
7387ebe182 New translations strings.xml (Catalan) 2018-09-16 16:00:06 +02:00
PhilippC
d6f305cfa6 New translations strings.xml (Dutch) 2018-09-16 10:40:05 +02:00
PhilippC
73b9fbb435 New translations strings.xml (Dutch) 2018-09-16 10:30:05 +02:00
PhilippC
51c2f313d4 New translations strings.xml (Dutch) 2018-09-16 10:20:05 +02:00
PhilippC
0a390107a3 New translations strings.xml (Polish) 2018-09-12 22:40:06 +02:00
PhilippC
077bf997c6 New translations strings.xml (Vietnamese) 2018-09-12 17:10:23 +02:00
PhilippC
48cb473ecb New translations strings.xml (Japanese) 2018-09-12 17:10:19 +02:00
PhilippC
40dc542302 New translations strings.xml (Chinese Simplified) 2018-09-12 17:10:13 +02:00
PhilippC
28bb4894b2 New translations strings.xml (Catalan) 2018-09-12 17:10:08 +02:00
PhilippC
774d17dd25 New translations strings.xml (Chinese Traditional) 2018-09-12 17:01:33 +02:00
PhilippC
790637f1bd New translations strings.xml (Croatian) 2018-09-12 17:01:31 +02:00
PhilippC
99fb5d3b8e New translations strings.xml (Czech) 2018-09-12 17:01:28 +02:00
PhilippC
6676e62579 New translations strings.xml (Danish) 2018-09-12 17:01:25 +02:00
PhilippC
d735992f5c New translations strings.xml (Dutch) 2018-09-12 17:01:22 +02:00
PhilippC
8a32cfc185 New translations strings.xml (Finnish) 2018-09-12 17:01:19 +02:00
PhilippC
285fafc300 New translations strings.xml (French) 2018-09-12 17:01:16 +02:00
PhilippC
0c90433a34 New translations strings.xml (Galician) 2018-09-12 17:01:12 +02:00
PhilippC
d6070368b7 New translations strings.xml (German) 2018-09-12 17:01:09 +02:00
PhilippC
b42389500f New translations strings.xml (Greek) 2018-09-12 17:01:06 +02:00
PhilippC
daca972fc2 New translations strings.xml (Bulgarian) 2018-09-12 17:01:03 +02:00
PhilippC
8447e59d1f New translations strings.xml (Hebrew) 2018-09-12 17:01:00 +02:00
PhilippC
07ff8cd662 New translations strings.xml (Indonesian) 2018-09-12 17:00:57 +02:00
PhilippC
dbc734eee5 New translations strings.xml (Italian) 2018-09-12 17:00:54 +02:00
PhilippC
eaa95fdba4 New translations strings.xml (Japanese) 2018-09-12 17:00:49 +02:00
PhilippC
3ba1169e9c New translations strings.xml (Korean) 2018-09-12 17:00:46 +02:00
PhilippC
0117b53ea2 New translations strings.xml (Russian) 2018-09-12 17:00:43 +02:00
PhilippC
a2ec04b641 New translations strings.xml (Serbian (Cyrillic)) 2018-09-12 17:00:39 +02:00
PhilippC
8fdcef9c42 New translations strings.xml (Slovak) 2018-09-12 17:00:36 +02:00
PhilippC
d311de764d New translations strings.xml (Slovenian) 2018-09-12 17:00:33 +02:00
PhilippC
e9b16b2f70 New translations strings.xml (Spanish) 2018-09-12 17:00:29 +02:00
PhilippC
21a81b977b New translations strings.xml (Swedish) 2018-09-12 17:00:27 +02:00
PhilippC
9ce1c2b075 New translations strings.xml (Turkish) 2018-09-12 17:00:23 +02:00
PhilippC
b974cbd14c New translations strings.xml (Ukrainian) 2018-09-12 17:00:19 +02:00
PhilippC
1d96282fd9 New translations strings.xml (Hungarian) 2018-09-12 17:00:14 +02:00
PhilippC
48efda6bd9 New translations strings.xml (Basque) 2018-09-12 17:00:09 +02:00
PhilippC
aba3e0033f New translations strings.xml (Portuguese) 2018-09-12 05:00:37 +02:00
PhilippC
5bf61a63cc New translations strings.xml (Polish) 2018-09-12 05:00:35 +02:00
PhilippC
48095c0433 New translations strings.xml (Persian) 2018-09-12 05:00:31 +02:00
PhilippC
3e1599119a New translations strings.xml (Norwegian Nynorsk) 2018-09-12 05:00:29 +02:00
PhilippC
f488e8a7ab New translations strings.xml (Norwegian Bokmal) 2018-09-12 05:00:27 +02:00
PhilippC
b5c17bf7bc New translations strings.xml (Romanian) 2018-09-12 05:00:25 +02:00
PhilippC
77e994e9fd New translations strings.xml (Arabic) 2018-09-12 05:00:22 +02:00
PhilippC
bbd3fc4d1d Merge pull request #543 from PhilippC/1.07
first 1.07 features
2018-09-12 04:53:01 +02:00
Philipp Crocoll
ee63946be2 set network security configuration to that of Android 6, trusting user certificates, closes #339 2018-09-12 04:51:58 +02:00
Philipp Crocoll
b1bcfacf35 refactor PasswordActivity's key provider handling, implement Password+Keyfile+ChallengeXC, closes #456 2018-09-12 04:39:21 +02:00
Philipp Crocoll
d4936e8eec fix issue with opening attachments with special characters in their name, closes #480 2018-09-11 21:42:44 +02:00
Philipp Crocoll
dbba098555 allow to delete entries from the EntryActivity (i.e. also after searching), closes #473 2018-09-11 05:03:54 +02:00
Philipp Crocoll
b368e93061 fix potential crash in keyboard 2018-09-11 05:02:31 +02:00
Philipp Crocoll
10b333ae48 allow to switch to built-in keyboard when opening PasswordActivity or EntryEditActivity, closes #67 2018-09-11 04:48:55 +02:00
Philipp Crocoll
87c0345a6a prevent accidental modification of password in edit text after using fingerprint, closes #493 2018-09-11 04:32:49 +02:00
Philipp Crocoll
381510d213 implement GUI for public key authentication with SFTP, closes #69 2018-09-11 04:19:40 +02:00
Philipp Crocoll
f5f99f5a04 attempt to integrate pulickey auth 2018-09-10 12:57:17 +02:00
Philipp Crocoll
fcf1214f80 implement publickey authentication in JavaFileStorage (not yet integrated in main app) 2018-09-10 12:56:03 +02:00
Philipp Crocoll
7e122529d2 implement prompt callbacks for JSch, fixes https://github.com/PhilippC/keepass2android/issues/519 2018-09-10 11:43:59 +02:00
Philipp Crocoll
600c3d21dc Merge branch '1.06' into 1.07 2018-09-10 09:52:39 +02:00
PhilippC
2a57b94e08 New translations strings.xml (German) 2018-09-09 21:20:06 +02:00
PhilippC
366a37b765 New translations strings.xml (Polish) 2018-09-09 16:40:05 +02:00
PhilippC
a3806f7a81 New translations strings.xml (Greek) 2018-09-06 22:00:07 +02:00
PhilippC
cf28e373f7 Merge pull request #535 from gilbsgilbs/pcloud-integration
Implement requiresSetup for PCloud.
2018-09-06 03:45:20 +02:00
Gilbert Gilb's
8d80295e07 Implement requiresSetup for PCloud.
Also consider error 2095 as a logout, so that the user can re-login.
2018-09-04 20:59:00 +02:00
PhilippC
1f7ffe6ea0 New translations strings.xml (Catalan) 2018-09-03 15:00:07 +02:00
PhilippC
a740753175 New translations strings.xml (Czech) 2018-09-02 10:30:06 +02:00
PhilippC
c70f996915 New translations strings.xml (Ukrainian) 2018-08-30 15:40:06 +02:00
PhilippC
707dfc2a0b New translations strings.xml (Chinese Traditional) 2018-08-30 01:20:53 +02:00
PhilippC
77db3362fc New translations strings.xml (French) 2018-08-30 01:20:41 +02:00
PhilippC
c8e0687288 New translations strings.xml (Russian) 2018-08-30 01:20:24 +02:00
PhilippC
f61a6191ec New translations strings.xml (Slovak) 2018-08-30 01:20:20 +02:00
PhilippC
2648236bb4 New translations strings.xml (Spanish) 2018-08-30 01:20:16 +02:00
PhilippC
382e23f545 New translations strings.xml (Turkish) 2018-08-30 01:20:12 +02:00
PhilippC
2eddbe3669 New translations strings.xml (Ukrainian) 2018-08-30 01:20:09 +02:00
Philipp Crocoll
267d710c13 some changes to get the build working on VS2017 and to reduce APK size 2018-08-28 21:58:33 +02:00
PhilippC
5e41517178 New translations strings.xml (Portuguese) 2018-08-28 21:00:25 +02:00
PhilippC
5c9cf0a655 Merge pull request #523 from gilbsgilbs/pcloud-integration
Add PCloud support.
2018-08-28 20:55:41 +02:00
Gilbert Gilb's
6301b48b5d Fix indentation. 2018-08-27 21:48:48 +02:00
Gilbert Gilb's
5dea97cce2 Add PCloud support. 2018-08-27 20:58:36 +02:00
PhilippC
69b63bcb15 Merge pull request #522 from gilbsgilbs/linux-build
Support build on Linux
2018-08-27 12:17:56 +02:00
Gilbert Gilb's
cefad66475 Add execution rights to gradle wrappers. 2018-08-25 15:37:25 +02:00
Gilbert Gilb's
726f4438d6 Fix xamarin.Android bindings path.
See https://github.com/PhilippC/keepass2android/pull/156#issuecomment-415965219
2018-08-25 15:37:25 +02:00
Gilbert Gilb's
880e75a91c Fix project configuration paths case.
This is required for linux builds.
2018-08-25 15:37:25 +02:00
Gilbert Gilb's
0f1fd0e367 Fix dummy credentials for Dropbox.
The client disallows empty credentials, making KP2A force close.
2018-08-25 15:37:25 +02:00
Gilbert Gilb's
7a44cf6e26 Add scripts and instructions for Linux builds.
This is mostly based on @bensku work.

See https://github.com/PhilippC/keepass2android/pull/156
2018-08-25 15:37:23 +02:00
PhilippC
177c709e0a New translations strings.xml (Chinese Simplified) 2018-08-24 08:00:06 +02:00
PhilippC
699eb824a1 New translations strings.xml (Chinese Simplified) 2018-08-24 07:50:05 +02:00
PhilippC
6b19e305f3 New translations strings.xml (Chinese Simplified) 2018-08-21 20:40:44 +02:00
PhilippC
8b1b4044b3 New translations strings.xml (Portuguese) 2018-08-21 20:40:18 +02:00
399 changed files with 27734 additions and 7873 deletions

View File

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

View File

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

View File

@@ -1,3 +1,6 @@
<h1 align="center"><img src="/src/keepass2android/Resources/mipmap-xxxhdpi/ic_launcher_online.png" align="center" width="100" alt="Keepass2Android Logo">Keepass2Android</h1>
# What is Keepass2Android?
Keepass2Android is a password manager app. It allows to store and retrieve passwords and other sensitive information in a file called "database". This database is secured with a so-called master password. The master password typically is a strong password and can be complemented with a second factor for additional security.
The password database file can be synchronized across different devices. This works best using one of the built-in cloud storage options, but can also be performed with third-party apps. Keepass2Android is compatible with Keepass 1 and Keepass 2 on Windows and KeepassX on Linux.
@@ -15,4 +18,4 @@ Beta-releases can be obtained by opting in to the [Beta testing channel](https:/
# How do I learn more?
Please see the [documentation](Documentation.md).
[![Build Status](https://www.bitrise.io/app/43a23ab54dee9f7e/status.svg?token=2vryTsMQzTX3XRPikhgRwA&branch=nonet)](https://www.bitrise.io/app/43a23ab54dee9f7e)
[![Build Status](https://www.bitrise.io/app/43a23ab54dee9f7e/status.svg?token=2vryTsMQzTX3XRPikhgRwA&branch=master)](https://www.bitrise.io/app/43a23ab54dee9f7e)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0B109C0E-0514-4340-8779-5BD6A0DDE84E}</ProjectGuid>
<ProjectTypeGuids>{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AdalBindings</RootNamespace>
<AssemblyName>AdalBindings</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />
<LibraryProjectZip Include="Jars\adal-1.14.0.aar" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Transforms\Metadata.xml" />
<TransformFile Include="Transforms\EnumFields.xml" />
<TransformFile Include="Transforms\EnumMethods.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\gson-2.3.1.jar" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

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

View File

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

Binary file not shown.

View File

@@ -0,0 +1,30 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AdalBindings")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AdalBindings")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

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

View File

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

View File

@@ -0,0 +1,13 @@
<metadata>
<!--
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
-->
<remove-node path="/api/package[@name='com.microsoft.aad.adal']/class[@name='AuthenticationActivity']" />
<remove-node path="/api/package[@name='com.microsoft.aad.adal']/class[@name='DateTimeAdapter']" />
<remove-node path="/api/package[@name='com.microsoft.aad.adal']" />
</metadata>

View File

@@ -60,7 +60,6 @@
</LibraryProjectZip>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />
<LibraryProjectZip Include="Jars\adal-1.14.0.aar" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Transforms\Metadata.xml" />
@@ -81,6 +80,9 @@
<Visible>False</Visible>
</XamarinComponentReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PCloudBindings\PCloudBindings.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\okhttp-digest-1.7.jar" />
</ItemGroup>

View File

@@ -11,6 +11,8 @@
<remove-node path="/api/package[@name='com.jcraft.jsch.jcraft']" />
<remove-node path="/api/package[@name='com.jcraft.jzlib']" />
<remove-node path="/api/package[@name='com.pcloud.sdk']" />
<remove-node path="/api/package[@name='com.dropbox.core']" />
<remove-node path="/api/package[@name='com.dropbox.core.util']" />
<remove-node path="/api/package[@name='com.dropbox.core.http']" />

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2010
VisualStudioVersion = 15.0.27004.2009
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}"
EndProject
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aBusinessLogic", "Kp2aBu
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwofishCipher", "TwofishCipher\TwofishCipher.csproj", "{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JavaFileStorageBindings", "JavaFileStorageBindings\JavaFileStorageBindings.csproj", "{48574278-4779-4B3A-A9E4-9CF1BC285D0B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidFileChooserBinding", "AndroidFileChooserBinding\AndroidFileChooserBinding.csproj", "{3C0F7FE5-639F-4422-A087-8B26CF862D1B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KP2AKdbLibraryBinding", "KP2AKdbLibraryBinding\KP2AKdbLibraryBinding.csproj", "{70D3844A-D9FA-4A64-B205-A84C6A822196}"
@@ -21,8 +23,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginSdkBinding", "PluginS
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZlibAndroid", "ZlibAndroid\ZlibAndroid.csproj", "{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.FtpClient.Android", "netftpandroid\System.Net.FtpClient\System.Net.FtpClient.Android.csproj", "{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCloudBindings", "PCloudBindings\PCloudBindings.csproj", "{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -105,8 +111,8 @@ Global
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Release|Win32.Build.0 = Release|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Release|x64.ActiveCfg = Release|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Release|x64.Build.0 = Release|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.ActiveCfg = Debug|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.Build.0 = Debug|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
@@ -147,6 +153,30 @@ Global
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Win32.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Win32.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|x64.ActiveCfg = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|x64.Build.0 = Debug|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Any CPU.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Win32.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Win32.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.ActiveCfg = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.Build.0 = Release|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Win32.Build.0 = ReleaseNoNet|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.Build.0 = ReleaseNoNet|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -159,8 +189,8 @@ Global
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|Win32.ActiveCfg = Release|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Release|x64.ActiveCfg = Release|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
@@ -177,8 +207,8 @@ Global
{70D3844A-D9FA-4A64-B205-A84C6A822196}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.Release|Win32.ActiveCfg = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.Release|x64.ActiveCfg = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{70D3844A-D9FA-4A64-B205-A84C6A822196}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
@@ -195,8 +225,8 @@ Global
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Win32.ActiveCfg = Release|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|x64.ActiveCfg = Release|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
@@ -225,6 +255,24 @@ Global
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Win32.ActiveCfg = Debug|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|x64.ActiveCfg = Debug|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Any CPU.Build.0 = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Win32.ActiveCfg = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|x64.ActiveCfg = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -243,6 +291,30 @@ Global
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Win32.ActiveCfg = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Win32.Build.0 = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|x64.ActiveCfg = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|x64.Build.0 = Debug|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Any CPU.Build.0 = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Win32.ActiveCfg = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Win32.Build.0 = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|x64.ActiveCfg = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|x64.Build.0 = Release|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Win32.Build.0 = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|x64.Build.0 = ReleaseNoNet|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -60,7 +60,12 @@ namespace KeePassLib.Keys
get { return m_pbKeyData; }
}
/// <summary>
public uint GetMinKdbxVersion()
{
return 0;
}
/// <summary>
/// Construct a user account key.
/// </summary>
public KcpUserAccount()

View File

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

View File

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

View File

@@ -485,12 +485,6 @@ namespace KeePassLib
set { m_pbHashOfLastIO = value; }
}
public bool UseFileTransactions
{
get { return m_bUseFileTransactions; }
set { m_bUseFileTransactions = value; }
}
public bool UseFileLocks
{
get { return m_bUseFileLocks; }

View File

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

View File

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

View File

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

View File

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

View File

@@ -207,8 +207,7 @@ namespace keepass2android.Io
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
{
//TODO: required for OTP Aux file retrieval
throw new NotImplementedException();
return IoUtil.GetParentPath(ioc);
}
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)

View File

@@ -255,7 +255,8 @@ namespace keepass2android.Io
if (ioc.IsLocalFile())
{
bool requiresPermission = !(ioc.Path.StartsWith(activity.Activity.FilesDir.CanonicalPath)
|| ioc.Path.StartsWith(IoUtil.GetInternalDirectory(activity.Activity).CanonicalPath));
|| ioc.Path.StartsWith(IoUtil.GetInternalDirectory(activity.Activity).CanonicalPath)
|| ioc.Path.StartsWith(IoUtil.GetInternalDirectory(activity.Activity).CanonicalPath));
var extDirectory = activity.Activity.GetExternalFilesDir(null);
if ((extDirectory != null) && (ioc.Path.StartsWith(extDirectory.CanonicalPath)))

View File

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

View File

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

View File

@@ -233,7 +233,6 @@ namespace keepass2android.Io
public FileDescription GetFileDescription(IOConnectionInfo ioc)
{
Kp2aLog.Log("GetFileDescription "+ioc.Path);
try
{
return ConvertToFileDescription(Jfs.GetFileEntry(IocToPath(ioc)));
@@ -302,7 +301,9 @@ namespace keepass2android.Io
public void OnResume(IFileStorageSetupActivity activity)
{
#if DEBUG
Kp2aLog.Log("JFS/OnResume Ioc.Path=" +activity.Ioc.Path+". Path="+((IJavaFileStorageFileStorageSetupActivity)activity).Path);
#endif
_jfs.OnResume(((IJavaFileStorageFileStorageSetupActivity) activity));
}
@@ -366,4 +367,4 @@ namespace keepass2android.Io
}
}
#endif
}
}

View File

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

View File

@@ -5,8 +5,8 @@ namespace keepass2android.Io
{
public class SftpFileStorage: JavaFileStorage
{
public SftpFileStorage(IKp2aApp app) :
base(new Keepass2android.Javafilestorage.SftpStorage(), app)
public SftpFileStorage(Context ctx, IKp2aApp app) :
base(new Keepass2android.Javafilestorage.SftpStorage(ctx.ApplicationContext), app)
{
}

View File

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

View File

@@ -31,7 +31,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NoNet;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
@@ -53,6 +53,7 @@
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
<Reference Include="Xamarin.Android.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
@@ -90,7 +91,7 @@
<Compile Include="database\CheckDatabaseForChanges.cs" />
<Compile Include="database\edit\AddTemplateEntries.cs" />
<Compile Include="database\edit\CopyEntry.cs" />
<Compile Include="database\edit\DeleteMultipleItems.cs" />
<Compile Include="database\edit\DeleteMultipleItemsFromOneDatabase.cs" />
<Compile Include="database\edit\EditGroup.cs" />
<Compile Include="database\edit\MoveElements.cs" />
<Compile Include="database\KdbDatabaseFormat.cs" />
@@ -102,15 +103,25 @@
<Compile Include="DataExchange\Formats\KeePassKdb2x.cs" />
<Compile Include="DataExchange\Formats\KeePassXml2x.cs" />
<Compile Include="DataExchange\PwExportInfo.cs" />
<Compile Include="ElementAndDatabaseId.cs" />
<Compile Include="Io\AndroidContentStorage.cs" />
<Compile Include="Io\BuiltInFileStorage.cs" />
<Compile Include="Io\CachingFileStorage.cs" />
<Compile Include="Io\DropboxFileStorage.cs" />
<Compile Include="Io\DropboxFileStorageKeys.cs" />
<Compile Include="Io\FileDescription.cs" />
<Compile Include="Io\FileStorageSetupActivity.cs" />
<Compile Include="Io\FileStorageSetupInitiatorActivity.cs" />
<Compile Include="Io\GDriveFileStorage.cs" />
<Compile Include="Io\IFileStorage.cs" />
<Compile Include="Io\IoUtil.cs" />
<Compile Include="Io\JavaFileStorage.cs" />
<Compile Include="Io\NetFtpFileStorage.cs" />
<Compile Include="Io\OfflineSwitchableFileStorage.cs" />
<Compile Include="Io\PCloudFileStorage.cs" />
<Compile Include="Io\SftpFileStorage.cs" />
<Compile Include="Io\OneDriveFileStorage.cs" />
<Compile Include="Io\WebDavFileStorage.cs" />
<Compile Include="IProgressDialog.cs" />
<Compile Include="PreferenceKey.cs" />
<Compile Include="SelectStorageLocationActivityBase.cs" />
@@ -119,15 +130,15 @@
<Compile Include="database\edit\ActionOnFinish.cs" />
<Compile Include="database\edit\AddEntry.cs" />
<Compile Include="database\edit\AddGroup.cs" />
<Compile Include="database\edit\CreateDb.cs" />
<Compile Include="database\edit\CreateDB.cs" />
<Compile Include="database\edit\DeleteEntry.cs" />
<Compile Include="database\edit\DeleteGroup.cs" />
<Compile Include="database\edit\DeleteRunnable.cs" />
<Compile Include="database\edit\FileOnFinish.cs" />
<Compile Include="database\edit\LoadDb.cs" />
<Compile Include="database\edit\LoadDB.cs" />
<Compile Include="database\edit\OnFinish.cs" />
<Compile Include="database\edit\RunnableOnFinish.cs" />
<Compile Include="database\edit\SaveDb.cs" />
<Compile Include="database\edit\SaveDB.cs" />
<Compile Include="database\edit\SetPassword.cs" />
<Compile Include="database\edit\UpdateEntry.cs" />
<Compile Include="IKp2aApp.cs" />
@@ -146,6 +157,10 @@
<Compile Include="Utils\Spr\SprEngine.PickChars.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj">
<Project>{48574278-4779-4b3a-a9e4-9cf1bc285d0b}</Project>
<Name>JavaFileStorageBindings</Name>
</ProjectReference>
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
<Project>{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}</Project>
<Name>KeePassLib2Android</Name>
@@ -154,6 +169,10 @@
<Project>{70D3844A-D9FA-4A64-B205-A84C6A822196}</Project>
<Name>KP2AKdbLibraryBinding</Name>
</ProjectReference>
<ProjectReference Include="..\netftpandroid\System.Net.FtpClient\System.Net.FtpClient.Android.csproj">
<Project>{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}</Project>
<Name>System.Net.FtpClient.Android</Name>
</ProjectReference>
<ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj">
<Project>{5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}</Project>
<Name>TwofishCipher</Name>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -63,6 +63,8 @@
<TransformFile Include="Transforms\EnumMethods.xml" />
<TransformFile Include="Transforms\Metadata.xml" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildExtensionsPath)\Novell\Xamarin.Android.Bindings.targets" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
<ItemGroup>
<Folder Include="libs\" />
</ItemGroup>
</Project>

View File

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

View File

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

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PCloudBindings</RootNamespace>
<AssemblyName>PCouldBindings</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<AndroidLinkMode>None</AndroidLinkMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseNoNet|AnyCPU'">
<OutputPath>bin\ReleaseNoNet\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />
<LibraryProjectZip Include="Jars\pcloud-sdk-android-1.0.1.aar" />
</ItemGroup>
<ItemGroup>
<TransformFile Include="Transforms\Metadata.xml" />
<TransformFile Include="Transforms\EnumFields.xml" />
<TransformFile Include="Transforms\EnumMethods.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<EmbeddedReferenceJar Include="Jars\pcloud-sdk-java-core-1.0.1.jar" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,30 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("PCloudBindings")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PCloudBindings")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
<metadata>
<!--
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
-->
<remove-node path="/api/package[@name='com.pcloud.sdk']" />
</metadata>

View File

@@ -53,8 +53,8 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\app-release.aar">
<Link>Jars\app-release.aar</Link>
<LibraryProjectZip Include="..\java\Keepass2AndroidPluginSDK2\app\build\outputs\aar\Keepass2AndroidPluginSDK2-release.aar">
<Link>Jars\Keepass2AndroidPluginSDK2-release.aar</Link>
</LibraryProjectZip>
<None Include="Jars\AboutJars.txt" />
<None Include="Additions\AboutAdditions.txt" />

20
src/build-scripts/build-all.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
set -e
echo '*****************************************'
echo '********** Building Java parts **********'
echo '*****************************************'
./build-java.sh
echo '*****************************************'
echo '******** Building Xamarin parts *********'
echo '*****************************************'
./build-xamarin.sh
echo '*****************************************'
echo '************** Building APK *************'
echo '*****************************************'
./build-apk.sh
echo
echo 'Congratulations! You you can find the target APK in src/keepass2android/bin/Debug/.'

8
src/build-scripts/build-apk.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
set -e
pushd ../keepass2android
xabuild keepass2android.csproj /t:SignAndroidPackage "$@"
popd

View File

@@ -7,4 +7,7 @@ call gradlew assemble
cd ..\Keepass2AndroidPluginSDK2
call gradlew assemble
cd ..\..\build-scripts
cd ..\PluginQR
call gradlew assemble
cd ..\..\build-scripts

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

@@ -0,0 +1,22 @@
#!/bin/bash
set -e
pushd ../java/
pushd JavaFileStorageTest-AS
./gradlew assemble
popd
pushd KP2ASoftkeyboard_AS
./gradlew assemble
popd
pushd Keepass2AndroidPluginSDK2
./gradlew assemble
popd
pushd PluginQR
./gradlew assemble
popd
popd

View File

@@ -6,11 +6,11 @@ if exist "DropboxFileStorageKeys.cs" (
)
cd ..\..\keepass2android
call UseManifestNoNet.bat
call UseManifestDebug.bat
cd ..
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64
msbuild KeePass.sln /target:keepass2android /p:BuildProjectReferences=true /p:Configuration="Release" /p:Platform="Any CPU"
msbuild KeePass.sln /target:keepass2android /p:BuildProjectReferences=true /p:Configuration="Debug" /p:Platform="Any CPU"
cd build-scripts

View File

@@ -0,0 +1,25 @@
#!/bin/bash
set -e
pushd ..
pushd Kp2aBusinessLogic/Io
if [ -f "DropboxFileStorageKeys.cs" ]
then
echo "DropboxFileStorageKeys.cs found."
else
cp DropboxFileStorageKeysDummy.cs DropboxFileStorageKeys.cs
fi
popd
pushd keepass2android
./UseManifestDebug.sh
popd
# call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64
xabuild KeePass.sln /target:keepass2android /p:BuildProjectReferences=true /p:Configuration="Debug" /p:Platform="Any CPU" "$@"
popd

55
src/build.readme.md Normal file
View File

@@ -0,0 +1,55 @@
# How to build Keepass2Android
## Overview
Keepass2Android is a Mono for Android app. This means that you need Xamarin's Mono for Android to build it. However, it also uses several components written in Java, so there are also Android-Studio projects involved. To make things even worse, parts of the keyboard and kdb-library are written in native code.
The current build-scripts assume that the native libraries are already built (they are included in the repo).
To build KP2A from scratch, make sure that you have Xamarin's Mono for Android installed and also install Android Studio. Make sure that both point to the same Android SDK location.
## Prerequisites
- Install Xamarin.Android
- Fetch all submodules (`git submodule init && git submodule update`)
## Build
### On Windows
```bat
cd build-scripts
build-java.bat
build-xamarin.bat
```
build-java.bat will call gradlew for several Java modules. build-xamarin.bat will first make sure that you have all files at their place. (There is a "secret" file for Dropbox SDK keys which is not in the repo, this is replaced with a dummy file. There are also different Android Manifest files depending on the configuration which is selected by calling the appropriate script.)
**Notes:**
- For building the java parts, it is suggested to keep a short name (e.g. "c:\projects\keepass2android") for the root project directory. Otherwise the Windows path length limit might be hit when building.
- Before building the java parts, make sure you have set the ANDROID_HOME variable or create a local.properties file inside the directories with a gradlew file. It is recommended to use the same SDK location as that of the Xamarin build.
### On Linux
- Install [Mono](https://www.mono-project.com/)
- Install Xamarin.Android
- Option 1: Use the mono-project [CI builds](https://jenkins.mono-project.com/view/Xamarin.Android/job/xamarin-android-linux/lastSuccessfulBuild/Azure/)
- Option 2: [Build it from source](https://github.com/xamarin/xamarin-android/blob/master/Documentation/README.md#building-from-source)
- Setup your environment:
- Add `xabuild` to your path: `export PATH=/path/to/xamarin.android-oss/bin/Release/bin/:$PATH`
- Setup your `ANDROID_HOME` if it's not already: `export ANDROID_HOME=/path/to/android/`
- Alternatively, you can set your `ANDROID_SDK_PATH` and `ANDROID_NDK_PATH`.
- Build [jar2xml](https://github.com/xamarin/jar2xml) and copy `jar2xml.jar` to `/path/to/xamarin.android-oss/bin/Release/lib/xamarin.android/xbuild/Xamarin/Android/`
- Install [libzip](https://libzip.org/) for your distribution.
- Note: Xamarin seems to require `libzip4`, yet most distributions only ships `libzip5`. As a dirty workaround, it's possible to symlink `libzip.so.5` to `libzip.so.4`. Luckily, it appears to be working.
- `sudo ln -s /usr/lib/libzip.so.5 /usr/lib/libzip.so.4`
- Install NuGet dependencies:
- `cd src/ && nuget restore KeePass.sln`
- Build:
- Option 1: `cd build-scripts && ./build-all.sh`
- Option 2:
- Build the Java parts: `cd build-scripts/ && ./build-java.sh`
- Build the Xamarin parts: `./build-xamarin.sh`
- Build the signed APK: `./build-apk.sh`
- Enjoy:
- `adb install ../keepass2android/bin/Debug/keepass2android.keepass2android_debug-Signed.apk`

View File

@@ -1,23 +0,0 @@
How to build Keepass2Android
* Overview *
Keepass2Android is a Mono for Android app. This means that you need Xamarin's Mono for Android to build it. However, it also uses several components written in Java, so there are also Android-Studio projects involved. To make things even worse, parts of the keyboard and kdb-library are written in native code.
The current build-scripts assume that the native libraries are already built (they are included in the repo).
To build KP2A from scratch, make sure that you have Xamarin's Mono for Android installed and also install Android Studio. Make sure that both point to the same Android SDK location.
On Windows you can use
cd build-scripts
build-java.bat
build-xamarin.bat
build-java.bat will call gradlew for several Java modules. build-xamarin.bat will first make sure that you have all files at their place. (There is a "secret" file for Dropbox SDK keys which is not in the repo, this is replaced with a dummy file. There are also different Android Manifest files depending on the configuration which is selected by calling the appropriate script.)
* Notes *
- Please don't forget to update the git submodules before building.
- For building the java parts on Windows, it is suggested to keep a short name (e.g. "c:\projects\keepass2android") for the root project directory. Otherwise the Windows path length limit might be hit when building.
- Before building the java parts, make sure you have set the ANDROID_HOME variable or create a local.properties file inside the directories with a gradlew file. It is recommended to use the same SDK location as that of the Xamarin build.

View File

@@ -35,6 +35,12 @@ dependencies {
compile('com.onedrive.sdk:onedrive-sdk-android:1.2.0') {
transitive = false
}
compile 'com.pcloud.sdk:java-core:1.0.1'
compile 'com.pcloud.sdk:android:1.0.1'
compile('com.microsoft.graph:msgraph-sdk-android:1.2.+')
compile ('com.microsoft.identity.client:msal:0.1.+') {
exclude group: 'com.android.support', module: 'appcompat-v7'
}
compile 'com.google.code.gson:gson:2.3.1'
compile 'com.microsoft.services.msa:msa-auth:0.8.6'
compile 'com.microsoft.aad:adal:1.14.0'

View File

@@ -1,15 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="keepass2android.javafilestorage"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
</manifest>
<application>
<activity
android:name=".NotifSlave"
android:label="Keepass2Android"></activity>
</application>
</manifest>

View File

@@ -190,12 +190,14 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase {
String part = parts[parts.length-1];
logDebug("parsing part " + part);
int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP);
String name = "";
if (indexOfSeparator < 0)
{
//seems invalid, but we're very generous here
displayName += "/"+part;
}
String name = part.substring(0, indexOfSeparator);
else
name = part.substring(0, indexOfSeparator);
try {
name = decode(name);
} catch (UnsupportedEncodingException e) {

View File

@@ -132,7 +132,7 @@ public class FileEntry {
public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception;
public String getCurrentFileVersionFast(String path);
public String getCurrentFileVersionFast(String path) throws Exception;
public InputStream openFileForRead(String path) throws Exception;
@@ -157,4 +157,4 @@ public class FileEntry {
public void onActivityResult(FileStorageSetupActivity activity, int requestCode, int resultCode, Intent data);
public void onRequestPermissionsResult(FileStorageSetupActivity activity, int requestCode, String[] permissions, int[] grantResults);
}
}

View File

@@ -0,0 +1,169 @@
package keepass2android.javafilestorage;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
//based on https://github.com/jwise/dumload/blob/master/src/com/joshuawise/dumload/NotifSlave.java
public class NotifSlave extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private void say(String s) {
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
private int _nextdialog = 0;
private Dialog dialog = null;
@Override
protected Dialog onCreateDialog(int id)
{
Log.e("KP2AJ.NotifSlave", "Create for dialog "+(Integer.toString(id)));
if (id != _nextdialog)
return null;
return dialog;
}
private void showDialog(Dialog d)
{
_nextdialog++;
dialog = d;
Log.e("KP2AJ.NotifSlave", "Attempting to show dialog "+(Integer.toString(_nextdialog)));
showDialog(_nextdialog);
}
public void onStart() {
super.onStart();
Intent i = getIntent(); /* i *am* not an intent! */
final Activity thisact = this;
final Messenger m = (Messenger)i.getParcelableExtra("keepass2android.sftp.returnmessenger");
String reqtype = i.getStringExtra("keepass2android.sftp.reqtype");
String prompt = i.getStringExtra("keepass2android.sftp.prompt");
if (prompt == null || reqtype == null || m == null) /* i.e., we got called by a dummy notification */
{
this.finish();
return;
}
if (reqtype.equals("yesno")) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Keepass2Android");
builder.setMessage(prompt);
builder.setCancelable(false);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.e("KP2AJ.NotifSlave", "Responding with a 1.");
try {
Message me = Message.obtain();
me.arg1 = 1;
m.send(me);
} catch (Exception e) {
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
}
dialog.cancel();
thisact.finish();
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Log.e("KP2AJ.NotifSlave", "Responding with a 1.");
try {
Message me = Message.obtain();
me.arg1 = 0;
m.send(me);
} catch (Exception e) {
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
}
dialog.cancel();
thisact.finish();
}
});
AlertDialog alert = builder.create();
showDialog(alert);
} else if (reqtype.equals("message")) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Keepass2Android");
builder.setMessage(prompt);
builder.setCancelable(false);
builder.setNeutralButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
Message me = Message.obtain();
m.send(me);
} catch (Exception e) {
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
}
dialog.cancel();
thisact.finish();
}
});
AlertDialog alert = builder.create();
showDialog(alert);
} /*else if (reqtype.equals("password")) {
final Dialog d = new Dialog(this);
d.setContentView(R.layout.notfif_slave);
d.setTitle("Keepass2Android");
d.setCancelable(false);
TextView text = (TextView) d.findViewById(R.id.prompt);
text.setText(prompt);
Button ok = (Button) d.findViewById(R.id.ok);
ok.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
Message me = Message.obtain();
me.arg1 = 1;
TextView entry = (TextView) d.findViewById(R.id.entry);
Bundle b = new Bundle(1);
b.putString("response", entry.getText().toString());
me.setData(b);
m.send(me);
} catch (Exception e) {
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
}
d.cancel();
thisact.finish();
}
});
Button cancel = (Button) d.findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
Message me = Message.obtain();
me.arg1 = 0;
m.send(me);
} catch (Exception e) {
Log.e("KP2AJ.NotifSlave", "Failed to send a message back to my buddy.");
}
d.cancel();
thisact.finish();
}
});
showDialog(d);
} */else {
Log.e("KP2AJ.NotifSlave", "What's a "+reqtype+"?");
}
}
}

View File

@@ -0,0 +1,486 @@
package keepass2android.javafilestorage;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.microsoft.graph.core.ClientException;
import com.microsoft.graph.core.DefaultClientConfig;
import com.microsoft.graph.core.GraphErrorCodes;
import com.microsoft.graph.extensions.DriveItem;
import com.microsoft.graph.extensions.GraphServiceClient;
import com.microsoft.graph.extensions.IDriveItemCollectionPage;
import com.microsoft.graph.extensions.IDriveItemCollectionRequestBuilder;
import com.microsoft.graph.extensions.IDriveItemRequest;
import com.microsoft.graph.extensions.IDriveItemRequestBuilder;
import com.microsoft.graph.extensions.IGraphServiceClient;
import com.microsoft.identity.client.AuthenticationCallback;
import com.microsoft.identity.client.AuthenticationResult;
import com.microsoft.identity.client.MsalException;
import com.microsoft.identity.client.PublicClientApplication;
import com.microsoft.identity.client.User;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import keepass2android.javafilestorage.onedrive2.GraphServiceClientManager;
/**
* Created by Philipp on 20.11.2016.
*/
public class OneDriveStorage2 extends JavaFileStorageBase
{
PublicClientApplication mPublicClientApp;
final HashMap<String /*userid*/, IGraphServiceClient> mClientByUser = new HashMap<String /*userid*/, IGraphServiceClient>();
private static final String[] scopes = {"openid","offline_access", "https://graph.microsoft.com/Files.ReadWrite","https://graph.microsoft.com/User.Read"};
public OneDriveStorage2(final Activity context, final String clientId) {
mPublicClientApp = new PublicClientApplication(context, clientId);
initAuthenticator(context);
}
@Override
public boolean requiresSetup(String path)
{
return !isConnected(null);
}
@Override
public void startSelectFile(FileStorageSetupInitiatorActivity activity, boolean isForSave, int requestCode) {
initAuthenticator((Activity)activity.getActivity());
String path = getProtocolId()+":///";
Log.d("KP2AJ", "startSelectFile "+path+", connected: "+path);
if (isConnected(null))
{
Intent intent = new Intent();
intent.putExtra(EXTRA_IS_FOR_SAVE, isForSave);
intent.putExtra(EXTRA_PATH, path);
activity.onImmediateResult(requestCode, RESULT_FILECHOOSER_PREPARED, intent);
}
else
{
activity.startSelectFileProcess(path, isForSave, requestCode);
}
}
private boolean isConnected(String path) {
try {
if (tryGetMsGraphClient(path) == null)
try {
final CountDownLatch latch = new CountDownLatch(1);
Log.d("KP2AJ", "trying silent login");
String userId = extractUserId(path);
final MsalException[] _exception = {null};
final AuthenticationResult[] _result = {null};
User user = mPublicClientApp.getUser(userId);
mPublicClientApp.acquireTokenSilentAsync(scopes, user,
new AuthenticationCallback() {
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
_result[0] = authenticationResult;
latch.countDown();
}
@Override
public void onError(MsalException exception) {
_exception[0] = exception;
latch.countDown();
}
@Override
public void onCancel() {
latch.countDown();
}
});
latch.await();
if (_result[0] != null) {
buildClient(_result[0]);
} else if (_exception[0] != null){
_exception[0].printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return tryGetMsGraphClient(path) != null;
}
catch (Exception e)
{
return false;
}
}
private IGraphServiceClient tryGetMsGraphClient(String path) throws Exception
{
String userId = extractUserId(path);
if (mClientByUser.containsKey(userId))
return mClientByUser.get(userId);
return null;
}
private String extractUserId(String path) throws Exception {
String pathWithoutProtocol = removeProtocol(path);
String[] parts = pathWithoutProtocol.split("/",1);
if (parts.length != 2 || ("".equals(parts[0])))
{
throw new Exception("path does not contain user");
}
return parts[0];
}
private void initAuthenticator(Activity activity) {
}
@Override
public void prepareFileUsage(FileStorageSetupInitiatorActivity activity, String path, int requestCode, boolean alwaysReturnSuccess) {
initAuthenticator((Activity)activity.getActivity());
if (isConnected(path))
{
Intent intent = new Intent();
intent.putExtra(EXTRA_PATH, path);
activity.onImmediateResult(requestCode, RESULT_FILEUSAGE_PREPARED, intent);
}
else
{
activity.startFileUsageProcess(path, requestCode, alwaysReturnSuccess);
}
}
@Override
public String getProtocolId() {
return "onedrive";
}
@Override
public void prepareFileUsage(Context appContext, String path) throws UserInteractionRequiredException {
if (!isConnected(null))
{
throw new UserInteractionRequiredException();
}
}
@Override
public void onCreate(FileStorageSetupActivity activity, Bundle savedInstanceState) {
Log.d("KP2AJ", "OnCreate");
}
@Override
public void onResume(final FileStorageSetupActivity activity) {
}
private IGraphServiceClient buildClient(AuthenticationResult authenticationResult) throws InterruptedException {
IGraphServiceClient newClient = new GraphServiceClient.Builder()
.fromConfig(DefaultClientConfig.createWithAuthenticationProvider(new GraphServiceClientManager(authenticationResult.getAccessToken())))
.buildClient();
mClientByUser.put(authenticationResult.getUser().getUserIdentifier(), newClient);
return newClient;
}
String removeProtocol(String path) throws Exception {
if (path == null)
return null;
return path.substring(getProtocolId().length()+3);
}
@Override
public String getDisplayName(String path) {
if (path == null)
return null;
return path;
}
@Override
public String getFilename(String path) throws Exception {
return path.substring(path.lastIndexOf("/")+1);
}
@Override
public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception {
return false;
}
@Override
public String getCurrentFileVersionFast(String path) {
return null;
}
class ClientAndPath
{
public IGraphServiceClient client;
public String oneDrivePath;
public IDriveItemRequestBuilder getPathItem()
{
IDriveItemRequestBuilder pathItem = client.getDrive().getRoot();
if ("".equals(oneDrivePath) == false) {
pathItem = pathItem.getItemWithPath(oneDrivePath);
}
return pathItem;
}
}
@Override
public InputStream openFileForRead(String path) throws Exception {
try {
ClientAndPath clientAndpath = getOneDriveClientAndPath(path);
logDebug("openFileForRead. Path="+path);
InputStream result = clientAndpath.client.getDrive()
.getRoot()
.getItemWithPath(clientAndpath.oneDrivePath)
.getContent()
.buildRequest()
.get();
logDebug("ok");
return result;
}
catch (ClientException e)
{
throw convertException(e);
}
}
private ClientAndPath getOneDriveClientAndPath(String path) throws Exception {
ClientAndPath result = new ClientAndPath();
String pathWithoutProtocol = removeProtocol(path);
String[] parts = pathWithoutProtocol.split("/",2);
if (parts.length != 2 || ("".equals(parts[0])))
{
throw new Exception("path does not contain user");
}
result.client = mClientByUser.get(parts[0]);
result.oneDrivePath = parts[1];
return result;
}
private Exception convertException(ClientException e) {
if (e.isError(GraphErrorCodes.ItemNotFound))
return new FileNotFoundException(e.getMessage());
return e;
}
@Override
public void uploadFile(String path, byte[] data, boolean writeTransactional) throws Exception {
try {
ClientAndPath clientAndPath = getOneDriveClientAndPath(path);
clientAndPath.client.getDrive()
.getRoot()
.getItemWithPath(clientAndPath.oneDrivePath)
.getContent()
.buildRequest()
.put(data);
} catch (ClientException e) {
throw convertException(e);
}
}
@Override
public String createFolder(String parentPath, String newDirName) throws Exception {
throw new Exception("not implemented.");
}
@Override
public String createFilePath(String parentPath, String newFileName) throws Exception {
String path = parentPath;
if (!path.endsWith("/"))
path = path + "/";
path = path + newFileName;
return path;
}
@Override
public List<FileEntry> listFiles(String parentPath) throws Exception {
try {
ArrayList<FileEntry> result = new ArrayList<FileEntry>();
ClientAndPath clientAndPath = getOneDriveClientAndPath(parentPath);
parentPath = clientAndPath.oneDrivePath;
IDriveItemCollectionPage itemsPage = clientAndPath.getPathItem()
.getChildren()
.buildRequest()
.get();
if (parentPath.endsWith("/"))
parentPath = parentPath.substring(0,parentPath.length()-1);
while (true)
{
List<DriveItem> items = itemsPage.getCurrentPage();
if (items.isEmpty())
return result;
for (DriveItem i: items)
{
FileEntry e = getFileEntry(parentPath + "/" + i.name, i);
Log.d("KP2AJ", e.path);
result.add(e);
}
IDriveItemCollectionRequestBuilder nextPageReqBuilder = itemsPage.getNextPage();
if (nextPageReqBuilder == null)
return result;
itemsPage = nextPageReqBuilder.buildRequest().get();
}
} catch (ClientException e) {
throw convertException(e);
}
}
private FileEntry getFileEntry(String path, DriveItem i) {
FileEntry e = new FileEntry();
if (i.size != null)
e.sizeInBytes = i.size;
else if ((i.remoteItem != null) && (i.remoteItem.size != null))
e.sizeInBytes = i.remoteItem.size;
e.displayName = i.name;
e.canRead = e.canWrite = true;
e.path = getProtocolId() +"://"+path;
if (i.lastModifiedDateTime != null)
e.lastModifiedTime = i.lastModifiedDateTime.getTimeInMillis();
else if ((i.remoteItem != null)&&(i.remoteItem.lastModifiedDateTime != null))
e.lastModifiedTime = i.remoteItem.lastModifiedDateTime.getTimeInMillis();
e.isDirectory = (i.folder != null) || ((i.remoteItem != null) && (i.remoteItem.folder != null));
return e;
}
@Override
public FileEntry getFileEntry(String filename) throws Exception {
try {
ClientAndPath clientAndPath = getOneDriveClientAndPath(filename);
IDriveItemRequestBuilder pathItem = clientAndPath.getPathItem();
IDriveItemRequest request = pathItem.buildRequest();
DriveItem item = request.get();
return getFileEntry(filename, item);
} catch (ClientException e) {
throw convertException(e);
}
}
@Override
public void delete(String path) throws Exception {
try {
ClientAndPath clientAndPath = getOneDriveClientAndPath(path);
clientAndPath.client.getDrive()
.getRoot()
.getItemWithPath(clientAndPath.oneDrivePath)
.buildRequest()
.delete();
} catch (ClientException e) {
throw convertException(e);
}
}
boolean acquireTokenRunning = false;
@Override
public void onStart(final FileStorageSetupActivity activity) {
Log.d("KP2AJ", "onStart " + activity.getPath());
if (activity.getProcessName().equals(PROCESS_NAME_SELECTFILE))
activity.getState().putString(EXTRA_PATH, activity.getPath());
String userId = activity.getState().getString("OneDriveUser");
if (mClientByUser.containsKey(userId)) {
finishActivityWithSuccess(activity);
return;
}
JavaFileStorage.FileStorageSetupActivity storageSetupAct = activity;
final CountDownLatch latch = new CountDownLatch(1);
final AuthenticationResult[] _authenticationResult = {null};
MsalException _exception[] = {null};
if (!acquireTokenRunning) {
acquireTokenRunning = true;
mPublicClientApp.acquireToken((Activity) activity, scopes, new AuthenticationCallback() {
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
Log.i(TAG, "authenticating successful");
try {
buildClient(authenticationResult);
} catch (InterruptedException e) {
e.printStackTrace();
}
activity.getState().putString(EXTRA_PATH, getProtocolPrefix() + authenticationResult.getUser().getUserIdentifier() + "/");
finishActivityWithSuccess(activity);
acquireTokenRunning = false;
return;
}
@Override
public void onError(MsalException exception) {
Log.i(TAG, "authenticating not successful");
Intent data = new Intent();
data.putExtra(EXTRA_ERROR_MESSAGE, "authenticating not successful");
((Activity) activity).setResult(Activity.RESULT_CANCELED, data);
((Activity) activity).finish();
acquireTokenRunning = false;
}
@Override
public void onCancel() {
Log.i(TAG, "authenticating cancelled");
Intent data = new Intent();
data.putExtra(EXTRA_ERROR_MESSAGE, "authenticating not cancelled");
((Activity) activity).setResult(Activity.RESULT_CANCELED, data);
((Activity) activity).finish();
acquireTokenRunning = false;
}
});
}
}
@Override
public void onActivityResult(FileStorageSetupActivity activity, int requestCode, int resultCode, Intent data) {
mPublicClientApp.handleInteractiveRequestRedirect(requestCode, resultCode, data);
}
}

View File

@@ -0,0 +1,407 @@
package keepass2android.javafilestorage;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.regex.Pattern;
import com.pcloud.sdk.ApiClient;
import com.pcloud.sdk.ApiError;
import com.pcloud.sdk.Authenticators;
import com.pcloud.sdk.AuthorizationActivity;
import com.pcloud.sdk.AuthorizationResult;
import com.pcloud.sdk.Call;
import com.pcloud.sdk.DataSource;
import com.pcloud.sdk.PCloudSdk;
import com.pcloud.sdk.RemoteEntry;
import com.pcloud.sdk.RemoteFile;
import com.pcloud.sdk.RemoteFolder;
/**
* FileStorage implementation for PCloud provider.
* https://www.pcloud.com/
*/
public class PCloudFileStorage extends JavaFileStorageBase
{
final static private int PCLOUD_AUTHORIZATION_REQUEST_CODE = 1001845497;
final static private String SHARED_PREF_NAME = "PCLOUD";
final static private String SHARED_PREF_AUTH_TOKEN = "AUTH_TOKEN";
private final Context ctx;
private ApiClient apiClient;
private String clientId;
public PCloudFileStorage(Context ctx, String clientId) {
this.ctx = ctx;
this.clientId = clientId;
this.apiClient = createApiClientFromSharedPrefs();
}
@Override
public boolean requiresSetup(String path) {
return !this.isConnected();
}
@Override
public void startSelectFile(FileStorageSetupInitiatorActivity activity, boolean isForSave, int requestCode) {
String path = getProtocolId() + "://";
activity.startSelectFileProcess(path, isForSave, requestCode);
}
@Override
public void prepareFileUsage(Context appContext, String path) throws Throwable {
if (!isConnected()) {
throw new UserInteractionRequiredException();
}
}
@Override
public void prepareFileUsage(FileStorageSetupInitiatorActivity activity, String path, int requestCode,
boolean alwaysReturnSuccess) {
if (this.isConnected()) {
Intent intent = new Intent();
intent.putExtra(EXTRA_PATH, path);
activity.onImmediateResult(requestCode, RESULT_FILEUSAGE_PREPARED, intent);
} else {
activity.startFileUsageProcess(path, requestCode, alwaysReturnSuccess);
}
}
@Override
public String getProtocolId() {
return "pcloud";
}
@Override
public String getDisplayName(String path) {
return path;
}
@Override
public String getFilename(String path) {
return path.substring(path.lastIndexOf("/") + 1);
}
@Override
public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception {
if (previousFileVersion == null || "".equals(previousFileVersion)) {
return false;
}
path = this.cleanPath(path);
RemoteFile remoteFile = this.getRemoteFileByPath(path);
return !remoteFile.hash().equals(previousFileVersion);
}
@Override
public String getCurrentFileVersionFast(String path) throws Exception {
path = this.cleanPath(path);
RemoteFile remoteFile = this.getRemoteFileByPath(path);
return remoteFile.hash();
}
@Override
public InputStream openFileForRead(String path) throws Exception {
path = this.cleanPath(path);
RemoteFile remoteFile = this.getRemoteFileByPath(path);
return remoteFile.byteStream();
}
@Override
public void uploadFile(String path, byte[] data, boolean writeTransactional) throws Exception {
path = this.cleanPath(path);
DataSource dataSource = DataSource.create(data);
String filename = path.substring(path.lastIndexOf("/") + 1);
String filePath = path.substring(0, path.lastIndexOf("/") + 1);
RemoteFolder remoteFolder = this.getRemoteFolderByPath(filePath);
String tempName = "." + UUID.randomUUID().toString();
try {
RemoteFile remoteFile = this.apiClient.createFile(remoteFolder, tempName, dataSource).execute();
this.apiClient.rename(remoteFile, filename).execute();
} catch (ApiError e) {
throw convertApiError(e);
}
}
@Override
public String createFolder(String parentPath, String newDirName) throws Exception {
String parentPathWithoutProtocol = this.cleanPath(parentPath);
RemoteFolder remoteFolder = this.getRemoteFolderByPath(parentPathWithoutProtocol);
try {
this.apiClient.createFolder(remoteFolder, newDirName).execute();
} catch (ApiError e) {
throw convertApiError(e);
}
return this.createFilePath(parentPath, newDirName);
}
@Override
public String createFilePath(String parentPath, String newFileName) throws Exception {
return (
this.getProtocolId() + "://" +
this.cleanPath(parentPath) +
("".equals(newFileName) ? "" : "/") +
newFileName
);
}
@Override
public List<FileEntry> listFiles(String parentPath) throws Exception {
parentPath = this.cleanPath(parentPath);
ArrayList<FileEntry> fileEntries = new ArrayList<>();
RemoteFolder remoteFolder = this.getRemoteFolderByPath(parentPath);
for (RemoteEntry remoteEntry : remoteFolder.children()) {
fileEntries.add(this.convertRemoteEntryToFileEntry(remoteEntry, parentPath));
}
return fileEntries;
}
@Override
public FileEntry getFileEntry(String path) throws Exception {
path = this.cleanPath(path);
RemoteEntry remoteEntry = this.getRemoteEntryByPath(path);
return this.convertRemoteEntryToFileEntry(
remoteEntry,
path.substring(0, path.lastIndexOf("/"))
);
}
@Override
public void delete(String path) throws Exception {
path = this.cleanPath(path);
RemoteEntry remoteEntry = this.getRemoteFileByPath(path);
try {
this.apiClient.delete(remoteEntry).execute();
} catch (ApiError e) {
throw convertApiError(e);
}
}
@Override
public void onCreate(FileStorageSetupActivity activity, Bundle savedInstanceState) {
}
@Override
public void onResume(FileStorageSetupActivity activity) {
if (activity.getProcessName().equals(PROCESS_NAME_SELECTFILE)) {
activity.getState().putString(EXTRA_PATH, activity.getPath());
}
if (this.isConnected()) {
finishActivityWithSuccess(activity);
} else if (!activity.getState().getBoolean("hasStartedAuth", false)) {
Activity castedActivity = (Activity)activity;
Intent authIntent = AuthorizationActivity.createIntent(castedActivity, this.clientId);
castedActivity.startActivityForResult(authIntent, PCLOUD_AUTHORIZATION_REQUEST_CODE);
activity.getState().putBoolean("hasStartedAuth", true);
}
}
@Override
public void onActivityResult(FileStorageSetupActivity activity, int requestCode, int resultCode, Intent data) {
if (requestCode == PCLOUD_AUTHORIZATION_REQUEST_CODE && data != null) {
activity.getState().putBoolean("hasStartedAuth", false);
AuthorizationResult result = (AuthorizationResult)(
data.getSerializableExtra(AuthorizationActivity.KEY_AUTHORIZATION_RESULT)
);
this.handleAuthResult(activity, result, data);
}
}
private void handleAuthResult(FileStorageSetupActivity activity, AuthorizationResult authorizationResult,
Intent data) {
if (authorizationResult == AuthorizationResult.ACCESS_GRANTED) {
String authToken = data.getStringExtra(AuthorizationActivity.KEY_ACCESS_TOKEN);
setAuthToken(authToken);
finishActivityWithSuccess(activity);
} else {
Activity castedActivity = (Activity)activity;
Intent resultData = new Intent();
resultData.putExtra(EXTRA_ERROR_MESSAGE, "Authentication failed.");
castedActivity.setResult(Activity.RESULT_CANCELED, resultData);
castedActivity.finish();
}
}
@Override
public void onStart(FileStorageSetupActivity activity) {
}
private ApiClient createApiClientFromSharedPrefs() {
SharedPreferences prefs = this.ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
String authToken = prefs.getString(SHARED_PREF_AUTH_TOKEN, null);
return this.createApiClient(authToken);
}
private ApiClient createApiClient(String authToken) {
if (authToken == null) {
return null;
}
return (
PCloudSdk.newClientBuilder()
.authenticator(Authenticators.newOAuthAuthenticator(authToken))
.create()
);
}
private boolean isConnected() {
return (this.apiClient != null);
}
private void clearAuthToken() {
this.apiClient = null;
SharedPreferences prefs = this.ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.clear();
edit.apply();
}
private void setAuthToken(String authToken) {
this.apiClient = this.createApiClient(authToken);
SharedPreferences prefs = this.ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putString(SHARED_PREF_AUTH_TOKEN, authToken);
edit.apply();
}
private String cleanPath(String path) {
return (
"/" + path.replaceAll("^(" + Pattern.quote(this.getProtocolId()) + "://)?/*", "")
);
}
private RemoteFile getRemoteFileByPath(String path) throws Exception {
RemoteEntry remoteEntry = this.getRemoteEntryByPath(path);
try {
return remoteEntry.asFile();
} catch (IllegalStateException e) {
throw new FileNotFoundException(e.toString());
}
}
private RemoteFolder getRemoteFolderByPath(String path) throws Exception {
RemoteEntry remoteEntry = this.getRemoteEntryByPath(path);
try {
return remoteEntry.asFolder();
} catch (IllegalStateException e) {
throw new FileNotFoundException(e.toString());
}
}
private RemoteEntry getRemoteEntryByPath(String path) throws Exception {
Call<RemoteFolder> call = this.apiClient.listFolder(RemoteFolder.ROOT_FOLDER_ID, true);
RemoteFolder folder;
try {
folder = call.execute();
} catch (ApiError apiError) {
throw convertApiError(apiError);
}
if ("/".equals(path)) {
return folder;
}
String[] fileNames = path.substring(1).split("/");
RemoteFolder currentFolder = folder;
Iterator<String> fileNamesIterator = Arrays.asList(fileNames).iterator();
while (true) {
String fileName = fileNamesIterator.next();
Iterator<RemoteEntry> entryIterator = currentFolder.children().iterator();
while (true) {
RemoteEntry remoteEntry;
try {
remoteEntry = entryIterator.next();
} catch (NoSuchElementException e) {
throw new FileNotFoundException(e.toString());
}
if (currentFolder.folderId() == remoteEntry.parentFolderId() && fileName.equals(remoteEntry.name())) {
if (!fileNamesIterator.hasNext()) {
return remoteEntry;
}
try {
currentFolder = remoteEntry.asFolder();
} catch (IllegalStateException e) {
throw new FileNotFoundException(e.toString());
}
break;
}
}
}
}
private Exception convertApiError(ApiError e) {
String strErrorCode = String.valueOf(e.errorCode());
if (strErrorCode.startsWith("1") || "2000".equals(strErrorCode) || "2095".equals(strErrorCode)) {
this.clearAuthToken();
return new UserInteractionRequiredException("Unlinked from PCloud! User must re-link.", e);
} else if (strErrorCode.startsWith("2")) {
return new FileNotFoundException(e.toString());
}
return e;
}
private FileEntry convertRemoteEntryToFileEntry(RemoteEntry remoteEntry, String parentPath) {
FileEntry fileEntry = new FileEntry();
fileEntry.canRead = true;
fileEntry.canWrite = true;
fileEntry.path = (
this.getProtocolId() + "://" +
("/".equals(parentPath) ? "" : parentPath) +
"/" + remoteEntry.name()
);
fileEntry.displayName = remoteEntry.name();
fileEntry.isDirectory = !remoteEntry.isFile();
fileEntry.lastModifiedTime = remoteEntry.lastModified().getTime();
if (remoteEntry.isFile()) {
fileEntry.sizeInBytes = remoteEntry.asFile().size();
}
return fileEntry;
}
}

View File

@@ -2,7 +2,9 @@ package keepass2android.javafilestorage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
@@ -13,6 +15,7 @@ import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.KeyPair;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
@@ -35,8 +38,10 @@ public class SftpStorage extends JavaFileStorageBase {
public String localPath;
public int port;
}
Context _appContext;
public SftpStorage() {
public SftpStorage(Context appContext) {
_appContext = appContext;
}
@@ -318,12 +323,28 @@ public class SftpStorage extends JavaFileStorageBase {
jsch = new JSch();
ConnectionInfo ci = splitStringToConnectionInfo(filename);
String base_dir = getBaseDir();
jsch.setKnownHosts(base_dir + "/known_hosts");
String key_filename = getKeyFileName();
try{
createKeyPair(key_filename);
} catch (Exception ex) {
System.out.println(ex);
}
try {
jsch.addIdentity(key_filename);
} catch (java.lang.Exception e)
{
}
Session session = jsch.getSession(ci.username, ci.host, ci.port);
UserInfo ui = new SftpUserInfo(ci.password);
UserInfo ui = new SftpUserInfo(ci.password,_appContext);
session.setUserInfo(ui);
session.setConfig("PreferredAuthentications",
"password,publickey");
session.setConfig("PreferredAuthentications", "publickey,password");
session.connect();
@@ -336,6 +357,35 @@ public class SftpStorage extends JavaFileStorageBase {
}
private String getBaseDir() {
return _appContext.getFilesDir().getAbsolutePath();
}
private String getKeyFileName() {
return getBaseDir() + "/id_kp2a_rsa";
}
public String createKeyPair() throws IOException, JSchException {
return createKeyPair(getKeyFileName());
}
private String createKeyPair(String key_filename) throws JSchException, IOException {
String public_key_filename = key_filename + ".pub";
File file = new File(key_filename);
if (file.exists())
return public_key_filename;
int type = KeyPair.RSA;
KeyPair kpair = KeyPair.genKeyPair(jsch, type, 2048);
kpair.writePrivateKey(key_filename);
kpair.writePublicKey(public_key_filename, "generated by Keepass2Android");
//ret = "Fingerprint: " + kpair.getFingerPrint();
kpair.dispose();
return public_key_filename;
}
public ConnectionInfo splitStringToConnectionInfo(String filename)
throws UnsupportedEncodingException {
ConnectionInfo ci = new ConnectionInfo();

View File

@@ -1,14 +1,119 @@
package keepass2android.javafilestorage;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.jcraft.jsch.UserInfo;
public class SftpUserInfo implements UserInfo {
private Object /* pick one type, and fixate on it */ dance(final String type, final String text) /* for inside the thread */
{
final Message msg = Message.obtain();
/* t(*A*t) */
Thread t = new Thread() {
public void run() {
Looper.prepare();
int bogon = (int)SystemClock.elapsedRealtime();
NotificationManager mNotificationManager = (NotificationManager)_appContext.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(_appContext);
builder.setContentText("SFTP prompt");
builder.setSmallIcon(R.drawable.ic_logo_green_foreground);
Handler h = new Handler() {
public void handleMessage(Message M) {
msg.copyFrom(M);
Looper.myLooper().quit();
}
};
Messenger m = new Messenger(h);
Intent intent = new Intent(_appContext, NotifSlave.class);
intent.setAction("keepass2android.sftp.NotifSlave");
intent.putExtra("keepass2android.sftp.returnmessenger", m);
intent.putExtra("keepass2android.sftp.reqtype", type);
intent.putExtra("keepass2android.sftp.prompt", text);
intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
PendingIntent contentIntent = PendingIntent.getActivity(_appContext, 0, intent, 0);
builder.setContentIntent(contentIntent);
{
Intent directIntent = new Intent(_appContext, NotifSlave.class);
directIntent.setAction("keepass2android.sftp.NotifSlave");
directIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
directIntent.putExtra("keepass2android.sftp.returnmessenger", m);
directIntent.putExtra("keepass2android.sftp.reqtype", type);
directIntent.putExtra("keepass2android.sftp.prompt", text);
directIntent.setData((Uri.parse("suckit://" + SystemClock.elapsedRealtime())));
_appContext.startActivity(directIntent);
}
Log.e("KP2AJFS[thread]", "Notifying...");
mNotificationManager.notify(bogon, builder.build());
Log.e("KP2AJFS[thread]", "About to go to 'sleep'...");
Looper.loop();
Log.e("KP2AJFS[thread]", "And we're alive!");
Log.e("KP2AJFS[thread]", "result was: "+(Integer.toString(msg.arg1)));
mNotificationManager.cancel(bogon);
}
};
t.start();
try {
t.join();
} catch (Exception e) {
return null;
}
if (type.equals("yesno"))
return new Boolean(msg.arg1 == 1);
else if (type.equals("message"))
return null;
else if (type.equals("password")) {
if (msg.arg1 == 0)
return null;
Bundle b = msg.getData();
return b.getString("response");
} else
return null;
}
Context _appContext;
String _password;
public SftpUserInfo(String password) {
public SftpUserInfo(String password, Context appContext)
{
_password = password;
_appContext = appContext;
}
@Override
@@ -35,12 +140,15 @@ public class SftpUserInfo implements UserInfo {
@Override
public boolean promptYesNo(String message) {
return true; //continue all operations without user action
return (Boolean)dance("yesno", message);
//test with https://www.sftp.net/public-online-sftp-servers?
}
@Override
public void showMessage(String message) {
Log.d("KP2AJ", message);
public void showMessage(String message)
{
dance("message", message);
}
}

View File

@@ -29,6 +29,7 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
@@ -70,9 +71,18 @@ public class WebDavStorage extends JavaFileStorageBase {
String scheme = filename.substring(0, filename.indexOf("://"));
filename = filename.substring(scheme.length() + 3);
String userPwd = filename.substring(0, filename.indexOf('@'));
ci.username = decode(userPwd.substring(0, userPwd.indexOf(":")));
ci.password = decode(userPwd.substring(userPwd.indexOf(":") + 1));
int idxAt = filename.indexOf('@');
if (idxAt >= 0)
{
String userPwd = filename.substring(0, idxAt);
int idxColon = userPwd.indexOf(":");
if (idxColon >= 0);
{
ci.username = decode(userPwd.substring(0, idxColon));
ci.password = decode(userPwd.substring(idxColon + 1));
}
}
ci.URL = scheme + "://" +filename.substring(filename.indexOf('@') + 1);
return ci;
}
@@ -149,13 +159,19 @@ public class WebDavStorage extends JavaFileStorageBase {
sslContext.init(null, new TrustManager[] { trustManager }, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
builder = builder.sslSocketFactory(sslSocketFactory, trustManager)
.hostnameVerifier(new DecoratedHostnameVerifier(OkHostnameVerifier.INSTANCE, mCertificateErrorHandler));
builder.connectTimeout(25, TimeUnit.SECONDS);
builder.readTimeout(25, TimeUnit.SECONDS);
builder.writeTimeout(25, TimeUnit.SECONDS);
}
OkHttpClient client = builder.build();
return client;
}

View File

@@ -0,0 +1,45 @@
package keepass2android.javafilestorage.onedrive2;
import com.microsoft.graph.authentication.IAuthenticationProvider;
import com.microsoft.graph.core.DefaultClientConfig;
import com.microsoft.graph.core.IClientConfig;
import com.microsoft.graph.extensions.GraphServiceClient;
import com.microsoft.graph.extensions.IGraphServiceClient;
import com.microsoft.graph.http.IHttpRequest;
/**
* Singleton class that manages a GraphServiceClient object.
* It implements IAuthentication provider to authenticate requests using an access token.
*/
public class GraphServiceClientManager implements IAuthenticationProvider {
private IGraphServiceClient mGraphServiceClient;
private String mAccessToken;
public GraphServiceClientManager(String accessToken) {
mAccessToken = accessToken;
}
@Override
public void authenticateRequest(IHttpRequest request) {
try {
request.addHeader("Authorization", "Bearer " + mAccessToken);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
public synchronized IGraphServiceClient getGraphServiceClient() {
return getGraphServiceClient(this);
}
public synchronized IGraphServiceClient getGraphServiceClient(IAuthenticationProvider authenticationProvider) {
if (mGraphServiceClient == null) {
IClientConfig clientConfig = DefaultClientConfig.createWithAuthenticationProvider(
authenticationProvider
);
mGraphServiceClient = new GraphServiceClient.Builder().fromConfig(clientConfig).buildClient();
}
return mGraphServiceClient;
}
}

View File

@@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="800.0"
android:viewportWidth="800.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffff" android:fillType="evenOdd" android:pathData="m318.7,232c13.6,0 24.6,10.9 24.6,24.4 0,13.5 -11,24.4 -24.6,24.4 -13.6,0 -24.6,-10.9 -24.6,-24.4 0,-13.5 11,-24.4 24.6,-24.4zM453.5,256.4c0,13.5 11,24.4 24.6,24.4 13.6,0 24.6,-10.9 24.6,-24.4 0,-13.5 -11,-24.4 -24.6,-24.4 -13.6,0 -24.6,10.9 -24.6,24.4zM399.8,177.7M140.2,600.6v47h517.3v-47zM140.2,350.9v47h517.3v-47zM140.1,481.2h191.8c-0.8,-4.1 -1.2,-8.3 -1.2,-12.4 0,-12.4 3.4,-24.2 9.9,-34.6L140.1,434.2ZM657.5,481.2v-47L454.9,434.2c6.5,10.4 9.8,22.2 9.8,34.6 0,4.1 -0.4,8.3 -1.2,12.4zM140.1,517.4v47h186.6l14.3,-47zM454.3,517.4 L468.7,564.4h188.8v-47zM432.7,565.8 L411.7,496.9 414.4,495.3c10.3,-5.9 16.7,-16.9 16.7,-28.6 0,-18.2 -15,-33 -33.3,-33 -18.3,0 -33.3,14.8 -33.3,33 0,11.8 6.4,22.7 16.7,28.6l2.7,1.6 -21.1,68.9zM507.5,158.5 L507.7,158.2 543.3,106.9c2.4,-3.5 1.8,-8.1 -1.4,-10.3 -3.2,-2.2 -7.7,-1.1 -10.2,2.4l-37.2,53.5 -0.1,0.3c-29.3,-11.8 -62.1,-18.5 -96.8,-18.5 -35.2,0 -68.5,6.9 -98.1,19L261.8,99c-2.4,-3.5 -7,-4.6 -10.2,-2.4 -3.2,2.2 -3.8,6.8 -1.4,10.3l36.2,52.2c-66.8,32.2 -111.9,92.4 -111.9,161.3h42.9c0,-79.1 80.8,-143.5 180.1,-143.5 99.3,0 180.1,64.3 180.1,143.5h42.9c0.2,-69.3 -45.4,-129.8 -113,-161.9z"/>
</vector>

0
src/java/JavaFileStorage/gradlew vendored Normal file → Executable file
View File

View File

@@ -10,6 +10,8 @@ android {
targetSdkVersion 23
versionCode 1
versionName "1.0"
multiDexEnabled true
}
buildTypes {

View File

@@ -59,6 +59,18 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.microsoft.identity.client.BrowserTabActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/msalPrefix"
android:host="auth" />
</intent-filter>
</activity>
</application>
@@ -68,6 +80,8 @@
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>

View File

@@ -89,6 +89,8 @@ extends Activity implements JavaFileStorage.FileStorageSetupActivity {
@Override
public String getPath() {
// TODO Auto-generated method stub
if (getState().containsKey(JavaFileStorage.EXTRA_PATH))
return getState().getString(JavaFileStorage.EXTRA_PATH);
return getIntent().getStringExtra(JavaFileStorage.EXTRA_PATH);
}

View File

@@ -135,17 +135,19 @@ package com.crocoapps.javafilestoragetest;
import group.pals.android.lib.ui.filechooser.FileChooserActivity;
import group.pals.android.lib.ui.filechooser.providers.BaseFileProviderUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
//import keepass2android.javafilestorage.DropboxCloudRailStorage;
import keepass2android.javafilestorage.DropboxV2Storage;
import keepass2android.javafilestorage.ICertificateErrorHandler;
import keepass2android.javafilestorage.JavaFileStorage;
import keepass2android.javafilestorage.JavaFileStorage.FileEntry;
import keepass2android.javafilestorage.OneDriveStorage;
import keepass2android.javafilestorage.OneDriveStorage2;
import keepass2android.javafilestorage.SftpStorage;
import keepass2android.javafilestorage.UserInteractionRequiredException;
import keepass2android.javafilestorage.WebDavStorage;
@@ -201,10 +203,17 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
}
catch (Exception e)
{
Log.d("KP2AJ",e.toString());
//if exception because folder exists
path = fs.createFilePath(parentPath, testPath);
}
String textToUpload2 = "abcdefg";
String filename2 = fs.createFilePath(parentPath, "file.txt");
/*if (!path.endsWith("/"))
path += "/";
String filename = path+"file.text";*/
fs.uploadFile(filename2,textToUpload2.getBytes(),true);
FileEntry e1 = fs.getFileEntry(parentPath);
FileEntry e2 = fs.getFileEntry(path);
@@ -526,9 +535,11 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
}
static JavaFileStorage createStorageToTest(Context ctx, Context appContext, boolean simulateRestart) {
//storageToTest = new SftpStorage();
//storageToTest = new SftpStorage(ctx.getApplicationContext());
//storageToTest = new SkyDriveFileStorage("000000004010C234", appContext);
storageToTest = new OneDriveStorage(appContext, "000000004010C234");
storageToTest = new OneDriveStorage2((Activity) ctx, "8374f801-0f55-407d-80cc-9a04fe86d9b2");
//storageToTest = new GoogleDriveFileStorage();
/*storageToTest = new WebDavStorage(new ICertificateErrorHandler() {
@Override
@@ -615,7 +626,7 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
Toast.makeText(this, "requestCode: "+requestCode, Toast.LENGTH_LONG).show();
if (requestCode == 1)
//new PerformTestTask().execute(path,"TestFileStorage<67>", storageToTest); //use an umlaut to see how that works
new PerformTestTask().execute(path,"TestFileStorage", storageToTest);
new PerformTestTask().execute(path,"TestFileStorage", storageToTest);
else
if (requestCode == 2)
{
@@ -662,6 +673,20 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
return this;
}
public static String readStream(InputStream is) {
StringBuilder sb = new StringBuilder(512);
try {
Reader r = new InputStreamReader(is, "UTF-8");
int c = 0;
while ((c = r.read()) != -1) {
sb.append((char) c);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return sb.toString();
}
@Override
public void performManualFileSelect(boolean isForSave, final int requestCode,
String protocolId)
@@ -669,6 +694,30 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag
if (protocolId.equals("sftp"))
{
final View view = getLayoutInflater().inflate(R.layout.sftp_credentials, null);
view.findViewById(R.id.send_public_key).setOnClickListener(v -> {
Intent sendIntent = new Intent();
SftpStorage sftpStorage = (SftpStorage)storageToTest;
try {
String pub_filename = sftpStorage.createKeyPair();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, readStream(new FileInputStream(pub_filename)));
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Keepass2Android sftp public key");
sendIntent.setType("text/plain");
this.startActivity(Intent.createChooser(sendIntent, "Send public key to..."));
}
catch (Exception ex)
{
Toast.makeText(this,"Failed to create key pair: " + ex.getMessage(), Toast.LENGTH_LONG);
return;
}
});
new AlertDialog.Builder(this)
.setView(view)
.setTitle("Enter SFTP credentials")

View File

@@ -63,6 +63,9 @@
android:singleLine="true"
android:text="/home/philipp"
/>
<Button android:id="@+id/send_public_key"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="send public key" />
</LinearLayout>

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