Compare commits
975 Commits
1.04b
...
Branch_b0f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0ce77a2729 | ||
![]() |
b0f61038e3 | ||
![]() |
d0749324c9 | ||
![]() |
a43f72d18a | ||
![]() |
3d691088be | ||
![]() |
bca3becadb | ||
![]() |
d937fbe7ad | ||
![]() |
c13e00871d | ||
![]() |
b5b716da4c | ||
![]() |
45d2a8e0b2 | ||
![]() |
d47c948699 | ||
![]() |
fdf36babba | ||
![]() |
d47411264e | ||
![]() |
b9ebad7942 | ||
![]() |
2878cc1cb5 | ||
![]() |
9277d76f37 | ||
![]() |
b7b1301334 | ||
![]() |
954dd73ffa | ||
![]() |
7aeab98c5b | ||
![]() |
51123d60d3 | ||
![]() |
395d4b5a97 | ||
![]() |
654f025f64 | ||
![]() |
8a9ccea5d3 | ||
![]() |
92e00075c6 | ||
![]() |
624e78e734 | ||
![]() |
76bb8822fa | ||
![]() |
e3cba097fa | ||
![]() |
c812fca8c1 | ||
![]() |
f86f4ee18c | ||
![]() |
dafed9786e | ||
![]() |
cd3a119053 | ||
![]() |
f143a171aa | ||
![]() |
ee93d7df82 | ||
![]() |
61a3bcc53d | ||
![]() |
17a46eb92c | ||
![]() |
14b121a8ba | ||
![]() |
41b57417e5 | ||
![]() |
bb492c3043 | ||
![]() |
b683dca67c | ||
![]() |
b6e6024bda | ||
![]() |
2b3a95e21d | ||
![]() |
de9c27f1f5 | ||
![]() |
85c9cb26b1 | ||
![]() |
8ffa27e93d | ||
![]() |
ea743fc2c5 | ||
![]() |
7fab9aab00 | ||
![]() |
444e224d41 | ||
![]() |
9fde19f1ce | ||
![]() |
4e085b5dca | ||
![]() |
06ab58cc07 | ||
![]() |
9dae1746ec | ||
![]() |
db87191f1f | ||
![]() |
76abe79b6d | ||
![]() |
970bc29e01 | ||
![]() |
79a3262659 | ||
![]() |
3add6d64ef | ||
![]() |
43168b18d1 | ||
![]() |
6970b42456 | ||
![]() |
a545b96601 | ||
![]() |
59b66409e8 | ||
![]() |
25c50bbcaf | ||
![]() |
a9a5df00d2 | ||
![]() |
5f4d9c29dc | ||
![]() |
31e158e39b | ||
![]() |
25af5844be | ||
![]() |
f79bb49af1 | ||
![]() |
2756bae656 | ||
![]() |
b574b55f84 | ||
![]() |
76ef1c4033 | ||
![]() |
409deaee9d | ||
![]() |
8396e18283 | ||
![]() |
5e952e06ff | ||
![]() |
7b6dc3d773 | ||
![]() |
1759b67921 | ||
![]() |
1307b0e5d1 | ||
![]() |
c1af6994bf | ||
![]() |
d09c15e5b8 | ||
![]() |
ea98b170d9 | ||
![]() |
c67f4e45c7 | ||
![]() |
c21a5afe94 | ||
![]() |
49de16f0f3 | ||
![]() |
6d60afadf4 | ||
![]() |
c6751af075 | ||
![]() |
d41aa389a7 | ||
![]() |
f95986fd7a | ||
![]() |
ac522bce43 | ||
![]() |
6e0729c3b3 | ||
![]() |
9ce674da2b | ||
![]() |
da8a8e7e77 | ||
![]() |
566a1088bd | ||
![]() |
11f1f07653 | ||
![]() |
45194bb26f | ||
![]() |
1f6440189f | ||
![]() |
60e98d87d8 | ||
![]() |
f560124088 | ||
![]() |
7521d0b787 | ||
![]() |
c45e52f571 | ||
![]() |
275920e5be | ||
![]() |
7045c6ee8d | ||
![]() |
7a7b65e8c6 | ||
![]() |
261526b4d1 | ||
![]() |
bc74c91a2c | ||
![]() |
ab47543df0 | ||
![]() |
3a601468a9 | ||
![]() |
f2002e2b90 | ||
![]() |
29031167d6 | ||
![]() |
7305ac47c3 | ||
![]() |
2aec6c9e4b | ||
![]() |
5a2cdf3cda | ||
![]() |
a943df63fc | ||
![]() |
ca771abebe | ||
![]() |
010db6148d | ||
![]() |
8f065f480c | ||
![]() |
f163f9382f | ||
![]() |
e752244b5f | ||
![]() |
4bbb958a05 | ||
![]() |
d1ddfed8dd | ||
![]() |
bdb39f203a | ||
![]() |
1bcb6aabe7 | ||
![]() |
90b09b0f7e | ||
![]() |
4e6e0a0e73 | ||
![]() |
ad4c764adb | ||
![]() |
2265432ec4 | ||
![]() |
bb45e60a3f | ||
![]() |
b1ff92d63e | ||
![]() |
016864edfc | ||
![]() |
dc5133e676 | ||
![]() |
1fbd10c918 | ||
![]() |
4cd219ab32 | ||
![]() |
871e84fec9 | ||
![]() |
08ce132587 | ||
![]() |
4c58d8df72 | ||
![]() |
bf554d2417 | ||
![]() |
631cd8e35f | ||
![]() |
f46c4d8054 | ||
![]() |
0010713b78 | ||
![]() |
f5bfd4f8f2 | ||
![]() |
6d04d2f579 | ||
![]() |
0d3cef1626 | ||
![]() |
4d251becb0 | ||
![]() |
372d4c4bf3 | ||
![]() |
2dbda89973 | ||
![]() |
2f55bbddd8 | ||
![]() |
928773b183 | ||
![]() |
bc9803cbc4 | ||
![]() |
fca8f5efbc | ||
![]() |
f09fe4f7e2 | ||
![]() |
de3bc0ff6c | ||
![]() |
c4a1b6a82e | ||
![]() |
bd08dd54e2 | ||
![]() |
b1f93fdb75 | ||
![]() |
51599b3f1a | ||
![]() |
1b753877a9 | ||
![]() |
d33ffa9d22 | ||
![]() |
df710e523a | ||
![]() |
7d218e0706 | ||
![]() |
88127a4858 | ||
![]() |
63f2a6f902 | ||
![]() |
d8286eb639 | ||
![]() |
668fa46a98 | ||
![]() |
e16a671a26 | ||
![]() |
7f89ef358c | ||
![]() |
e0df319279 | ||
![]() |
61c7a260b4 | ||
![]() |
f26fce63ad | ||
![]() |
74c3c96b43 | ||
![]() |
765b020152 | ||
![]() |
59c05235f6 | ||
![]() |
92a4131c88 | ||
![]() |
540e14bbe7 | ||
![]() |
0ebd355edd | ||
![]() |
68d4dfed04 | ||
![]() |
37a482d2e4 | ||
![]() |
b79cc65728 | ||
![]() |
78977c7e31 | ||
![]() |
1957fc5345 | ||
![]() |
49cefff75d | ||
![]() |
2ebb145b7b | ||
![]() |
0a6f1394e4 | ||
![]() |
1310913281 | ||
![]() |
c245c5ade3 | ||
![]() |
9e6f45a59b | ||
![]() |
f6a78c8890 | ||
![]() |
76717fa3cb | ||
![]() |
a19230393d | ||
![]() |
0b89969a33 | ||
![]() |
bbe97230d2 | ||
![]() |
ee0161737c | ||
![]() |
e7e0b91703 | ||
![]() |
dbcdf71bbe | ||
![]() |
779615c09a | ||
![]() |
1c3a1ce53c | ||
![]() |
981c524e3f | ||
![]() |
44a7d68f31 | ||
![]() |
ae858e3dc4 | ||
![]() |
22fd23a31d | ||
![]() |
2babe87d6d | ||
![]() |
95a8b3fe34 | ||
![]() |
32c526a26a | ||
![]() |
b2adfad2ee | ||
![]() |
ee5a8534a7 | ||
![]() |
80ba3b969d | ||
![]() |
83bd6911c8 | ||
![]() |
6c66f6199c | ||
![]() |
c11731541c | ||
![]() |
609593ebd0 | ||
![]() |
85b867a5ca | ||
![]() |
a3690051eb | ||
![]() |
ecb44a2611 | ||
![]() |
7898ea9ba7 | ||
![]() |
90a2029f3d | ||
![]() |
1d9a9ea658 | ||
![]() |
e88f80eda3 | ||
![]() |
025e2f415d | ||
![]() |
e113ca79de | ||
![]() |
f988c44440 | ||
![]() |
37cda26e27 | ||
![]() |
65c2da9afa | ||
![]() |
434b7b756b | ||
![]() |
9dfcab6c1c | ||
![]() |
9f39f4e377 | ||
![]() |
58da4284ac | ||
![]() |
55787ff6cf | ||
![]() |
3b93610e43 | ||
![]() |
40f3066ee0 | ||
![]() |
2108aac41c | ||
![]() |
68f8300395 | ||
![]() |
325a61912e | ||
![]() |
7363c88fce | ||
![]() |
0b0f95c65c | ||
![]() |
354675f1e5 | ||
![]() |
7a769f283b | ||
![]() |
3dc67d5978 | ||
![]() |
d3a0d71857 | ||
![]() |
72f7534a5f | ||
![]() |
27a733cbed | ||
![]() |
92a0ce98bb | ||
![]() |
84c9632508 | ||
![]() |
22c2b406db | ||
![]() |
bc374a1317 | ||
![]() |
0bf82a999a | ||
![]() |
453a8459ac | ||
![]() |
53f6ddad22 | ||
![]() |
14bd128931 | ||
![]() |
b0b8daa03d | ||
![]() |
940cd70f64 | ||
![]() |
d8cdef0622 | ||
![]() |
44a7cfe32e | ||
![]() |
8584352e21 | ||
![]() |
1c39d027e0 | ||
![]() |
ce82e2cdcf | ||
![]() |
a8492f75cd | ||
![]() |
03afb38aa3 | ||
![]() |
acc2acce2c | ||
![]() |
3a612864f8 | ||
![]() |
7e1789a3f4 | ||
![]() |
69dea794e1 | ||
![]() |
4e024bd8b1 | ||
![]() |
6078e511aa | ||
![]() |
58574cd824 | ||
![]() |
635fa99cf2 | ||
![]() |
074d71cef7 | ||
![]() |
027075b1b2 | ||
![]() |
898ad42f96 | ||
![]() |
c87ffeff71 | ||
![]() |
40f0744adc | ||
![]() |
eba555f260 | ||
![]() |
e7db208a40 | ||
![]() |
69399bb328 | ||
![]() |
749e928d66 | ||
![]() |
a3b8690609 | ||
![]() |
340e6794ca | ||
![]() |
7a23152cee | ||
![]() |
d00f71884a | ||
![]() |
587014159d | ||
![]() |
e2cb3691e4 | ||
![]() |
a40be3b658 | ||
![]() |
598d7c699a | ||
![]() |
23c9b9f2d9 | ||
![]() |
22aeff708a | ||
![]() |
e9b7b935ee | ||
![]() |
eb0d9ec482 | ||
![]() |
cfd0d72100 | ||
![]() |
f615dc265a | ||
![]() |
53c4971c4e | ||
![]() |
3a98fa9f53 | ||
![]() |
6ed5386c12 | ||
![]() |
a998a7f92b | ||
![]() |
3218989b13 | ||
![]() |
3aff954063 | ||
![]() |
11e824c133 | ||
![]() |
a26662a813 | ||
![]() |
007838197b | ||
![]() |
0ad82d5b91 | ||
![]() |
52e47a62d2 | ||
![]() |
cbaaf3ee54 | ||
![]() |
26f26ee35d | ||
![]() |
0102ac77e3 | ||
![]() |
d24101bee2 | ||
![]() |
36cced5ce7 | ||
![]() |
87eb537ebe | ||
![]() |
86fdc17d2a | ||
![]() |
bd8763c62f | ||
![]() |
bc917d41ad | ||
![]() |
68b60b427a | ||
![]() |
c9e64c53ec | ||
![]() |
6ba6c6bac7 | ||
![]() |
f2967e1d8f | ||
![]() |
60783ca88e | ||
![]() |
8d7c1371df | ||
![]() |
090bfe9091 | ||
![]() |
3ad2ba9f33 | ||
![]() |
1036def599 | ||
![]() |
2acad69940 | ||
![]() |
1f18011a5b | ||
![]() |
3da63b378c | ||
![]() |
0852aa7429 | ||
![]() |
8a863ca636 | ||
![]() |
83db5c205d | ||
![]() |
760e73959c | ||
![]() |
e516e06a53 | ||
![]() |
a954461be3 | ||
![]() |
5998369af6 | ||
![]() |
f41a2604c4 | ||
![]() |
6fc578d286 | ||
![]() |
f2604a5fec | ||
![]() |
642026156a | ||
![]() |
708c511a98 | ||
![]() |
2c75b5886f | ||
![]() |
0ef7f5a955 | ||
![]() |
28856c01cd | ||
![]() |
a47bd03e94 | ||
![]() |
c5551ddeb5 | ||
![]() |
020f274ef3 | ||
![]() |
e2f8f04ace | ||
![]() |
6d61d885c1 | ||
![]() |
e98cd16032 | ||
![]() |
4ec8bdda2f | ||
![]() |
16df1624f8 | ||
![]() |
cb978e012b | ||
![]() |
b7ea02696b | ||
![]() |
49cb8874ca | ||
![]() |
1384256d87 | ||
![]() |
705b2fcd9a | ||
![]() |
906ca77973 | ||
![]() |
7dc5c734d0 | ||
![]() |
a3c1e311f7 | ||
![]() |
4d246a250d | ||
![]() |
8d2c41f558 | ||
![]() |
3b06c4c14a | ||
![]() |
f98dcb813d | ||
![]() |
17cf31e8cf | ||
![]() |
6771c378bf | ||
![]() |
013aa4d071 | ||
![]() |
b887e16628 | ||
![]() |
7774ed65bd | ||
![]() |
c85f996aa3 | ||
![]() |
64d9cc00d1 | ||
![]() |
a0efbecee4 | ||
![]() |
cceb4c6677 | ||
![]() |
66e448a648 | ||
![]() |
eb134fd41a | ||
![]() |
857d6f9008 | ||
![]() |
32396c4534 | ||
![]() |
2df46b6647 | ||
![]() |
9f6ad37547 | ||
![]() |
65955843e5 | ||
![]() |
9e9b5fb9dd | ||
![]() |
f96fc67bc2 | ||
![]() |
07ebd0b4ca | ||
![]() |
64e955c512 | ||
![]() |
161753b195 | ||
![]() |
f92adb847a | ||
![]() |
98f780c277 | ||
![]() |
3c512e74db | ||
![]() |
9b752dd28f | ||
![]() |
3cf2719c29 | ||
![]() |
be420c0394 | ||
![]() |
1b1d995b9d | ||
![]() |
6410f41fa2 | ||
![]() |
f90a45b1e6 | ||
![]() |
9ca5569122 | ||
![]() |
a6b4a35973 | ||
![]() |
06cb6bac3e | ||
![]() |
5241aeea9f | ||
![]() |
6b69ad20ad | ||
![]() |
a79d2ec323 | ||
![]() |
209a0fe2da | ||
![]() |
277f439f70 | ||
![]() |
d9f29fdcaa | ||
![]() |
a9141d3fe2 | ||
![]() |
4ce55e88fa | ||
![]() |
c930d388dc | ||
![]() |
12c7911cf4 | ||
![]() |
06377ff497 | ||
![]() |
7a1938e515 | ||
![]() |
445166d220 | ||
![]() |
3963501d0c | ||
![]() |
acb51d7859 | ||
![]() |
4dbfb76ced | ||
![]() |
4188464652 | ||
![]() |
fb552a8d62 | ||
![]() |
c998e4e34f | ||
![]() |
ab46015a5a | ||
![]() |
dd10740bf2 | ||
![]() |
44f26685e4 | ||
![]() |
3caa56ae8c | ||
![]() |
1ca4fbb078 | ||
![]() |
bdf5270fa0 | ||
![]() |
e3e865b108 | ||
![]() |
33f3736798 | ||
![]() |
a86fbcee44 | ||
![]() |
cdbf8a2811 | ||
![]() |
da4fae4e04 | ||
![]() |
ddeefc4ab6 | ||
![]() |
33702064a5 | ||
![]() |
b72995c8bf | ||
![]() |
868eb1c4fb | ||
![]() |
d93140efc6 | ||
![]() |
0f59d46ede | ||
![]() |
812b5f22f9 | ||
![]() |
d1b5feae0d | ||
![]() |
0861fa9e03 | ||
![]() |
c3fe9f513d | ||
![]() |
b513669f4d | ||
![]() |
1ad74fdacc | ||
![]() |
9a24ede989 | ||
![]() |
7ea8dfa8ce | ||
![]() |
670068eeba | ||
![]() |
70310f1970 | ||
![]() |
4463c148a5 | ||
![]() |
c982b45134 | ||
![]() |
d209a2c7f8 | ||
![]() |
75c73193a2 | ||
![]() |
fc99f6774d | ||
![]() |
d40fab86c9 | ||
![]() |
5c0520e093 | ||
![]() |
1bb9ead202 | ||
![]() |
3afd8915f0 | ||
![]() |
ba3f2d2823 | ||
![]() |
24989d80ac | ||
![]() |
d2c16158cc | ||
![]() |
8514fd6266 | ||
![]() |
30d1534c01 | ||
![]() |
4f0800d4fc | ||
![]() |
41fa396318 | ||
![]() |
d94af84002 | ||
![]() |
63b92cc35a | ||
![]() |
3238d9fbc5 | ||
![]() |
780d4c95fe | ||
![]() |
c3b27c75bf | ||
![]() |
23c7031672 | ||
![]() |
9e98d09a93 | ||
![]() |
06e64f7347 | ||
![]() |
92594db78d | ||
![]() |
c574f2d6bd | ||
![]() |
ee156cbfd6 | ||
![]() |
73d12daf04 | ||
![]() |
e4179a934b | ||
![]() |
afd309d9a8 | ||
![]() |
1a24b00c5e | ||
![]() |
445e4d8b31 | ||
![]() |
224ca98d0e | ||
![]() |
13419c9fb7 | ||
![]() |
00646bc84b | ||
![]() |
cb4b686335 | ||
![]() |
5e900b62c8 | ||
![]() |
74c94d37e5 | ||
![]() |
588814d1a6 | ||
![]() |
572b858f81 | ||
![]() |
1a9fc48490 | ||
![]() |
2dd131e6c3 | ||
![]() |
d1ad2a681f | ||
![]() |
e2e7666c4f | ||
![]() |
665639fdca | ||
![]() |
8bb930c1fc | ||
![]() |
b3b9d8d105 | ||
![]() |
82c409252b | ||
![]() |
14c63a03c4 | ||
![]() |
0c7ad8b16c | ||
![]() |
1bf2d8219a | ||
![]() |
a72264ef36 | ||
![]() |
1acc399568 | ||
![]() |
160960437c | ||
![]() |
61992adcca | ||
![]() |
10e0ae8200 | ||
![]() |
eb58b8576e | ||
![]() |
9b4d2d6ed7 | ||
![]() |
6417e9dec5 | ||
![]() |
f5ac217f13 | ||
![]() |
a3d3b14dd1 | ||
![]() |
8fccce8684 | ||
![]() |
4a847cd74a | ||
![]() |
f4c1db39ad | ||
![]() |
d9ff177427 | ||
![]() |
95e3566c5f | ||
![]() |
76e02ff514 | ||
![]() |
8aca9a2d82 | ||
![]() |
3abab2072a | ||
![]() |
ca9e479dc5 | ||
![]() |
4d230a7b3e | ||
![]() |
974cc59e6c | ||
![]() |
9f09b144f0 | ||
![]() |
9d4dad5fee | ||
![]() |
46ffa93d93 | ||
![]() |
8b709bc070 | ||
![]() |
c1284c760a | ||
![]() |
6529a94d3a | ||
![]() |
f5e91a0524 | ||
![]() |
f63bd3016b | ||
![]() |
09cd590796 | ||
![]() |
da728c4039 | ||
![]() |
14b7b8cec1 | ||
![]() |
3695c04933 | ||
![]() |
f0f3bb6ede | ||
![]() |
7824326c5b | ||
![]() |
a65d263ae2 | ||
![]() |
f3e628be6b | ||
![]() |
62e8dc7767 | ||
![]() |
8e8cfa704a | ||
![]() |
8b2eff0194 | ||
![]() |
d4d063b97a | ||
![]() |
d5ec33e1bd | ||
![]() |
0726f22ec7 | ||
![]() |
531ab93388 | ||
![]() |
a7ad00d402 | ||
![]() |
1f18848b4e | ||
![]() |
38179d9ce3 | ||
![]() |
b86c493cf8 | ||
![]() |
0cc2df85da | ||
![]() |
3157bac5f6 | ||
![]() |
5cb1709f5d | ||
![]() |
e6834b13a5 | ||
![]() |
8a17daa002 | ||
![]() |
1b09189195 | ||
![]() |
7f21fa2c40 | ||
![]() |
e0e4fc85f7 | ||
![]() |
b3e57db9f8 | ||
![]() |
f8d93a5de7 | ||
![]() |
c5423ac650 | ||
![]() |
6e93d17d14 | ||
![]() |
127bc1be5c | ||
![]() |
8136b09992 | ||
![]() |
2ffac3268e | ||
![]() |
c7056e9d40 | ||
![]() |
3fb8b4e7ff | ||
![]() |
c728a7802d | ||
![]() |
e7d3049456 | ||
![]() |
316675c77e | ||
![]() |
c836d3de71 | ||
![]() |
230429135a | ||
![]() |
0be8092382 | ||
![]() |
eb2019e568 | ||
![]() |
bffbb17271 | ||
![]() |
16b997096d | ||
![]() |
3b23f2a4ed | ||
![]() |
87f86fd2e8 | ||
![]() |
396509579a | ||
![]() |
91175f19c4 | ||
![]() |
7c22ca0f91 | ||
![]() |
5eb416d8d9 | ||
![]() |
12e374bd2f | ||
![]() |
9b50f0e77c | ||
![]() |
6aa89287b1 | ||
![]() |
4b9ebdc87c | ||
![]() |
336b45667e | ||
![]() |
3c33a1126b | ||
![]() |
836cdfb16c | ||
![]() |
8512bae997 | ||
![]() |
6fbe8c5dee | ||
![]() |
2132ea416b | ||
![]() |
24081b9223 | ||
![]() |
220cc98559 | ||
![]() |
ef8b9b0685 | ||
![]() |
e8dd47369c | ||
![]() |
537eaddecd | ||
![]() |
183c171da6 | ||
![]() |
58c6114840 | ||
![]() |
df5162ce56 | ||
![]() |
ae61fe892d | ||
![]() |
a78de3b4b9 | ||
![]() |
f26a864e83 | ||
![]() |
0e0b03e6f2 | ||
![]() |
e5595f13eb | ||
![]() |
1b12c16685 | ||
![]() |
048055daac | ||
![]() |
f2590f1fed | ||
![]() |
2eb7b22100 | ||
![]() |
f169750d1a | ||
![]() |
fbb361fa7a | ||
![]() |
902faca13c | ||
![]() |
7e476a5785 | ||
![]() |
c78c5aad02 | ||
![]() |
42c49645da | ||
![]() |
9427fb9ecc | ||
![]() |
61878f293f | ||
![]() |
2bd1727076 | ||
![]() |
f0fbf7bf8b | ||
![]() |
4a1fccc395 | ||
![]() |
54c0497933 | ||
![]() |
49a99e9f15 | ||
![]() |
134fd5b2c2 | ||
![]() |
696f9b3550 | ||
![]() |
aeda42cb71 | ||
![]() |
7ba8400c38 | ||
![]() |
02f10f07e8 | ||
![]() |
83cc32afaa | ||
![]() |
5b8382643a | ||
![]() |
003cb8719a | ||
![]() |
c625ebc128 | ||
![]() |
89c0b02327 | ||
![]() |
94bb17a301 | ||
![]() |
4f29b921e5 | ||
![]() |
8d5dbb0f3d | ||
![]() |
db321e45da | ||
![]() |
8e254a341c | ||
![]() |
847a52ab08 | ||
![]() |
94e69e4e84 | ||
![]() |
8834526cac | ||
![]() |
788365687e | ||
![]() |
4c3d328140 | ||
![]() |
2588f74f7c | ||
![]() |
b70a4ef428 | ||
![]() |
026a903251 | ||
![]() |
3557113ed8 | ||
![]() |
acd8c27a13 | ||
![]() |
3c186eb113 | ||
![]() |
841eb34224 | ||
![]() |
ef583ba7ec | ||
![]() |
fa0e06df75 | ||
![]() |
c26ee7271b | ||
![]() |
f37c0a9124 | ||
![]() |
80fbd656a7 | ||
![]() |
3fb5749c86 | ||
![]() |
1692130559 | ||
![]() |
cf77a9eae2 | ||
![]() |
26151af48a | ||
![]() |
c3b858f0fd | ||
![]() |
914e788ad8 | ||
![]() |
074178621c | ||
![]() |
25d1b6b695 | ||
![]() |
f121c73c4b | ||
![]() |
3f79e7677c | ||
![]() |
ca573f27be | ||
![]() |
056a3342bf | ||
![]() |
eaa661cf09 | ||
![]() |
b2d791d6ea | ||
![]() |
f1ea1935c5 | ||
![]() |
d9c101debe | ||
![]() |
e3a720a69d | ||
![]() |
4f3f18a0ad | ||
![]() |
10a3a8324b | ||
![]() |
a2dab72b25 | ||
![]() |
ca0a381d8c | ||
![]() |
a503e85a57 | ||
![]() |
0d668561b4 | ||
![]() |
c8d39a2c15 | ||
![]() |
6146ac90c1 | ||
![]() |
2bb00c948d | ||
![]() |
01eadd986c | ||
![]() |
b482ea4ecc | ||
![]() |
19bb98c857 | ||
![]() |
225afb85e4 | ||
![]() |
2873ffdff7 | ||
![]() |
52ba506138 | ||
![]() |
798f70a706 | ||
![]() |
d731d55a7a | ||
![]() |
1bfcea0227 | ||
![]() |
71a307bfef | ||
![]() |
7a16a8eaff | ||
![]() |
c1c2ccd940 | ||
![]() |
8a993b7dcb | ||
![]() |
977393a9aa | ||
![]() |
4f36de9900 | ||
![]() |
ef658eb4cd | ||
![]() |
6f77577482 | ||
![]() |
bfdb1a8f62 | ||
![]() |
0935d70ae4 | ||
![]() |
24e4e2b960 | ||
![]() |
e608d7463e | ||
![]() |
47453f1471 | ||
![]() |
362780f59a | ||
![]() |
a2a511b3c0 | ||
![]() |
78cde8ab62 | ||
![]() |
46b779c9d5 | ||
![]() |
23129bf95a | ||
![]() |
fba137bb3f | ||
![]() |
e50a73b4bf | ||
![]() |
31afe11d0e | ||
![]() |
5dc1d047ac | ||
![]() |
19e0cf406c | ||
![]() |
0bc1eece0a | ||
![]() |
f2e93e915b | ||
![]() |
8db6a99194 | ||
![]() |
1490ebce03 | ||
![]() |
cd189e01dc | ||
![]() |
15467248ee | ||
![]() |
23008ab5b8 | ||
![]() |
041fbb10a1 | ||
![]() |
9ba0e59df5 | ||
![]() |
0bb9f57919 | ||
![]() |
106da869c1 | ||
![]() |
d34a3352f2 | ||
![]() |
4b5c922f11 | ||
![]() |
aacb415364 | ||
![]() |
bdc8bcfe5c | ||
![]() |
154238edf0 | ||
![]() |
eba789c200 | ||
![]() |
63cb67a03c | ||
![]() |
1c299c6d5d | ||
![]() |
486c5310d7 | ||
![]() |
5ef4a97d5f | ||
![]() |
03adb8f730 | ||
![]() |
abdcd0b3f0 | ||
![]() |
6e225808a9 | ||
![]() |
382c96f587 | ||
![]() |
80cb0119c7 | ||
![]() |
e7bc5072c0 | ||
![]() |
a65057679c | ||
![]() |
025186d22f | ||
![]() |
e17217206f | ||
![]() |
c64ca44457 | ||
![]() |
c6e9a16274 | ||
![]() |
2dc125e0ce | ||
![]() |
9c88ce213b | ||
![]() |
f945380a87 | ||
![]() |
bb9664eafc | ||
![]() |
eaca802ecc | ||
![]() |
2e6ca574b6 | ||
![]() |
026de5dd4e | ||
![]() |
262897fbf6 | ||
![]() |
304a9d90d0 | ||
![]() |
91e1674833 | ||
![]() |
d4c61ce932 | ||
![]() |
7387ebe182 | ||
![]() |
d6f305cfa6 | ||
![]() |
73b9fbb435 | ||
![]() |
51c2f313d4 | ||
![]() |
0a390107a3 | ||
![]() |
077bf997c6 | ||
![]() |
48cb473ecb | ||
![]() |
40dc542302 | ||
![]() |
28bb4894b2 | ||
![]() |
774d17dd25 | ||
![]() |
790637f1bd | ||
![]() |
99fb5d3b8e | ||
![]() |
6676e62579 | ||
![]() |
d735992f5c | ||
![]() |
8a32cfc185 | ||
![]() |
285fafc300 | ||
![]() |
0c90433a34 | ||
![]() |
d6070368b7 | ||
![]() |
b42389500f | ||
![]() |
daca972fc2 | ||
![]() |
8447e59d1f | ||
![]() |
07ff8cd662 | ||
![]() |
dbc734eee5 | ||
![]() |
eaa95fdba4 | ||
![]() |
3ba1169e9c | ||
![]() |
0117b53ea2 | ||
![]() |
a2ec04b641 | ||
![]() |
8fdcef9c42 | ||
![]() |
d311de764d | ||
![]() |
e9b16b2f70 | ||
![]() |
21a81b977b | ||
![]() |
9ce1c2b075 | ||
![]() |
b974cbd14c | ||
![]() |
1d96282fd9 | ||
![]() |
48efda6bd9 | ||
![]() |
aba3e0033f | ||
![]() |
5bf61a63cc | ||
![]() |
48095c0433 | ||
![]() |
3e1599119a | ||
![]() |
f488e8a7ab | ||
![]() |
b5c17bf7bc | ||
![]() |
77e994e9fd | ||
![]() |
bbd3fc4d1d | ||
![]() |
ee63946be2 | ||
![]() |
b1bcfacf35 | ||
![]() |
d4936e8eec | ||
![]() |
dbba098555 | ||
![]() |
b368e93061 | ||
![]() |
10b333ae48 | ||
![]() |
87c0345a6a | ||
![]() |
381510d213 | ||
![]() |
f5f99f5a04 | ||
![]() |
fcf1214f80 | ||
![]() |
7e122529d2 | ||
![]() |
600c3d21dc | ||
![]() |
135d7ebda5 | ||
![]() |
2a57b94e08 | ||
![]() |
366a37b765 | ||
![]() |
a3806f7a81 | ||
![]() |
cf28e373f7 | ||
![]() |
8d80295e07 | ||
![]() |
1f7ffe6ea0 | ||
![]() |
a740753175 | ||
![]() |
c70f996915 | ||
![]() |
707dfc2a0b | ||
![]() |
77db3362fc | ||
![]() |
c8e0687288 | ||
![]() |
f61a6191ec | ||
![]() |
2648236bb4 | ||
![]() |
382e23f545 | ||
![]() |
2eddbe3669 | ||
![]() |
267d710c13 | ||
![]() |
5e41517178 | ||
![]() |
5c9cf0a655 | ||
![]() |
337297e3e0 | ||
![]() |
26def9805f | ||
![]() |
5429876cde | ||
![]() |
6301b48b5d | ||
![]() |
5dea97cce2 | ||
![]() |
69b63bcb15 | ||
![]() |
d13b2d236b | ||
![]() |
9dce637d22 | ||
![]() |
dbb291fb86 | ||
![]() |
cefad66475 | ||
![]() |
726f4438d6 | ||
![]() |
880e75a91c | ||
![]() |
0f1fd0e367 | ||
![]() |
7a44cf6e26 | ||
![]() |
177c709e0a | ||
![]() |
699eb824a1 | ||
![]() |
bc2dc1b2e9 | ||
![]() |
6b19e305f3 | ||
![]() |
8b1b4044b3 | ||
![]() |
2d9429d688 | ||
![]() |
62f3ff1902 | ||
![]() |
36735cdfbe | ||
![]() |
f57db90d7b | ||
![]() |
97aec23384 | ||
![]() |
eb3bcf04ea | ||
![]() |
40626ba708 | ||
![]() |
882597365b | ||
![]() |
6b456c2f57 | ||
![]() |
515ae57e88 | ||
![]() |
9cc9d6ab66 | ||
![]() |
40b4fd210a | ||
![]() |
2ce2d0efab | ||
![]() |
97a863293d | ||
![]() |
d45426a4c1 | ||
![]() |
d5a49db782 | ||
![]() |
4b393f412c | ||
![]() |
8cc77fbe1d | ||
![]() |
673632bd92 | ||
![]() |
d2b9a5d1a9 | ||
![]() |
2bc46b0a0e | ||
![]() |
74200daf90 | ||
![]() |
b89c127df4 | ||
![]() |
67bbbb2097 | ||
![]() |
c6ddf0de87 | ||
![]() |
0ef73952b1 | ||
![]() |
0e02a3aeee | ||
![]() |
1558a7c386 | ||
![]() |
b72becd328 | ||
![]() |
df2ac8e203 | ||
![]() |
c6c230002c | ||
![]() |
885503b5fa | ||
![]() |
40fd91257e | ||
![]() |
02ece3cf41 | ||
![]() |
901c879647 | ||
![]() |
990a73f4a4 | ||
![]() |
73169d339d | ||
![]() |
265b86c031 | ||
![]() |
7c29c23015 | ||
![]() |
538e579477 | ||
![]() |
73db5f55e2 | ||
![]() |
31a9980343 | ||
![]() |
02c50f510f | ||
![]() |
3541ee0512 | ||
![]() |
e72821ba1e | ||
![]() |
3af00871a5 | ||
![]() |
22fe4ca790 | ||
![]() |
72d0570c15 | ||
![]() |
62e0cc0867 | ||
![]() |
8987480491 | ||
![]() |
70bb4c2478 | ||
![]() |
cf079a6be4 | ||
![]() |
f153cdcba1 | ||
![]() |
4e048240c5 | ||
![]() |
c098bb1ca0 | ||
![]() |
e02ded734c | ||
![]() |
e721f29f5a | ||
![]() |
f763d5f936 | ||
![]() |
a3368eb557 | ||
![]() |
b5758347c2 | ||
![]() |
775a6d92aa | ||
![]() |
2ab5995177 | ||
![]() |
f6e847d43f | ||
![]() |
cac2ca3d18 | ||
![]() |
d1e870cee0 | ||
![]() |
ca0f65767b | ||
![]() |
7968bfc262 | ||
![]() |
ed4bbe9814 | ||
![]() |
6e83eb6da2 | ||
![]() |
00949b6135 | ||
![]() |
f3a857f26f | ||
![]() |
4bd03372aa | ||
![]() |
dcc589c57a | ||
![]() |
3018ec8cf0 | ||
![]() |
c452a66a4f | ||
![]() |
7a860f8564 | ||
![]() |
94f6f4bdff | ||
![]() |
a627dac4b7 | ||
![]() |
848b6862be | ||
![]() |
d181575e93 | ||
![]() |
778775055f | ||
![]() |
22ccda8d34 | ||
![]() |
c5fc6fd72e | ||
![]() |
c8a4978b5f | ||
![]() |
9e88f8c884 | ||
![]() |
2e543bf4d3 | ||
![]() |
caf42d423f | ||
![]() |
dc39f874ac | ||
![]() |
d1c7a124cf | ||
![]() |
8ec17ce9a6 | ||
![]() |
012af35e87 | ||
![]() |
78bd1f4a5d | ||
![]() |
4477158182 | ||
![]() |
6e96021047 | ||
![]() |
48f57eea66 | ||
![]() |
4b6cfefaf3 | ||
![]() |
0e34cc7f26 | ||
![]() |
27fb2870ab | ||
![]() |
ee6b7c4fe0 | ||
![]() |
0464cecde5 | ||
![]() |
b237259599 | ||
![]() |
8c379739f0 | ||
![]() |
4fb8db982c | ||
![]() |
921b50b642 | ||
![]() |
031332e8ab | ||
![]() |
f03ccced8d | ||
![]() |
51973d225c | ||
![]() |
a59666e752 | ||
![]() |
8259191e50 | ||
![]() |
3eb84cc955 | ||
![]() |
b1b7bff09d | ||
![]() |
82f28bfc8c | ||
![]() |
dfed92ac61 | ||
![]() |
0d6c9b468e | ||
![]() |
2bc12c510b | ||
![]() |
f3022a19c2 | ||
![]() |
800afae1c9 | ||
![]() |
3c19f8e76f | ||
![]() |
3ca462f46f | ||
![]() |
fadd21ebd0 | ||
![]() |
a10c474ce5 | ||
![]() |
513ea5a198 | ||
![]() |
4bab1c32d7 | ||
![]() |
39064eb2c6 | ||
![]() |
28a60f5243 | ||
![]() |
56b9b878f8 | ||
![]() |
e7ad6e32e3 | ||
![]() |
a1d6347db3 | ||
![]() |
9e80013e28 | ||
![]() |
e66a8a0b21 | ||
![]() |
77593969b2 | ||
![]() |
186fa35f70 | ||
![]() |
c39d0048a8 | ||
![]() |
5fc22b9530 | ||
![]() |
51735c3f6d | ||
![]() |
f14aad0c50 | ||
![]() |
cdbb492f2c | ||
![]() |
de18aefd7b | ||
![]() |
5f8807d62c | ||
![]() |
e42d8b8eeb | ||
![]() |
d67b8b8298 | ||
![]() |
10c8d157f5 | ||
![]() |
1f10558f1f | ||
![]() |
409228285e | ||
![]() |
0ac7758c04 | ||
![]() |
802e3d04b2 | ||
![]() |
39ef4a4711 | ||
![]() |
b2215e1db6 |
10
crowdin.yml
Normal file
10
crowdin.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
files:
|
||||
- source: src/keepass2android/Resources/values/strings.xml
|
||||
translation: >-
|
||||
/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
|
@@ -7,11 +7,12 @@ If you think something is missing in the documentation, please create an issue a
|
||||
If you store important information using Keepass2Android, you should know a little bit about what's going on:
|
||||
* Keepass2Android stores your password in an encrypted file. It is *your responsibility* to backup this file regularly and safely.
|
||||
* There is no way for anyone, including the app's author, to access the information stored in your password database without
|
||||
** having the database file
|
||||
** knowing the master password (and additional second factor if you chose one)
|
||||
This means that **if you forget the master password, your database is lost**! So make sure you remember the password. You might also want to think about:
|
||||
** What happens if I have an accident? Should any trusted person be able to access my database?
|
||||
** What happens if my phone gets lost or stolen? Do I know how to recover my database from a backup or the cloud?
|
||||
* having the database file
|
||||
* knowing the master password (and additional second factor if you chose one)
|
||||
This means that **if you forget the master password, your database is lost**! So make sure you remember the password and retain any second factor method (if one is used).
|
||||
* You might also want to think about:
|
||||
* What happens if I have an accident? Should any trusted person be able to access my database?
|
||||
* What happens if my phone gets lost or stolen? Do I know how to recover my database from a backup or the cloud?
|
||||
|
||||
|
||||
# Getting started
|
||||
|
@@ -4,28 +4,28 @@
|
||||
on how to set up a Keepass 2 database with Yubikey/OTP protection.<br>
|
||||
<br>
|
||||
After successful setup you should have the database file, e.g. yubi.kdbx, and the OTP auxiliary file, e.g. yubi.otp.xml, both in the same folder.<br>
|
||||
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767825"><img title="OTPAuxFile" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767826" alt="OTPAuxFile" width="513" height="40" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<a href="How to use Keepass2Android with YubiKey NEO_OTPAuxFile_2.png"><img title="OTPAuxFile" src="How to use Keepass2Android with YubiKey NEO_OTPAuxFile_thumb.png" alt="OTPAuxFile" width="513" height="40" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<p>Make sure you make <strong>both files</strong> available to Keepass2Android, e.g. by placing them both in your Dropbox.</p>
|
||||
<p>Now you should check your NDEF setup of the Yubikey NEO. Therefore, go to the Tools menu in the Yubico Personalization Utility. Select the same slot as used for OTPs with Keepass 2. The default setting for NDEF type and payload should work. If you experience
|
||||
problems, you may use the configuration as shown in this screenshot or simply press the “Reset” button:</p>
|
||||
<p><a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767911"><img title="image" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767912" alt="image" width="760" height="622" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<p><a href="How to use Keepass2Android with YubiKey NEO_image_2.png"><img title="image" src="How to use Keepass2Android with YubiKey NEO_image_thumb.png" alt="image" width="760" height="622" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<p><br>
|
||||
<br>
|
||||
In Keepass2Android, select "Open file" and locate your database file, e.g. yubi.kdbx.<br>
|
||||
<br>
|
||||
In the password screen under "Select master key type" select "Password + OTP".</p>
|
||||
<p><a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767913"><img title="Screenshot_2013-12-13-06-38-50" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767914" alt="Screenshot_2013-12-13-06-38-50" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<p><a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-50_2.png"><img title="Screenshot_2013-12-13-06-38-50" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-50_thumb.png" alt="Screenshot_2013-12-13-06-38-50" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<p>Click "Load auxiliary OTP file". This is required to load the information how many OTPs must be entered. As loading the file might require user action in some cases, this is not performed automatically.<br>
|
||||
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767915"><img title="Screenshot_2013-12-13-06-38-12" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767916" alt="Screenshot_2013-12-13-06-38-12" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
|
||||
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-12_2.png"><img title="Screenshot_2013-12-13-06-38-12" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-12_thumb.png" alt="Screenshot_2013-12-13-06-38-12" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
|
||||
After loading the OTP auxiliary file, you should see a few text fields for entering the OTPs. Now swipe your YubiKey NEO at the back of your Android device. If you have multiple apps which can handle NFC actions, you might be prompted to select which app to
|
||||
use. Select Keepass2Android in this case. Swipe your YubiKey again until all OTP fields are filled. Note: You don't need to select the next text field, this is done automatically!<br>
|
||||
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767917"><img title="Screenshot_2013-12-13-06-38-36" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767918" alt="Screenshot_2013-12-13-06-38-36" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
|
||||
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-36_2.png"><img title="Screenshot_2013-12-13-06-38-36" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-38-36_thumb.png" alt="Screenshot_2013-12-13-06-38-36" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a><br>
|
||||
Don't forget to also enter your password and click OK. You will see the “Saving auxiliary OTP file…” dialog. Note that there is some encryption envolved which is probably fast on your PC but might take some time on your mobile device. You
|
||||
can reduce the look-ahead window length to speed this up.<br>
|
||||
<a href="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767919"><img title="Screenshot_2013-12-13-06-39-47" src="http://download-codeplex.sec.s-msft.com/Download?ProjectName=keepass2android&DownloadId=767920" alt="Screenshot_2013-12-13-06-39-47" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<a href="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-39-47_2.png"><img title="Screenshot_2013-12-13-06-39-47" src="How to use Keepass2Android with YubiKey NEO_Screenshot_2013-12-13-06-39-47_thumb.png" alt="Screenshot_2013-12-13-06-39-47" width="204" height="360" border="0" style="padding-top:0px; padding-left:0px; display:inline; padding-right:0px; border:0px"></a></p>
|
||||
<h2> </h2>
|
||||
<h2>A note about offline access</h2>
|
||||
<p>If your database is stored in the cloud or on the web, you can still access it if you have enabled file caching (which is on by default). With OTPs, this becomes a little bit more complicated: If you repeatedly open your datbase while being offline, the
|
||||
OTP counter stored on the Yubikey will be increased. Don’t forget to synchronize the database (which will also synchronize the OTP auxiliary file) as soon as possible to avoid problems with accessing your database on other devices! If you often need
|
||||
to open the database while you’re offline, consider increasing the look-ahead window length!</p>
|
||||
</div><div class="ClearBoth"></div>
|
||||
</div><div class="ClearBoth"></div>
|
||||
|
@@ -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
|
||||
}}
|
||||
```
|
||||
|
@@ -1,7 +1,9 @@
|
||||
<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 KepassX on Linux.
|
||||
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.
|
||||
|
||||
# Where to get it?
|
||||
Regular stable releases of Keepass2Android are available on [Google Play](https://play.google.com/store/apps/details?id=keepass2android.keepass2android).
|
||||
|
BIN
graphics/launcher_icon/Logo-green-96.png
Normal file
BIN
graphics/launcher_icon/Logo-green-96.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
64
src/AdalBindings/AdalBindings.csproj
Normal file
64
src/AdalBindings/AdalBindings.csproj
Normal 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>
|
48
src/AdalBindings/Additions/AboutAdditions.txt
Normal file
48
src/AdalBindings/Additions/AboutAdditions.txt
Normal 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; }
|
||||
}
|
24
src/AdalBindings/Jars/AboutJars.txt
Normal file
24
src/AdalBindings/Jars/AboutJars.txt
Normal 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".
|
BIN
src/AdalBindings/Jars/adal-1.14.0.aar
Normal file
BIN
src/AdalBindings/Jars/adal-1.14.0.aar
Normal file
Binary file not shown.
BIN
src/AdalBindings/Jars/gson-2.3.1.jar
Normal file
BIN
src/AdalBindings/Jars/gson-2.3.1.jar
Normal file
Binary file not shown.
30
src/AdalBindings/Properties/AssemblyInfo.cs
Normal file
30
src/AdalBindings/Properties/AssemblyInfo.cs
Normal 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")]
|
14
src/AdalBindings/Transforms/EnumFields.xml
Normal file
14
src/AdalBindings/Transforms/EnumFields.xml
Normal 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>
|
13
src/AdalBindings/Transforms/EnumMethods.xml
Normal file
13
src/AdalBindings/Transforms/EnumMethods.xml
Normal 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>
|
13
src/AdalBindings/Transforms/Metadata.xml
Normal file
13
src/AdalBindings/Transforms/Metadata.xml
Normal 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>
|
@@ -26,6 +26,7 @@
|
||||
android:hint="@string/http_auth_dialog_password"
|
||||
android:inputType="textPassword"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="20dp" />
|
||||
android:paddingBottom="20dp"
|
||||
android:importantForAccessibility="no" />
|
||||
|
||||
</LinearLayout>
|
@@ -80,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>
|
||||
@@ -92,9 +95,6 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedReferenceJar Include="Jars\onedrive-sdk-android-1.2.2\classes-onedrive-sdk.jar" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedReferenceJar Include="Jars\adal-1.1.19\classes-adal.jar" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedReferenceJar Include="Jars\gdrive\commons-logging-1.1.1.jar" />
|
||||
</ItemGroup>
|
||||
|
@@ -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']" />
|
||||
|
@@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.FtpClient.Androi
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCloudBindings", "PCloudBindings\PCloudBindings.csproj", "{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -156,19 +158,25 @@ Global
|
||||
{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}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.Build.0 = 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 = Release|Any CPU
|
||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = Release|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
|
||||
@@ -283,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
|
||||
|
@@ -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;
|
||||
@@ -55,7 +55,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
||||
get { return "AES-KDF"; }
|
||||
}
|
||||
|
||||
public AesKdf()
|
||||
public override byte[] GetSeed(KdfParameters p)
|
||||
{ return p.GetByteArray(ParamSeed); }
|
||||
|
||||
public AesKdf()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -141,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();
|
||||
|
@@ -68,7 +68,10 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
||||
get { return "Argon2"; }
|
||||
}
|
||||
|
||||
public Argon2Kdf()
|
||||
public override byte[] GetSeed(KdfParameters p)
|
||||
{ return p.GetByteArray(ParamSalt); }
|
||||
|
||||
public Argon2Kdf()
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,9 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
||||
get;
|
||||
}
|
||||
|
||||
public virtual KdfParameters GetDefaultParameters()
|
||||
public abstract byte[] GetSeed(KdfParameters p);
|
||||
|
||||
public virtual KdfParameters GetDefaultParameters()
|
||||
{
|
||||
return new KdfParameters(this.Uuid);
|
||||
}
|
||||
|
@@ -20,11 +20,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using KeePassLib.Cryptography;
|
||||
using KeePassLib.Cryptography.KeyDerivation;
|
||||
using KeePassLib.Native;
|
||||
using KeePassLib.Resources;
|
||||
using KeePassLib.Security;
|
||||
using KeePassLib.Utility;
|
||||
@@ -168,7 +165,7 @@ namespace KeePassLib.Keys
|
||||
/// Creates the composite key from the supplied user key sources (password,
|
||||
/// key file, user account, computer ID, etc.).
|
||||
/// </summary>
|
||||
private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed)
|
||||
private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed, byte[] mPbKdfSeed)
|
||||
{
|
||||
ValidateUserKeys();
|
||||
|
||||
@@ -178,7 +175,7 @@ namespace KeePassLib.Keys
|
||||
foreach(IUserKey pKey in m_vUserKeys)
|
||||
{
|
||||
if (pKey is ISeedBasedUserKey)
|
||||
((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed);
|
||||
((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed, mPbKdfSeed);
|
||||
ProtectedBinary b = pKey.KeyData;
|
||||
if(b != null)
|
||||
{
|
||||
@@ -211,15 +208,17 @@ namespace KeePassLib.Keys
|
||||
{
|
||||
if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); }
|
||||
|
||||
byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed);
|
||||
|
||||
KdfEngine kdf = KdfPool.Get(p.KdfUuid);
|
||||
if (kdf == null) // CryptographicExceptions are translated to "file corrupted"
|
||||
throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
|
||||
KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
|
||||
"UUID: " + p.KdfUuid.ToHexString() + ".");
|
||||
|
||||
byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed, kdf.GetSeed(p));
|
||||
if((pbRaw32 == null) || (pbRaw32.Length != 32))
|
||||
{ Debug.Assert(false); return null; }
|
||||
|
||||
KdfEngine kdf = KdfPool.Get(p.KdfUuid);
|
||||
if(kdf == null) // CryptographicExceptions are translated to "file corrupted"
|
||||
throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
|
||||
KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
|
||||
"UUID: " + p.KdfUuid.ToHexString() + ".");
|
||||
|
||||
byte[] pbTrf32 = kdf.Transform(pbRaw32, p);
|
||||
if(pbTrf32 == null) { Debug.Assert(false); return null; }
|
||||
@@ -256,7 +255,7 @@ namespace KeePassLib.Keys
|
||||
|
||||
public interface ISeedBasedUserKey
|
||||
{
|
||||
void SetParams(byte[] masterSeed);
|
||||
void SetParams(byte[] masterSeed, byte[] mPbKdfSeed);
|
||||
}
|
||||
|
||||
public sealed class InvalidCompositeKeyException : Exception
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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");
|
||||
|
@@ -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; }
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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()
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -302,7 +302,7 @@ namespace KeePassLib.Native
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.Log(e.Message);
|
||||
Kp2aLog.Log(e.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -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; }
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
|
47
src/Kp2aBusinessLogic/ElementAndDatabaseId.cs
Normal file
47
src/Kp2aBusinessLogic/ElementAndDatabaseId.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
}
|
@@ -2,12 +2,16 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Android;
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.OS;
|
||||
using Android.Provider;
|
||||
using Java.IO;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
using Console = System.Console;
|
||||
|
||||
namespace keepass2android.Io
|
||||
{
|
||||
@@ -51,7 +55,20 @@ namespace keepass2android.Io
|
||||
|
||||
public Stream OpenFileForRead(IOConnectionInfo ioc)
|
||||
{
|
||||
return _ctx.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(ioc.Path));
|
||||
try
|
||||
{
|
||||
return _ctx.ContentResolver.OpenInputStream(Android.Net.Uri.Parse(ioc.Path));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e.Message.Contains("requires that you obtain access using ACTION_OPEN_DOCUMENT"))
|
||||
{
|
||||
//looks like permission was revoked.
|
||||
throw new DocumentAccessRevokedException();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
|
||||
@@ -61,8 +78,9 @@ namespace keepass2android.Io
|
||||
|
||||
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return UrlUtil.StripExtension(
|
||||
UrlUtil.GetFileName(ioc.Path));
|
||||
}
|
||||
|
||||
public bool RequiresCredentials(IOConnectionInfo ioc)
|
||||
{
|
||||
@@ -189,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)
|
||||
@@ -267,7 +284,26 @@ namespace keepass2android.Io
|
||||
|
||||
}
|
||||
|
||||
class AndroidContentWriteTransaction : IWriteTransaction
|
||||
public class DocumentAccessRevokedException : Exception
|
||||
{
|
||||
public DocumentAccessRevokedException()
|
||||
{
|
||||
}
|
||||
|
||||
public DocumentAccessRevokedException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public DocumentAccessRevokedException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected DocumentAccessRevokedException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidContentWriteTransaction : IWriteTransaction
|
||||
{
|
||||
private readonly string _path;
|
||||
private readonly Context _ctx;
|
||||
|
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
using System.Security;
|
||||
@@ -10,10 +11,14 @@ using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Android.Support.V13.App;
|
||||
using Android.Support.V4.App;
|
||||
using Java.IO;
|
||||
using Java.Util;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
using ActivityCompat = Android.Support.V13.App.ActivityCompat;
|
||||
using File = System.IO.File;
|
||||
using FileNotFoundException = System.IO.FileNotFoundException;
|
||||
using IOException = System.IO.IOException;
|
||||
@@ -250,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)))
|
||||
@@ -258,10 +264,14 @@ namespace keepass2android.Io
|
||||
|
||||
if (requiresPermission && (Build.VERSION.SdkInt >= BuildVersionCodes.M))
|
||||
{
|
||||
if (activity.Activity.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) ==
|
||||
if ((activity.Activity.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) ==
|
||||
Permission.Denied)
|
||||
{
|
||||
activity.StartFileUsageProcess(ioc, requestCode, alwaysReturnSuccess);
|
||||
||
|
||||
(activity.Activity.CheckSelfPermission(Manifest.Permission.ReadExternalStorage) ==
|
||||
Permission.Denied))
|
||||
|
||||
{
|
||||
activity.StartFileUsageProcess(ioc, requestCode, alwaysReturnSuccess);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -279,7 +289,7 @@ namespace keepass2android.Io
|
||||
|
||||
public void OnCreate(IFileStorageSetupActivity fileStorageSetupActivity, Bundle savedInstanceState)
|
||||
{
|
||||
((Activity)fileStorageSetupActivity).RequestPermissions(new[] { Manifest.Permission.WriteExternalStorage }, 0);
|
||||
Android.Support.V4.App.ActivityCompat.RequestPermissions(((Activity)fileStorageSetupActivity), new[] { Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage }, 0);
|
||||
}
|
||||
|
||||
public void OnResume(IFileStorageSetupActivity activity)
|
||||
@@ -372,7 +382,14 @@ namespace keepass2android.Io
|
||||
{
|
||||
if (ioc.IsLocalFile())
|
||||
{
|
||||
if (IsLocalFileFlaggedReadOnly(ioc))
|
||||
if (IsLocalBackup(ioc))
|
||||
{
|
||||
if (reason != null)
|
||||
reason.Result = UiStringKey.ReadOnlyReason_LocalBackup;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsLocalFileFlaggedReadOnly(ioc))
|
||||
{
|
||||
if (reason != null)
|
||||
reason.Result = UiStringKey.ReadOnlyReason_ReadOnlyFlag;
|
||||
@@ -393,7 +410,22 @@ namespace keepass2android.Io
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsLocalFileFlaggedReadOnly(IOConnectionInfo ioc)
|
||||
private readonly Dictionary<string, bool> _isLocalBackupCache = new Dictionary<string, bool>();
|
||||
public bool IsLocalBackup(IOConnectionInfo ioc)
|
||||
{
|
||||
if (!ioc.IsLocalFile())
|
||||
return false;
|
||||
bool result;
|
||||
if (_isLocalBackupCache.TryGetValue(ioc.Path, out result))
|
||||
return result;
|
||||
|
||||
result = (PreferenceManager.GetDefaultSharedPreferences(Application.Context)
|
||||
.GetBoolean(IoUtil.GetIocPrefKey(ioc, "is_local_backup"), false));
|
||||
_isLocalBackupCache[ioc.Path] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool IsLocalFileFlaggedReadOnly(IOConnectionInfo ioc)
|
||||
{
|
||||
//see http://stackoverflow.com/a/33292700/292233
|
||||
try
|
||||
@@ -417,7 +449,7 @@ namespace keepass2android.Io
|
||||
public void OnRequestPermissionsResult(IFileStorageSetupActivity fileStorageSetupActivity, int requestCode,
|
||||
string[] permissions, Permission[] grantResults)
|
||||
{
|
||||
fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults[0] == Permission.Granted);
|
||||
fileStorageSetupActivity.State.PutBoolean(PermissionGrantedKey, grantResults.All(res => res == Permission.Granted));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
@@ -345,57 +357,7 @@ namespace keepass2android.Io
|
||||
|
||||
private class CachedWriteTransaction: IWriteTransaction
|
||||
{
|
||||
private class CachedWriteMemoryStream : MemoryStream
|
||||
{
|
||||
private readonly IOConnectionInfo ioc;
|
||||
private readonly CachingFileStorage _cachingFileStorage;
|
||||
private readonly bool _useFileTransaction;
|
||||
private bool _closed;
|
||||
|
||||
public CachedWriteMemoryStream(IOConnectionInfo ioc, CachingFileStorage cachingFileStorage, bool useFileTransaction)
|
||||
{
|
||||
this.ioc = ioc;
|
||||
_cachingFileStorage = cachingFileStorage;
|
||||
_useFileTransaction = useFileTransaction;
|
||||
}
|
||||
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (_closed) return;
|
||||
|
||||
//write file to cache:
|
||||
//(note: this might overwrite local changes. It's assumed that a sync operation or check was performed before
|
||||
string hash;
|
||||
using (var hashingStream = new HashingStreamEx(File.Create(_cachingFileStorage.CachedFilePath(ioc)), true, new SHA256Managed()))
|
||||
{
|
||||
Position = 0;
|
||||
CopyTo(hashingStream);
|
||||
|
||||
hashingStream.Close();
|
||||
hash = MemUtil.ByteArrayToHexString(hashingStream.Hash);
|
||||
}
|
||||
|
||||
File.WriteAllText(_cachingFileStorage.VersionFilePath(ioc), hash);
|
||||
//update file on remote. This might overwrite changes there as well, see above.
|
||||
Position = 0;
|
||||
if (_cachingFileStorage.IsCached(ioc))
|
||||
{
|
||||
//if the file already is in the cache, it's ok if writing to remote fails.
|
||||
_cachingFileStorage.TryUpdateRemoteFile(this, ioc, _useFileTransaction, hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if not, we don't accept a failure (e.g. invalid credentials would always remain a problem)
|
||||
_cachingFileStorage.UpdateRemoteFile(this, ioc, _useFileTransaction, hash);
|
||||
}
|
||||
|
||||
base.Close();
|
||||
|
||||
_closed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private readonly IOConnectionInfo _ioc;
|
||||
private readonly bool _useFileTransaction;
|
||||
@@ -429,17 +391,48 @@ namespace keepass2android.Io
|
||||
|
||||
public Stream OpenFile()
|
||||
{
|
||||
_memoryStream = new CachedWriteMemoryStream(_ioc, _cachingFileStorage, _useFileTransaction);
|
||||
_memoryStream = new MemoryStream();
|
||||
return _memoryStream;
|
||||
}
|
||||
|
||||
public void CommitWrite()
|
||||
{
|
||||
//the transaction is committed in the stream's Close
|
||||
_committed = true;
|
||||
_memoryStream.Close();
|
||||
|
||||
//write file to cache:
|
||||
//(note: this might overwrite local changes. It's assumed that a sync operation or check was performed before
|
||||
|
||||
byte[] output = _memoryStream.ToArray();
|
||||
|
||||
string hash;
|
||||
using (var hashingStream = new HashingStreamEx(File.Create(_cachingFileStorage.CachedFilePath(_ioc)), true, new SHA256Managed()))
|
||||
{
|
||||
hashingStream.Write(output, 0, output.Length);
|
||||
|
||||
hashingStream.Close();
|
||||
hash = MemUtil.ByteArrayToHexString(hashingStream.Hash);
|
||||
}
|
||||
|
||||
File.WriteAllText(_cachingFileStorage.VersionFilePath(_ioc), hash);
|
||||
//create another memory stream which is open for reading again
|
||||
MemoryStream openMemStream = new MemoryStream(output);
|
||||
//update file on remote. This might overwrite changes there as well, see above.
|
||||
if (_cachingFileStorage.IsCached(_ioc))
|
||||
{
|
||||
//if the file already is in the cache, it's ok if writing to remote fails.
|
||||
_cachingFileStorage.TryUpdateRemoteFile(openMemStream, _ioc, _useFileTransaction, hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if not, we don't accept a failure (e.g. invalid credentials would always remain a problem)
|
||||
_cachingFileStorage.UpdateRemoteFile(openMemStream, _ioc, _useFileTransaction, hash);
|
||||
}
|
||||
|
||||
openMemStream.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
|
||||
|
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Java.IO;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace keepass2android.Io
|
||||
{
|
||||
@@ -125,5 +127,53 @@ namespace keepass2android.Io
|
||||
return ctx.FilesDir;
|
||||
}
|
||||
|
||||
}
|
||||
//creates a local ioc where the sourceIoc can be stored to
|
||||
public static IOConnectionInfo GetInternalIoc(IOConnectionInfo sourceIoc, Context ctx)
|
||||
{
|
||||
Java.IO.File internalDirectory = IoUtil.GetInternalDirectory(ctx);
|
||||
string targetPath = UrlUtil.GetFileName(sourceIoc.Path);
|
||||
targetPath = targetPath.Trim("|\\?*<\":>+[]/'".ToCharArray());
|
||||
if (targetPath == "")
|
||||
targetPath = "internal";
|
||||
if (new File(internalDirectory, targetPath).Exists())
|
||||
{
|
||||
int c = 1;
|
||||
var ext = UrlUtil.GetExtension(targetPath);
|
||||
var filenameWithoutExt = UrlUtil.StripExtension(targetPath);
|
||||
do
|
||||
{
|
||||
c++;
|
||||
targetPath = filenameWithoutExt + c;
|
||||
if (!String.IsNullOrEmpty(ext))
|
||||
targetPath += "." + ext;
|
||||
} while (new File(internalDirectory, targetPath).Exists());
|
||||
}
|
||||
return IOConnectionInfo.FromPath(new File(internalDirectory, targetPath).CanonicalPath);
|
||||
}
|
||||
|
||||
public static IOConnectionInfo ImportFileToInternalDirectory(IOConnectionInfo sourceIoc, Context ctx, IKp2aApp app)
|
||||
{
|
||||
var targetIoc = GetInternalIoc(sourceIoc, ctx);
|
||||
|
||||
|
||||
IoUtil.Copy(targetIoc, sourceIoc, app);
|
||||
return targetIoc;
|
||||
}
|
||||
|
||||
public static string GetIocPrefKey(IOConnectionInfo ioc, string suffix)
|
||||
{
|
||||
var iocAsHexString = IocAsHexString(ioc);
|
||||
|
||||
return "kp2a_ioc_key_" + iocAsHexString + suffix;
|
||||
}
|
||||
|
||||
|
||||
public static string IocAsHexString(IOConnectionInfo ioc)
|
||||
{
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
string iocAsHexString =
|
||||
MemUtil.ByteArrayToHexString(sha256.ComputeHash(Encoding.Unicode.GetBytes(ioc.Path.ToCharArray())));
|
||||
return iocAsHexString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
@@ -231,7 +231,7 @@ namespace keepass2android.Io
|
||||
|
||||
|
||||
|
||||
internal Uri IocToUri(IOConnectionInfo ioc)
|
||||
public static Uri IocToUri(IOConnectionInfo ioc)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ioc.UserName))
|
||||
{
|
||||
@@ -575,7 +575,7 @@ namespace keepass2android.Io
|
||||
{
|
||||
|
||||
_client = _fileStorage.GetClient(_ioc, false);
|
||||
_stream = _client.OpenWrite(_fileStorage.IocToUri(_iocTemp).PathAndQuery);
|
||||
_stream = _client.OpenWrite(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery);
|
||||
return _stream;
|
||||
}
|
||||
catch (FtpCommandException ex)
|
||||
@@ -595,8 +595,8 @@ namespace keepass2android.Io
|
||||
//make sure target file does not exist:
|
||||
//try
|
||||
{
|
||||
if (_client.FileExists(_fileStorage.IocToUri(_ioc).PathAndQuery))
|
||||
_client.DeleteFile(_fileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
if (_client.FileExists(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery))
|
||||
_client.DeleteFile(NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
|
||||
}
|
||||
//catch (FtpCommandException)
|
||||
@@ -604,8 +604,8 @@ namespace keepass2android.Io
|
||||
//TODO get a new clien? might be stale
|
||||
}
|
||||
|
||||
_client.Rename(_fileStorage.IocToUri(_iocTemp).PathAndQuery,
|
||||
_fileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
_client.Rename(NetFtpFileStorage.IocToUri(_iocTemp).PathAndQuery,
|
||||
NetFtpFileStorage.IocToUri(_ioc).PathAndQuery);
|
||||
|
||||
}
|
||||
catch (FtpCommandException ex)
|
||||
|
23
src/Kp2aBusinessLogic/Io/PCloudFileStorage.cs
Normal file
23
src/Kp2aBusinessLogic/Io/PCloudFileStorage.cs
Normal 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
|
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -14,7 +14,8 @@
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
|
||||
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
|
||||
<NuGetPackageImportStamp>06ffb71c</NuGetPackageImportStamp>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -55,12 +56,42 @@
|
||||
<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">
|
||||
<HintPath>..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Core.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Arch.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Arch.Lifecycle.Runtime, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\lib\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Annotations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Annotations.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Support.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Compat.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Core.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Core.Utils, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Core.Utils.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Fragment, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Fragment.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.Media.Compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.Media.Compat.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Xamarin.Android.Support.v13, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xamarin.Android.Support.v13.26.1.0.1\lib\MonoAndroid80\Xamarin.Android.Support.v13.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="database\CheckDatabaseForChanges.cs" />
|
||||
<Compile Include="database\edit\AddTemplateEntries.cs" />
|
||||
<Compile Include="database\edit\CopyEntry.cs" />
|
||||
<Compile Include="database\edit\DeleteMultipleItems.cs" />
|
||||
<Compile Include="database\edit\DeleteMultipleItemsFromOneDatabase.cs" />
|
||||
<Compile Include="database\edit\EditGroup.cs" />
|
||||
<Compile Include="database\edit\MoveElements.cs" />
|
||||
<Compile Include="database\KdbDatabaseFormat.cs" />
|
||||
@@ -72,6 +103,7 @@
|
||||
<Compile Include="DataExchange\Formats\KeePassKdb2x.cs" />
|
||||
<Compile Include="DataExchange\Formats\KeePassXml2x.cs" />
|
||||
<Compile Include="DataExchange\PwExportInfo.cs" />
|
||||
<Compile Include="ElementAndDatabaseId.cs" />
|
||||
<Compile Include="Io\AndroidContentStorage.cs" />
|
||||
<Compile Include="Io\BuiltInFileStorage.cs" />
|
||||
<Compile Include="Io\CachingFileStorage.cs" />
|
||||
@@ -86,6 +118,7 @@
|
||||
<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" />
|
||||
@@ -97,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" />
|
||||
@@ -148,7 +181,35 @@
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Annotations.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Annotations.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Core.Common.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Core.Common.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Common.1.0.1\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Common.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets" Condition="Exists('..\packages\Xamarin.Android.Arch.Lifecycle.Runtime.1.0.0\build\MonoAndroid80\Xamarin.Android.Arch.Lifecycle.Runtime.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Compat.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.UI.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.UI.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Core.Utils.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Core.Utils.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Fragment.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Fragment.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Media.Compat.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.Media.Compat.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v13.26.1.0.1\build\MonoAndroid80\Xamarin.Android.Support.v13.targets')" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
@@ -30,8 +30,12 @@ namespace keepass2android
|
||||
readonly IKp2aApp _app;
|
||||
private readonly Handler _handler;
|
||||
private string _message = "";
|
||||
private string _submessage;
|
||||
|
||||
public ProgressDialogStatusLogger() {
|
||||
public String SubMessage => _submessage;
|
||||
public String Message => _message;
|
||||
|
||||
public ProgressDialogStatusLogger() {
|
||||
|
||||
}
|
||||
|
||||
@@ -48,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); } );
|
||||
}
|
||||
@@ -56,6 +61,8 @@ namespace keepass2android
|
||||
|
||||
public void UpdateSubMessage(String submessage)
|
||||
{
|
||||
Kp2aLog.Log("status submessage: " + submessage);
|
||||
_submessage = submessage;
|
||||
if (_app != null && _progressDialog != null && _handler != null)
|
||||
{
|
||||
_handler.Post(() =>
|
||||
|
@@ -25,39 +25,107 @@ namespace keepass2android
|
||||
/// <summary>
|
||||
/// Class to run a task while a progress dialog is shown
|
||||
/// </summary>
|
||||
public class ProgressTask {
|
||||
private readonly Handler _handler;
|
||||
public class ProgressTask
|
||||
{
|
||||
//for handling Activity recreation situations, we need access to the currently active task. It must hold that there is no more than one active task.
|
||||
private static ProgressTask _currentTask = null;
|
||||
|
||||
public static void SetNewActiveActivity(Activity activeActivity)
|
||||
{
|
||||
if (_currentTask != null)
|
||||
{
|
||||
_currentTask.ActiveActivity = activeActivity;
|
||||
}
|
||||
}
|
||||
public static void RemoveActiveActivity(Activity activity)
|
||||
{
|
||||
if ((_currentTask != null) && (_currentTask._activeActivity == activity))
|
||||
_currentTask.ActiveActivity = null;
|
||||
|
||||
}
|
||||
|
||||
public Activity ActiveActivity
|
||||
{
|
||||
get { return _activeActivity; }
|
||||
private set
|
||||
{
|
||||
_activeActivity = value;
|
||||
if (_task != null)
|
||||
_task.ActiveActivity = _activeActivity;
|
||||
if (_activeActivity != null)
|
||||
{
|
||||
SetupProgressDialog(_app);
|
||||
_progressDialog.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Handler _handler;
|
||||
private readonly RunnableOnFinish _task;
|
||||
private readonly IProgressDialog _progressDialog;
|
||||
private IProgressDialog _progressDialog;
|
||||
private readonly IKp2aApp _app;
|
||||
private Thread _thread;
|
||||
private Activity _activeActivity;
|
||||
private ProgressDialogStatusLogger _progressDialogStatusLogger;
|
||||
|
||||
public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task) {
|
||||
public ProgressTask(IKp2aApp app, Activity activity, RunnableOnFinish task)
|
||||
{
|
||||
_activeActivity = activity;
|
||||
_task = task;
|
||||
_handler = app.UiThreadHandler;
|
||||
_app = app;
|
||||
|
||||
// Show process dialog
|
||||
_progressDialog = app.CreateProgressDialog(ctx);
|
||||
_progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
|
||||
_progressDialog.SetMessage("Initializing...");
|
||||
|
||||
// Set code to run when this is finished
|
||||
_task.OnFinishToRun = new AfterTask(task.OnFinishToRun, _handler, _progressDialog);
|
||||
_task.SetStatusLogger(new ProgressDialogStatusLogger(_app, _handler, _progressDialog));
|
||||
SetupProgressDialog(app);
|
||||
|
||||
// Set code to run when this is finished
|
||||
_task.OnFinishToRun = new AfterTask(activity, task.OnFinishToRun, _handler, this);
|
||||
|
||||
_task.SetStatusLogger(_progressDialogStatusLogger);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void Run() {
|
||||
// Show process dialog
|
||||
_progressDialog.Show();
|
||||
|
||||
private void SetupProgressDialog(IKp2aApp app)
|
||||
{
|
||||
string currentMessage = "Initializing...";
|
||||
string currentSubmessage = "";
|
||||
|
||||
if (_progressDialogStatusLogger != null)
|
||||
{
|
||||
currentMessage = _progressDialogStatusLogger.Message;
|
||||
currentSubmessage = _progressDialogStatusLogger.SubMessage;
|
||||
}
|
||||
|
||||
if (_progressDialog != null)
|
||||
{
|
||||
var pd = _progressDialog;
|
||||
app.UiThreadHandler.Post(() =>
|
||||
{
|
||||
pd.Dismiss();
|
||||
});
|
||||
}
|
||||
|
||||
// Show process dialog
|
||||
_progressDialog = app.CreateProgressDialog(_activeActivity);
|
||||
_progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title));
|
||||
_progressDialogStatusLogger = new ProgressDialogStatusLogger(_app, _handler, _progressDialog);
|
||||
_progressDialogStatusLogger.UpdateMessage(currentMessage);
|
||||
_progressDialogStatusLogger.UpdateSubMessage(currentSubmessage);
|
||||
}
|
||||
|
||||
public void Run(bool allowOverwriteCurrentTask = false)
|
||||
{
|
||||
if ((!allowOverwriteCurrentTask) && (_currentTask != null))
|
||||
throw new Exception("Cannot start another ProgressTask while ProgressTask is already running! " + _task.GetType().Name + "/" + _currentTask._task.GetType().Name);
|
||||
_currentTask = this;
|
||||
|
||||
// Show process dialog
|
||||
_progressDialog.Show();
|
||||
|
||||
|
||||
// Start Thread to Run task
|
||||
_thread = new Thread(_task.Run);
|
||||
_thread.Start();
|
||||
|
||||
}
|
||||
|
||||
public void JoinWorkerThread()
|
||||
@@ -66,11 +134,11 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
private class AfterTask : OnFinish {
|
||||
readonly IProgressDialog _progressDialog;
|
||||
readonly ProgressTask _progressTask;
|
||||
|
||||
public AfterTask (OnFinish finish, Handler handler, IProgressDialog pd): base(finish, handler)
|
||||
public AfterTask (Activity activity, OnFinish finish, Handler handler, ProgressTask pt): base(activity, finish, handler)
|
||||
{
|
||||
_progressDialog = pd;
|
||||
_progressTask = pt;
|
||||
}
|
||||
|
||||
public override void Run() {
|
||||
@@ -79,17 +147,22 @@ namespace keepass2android
|
||||
if (Handler != null) //can be null in tests
|
||||
{
|
||||
// Remove the progress dialog
|
||||
Handler.Post(delegate { _progressDialog.Dismiss(); });
|
||||
Handler.Post(delegate
|
||||
{
|
||||
_progressTask._progressDialog.Dismiss();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_progressDialog.Dismiss();
|
||||
_progressTask._progressDialog.Dismiss();
|
||||
}
|
||||
_currentTask = null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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));
|
||||
|
@@ -63,7 +63,8 @@ namespace keepass2android
|
||||
AskDeletePermanentlyItems,
|
||||
AskDeletePermanentlyItemsNoRecycle,
|
||||
InOfflineMode,
|
||||
DuplicateTitle,
|
||||
DocumentAccessRevoked,
|
||||
DuplicateTitle,
|
||||
TemplateTitle_IdCard,
|
||||
TemplateField_IdCard_Name,
|
||||
TemplateField_IdCard_PlaceOfIssue,
|
||||
@@ -84,6 +85,9 @@ namespace keepass2android
|
||||
AskAddTemplatesMessage,
|
||||
ReadOnlyReason_PreKitKat,
|
||||
ReadOnlyReason_ReadOnlyFlag,
|
||||
ReadOnlyReason_ReadOnlyKitKat
|
||||
ReadOnlyReason_ReadOnlyKitKat,
|
||||
ReadOnlyReason_LocalBackup,
|
||||
Ok,
|
||||
cancel
|
||||
}
|
||||
}
|
||||
|
@@ -18,8 +18,8 @@ namespace keepass2android
|
||||
private readonly IKp2aApp _app;
|
||||
|
||||
|
||||
public CheckDatabaseForChanges(Context context, IKp2aApp app, OnFinish finish)
|
||||
: base(finish)
|
||||
public CheckDatabaseForChanges(Activity context, IKp2aApp app, OnFinish finish)
|
||||
: base(context, finish)
|
||||
{
|
||||
_context = context;
|
||||
_app = app;
|
||||
@@ -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);
|
||||
|
@@ -21,12 +21,12 @@ using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Android.Content;
|
||||
using Java.Lang;
|
||||
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;
|
||||
@@ -34,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.
|
||||
@@ -74,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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -113,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>
|
||||
@@ -152,27 +119,20 @@ namespace keepass2android
|
||||
set { _databaseFormat = value; }
|
||||
}
|
||||
|
||||
public static string GetFingerprintPrefKey(IOConnectionInfo ioc)
|
||||
{
|
||||
var iocAsHexString = IocAsHexString(ioc);
|
||||
public string IocAsHexString()
|
||||
{
|
||||
return IoUtil.IocAsHexString(Ioc);
|
||||
}
|
||||
|
||||
return "kp2a_ioc_" + iocAsHexString;
|
||||
}
|
||||
public static string GetFingerprintPrefKey(IOConnectionInfo ioc)
|
||||
{
|
||||
var iocAsHexString = IoUtil.IocAsHexString(ioc);
|
||||
|
||||
public string IocAsHexString()
|
||||
{
|
||||
return IocAsHexString(Ioc);
|
||||
}
|
||||
return "kp2a_ioc_" + iocAsHexString;
|
||||
}
|
||||
|
||||
private static string IocAsHexString(IOConnectionInfo ioc)
|
||||
{
|
||||
SHA256Managed sha256 = new SHA256Managed();
|
||||
string iocAsHexString =
|
||||
MemUtil.ByteArrayToHexString(sha256.ComputeHash(Encoding.Unicode.GetBytes(ioc.Path.ToCharArray())));
|
||||
return iocAsHexString;
|
||||
}
|
||||
|
||||
public static string GetFingerprintModePrefKey(IOConnectionInfo ioc)
|
||||
public static string GetFingerprintModePrefKey(IOConnectionInfo ioc)
|
||||
{
|
||||
return GetFingerprintPrefKey(ioc) + "_mode";
|
||||
}
|
||||
@@ -225,10 +185,9 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
public void SaveData(Context ctx) {
|
||||
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());
|
||||
|
||||
@@ -247,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)
|
||||
@@ -266,7 +229,6 @@ namespace keepass2android
|
||||
}
|
||||
* */
|
||||
}
|
||||
Groups[g.Uuid] = g;
|
||||
PopulateGlobals(g);
|
||||
}
|
||||
}
|
||||
@@ -274,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]
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -11,12 +11,12 @@ namespace keepass2android
|
||||
{
|
||||
public class SynchronizeCachedDatabase: RunnableOnFinish
|
||||
{
|
||||
private readonly Context _context;
|
||||
private readonly Activity _context;
|
||||
private readonly IKp2aApp _app;
|
||||
private SaveDb _saveDb;
|
||||
|
||||
public SynchronizeCachedDatabase(Context context, IKp2aApp app, OnFinish finish)
|
||||
: base(finish)
|
||||
public SynchronizeCachedDatabase(Activity context, IKp2aApp app, OnFinish finish)
|
||||
: base(context, finish)
|
||||
{
|
||||
_context = context;
|
||||
_app = app;
|
||||
@@ -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))
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace keepass2android
|
||||
if (cachingFileStorage.HasLocalChanges(ioc))
|
||||
{
|
||||
//conflict! need to merge
|
||||
_saveDb = new SaveDb(_context, _app, new ActionOnFinish((success, result) =>
|
||||
_saveDb = new SaveDb(_context, _app, new ActionOnFinish(ActiveActivity, (success, result, activity) =>
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -16,41 +16,37 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.OS;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
public class ActionOnFinish: OnFinish
|
||||
{
|
||||
public delegate void ActionToPerformOnFinsh(bool success, String message);
|
||||
public delegate void ActionToPerformOnFinsh(bool success, String message, Activity activeActivity);
|
||||
|
||||
readonly ActionToPerformOnFinsh _actionToPerform;
|
||||
|
||||
public ActionOnFinish(ActionToPerformOnFinsh actionToPerform) : base(null, null)
|
||||
public ActionOnFinish(Activity activity, ActionToPerformOnFinsh actionToPerform) : base(activity, null, null)
|
||||
{
|
||||
_actionToPerform = actionToPerform;
|
||||
}
|
||||
|
||||
public ActionOnFinish(ActionToPerformOnFinsh actionToPerform, OnFinish finish) : base(finish)
|
||||
public ActionOnFinish(Activity activity, ActionToPerformOnFinsh actionToPerform, OnFinish finish) : base(activity, finish)
|
||||
{
|
||||
_actionToPerform = actionToPerform;
|
||||
}
|
||||
|
||||
public ActionOnFinish(ActionToPerformOnFinsh actionToPerform, Handler handler) : base(handler)
|
||||
{
|
||||
_actionToPerform = actionToPerform;
|
||||
}
|
||||
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
if (Message == null)
|
||||
Message = "";
|
||||
if (Handler != null)
|
||||
{
|
||||
Handler.Post(() => {_actionToPerform(Success, Message);});
|
||||
Handler.Post(() => {_actionToPerform(Success, Message, ActiveActivity);});
|
||||
}
|
||||
else
|
||||
_actionToPerform(Success, Message);
|
||||
_actionToPerform(Success, Message, ActiveActivity);
|
||||
base.Run();
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
|
||||
@@ -23,26 +24,26 @@ namespace keepass2android
|
||||
public class AddEntry : RunnableOnFinish {
|
||||
protected Database Db
|
||||
{
|
||||
get { return _app.GetDb(); }
|
||||
get { return _app.CurrentDb; }
|
||||
}
|
||||
|
||||
private readonly IKp2aApp _app;
|
||||
private readonly PwEntry _entry;
|
||||
private readonly PwGroup _parentGroup;
|
||||
private readonly Context _ctx;
|
||||
private readonly Activity _ctx;
|
||||
|
||||
public static AddEntry GetInstance(Context ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish) {
|
||||
public static AddEntry GetInstance(Activity ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish) {
|
||||
|
||||
return new AddEntry(ctx, app, entry, parentGroup, finish);
|
||||
}
|
||||
|
||||
protected AddEntry(Context ctx, IKp2aApp app, PwEntry entry, PwGroup parentGroup, OnFinish finish):base(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(app.GetDb(), entry, OnFinishToRun);
|
||||
_onFinishToRun = new AfterAdd(ctx, app.CurrentDb, entry, app,OnFinishToRun);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,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();
|
||||
}
|
||||
@@ -67,12 +68,13 @@ namespace keepass2android
|
||||
private class AfterAdd : OnFinish {
|
||||
private readonly Database _db;
|
||||
private readonly PwEntry _entry;
|
||||
private readonly IKp2aApp _app;
|
||||
|
||||
public AfterAdd(Database db, PwEntry entry, OnFinish finish):base(finish) {
|
||||
public AfterAdd(Activity activity, Database db, PwEntry entry, IKp2aApp app, OnFinish finish):base(activity, finish) {
|
||||
_db = db;
|
||||
_entry = entry;
|
||||
|
||||
}
|
||||
_app = app;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -82,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);
|
||||
|
@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
|
||||
@@ -25,25 +26,28 @@ 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 Context _ctx;
|
||||
readonly Activity _ctx;
|
||||
|
||||
|
||||
public static AddGroup GetInstance(Context ctx, IKp2aApp app, string name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave) {
|
||||
public static AddGroup GetInstance(Activity ctx, IKp2aApp app, string name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave) {
|
||||
return new AddGroup(ctx, app, name, iconid, groupCustomIconId, parent, finish, dontSave);
|
||||
}
|
||||
|
||||
|
||||
private AddGroup(Context ctx, IKp2aApp app, String name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave)
|
||||
: base(finish)
|
||||
private AddGroup(Activity ctx, IKp2aApp app, String name, int iconid, PwUuid groupCustomIconId, PwGroup parent, OnFinish finish, bool dontSave)
|
||||
: base(ctx, finish)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_name = name;
|
||||
@@ -53,7 +57,7 @@ namespace keepass2android
|
||||
DontSave = dontSave;
|
||||
_app = app;
|
||||
|
||||
_onFinishToRun = new AfterAdd(this, OnFinishToRun);
|
||||
_onFinishToRun = new AfterAdd(ctx, this, OnFinishToRun);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,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();
|
||||
}
|
||||
@@ -76,7 +82,7 @@ namespace keepass2android
|
||||
private class AfterAdd : OnFinish {
|
||||
readonly AddGroup _addGroup;
|
||||
|
||||
public AfterAdd(AddGroup addGroup,OnFinish finish): base(finish) {
|
||||
public AfterAdd(Activity activity, AddGroup addGroup,OnFinish finish): base(activity, finish) {
|
||||
_addGroup = addGroup;
|
||||
}
|
||||
|
||||
@@ -85,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();
|
||||
|
@@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2016 Philipp Crocoll. This file
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Security;
|
||||
@@ -27,7 +28,7 @@ namespace keepass2android
|
||||
{
|
||||
public class AddTemplateEntries : RunnableOnFinish {
|
||||
|
||||
class TemplateEntry
|
||||
public class TemplateEntry
|
||||
{
|
||||
public UiStringKey Title { get; set; }
|
||||
public PwIcon Icon { get; set; }
|
||||
@@ -46,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
|
||||
}
|
||||
@@ -124,14 +126,14 @@ namespace keepass2android
|
||||
|
||||
protected Database Db
|
||||
{
|
||||
get { return _app.GetDb(); }
|
||||
get { return _app.CurrentDb; }
|
||||
}
|
||||
|
||||
private readonly IKp2aApp _app;
|
||||
private readonly Context _ctx;
|
||||
private readonly Activity _ctx;
|
||||
|
||||
public AddTemplateEntries(Context ctx, IKp2aApp app, OnFinish finish)
|
||||
: base(finish)
|
||||
public AddTemplateEntries(Activity ctx, IKp2aApp app, OnFinish finish)
|
||||
: base(ctx, finish)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_app = app;
|
||||
@@ -139,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()
|
||||
{
|
||||
@@ -284,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;
|
||||
@@ -297,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();
|
||||
}
|
||||
@@ -314,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;
|
||||
}
|
||||
@@ -358,7 +373,7 @@ namespace keepass2android
|
||||
private readonly Database _db;
|
||||
private readonly List<PwEntry> _entries;
|
||||
|
||||
public AfterAdd(Database db, List<PwEntry> entries, OnFinish finish):base(finish) {
|
||||
public AfterAdd(Activity activity, Database db, List<PwEntry> entries, OnFinish finish):base(activity, finish) {
|
||||
_db = db;
|
||||
_entries = entries;
|
||||
|
||||
@@ -372,8 +387,12 @@ namespace keepass2android
|
||||
base.Run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static bool IsTemplateId(PwUuid pwUuid)
|
||||
{
|
||||
return TemplateEntries.Any(te => te.Uuid.Equals(pwUuid));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ namespace keepass2android.database.edit
|
||||
{
|
||||
public class CopyEntry: AddEntry
|
||||
{
|
||||
public CopyEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish)
|
||||
public CopyEntry(Activity ctx, IKp2aApp app, PwEntry entry, OnFinish finish)
|
||||
: base(ctx, app, CreateCopy(entry, app), entry.ParentGroup, finish)
|
||||
{
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Cryptography.KeyDerivation;
|
||||
@@ -26,36 +27,36 @@ 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 Context _ctx;
|
||||
private readonly Activity _ctx;
|
||||
private readonly IKp2aApp _app;
|
||||
private CompositeKey _key;
|
||||
private readonly bool _makeCurrent;
|
||||
|
||||
public CreateDb(IKp2aApp app, Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(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, Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key)
|
||||
: base(finish)
|
||||
public CreateDb(IKp2aApp app, Activity ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave, CompositeKey key, bool makeCurrent)
|
||||
: base(ctx, finish)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_ioc = ioc;
|
||||
_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();
|
||||
|
||||
@@ -73,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
|
||||
@@ -87,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();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Interfaces;
|
||||
@@ -28,9 +29,9 @@ namespace keepass2android
|
||||
private readonly PwEntry _entry;
|
||||
private UiStringKey _statusMessage;
|
||||
|
||||
public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish):base(finish, app) {
|
||||
Ctx = ctx;
|
||||
Db = app.GetDb();
|
||||
public DeleteEntry(Activity activiy, IKp2aApp app, PwEntry entry, OnFinish finish):base(activiy, finish, app) {
|
||||
Ctx = activiy;
|
||||
Db = app.FindDatabaseForElement(entry);
|
||||
_entry = entry;
|
||||
|
||||
}
|
||||
@@ -39,7 +40,7 @@ namespace keepass2android
|
||||
{
|
||||
get
|
||||
{
|
||||
return App.GetDb().DatabaseFormat.CanRecycle && CanRecycleGroup(_entry.ParentGroup);
|
||||
return Db.DatabaseFormat.CanRecycle && CanRecycleGroup(_entry.ParentGroup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
|
||||
@@ -28,10 +29,10 @@ namespace keepass2android
|
||||
private PwGroup _group;
|
||||
protected bool DontSave;
|
||||
|
||||
public DeleteGroup(Context ctx, IKp2aApp app, PwGroup group, OnFinish finish)
|
||||
: base(finish, app)
|
||||
public DeleteGroup(Activity activity, IKp2aApp app, PwGroup group, OnFinish finish)
|
||||
: base(activity, finish, app)
|
||||
{
|
||||
SetMembers(ctx, app, group, false);
|
||||
SetMembers(activity, app, group, false);
|
||||
}
|
||||
/*
|
||||
public DeleteGroup(Context ctx, Database db, PwGroup group, Activity act, OnFinish finish, bool dontSave)
|
||||
@@ -44,9 +45,9 @@ namespace keepass2android
|
||||
SetMembers(ctx, db, group, null, dontSave);
|
||||
}
|
||||
*/
|
||||
private void SetMembers(Context ctx, IKp2aApp app, PwGroup group, bool dontSave)
|
||||
private void SetMembers(Activity activity, IKp2aApp app, PwGroup group, bool dontSave)
|
||||
{
|
||||
base.SetMembers(ctx, app.GetDb());
|
||||
base.SetMembers(activity, app.FindDatabaseForElement(group));
|
||||
|
||||
_group = group;
|
||||
DontSave = dontSave;
|
||||
@@ -57,7 +58,7 @@ namespace keepass2android
|
||||
{
|
||||
get
|
||||
{
|
||||
return App.GetDb().DatabaseFormat.CanRecycle && CanRecycleGroup(_group);
|
||||
return Db.DatabaseFormat.CanRecycle && CanRecycleGroup(_group);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,31 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Interfaces;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
public class DeleteMultipleItems : DeleteRunnable
|
||||
public class DeleteMultipleItemsFromOneDatabase : DeleteRunnable
|
||||
{
|
||||
private readonly List<IStructureItem> _elementsToDelete;
|
||||
private readonly bool _canRecycle;
|
||||
|
||||
public DeleteMultipleItems(Context ctx, Database db, List<IStructureItem> elementsToDelete, OnFinish finish, IKp2aApp app)
|
||||
: base(finish, app)
|
||||
public DeleteMultipleItemsFromOneDatabase(Activity activity, Database db, List<IStructureItem> elementsToDelete, OnFinish finish, IKp2aApp app)
|
||||
: base(activity, finish, app)
|
||||
{
|
||||
_elementsToDelete = elementsToDelete;
|
||||
SetMembers(ctx, db);
|
||||
SetMembers(activity, db);
|
||||
|
||||
//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;
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
|
||||
@@ -7,8 +8,8 @@ namespace keepass2android
|
||||
{
|
||||
public abstract class DeleteRunnable : RunnableOnFinish
|
||||
{
|
||||
protected DeleteRunnable(OnFinish finish, IKp2aApp app)
|
||||
: base(finish)
|
||||
protected DeleteRunnable(Activity activity, OnFinish finish, IKp2aApp app)
|
||||
: base(activity, finish)
|
||||
{
|
||||
App = app;
|
||||
}
|
||||
@@ -17,11 +18,11 @@ namespace keepass2android
|
||||
|
||||
protected Database Db;
|
||||
|
||||
protected Context Ctx;
|
||||
protected Activity Ctx;
|
||||
|
||||
protected void SetMembers(Context ctx, Database db)
|
||||
protected void SetMembers(Activity activity, Database db)
|
||||
{
|
||||
Ctx = ctx;
|
||||
Ctx = activity;
|
||||
Db = db;
|
||||
}
|
||||
|
||||
@@ -99,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;
|
||||
@@ -120,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);
|
||||
|
||||
|
||||
|
||||
@@ -148,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);
|
||||
|
||||
|
||||
}
|
||||
@@ -181,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
|
||||
{
|
||||
@@ -209,36 +215,46 @@ namespace keepass2android
|
||||
Android.Util.Log.Debug("KP2A", "Calling PerformDelete..");
|
||||
PerformDelete(touchedGroups, permanentlyDeletedGroups);
|
||||
|
||||
_onFinishToRun = new ActionOnFinish((success, message) =>
|
||||
_onFinishToRun = new ActionOnFinish(ActiveActivity,(success, message, activity) =>
|
||||
{
|
||||
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; }
|
||||
|
||||
|
@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
|
||||
@@ -25,17 +26,20 @@ 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;
|
||||
internal PwGroup Group;
|
||||
readonly Context _ctx;
|
||||
readonly Activity _ctx;
|
||||
|
||||
public EditGroup(Context ctx, IKp2aApp app, String name, PwIcon iconid, PwUuid customIconId, PwGroup group, OnFinish finish)
|
||||
: base(finish)
|
||||
public EditGroup(Activity ctx, IKp2aApp app, String name, PwIcon iconid, PwUuid customIconId, PwGroup group, OnFinish finish)
|
||||
: base(ctx, finish)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_name = name;
|
||||
@@ -44,7 +48,7 @@ namespace keepass2android
|
||||
_customIconId = customIconId;
|
||||
_app = app;
|
||||
|
||||
_onFinishToRun = new AfterEdit(this, OnFinishToRun);
|
||||
_onFinishToRun = new AfterEdit(ctx, this, OnFinishToRun);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,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();
|
||||
}
|
||||
@@ -64,8 +68,8 @@ namespace keepass2android
|
||||
private class AfterEdit : OnFinish {
|
||||
readonly EditGroup _editGroup;
|
||||
|
||||
public AfterEdit(EditGroup editGroup, OnFinish finish)
|
||||
: base(finish)
|
||||
public AfterEdit(Activity ctx, EditGroup editGroup, OnFinish finish)
|
||||
: base(ctx, finish)
|
||||
{
|
||||
_editGroup = editGroup;
|
||||
}
|
||||
@@ -75,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();
|
||||
|
@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Android.App;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -23,7 +24,7 @@ namespace keepass2android
|
||||
public abstract class FileOnFinish : OnFinish {
|
||||
private String _filename = "";
|
||||
|
||||
protected FileOnFinish(FileOnFinish finish):base(finish) {
|
||||
protected FileOnFinish(Activity activity, FileOnFinish finish):base(activity, finish) {
|
||||
}
|
||||
|
||||
public string Filename
|
||||
|
@@ -18,7 +18,10 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
using System;
|
||||
using System.IO;
|
||||
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;
|
||||
@@ -34,28 +37,35 @@ namespace keepass2android
|
||||
private readonly bool _rememberKeyfile;
|
||||
IDatabaseFormat _format;
|
||||
|
||||
public LoadDb(IKp2aApp app, IOConnectionInfo ioc, Task<MemoryStream> databaseData, CompositeKey compositeKey, String keyfileOrProvider, OnFinish finish): base(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
|
||||
{
|
||||
try
|
||||
{
|
||||
//make sure the file data is stored in the recent files list even if loading fails
|
||||
SaveFileData(_ioc, _keyfileOrProvider);
|
||||
|
||||
|
||||
StatusLogger.UpdateMessage(UiStringKey.loading_database);
|
||||
StatusLogger.UpdateMessage(UiStringKey.loading_database);
|
||||
//get the stream data into a single stream variable (databaseStream) regardless whether its preloaded or not:
|
||||
MemoryStream preloadedMemoryStream = _databaseData == null ? null : _databaseData.Result;
|
||||
MemoryStream databaseStream;
|
||||
@@ -74,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)
|
||||
{
|
||||
@@ -85,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)
|
||||
{
|
||||
@@ -96,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;
|
||||
}
|
||||
|
||||
@@ -121,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.
|
||||
@@ -134,15 +148,16 @@ namespace keepass2android
|
||||
//now let's go:
|
||||
try
|
||||
{
|
||||
_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format);
|
||||
SaveFileData(_ioc, _keyfileOrProvider);
|
||||
Database newDb = _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format, _makeCurrent);
|
||||
Kp2aLog.Log("LoadDB OK");
|
||||
Finish(true, _format.SuccessMessage);
|
||||
|
||||
Finish(true, _format.SuccessMessage);
|
||||
return newDb;
|
||||
}
|
||||
catch (OldFormatException)
|
||||
{
|
||||
_format = new KdbDatabaseFormat(_app);
|
||||
TryLoad(databaseStream);
|
||||
return TryLoad(databaseStream);
|
||||
}
|
||||
catch (InvalidCompositeKeyException)
|
||||
{
|
||||
@@ -154,7 +169,7 @@ namespace keepass2android
|
||||
//retry without password:
|
||||
_compositeKey.RemoveUserKey(passwordKey);
|
||||
//retry:
|
||||
TryLoad(databaseStream);
|
||||
return TryLoad(databaseStream);
|
||||
}
|
||||
else throw;
|
||||
}
|
||||
@@ -167,7 +182,7 @@ namespace keepass2android
|
||||
{
|
||||
keyfileOrProvider = "";
|
||||
}
|
||||
_app.StoreOpenedFileAsRecent(ioc, keyfileOrProvider);
|
||||
_app.StoreOpenedFileAsRecent(ioc, keyfileOrProvider, _updateLastUsageTimestamp);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Interfaces;
|
||||
@@ -12,10 +14,10 @@ namespace keepass2android.database.edit
|
||||
{
|
||||
private readonly List<IStructureItem> _elementsToMove;
|
||||
private readonly PwGroup _targetGroup;
|
||||
private readonly Context _ctx;
|
||||
private readonly Activity _ctx;
|
||||
private readonly IKp2aApp _app;
|
||||
|
||||
public MoveElements(List<IStructureItem> elementsToMove, PwGroup targetGroup, Context ctx, IKp2aApp app, OnFinish finish) : base(finish)
|
||||
public MoveElements(List<IStructureItem> elementsToMove, PwGroup targetGroup, Activity ctx, IKp2aApp app, OnFinish finish) : base(ctx, finish)
|
||||
{
|
||||
_elementsToMove = elementsToMove;
|
||||
_targetGroup = targetGroup;
|
||||
@@ -49,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)
|
||||
@@ -62,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
|
||||
{
|
||||
@@ -73,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((success, message) =>
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,8 @@ 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;
|
||||
using Android.Widget;
|
||||
@@ -27,49 +29,77 @@ 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;
|
||||
|
||||
public ProgressDialogStatusLogger StatusLogger
|
||||
|
||||
public ProgressDialogStatusLogger StatusLogger
|
||||
{
|
||||
get { return _statusLogger; }
|
||||
set { _statusLogger = value; }
|
||||
}
|
||||
|
||||
public Activity ActiveActivity
|
||||
{
|
||||
get { return _activeActivity; }
|
||||
set
|
||||
{
|
||||
_activeActivity = value;
|
||||
if (BaseOnFinish != null)
|
||||
{
|
||||
BaseOnFinish.ActiveActivity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected OnFinish(Handler handler) {
|
||||
|
||||
protected OnFinish(Activity activeActivity, Handler handler)
|
||||
{
|
||||
ActiveActivity = activeActivity;
|
||||
BaseOnFinish = null;
|
||||
Handler = handler;
|
||||
|
||||
}
|
||||
|
||||
protected OnFinish(OnFinish finish, Handler handler) {
|
||||
protected OnFinish(Activity activeActivity, OnFinish finish, Handler handler)
|
||||
{
|
||||
ActiveActivity = activeActivity;
|
||||
BaseOnFinish = finish;
|
||||
Handler = handler;
|
||||
}
|
||||
|
||||
protected OnFinish(OnFinish finish) {
|
||||
protected OnFinish(Activity activeActivity, OnFinish finish)
|
||||
{
|
||||
ActiveActivity = activeActivity;
|
||||
BaseOnFinish = finish;
|
||||
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);
|
||||
@@ -79,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, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,8 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -23,8 +25,11 @@ namespace keepass2android
|
||||
|
||||
protected OnFinish _onFinishToRun;
|
||||
public ProgressDialogStatusLogger StatusLogger = new ProgressDialogStatusLogger(); //default: empty but not null
|
||||
private Activity _activeActivity;
|
||||
|
||||
protected RunnableOnFinish(OnFinish finish) {
|
||||
protected RunnableOnFinish(Activity activeActivity, OnFinish finish)
|
||||
{
|
||||
_activeActivity = activeActivity;
|
||||
_onFinishToRun = finish;
|
||||
}
|
||||
|
||||
@@ -34,9 +39,20 @@ namespace keepass2android
|
||||
set { _onFinishToRun = value; }
|
||||
}
|
||||
|
||||
protected void Finish(bool result, String message, Exception exception = null) {
|
||||
public Activity ActiveActivity
|
||||
{
|
||||
get { return _activeActivity; }
|
||||
set
|
||||
{
|
||||
_activeActivity = value;
|
||||
if (_onFinishToRun != null)
|
||||
_onFinishToRun.ActiveActivity = _activeActivity;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -56,7 +72,7 @@ namespace keepass2android
|
||||
StatusLogger = status;
|
||||
}
|
||||
|
||||
abstract public void Run();
|
||||
public abstract void Run();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Java.Lang;
|
||||
@@ -33,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
|
||||
@@ -42,9 +44,10 @@ namespace keepass2android
|
||||
private readonly Context _ctx;
|
||||
private Thread _workerThread;
|
||||
|
||||
public SaveDb(Context ctx, IKp2aApp app, OnFinish finish, bool dontSave)
|
||||
: base(finish)
|
||||
public SaveDb(Activity ctx, IKp2aApp app, Database db, OnFinish finish, bool dontSave)
|
||||
: base(ctx, finish)
|
||||
{
|
||||
_db = db;
|
||||
_ctx = ctx;
|
||||
_app = app;
|
||||
_dontSave = dontSave;
|
||||
@@ -58,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(Context ctx, IKp2aApp app, OnFinish finish, bool dontSave, Stream streamForOrigFile)
|
||||
: base(finish)
|
||||
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(Context ctx, IKp2aApp app, OnFinish finish)
|
||||
: base(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);
|
||||
@@ -108,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:
|
||||
)
|
||||
{
|
||||
|
||||
@@ -127,6 +139,7 @@ namespace keepass2android
|
||||
//small.
|
||||
MergeIn(fileStorage, ioc);
|
||||
PerformSaveWithoutCheck(fileStorage, ioc);
|
||||
_db.UpdateGlobals();
|
||||
Finish(true);
|
||||
};
|
||||
RunInWorkerThread(runHandler);
|
||||
@@ -216,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);
|
||||
@@ -248,8 +261,8 @@ namespace keepass2android
|
||||
private void PerformSaveWithoutCheck(IFileStorage fileStorage, IOConnectionInfo ioc)
|
||||
{
|
||||
StatusLogger.UpdateSubMessage("");
|
||||
_app.GetDb().SaveData(_ctx);
|
||||
_app.GetDb().LastFileVersion = fileStorage.GetCurrentFileVersionFast(ioc);
|
||||
_db.SaveData();
|
||||
_db.LastFileVersion = fileStorage.GetCurrentFileVersionFast(ioc);
|
||||
}
|
||||
|
||||
public byte[] HashOriginalFile(IOConnectionInfo iocFile)
|
||||
|
@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using System;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Keys;
|
||||
@@ -27,9 +28,9 @@ namespace keepass2android
|
||||
private readonly String _keyfile;
|
||||
private readonly IKp2aApp _app;
|
||||
private readonly bool _dontSave;
|
||||
private readonly Context _ctx;
|
||||
private readonly Activity _ctx;
|
||||
|
||||
public SetPassword(Context ctx, IKp2aApp app, String password, String keyfile, OnFinish finish): base(finish) {
|
||||
public SetPassword(Activity ctx, IKp2aApp app, String password, String keyfile, OnFinish finish): base(ctx, finish) {
|
||||
_ctx = ctx;
|
||||
_app = app;
|
||||
_password = password;
|
||||
@@ -37,8 +38,8 @@ namespace keepass2android
|
||||
_dontSave = false;
|
||||
}
|
||||
|
||||
public SetPassword(Context ctx, IKp2aApp app, String password, String keyfile, OnFinish finish, bool dontSave)
|
||||
: base(finish)
|
||||
public SetPassword(Activity ctx, IKp2aApp app, String password, String keyfile, OnFinish finish, bool dontSave)
|
||||
: base(ctx, finish)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_app = app;
|
||||
@@ -51,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));
|
||||
@@ -72,8 +73,8 @@ namespace keepass2android
|
||||
pm.MasterKey = newKey;
|
||||
|
||||
// Save Database
|
||||
_onFinishToRun = new AfterSave(previousKey, previousMasterKeyChanged, pm, OnFinishToRun);
|
||||
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, _dontSave);
|
||||
_onFinishToRun = new AfterSave(ActiveActivity, previousKey, previousMasterKeyChanged, pm, OnFinishToRun);
|
||||
SaveDb save = new SaveDb(_ctx, _app, _app.CurrentDb, OnFinishToRun, _dontSave);
|
||||
save.SetStatusLogger(StatusLogger);
|
||||
save.Run();
|
||||
}
|
||||
@@ -83,7 +84,7 @@ namespace keepass2android
|
||||
private readonly DateTime _previousKeyChanged;
|
||||
private readonly PwDatabase _db;
|
||||
|
||||
public AfterSave(CompositeKey backup, DateTime previousKeyChanged, PwDatabase db, OnFinish finish): base(finish) {
|
||||
public AfterSave(Activity activity, CompositeKey backup, DateTime previousKeyChanged, PwDatabase db, OnFinish finish): base(activity, finish) {
|
||||
_previousKeyChanged = previousKeyChanged;
|
||||
_backup = backup;
|
||||
_db = db;
|
||||
|
@@ -15,6 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
|
||||
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib;
|
||||
|
||||
@@ -23,19 +24,19 @@ namespace keepass2android
|
||||
|
||||
public class UpdateEntry : RunnableOnFinish {
|
||||
private readonly IKp2aApp _app;
|
||||
private readonly Context _ctx;
|
||||
private readonly Activity _ctx;
|
||||
|
||||
public UpdateEntry(Context ctx, IKp2aApp app, PwEntry oldE, PwEntry newE, OnFinish finish):base(finish) {
|
||||
public UpdateEntry(Activity ctx, IKp2aApp app, PwEntry oldE, PwEntry newE, OnFinish finish):base(ctx, finish) {
|
||||
_ctx = ctx;
|
||||
_app = app;
|
||||
|
||||
_onFinishToRun = new AfterUpdate(oldE, newE, app, finish);
|
||||
_onFinishToRun = new AfterUpdate(ctx, oldE, newE, app, finish);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -45,7 +46,7 @@ namespace keepass2android
|
||||
private readonly PwEntry _updatedEntry;
|
||||
private readonly IKp2aApp _app;
|
||||
|
||||
public AfterUpdate(PwEntry backup, PwEntry updatedEntry, IKp2aApp app, OnFinish finish):base(finish) {
|
||||
public AfterUpdate(Activity activity, PwEntry backup, PwEntry updatedEntry, IKp2aApp app, OnFinish finish):base(activity, finish) {
|
||||
_backup = backup;
|
||||
_updatedEntry = updatedEntry;
|
||||
_app = app;
|
||||
@@ -58,7 +59,7 @@ namespace keepass2android
|
||||
if ( parent != null ) {
|
||||
|
||||
// Mark parent group dirty
|
||||
_app.GetDb().Dirty.Add(parent);
|
||||
_app.DirtyGroups.Add(parent);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Xamarin.Android.Arch.Core.Common" version="1.0.0" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Arch.Lifecycle.Common" version="1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Arch.Lifecycle.Runtime" version="1.0.0" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.Annotations" version="26.1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.Core.UI" version="26.1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.Core.Utils" version="26.1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.Fragment" version="26.1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.Media.Compat" version="26.1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.v13" version="26.1.0.1" targetFramework="monoandroid81" />
|
||||
<package id="Xamarin.Android.Support.v4" version="23.1.1.0" targetFramework="MonoAndroid50" />
|
||||
</packages>
|
@@ -63,8 +63,8 @@
|
||||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||
<TransformFile Include="Transforms\Metadata.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
||||
<ItemGroup>
|
||||
<Folder Include="libs\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Novell\Xamarin.Android.Bindings.targets" />
|
||||
</Project>
|
48
src/PCloudBindings/Additions/AboutAdditions.txt
Normal file
48
src/PCloudBindings/Additions/AboutAdditions.txt
Normal 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; }
|
||||
}
|
24
src/PCloudBindings/Jars/AboutJars.txt
Normal file
24
src/PCloudBindings/Jars/AboutJars.txt
Normal 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".
|
BIN
src/PCloudBindings/Jars/pcloud-sdk-android-1.0.1.aar
Normal file
BIN
src/PCloudBindings/Jars/pcloud-sdk-android-1.0.1.aar
Normal file
Binary file not shown.
BIN
src/PCloudBindings/Jars/pcloud-sdk-java-core-1.0.1.jar
Normal file
BIN
src/PCloudBindings/Jars/pcloud-sdk-java-core-1.0.1.jar
Normal file
Binary file not shown.
90
src/PCloudBindings/PCloudBindings.csproj
Normal file
90
src/PCloudBindings/PCloudBindings.csproj
Normal 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>
|
30
src/PCloudBindings/Properties/AssemblyInfo.cs
Normal file
30
src/PCloudBindings/Properties/AssemblyInfo.cs
Normal 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")]
|
14
src/PCloudBindings/Transforms/EnumFields.xml
Normal file
14
src/PCloudBindings/Transforms/EnumFields.xml
Normal 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>
|
13
src/PCloudBindings/Transforms/EnumMethods.xml
Normal file
13
src/PCloudBindings/Transforms/EnumMethods.xml
Normal 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>
|
10
src/PCloudBindings/Transforms/Metadata.xml
Normal file
10
src/PCloudBindings/Transforms/Metadata.xml
Normal 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>
|
@@ -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
20
src/build-scripts/build-all.sh
Executable 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
8
src/build-scripts/build-apk.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
pushd ../keepass2android
|
||||
|
||||
xabuild keepass2android.csproj /t:SignAndroidPackage "$@"
|
||||
|
||||
popd
|
@@ -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
22
src/build-scripts/build-java.sh
Executable 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
|
25
src/build-scripts/build-xamarin.sh
Executable file
25
src/build-scripts/build-xamarin.sh
Executable 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
55
src/build.readme.md
Normal 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`
|
@@ -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.
|
||||
|
||||
|
@@ -32,11 +32,17 @@ dependencies {
|
||||
compile 'com.google.apis:google-api-services-drive:v2-rev102-1.16.0-rc'
|
||||
compile 'com.dropbox.core:dropbox-core-sdk:3.0.3'
|
||||
//onedrive:
|
||||
compile('com.onedrive.sdk:onedrive-sdk-android:1.2+') {
|
||||
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.+'
|
||||
compile 'com.microsoft.aad:adal:1.1.+'
|
||||
compile 'com.microsoft.services.msa:msa-auth:0.8.6'
|
||||
compile 'com.microsoft.aad:adal:1.14.0'
|
||||
|
||||
}
|
||||
|
@@ -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>
|
@@ -1,6 +1,6 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
|
||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@@ -213,8 +213,11 @@ public class Buffer{
|
||||
}
|
||||
|
||||
void checkFreeSize(int n){
|
||||
if(buffer.length<index+n){
|
||||
byte[] tmp = new byte[buffer.length*2];
|
||||
int size = index+n+Session.buffer_margin;
|
||||
if(buffer.length<size){
|
||||
int i = buffer.length*2;
|
||||
if(i<size) i = size;
|
||||
byte[] tmp = new byte[i];
|
||||
System.arraycopy(buffer, 0, tmp, 0, index);
|
||||
buffer = tmp;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
|
||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@@ -192,29 +192,38 @@ public abstract class Channel implements Runnable{
|
||||
io.setExtOutputStream(out, dontclose);
|
||||
}
|
||||
public InputStream getInputStream() throws IOException {
|
||||
PipedInputStream in=
|
||||
int max_input_buffer_size = 32*1024;
|
||||
try {
|
||||
max_input_buffer_size =
|
||||
Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
|
||||
}
|
||||
catch(Exception e){}
|
||||
PipedInputStream in =
|
||||
new MyPipedInputStream(
|
||||
32*1024 // this value should be customizable.
|
||||
32*1024, // this value should be customizable.
|
||||
max_input_buffer_size
|
||||
);
|
||||
io.setOutputStream(new PassiveOutputStream(in), false);
|
||||
boolean resizable = 32*1024<max_input_buffer_size;
|
||||
io.setOutputStream(new PassiveOutputStream(in, resizable), false);
|
||||
return in;
|
||||
}
|
||||
public InputStream getExtInputStream() throws IOException {
|
||||
PipedInputStream in=
|
||||
int max_input_buffer_size = 32*1024;
|
||||
try {
|
||||
max_input_buffer_size =
|
||||
Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
|
||||
}
|
||||
catch(Exception e){}
|
||||
PipedInputStream in =
|
||||
new MyPipedInputStream(
|
||||
32*1024 // this value should be customizable.
|
||||
32*1024, // this value should be customizable.
|
||||
max_input_buffer_size
|
||||
);
|
||||
io.setExtOutputStream(new PassiveOutputStream(in), false);
|
||||
boolean resizable = 32*1024<max_input_buffer_size;
|
||||
io.setExtOutputStream(new PassiveOutputStream(in, resizable), false);
|
||||
return in;
|
||||
}
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
/*
|
||||
PipedOutputStream out=new PipedOutputStream();
|
||||
io.setInputStream(new PassiveInputStream(out
|
||||
, 32*1024
|
||||
), false);
|
||||
return out;
|
||||
*/
|
||||
|
||||
final Channel channel=this;
|
||||
OutputStream out=new OutputStream(){
|
||||
@@ -317,15 +326,24 @@ public abstract class Channel implements Runnable{
|
||||
}
|
||||
|
||||
class MyPipedInputStream extends PipedInputStream{
|
||||
private int BUFFER_SIZE = 1024;
|
||||
private int max_buffer_size = BUFFER_SIZE;
|
||||
MyPipedInputStream() throws IOException{ super(); }
|
||||
MyPipedInputStream(int size) throws IOException{
|
||||
super();
|
||||
buffer=new byte[size];
|
||||
BUFFER_SIZE = size;
|
||||
max_buffer_size = size;
|
||||
}
|
||||
MyPipedInputStream(int size, int max_buffer_size) throws IOException{
|
||||
this(size);
|
||||
this.max_buffer_size = max_buffer_size;
|
||||
}
|
||||
MyPipedInputStream(PipedOutputStream out) throws IOException{ super(out); }
|
||||
MyPipedInputStream(PipedOutputStream out, int size) throws IOException{
|
||||
super(out);
|
||||
buffer=new byte[size];
|
||||
BUFFER_SIZE=size;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -343,12 +361,66 @@ public abstract class Channel implements Runnable{
|
||||
buffer[in++] = 0;
|
||||
read();
|
||||
}
|
||||
|
||||
private int freeSpace(){
|
||||
int size = 0;
|
||||
if(out < in) {
|
||||
size = buffer.length-in;
|
||||
}
|
||||
else if(in < out){
|
||||
if(in == -1) size = buffer.length;
|
||||
else size = out - in;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
synchronized void checkSpace(int len) throws IOException {
|
||||
int size = freeSpace();
|
||||
if(size<len){
|
||||
int datasize=buffer.length-size;
|
||||
int foo = buffer.length;
|
||||
while((foo - datasize) < len){
|
||||
foo*=2;
|
||||
}
|
||||
|
||||
if(foo > max_buffer_size){
|
||||
foo = max_buffer_size;
|
||||
}
|
||||
if((foo - datasize) < len) return;
|
||||
|
||||
byte[] tmp = new byte[foo];
|
||||
if(out < in) {
|
||||
System.arraycopy(buffer, 0, tmp, 0, buffer.length);
|
||||
}
|
||||
else if(in < out){
|
||||
if(in == -1) {
|
||||
}
|
||||
else {
|
||||
System.arraycopy(buffer, 0, tmp, 0, in);
|
||||
System.arraycopy(buffer, out,
|
||||
tmp, tmp.length-(buffer.length-out),
|
||||
(buffer.length-out));
|
||||
out = tmp.length-(buffer.length-out);
|
||||
}
|
||||
}
|
||||
else if(in == out){
|
||||
System.arraycopy(buffer, 0, tmp, 0, buffer.length);
|
||||
in=buffer.length;
|
||||
}
|
||||
buffer=tmp;
|
||||
}
|
||||
else if(buffer.length == size && size > BUFFER_SIZE) {
|
||||
int i = size/2;
|
||||
if(i<BUFFER_SIZE) i = BUFFER_SIZE;
|
||||
byte[] tmp = new byte[i];
|
||||
buffer=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
void setLocalWindowSizeMax(int foo){ this.lwsize_max=foo; }
|
||||
void setLocalWindowSize(int foo){ this.lwsize=foo; }
|
||||
void setLocalPacketSize(int foo){ this.lmpsize=foo; }
|
||||
synchronized void setRemoteWindowSize(long foo){ this.rwsize=foo; }
|
||||
synchronized void addRemoteWindowSize(int foo){
|
||||
synchronized void addRemoteWindowSize(long foo){
|
||||
this.rwsize+=foo;
|
||||
if(notifyme>0)
|
||||
notifyAll();
|
||||
@@ -384,12 +456,15 @@ public abstract class Channel implements Runnable{
|
||||
if(eof_local)return;
|
||||
eof_local=true;
|
||||
|
||||
int i = getRecipient();
|
||||
if(i == -1) return;
|
||||
|
||||
try{
|
||||
Buffer buf=new Buffer(100);
|
||||
Packet packet=new Packet(buf);
|
||||
packet.reset();
|
||||
buf.putByte((byte)Session.SSH_MSG_CHANNEL_EOF);
|
||||
buf.putInt(getRecipient());
|
||||
buf.putInt(i);
|
||||
synchronized(this){
|
||||
if(!close)
|
||||
getSession().write(packet);
|
||||
@@ -445,12 +520,15 @@ public abstract class Channel implements Runnable{
|
||||
close=true;
|
||||
eof_local=eof_remote=true;
|
||||
|
||||
int i = getRecipient();
|
||||
if(i == -1) return;
|
||||
|
||||
try{
|
||||
Buffer buf=new Buffer(100);
|
||||
Packet packet=new Packet(buf);
|
||||
packet.reset();
|
||||
buf.putByte((byte)Session.SSH_MSG_CHANNEL_CLOSE);
|
||||
buf.putInt(getRecipient());
|
||||
buf.putInt(i);
|
||||
synchronized(this){
|
||||
getSession().write(packet);
|
||||
}
|
||||
@@ -561,8 +639,25 @@ public abstract class Channel implements Runnable{
|
||||
}
|
||||
}
|
||||
class PassiveOutputStream extends PipedOutputStream{
|
||||
PassiveOutputStream(PipedInputStream in) throws IOException{
|
||||
private MyPipedInputStream _sink=null;
|
||||
PassiveOutputStream(PipedInputStream in,
|
||||
boolean resizable_buffer) throws IOException{
|
||||
super(in);
|
||||
if(resizable_buffer && (in instanceof MyPipedInputStream)) {
|
||||
this._sink=(MyPipedInputStream)in;
|
||||
}
|
||||
}
|
||||
public void write(int b) throws IOException {
|
||||
if(_sink != null) {
|
||||
_sink.checkSpace(1);
|
||||
}
|
||||
super.write(b);
|
||||
}
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if(_sink != null) {
|
||||
_sink.checkSpace(len);
|
||||
}
|
||||
super.write(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,7 +731,7 @@ public abstract class Channel implements Runnable{
|
||||
Packet packet = genChannelOpenPacket();
|
||||
_session.write(packet);
|
||||
|
||||
int retry=10;
|
||||
int retry=2000;
|
||||
long start=System.currentTimeMillis();
|
||||
long timeout=connectTimeout;
|
||||
if(timeout!=0L) retry = 1;
|
||||
@@ -651,7 +746,7 @@ public abstract class Channel implements Runnable{
|
||||
}
|
||||
}
|
||||
try{
|
||||
long t = timeout==0L ? 5000L : timeout;
|
||||
long t = timeout==0L ? 10L : timeout;
|
||||
this.notifyme=1;
|
||||
wait(t);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved.
|
||||
Copyright (c) 2006-2016 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
|
||||
/*
|
||||
Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved.
|
||||
Copyright (c) 2002-2016 ymnk, JCraft,Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@@ -120,7 +120,16 @@ public class ChannelDirectTCPIP extends Channel{
|
||||
}
|
||||
}
|
||||
catch(Exception e){
|
||||
// Whenever an exception is thrown by sendChannelOpen(),
|
||||
// 'connected' is false.
|
||||
if(!connected){
|
||||
connected=true;
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
eof();
|
||||
disconnect();
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user