Compare commits
3358 Commits
1.03
...
v1.09e-r5b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
554f88c723 | ||
|
|
4cd32d30c6 | ||
|
|
d0da83182f | ||
|
|
ec5f26e0cd | ||
|
|
6110166af8 | ||
|
|
6f10a04589 | ||
|
|
e0c003fcb2 | ||
|
|
944f44bc4b | ||
|
|
58047d5386 | ||
|
|
c0a06c9f3a | ||
|
|
d0c041a0e2 | ||
|
|
df060e2f4b | ||
|
|
aea55dad45 | ||
|
|
5442dbf441 | ||
|
|
317476d9b5 | ||
|
|
ad0acb7a69 | ||
|
|
b66ae5d264 | ||
|
|
d87706fa43 | ||
|
|
cb25d12709 | ||
|
|
dce536009e | ||
|
|
656e785214 | ||
|
|
35d50a6eb0 | ||
|
|
786bb646c2 | ||
|
|
72cc6ff768 | ||
|
|
404e07e5c0 | ||
|
|
1c7159ede9 | ||
|
|
2378cd0d7c | ||
|
|
b149bab761 | ||
|
|
5ebd8e5e33 | ||
|
|
db6b266a59 | ||
|
|
7de28c5aba | ||
|
|
ed79df0c6d | ||
|
|
4949fede32 | ||
|
|
bddef6442c | ||
|
|
48a6d0a2ad | ||
|
|
ac5f3c9ca5 | ||
|
|
93e1cf1147 | ||
|
|
a805787a95 | ||
|
|
85315d0ecc | ||
|
|
595a451f77 | ||
|
|
914224e4fa | ||
|
|
e350e8788c | ||
|
|
ca5f6dc43c | ||
|
|
0d4955622d | ||
|
|
886daa6b27 | ||
|
|
8fa0803474 | ||
|
|
4cad70e750 | ||
|
|
c29b789a2b | ||
|
|
cd34896661 | ||
|
|
1e02db86d6 | ||
|
|
994741cbf5 | ||
|
|
58844be6eb | ||
|
|
2d899fa067 | ||
|
|
060bf6a6ee | ||
|
|
890f1bd704 | ||
|
|
139abcaec6 | ||
|
|
78a48b75b8 | ||
|
|
3918b06b1f | ||
|
|
40847ebe31 | ||
|
|
34cac86a9b | ||
|
|
d8598a53e0 | ||
|
|
92d9eb1512 | ||
|
|
1be7b33f6b | ||
|
|
8464fa4f29 | ||
|
|
eff9a96bd5 | ||
|
|
bd4e321b0e | ||
|
|
47aaedbfb5 | ||
|
|
3043f8981d | ||
|
|
cfd413f1f4 | ||
|
|
30df03eec6 | ||
|
|
5048f63204 | ||
|
|
7557c0b9fd | ||
|
|
9346f6bb32 | ||
|
|
23d7efff53 | ||
|
|
c7eb2bf873 | ||
|
|
632121f3ec | ||
|
|
f7feddcf1f | ||
|
|
e745fee6e2 | ||
|
|
bcc17d91bd | ||
|
|
8c8a8e3968 | ||
|
|
3c41550404 | ||
|
|
76107b1207 | ||
|
|
bb0c13b9d8 | ||
|
|
405166ba9d | ||
|
|
f5cb60770e | ||
|
|
9958a73d4a | ||
|
|
fd287b8da7 | ||
|
|
9bea5b13e3 | ||
|
|
aa6a728e8c | ||
|
|
1c8431a3f9 | ||
|
|
6a0eacd8f1 | ||
|
|
d27976b737 | ||
|
|
f312b50f0c | ||
|
|
deb169fece | ||
|
|
2df656211d | ||
|
|
c86f9b3a4f | ||
|
|
1c517dceb8 | ||
|
|
bede68b60a | ||
|
|
8ab7fe84dd | ||
|
|
305946b552 | ||
|
|
f1fdfa5205 | ||
|
|
c1f7460c3e | ||
|
|
1f92e449f5 | ||
|
|
50aec43b38 | ||
|
|
dc75565d7c | ||
|
|
91b59c7c9f | ||
|
|
e42b4c9654 | ||
|
|
d6486d4b98 | ||
|
|
5bdf93633f | ||
|
|
81f582bb8b | ||
|
|
7ba6a44888 | ||
|
|
187d4c8f41 | ||
|
|
58b0b666ce | ||
|
|
8393694e6c | ||
|
|
b99f82d3d7 | ||
|
|
dfbfeb3fa3 | ||
|
|
3c9a8341ae | ||
|
|
8f69a60307 | ||
|
|
14c2e64e2f | ||
|
|
554338012e | ||
|
|
3185cf1a9c | ||
|
|
ed91d0db0b | ||
|
|
dd7cb0a088 | ||
|
|
874e1dbae8 | ||
|
|
649c0739f6 | ||
|
|
3db5ea4713 | ||
|
|
96b5e1c10e | ||
|
|
2bf5222505 | ||
|
|
24d6909297 | ||
|
|
1c3f4106dd | ||
|
|
4b3f6657a8 | ||
|
|
fd75737331 | ||
|
|
195cdb8ad7 | ||
|
|
a8e519660b | ||
|
|
54047e8a26 | ||
|
|
e84c5bacb1 | ||
|
|
48037d667c | ||
|
|
41682aab0a | ||
|
|
9561c99711 | ||
|
|
1fd538999f | ||
|
|
a4396af352 | ||
|
|
d7c403cf30 | ||
|
|
089eb9bcb2 | ||
|
|
178383d549 | ||
|
|
f6e6d0e59c | ||
|
|
30c1cc1e3f | ||
|
|
e7f579862f | ||
|
|
22fc984432 | ||
|
|
33b3c78676 | ||
|
|
0052641b86 | ||
|
|
b5b67ed6c4 | ||
|
|
08e0b6e72d | ||
|
|
6e23b1ef22 | ||
|
|
e0da7c6bf5 | ||
|
|
138bd8adef | ||
|
|
ab527368c0 | ||
|
|
335c53360d | ||
|
|
7b31f6ec5a | ||
|
|
63a8791752 | ||
|
|
e3ce7fe95a | ||
|
|
ce6556496e | ||
|
|
eab5e22c8c | ||
|
|
827905e690 | ||
|
|
7fe407d25e | ||
|
|
b9d0f56e0f | ||
|
|
5d06a8b62a | ||
|
|
39c1f671d4 | ||
|
|
4eb8c77304 | ||
|
|
c933748077 | ||
|
|
3347722d6d | ||
|
|
56c35ac573 | ||
|
|
68a61dfcd8 | ||
|
|
664c260b99 | ||
|
|
a07ce67c95 | ||
|
|
6cd71b2bf5 | ||
|
|
eb3001a57d | ||
|
|
cfd44501d4 | ||
|
|
62f7592e1d | ||
|
|
5b07f5d726 | ||
|
|
3c7cdd150a | ||
|
|
3bafb4e022 | ||
|
|
477bb87322 | ||
|
|
6584303cdf | ||
|
|
cbcb72158e | ||
|
|
43c8c7d243 | ||
|
|
9d31559916 | ||
|
|
3483654830 | ||
|
|
a74b162e37 | ||
|
|
52dd73fa9f | ||
|
|
548b92ffe9 | ||
|
|
1df84ae7a3 | ||
|
|
ba40179c82 | ||
|
|
1add52a459 | ||
|
|
2f105d30fd | ||
|
|
e473940c26 | ||
|
|
5f836c381f | ||
|
|
7282fdae0b | ||
|
|
df2a7412d3 | ||
|
|
ae4cdeedbf | ||
|
|
fe6115aefb | ||
|
|
414dfa57b2 | ||
|
|
193a39390c | ||
|
|
43455959e2 | ||
|
|
2d0e142a79 | ||
|
|
27714c0cdf | ||
|
|
37db758ee5 | ||
|
|
faccbc10e5 | ||
|
|
748bd493c4 | ||
|
|
8616956df1 | ||
|
|
e0da5470e2 | ||
|
|
27e237c5e9 | ||
|
|
22d4ebbea4 | ||
|
|
586b7fc389 | ||
|
|
63f6c1e5cf | ||
|
|
2c128794ac | ||
|
|
cf0e8a1926 | ||
|
|
06bd468658 | ||
|
|
7b6ff73fb9 | ||
|
|
54231b23f3 | ||
|
|
77ee958587 | ||
|
|
69137b2212 | ||
|
|
208f080bd2 | ||
|
|
34b738e2fe | ||
|
|
1664171794 | ||
|
|
5690ff6c99 | ||
|
|
e7a43ab7a6 | ||
|
|
96fcc79c93 | ||
|
|
b99272e850 | ||
|
|
b04aba7644 | ||
|
|
cef13eafa0 | ||
|
|
37befe2c46 | ||
|
|
dd84af3bfc | ||
|
|
65a4d64925 | ||
|
|
0b2d62917a | ||
|
|
9fc7dca138 | ||
|
|
b50c7e6cf6 | ||
|
|
944bce14b8 | ||
|
|
269952ee67 | ||
|
|
d1ccd16987 | ||
|
|
78a7c79376 | ||
|
|
41c66ecb28 | ||
|
|
b2f21094b5 | ||
|
|
32666a0d86 | ||
|
|
61afc4ed58 | ||
|
|
9904946ce2 | ||
|
|
78f76054ad | ||
|
|
6e71b3fb66 | ||
|
|
37a8b51a5f | ||
|
|
02a43799a7 | ||
|
|
a5994ebe63 | ||
|
|
7319652db7 | ||
|
|
35f91fd842 | ||
|
|
801fd86db5 | ||
|
|
afb376a3bc | ||
|
|
3baaef19d4 | ||
|
|
2e0e0c1d86 | ||
|
|
c091c5aeda | ||
|
|
74dd3b67e2 | ||
|
|
2b3d090fd6 | ||
|
|
d875f3fb2f | ||
|
|
92f90eddc7 | ||
|
|
3feae3b211 | ||
|
|
03855a604a | ||
|
|
b88000a5b4 | ||
|
|
136ba783c8 | ||
|
|
df6fb03245 | ||
|
|
9509f5ae52 | ||
|
|
c69177be6f | ||
|
|
daaa7d4016 | ||
|
|
d6914456dc | ||
|
|
4c3efb6b52 | ||
|
|
f6193103e2 | ||
|
|
68a78c32e3 | ||
|
|
241ea648ee | ||
|
|
a7a4e45c8b | ||
|
|
0b17c5dcda | ||
|
|
60b79a9b8a | ||
|
|
9dfd8bbadf | ||
|
|
7bfd80a122 | ||
|
|
8b6c6707c7 | ||
|
|
d1ee19243f | ||
|
|
3aca98d1e2 | ||
|
|
b76c6063b0 | ||
|
|
584b4321ca | ||
|
|
b499d12768 | ||
|
|
246f6f8132 | ||
|
|
e07a350159 | ||
|
|
ac05f5c93c | ||
|
|
41cec5ffc3 | ||
|
|
f5ca01c529 | ||
|
|
6b115616b7 | ||
|
|
611efe05ca | ||
|
|
9e3d30e81e | ||
|
|
ba20fd79e0 | ||
|
|
37e6ea89b7 | ||
|
|
a8457067b3 | ||
|
|
6e82ca9ac2 | ||
|
|
57a6e4f175 | ||
|
|
7621ae0c98 | ||
|
|
70b87adf62 | ||
|
|
55e6bd42b1 | ||
|
|
b5711591d5 | ||
|
|
f29463ef6d | ||
|
|
18b623548a | ||
|
|
6c394c22da | ||
|
|
738f9e7547 | ||
|
|
d885fddfe6 | ||
|
|
95a1713c8a | ||
|
|
6661ffb580 | ||
|
|
99b7a6ccf7 | ||
|
|
c63865f043 | ||
|
|
a00312df84 | ||
|
|
9ec3374240 | ||
|
|
81c8e17333 | ||
|
|
cf576dcbfd | ||
|
|
3cbaa09769 | ||
|
|
89f795e953 | ||
|
|
86c9ab40cf | ||
|
|
681a7d17d5 | ||
|
|
5a1d0ea51b | ||
|
|
9aa3c02907 | ||
|
|
0cfdfed476 | ||
|
|
a205614d65 | ||
|
|
db27bcbbe7 | ||
|
|
943430cfce | ||
|
|
6c55d2aec6 | ||
|
|
7d3ecaca7e | ||
|
|
f2e8de6938 | ||
|
|
26090e87b3 | ||
|
|
af82d9fec1 | ||
|
|
86defbb144 | ||
|
|
d0a5557807 | ||
|
|
74788c77e0 | ||
|
|
f77bdc4b9c | ||
|
|
7f659178c5 | ||
|
|
b67e8e6c85 | ||
|
|
df4e7c0774 | ||
|
|
8d5882cb81 | ||
|
|
d540fda5b0 | ||
|
|
d39957b8ca | ||
|
|
7160bcc33f | ||
|
|
36d8a0aa8d | ||
|
|
0dec97fad1 | ||
|
|
9da08e94ac | ||
|
|
62b3fe61b6 | ||
|
|
50287025a0 | ||
|
|
ed234c898e | ||
|
|
f2775fe0f0 | ||
|
|
135168c1bb | ||
|
|
35f74f5ea4 | ||
|
|
26f0ab6661 | ||
|
|
6213c753fe | ||
|
|
3f1b23dc82 | ||
|
|
dda76323c6 | ||
|
|
c41128401d | ||
|
|
9a5fe131cd | ||
|
|
e45fe2f279 | ||
|
|
4698a948cc | ||
|
|
3648213be2 | ||
|
|
40146a42ce | ||
|
|
35501c4c48 | ||
|
|
dc28e5708d | ||
|
|
d4f3f69129 | ||
|
|
936bc7ed72 | ||
|
|
8a59fbdb41 | ||
|
|
2c93fd1542 | ||
|
|
2981497da9 | ||
|
|
6745e0486c | ||
|
|
76c6f56d73 | ||
|
|
21b0c63422 | ||
|
|
093ebb424e | ||
|
|
c344b0f62a | ||
|
|
b447d2e5ad | ||
|
|
2b85ed473c | ||
|
|
d536b38acc | ||
|
|
b4a82511ff | ||
|
|
35a84adde3 | ||
|
|
f1de28e6c1 | ||
|
|
2336255763 | ||
|
|
a3022963c0 | ||
|
|
396a035cfd | ||
|
|
2001fd26f8 | ||
|
|
9daf2d0448 | ||
|
|
b2d14ff400 | ||
|
|
675fd5b735 | ||
|
|
14c7663167 | ||
|
|
788a04aceb | ||
|
|
99c70f96d8 | ||
|
|
9f729e8c36 | ||
|
|
35f1a351ba | ||
|
|
5f59de2fba | ||
|
|
95b7c59606 | ||
|
|
7962b5c8ea | ||
|
|
d2818a35c6 | ||
|
|
44183178c6 | ||
|
|
2ebb35b631 | ||
|
|
173a5fedf0 | ||
|
|
00c0bbd942 | ||
|
|
1dfb38207b | ||
|
|
df0d087646 | ||
|
|
8f84e292b2 | ||
|
|
45bf4247c1 | ||
|
|
daecd42d8e | ||
|
|
952aaa76ff | ||
|
|
fe57c05579 | ||
|
|
309fd9f4d1 | ||
|
|
9af0d74ba4 | ||
|
|
c1292b585f | ||
|
|
87a6bbe0fd | ||
|
|
b807431053 | ||
|
|
1442af3148 | ||
|
|
eb92645ed0 | ||
|
|
714be0f6ae | ||
|
|
e77c3ce1d3 | ||
|
|
48d080bcda | ||
|
|
531cb51fac | ||
|
|
e8bc949230 | ||
|
|
d99d43dde7 | ||
|
|
b64c304a92 | ||
|
|
d392b1c434 | ||
|
|
1f9b5df44b | ||
|
|
edd4067efc | ||
|
|
1a23b8363a | ||
|
|
04df628fe8 | ||
|
|
2bb5a18f27 | ||
|
|
6cc7c3b1fb | ||
|
|
21c1b1e913 | ||
|
|
a1cdba5baa | ||
|
|
3b14ffb331 | ||
|
|
b0e6de8a47 | ||
|
|
2a3138ca76 | ||
|
|
56a0c6325d | ||
|
|
69c0485fe8 | ||
|
|
21205f85aa | ||
|
|
9d10d75d54 | ||
|
|
2757f657c5 | ||
|
|
1c4040707e | ||
|
|
ca4a29a991 | ||
|
|
9120da776c | ||
|
|
24b2f1fca5 | ||
|
|
f4f0bb166a | ||
|
|
27c8d78ac9 | ||
|
|
fe32105491 | ||
|
|
ad7ef30f68 | ||
|
|
c1df53e986 | ||
|
|
36b8f52929 | ||
|
|
f84ab77a9a | ||
|
|
1ec842c274 | ||
|
|
e06849cd24 | ||
|
|
3f31533909 | ||
|
|
5a408ccd4a | ||
|
|
07d3a4ef84 | ||
|
|
eb50ed1bc3 | ||
|
|
681d120e8b | ||
|
|
74ae266fed | ||
|
|
028f16af06 | ||
|
|
fa7980f379 | ||
|
|
4ddc173757 | ||
|
|
8bc93d7f23 | ||
|
|
de72df99ea | ||
|
|
580fd60fd9 | ||
|
|
c884f93ac3 | ||
|
|
a57ff299b5 | ||
|
|
159a90d7e3 | ||
|
|
b8fe4639ba | ||
|
|
6a80021bd1 | ||
|
|
d2dc75d556 | ||
|
|
2aa93b56cb | ||
|
|
11037daca9 | ||
|
|
93932e78f9 | ||
|
|
7ad476d543 | ||
|
|
9b487f94de | ||
|
|
68e34eb3bd | ||
|
|
88f95b96b0 | ||
|
|
e22a69caf5 | ||
|
|
bb339504d4 | ||
|
|
2666c5248b | ||
|
|
c0df8e9a04 | ||
|
|
bead854cf1 | ||
|
|
48da600598 | ||
|
|
3b0b349f4c | ||
|
|
294e6f5edf | ||
|
|
02fb27f48e | ||
|
|
e57a02408e | ||
|
|
5325381f2f | ||
|
|
4176b06578 | ||
|
|
7014f5d9f1 | ||
|
|
afbef4272c | ||
|
|
45df2d6605 | ||
|
|
1c2369c419 | ||
|
|
81211ecb74 | ||
|
|
17a06adfd9 | ||
|
|
da565e43bb | ||
|
|
641497a8d3 | ||
|
|
7cecadcf82 | ||
|
|
cd776754b5 | ||
|
|
9d2d920fda | ||
|
|
cb30d3a79e | ||
|
|
3842cbffc4 | ||
|
|
1cf7cbc144 | ||
|
|
73e8291cb0 | ||
|
|
1e89c8dac1 | ||
|
|
81c4477453 | ||
|
|
adb0865aa7 | ||
|
|
d65ae7767a | ||
|
|
d83474d6f6 | ||
|
|
5cffec4724 | ||
|
|
8af2f51eae | ||
|
|
39579b0183 | ||
|
|
caff2e25e2 | ||
|
|
0fee6e2298 | ||
|
|
feaad1300a | ||
|
|
1a59129d88 | ||
|
|
1c7fa8d41d | ||
|
|
1480657857 | ||
|
|
c8ab5836eb | ||
|
|
2bb7a2065a | ||
|
|
0564a103e1 | ||
|
|
cd0954badb | ||
|
|
2e5a1a9820 | ||
|
|
8acc6dec1b | ||
|
|
3f0bbbb19e | ||
|
|
16e9077cd4 | ||
|
|
53bb822013 | ||
|
|
37c1da8962 | ||
|
|
75535c8edd | ||
|
|
36c7e9eecc | ||
|
|
fee5103bdd | ||
|
|
4a5a77de21 | ||
|
|
1b5f25f10b | ||
|
|
4cf67734a1 | ||
|
|
b6778fb331 | ||
|
|
2ae50c2fbd | ||
|
|
f33ad9e403 | ||
|
|
4f7d58d8b4 | ||
|
|
6582faa8d7 | ||
|
|
387f584b2c | ||
|
|
b320c0fd5a | ||
|
|
30294a0195 | ||
|
|
252778bf7c | ||
|
|
80bd3c2043 | ||
|
|
eb968ba676 | ||
|
|
1abe428559 | ||
|
|
9854a2ad33 | ||
|
|
54ebe89d44 | ||
|
|
2565a04c83 | ||
|
|
bb11bdf423 | ||
|
|
d6983265ce | ||
|
|
0034999256 | ||
|
|
10004bd67e | ||
|
|
a5c35b8fa9 | ||
|
|
c0d7626ec3 | ||
|
|
1fbd310371 | ||
|
|
5f0b5919a4 | ||
|
|
ae41b34f13 | ||
|
|
4ecb7ef8a6 | ||
|
|
bfef18bfe7 | ||
|
|
0448aca24e | ||
|
|
af67e29ea3 | ||
|
|
f12ee10b9d | ||
|
|
aea585a93d | ||
|
|
a5b30b557a | ||
|
|
a52ebcf576 | ||
|
|
62fcfdfc95 | ||
|
|
a69e5d9c5f | ||
|
|
72ffaf39f4 | ||
|
|
08734d733f | ||
|
|
e3ddad2c64 | ||
|
|
693cf3608a | ||
|
|
ad9f49f66e | ||
|
|
6910414ba3 | ||
|
|
f8bb39384b | ||
|
|
e7b4cfe53e | ||
|
|
8e6146dd46 | ||
|
|
50254c497a | ||
|
|
66a7469cd5 | ||
|
|
70cf30b8a3 | ||
|
|
1549d71af0 | ||
|
|
69c95a4073 | ||
|
|
6c79c1539a | ||
|
|
0b7d45d3b9 | ||
|
|
edd1b683dd | ||
|
|
eccd8e3810 | ||
|
|
8855541ee1 | ||
|
|
fd300add4f | ||
|
|
3161e04752 | ||
|
|
ca1a51749a | ||
|
|
5aba209857 | ||
|
|
80cfb9e098 | ||
|
|
b98c887d71 | ||
|
|
be8e8f9b02 | ||
|
|
87cbf65654 | ||
|
|
6a0e132945 | ||
|
|
438cf5793a | ||
|
|
74a736ef87 | ||
|
|
4ce451b99c | ||
|
|
f017d3fdf2 | ||
|
|
54eb656726 | ||
|
|
9d63578110 | ||
|
|
06baeeb79a | ||
|
|
a77fe463d8 | ||
|
|
c016fc164d | ||
|
|
a409bb1318 | ||
|
|
7eeaf205cd | ||
|
|
85882b2547 | ||
|
|
12e4af7b0d | ||
|
|
774406fe00 | ||
|
|
e7c8534c01 | ||
|
|
0655dd41bb | ||
|
|
48bb71d5dc | ||
|
|
b2641fe4d3 | ||
|
|
e58de5a99f | ||
|
|
68df9ada01 | ||
|
|
a91a711499 | ||
|
|
780ab1125d | ||
|
|
2e83495542 | ||
|
|
b69b7a8b5f | ||
|
|
00f264c313 | ||
|
|
ba9eb65fa6 | ||
|
|
824a7484e0 | ||
|
|
7ebab48b97 | ||
|
|
708bd9bc8a | ||
|
|
960b00b9ca | ||
|
|
d654137caa | ||
|
|
e4b36c172b | ||
|
|
05f8a067f1 | ||
|
|
d3db23d1b7 | ||
|
|
30288a3106 | ||
|
|
89410e60c7 | ||
|
|
3e971b5fe9 | ||
|
|
7673e4d638 | ||
|
|
9a76ea1433 | ||
|
|
92ff60c66d | ||
|
|
dfad45f83d | ||
|
|
6c0a11d300 | ||
|
|
54f58067d3 | ||
|
|
edb23bef1e | ||
|
|
cddd0705d8 | ||
|
|
fc4447748b | ||
|
|
433310030f | ||
|
|
388fb2ba34 | ||
|
|
d2a19967bc | ||
|
|
b2538c0133 | ||
|
|
dde2fdb103 | ||
|
|
7a83064745 | ||
|
|
970ebfede5 | ||
|
|
4ecc56fa79 | ||
|
|
1e25bc6c7c | ||
|
|
8eca4a1d19 | ||
|
|
c6f7a0ba1a | ||
|
|
fe07cf6060 | ||
|
|
022c26c89d | ||
|
|
a13bcaf223 | ||
|
|
8b469ed263 | ||
|
|
ff631935fc | ||
|
|
6fd363e071 | ||
|
|
57556764e9 | ||
|
|
fbef5de705 | ||
|
|
bff035f8a5 | ||
|
|
272a124d3a | ||
|
|
ae5fd9765d | ||
|
|
2900b293c3 | ||
|
|
b8fbca0d49 | ||
|
|
370f5a5b4e | ||
|
|
9558786b76 | ||
|
|
c0260974bd | ||
|
|
f864af6003 | ||
|
|
30fc5e4646 | ||
|
|
3dee4935c8 | ||
|
|
0e088a48b8 | ||
|
|
0928ab0224 | ||
|
|
ec07a61cab | ||
|
|
14d7eaf361 | ||
|
|
0f2892bd28 | ||
|
|
51ae5a2a0c | ||
|
|
5bb5fc9496 | ||
|
|
9e550f85cc | ||
|
|
4ef46e302d | ||
|
|
079806c857 | ||
|
|
deed92af0d | ||
|
|
48367c5926 | ||
|
|
0f3cdf77d4 | ||
|
|
4b06833c3f | ||
|
|
8a6bfe3288 | ||
|
|
2d106f7b87 | ||
|
|
130ef249d7 | ||
|
|
5b55cf0edc | ||
|
|
1d824049cb | ||
|
|
2eef3cfa00 | ||
|
|
f82cfeed3d | ||
|
|
3aba034155 | ||
|
|
114a0832cb | ||
|
|
66f627fd1a | ||
|
|
1ce915cd9e | ||
|
|
712f476da8 | ||
|
|
2d0e5d208b | ||
|
|
053cef944a | ||
|
|
ff2ba3f4ed | ||
|
|
ec7d908941 | ||
|
|
1afbd4c632 | ||
|
|
a5af23b2f7 | ||
|
|
78ac8f45e9 | ||
|
|
c9ade3ad3f | ||
|
|
c588d3d581 | ||
|
|
0140b4f74e | ||
|
|
eb42d33630 | ||
|
|
f6b0eab8b1 | ||
|
|
b316c21623 | ||
|
|
bd661fddb1 | ||
|
|
fd5ca57f36 | ||
|
|
d38d446a70 | ||
|
|
4f97e6e8b9 | ||
|
|
e79450a54d | ||
|
|
44fd071c9d | ||
|
|
8487b935c4 | ||
|
|
f497194281 | ||
|
|
614e014cab | ||
|
|
5bf976747c | ||
|
|
5c2a7f27e6 | ||
|
|
4c059b625c | ||
|
|
1860a92fa0 | ||
|
|
f4799acf31 | ||
|
|
a704e523d9 | ||
|
|
725cdf3ec3 | ||
|
|
f3a3956d79 | ||
|
|
167cd39c8f | ||
|
|
681492f5f8 | ||
|
|
80766034a6 | ||
|
|
4e7b96462c | ||
|
|
761cae4a2b | ||
|
|
d0d526d36d | ||
|
|
f29cfd55fa | ||
|
|
7a4116c016 | ||
|
|
5639517128 | ||
|
|
17c7b9c526 | ||
|
|
e40c5aa821 | ||
|
|
1915a8b1db | ||
|
|
c105312b99 | ||
|
|
2b5d4365c2 | ||
|
|
f145c68cfe | ||
|
|
2fff53f468 | ||
|
|
6a1e75bf51 | ||
|
|
4d903239ca | ||
|
|
570133d365 | ||
|
|
9cc49389e4 | ||
|
|
cfcc472c4c | ||
|
|
79ff2c1adf | ||
|
|
01e5aad370 | ||
|
|
50ba6c2750 | ||
|
|
49a4c8e771 | ||
|
|
97de25e2ed | ||
|
|
7a6d9392d3 | ||
|
|
4738db9b7d | ||
|
|
172e75e4e8 | ||
|
|
c4795547c8 | ||
|
|
fefc6ca04b | ||
|
|
b00945a815 | ||
|
|
3ad7112011 | ||
|
|
9b49df08e3 | ||
|
|
06ba923c28 | ||
|
|
67c5e58c2c | ||
|
|
e8c5e0d911 | ||
|
|
668836e646 | ||
|
|
e1cd8123cf | ||
|
|
6cfeb715e5 | ||
|
|
19419dc483 | ||
|
|
1aac650a3d | ||
|
|
7030c9e29b | ||
|
|
730fbe211c | ||
|
|
0993ea5e46 | ||
|
|
0cc4fc76fd | ||
|
|
3a6f536cd9 | ||
|
|
4809037fdc | ||
|
|
3d9c084e59 | ||
|
|
75f64c31a9 | ||
|
|
4d64c06f79 | ||
|
|
f6a4f46b12 | ||
|
|
df68fd70f7 | ||
|
|
2631982e62 | ||
|
|
bcbc89f3a3 | ||
|
|
d5f5d9a6b1 | ||
|
|
01028a956a | ||
|
|
eb55d15a2f | ||
|
|
8219ea74b2 | ||
|
|
18b1cb6805 | ||
|
|
b0f9dbb062 | ||
|
|
94118d31f1 | ||
|
|
44c52ee47c | ||
|
|
b71b9c523c | ||
|
|
06b19dc05f | ||
|
|
6a05c0348b | ||
|
|
c04184d715 | ||
|
|
c3bfdfcc29 | ||
|
|
b6a83339e8 | ||
|
|
5a50b1b91f | ||
|
|
31f3b70fdb | ||
|
|
c4673f87d7 | ||
|
|
3b5822fd8f | ||
|
|
f0d40713ae | ||
|
|
a1a249421c | ||
|
|
fe927f8111 | ||
|
|
b639a0bc9f | ||
|
|
1ce9afb8be | ||
|
|
a277511be9 | ||
|
|
25e9b51d04 | ||
|
|
b20076e7b8 | ||
|
|
0c4d096e36 | ||
|
|
6b3ab59f13 | ||
|
|
98e937a61b | ||
|
|
b10893dfc6 | ||
|
|
ec6d5bb56e | ||
|
|
7dbaf6feaa | ||
|
|
6cffa74196 | ||
|
|
7906c477c4 | ||
|
|
5cc139e7f0 | ||
|
|
a3b2ccfbb9 | ||
|
|
f0cde44dc1 | ||
|
|
c7cf38de48 | ||
|
|
dad72764e8 | ||
|
|
10ef165112 | ||
|
|
47fcc8007d | ||
|
|
bb9a53e6cc | ||
|
|
46544570ad | ||
|
|
db71a06371 | ||
|
|
f5b88df4c1 | ||
|
|
a4dfc59126 | ||
|
|
c980d37aa2 | ||
|
|
411740cf01 | ||
|
|
9d4ca67722 | ||
|
|
ad5b7e5b46 | ||
|
|
785c0bba8d | ||
|
|
f6395908ee | ||
|
|
4636f5800c | ||
|
|
212418f11a | ||
|
|
7f443e8505 | ||
|
|
488d11b693 | ||
|
|
f0255703c1 | ||
|
|
f7e33728f2 | ||
|
|
86fcfb49eb | ||
|
|
17ae8f7e99 | ||
|
|
638a2ec462 | ||
|
|
789e474c04 | ||
|
|
65ade96fd8 | ||
|
|
05e2502831 | ||
|
|
f1a4536a42 | ||
|
|
0bb372c2e9 | ||
|
|
98c38e6f8f | ||
|
|
7739a1bb85 | ||
|
|
5dbc4df7c1 | ||
|
|
3bee5fc4c9 | ||
|
|
62fe696921 | ||
|
|
603f30cd9d | ||
|
|
764d208695 | ||
|
|
147c83f62b | ||
|
|
da89fd674f | ||
|
|
6bc4677f3a | ||
|
|
0676cd6e7c | ||
|
|
7dceb7e363 | ||
|
|
6a2be81241 | ||
|
|
b26c9bfa35 | ||
|
|
19ecbfae85 | ||
|
|
221277bf24 | ||
|
|
41d864e69f | ||
|
|
46341b5d37 | ||
|
|
b3569f1459 | ||
|
|
963df05ed3 | ||
|
|
f693d93e03 | ||
|
|
b3a78194dd | ||
|
|
2d27c95388 | ||
|
|
3e760df174 | ||
|
|
9dca986efe | ||
|
|
6967bd2b84 | ||
|
|
b32e599223 | ||
|
|
727863e4ee | ||
|
|
2c157bc76f | ||
|
|
f78f2b9361 | ||
|
|
3859ce78a5 | ||
|
|
1e1c79e8f8 | ||
|
|
beadd426c4 | ||
|
|
edc650a66e | ||
|
|
562a80132a | ||
|
|
f5ee9e3955 | ||
|
|
a0a8a2810c | ||
|
|
1d6dadea58 | ||
|
|
5144fe6fc9 | ||
|
|
7e0913fe8b | ||
|
|
15f1aa68da | ||
|
|
1eb11928c2 | ||
|
|
982527b4bf | ||
|
|
2a2622ddd8 | ||
|
|
39939790c2 | ||
|
|
ddabf82ea7 | ||
|
|
7dd6745cd9 | ||
|
|
3ac02da522 | ||
|
|
d5982ae1e3 | ||
|
|
fe2ebfcfd9 | ||
|
|
977fe33d6a | ||
|
|
951e11f6b0 | ||
|
|
2fa1cd175d | ||
|
|
5c9ab11aff | ||
|
|
1f9327db80 | ||
|
|
e16429f77b | ||
|
|
3e58ef5dba | ||
|
|
84ac5fef4f | ||
|
|
303d98bad7 | ||
|
|
e39a126229 | ||
|
|
7257657432 | ||
|
|
99999dde2c | ||
|
|
60fc41d524 | ||
|
|
559a6f87b2 | ||
|
|
02fbe3ce93 | ||
|
|
aa221c221e | ||
|
|
796efc490e | ||
|
|
b3c6b9b8e3 | ||
|
|
bc44d8a0a6 | ||
|
|
a43c291794 | ||
|
|
2a4c0a8427 | ||
|
|
bca9156a38 | ||
|
|
cd97ac8106 | ||
|
|
e464413b05 | ||
|
|
39c50eda0c | ||
|
|
4901485dc3 | ||
|
|
0762c227c1 | ||
|
|
09537689cf | ||
|
|
92ffe596ce | ||
|
|
7037fbfe94 | ||
|
|
9eab59dcbe | ||
|
|
d705371f87 | ||
|
|
09206a387b | ||
|
|
65fc67a4b2 | ||
|
|
7faa6a8efc | ||
|
|
4f4b7fdfa4 | ||
|
|
ce09d9c8a9 | ||
|
|
c9744aeb94 | ||
|
|
a65dbfafa3 | ||
|
|
e40c117228 | ||
|
|
46bded5c16 | ||
|
|
47ab6df725 | ||
|
|
94a366a13e | ||
|
|
f23de8f380 | ||
|
|
f1fb2a47f0 | ||
|
|
175c64bdc8 | ||
|
|
07ab9f21db | ||
|
|
56ece19994 | ||
|
|
1163e9956a | ||
|
|
d02b9438eb | ||
|
|
40cbd51e8b | ||
|
|
490de22dc7 | ||
|
|
ef71df7d5f | ||
|
|
0fbf0179f3 | ||
|
|
5a45360ab6 | ||
|
|
94ac246d1f | ||
|
|
85ef205fab | ||
|
|
4dd0215ac8 | ||
|
|
4fa940af47 | ||
|
|
6e76e4908e | ||
|
|
8991538449 | ||
|
|
9a51267b8f | ||
|
|
373128f678 | ||
|
|
563faf6cc5 | ||
|
|
aff243389d | ||
|
|
a38be4ad80 | ||
|
|
bd52090236 | ||
|
|
5ae11a91c1 | ||
|
|
f1cc61e8ce | ||
|
|
5af68c5d9b | ||
|
|
dbe804f223 | ||
|
|
2bbbc4fe94 | ||
|
|
9cd66fc30c | ||
|
|
65f6731b61 | ||
|
|
25defeaf3a | ||
|
|
e8d8f13888 | ||
|
|
4a9a767fc6 | ||
|
|
d8b22b4914 | ||
|
|
ef22f19dec | ||
|
|
4bcf651e5e | ||
|
|
19aea7808d | ||
|
|
afa4c9c0f2 | ||
|
|
d2d853e916 | ||
|
|
3ead147be4 | ||
|
|
c863ff1fd1 | ||
|
|
6028b10bf1 | ||
|
|
e74bb8d3b5 | ||
|
|
7bbe3fb9b5 | ||
|
|
e00eb2a5bc | ||
|
|
23ca92039b | ||
|
|
54f8916ddd | ||
|
|
a4b3c933ef | ||
|
|
d0633e883e | ||
|
|
8071e0692a | ||
|
|
47f07c66bf | ||
|
|
5db30a2b98 | ||
|
|
fcd3cddbc7 | ||
|
|
3c49d30de6 | ||
|
|
377bffd7a4 | ||
|
|
6af1da01db | ||
|
|
a6e430e569 | ||
|
|
15d3492ae3 | ||
|
|
7a731da44f | ||
|
|
64a53ce887 | ||
|
|
45355ba972 | ||
|
|
3b769e2a9f | ||
|
|
ed70c3fcb1 | ||
|
|
86d56be044 | ||
|
|
448492cbc1 | ||
|
|
5010eb3a7c | ||
|
|
e429f082e4 | ||
|
|
53be95ac35 | ||
|
|
1a47b603c7 | ||
|
|
4b956af0f7 | ||
|
|
8a9495edce | ||
|
|
b96e8a5b2b | ||
|
|
a37789fbfe | ||
|
|
8d95fb1660 | ||
|
|
db83855fee | ||
|
|
56d896ca22 | ||
|
|
1169e7183e | ||
|
|
fe0b377561 | ||
|
|
5528d6bc8d | ||
|
|
7856ea8130 | ||
|
|
dbc684306b | ||
|
|
19187352b5 | ||
|
|
cc7ee35500 | ||
|
|
63ffd56fd9 | ||
|
|
4ea3da158d | ||
|
|
00daf35918 | ||
|
|
18bfc06091 | ||
|
|
0cf78f5c8e | ||
|
|
1193b37a53 | ||
|
|
6cb3fb2354 | ||
|
|
1109b40af4 | ||
|
|
479ab9377e | ||
|
|
5e01b3c0ab | ||
|
|
3b876dde1c | ||
|
|
36fdc5e737 | ||
|
|
0410687ae1 | ||
|
|
d05be2b599 | ||
|
|
39b0d4f0c2 | ||
|
|
661aefaebc | ||
|
|
d25c951c88 | ||
|
|
6d5d8142b3 | ||
|
|
dee8bdec24 | ||
|
|
e5010b761d | ||
|
|
8b345d4fac | ||
|
|
d9679801e2 | ||
|
|
293864e62b | ||
|
|
ddd1a25d93 | ||
|
|
a44e3bae90 | ||
|
|
97c682416c | ||
|
|
490d32e8d6 | ||
|
|
36739e1b11 | ||
|
|
8639cc313a | ||
|
|
20cacc6dd5 | ||
|
|
b60b0f2bf6 | ||
|
|
4db37a0f18 | ||
|
|
6a28219b7f | ||
|
|
904885db6c | ||
|
|
6a7b003246 | ||
|
|
a2aeb67d6d | ||
|
|
412b4f26b7 | ||
|
|
b95e380bd8 | ||
|
|
bf46b015a5 | ||
|
|
d23f4c8095 | ||
|
|
70c6c59e74 | ||
|
|
e69f662608 | ||
|
|
8d934663c5 | ||
|
|
12070b042f | ||
|
|
2e5ee5f836 | ||
|
|
177b36d869 | ||
|
|
cd484c0398 | ||
|
|
a6e3c2024f | ||
|
|
31e7037d4f | ||
|
|
13c2e297a8 | ||
|
|
45d08a5762 | ||
|
|
0568efc94b | ||
|
|
b61edb44bf | ||
|
|
415d01b36d | ||
|
|
b2864feb73 | ||
|
|
9ddafb6525 | ||
|
|
3771e86169 | ||
|
|
e8533afe78 | ||
|
|
28361f4105 | ||
|
|
110ef46f56 | ||
|
|
5cb23cd9b4 | ||
|
|
6d368e57af | ||
|
|
36bbaa7270 | ||
|
|
eb4888c361 | ||
|
|
1773f9672e | ||
|
|
59fbaf87e6 | ||
|
|
305a2aa6dc | ||
|
|
ed92b3476f | ||
|
|
b32fa9672f | ||
|
|
dd07271550 | ||
|
|
430db12d6f | ||
|
|
53b881c451 | ||
|
|
a4219bb9c7 | ||
|
|
7609260218 | ||
|
|
2c8bd15474 | ||
|
|
d6f3ad8b56 | ||
|
|
b9d2f57d41 | ||
|
|
cd34858f9a | ||
|
|
1639d5abee | ||
|
|
dd2e4546b9 | ||
|
|
5b6af723b0 | ||
|
|
9e660f957f | ||
|
|
1960af5149 | ||
|
|
792d16aba7 | ||
|
|
e6e854138b | ||
|
|
2117e5abf9 | ||
|
|
04151becfe | ||
|
|
6cc007e47e | ||
|
|
cd1877d34d | ||
|
|
df3bc19fc0 | ||
|
|
e4e7b1cb48 | ||
|
|
c46b7be051 | ||
|
|
5a8fa21cd1 | ||
|
|
7df048263b | ||
|
|
aba45f4cf5 | ||
|
|
d9bcac600c | ||
|
|
533021da3f | ||
|
|
ceeb7e23b4 | ||
|
|
f226edf018 | ||
|
|
e6f0f12240 | ||
|
|
9df7c03e02 | ||
|
|
1b8e290b30 | ||
|
|
a90fd17bea | ||
|
|
3fb358ca85 | ||
|
|
83d638e0e5 | ||
|
|
20a147fd04 | ||
|
|
730af8b9ac | ||
|
|
9a400cecd2 | ||
|
|
b5d9ac859f | ||
|
|
144cc3c40a | ||
|
|
2b514598d4 | ||
|
|
9c55f7d9e0 | ||
|
|
7fb070c5fc | ||
|
|
b0dccaea98 | ||
|
|
7939a0c9e7 | ||
|
|
5bccc32bb1 | ||
|
|
1bf7ce27da | ||
|
|
59085fd790 | ||
|
|
7f004ca720 | ||
|
|
71098fd9ac | ||
|
|
1ec17c77b5 | ||
|
|
adb3a81b2a | ||
|
|
ccf3a53253 | ||
|
|
9a7a3c6400 | ||
|
|
1963e2d7bb | ||
|
|
e385eb78e2 | ||
|
|
e80ac513c4 | ||
|
|
cf36613c65 | ||
|
|
ca3a9a7722 | ||
|
|
e85d5d519a | ||
|
|
2eccf190b4 | ||
|
|
2c18da0fbc | ||
|
|
776a13ef28 | ||
|
|
b5e6e4904c | ||
|
|
1e2d1503fe | ||
|
|
50d16acee9 | ||
|
|
710e0f9bba | ||
|
|
84efc14b00 | ||
|
|
ddb58119be | ||
|
|
3ced852eb4 | ||
|
|
9928c85d0a | ||
|
|
8a095a4032 | ||
|
|
9372cb7190 | ||
|
|
bf3a5891e3 | ||
|
|
ca61fa9d1d | ||
|
|
42eb8222fc | ||
|
|
2aca631390 | ||
|
|
b175295d43 | ||
|
|
0226456d41 | ||
|
|
d18aba0747 | ||
|
|
449b5e3f0a | ||
|
|
301216fc2e | ||
|
|
c3bef01fe9 | ||
|
|
19abf7a1b0 | ||
|
|
3e36a6e5fa | ||
|
|
e65bd9a524 | ||
|
|
697b331a65 | ||
|
|
3767450343 | ||
|
|
2ffa9b06c5 | ||
|
|
c1e80d209f | ||
|
|
a36f5a375a | ||
|
|
4e7f6d62d2 | ||
|
|
f8e637cdbc | ||
|
|
abf32cf499 | ||
|
|
eee24819d5 | ||
|
|
b7e4bf0be5 | ||
|
|
be65fe2521 | ||
|
|
05e62bd40d | ||
|
|
ca4e819183 | ||
|
|
80b75f11a0 | ||
|
|
a18f013d8c | ||
|
|
ffc06404c1 | ||
|
|
849cb0c707 | ||
|
|
219932258c | ||
|
|
59a5bb0c89 | ||
|
|
29fca5c1f0 | ||
|
|
fec0e7768a | ||
|
|
3dcb8ed32b | ||
|
|
2b1f5cfd0a | ||
|
|
84e08d39a4 | ||
|
|
0a171a6a72 | ||
|
|
cdcbe148c9 | ||
|
|
fea28640b5 | ||
|
|
295f19c54e | ||
|
|
de759e5870 | ||
|
|
e9995e0c80 | ||
|
|
234fd59d22 | ||
|
|
7617012292 | ||
|
|
e8085c1c0e | ||
|
|
9e8a9e7b9e | ||
|
|
e47516b0e0 | ||
|
|
b85cb20177 | ||
|
|
612c7927e9 | ||
|
|
ad4b719f3f | ||
|
|
24b690d19b | ||
|
|
e69af9cfbe | ||
|
|
23f324b1d8 | ||
|
|
a1f7a4245a | ||
|
|
5dab309921 | ||
|
|
57308b476d | ||
|
|
44d324bc7d | ||
|
|
90ae1bd7d7 | ||
|
|
67e40bc284 | ||
|
|
58a0f4d536 | ||
|
|
ebadedae41 | ||
|
|
3f89a34946 | ||
|
|
d823768464 | ||
|
|
174c440813 | ||
|
|
1479ecf03f | ||
|
|
c8ac6ec972 | ||
|
|
ee340b069b | ||
|
|
d13a35b9a8 | ||
|
|
b4e5b0107a | ||
|
|
0ce41b9f54 | ||
|
|
1be1829cfe | ||
|
|
160922c9fb | ||
|
|
8b072a3c3f | ||
|
|
7d98ea39e9 | ||
|
|
170a86f433 | ||
|
|
7d4c8d3735 | ||
|
|
2d23f579e9 | ||
|
|
9586e7f3ae | ||
|
|
7bda4095a6 | ||
|
|
54dc7f46fb | ||
|
|
87ddfc92a3 | ||
|
|
df98ebeb3b | ||
|
|
bbf3b40df8 | ||
|
|
a01e70012e | ||
|
|
48517665e2 | ||
|
|
387998a260 | ||
|
|
ef194fe70c | ||
|
|
c74c718021 | ||
|
|
c8f29bd424 | ||
|
|
64e26fe372 | ||
|
|
da213a1172 | ||
|
|
0e19dc9d17 | ||
|
|
27f9625d4e | ||
|
|
1a02741f95 | ||
|
|
35c69fcb3a | ||
|
|
561ff54afd | ||
|
|
f50c6ea3b9 | ||
|
|
40f6f5a72e | ||
|
|
700bedfe81 | ||
|
|
2b50407127 | ||
|
|
ba68402479 | ||
|
|
7b4c75aa90 | ||
|
|
a6c9e7a64a | ||
|
|
4c0c011714 | ||
|
|
4ba2f648df | ||
|
|
d8c2966d87 | ||
|
|
5a608fad93 | ||
|
|
9790d6ff69 | ||
|
|
f24e23d417 | ||
|
|
2eea4c163c | ||
|
|
541106f77b | ||
|
|
2231a9638f | ||
|
|
e01f910869 | ||
|
|
4f511655b4 | ||
|
|
081d3ed4ff | ||
|
|
46703c5ed6 | ||
|
|
db2ad06e7a | ||
|
|
328998be57 | ||
|
|
cb6dfa1521 | ||
|
|
f54f127fd4 | ||
|
|
00bc1e0998 | ||
|
|
8e0cad21d7 | ||
|
|
1df873540c | ||
|
|
454f7acb00 | ||
|
|
e848a5e4d8 | ||
|
|
5fa51ca833 | ||
|
|
28ee65da9a | ||
|
|
f2eeab8609 | ||
|
|
37b529a1d8 | ||
|
|
31f2abb3a8 | ||
|
|
10b6e0f35e | ||
|
|
f1d9655ea2 | ||
|
|
793845c92e | ||
|
|
52c8de4b5c | ||
|
|
3b3b0d7388 | ||
|
|
2bf4565c83 | ||
|
|
ee95bf3bcc | ||
|
|
f53f7d0fee | ||
|
|
8bc6e4c33e | ||
|
|
4b78fab2ac | ||
|
|
40f8b6da71 | ||
|
|
f92cb3d3ea | ||
|
|
1bc2ba2284 | ||
|
|
8ac84cb7c1 | ||
|
|
385d1b0979 | ||
|
|
01210c401d | ||
|
|
d48f54c086 | ||
|
|
7a800928e2 | ||
|
|
a893150c9e | ||
|
|
50a1092a65 | ||
|
|
555109c243 | ||
|
|
7409246425 | ||
|
|
feb38f52ea | ||
|
|
69ac2d1303 | ||
|
|
023a026a85 | ||
|
|
5198476d06 | ||
|
|
bc614ade20 | ||
|
|
86cf3a9630 | ||
|
|
aa57120c9c | ||
|
|
7ee0b78300 | ||
|
|
9ba4d95789 | ||
|
|
a221a6bfc3 | ||
|
|
0fea740a7f | ||
|
|
7755116473 | ||
|
|
244f64fc4d | ||
|
|
c4d105c02f | ||
|
|
c25bfb8ade | ||
|
|
e49a1c3d6e | ||
|
|
d81502e4b5 | ||
|
|
3763374f70 | ||
|
|
b043006a74 | ||
|
|
6897bedd7f | ||
|
|
b7fc2c4d1c | ||
|
|
4012c777a8 | ||
|
|
0ca0dd0ea5 | ||
|
|
a443507719 | ||
|
|
03714c70e0 | ||
|
|
6335d642ec | ||
|
|
48eb8c60ea | ||
|
|
065acfcb35 | ||
|
|
9b0d63b853 | ||
|
|
e6b93af59a | ||
|
|
024de21188 | ||
|
|
8ccab7fd78 | ||
|
|
7165f455a4 | ||
|
|
ff5ada3195 | ||
|
|
cae5f339c9 | ||
|
|
2b7b618302 | ||
|
|
5ec91691c8 | ||
|
|
690f456482 | ||
|
|
fa7e3e229e | ||
|
|
08a9af6b80 | ||
|
|
4322d3c09c | ||
|
|
0ba83b48fd | ||
|
|
dbdb98280a | ||
|
|
12641a754d | ||
|
|
882297877b | ||
|
|
bef0bd5226 | ||
|
|
e20da59b7f | ||
|
|
97682034a0 | ||
|
|
4326aa88e9 | ||
|
|
e60a5e6461 | ||
|
|
258673062a | ||
|
|
9b9ee82aea | ||
|
|
fb6f1c3a6e | ||
|
|
e8a2fe42e1 | ||
|
|
7dd422b0ce | ||
|
|
5820def039 | ||
|
|
7abfbd3e3b | ||
|
|
9b9ea2ed78 | ||
|
|
7abcff24dc | ||
|
|
c1b35a9a7e | ||
|
|
eeb9cc2324 | ||
|
|
db564dda61 | ||
|
|
1dc89389db | ||
|
|
74eb2c64e7 | ||
|
|
04f53d607b | ||
|
|
ee1d0bd61b | ||
|
|
3f1a54a962 | ||
|
|
670a50fdce | ||
|
|
b1c89d5dbc | ||
|
|
5afb5640c4 | ||
|
|
799d9c0fd7 | ||
|
|
4e833cd382 | ||
|
|
e933c29715 | ||
|
|
0bb78b5b17 | ||
|
|
12daa78948 | ||
|
|
8d563a9adf | ||
|
|
ae3295ce04 | ||
|
|
ca4221b7fb | ||
|
|
816cdd3156 | ||
|
|
eb13676193 | ||
|
|
7111ef5c8e | ||
|
|
86a40a8f3b | ||
|
|
268ed3990c | ||
|
|
bcde5f487d | ||
|
|
b749728946 | ||
|
|
7b6ac879db | ||
|
|
5633403f63 | ||
|
|
9f5ffca429 | ||
|
|
4a71208629 | ||
|
|
8d7d960173 | ||
|
|
5a69cd878d | ||
|
|
e81b1d6928 | ||
|
|
c22bace184 | ||
|
|
1dfaba8dad | ||
|
|
08c5403c00 | ||
|
|
8ac4ef3ce8 | ||
|
|
b6488af6fe | ||
|
|
65597bba5f | ||
|
|
88bdeebc93 | ||
|
|
9eb73c745c | ||
|
|
410f5f9437 | ||
|
|
390f20af79 | ||
|
|
d0954ec83d | ||
|
|
0718a7b5dd | ||
|
|
bc9d80f369 | ||
|
|
f94491526f | ||
|
|
c60ab35ad3 | ||
|
|
2227221725 | ||
|
|
90646f2551 | ||
|
|
8536c26828 | ||
|
|
a02e7a473f | ||
|
|
80d2f8cebd | ||
|
|
94a79b3c11 | ||
|
|
13e530d173 | ||
|
|
832ce4996a | ||
|
|
5fefd53bab | ||
|
|
646e203ea5 | ||
|
|
35162c6205 | ||
|
|
6ef20e2e07 | ||
|
|
a9724638af | ||
|
|
54677a41a4 | ||
|
|
c806130741 | ||
|
|
8b79022e48 | ||
|
|
1271596c8c | ||
|
|
e82b7e397e | ||
|
|
8813753a7e | ||
|
|
4da61a1f76 | ||
|
|
eb7d63a49a | ||
|
|
22dc95f8d9 | ||
|
|
ffa306f239 | ||
|
|
3cd8bf12ea | ||
|
|
ec51d0b52c | ||
|
|
0622c30e78 | ||
|
|
35e8338aca | ||
|
|
c5a3312bb1 | ||
|
|
1af865ae4e | ||
|
|
542584a531 | ||
|
|
6973546803 | ||
|
|
875488775b | ||
|
|
1c617ee172 | ||
|
|
ff86ef2114 | ||
|
|
8386ffc6aa | ||
|
|
5e65563e24 | ||
|
|
a26fd7df82 | ||
|
|
0d659a4170 | ||
|
|
5b14afce8b | ||
|
|
4856c31476 | ||
|
|
e07a33bb3f | ||
|
|
2d5ae5d24f | ||
|
|
2f0da0ae55 | ||
|
|
b33ab579bc | ||
|
|
94c8cb4c33 | ||
|
|
bc1143cc29 | ||
|
|
9e357e63fb | ||
|
|
f07a8fc831 | ||
|
|
1306ae91e0 | ||
|
|
11f7e6d01f | ||
|
|
c815ee5a54 | ||
|
|
cd92c7a135 | ||
|
|
6dcdeb1d81 | ||
|
|
05b6eb8d47 | ||
|
|
6f12c57780 | ||
|
|
18c806bb68 | ||
|
|
17b984dd75 | ||
|
|
ac889e9b1f | ||
|
|
e043c7aa85 | ||
|
|
c4a9d0b7b9 | ||
|
|
3902e35738 | ||
|
|
627684a806 | ||
|
|
b16e95a527 | ||
|
|
8fcf608515 | ||
|
|
2d86b7422d | ||
|
|
3c7cec40a2 | ||
|
|
c93515a45a | ||
|
|
73e9631459 | ||
|
|
e922d01ee7 | ||
|
|
d77e45ee41 | ||
|
|
b3774ea1a8 | ||
|
|
35324c4f59 | ||
|
|
81f3b354b4 | ||
|
|
3c7bc76d13 | ||
|
|
fde262e6a2 | ||
|
|
9dcefc79ac | ||
|
|
019a20e983 | ||
|
|
b7655ad5ee | ||
|
|
6e3d923ba5 | ||
|
|
c9cd62eff9 | ||
|
|
ade983ae6c | ||
|
|
5dd91b96c8 | ||
|
|
f4f4a55aba | ||
|
|
af76080539 | ||
|
|
a76c394f1a | ||
|
|
040f229ec1 | ||
|
|
617d4e0b99 | ||
|
|
747f89aa9e | ||
|
|
0b766062fd | ||
|
|
624a4430ca | ||
|
|
04377b03af | ||
|
|
cbcbdacca1 | ||
|
|
1cf6481847 | ||
|
|
902ae521ad | ||
|
|
dd679c295d | ||
|
|
f71b44c329 | ||
|
|
d0f13a7aaf | ||
|
|
7b071e8bf9 | ||
|
|
c24b592ed1 | ||
|
|
3faabacfa6 | ||
|
|
0587398f86 | ||
|
|
b7b4bde51d | ||
|
|
160dd70412 | ||
|
|
e354bbd647 | ||
|
|
b3e67cf8d6 | ||
|
|
b9c2dd83a9 | ||
|
|
0661598244 | ||
|
|
4d579fabdf | ||
|
|
6f77fac4b2 | ||
|
|
cd9bd03c47 | ||
|
|
932cb97e89 | ||
|
|
bedf92595c | ||
|
|
316668304e | ||
|
|
3da270c053 | ||
|
|
0d28047dfa | ||
|
|
ee4677b70e | ||
|
|
f8462fcdbc | ||
|
|
2afb269268 | ||
|
|
5fa13c6316 | ||
|
|
1c4c7243ed | ||
|
|
c9e6a521dc | ||
|
|
f2ecb9bc22 | ||
|
|
d60a20f2a5 | ||
|
|
c32a118157 | ||
|
|
07e6e440f2 | ||
|
|
4d6db6e394 | ||
|
|
9fa0f541ae | ||
|
|
73c5bab70c | ||
|
|
929fb69beb | ||
|
|
e52e8c76a4 | ||
|
|
1bf294c6fe | ||
|
|
d172aca74d | ||
|
|
66a62df64a | ||
|
|
902fd70071 | ||
|
|
b7b938fef3 | ||
|
|
6a6437fefb | ||
|
|
b90e959e48 | ||
|
|
abeefab726 | ||
|
|
1bea5cd1ef | ||
|
|
b4e22849bd | ||
|
|
07adea2465 | ||
|
|
e7fdb9239e | ||
|
|
b70adfbc09 | ||
|
|
1474549886 | ||
|
|
bfdf731fdd | ||
|
|
d3ced0cdf3 | ||
|
|
5fc2f94688 | ||
|
|
5aab4c98cf | ||
|
|
02073c01b6 | ||
|
|
d14d287c3a | ||
|
|
862083c0be | ||
|
|
1f9412c5cf | ||
|
|
dd18e505a6 | ||
|
|
7e2db583a0 | ||
|
|
8d33ced838 | ||
|
|
f83e5dcc6e | ||
|
|
eeaa9f3280 | ||
|
|
1fad137c1e | ||
|
|
b88bca35ab | ||
|
|
e9b9d0a781 | ||
|
|
d30c532a88 | ||
|
|
b4dbc4bc08 | ||
|
|
85d852cc54 | ||
|
|
484a4732f8 | ||
|
|
0649de8cc6 | ||
|
|
69f8481cf1 | ||
|
|
1625e5e3ac | ||
|
|
be1cc06a4b | ||
|
|
adc45d8151 | ||
|
|
965a79f029 | ||
|
|
7c72f781a2 | ||
|
|
b9a15471ef | ||
|
|
e667f4e89c | ||
|
|
349f6c7c90 | ||
|
|
e688639f47 | ||
|
|
8fbeb5c409 | ||
|
|
9d34dfe23e | ||
|
|
01ea54932c | ||
|
|
ad0ac93bd3 | ||
|
|
dc9d830d16 | ||
|
|
cab797ee1e | ||
|
|
e1416b984e | ||
|
|
ff95c32c2d | ||
|
|
2b2deb291a | ||
|
|
e51999ea1f | ||
|
|
7ba17b8552 | ||
|
|
406723fab0 | ||
|
|
e1ea3a1502 | ||
|
|
3f101c070d | ||
|
|
dd49cc9324 | ||
|
|
d607151734 | ||
|
|
9b780cb216 | ||
|
|
bd4c01c630 | ||
|
|
7f4a151a63 | ||
|
|
d6174dc69e | ||
|
|
61cd5775a2 | ||
|
|
69b4828add | ||
|
|
ca09103e98 | ||
|
|
efadf03238 | ||
|
|
11727b80f2 | ||
|
|
e57b7179e3 | ||
|
|
1c720ddb7d | ||
|
|
d19396e542 | ||
|
|
ae436249b7 | ||
|
|
4518a87f24 | ||
|
|
4cc0359c4d | ||
|
|
ec122e078b | ||
|
|
bbc0ba7b3c | ||
|
|
c4ba08db15 | ||
|
|
75ab8d4eed | ||
|
|
d91cfe7cb0 | ||
|
|
037c7d35d7 | ||
|
|
6fd0ab790c | ||
|
|
1a578ca68e | ||
|
|
60ea6cef08 | ||
|
|
d795dbffee | ||
|
|
a5163df44c | ||
|
|
9fd62088ab | ||
|
|
1f162c85d8 | ||
|
|
9ac6a6a770 | ||
|
|
78de922261 | ||
|
|
76c839b091 | ||
|
|
b5294d6d25 | ||
|
|
764963b087 | ||
|
|
0f7ce379d6 | ||
|
|
1d066f13ba | ||
|
|
1c9450ca10 | ||
|
|
4f4f9405fe | ||
|
|
284e5e472f | ||
|
|
14c1026ad1 | ||
|
|
a6f69cc433 | ||
|
|
dfb50586aa | ||
|
|
4f1358ffc7 | ||
|
|
1d12b1c925 | ||
|
|
de8202554a | ||
|
|
80655e1ca7 | ||
|
|
4148399f6d | ||
|
|
0bcba06ebf | ||
|
|
c2cc965c21 | ||
|
|
dd0c950474 | ||
|
|
b7c8baacc9 | ||
|
|
5e2fa65a4c | ||
|
|
52676eb113 | ||
|
|
bf5ca8908e | ||
|
|
acbe62d6ed | ||
|
|
79ec921abc | ||
|
|
65bd88af72 | ||
|
|
0273b4d2bb | ||
|
|
63ef21287a | ||
|
|
1be320b755 | ||
|
|
abcad958ab | ||
|
|
35b4350455 | ||
|
|
8f1251e59b | ||
|
|
0400ab3c53 | ||
|
|
2f3d614ac0 | ||
|
|
fd90b10444 | ||
|
|
7f5ec35ada | ||
|
|
b7f7b0d470 | ||
|
|
97fb35db90 | ||
|
|
69abcd0786 | ||
|
|
d697b93f6a | ||
|
|
2290b35317 | ||
|
|
d838ff0cd9 | ||
|
|
a2aa9d61a9 | ||
|
|
056d791ae9 | ||
|
|
d3acacb20b | ||
|
|
bb74305b26 | ||
|
|
32549c9eff | ||
|
|
83b5aa7d7b | ||
|
|
640a2c7e88 | ||
|
|
31aad963d6 | ||
|
|
326f4282d7 | ||
|
|
e5b3cf3db6 | ||
|
|
ca3e4a5135 | ||
|
|
c1607bbfb3 | ||
|
|
0639201b4c | ||
|
|
b5fe3b8ce4 | ||
|
|
2362efe5fc | ||
|
|
308d8889e4 | ||
|
|
5e4ea21377 | ||
|
|
45489ad600 | ||
|
|
683cde5a8b | ||
|
|
8a9c781de2 | ||
|
|
6812998c8d | ||
|
|
89fda1eee5 | ||
|
|
0cf0170144 | ||
|
|
cb79c8b1ff | ||
|
|
658dd6a0ec | ||
|
|
e6049eca2c | ||
|
|
efcaa36325 | ||
|
|
905efd0454 | ||
|
|
3ce1c04cf2 | ||
|
|
cb979f8975 | ||
|
|
cc8cea0049 | ||
|
|
a94e6143e1 | ||
|
|
699c97eaf9 | ||
|
|
10d4ec9bba | ||
|
|
e1f1b10f56 | ||
|
|
cfc09b8f3b | ||
|
|
4c1571ff2d | ||
|
|
5aea520cd1 | ||
|
|
00294f1aad | ||
|
|
e0fd45f838 | ||
|
|
a7e8363ed7 | ||
|
|
cb144c5bcf | ||
|
|
57a9570d34 | ||
|
|
28162762ef | ||
|
|
b9e745a7fb | ||
|
|
e08e59c226 | ||
|
|
3d6b02a016 | ||
|
|
b18a7b1a23 | ||
|
|
8595674eb0 | ||
|
|
23fd50df21 | ||
|
|
af80997ed4 | ||
|
|
7e3ac2959e | ||
|
|
78124c505e | ||
|
|
589b3f9540 | ||
|
|
bd505d858a | ||
|
|
308909f4eb | ||
|
|
9cfcda2938 | ||
|
|
fa4887ffef | ||
|
|
f70f26149e | ||
|
|
3cc904dc18 | ||
|
|
16c6346797 | ||
|
|
01b8f92d43 | ||
|
|
082f0a928f | ||
|
|
2ec4d6e006 | ||
|
|
7bd46b2182 | ||
|
|
2e9ba3bcfc | ||
|
|
551e374786 | ||
|
|
4366858b73 | ||
|
|
29b7c24312 | ||
|
|
3c5894db5d | ||
|
|
1d652272d7 | ||
|
|
d8c7f479ae | ||
|
|
3a0cb3fc72 | ||
|
|
65f1ec8bf4 | ||
|
|
0421e16910 | ||
|
|
2489d8e95f | ||
|
|
ac46ac7372 | ||
|
|
3ed3c90dae | ||
|
|
a45530393e | ||
|
|
a3e4b61216 | ||
|
|
c4939dd231 | ||
|
|
c20303ebf1 | ||
|
|
d7627899ea | ||
|
|
87f82fb23f | ||
|
|
f866cdd4aa | ||
|
|
a9fc44a4a2 | ||
|
|
ee00e66e4f | ||
|
|
cfa97759da | ||
|
|
cf26b9fd58 | ||
|
|
6a5ddcc06d | ||
|
|
592667a845 | ||
|
|
8f6e3db71d | ||
|
|
70502414c3 | ||
|
|
c9189d37f5 | ||
|
|
9e62e32e0a | ||
|
|
f592126d63 | ||
|
|
c26b360bcc | ||
|
|
33c844bc97 | ||
|
|
23a4a90afa | ||
|
|
643d8cc644 | ||
|
|
10d9f73982 | ||
|
|
a8f3e079a4 | ||
|
|
8ad258d6b3 | ||
|
|
9a37d61892 | ||
|
|
30b5443ee1 | ||
|
|
82885da6aa | ||
|
|
b498b8b437 | ||
|
|
7109fe405a | ||
|
|
0611cf2d89 | ||
|
|
2f5a1770c4 | ||
|
|
f7ee43fc89 | ||
|
|
1457bdf69b | ||
|
|
db4a1a918e | ||
|
|
66fafc25c8 | ||
|
|
b83cd39754 | ||
|
|
3010643dc1 | ||
|
|
823d6467b9 | ||
|
|
9ebdf9c22c | ||
|
|
0e4421ddc2 | ||
|
|
3fbdf836cd | ||
|
|
124c07efa3 | ||
|
|
5d8cb69938 | ||
|
|
5e2f19b73e | ||
|
|
6e5f2dc910 | ||
|
|
11119c8aa6 | ||
|
|
b53ebafa9b | ||
|
|
53bb74b837 | ||
|
|
8b56ace8d1 | ||
|
|
524b8414d5 | ||
|
|
88bfa05921 | ||
|
|
4115463922 | ||
|
|
83ab0b2ee4 | ||
|
|
5bacadbca0 | ||
|
|
005930c8a0 | ||
|
|
a16e6ff00b | ||
|
|
aef334ec61 | ||
|
|
7917a59757 | ||
|
|
954fc0f5fb | ||
|
|
f9578493b4 | ||
|
|
f49a82745f | ||
|
|
84bd67bdea | ||
|
|
e32bb0a573 | ||
|
|
8f5d4be864 | ||
|
|
e99c425120 | ||
|
|
369379df2f | ||
|
|
9a35575741 | ||
|
|
455ca956ab | ||
|
|
b87df11941 | ||
|
|
beb9e2241b | ||
|
|
71c78d04c6 | ||
|
|
9a5b18d842 | ||
|
|
702baf3614 | ||
|
|
c8b7a8d51e | ||
|
|
95f1d2ca14 | ||
|
|
d4673abd01 | ||
|
|
225f0ab437 | ||
|
|
7a36a53a4b | ||
|
|
d9a3469e19 | ||
|
|
46a5202edb | ||
|
|
e28b55df9d | ||
|
|
91a8d6ac6c | ||
|
|
151d7bb5ca | ||
|
|
7432f294b2 | ||
|
|
6ac2bd3c1f | ||
|
|
3ad238e7e8 | ||
|
|
59230fe57a | ||
|
|
43e1e62b41 | ||
|
|
afb4dd5ce9 | ||
|
|
f2b861c369 | ||
|
|
4080966331 | ||
|
|
54b4662322 | ||
|
|
26e8e2afc9 | ||
|
|
9aa705f3e7 | ||
|
|
cb49c90b4a | ||
|
|
84b2b83901 | ||
|
|
abebc9d3aa | ||
|
|
19a6044044 | ||
|
|
6a396561a8 | ||
|
|
025b822046 | ||
|
|
1f95c684d8 | ||
|
|
7116370908 | ||
|
|
caca6237b8 | ||
|
|
c5ddf1644d | ||
|
|
7147874d79 | ||
|
|
91bcbcf47d | ||
|
|
e9ecff62a3 | ||
|
|
69e081a279 | ||
|
|
51ce9847e2 | ||
|
|
988cc8bd3d | ||
|
|
9b34ddfd9d | ||
|
|
bd158984b7 | ||
|
|
ba76baf6ce | ||
|
|
19cf36c1e6 | ||
|
|
2bee860748 | ||
|
|
edcbfeca1c | ||
|
|
db7a629e7d | ||
|
|
213ff373a9 | ||
|
|
13fe371b73 | ||
|
|
42e8c28320 | ||
|
|
cefeff50c9 | ||
|
|
d3bb247b65 | ||
|
|
6a7097a70f | ||
|
|
c00ba4ad67 | ||
|
|
63f3639196 | ||
|
|
5a02b65b66 | ||
|
|
daf0dfa761 | ||
|
|
9aaf0ff08d | ||
|
|
afac7406d7 | ||
|
|
6ae7c6e7ab | ||
|
|
16e8b01bcc | ||
|
|
ffd37f3658 | ||
|
|
f6d18b18b9 | ||
|
|
2061ea8e18 | ||
|
|
f9ff03d85d | ||
|
|
4b8a8e83d2 | ||
|
|
47466e7322 | ||
|
|
92be6e1b56 | ||
|
|
f763840c14 | ||
|
|
09fed92c4f | ||
|
|
0cb4e1db64 | ||
|
|
66c7afc8db | ||
|
|
7482006851 | ||
|
|
45f17d81e7 | ||
|
|
dc2e557d2c | ||
|
|
6d4630e2d9 | ||
|
|
fc96bc6b4e | ||
|
|
c13986a88f | ||
|
|
6eb7f15045 | ||
|
|
61346438eb | ||
|
|
47e520c4b0 | ||
|
|
bcdae3d3e7 | ||
|
|
a17aafeabd | ||
|
|
286c27f7f8 | ||
|
|
a44d08c352 | ||
|
|
aeb396f000 | ||
|
|
6c8dcbadb4 | ||
|
|
0071502c83 | ||
|
|
eb47e19df7 | ||
|
|
8ff2d10697 | ||
|
|
e1bfb4f7c2 | ||
|
|
8ae699b751 | ||
|
|
6381d323da | ||
|
|
8e9ec81591 | ||
|
|
ad847e0114 | ||
|
|
d44dd3e738 | ||
|
|
6b6a3db89a | ||
|
|
cecdb4e76d | ||
|
|
c984497454 | ||
|
|
5a617ad824 | ||
|
|
7f83846937 | ||
|
|
19de6e7d52 | ||
|
|
12d2f961cf | ||
|
|
8fe549fc55 | ||
|
|
a99e55e884 | ||
|
|
e361f770e8 | ||
|
|
a27e13bcb3 | ||
|
|
03cf25766b | ||
|
|
9ce42a8e98 | ||
|
|
c03a5b08fd | ||
|
|
9b5853d3f9 | ||
|
|
8a3735dc01 | ||
|
|
aae662ab5e | ||
|
|
d051f02a43 | ||
|
|
2e4cf0dfc6 | ||
|
|
fc76e2042d | ||
|
|
d7f462d21f | ||
|
|
2b61598c21 | ||
|
|
799dc3a38f | ||
|
|
9c76dce17d | ||
|
|
28ac79bbe5 | ||
|
|
bdf825a2b5 | ||
|
|
37d03a2735 | ||
|
|
e8fde4ad0a | ||
|
|
1aa29a82fb | ||
|
|
60f292a5a7 | ||
|
|
1f956ab1db | ||
|
|
df39fa5545 | ||
|
|
dd0800f543 | ||
|
|
8b3c6eb1ff | ||
|
|
88b35c0051 | ||
|
|
2f83169ddd | ||
|
|
ce4b301f5c | ||
|
|
433f46b8f1 | ||
|
|
03eb52dc14 | ||
|
|
9d785679c5 | ||
|
|
699a4f96b0 | ||
|
|
afd6f0f4d6 | ||
|
|
eaadc45fce | ||
|
|
e9852a6d98 | ||
|
|
e1b3e769d8 | ||
|
|
501535a9a4 | ||
|
|
fb8608e467 | ||
|
|
e9eb8c250a | ||
|
|
eaa5a9d375 | ||
|
|
d28834591a | ||
|
|
49aa0a20cd | ||
|
|
8d611bd6c6 | ||
|
|
bfe8650ec9 | ||
|
|
fd52a5f388 | ||
|
|
6b8c5ea1fb | ||
|
|
8347feceff | ||
|
|
626b7fc6b3 | ||
|
|
1701c9142b | ||
|
|
245794ed53 | ||
|
|
24aba30fa8 | ||
|
|
6338472e73 | ||
|
|
580b46a394 | ||
|
|
ea1a34353c | ||
|
|
f9790e0e3e | ||
|
|
540c4a72a2 | ||
|
|
bc905304e7 | ||
|
|
ad04309f9d | ||
|
|
684ffb8525 | ||
|
|
049764fe67 | ||
|
|
a048c45b32 | ||
|
|
60c78642b1 | ||
|
|
5c7f551922 | ||
|
|
ceac7841a0 | ||
|
|
a29fc9d3cc | ||
|
|
f5dbc85450 | ||
|
|
6a86a6906c | ||
|
|
2b4bd1a79d | ||
|
|
2b2ce4eb29 | ||
|
|
6ac875aeb5 | ||
|
|
f43c6d3899 | ||
|
|
3f240868d0 | ||
|
|
5ccea973ee | ||
|
|
c1d59d9203 | ||
|
|
c6d3eb7131 | ||
|
|
f462bbe98b | ||
|
|
c6be5fcf84 | ||
|
|
023d9e194f | ||
|
|
78ad964481 | ||
|
|
9c9a8277a9 | ||
|
|
3f414ded5b | ||
|
|
5906824ffc | ||
|
|
737c87bdf8 | ||
|
|
bb27734a07 | ||
|
|
a9e6880add | ||
|
|
a1c3bf19ae | ||
|
|
0dc86e8662 | ||
|
|
bddc731390 | ||
|
|
2521aa2621 | ||
|
|
23af6f3031 | ||
|
|
89ac5af115 | ||
|
|
1f1ac04640 | ||
|
|
67d2eeaaff | ||
|
|
0788af941e | ||
|
|
484cea229c | ||
|
|
827a680f81 | ||
|
|
8b5c170409 | ||
|
|
9ec76c2738 | ||
|
|
ea9539ad0a | ||
|
|
03f4040c09 | ||
|
|
869f5d35bd | ||
|
|
01ac1c601f | ||
|
|
22f3f5ce59 | ||
|
|
0b430c90f4 | ||
|
|
080483b2d0 | ||
|
|
2da645f25b | ||
|
|
3ff6c35e35 | ||
|
|
5f3fb52833 | ||
|
|
6117053dd7 | ||
|
|
c3a1faffca | ||
|
|
5d85fdda46 | ||
|
|
907705b657 | ||
|
|
22e460d7bf | ||
|
|
3a81ebfcd9 | ||
|
|
ec92225e50 | ||
|
|
5163d472b3 | ||
|
|
069a2d287c | ||
|
|
01b8469fbb | ||
|
|
421a590514 | ||
|
|
a0a494e724 | ||
|
|
3f6f0b7430 | ||
|
|
b8d161ffee | ||
|
|
e27ff98517 | ||
|
|
4c2c6bbb54 | ||
|
|
5de92719f8 | ||
|
|
34b9d71cbf | ||
|
|
57e9253270 | ||
|
|
99d0ecfd59 | ||
|
|
706debfa33 | ||
|
|
db26fb6f39 | ||
|
|
57e36fb728 | ||
|
|
7c49eeca97 | ||
|
|
8d065255d6 | ||
|
|
a630543ecc | ||
|
|
989e397ee2 | ||
|
|
f99843737f | ||
|
|
5197111a3a | ||
|
|
d12339bb50 | ||
|
|
e166e9f754 | ||
|
|
1d5bca81da | ||
|
|
56891d6183 | ||
|
|
d0f1882995 | ||
|
|
b1b67807ac | ||
|
|
265c67c91c | ||
|
|
7c55c50b4c | ||
|
|
a42b74b614 | ||
|
|
262b931a1e | ||
|
|
3f1db5aa56 | ||
|
|
95ce6878e6 | ||
|
|
9f6fea7038 | ||
|
|
28eaa2ee7f | ||
|
|
c35cf56d8a | ||
|
|
0526c58913 | ||
|
|
1f20c18ad6 | ||
|
|
4b56eca5e2 | ||
|
|
d14702494e | ||
|
|
f2bda0f2d1 | ||
|
|
5f90628d2d | ||
|
|
409c3eec55 | ||
|
|
2a7ea24d17 | ||
|
|
f81a398f4b | ||
|
|
7a94f83019 | ||
|
|
134234da12 | ||
|
|
7354c8933c | ||
|
|
0565a83085 | ||
|
|
eab79eaac2 | ||
|
|
1007f7ee6b | ||
|
|
ce008843e2 | ||
|
|
ea5ae50813 | ||
|
|
0970f0659a | ||
|
|
ef2123422c | ||
|
|
6d82642176 | ||
|
|
f9c22574a7 | ||
|
|
3fde6af2a2 | ||
|
|
5322468819 | ||
|
|
0ce77a2729 | ||
|
|
e50cb41d1f | ||
|
|
428c360abf | ||
|
|
b89f3906e9 | ||
|
|
c3898245ce | ||
|
|
f15748b4e9 | ||
|
|
d11c871526 | ||
|
|
6944d842c3 | ||
|
|
183087b441 | ||
|
|
5e081805f1 | ||
|
|
e1addd1485 | ||
|
|
801f13c2d3 | ||
|
|
6dcb22dfc2 | ||
|
|
e5dbd86eb3 | ||
|
|
1706891be4 | ||
|
|
11323c0206 | ||
|
|
c36d252159 | ||
|
|
7d1eeb1e34 | ||
|
|
e081a6aa2c | ||
|
|
014f238f6c | ||
|
|
9482b37672 | ||
|
|
69c5601de4 | ||
|
|
96c717f748 | ||
|
|
856ba36a20 | ||
|
|
396cf51794 | ||
|
|
8138790396 | ||
|
|
e698468c39 | ||
|
|
da005a35bf | ||
|
|
9b62f28e93 | ||
|
|
5adc738c03 | ||
|
|
d784394ea9 | ||
|
|
b1cbb7893c | ||
|
|
51b2049429 | ||
|
|
84c8af7357 | ||
|
|
69cbda8a39 | ||
|
|
48f351ba0d | ||
|
|
0a7fac77ff | ||
|
|
ff336b40ae | ||
|
|
86a8da3ef3 | ||
|
|
a72b681205 | ||
|
|
3c75a4a012 | ||
|
|
f9fc4b9a06 | ||
|
|
6869f940ac | ||
|
|
79f0f90f3e | ||
|
|
1119610a10 | ||
|
|
90fe3f04c0 | ||
|
|
aca0aef285 | ||
|
|
8134b73902 | ||
|
|
57414cd0b8 | ||
|
|
6792eb53f0 | ||
|
|
a6d4814980 | ||
|
|
3ef0afa6bc | ||
|
|
942be17e61 | ||
|
|
37e8f14e3b | ||
|
|
64ca771c51 | ||
|
|
df2c2cd827 | ||
|
|
4b692e4697 | ||
|
|
a0fa5ff4c2 | ||
|
|
32df0ae8fe | ||
|
|
73b9bcac7a | ||
|
|
11f606631c | ||
|
|
9f696441e3 | ||
|
|
118d18613f | ||
|
|
a39bc9b7f7 | ||
|
|
e0e17359c9 | ||
|
|
5ab25b0bc8 | ||
|
|
686e7eb6c1 | ||
|
|
c3ba8662b9 | ||
|
|
b7e23fd046 | ||
|
|
9ff89ba263 | ||
|
|
c84f85444a | ||
|
|
37c10e7b48 | ||
|
|
02b8292a2e | ||
|
|
2d1909c227 | ||
|
|
f470606af0 | ||
|
|
4a7b3f17c2 | ||
|
|
788df21115 | ||
|
|
2aaaa8b416 | ||
|
|
2660084401 | ||
|
|
e0dfb888c1 | ||
|
|
ab66b5585d | ||
|
|
bf8b9f32df | ||
|
|
d259143736 | ||
|
|
83dc82a308 | ||
|
|
233f4bb04f | ||
|
|
8183d17706 | ||
|
|
feedcae410 | ||
|
|
3157ea741e | ||
|
|
623040bf3e | ||
|
|
6a394f697a | ||
|
|
3908f4b5ce | ||
|
|
ad21ee1e64 | ||
|
|
6c69796248 | ||
|
|
e6f79562dc | ||
|
|
5e9c655672 | ||
|
|
6b01100ca4 | ||
|
|
838382ea0a | ||
|
|
3c62c22f3a | ||
|
|
bc1197b4a0 | ||
|
|
d691570099 | ||
|
|
772d55fa45 | ||
|
|
676072e96b | ||
|
|
29dec2d9f7 | ||
|
|
b1d6099e2c | ||
|
|
e5cbf010a3 | ||
|
|
023364f968 | ||
|
|
26fe7f610d | ||
|
|
37d6e54e70 | ||
|
|
adc4c59a99 | ||
|
|
16fd528e95 | ||
|
|
efdfdac6cb | ||
|
|
03ebe6b176 | ||
|
|
730019b420 | ||
|
|
b0f61038e3 | ||
|
|
477c36d880 | ||
|
|
d4a99ce9b2 | ||
|
|
025c5fe301 | ||
|
|
422f5deafb | ||
|
|
00b5473a7a | ||
|
|
945264d927 | ||
|
|
74848cd015 | ||
|
|
c583e3238a | ||
|
|
0cc7abf322 | ||
|
|
8f3b9c532c | ||
|
|
4ce35de276 | ||
|
|
7c05aa625f | ||
|
|
139ac0b269 | ||
|
|
8ba35083d8 | ||
|
|
02003abf1d | ||
|
|
88ce729351 | ||
|
|
dcac392e43 | ||
|
|
87cfa4c4d4 | ||
|
|
58ec829d1a | ||
|
|
90fd2daa01 | ||
|
|
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 | ||
|
|
b2b29c692e | ||
|
|
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 | ||
|
|
7d42da5d3c | ||
|
|
82770e6dd0 | ||
|
|
62bbfc6075 | ||
|
|
a5eb77dd87 | ||
|
|
cb9cf4885f | ||
|
|
a5455925ea | ||
|
|
61ef383c38 | ||
|
|
b0aa706c07 | ||
|
|
a04c8f6214 | ||
|
|
fd5b582c6c | ||
|
|
dc45613b7b | ||
|
|
d986d8f398 | ||
|
|
6c64f20a14 | ||
|
|
2071087794 | ||
|
|
ba56ab719c | ||
|
|
617c053b95 | ||
|
|
868cff2c4c | ||
|
|
8e23ebf3e4 | ||
|
|
6dd6eff02c | ||
|
|
3a1fcd2147 | ||
|
|
d4bd4a8150 | ||
|
|
2ace518db9 | ||
|
|
e8641cee8f | ||
|
|
884328d10f | ||
|
|
d8bd8a29bc | ||
|
|
cbd6b796ca | ||
|
|
90cfa4ed5c | ||
|
|
6426abfedf | ||
|
|
d746928765 | ||
|
|
f83554c817 | ||
|
|
6fc4741c9a | ||
|
|
7b63346bd0 | ||
|
|
737c63e8b0 | ||
|
|
94b37f6414 | ||
|
|
5fa2bc3bc8 | ||
|
|
5d7a5ace66 | ||
|
|
0bd213a327 | ||
|
|
3d9f351d84 | ||
|
|
9fda220f33 | ||
|
|
991ae1d6e3 | ||
|
|
b993be4658 | ||
|
|
c4f8af2311 | ||
|
|
4c541e98ab | ||
|
|
7b8b24b45d | ||
|
|
a61a44edc9 | ||
|
|
393f3e5737 | ||
|
|
c34e38e50f | ||
|
|
b98676ea77 | ||
|
|
002c67e48c | ||
|
|
cf21684916 | ||
|
|
9fe1a904c8 | ||
|
|
c4e67db75f | ||
|
|
8487555315 | ||
|
|
304c1ef5d2 | ||
|
|
c911a7a310 | ||
|
|
322f29b31b | ||
|
|
f0a86db9e4 | ||
|
|
60bcfa8ab1 | ||
|
|
074b63d68d | ||
|
|
45fb856898 | ||
|
|
138ed85f93 | ||
|
|
a632dd172e | ||
|
|
8fbf915710 | ||
|
|
8eafc5816d | ||
|
|
17b50df101 | ||
|
|
b9e436d56d | ||
|
|
a929db9939 | ||
|
|
8287232866 | ||
|
|
11330b608b | ||
|
|
ff94d188db | ||
|
|
332ce12eb5 | ||
|
|
e4eb0c7019 | ||
|
|
8e45d6462f | ||
|
|
1857dd72b9 | ||
|
|
e4c6285fab | ||
|
|
c150d24843 | ||
|
|
6c69119d09 | ||
|
|
d87b8f7652 | ||
|
|
577febe3b7 | ||
|
|
c8d56a237b | ||
|
|
fb018946b9 | ||
|
|
0697f4a964 | ||
|
|
4c0cfb77fb | ||
|
|
1a2885408d | ||
|
|
de8e363d33 | ||
|
|
7436ac0b5e | ||
|
|
eaf9447abc | ||
|
|
45cadb9cfb | ||
|
|
9bab31514e | ||
|
|
6e13320f36 | ||
|
|
1ed1e91189 | ||
|
|
7561afd92d | ||
|
|
92eb5836fb | ||
|
|
0068fcef88 | ||
|
|
e2df24522f | ||
|
|
0c185c78e3 | ||
|
|
7720e8005e | ||
|
|
4a738990ae | ||
|
|
f7e8f25b70 | ||
|
|
da828523f3 | ||
|
|
d621ea15a3 | ||
|
|
db74e573d1 | ||
|
|
d40656b69a | ||
|
|
4a5402db0f | ||
|
|
b7df1b0bb0 | ||
|
|
d0b80492c7 | ||
|
|
7174c3956c | ||
|
|
135f2617f6 | ||
|
|
5f855209c9 | ||
|
|
0741bcbbaa | ||
|
|
a4361a28b2 | ||
|
|
417164cc58 | ||
|
|
d9159ffc96 | ||
|
|
ec022e7acd | ||
|
|
7a0aa556ff | ||
|
|
9f7eaf22b0 | ||
|
|
6a3fee98fd | ||
|
|
abf5bfdd69 | ||
|
|
994939b121 | ||
|
|
1b3334341d | ||
|
|
286ac6dc05 | ||
|
|
85ae4cae34 | ||
|
|
ba840822bc | ||
|
|
d10515c003 | ||
|
|
0db5d24673 | ||
|
|
e6135c69b4 | ||
|
|
e2e4c97300 | ||
|
|
635d06df87 | ||
|
|
fcc7d126f9 | ||
|
|
fa152a908b | ||
|
|
230887bea3 | ||
|
|
8677aa1bca |
351
.github/workflows/build.yml
vendored
Normal file
351
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
name: Build keepass2android app
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# macos:
|
||||||
|
# Disabled. Does not work, maybe due to nuget version, see https://github.com/PhilippC/keepass2android/actions/runs/4297640426/jobs/7490853348
|
||||||
|
# should work again when the Project solution is converted to sdk style .csproj files.
|
||||||
|
|
||||||
|
# runs-on: macos-12
|
||||||
|
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# - name: Fetch submodules
|
||||||
|
# run: git submodule init && git submodule update
|
||||||
|
|
||||||
|
# - name: Setup Gradle
|
||||||
|
# uses: gradle/gradle-build-action@v2
|
||||||
|
|
||||||
|
# - name: Cache NuGet packages
|
||||||
|
# uses: actions/cache@v3
|
||||||
|
# with:
|
||||||
|
# path: ~/.nuget/packages
|
||||||
|
# key: ${{ runner.os }}-nuget-${{ hashFiles('src/**/*.csproj', 'src/**/packages.config') }}
|
||||||
|
# restore-keys: |
|
||||||
|
# ${{ runner.os }}-nuget-
|
||||||
|
|
||||||
|
# # As per https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md#visual-studio-for-mac
|
||||||
|
# - name: Switch to Visual Studio 2019
|
||||||
|
# if: ${{ false }} # Not needed. We stay with the default 'Visual Studio 2022' of macos-12 runner.
|
||||||
|
# run: |
|
||||||
|
# mv "/Applications/Visual Studio.app" "/Applications/Visual Studio 2022.app"
|
||||||
|
# mv "/Applications/Visual Studio 2019.app" "/Applications/Visual Studio.app"
|
||||||
|
|
||||||
|
# # As of 2022-12-02, keepass2android doesn't build with Xamarin >= 12.1 because there is some issue with SamsungPass. Removing SamsungPass would make the build succeed.
|
||||||
|
# - name: Set default Xamarin SDK versions
|
||||||
|
# run: |
|
||||||
|
# # If using the github runner 'macos-12'
|
||||||
|
# #$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.3
|
||||||
|
# #$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=12.0
|
||||||
|
# #$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=12.1 # Build fails in this case, as of 2022-12-02 : Xamarin/Android/Xamarin.Android.D8.targets(79,5): error : java.lang.ArrayIndexOutOfBoundsException : Index 4 out of bounds for length 4
|
||||||
|
# #$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=12.2 # Build fails in this case, as of 2022-12-02 : Xamarin/Android/Xamarin.Android.D8.targets(79,5): error : java.lang.ArrayIndexOutOfBoundsException : Index 4 out of bounds for length 4
|
||||||
|
# #$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=12.3 # Build fails in this case, as of 2022-12-02
|
||||||
|
# $VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=13.1
|
||||||
|
|
||||||
|
# # If using the github runner 'macos-11'
|
||||||
|
# #$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.0
|
||||||
|
# #$VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=12.0
|
||||||
|
|
||||||
|
# # If using the github runner 'macos-10.15'
|
||||||
|
# # $VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.2
|
||||||
|
|
||||||
|
# - name: Switch to JDK-11
|
||||||
|
# uses: actions/setup-java@v3
|
||||||
|
# with:
|
||||||
|
# java-version: '11'
|
||||||
|
# distribution: 'temurin'
|
||||||
|
|
||||||
|
# - name: Display java version
|
||||||
|
# run: java -version
|
||||||
|
|
||||||
|
# # Some components of Keepass2Android currently target android API 26 which are not available on the runner
|
||||||
|
# - name: Download android-26 API
|
||||||
|
# run: $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --install "platforms;android-26"
|
||||||
|
|
||||||
|
# - name: Build native dependencies
|
||||||
|
# run: make native
|
||||||
|
|
||||||
|
# - name: Build java dependencies
|
||||||
|
# run: make java
|
||||||
|
|
||||||
|
# - name: Install NuGet dependencies (net)
|
||||||
|
# run: make nuget Flavor=Net
|
||||||
|
|
||||||
|
# - name: Build keepass2android (net)
|
||||||
|
# run: |
|
||||||
|
# make msbuild Flavor=Net
|
||||||
|
|
||||||
|
# - name: Build APK (net)
|
||||||
|
# run: |
|
||||||
|
# make apk Flavor=Net
|
||||||
|
|
||||||
|
# - name: Archive production artifacts (net)
|
||||||
|
# uses: actions/upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# name: signed APK ('net' built on ${{ github.job }})
|
||||||
|
# path: |
|
||||||
|
# src/keepass2android/bin/*/*-Signed.apk
|
||||||
|
|
||||||
|
# - name: Install NuGet dependencies (nonet)
|
||||||
|
# run: make nuget Flavor=NoNet
|
||||||
|
|
||||||
|
# - name: Build keepass2android (nonet)
|
||||||
|
# run: |
|
||||||
|
# make msbuild Flavor=NoNet
|
||||||
|
|
||||||
|
# - name: Build APK (nonet)
|
||||||
|
# run: |
|
||||||
|
# make apk Flavor=NoNet
|
||||||
|
|
||||||
|
# - name: Archive production artifacts (nonet)
|
||||||
|
# uses: actions/upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# name: signed APK ('nonet' built on ${{ github.job }})
|
||||||
|
# path: |
|
||||||
|
# src/keepass2android/bin/*/*-Signed.apk
|
||||||
|
|
||||||
|
# - name: Perform "make distclean"
|
||||||
|
# run: make distclean
|
||||||
|
|
||||||
|
# linux:
|
||||||
|
# disabled.
|
||||||
|
# As per: xamarin/xamarin-android#7235 (comment)
|
||||||
|
# > Unfortunately the Classic OSS Xamarin.Android packages for Linux are no longer being built and as such they are not available for the v13.0 tag.
|
||||||
|
# we can re-enable this after porting to .net 6.0
|
||||||
|
|
||||||
|
# runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
# env:
|
||||||
|
# # Build Artifact of xamarin.android-oss dated 2021-02-02, master branch (= version 11.2.99) - *.deb cannot be installed because "lxd" package is not anymore shipped in current ubuntu version
|
||||||
|
# #xamarin_url: https://artprodcus3.artifacts.visualstudio.com/Ad0adf05a-e7d7-4b65-96fe-3f3884d42038/6fd3d886-57a5-4e31-8db7-52a1b47c07a8/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL3hhbWFyaW4vcHJvamVjdElkLzZmZDNkODg2LTU3YTUtNGUzMS04ZGI3LTUyYTFiNDdjMDdhOC9idWlsZElkLzM0NTE3L2FydGlmYWN0TmFtZS9JbnN0YWxsZXJzKy0rTGludXg1/content?format=zip
|
||||||
|
|
||||||
|
# # Build Artifact of xamarin.android-oss dated 2021-03-23, d16-9 branch (= version 11.2.2) - *.deb cannot be installed because "lxd" package is not anymore shipped in current ubuntu version
|
||||||
|
# #xamarin_url: https://artprodcus3.artifacts.visualstudio.com/Ad0adf05a-e7d7-4b65-96fe-3f3884d42038/6fd3d886-57a5-4e31-8db7-52a1b47c07a8/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL3hhbWFyaW4vcHJvamVjdElkLzZmZDNkODg2LTU3YTUtNGUzMS04ZGI3LTUyYTFiNDdjMDdhOC9idWlsZElkLzM3Njg0L2FydGlmYWN0TmFtZS9JbnN0YWxsZXJzKy0rTGludXg1/content?format=zip
|
||||||
|
|
||||||
|
# # Build Artifact of xamarin.android-oss dated 2021-07-21, master branch (= version 11.4.99)
|
||||||
|
# # xamarin_url: https://artprodcus3.artifacts.visualstudio.com/Ad0adf05a-e7d7-4b65-96fe-3f3884d42038/6fd3d886-57a5-4e31-8db7-52a1b47c07a8/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL3hhbWFyaW4vcHJvamVjdElkLzZmZDNkODg2LTU3YTUtNGUzMS04ZGI3LTUyYTFiNDdjMDdhOC9idWlsZElkLzQzNjU5L2FydGlmYWN0TmFtZS9pbnN0YWxsZXJzLXVuc2lnbmVkKy0rTGludXg1/content?format=zip
|
||||||
|
|
||||||
|
# # Build Artifact of xamarin.android-oss dated 2022-02-16, master branch (= version 12.2.99)
|
||||||
|
# xamarin_url: https://artprodcus3.artifacts.visualstudio.com/Ad0adf05a-e7d7-4b65-96fe-3f3884d42038/6fd3d886-57a5-4e31-8db7-52a1b47c07a8/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL3hhbWFyaW4vcHJvamVjdElkLzZmZDNkODg2LTU3YTUtNGUzMS04ZGI3LTUyYTFiNDdjMDdhOC9idWlsZElkLzU0OTUzL2FydGlmYWN0TmFtZS9pbnN0YWxsZXJzLXVuc2lnbmVkKy0rTGludXg1/content?format=zip
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# - name: Fetch submodules
|
||||||
|
# run: git submodule init && git submodule update
|
||||||
|
|
||||||
|
# - name: Setup Gradle
|
||||||
|
# uses: gradle/gradle-build-action@v2
|
||||||
|
|
||||||
|
# - name: Cache NuGet packages
|
||||||
|
# uses: actions/cache@v3
|
||||||
|
# with:
|
||||||
|
# path: ~/.nuget/packages
|
||||||
|
# key: ${{ runner.os }}-nuget-${{ hashFiles('src/**/*.csproj', 'src/**/packages.config') }}
|
||||||
|
# restore-keys: |
|
||||||
|
# ${{ runner.os }}-nuget-
|
||||||
|
|
||||||
|
# - name: Cache Xamarin.Android packages
|
||||||
|
# id: xamarin_cache
|
||||||
|
# uses: actions/cache@v3
|
||||||
|
# with:
|
||||||
|
# path: ~/xamarin.android-oss
|
||||||
|
# key: ${{ runner.os }}-xamarin.android-oss-${{ env.xamarin_url }}
|
||||||
|
# restore-keys: |
|
||||||
|
# ${{ runner.os }}-xamarin.android-oss-${{ env.xamarin_url }}
|
||||||
|
|
||||||
|
# - name: Install Mono
|
||||||
|
# if: ${{ false }} # disable for now since it is already installed on the runner which uses the same repo https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md#language-and-runtime
|
||||||
|
# run: |
|
||||||
|
# sudo apt install gnupg ca-certificates &&
|
||||||
|
# sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF &&
|
||||||
|
# echo "deb https://download.mono-project.com/repo/ubuntu stable-focal main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list &&
|
||||||
|
# sudo apt update &&
|
||||||
|
# sudo apt-get -y -t stable-focal install mono-complete
|
||||||
|
|
||||||
|
# - name: Download & unpack Xamarin.Android
|
||||||
|
# if: steps.xamarin_cache.outputs.cache-hit != 'true'
|
||||||
|
# run: |
|
||||||
|
# set -x
|
||||||
|
# cd $HOME &&
|
||||||
|
# wget -O "installers-unsigned - Linux.zip" ${{ env.xamarin_url }} &&
|
||||||
|
# unzip "installers-unsigned - Linux.zip" &&
|
||||||
|
# mkdir -p xamarin.android-oss &&
|
||||||
|
# DIR=$(unzip -Z -1 installers-unsigned\ -\ Linux.zip | cut -d '/' -f1 | sort -u) &&
|
||||||
|
# tar -xvf "$DIR"/xamarin.android-oss-*.tar.* --strip-components=1 -C xamarin.android-oss &&
|
||||||
|
# mv "$DIR"/*.deb xamarin.android-oss
|
||||||
|
|
||||||
|
# - name: Setup Xamarin.Android
|
||||||
|
# run: |
|
||||||
|
# cd $HOME &&
|
||||||
|
# sudo apt install -y ./xamarin.android-oss/*.deb &&
|
||||||
|
# echo "$HOME/xamarin.android-oss/bin/Release/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# - name: Switch to JDK-11
|
||||||
|
# uses: actions/setup-java@v3
|
||||||
|
# with:
|
||||||
|
# java-version: '11'
|
||||||
|
# distribution: 'temurin'
|
||||||
|
|
||||||
|
# - name: Display java version
|
||||||
|
# run: java -version
|
||||||
|
|
||||||
|
# # Some components of Keepass2Android currently target android API 26 which are not available on the runner
|
||||||
|
# - name: Download android-26 API
|
||||||
|
# run: $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --install "platforms;android-26"
|
||||||
|
|
||||||
|
# - name: Install libzip4
|
||||||
|
# if: ${{ false }} # disable for now since it is already installed on the runner
|
||||||
|
# run: sudo apt -y install libzip4
|
||||||
|
|
||||||
|
# - name: Build native dependencies
|
||||||
|
# run: make native
|
||||||
|
|
||||||
|
# - name: Build java dependencies
|
||||||
|
# run: make java
|
||||||
|
|
||||||
|
# - name: Install NuGet dependencies (net)
|
||||||
|
# run: make nuget Flavor=Net
|
||||||
|
|
||||||
|
# - name: Build keepass2android (net)
|
||||||
|
# run: |
|
||||||
|
# make msbuild Flavor=Net
|
||||||
|
|
||||||
|
# - name: Build APK (net)
|
||||||
|
# run: |
|
||||||
|
# make apk Flavor=Net
|
||||||
|
|
||||||
|
# - name: Archive production artifacts (net)
|
||||||
|
# uses: actions/upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# name: signed APK ('net' built on ${{ github.job }})
|
||||||
|
# path: |
|
||||||
|
# src/keepass2android/bin/*/*-Signed.apk
|
||||||
|
|
||||||
|
# - name: Install NuGet dependencies (nonet)
|
||||||
|
# run: make nuget Flavor=NoNet
|
||||||
|
|
||||||
|
# - name: Build keepass2android (nonet)
|
||||||
|
# run: |
|
||||||
|
# make msbuild Flavor=NoNet
|
||||||
|
|
||||||
|
# - name: Build APK (nonet)
|
||||||
|
# run: |
|
||||||
|
# make apk Flavor=NoNet
|
||||||
|
|
||||||
|
# - name: Archive production artifacts (nonet)
|
||||||
|
# uses: actions/upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# name: signed APK ('nonet' built on ${{ github.job }})
|
||||||
|
# path: |
|
||||||
|
# src/keepass2android/bin/*/*-Signed.apk
|
||||||
|
|
||||||
|
# - name: Perform "make distclean"
|
||||||
|
# run: make distclean
|
||||||
|
|
||||||
|
windows:
|
||||||
|
|
||||||
|
# on windows-2022 it builds with:
|
||||||
|
# Microsoft Visual Studio\2022\Enterprise
|
||||||
|
# Found Java SDK version 11.0.12
|
||||||
|
# Found Xamarin.Android 13.1.0.1
|
||||||
|
#
|
||||||
|
runs-on: windows-2022
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
|
||||||
|
- name: Cache NuGet packages
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.nuget/packages
|
||||||
|
key: ${{ runner.os }}-nuget-${{ hashFiles('src/**/*.csproj', 'src/**/packages.config') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-nuget-
|
||||||
|
|
||||||
|
- name: Fetch submodules
|
||||||
|
run: git submodule init && git submodule update
|
||||||
|
|
||||||
|
# Workaround an issue when building on windows-2022. Error was
|
||||||
|
# D8 : OpenJDK 64-Bit Server VM warning : INFO: os::commit_memory(0x00000000ae400000, 330301440, 0) failed; error='The paging file is too small for this operation to complete' (DOS error/errno=1455) [D:\a\keepass2android\keepass2android\src\keepass2android\keepass2android-app.csproj]
|
||||||
|
# C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.D8.targets(81,5): error MSB6006: "java.exe" exited with code 1. [D:\a\keepass2android\keepass2android\src\keepass2android\keepass2android-app.csproj]
|
||||||
|
- name: Configure Pagefile
|
||||||
|
uses: al-cheb/configure-pagefile-action@v1.3
|
||||||
|
with:
|
||||||
|
minimum-size: 8GB
|
||||||
|
|
||||||
|
- name: Add msbuild to PATH
|
||||||
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
# If we want to also have nmake, use this instead
|
||||||
|
#uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
|
||||||
|
- name: Switch to JDK-11
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '11'
|
||||||
|
distribution: 'temurin'
|
||||||
|
|
||||||
|
- name: Display java version
|
||||||
|
run: java -version
|
||||||
|
|
||||||
|
# Some components of Keepass2Android currently target android API 26 which are not available on the runner
|
||||||
|
- name: Download android-26 API
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
%ANDROID_SDK_ROOT%\cmdline-tools\latest\bin\sdkmanager --install "platforms;android-26"
|
||||||
|
|
||||||
|
- name: Build native dependencies
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
make native
|
||||||
|
|
||||||
|
- name: Build java dependencies
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
make java
|
||||||
|
|
||||||
|
- name: Install NuGet dependencies (net)
|
||||||
|
run: make nuget Flavor=Net
|
||||||
|
|
||||||
|
- name: Build keepass2android (net)
|
||||||
|
run: |
|
||||||
|
make msbuild Flavor=Net
|
||||||
|
|
||||||
|
- name: Build APK (net)
|
||||||
|
run: |
|
||||||
|
make apk Flavor=Net
|
||||||
|
|
||||||
|
- name: Archive production artifacts (net)
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: signed APK ('net' built on ${{ github.job }})
|
||||||
|
path: |
|
||||||
|
src/keepass2android/bin/*/*-Signed.apk
|
||||||
|
|
||||||
|
- name: Install NuGet dependencies (nonet)
|
||||||
|
run: make nuget Flavor=NoNet
|
||||||
|
|
||||||
|
- name: Build keepass2android (nonet)
|
||||||
|
run: |
|
||||||
|
make msbuild Flavor=NoNet
|
||||||
|
- name: Test Autofill
|
||||||
|
working-directory: ./src/Kp2aAutofillParserTest
|
||||||
|
run: dotnet test
|
||||||
|
|
||||||
|
- name: Build APK (nonet)
|
||||||
|
run: |
|
||||||
|
make apk Flavor=NoNet
|
||||||
|
|
||||||
|
- name: Archive production artifacts (nonet)
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: signed APK ('nonet' built on ${{ github.job }})
|
||||||
|
path: |
|
||||||
|
src/keepass2android/bin/*/*-Signed.apk
|
||||||
|
|
||||||
|
- name: Perform "make distclean"
|
||||||
|
run: make distclean
|
||||||
29
.gitignore
vendored
29
.gitignore
vendored
@@ -7,6 +7,10 @@ PCtest
|
|||||||
bin
|
bin
|
||||||
obj
|
obj
|
||||||
|
|
||||||
|
# Makefile-related files
|
||||||
|
/allow_git_clean
|
||||||
|
/stamp.nuget_*
|
||||||
|
|
||||||
Resource.designer.cs
|
Resource.designer.cs
|
||||||
R.java
|
R.java
|
||||||
|
|
||||||
@@ -105,7 +109,6 @@ Thumbs.db
|
|||||||
/src/java/JavaFileStorageTest/gen/group/pals/android/lib/ui/filechooser/R.java
|
/src/java/JavaFileStorageTest/gen/group/pals/android/lib/ui/filechooser/R.java
|
||||||
/src/java/JavaFileStorageTest/gen/keepass2android/javafilestorage/R.java
|
/src/java/JavaFileStorageTest/gen/keepass2android/javafilestorage/R.java
|
||||||
|
|
||||||
/src/TwofishCipher/Resources/Resource.Designer.cs
|
|
||||||
/src/BindingLibrary1
|
/src/BindingLibrary1
|
||||||
|
|
||||||
/src/PluginTOTP
|
/src/PluginTOTP
|
||||||
@@ -149,3 +152,27 @@ intermediates
|
|||||||
*.iml
|
*.iml
|
||||||
/build
|
/build
|
||||||
/src/Kp2aKeyboardBinding/Jars
|
/src/Kp2aKeyboardBinding/Jars
|
||||||
|
/src/java/Kp2aAccServiceLib/app/build
|
||||||
|
/src/java/Kp2aAccServiceLib/app/app.iml
|
||||||
|
/src/java/Kp2aAccServiceLib/gradle
|
||||||
|
adbprompt.ps1
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/build/android-profile/*.rawproto
|
||||||
|
src/java/KP2ASoftkeyboard_AS/build/generated/mockable-android-23.jar
|
||||||
|
*.rawproto
|
||||||
|
src/java/Keepass2AndroidPluginSDK2/build/generated/mockable-Google-Inc.-Google-APIs-23.jar
|
||||||
|
/src/.vs
|
||||||
|
/src/JavaFileStorageBindings/Jars/JavaFileStorage-release.aar
|
||||||
|
/src/PluginSdkBinding/Jars/app-debug.aar
|
||||||
|
/src/java/KP2AKdbLibrary/libs/arm64-v8a/libfinal-key.so
|
||||||
|
/src/java/KP2AKdbLibrary/libs/x86_64/libfinal-key.so
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/arm64-v8a/libkp2akeyboard_jni.so
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/armeabi-v7a/libkp2akeyboard_jni.so
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/x86/libkp2akeyboard_jni.so
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs/x86_64/libkp2akeyboard_jni.so
|
||||||
|
/src/java/KP2AKdbLibrary/app/build
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/app/.cxx
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/app/src/main/libs
|
||||||
|
/src/java/KP2AKdbLibrary/app/.cxx
|
||||||
|
/src/ActionViewFilterTest
|
||||||
|
/docs/gdrive-verification
|
||||||
|
/src/MegaTest
|
||||||
|
|||||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,6 +1,6 @@
|
|||||||
[submodule "src/SamsungPass"]
|
[submodule "src/SamsungPass"]
|
||||||
path = src/SamsungPass
|
path = src/SamsungPass
|
||||||
url = https://github.com/PhilippC/Xamarin-Samsung-Pass.git
|
url = https://github.com/PhilippC/Xamarin-Samsung-Pass.git
|
||||||
[submodule "src/netftpandroid"]
|
[submodule "src/java/argon2/phc-winner-argon2"]
|
||||||
path = src/netftpandroid
|
path = src/java/argon2/phc-winner-argon2
|
||||||
url = https://git01.codeplex.com/forks/philippc/netftpandroid
|
url = https://github.com/P-H-C/phc-winner-argon2
|
||||||
|
|||||||
361
Makefile
Normal file
361
Makefile
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
#
|
||||||
|
# This Makefile can be used on both unix-like (use make) & windows (with GNU make)
|
||||||
|
#
|
||||||
|
# append the Configuration variable to 'make' call with value to use in '/p:Configuration='
|
||||||
|
# of msbuild command.
|
||||||
|
#
|
||||||
|
# append the Flavor variable to 'make' call with value to use in '/p:Flavor='
|
||||||
|
# of msbuild command.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# make Configuration=Release Flavor=NoNet
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Some targets:
|
||||||
|
# - all: everything (including APK)
|
||||||
|
# - native: build the native libs
|
||||||
|
# - java: build the java libs
|
||||||
|
# - nuget: restore NuGet packages
|
||||||
|
# - msbuild: build the project
|
||||||
|
# - apk: same as all
|
||||||
|
#
|
||||||
|
# - distclean: run a 'git clean -xdff'. Remove everyhing that is not in the git tree.
|
||||||
|
# - clean: all clean_* targets below
|
||||||
|
# - clean_native: clean native lib
|
||||||
|
# - clean_java: call clean target of java libs
|
||||||
|
# - clean_nuget: cleanup the 'nuget restore'
|
||||||
|
# - clean_msbuild: call clean target of msbuild
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
# Disable built-in rules to speed-up the Makefile processing.
|
||||||
|
# for example when running 'make java' on Windows it could take ~10 sec more than on linux to start building
|
||||||
|
# from what this option disables, the "clearing out the default list of suffixes for suffix rules"
|
||||||
|
# gives the most speed gain.
|
||||||
|
MAKEFLAGS += --no-builtin-rules
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT) # is Windows_NT on XP, 2000, 7, Vista, 10...
|
||||||
|
detected_OS := Windows
|
||||||
|
WHICH := where
|
||||||
|
RM := RMDIR /S /Q
|
||||||
|
RMFILE := DEL
|
||||||
|
CP := copy
|
||||||
|
GRADLEW := gradlew.bat
|
||||||
|
# Force use of cmd shell (don't use POSIX shell because the user may not have one installed)
|
||||||
|
SHELL := cmd
|
||||||
|
else
|
||||||
|
detected_OS := $(shell uname)
|
||||||
|
WHICH := which
|
||||||
|
RM := rm -rf
|
||||||
|
RMFILE := $(RM)
|
||||||
|
CP := cp
|
||||||
|
GRADLEW := ./gradlew
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(info MAKESHELL: $(MAKESHELL))
|
||||||
|
$(info SHELL: $(SHELL))
|
||||||
|
$(info )
|
||||||
|
|
||||||
|
# On linux use xabuild, on Windows use MSBuild.exe, otherwise (macos?) use msbuild.
|
||||||
|
ifeq ($(detected_OS),Linux)
|
||||||
|
MSBUILD_binary := xabuild
|
||||||
|
MSBUILD := $(shell $(WHICH) $(MSBUILD_binary))
|
||||||
|
else ifeq ($(detected_OS),Windows)
|
||||||
|
MSBUILD_binary := MSBuild.exe
|
||||||
|
MSBUILD := $(shell $(WHICH) $(MSBUILD_binary) 2> nul)
|
||||||
|
ifeq ($(MSBUILD),)
|
||||||
|
# Additional heuristic to find MSBUILD_BINARY on Windows
|
||||||
|
VSWHERE := "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||||
|
VSWHERE_CHECK := $(shell @echo off & $(VSWHERE) 2> nul || echo VSWHERE_NOT_FOUND)
|
||||||
|
ifneq ($(VSWHERE_CHECK),VSWHERE_NOT_FOUND)
|
||||||
|
MSBUILD := $(shell @echo off & $(VSWHERE) -latest -prerelease -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe)
|
||||||
|
VS_INSTALL_PATH := $(shell @echo off & $(VSWHERE) -property installationPath)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
MSBUILD_binary := msbuild
|
||||||
|
MSBUILD := $(shell $(WHICH) $(MSBUILD_binary))
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(MSBUILD),)
|
||||||
|
$(info )
|
||||||
|
$(info '$(MSBUILD_binary)' binary could not be found. Check it is in your PATH.)
|
||||||
|
ifeq ($(detected_OS),Windows)
|
||||||
|
ifneq ($(VSWHERE_CHECK),VSWHERE_NOT_FOUND)
|
||||||
|
$(info )
|
||||||
|
$(info You may retry after running in the command prompt:)
|
||||||
|
$(info )
|
||||||
|
$(info "$(VS_INSTALL_PATH)\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64)
|
||||||
|
$(info )
|
||||||
|
$(info If this doesn't work, install/find the location of vcvarsall.bat)
|
||||||
|
$(info or install and add msbuild.exe to your PATH)
|
||||||
|
$(info )
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
$(error )
|
||||||
|
endif
|
||||||
|
$(info MSBUILD: $(MSBUILD))
|
||||||
|
$(info )
|
||||||
|
|
||||||
|
ifeq ($(ANDROID_SDK_ROOT),)
|
||||||
|
$(error set ANDROID_SDK_ROOT environment variable)
|
||||||
|
endif
|
||||||
|
$(info ANDROID_SDK_ROOT: $(ANDROID_SDK_ROOT))
|
||||||
|
|
||||||
|
ifeq ($(ANDROID_HOME),)
|
||||||
|
$(error set ANDROID_HOME environment variable)
|
||||||
|
endif
|
||||||
|
$(info ANDROID_HOME: $(ANDROID_SDK_ROOT))
|
||||||
|
|
||||||
|
ifeq ($(ANDROID_NDK_ROOT),)
|
||||||
|
$(error set ANDROID_NDK_ROOT environment variable)
|
||||||
|
endif
|
||||||
|
$(info ANDROID_NDK_ROOT: $(ANDROID_NDK_ROOT))
|
||||||
|
|
||||||
|
ifneq ($(Configuration),)
|
||||||
|
MSBUILD_PARAM = -p:Configuration="$(Configuration)"
|
||||||
|
else
|
||||||
|
$(warning Configuration environment variable not set.)
|
||||||
|
endif
|
||||||
|
ifneq ($(Flavor),)
|
||||||
|
MSBUILD_PARAM += -p:Flavor="$(Flavor)"
|
||||||
|
else
|
||||||
|
$(warning Flavor environment variable not set.)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(KeyStore),)
|
||||||
|
MSBUILD_PARAM += -p:AndroidKeyStore=True -p:AndroidSigningKeyStore="$(KeyStore)" -p:AndroidSigningStorePass=env:MyAndroidSigningStorePass -p:AndroidSigningKeyPass=env:MyAndroidSigningKeyPass
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(detected_OS),Windows)
|
||||||
|
to_win_path=$(subst /,\,$(1))
|
||||||
|
to_posix_path=$(subst \,/,$(1))
|
||||||
|
define remove_dir
|
||||||
|
if exist $(1) ( $(RM) $(1) )
|
||||||
|
endef
|
||||||
|
define remove_files
|
||||||
|
$(foreach file,$(call to_win_path,$(1)), IF EXIST $(file) ( $(RMFILE) $(file) ) & )
|
||||||
|
endef
|
||||||
|
else
|
||||||
|
define remove_dir
|
||||||
|
$(RM) $(1)
|
||||||
|
endef
|
||||||
|
define remove_files
|
||||||
|
$(RMFILE) $(1)
|
||||||
|
endef
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Recursive wildcard: https://stackoverflow.com/a/18258352
|
||||||
|
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
|
||||||
|
|
||||||
|
$(info MSBUILD_PARAM: $(MSBUILD_PARAM))
|
||||||
|
$(info nuget path: $(shell $(WHICH) nuget))
|
||||||
|
$(info )
|
||||||
|
|
||||||
|
NATIVE_COMPONENTS := argon2
|
||||||
|
NATIVE_CLEAN_TARGETS := clean_argon2
|
||||||
|
|
||||||
|
OUTPUT_argon2 = src/java/argon2/libs/armeabi-v7a/libargon2.so \
|
||||||
|
src/java/argon2/libs/arm64-v8a/libargon2.so \
|
||||||
|
src/java/argon2/libs/x86/libargon2.so \
|
||||||
|
src/java/argon2/libs/x86_64/libargon2.so
|
||||||
|
|
||||||
|
JAVA_COMPONENTS := \
|
||||||
|
JavaFileStorageTest-AS \
|
||||||
|
KP2ASoftkeyboard_AS \
|
||||||
|
Keepass2AndroidPluginSDK2 \
|
||||||
|
KP2AKdbLibrary
|
||||||
|
#PluginQR # Doesn't seem required
|
||||||
|
JAVA_CLEAN_TARGETS := \
|
||||||
|
clean_JavaFileStorageTest-AS \
|
||||||
|
clean_KP2ASoftkeyboard_AS \
|
||||||
|
clean_Keepass2AndroidPluginSDK2 \
|
||||||
|
clean_KP2AKdbLibrary \
|
||||||
|
clean_PluginQR
|
||||||
|
|
||||||
|
INPUT_android-filechooser-AS := $(filter-out $(filter %/app,$(wildcard src/java/android-filechooser-AS/*)),$(wildcard src/java/android-filechooser-AS/*)) \
|
||||||
|
$(filter-out $(filter %/build,$(wildcard src/java/android-filechooser-AS/app/*)),$(wildcard src/java/android-filechooser-AS/app/*)) \
|
||||||
|
$(call rwildcard,src/java/android-filechooser-AS/app/src,*)
|
||||||
|
|
||||||
|
INPUT_JavaFileStorage := $(filter-out $(filter %/app,$(wildcard src/java/JavaFileStorage/*)),$(wildcard src/java/JavaFileStorage/*)) \
|
||||||
|
$(filter-out $(filter %/build,$(wildcard src/java/JavaFileStorage/app/*)),$(wildcard src/java/JavaFileStorage/app/*)) \
|
||||||
|
$(wildcard src/java/JavaFileStorage/libs/*) \
|
||||||
|
$(call rwildcard,src/java/JavaFileStorage/app/src,*) \
|
||||||
|
|
||||||
|
INPUT_JavaFileStorageTest-AS := $(filter-out $(filter %/app,$(wildcard src/java/JavaFileStorageTest-AS/*)),$(wildcard src/java/JavaFileStorageTest-AS/*)) \
|
||||||
|
$(filter-out $(filter %/build,$(wildcard src/java/JavaFileStorageTest-AS/app/*)),$(wildcard src/java/JavaFileStorageTest-AS/app/*)) \
|
||||||
|
$(call rwildcard,src/java/JavaFileStorageTest-AS/app/src,*) \
|
||||||
|
$(INPUT_android-filechooser-AS) \
|
||||||
|
$(INPUT_JavaFileStorage)
|
||||||
|
OUTPUT_JavaFileStorageTest-AS = src/java/android-filechooser-AS/app/build/outputs/aar/android-filechooser-debug.aar \
|
||||||
|
src/java/android-filechooser-AS/app/build/outputs/aar/android-filechooser-release.aar \
|
||||||
|
src/java/JavaFileStorage/app/build/outputs/aar/JavaFileStorage-debug.aar \
|
||||||
|
src/java/JavaFileStorage/app/build/outputs/aar/JavaFileStorage-release.aar \
|
||||||
|
src/java/JavaFileStorageTest-AS/app/build/outputs/apk/debug/app-debug.apk \
|
||||||
|
src/java/JavaFileStorageTest-AS/app/build/outputs/apk/release/app-release-unsigned.apk
|
||||||
|
|
||||||
|
INPUT_KP2ASoftkeyboard_AS := $(wildcard src/java/KP2ASoftkeyboard_AS/*) \
|
||||||
|
$(wildcard src/java/KP2ASoftkeyboard_AS/app/*) \
|
||||||
|
$(call rwildcard,src/java/KP2ASoftkeyboard_AS/app/src,*)
|
||||||
|
OUTPUT_KP2ASoftkeyboard_AS = src/java/KP2ASoftkeyboard_AS/app/build/outputs/aar/app-debug.aar \
|
||||||
|
src/java/KP2ASoftkeyboard_AS/app/build/outputs/aar/app-release.aar
|
||||||
|
|
||||||
|
INPUT_Keepass2AndroidPluginSDK2 := $(wildcard src/java/Keepass2AndroidPluginSDK2/*) \
|
||||||
|
$(wildcard src/java/Keepass2AndroidPluginSDK2/app/*) \
|
||||||
|
$(call rwildcard,src/java/Keepass2AndroidPluginSDK2/app/src,*)
|
||||||
|
OUTPUT_Keepass2AndroidPluginSDK2 = src/java/Keepass2AndroidPluginSDK2/app/build/outputs/aar/app-debug.aar \
|
||||||
|
src/java/Keepass2AndroidPluginSDK2/app/build/outputs/aar/app-release.aar
|
||||||
|
|
||||||
|
INPUT_KP2AKdbLibrary := $(wildcard src/java/KP2AKdbLibrary/*) \
|
||||||
|
$(wildcard src/java/KP2AKdbLibrary/app/*) \
|
||||||
|
$(call rwildcard,src/java/KP2AKdbLibrary/app/src,*)
|
||||||
|
OUTPUT_KP2AKdbLibrary = src/java/KP2AKdbLibrary/app/build/outputs/aar/app-debug.aar \
|
||||||
|
src/java/KP2AKdbLibrary/app/build/outputs/aar/app-release.aar
|
||||||
|
|
||||||
|
INPUT_PluginQR := $(wildcard src/java/PluginQR/*) \
|
||||||
|
$(wildcard src/java/PluginQR/app/*) \
|
||||||
|
$(call rwildcard,src/java/PluginQR/app/src,*) \
|
||||||
|
$(INPUT_Keepass2AndroidPluginSDK2)
|
||||||
|
OUTPUT_PluginQR = src/java/Keepass2AndroidPluginSDK2/app/build/outputs/aar/Keepass2AndroidPluginSDK2-debug.aar \
|
||||||
|
src/java/Keepass2AndroidPluginSDK2/app/build/outputs/aar/Keepass2AndroidPluginSDK2-release.aar \
|
||||||
|
src/java/PluginQR/app/build/outputs/apk/debug/app-debug.apk \
|
||||||
|
src/java/PluginQR/app/build/outputs/apk/debug/app-release-unsigned.apk
|
||||||
|
|
||||||
|
##### Targets definition
|
||||||
|
|
||||||
|
.PHONY: native $(NATIVE_COMPONENTS) clean_native $(NATIVE_CLEAN_TARGETS) \
|
||||||
|
java $(JAVA_COMPONENTS) clean_java $(JAVA_CLEAN_TARGETS) \
|
||||||
|
nuget clean_nuget \
|
||||||
|
msbuild clean_msbuild \
|
||||||
|
apk all clean
|
||||||
|
|
||||||
|
all: apk
|
||||||
|
|
||||||
|
##### Native Dependencies
|
||||||
|
|
||||||
|
native: $(NATIVE_COMPONENTS)
|
||||||
|
|
||||||
|
argon2: $(OUTPUT_argon2)
|
||||||
|
$(OUTPUT_argon2): $(wildcard src/java/argon2/phc-winner-argon2/src/*) $(wildcard src/java/argon2/phc-winner-argon2/src/blake2/*)
|
||||||
|
cd src/java/argon2 && $(ANDROID_NDK_ROOT)/ndk-build
|
||||||
|
|
||||||
|
##### Java Dependencies
|
||||||
|
|
||||||
|
java: $(JAVA_COMPONENTS)
|
||||||
|
|
||||||
|
JavaFileStorageTest-AS: $(OUTPUT_JavaFileStorageTest-AS)
|
||||||
|
KP2ASoftkeyboard_AS: $(OUTPUT_KP2ASoftkeyboard_AS)
|
||||||
|
Keepass2AndroidPluginSDK2: $(OUTPUT_Keepass2AndroidPluginSDK2)
|
||||||
|
KP2AKdbLibrary: $(OUTPUT_KP2AKdbLibrary)
|
||||||
|
PluginQR: $(OUTPUT_PluginQR)
|
||||||
|
|
||||||
|
$(OUTPUT_JavaFileStorageTest-AS): $(INPUT_JavaFileStorageTest-AS)
|
||||||
|
$(call remove_files,$(OUTPUT_JavaFileStorageTest-AS))
|
||||||
|
cd src/java/JavaFileStorageTest-AS && $(GRADLEW) assemble
|
||||||
|
$(OUTPUT_KP2ASoftkeyboard_AS): $(INPUT_KP2ASoftkeyboard_AS)
|
||||||
|
$(call remove_files,$(OUTPUT_KP2ASoftkeyboard_AS))
|
||||||
|
cd src/java/KP2ASoftkeyboard_AS && $(GRADLEW) assemble
|
||||||
|
$(OUTPUT_Keepass2AndroidPluginSDK2): $(INPUT_Keepass2AndroidPluginSDK2)
|
||||||
|
$(call remove_files,$(OUTPUT_Keepass2AndroidPluginSDK2))
|
||||||
|
cd src/java/Keepass2AndroidPluginSDK2 && $(GRADLEW) assemble
|
||||||
|
$(OUTPUT_KP2AKdbLibrary): $(INPUT_KP2AKdbLibrary)
|
||||||
|
$(call remove_files,$(OUTPUT_KP2AKdbLibrary))
|
||||||
|
cd src/java/KP2AKdbLibrary && $(GRADLEW) assemble
|
||||||
|
$(OUTPUT_PluginQR): $(INPUT_PluginQR)
|
||||||
|
$(call remove_files,$(OUTPUT_PluginQR))
|
||||||
|
cd src/java/PluginQR && $(GRADLEW) assemble
|
||||||
|
|
||||||
|
|
||||||
|
##### Nuget Dependencies
|
||||||
|
|
||||||
|
nuget: stamp.nuget_$(Flavor)
|
||||||
|
stamp.nuget_$(Flavor): src/KeePass.sln $(wildcard src/*/*.csproj) $(wildcard src/*/packages.config)
|
||||||
|
ifeq ($(shell $(WHICH) nuget),)
|
||||||
|
$(error "nuget" command not found. Check it is in your PATH)
|
||||||
|
endif
|
||||||
|
$(RMFILE) stamp.nuget_*
|
||||||
|
nuget restore src/KeePass.sln
|
||||||
|
$(MSBUILD) src/KeePass.sln -t:restore $(MSBUILD_PARAM) -p:RestorePackagesConfig=true
|
||||||
|
@echo "" > stamp.nuget_$(Flavor)
|
||||||
|
|
||||||
|
#####
|
||||||
|
src/Kp2aBusinessLogic/Io/DropboxFileStorageKeys.cs:
|
||||||
|
ifeq ($(detected_OS),Windows)
|
||||||
|
$(CP) src\Kp2aBusinessLogic\Io\DropboxFileStorageKeysDummy.cs src\Kp2aBusinessLogic\Io\DropboxFileStorageKeys.cs
|
||||||
|
else
|
||||||
|
$(CP) src/Kp2aBusinessLogic/Io/DropboxFileStorageKeysDummy.cs $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
msbuild: native java nuget src/Kp2aBusinessLogic/Io/DropboxFileStorageKeys.cs
|
||||||
|
$(MSBUILD) src/KeePass.sln -target:keepass2android-app -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -p:BuildProjectReferences=true $(MSBUILD_PARAM) -p:Platform="Any CPU" -m
|
||||||
|
|
||||||
|
apk: msbuild
|
||||||
|
$(MSBUILD) src/keepass2android/keepass2android-app.csproj -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -t:SignAndroidPackage $(MSBUILD_PARAM) -p:Platform=AnyCPU -m
|
||||||
|
|
||||||
|
build_all: msbuild
|
||||||
|
|
||||||
|
##### Cleanup targets
|
||||||
|
|
||||||
|
clean_native: $(NATIVE_CLEAN_TARGETS)
|
||||||
|
clean_argon2:
|
||||||
|
cd src/java/argon2 && $(ANDROID_NDK_ROOT)/ndk-build clean
|
||||||
|
|
||||||
|
clean_java: $(JAVA_CLEAN_TARGETS)
|
||||||
|
clean_JavaFileStorageTest-AS:
|
||||||
|
cd src/java/JavaFileStorageTest-AS && $(GRADLEW) clean
|
||||||
|
clean_KP2ASoftkeyboard_AS:
|
||||||
|
cd src/java/KP2ASoftkeyboard_AS && $(GRADLEW) clean
|
||||||
|
clean_Keepass2AndroidPluginSDK2:
|
||||||
|
cd src/java/Keepass2AndroidPluginSDK2 && $(GRADLEW) clean
|
||||||
|
clean_KP2AKdbLibrary:
|
||||||
|
cd src/java/KP2AKdbLibrary && $(GRADLEW) clean
|
||||||
|
clean_PluginQR:
|
||||||
|
cd src/java/PluginQR && $(GRADLEW) clean
|
||||||
|
clean_rm:
|
||||||
|
rm -rf src/*/obj
|
||||||
|
rm -rf src/*/bin
|
||||||
|
rm -rf src/java/*/app/build
|
||||||
|
rm -rf src/java/argon2/obj
|
||||||
|
rm -rf src/java/argon2/libs
|
||||||
|
rm -rf src/packages
|
||||||
|
rm -rf src/java/KP2AKdbLibrary/app/.cxx
|
||||||
|
rm -rf src/java/KP2ASoftkeyboard_AS/app/.cxx
|
||||||
|
rm -rf src/SamsungPass/Xamarin.SamsungPass/SamsungPass/bin
|
||||||
|
rm -rf src/SamsungPass/Xamarin.SamsungPass/SamsungPass/obj
|
||||||
|
|
||||||
|
|
||||||
|
# https://learn.microsoft.com/en-us/nuget/consume-packages/package-restore-troubleshooting#other-potential-conditions
|
||||||
|
clean_nuget:
|
||||||
|
cd src && $(call remove_dir,packages)
|
||||||
|
ifeq ($(detected_OS),Windows)
|
||||||
|
DEL /S src\project.assets.json
|
||||||
|
DEL /S src\*.nuget.*
|
||||||
|
else
|
||||||
|
$(RM) src/*/obj/project.assets.json
|
||||||
|
$(RM) src/*/obj/*.nuget.*
|
||||||
|
endif
|
||||||
|
$(RMFILE) stamp.nuget_*
|
||||||
|
|
||||||
|
clean_msbuild:
|
||||||
|
$(MSBUILD) src/KeePass.sln -target:clean $(MSBUILD_PARAM)
|
||||||
|
|
||||||
|
clean: clean_native clean_java clean_nuget clean_msbuild
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
ifneq ("$(wildcard ./allow_git_clean)","")
|
||||||
|
ifeq ($(shell $(WHICH) git),)
|
||||||
|
$(error "git" command not found. Check it is in your PATH)
|
||||||
|
endif
|
||||||
|
git clean -xdff src
|
||||||
|
else
|
||||||
|
$(warning 'git clean' skipped for safety reasons. See hint below:)
|
||||||
|
$(info )
|
||||||
|
$(info 'git clean' would delete all untracked files, those in '.gitignore' and those in '.git/info/exclude'.)
|
||||||
|
$(info )
|
||||||
|
$(info Check which files would be deleted by running: "git clean -n -xdff src")
|
||||||
|
$(info If listed files are acceptable, you can enable the call to "git clean" by creating an empty file named 'allow_git_clean' next to the Makefile.)
|
||||||
|
$(info )
|
||||||
|
endif
|
||||||
34
crowdin.yml
Normal file
34
crowdin.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
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
|
||||||
|
pt-PT: pt
|
||||||
|
pt-BR: pt-rBR
|
||||||
|
- source: src/java/android-filechooser-AS/app/src/main/res/values/strings.xml
|
||||||
|
translation: >-
|
||||||
|
/src/java/android-filechooser-AS/app/src/main/res/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
|
||||||
|
pt-PT: pt
|
||||||
|
pt-BR: pt-rBR
|
||||||
|
- source: src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/strings.xml
|
||||||
|
translation: >-
|
||||||
|
/src/java/KP2ASoftkeyboard_AS/app/src/main/res/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
|
||||||
|
pt-PT: pt
|
||||||
|
pt-BR: pt-rBR
|
||||||
5
docs/AccServiceAutoFill.md
Normal file
5
docs/AccServiceAutoFill.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
As of December 2017, Google does not accept the use of Accessibility services for anything except helping people with disabilities. This means that Keepass2Android can no longer provide the accessibility service based AutoFill feature. Otherwise, Google would remove Keepass2Android from Play Store.
|
||||||
|
|
||||||
|
If you want to continue using this feature, please [install the Accessibility service based AutoFill plugin](https://github.com/PhilippC/kp2a_accservice_autofill/releases/).
|
||||||
|
|
||||||
|
After installation, please enable the accessibility service "KP2A AutoFillPlugin" in the Android system settings. When trying to use the plugin for the first time, KP2A will ask you if the plugin may access the Keepass database. Please accept this to use the plugin.
|
||||||
@@ -2,6 +2,14 @@
|
|||||||
Displays password entries as QR code; can be used to scan QR codes which can then be added to Keepass2Android.
|
Displays password entries as QR code; can be used to scan QR codes which can then be added to Keepass2Android.
|
||||||
[https://play.google.com/store/apps/details?id=keepass2android.plugin.qr](https://play.google.com/store/apps/details?id=keepass2android.plugin.qr)
|
[https://play.google.com/store/apps/details?id=keepass2android.plugin.qr](https://play.google.com/store/apps/details?id=keepass2android.plugin.qr)
|
||||||
|
|
||||||
|
# KeyboardSwap Plug-in
|
||||||
|
Allows to switch input method automatically on non-rooted devices.
|
||||||
|
[https://play.google.com/store/apps/details?id=keepass2android.plugin.keyboardswap2](https://play.google.com/store/apps/details?id=keepass2android.plugin.keyboardswap2)
|
||||||
|
|
||||||
|
# AutoFill Plug-in
|
||||||
|
Uses Android Accessibility Service to provide an option to AutoFill forms (e.g. on Chrome) or any Android app.
|
||||||
|
[https://philippc.github.io/keepass2android/AccServiceAutoFill.html](https://philippc.github.io/keepass2android/AccServiceAutoFill.html)
|
||||||
|
|
||||||
# InputStick Plug-in
|
# InputStick Plug-in
|
||||||
Allows to send text from KP2A via InputStick to your PC.
|
Allows to send text from KP2A via InputStick to your PC.
|
||||||
[https://play.google.com/store/apps/details?id=com.inputstick.apps.kp2aplugin](https://play.google.com/store/apps/details?id=com.inputstick.apps.kp2aplugin)
|
[https://play.google.com/store/apps/details?id=com.inputstick.apps.kp2aplugin](https://play.google.com/store/apps/details?id=com.inputstick.apps.kp2aplugin)
|
||||||
|
|||||||
239
docs/Build.readme.md
Normal file
239
docs/Build.readme.md
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
# How to build Keepass2Android
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Keepass2Android is a Mono for Android app. This means that you need Xamarin's Mono for Android to build it. However, it also uses several components written in Java, so there are also Android-Studio projects involved. To make things even worse, parts of the keyboard and kdb-library are written in native code.
|
||||||
|
|
||||||
|
To build KP2A from scratch, you need:
|
||||||
|
- Xamarin's Mono for Android (also included in Visual Studio)
|
||||||
|
- Android SDK & NDK
|
||||||
|
|
||||||
|
Prior to building Keepass2Android, you need to build some of its components (from command line). Then you can build the full project either through Visual Studio, or through command line.
|
||||||
|
|
||||||
|
By using the command line, you can build on Windows, macOS or Linux.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### Common to all architectures
|
||||||
|
- Install Android SDK & NDK (either manually with Google's [sdkmanager](https://developer.android.com/studio/command-line/sdkmanager), or through Android Studio). Visual Studio also installs a version of it, but in the end the directory must be writable and in a path without spaces (see below) so as to be able to build the components.
|
||||||
|
- Fetch the main repository of Keepass2Android and all submodules
|
||||||
|
- Note that VisualStudio can do this for you, otherwise run:
|
||||||
|
- `git submodule init && git submodule update`
|
||||||
|
|
||||||
|
### On Windows or macOS
|
||||||
|
- Install Visual Studio (for example 2019) with Xamarin.Android (ie. with capability to build Android apps). This should provide the needed tools like
|
||||||
|
- Xamarin.Android
|
||||||
|
- MSBuild
|
||||||
|
- Java JDK
|
||||||
|
- If you plan to build also from the command line:
|
||||||
|
- Install the MSVC build tools of visual studio. They provide the `vcvarsall.bat` file which among other things adds MSBuild to the PATH.
|
||||||
|
- Install [NuGet](https://www.nuget.org/downloads) to build also with "make". Alternatively, on Windows, if you use [chocolatey](https://chocolatey.org), run as administrator:
|
||||||
|
- `choco install nuget.commandline`
|
||||||
|
- Check that you have access to 'GNU make'.
|
||||||
|
- On Windows, it is usually not available by default. But the Android NDK provides it. You can find it in `%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make.exe`. Alternatively, on Windows, if you use [chocolatey](https://chocolatey.org), run as administrator:
|
||||||
|
- `choco install make`
|
||||||
|
- On macOS, it is usually only installed if you have developer command line tools installed or if you use [homebrew](https://brew.sh) or [macports](https://www.macports.org/). As an alternative it may be available in the Android NDK at `%ANDROID_NDK_ROOT%/prebuilt/darwin-x86_64/bin/make`.
|
||||||
|
|
||||||
|
### On Linux
|
||||||
|
- Install Java's JDK
|
||||||
|
- On Debian, for example: `apt install default-jdk-headless`.
|
||||||
|
|
||||||
|
- Install [Mono](https://www.mono-project.com/)
|
||||||
|
- This should provide `msbuild` & `xabuild` binary
|
||||||
|
- On Debian, after having added the repo from above, install with `apt install -t <repo_name> mono-devel msbuild`. A value for `<repo_name>` could be `stable-buster` for example, depending on which one you chose. You could also install the `mono-complete` package if you prefer.
|
||||||
|
|
||||||
|
- Install Xamarin.Android
|
||||||
|
- ~~Option 1: Use the mono-project [CI builds](https://dev.azure.com/xamarin/public/_build/latest?definitionId=48&branchName=main&stageName=Linux)~~ **NOTE:** KP2A now requires Xamarin.Android v13, which is newer than the current CI build; until a more recent CI build is available, this option is unfortunately no longer viable.
|
||||||
|
- Option 2: [Build it from source](https://github.com/xamarin/xamarin-android/blob/master/Documentation/README.md#building-from-source)
|
||||||
|
|
||||||
|
- Install NuGet package of your distribution
|
||||||
|
- On Debian/Ubuntu: `apt install nuget`
|
||||||
|
|
||||||
|
- Install [libzip](https://libzip.org/) for your distribution for some Xamarin.Android versions
|
||||||
|
- This may not be relevant anymore: for example, with Xamarin.Android 11.4.99. this is not needed.
|
||||||
|
- Some versions of Xamarin may require `libzip4`. If you are in this case:
|
||||||
|
- On Debian/Ubuntu, install it with `apt install libzip4`.
|
||||||
|
- Other distributions ship only `libzip5`. As a dirty workaround, it's possible to symlink `libzip.so.5` to `libzip.so.4`. Luckily, it appears to be working. For example:
|
||||||
|
- `sudo ln -s /usr/lib/libzip.so.5 /usr/lib/libzip.so.4`
|
||||||
|
- or `sudo ln -s /usr/lib64/libzip.so.5 /usr/lib/libzip.so.4`
|
||||||
|
|
||||||
|
## Building the required components:
|
||||||
|
|
||||||
|
This is done on the command line and requires the Android SDK & NDK and Java JDK.
|
||||||
|
|
||||||
|
### On Windows
|
||||||
|
- Setup your environment:
|
||||||
|
- Set these environment variables for Android's SDK & NDK
|
||||||
|
- `ANDROID_HOME` (for example `set ANDROID_HOME=C:\PATH\TO\android-sdk`)
|
||||||
|
- `ANDROID_SDK_ROOT` (for example `set ANDROID_SDK_ROOT=C:\PATH\TO\android-sdk`)
|
||||||
|
- `ANDROID_NDK_ROOT` (for example `set ANDROID_NDK_ROOT=C:\PATH\TO\android-sdk\ndk\version`)
|
||||||
|
|
||||||
|
**Note:** Care must be taken when setting the above variables to **not** include a trailing backslash in the path. A trailing backslash may cause `make` to fail.
|
||||||
|
|
||||||
|
**Note**: If the path to the Android SDK contains spaces, you **must** do one of these:
|
||||||
|
- either put the Android SDK into a path without spaces.
|
||||||
|
- or create a symlink to that path which doesn't contain spaces. Attention: this requires **administrator** priveleges. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
IF NOT EXIST C:\Android ( MKDIR C:\Android ) &&
|
||||||
|
MKLINK /D C:\Android\android-sdk "C:\Program Files (x86)\Android\android-sdk"
|
||||||
|
```
|
||||||
|
This is because [Android NDK doesn't support being installed in a path with spaces](https://github.com/android/ndk/issues/1400).
|
||||||
|
|
||||||
|
**Note**: The Android SDK path will require to be writeable because during the build, some missing components might be downloaded & installed.
|
||||||
|
|
||||||
|
- If you have "GNU make" available on your windows system, you may build by using the Makefile. You can also find a `make` executable in `%ANDROID_NDK_ROOT%\prebuilt\windows-x86_64\bin\make.exe`. To use it, see the instructions for Linux/macOS. Basically, just run `make` or `mingw32-make` depending on which distribution of GNU make for windows you have installed.
|
||||||
|
|
||||||
|
- Otherwise proceed as below:
|
||||||
|
|
||||||
|
1. Build argon2
|
||||||
|
|
||||||
|
```
|
||||||
|
cd src/java/argon2
|
||||||
|
%ANDROID_NDK_ROOT%/ndk-build.cmd
|
||||||
|
```
|
||||||
|
1. Build the other java components
|
||||||
|
|
||||||
|
```
|
||||||
|
cd src/build-scripts
|
||||||
|
build-java.bat
|
||||||
|
```
|
||||||
|
|
||||||
|
`build-java.bat` will call `gradlew` for several Java modules.
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
|
||||||
|
- For building the java parts, it is suggested to keep a short name (e.g. "c:\projects\keepass2android") for the root project directory. Otherwise the Windows path length limit might be hit when building.
|
||||||
|
- Before building the java parts, make sure you have set the ANDROID_HOME variable or create a local.properties file inside the directories with a gradlew file. It is recommended to use the same SDK location as that of the Xamarin build.
|
||||||
|
- On some environments, `make` can fail to properly use the detected `MSBUILD` tools. This seems to be due to long pathnames and/or spaces in pathnames. It may be required to explicitly set the `MSBUILD` path using 8.3 "short" path notation:
|
||||||
|
- Determine the location of `MSBUILD` (e.g. `C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe`)
|
||||||
|
- [Generate the "short" path](https://superuser.com/a/728792) of that location (e.g.: `C:\PROGRA~1\MICROS~2\2022\COMMUN~1\MSBuild\Current\Bin\MSBuild.exe`)
|
||||||
|
- When running `make` specify the location of ``MSBUILD` explicitly (e.g.: `make MSBUILD="C:\PROGRA~1\MICROS~2\2022\COMMUN~1\MSBuild\Current\Bin\MSBuild.exe`
|
||||||
|
|
||||||
|
|
||||||
|
### On Linux/macOS
|
||||||
|
|
||||||
|
- Setup your environment:
|
||||||
|
- Set these environment variables for Android's SDK & NDK
|
||||||
|
- `ANDROID_HOME` (for example `export ANDROID_HOME=/path/to/android-sdk/`)
|
||||||
|
- `ANDROID_SDK_ROOT` (for example `export ANDROID_SDK_ROOT=/path/to/android-sdk/`)
|
||||||
|
- `ANDROID_NDK_ROOT` (for example `export ANDROID_NDK_ROOT=/path/to/android-sdk/ndk/version`)
|
||||||
|
|
||||||
|
- Update your PATH environment variable so that it can access `nuget`, `msbuild` or `xabuild` (for linux):
|
||||||
|
- On Linux:
|
||||||
|
- add `xabuild` to your path: `export PATH=/path/to/xamarin.android-oss/bin/Release/bin/:$PATH`
|
||||||
|
- On macOS:
|
||||||
|
- you may similarly need to add `msbuild` & `nuget` to your PATH.
|
||||||
|
|
||||||
|
- Start the build:
|
||||||
|
- This will use the Makefile at the root of the project (requires GNU make). To build everything (components & Keepass2Android APK) in a single command simply run:
|
||||||
|
|
||||||
|
```
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
- Otherwise, if you prefer to do step by step
|
||||||
|
|
||||||
|
1. Build argon2
|
||||||
|
|
||||||
|
```
|
||||||
|
make native
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Build the other java components
|
||||||
|
|
||||||
|
```
|
||||||
|
make java
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building Keepass2Android:
|
||||||
|
|
||||||
|
These are the basic steps to build Keepass2Android. You can also build Keepass2Android Offline. For this, configure the build by using the [Flavors](#Flavors).
|
||||||
|
|
||||||
|
### With Visual Studio
|
||||||
|
|
||||||
|
- On windows or on macOS open the src/KeePass.sln file with visual studio, and choose to build the project named 'keepass2android-app'
|
||||||
|
|
||||||
|
### Command Line
|
||||||
|
|
||||||
|
#### Windows, Macos & Linux
|
||||||
|
to build the APK, simply run:
|
||||||
|
|
||||||
|
```
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
or to skip building the APK:
|
||||||
|
|
||||||
|
```
|
||||||
|
make msbuild
|
||||||
|
```
|
||||||
|
|
||||||
|
## Where is the APK ?
|
||||||
|
The Apk can be installed on a device.
|
||||||
|
It is located in `src/keepass2android/bin/*/*-Signed.apk`
|
||||||
|
|
||||||
|
If you build with Visual Studio, the APK is not produced automatically. You need to perform some extra step. See the documentation of Visual Studio on how to proceed.
|
||||||
|
|
||||||
|
## Flavors
|
||||||
|
|
||||||
|
Keepass2Android is distributed in two flavors.
|
||||||
|
- Keepass2Android (aka `net`)
|
||||||
|
- Keepass2Android Offline (aka `nonet`)
|
||||||
|
|
||||||
|
The flavor is set through a MSBuild Property named "`Flavor`". The possible values are '`Net`' and '`NoNet`'.
|
||||||
|
|
||||||
|
The value of the Flavor property is used in 2 projects:
|
||||||
|
- `keepass2android-app` (in `src/keepass2android`)
|
||||||
|
- `Kp2aBusinessLogic` (in `src/keepass2android`)
|
||||||
|
|
||||||
|
Its value is set inside the `*.csproj` file (XML format) of each project in the `Project`/`PropertyGroup`/`Flavor` node.
|
||||||
|
By default its value is set to an empty string so that development is made with `AndroidManifest_debug.xml` on the '`net`' flavor.
|
||||||
|
|
||||||
|
This is the behaviour of the build system depending on the value of Flavor:
|
||||||
|
| Flavor | What is built | `AndroidManifest.xml` used |
|
||||||
|
| ----- | ----- | ----- |
|
||||||
|
| `` (empty string): This is the default value. | Keepass2Android | `AndroidManifest_debug.xml` |
|
||||||
|
| `Net` | Keepass2Android | `AndroidManifest_net.xml` |
|
||||||
|
| `NoNet` | Keepass2Android Offline | `AndroidManifest_nonet.xml` |
|
||||||
|
|
||||||
|
### Select/Change flavor:
|
||||||
|
|
||||||
|
When building, by default, the flavor is not set. So the value used is the value of the Flavor property in *.csproj file. This should result on doing a build of the 'net' flavor.
|
||||||
|
|
||||||
|
You can force the Flavor by setting the Flavor property.
|
||||||
|
|
||||||
|
Proceed this way:
|
||||||
|
|
||||||
|
#### Command line
|
||||||
|
|
||||||
|
##### Windows, Macos & Linux
|
||||||
|
|
||||||
|
To force building 'net' with `make`, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
make Flavor=Net
|
||||||
|
```
|
||||||
|
|
||||||
|
To build 'nonet' with `make`, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
make Flavor=NoNet
|
||||||
|
```
|
||||||
|
|
||||||
|
##### MSBuild
|
||||||
|
|
||||||
|
To build with MSBuild directly on the command line, set the flavor with `-p:Flavor=value` argument. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
MSBuild src/KeePass.sln ... -p:Flavor=NoNet
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Visual Studio
|
||||||
|
When building with Visual Studio, edit the `*.csproj` file (XML format) and set the value in the `Project`/`PropertyGroup`/`Flavor` node. This is needed only for the projects that use the flavors.
|
||||||
|
|
||||||
|
**Note:** When switching between flavors, be sure to clean the previous build before.
|
||||||
|
|
||||||
|
## Makefile
|
||||||
|
|
||||||
|
It is possible to override the project's default 'Flavor' (Net, NoNet) and 'Configuration' (Release, Debug) by passing it as argument to `make`. See the header of the Makefile to see what can be done.
|
||||||
@@ -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:
|
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.
|
* 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
|
* 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
|
* having the database file
|
||||||
** knowing the master password (and additional second factor if you chose one)
|
* 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:
|
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).
|
||||||
** What happens if I have an accident? Should any trusted person be able to access my database?
|
* You might also want to think about:
|
||||||
** What happens if my phone gets lost or stolen? Do I know how to recover my database from a backup or the cloud?
|
* 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
|
# Getting started
|
||||||
@@ -27,14 +28,14 @@ Select "Create new database" from the start screen. Tap the integrated help icon
|
|||||||
## Getting passwords into password fields
|
## Getting passwords into password fields
|
||||||
There are many ways how to enter the passwords from your database in the corresponding fields. By default, the clipboard as well as the KP2A keyboard are activated in the settings:
|
There are many ways how to enter the passwords from your database in the corresponding fields. By default, the clipboard as well as the KP2A keyboard are activated in the settings:
|
||||||
* The KP2A keyboard is the recommended way because it's safe against clipboard loggers: Whenever you select an entry, the KP2A keyboard notification will appear in the notification bar. Click it to activate the keyboard. (The first time you do this, you are required to enable the keyboard in the system settings. This must be done by the user for Android security reasons.) As soon as it's activated, you can tap a field where you want to enter data from the selected entry. The KP2A keyboard will come up. Click the KP2A key (on the bottom left) to select whether you want to enter Username/password etc. When you're done, click the Keyboard key (next to the KP2A key) to switch back to your favorite keyboard.
|
* The KP2A keyboard is the recommended way because it's safe against clipboard loggers: Whenever you select an entry, the KP2A keyboard notification will appear in the notification bar. Click it to activate the keyboard. (The first time you do this, you are required to enable the keyboard in the system settings. This must be done by the user for Android security reasons.) As soon as it's activated, you can tap a field where you want to enter data from the selected entry. The KP2A keyboard will come up. Click the KP2A key (on the bottom left) to select whether you want to enter Username/password etc. When you're done, click the Keyboard key (next to the KP2A key) to switch back to your favorite keyboard.
|
||||||
* You can enable the Keepass2Android Autofill service in the system's accessibility settings which allows to fill data using Android's accessibility system. This works with many apps including Chrome browser but is not supported for Firefox on Android.
|
* You can enable the Keepass2Android Autofill service in the system's Autofill settings (Android 8+) which allows to fill data using Android's accessibility system. This works with many apps including Firefox browser but is not supported for Chrome (when writing this).
|
||||||
* The clipboard based approach can be used as well: Pull the notification bar down and select "Copy username/password to clipboard". Then long-tap the field where you want to paste the data. A small "paste" button should come up. Note, however, that information in the clipboard can be monitored by all apps on your device.
|
* The clipboard based approach can be used as well: Pull the notification bar down and select "Copy username/password to clipboard". Then long-tap the field where you want to paste the data. A small "paste" button should come up. Note, however, that information in the clipboard can be monitored by all apps on your device and clearing the clipboard is not always possible.
|
||||||
|
|
||||||
These options can be used in different workflows:
|
These options can be used in different workflows:
|
||||||
### Browser-based workflow
|
### Browser-based workflow
|
||||||
If you are browsing the web and need to enter crendentials for a webpage, a simple and powerful workflow is to use the "Share URL" option from the browser's menu. Then select Keepass2Android (or KP2A Offline). Open your database (if it's not already opened) and select the entry you want to enter (if KP2A did not already select the appropriate entry). Use the built-in keyboard or the clipboard to enter the password.
|
If you are browsing the web and need to enter crendentials for a webpage, a simple and powerful workflow is to use the "Share URL" option from the browser's menu. Then select Keepass2Android (or KP2A Offline). Open your database (if it's not already opened) and select the entry you want to enter (if KP2A did not already select the appropriate entry). Use the built-in keyboard or the clipboard to enter the password.
|
||||||
### Autofill service based workflow
|
### Autofill service based workflow
|
||||||
If you have enabled the autofill service and open a (supported) app with a password field, a notification appears in the notification bar. Select this notification to select the appropriate entry. When you return to the app, the password and user field should be filled already.
|
If you have enabled the autofill service and open a (supported) app with a password field, a dropdown appears. Select "Fill with Keepass2Android" to select the appropriate entry. When you return to the app, the password and user field should be filled already.
|
||||||
### KP2A based workflow for websites
|
### KP2A based workflow for websites
|
||||||
Open KP2A, open your database, select your entry (in this step, the notification bar items should show up already). Now click the URL link of the entry to open a browser window with the website. Use one of the methods described above to enter the credentials.
|
Open KP2A, open your database, select your entry (in this step, the notification bar items should show up already). Now click the URL link of the entry to open a browser window with the website. Use one of the methods described above to enter the credentials.
|
||||||
### KP2A Keyboard based workflow
|
### KP2A Keyboard based workflow
|
||||||
@@ -69,16 +70,53 @@ Please see the [Advanced usage of the Keepass2Android keyboard](Advanced-usage-o
|
|||||||
|
|
||||||
# FAQ
|
# FAQ
|
||||||
|
|
||||||
* Should I use the KP2A keyboard for entering passwords?
|
## Should I use the KP2A keyboard for entering passwords?
|
||||||
The KP2A keyboard is meant to quickly "paste" or "type" values from your database to any text fields by using the KP2A icon. The QUERTY keyboard is just for convenience (if you just have the KP2A keyboard activated and need to enter a few letters). However, every other (trustworthy) keyboard is ok as well to enter sensitive information: Keyboard's aren't unsafe in Android. Only the clipboard is. Thus, the KP2A keyboard allows to get information out of the database without using the clipboard.
|
The KP2A keyboard is meant to quickly "paste" or "type" values from your database to any text fields by using the KP2A icon. The QUERTY keyboard is just for convenience (if you just have the KP2A keyboard activated and need to enter a few letters). However, every other (trustworthy) keyboard is ok as well to enter sensitive information: Keyboard's aren't unsafe in Android. Only the clipboard is. Thus, the KP2A keyboard allows to get information out of the database without using the clipboard.
|
||||||
**You can use any keyboard when you enter the main database password**
|
**You can use any keyboard when you enter the main database password**
|
||||||
|
|
||||||
* Is it safe to store my kdbx file in the cloud?
|
## Is it safe to store my kdbx file in the cloud?
|
||||||
While it may happen that someone gets access to your kdbx file in the cloud, there is still no need to worry: the purpose of encryption is to protect the data even in case someone gets the kdbx file! As long as you are using a safe master key, you're safe!
|
While it may happen that someone gets access to your kdbx file in the cloud, there is still no need to worry: the purpose of encryption is to protect the data even in case someone gets the kdbx file! As long as you are using a safe master key, you're safe! [Key files](https://keepass.info/help/base/keys.html#keyfiles) can help with securing the database even more.
|
||||||
|
|
||||||
* Why is Keepass2Android so big?
|
## Doesn't Keepass2Android create automatic backups?
|
||||||
|
Yes and no. Yes: Keepass2Android stores the last successfully opened file as a read-only backup locally on the phone (unless you disable this is in the settings). This should make sure that even if the file gets destroyed during a save operation or gets deleted by accident, you should always have a version that can be opened. (Don't mix this up with the internal file cache which is not meant as a backup and can easily be overwritten even with a corrupt file. This internal file cache is meant for providing writable access even when the original file is not reachable, e.g. when you're offline.)
|
||||||
|
No: The local backup has two shortcomings: It is only one backup and does not allow to revert to older versions. So if you deleted an entry from the database, it might be deleted in the local backup soon as well. The even more important shortcoming is that it is just a local backup. It won't help when your phone gets lost or broken. Please create additional backups on seperate storage!
|
||||||
|
|
||||||
|
## How do I backup the database?
|
||||||
|
If you have stored your database on the cloud, you might rely on your cloud storage providers backups. Make sure they allow you to revert to older revisions in case the file gets corrupted for some reason.
|
||||||
|
If you are working with a local database file, make sure you create regular backups. I suggest you have an aumotated mechanism, e.g. with FolderSync (Lite) which can copy local files from your device to other locations, e.g. your PC in a local network. You can also use USB or tools like MyPhoneExploror to transfer data to your PC. Or, you use a removable storage like an SD card which you keep in a safe place after making the backup.
|
||||||
|
In all cases, you need to verify that your backup is readable! It's even best to test this on another device (e.g. a PC), so you simulate the case that you may lose your phone.
|
||||||
|
|
||||||
|
## I can open my database with fingerprint, but don't remember my master password!
|
||||||
|
It's time for action! As soon as possible, select Settings - Database - Export and choose unencrypted XML (don't put this on the cloud but on a local file). Transfer this file to a PC and import it to a new kdbx file, e.g. with Keepass2. Choose a new master password and make sure you don't forget this password!
|
||||||
|
|
||||||
|
## How can I transfer data from one device to another?
|
||||||
|
* If you are about to get a new Android device, you should make sure you're not losing your passwords in the transition! The first thing you need to make sure is that you can access your .kdbx file (which stores the passwords) on the new device. If it is already stored in the cloud, you only need to make sure you know how to setup the cloud storage on the new device (it might require a password, so make sure you have access to that!).
|
||||||
|
* If the .kdbx-file is stored locally on the old device, make sure you have an up-to-date backup (see above). You can then transfer that backup copy to the new device. (Note: transferring via USB causes data corruption in some cases, use MyPhoneExplorer or similar tools to be sure this does not happen.)
|
||||||
|
* If you are securing your password database with a keyfile, also transfer this key file to the new device.
|
||||||
|
* If you are opening your database with a fingerprint, make sure you also know the master password because fingerprint will not be available immediately on the new device.
|
||||||
|
|
||||||
|
## Why is Keepass2Android's apk so big?
|
||||||
Please see [Keepass2Android Apk](Keepass2Android-Apk.md) for more information.
|
Please see [Keepass2Android Apk](Keepass2Android-Apk.md) for more information.
|
||||||
|
|
||||||
|
## I get a message "File is trashed" when reading or writing a file on Google Drive
|
||||||
|
This happens because ocaml-fuse (I guess you are on Linux and use that) moves files to trash and then creates a new one instead of correctly updating the file on Google Drive (each file has a unique ID which Keepass2Android uses). Fortunately, this was fixed: https://github.com/astrada/google-drive-ocamlfuse/issues/494. After activating this option, please select "Change database" in KP2A, tap ,"Open file" and browse to the file on Google Drive again. After that, the message should no longer pop up.
|
||||||
|
|
||||||
|
## I get a message "The name must not be empty: null" when opening from Google Drive
|
||||||
|
Please follow these steps:
|
||||||
|
|
||||||
|
* select "Change database" on the password screen, then "Open database" and browse to your file again
|
||||||
|
* go to Android app settings and disable all permissions for the KP2A app. Then try again to open the database file.
|
||||||
|
* reboot the device
|
||||||
|
|
||||||
|
(Before running the following steps, make sure you don't have local changes in your database which have not been synchronized with Google Drive (this can happen if you worked offline). If you have, please open the database from the local cache and go to settings - database settings - export database and make a backup copy of the data.)
|
||||||
|
|
||||||
|
* clear KP2A's app cache in the Android settings
|
||||||
|
* uninstall & reinstall
|
||||||
|
|
||||||
|
One of these has helped all users so far, but unfortunately it's not totally clear to me why different steps are required (or nothing for most users).
|
||||||
|
|
||||||
# For developers
|
# For developers
|
||||||
If you are interested in adding new features, you have two options:
|
If you are interested in adding new features, you have two options:
|
||||||
Either your features can be implemented as a plug-in. Please see [How to create a plug-in?](How-to-create-a-plug-in_.md) for more information. Or you add the features directly in the source code of the projects and create a pull request.
|
Either your features can be implemented as a plug-in. Please see [How to create a plug-in?](How-to-create-a-plug-in_.md) for more information. Or you add the features directly in the source code of the projects and create a pull request.
|
||||||
|
|
||||||
|
If you want to build Keepass2Android, check the [build guide](Build.readme.md).
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ Keepass2Android stores very sensitive user data and therefore implements a plug-
|
|||||||
|
|
||||||
To tell Kp2a that you're a plug-in, you need to add a simple BroadcastReceiver like this:
|
To tell Kp2a that you're a plug-in, you need to add a simple BroadcastReceiver like this:
|
||||||
|
|
||||||
{{
|
```java
|
||||||
|
|
||||||
public class PluginAAccessReceiver
|
public class PluginAAccessReceiver extends keepass2android.pluginsdk.PluginAccessBroadcastReceiver
|
||||||
extends keepass2android.pluginsdk.PluginAccessBroadcastReceiver
|
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -29,13 +28,13 @@ public class PluginAAccessReceiver
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}}
|
```
|
||||||
|
|
||||||
Here, you define the method getScopes where the list of scopes is created which must be granted by the user. The actual logic of the authorization process is implemented by the base class in the sdk.
|
Here, you define the method getScopes where the list of scopes is created which must be granted by the user. The actual logic of the authorization process is implemented by the base class in the sdk.
|
||||||
|
|
||||||
In order to make this broadcast receiver visible to KP2A, add the following lines (probably with the name adapted to your class name) in the AndroidManifest.xml:
|
In order to make this broadcast receiver visible to KP2A, add the following lines (probably with the name adapted to your class name) in the AndroidManifest.xml:
|
||||||
|
|
||||||
{{
|
```xml
|
||||||
<receiver android:name="PluginAAccessReceiver" android:exported="true">
|
<receiver android:name="PluginAAccessReceiver" android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
|
<action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
|
||||||
@@ -43,19 +42,19 @@ In order to make this broadcast receiver visible to KP2A, add the following line
|
|||||||
<action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
|
<action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
}}
|
```
|
||||||
|
|
||||||
Please also add a few strings in your resource files (e.g. strings.xml) with the following keys:
|
Please also add a few strings in your resource files (e.g. strings.xml) with the following keys:
|
||||||
|
|
||||||
{{
|
```xml
|
||||||
<string name="kp2aplugin_title">The Great PluginA</string>
|
<string name="kp2aplugin_title">The Great PluginA</string>
|
||||||
<string name="kp2aplugin_shortdesc">Test plugin to demonstrate how plugins work</string>
|
<string name="kp2aplugin_shortdesc">Test plugin to demonstrate how plugins work</string>
|
||||||
<string name="kp2aplugin_author">[your name here](your-name-here)</string>
|
<string name="kp2aplugin_author">[your name here](your-name-here)</string>
|
||||||
}}
|
```
|
||||||
These strings will be displayed to the user when KP2A asks if access should be granted.
|
These strings will be displayed to the user when KP2A asks if access should be granted.
|
||||||
|
|
||||||
## Modifying the entry view
|
## Modifying the entry view
|
||||||
You can add menu options for the full entry or for individual fields of the entry when displayed to the user. This is done, for example, by the QR plugin ([https://play.google.com/store/apps/details?id=keepass2android.plugin.qr](https___play.google.com_store_apps_details_id=keepass2android.plugin.qr)).
|
You can add menu options for the full entry or for individual fields of the entry when displayed to the user. This is done, for example, by the QR plugin ([https://play.google.com/store/apps/details?id=keepass2android.plugin.qr](https://play.google.com/store/apps/details?id=keepass2android.plugin.qr)).
|
||||||
In addition, it is even possible to add new fields or modify existing fields. Please see the sample plugin "PluginA" in the KP2A repository for a simple example on how to do this:
|
In addition, it is even possible to add new fields or modify existing fields. Please see the sample plugin "PluginA" in the KP2A repository for a simple example on how to do this:
|
||||||
[https://keepass2android.codeplex.com/SourceControl/latest#src/java/PluginA/src/keepass2android/plugina/PluginAActionReceiver.java](https://keepass2android.codeplex.com/SourceControl/latest#src/java/PluginA/src/keepass2android/plugina/PluginAActionReceiver.java)
|
[https://keepass2android.codeplex.com/SourceControl/latest#src/java/PluginA/src/keepass2android/plugina/PluginAActionReceiver.java](https://keepass2android.codeplex.com/SourceControl/latest#src/java/PluginA/src/keepass2android/plugina/PluginAActionReceiver.java)
|
||||||
|
|
||||||
@@ -64,7 +63,7 @@ KP2A 0.9.4 adds a great opportunity for third party apps: Instead of prompting t
|
|||||||
|
|
||||||
To implement this, simply follow the steps descrIbed above in the sections Preparation and Authorization. Then, wherever appropriate in your app, do something like this:
|
To implement this, simply follow the steps descrIbed above in the sections Preparation and Authorization. Then, wherever appropriate in your app, do something like this:
|
||||||
|
|
||||||
{{
|
```java
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PlaceholderFragment.this.startActivityForResult(
|
PlaceholderFragment.this.startActivityForResult(
|
||||||
@@ -73,22 +72,23 @@ To implement this, simply follow the steps descrIbed above in the sections Prepa
|
|||||||
}
|
}
|
||||||
catch (ActivityNotFoundException e)
|
catch (ActivityNotFoundException e)
|
||||||
{
|
{
|
||||||
Toast.makeText(PlaceholderFragment.this.getActivity(), "no KP2A host app found", Toast.LENGTH_SHORT).show();
|
Toast.makeText(
|
||||||
|
PlaceholderFragment.this.getActivity(),
|
||||||
|
"no KP2A host app found",
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
```
|
||||||
|
|
||||||
(of course you can use PacketManager to check if the intent can be started instead of catching the Exception).
|
(of course you can use `PacketManager` to check if the intent can be started instead of catching the `Exception`).
|
||||||
|
|
||||||
Instead of querying credentials associated with your own app, you might want to query other credentials as well. instead of Kp2aControl.getQueryEntryIntentForOwnPackage() use
|
Instead of querying credentials associated with your own app, you might want to query other credentials as well. instead of `KpControl.getQueryEntryIntentForOwnPackage()` use
|
||||||
{{
|
`Kp2aControl.getQueryEntryIntent("google.com")`
|
||||||
Kp2aControl.getQueryEntryIntent("google.com")
|
This requires \{"SCOPE_QUERY_CREDENTIALS (whereas getQueryEntryIntentForOwnPackage() requires SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE)"\}.
|
||||||
}}
|
|
||||||
This requires {"SCOPE_QUERY_CREDENTIALS (whereas getQueryEntryIntentForOwnPackage() requires SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE)"}.
|
|
||||||
|
|
||||||
The credential data can be retrieved in onActivityResult():
|
The credential data can be retrieved in onActivityResult():
|
||||||
|
|
||||||
{{
|
```java
|
||||||
if ((requestCode == 1) //queryEntry for own package
|
if ((requestCode == 1) //queryEntry for own package
|
||||||
&& (resultCode == RESULT_OK)) // ensure user granted access and selected something
|
&& (resultCode == RESULT_OK)) // ensure user granted access and selected something
|
||||||
{
|
{
|
||||||
@@ -96,17 +96,20 @@ if ((requestCode == 1) //queryEntry for own package
|
|||||||
if (!credentials.isEmpty())
|
if (!credentials.isEmpty())
|
||||||
{
|
{
|
||||||
//here we go!
|
//here we go!
|
||||||
Toast.makeText(getActivity(), "retrieved credenitals! Username="+credentials.get(KeepassDefs.UserNameField), Toast.LENGTH_LONG).show();
|
Toast.makeText(
|
||||||
|
getActivity(),
|
||||||
|
"retrieved credenitals! Username="+credentials.get(KeepassDefs.UserNameField),
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
```
|
||||||
|
|
||||||
Note that you get access to all strings (Title, Username, Password, URL, Notes + any user defined strings) in the entry. This may be in intersting in combination with the following section:
|
Note that you get access to all strings (Title, Username, Password, URL, Notes + any user defined strings) in the entry. This may be in intersting in combination with the following section:
|
||||||
|
|
||||||
## Storing data in KP2A
|
## Storing data in KP2A
|
||||||
If you allow the user to set up an account in your app or create a password, e.g. for encryption, please add an option to store this data in the Keepass2Android database, as this will lead to great workflows for the user. It's as simple as
|
If you allow the user to set up an account in your app or create a password, e.g. for encryption, please add an option to store this data in the Keepass2Android database, as this will lead to great workflows for the user. It's as simple as
|
||||||
|
|
||||||
{{
|
```java
|
||||||
try {
|
try {
|
||||||
HashMap<String, String> fields = new HashMap<String, String>();
|
HashMap<String, String> fields = new HashMap<String, String>();
|
||||||
//standard fields
|
//standard fields
|
||||||
@@ -124,8 +127,7 @@ try {
|
|||||||
|
|
||||||
//add to KP2A
|
//add to KP2A
|
||||||
PlaceholderFragment.this.startActivityForResult(
|
PlaceholderFragment.this.startActivityForResult(
|
||||||
Kp2aControl
|
Kp2aControl.getAddEntryIntent(fields, protectedFields),
|
||||||
.getAddEntryIntent(fields, protectedFields),
|
|
||||||
2);
|
2);
|
||||||
} catch (ActivityNotFoundException e) {
|
} catch (ActivityNotFoundException e) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
@@ -133,7 +135,7 @@ try {
|
|||||||
"no KP2A host app found",
|
"no KP2A host app found",
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}}
|
```
|
||||||
|
|
||||||
Note that this does not even require access authorization because the user will actively save the entry anyways (after selecting the group where to create it.)
|
Note that this does not even require access authorization because the user will actively save the entry anyways (after selecting the group where to create it.)
|
||||||
|
|
||||||
@@ -142,13 +144,13 @@ With {"SCOPE_DATABASE_ACTIONS"}, you will be informed when the user opens, close
|
|||||||
|
|
||||||
PluginA uses this to simply display a toast message in its ActionReceiver:
|
PluginA uses this to simply display a toast message in its ActionReceiver:
|
||||||
|
|
||||||
{{
|
```java
|
||||||
@Override
|
@Override
|
||||||
protected void dbAction(DatabaseAction db) {
|
protected void dbAction(DatabaseAction db) {
|
||||||
|
|
||||||
Log.d("PluginA", db.getAction() + " in file " + db.getFileDisplayName() + " ("+db.getFilePath()+")");
|
Log.d("PluginA", db.getAction() + " in file " + db.getFileDisplayName() + " ("+db.getFilePath()+")");
|
||||||
}
|
}
|
||||||
}}
|
```
|
||||||
|
|
||||||
|
|
||||||
## Sample plugin
|
## Sample plugin
|
||||||
|
|||||||
@@ -4,25 +4,25 @@
|
|||||||
on how to set up a Keepass 2 database with Yubikey/OTP protection.<br>
|
on how to set up a Keepass 2 database with Yubikey/OTP protection.<br>
|
||||||
<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>
|
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>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
|
<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>
|
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>
|
<p><br>
|
||||||
<br>
|
<br>
|
||||||
In Keepass2Android, select "Open file" and locate your database file, e.g. yubi.kdbx.<br>
|
In Keepass2Android, select "Open file" and locate your database file, e.g. yubi.kdbx.<br>
|
||||||
<br>
|
<br>
|
||||||
In the password screen under "Select master key type" select "Password + OTP".</p>
|
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>
|
<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
|
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>
|
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
|
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>
|
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> </h2>
|
||||||
<h2>A note about offline access</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
|
<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
|
||||||
|
|||||||
@@ -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:
|
Here's a list of what is contained in the Keepass2Android 0.9.1 application package:
|
||||||
|
|
||||||
{{
|
```
|
||||||
Mono for Android
|
Mono for Android
|
||||||
.net dlls 5.0 MB
|
.net dlls 5.0 MB
|
||||||
Runtime 2.5 MB
|
Runtime 2.5 MB
|
||||||
@@ -22,4 +22,4 @@ Java/Mono bindings 0.5 MB
|
|||||||
rest 0.3 MB
|
rest 0.3 MB
|
||||||
|
|
||||||
TOTAL 13 MB
|
TOTAL 13 MB
|
||||||
}}
|
```
|
||||||
|
|||||||
20
docs/OreoAutoFill.md
Normal file
20
docs/OreoAutoFill.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Google has introduced the Android Autofill interface in Android 8. Keepass2Android supports this interface. In most Android apps and all Autofill-enabled browsers, this is the most convenient way of entering passwords. As soon as you focus a field, you will see a popup "Fill with Keepass2Android".
|
||||||
|
|
||||||
|
<img src="autofill-facebook.png" />
|
||||||
|
|
||||||
|
After clicking this popup, you can unlock your KP2A database. If automatic look up succeeds, KP2A will close automatically, if not you are prompted to select the entry you want to auto-fill. When returning to the target app, the fields should be filled automatically already.
|
||||||
|
|
||||||
|
As of January 2018, the following browsers are known to have Android Autofill support:
|
||||||
|
|
||||||
|
* Firefox Focus / Firefox Klar
|
||||||
|
* Opera Mini
|
||||||
|
|
||||||
|
These browsers do not (yet) have autofill support:
|
||||||
|
|
||||||
|
* Google Chrome
|
||||||
|
* Firefox for Android ([bugzilla entry](https://bugzilla.mozilla.org/show_bug.cgi?id=1352011))
|
||||||
|
* Brave-Browser
|
||||||
|
* Opera
|
||||||
|
|
||||||
|
Please use the Share-URL-feature and the built-in KP2A keyboard for these browsers.
|
||||||
|
|
||||||
@@ -11,9 +11,7 @@ is the author of Keepass2Android and Keepass2Android Offline.
|
|||||||
|
|
||||||
The contents of your password database is yours and is never collected by us. Keepass2Android stores this data on a location chosen by the user and encrypted in the Keepass database format. The app author does not have any access, neither to the files nor the contents. Depending on the user's choice of the storage location, the files may be stored on third-party servers like Dropbox or Google Drive.
|
The contents of your password database is yours and is never collected by us. Keepass2Android stores this data on a location chosen by the user and encrypted in the Keepass database format. The app author does not have any access, neither to the files nor the contents. Depending on the user's choice of the storage location, the files may be stored on third-party servers like Dropbox or Google Drive.
|
||||||
|
|
||||||
Keepass2Android does not collect personal identifiable information. After unexpected errors or crashes of the app, the user may be asked if he/she whants to send an error report (Keepass2Android regular only). Error reports do not contain database contents, except (depending on the error message) UUIDs of entries. They may contain file paths if the error was related to a failed file operation. Error reports sent from inside the app are sent using Xamarin Insights.
|
Keepass2Android does not collect personal identifiable information. For debugging purposes, the user may activate creating a debug log. This collects data inside the app and is not accessible to any other app nor the author of the app, unless the user explicitly sends the debug log to the author. Debug logs usually do not contain personal identifiable information, except if such information is part of file or folder names. Debug logs will not be shared with third parties unless explicitly authorized by the sender.
|
||||||
|
|
||||||
The app author does not pass any of this data to third parties.
|
|
||||||
|
|
||||||
# What Android permissions are required?
|
# What Android permissions are required?
|
||||||
|
|
||||||
@@ -22,5 +20,4 @@ The app author does not pass any of this data to third parties.
|
|||||||
* **Storage**: Required to allow the user to read/store password databases or key files on the device locally.
|
* **Storage**: Required to allow the user to read/store password databases or key files on the device locally.
|
||||||
* **Fingerprint**: Required if you want to use fingerprint unlock.
|
* **Fingerprint**: Required if you want to use fingerprint unlock.
|
||||||
* **Vibrate**: Required by the built-in keyboard (vibrate on key press)
|
* **Vibrate**: Required by the built-in keyboard (vibrate on key press)
|
||||||
* **Bind Accessibility service**: Required to provide the Auto-Fill accessibility service.
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,27 @@
|
|||||||
|
<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?
|
# 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.
|
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?
|
# Where to get it?
|
||||||
Regular stable releases of Keepass2Android are available on [Google Play](https://play.google.com/store/apps/details?id=keepass2android.keepass2android).
|
Regular stable releases of Keepass2Android are available on [Google Play](https://play.google.com/store/apps/details?id=keepass2android.keepass2android).
|
||||||
|
|
||||||
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android). Please join the [Beta tester group](https://plus.google.com/communities/107293657110547776032) for news and discussions about the latest beta releases.
|
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android) or [Beta testing channel for Keepass2Android Offline](https://play.google.com/apps/testing/keepass2android.keepass2android_nonet).
|
||||||
|
|
||||||
# How can I contribute?
|
# How can I contribute?
|
||||||
* Help to translate Keepass2Android into your language or improve translations at [our Crowdin page](http://crowdin.net/project/keepass2android)
|
* Help to translate Keepass2Android into your language or improve translations at [our Crowdin page](http://crowdin.net/project/keepass2android)
|
||||||
* Add features by [creating a plugin](How-to-create-a-plug-in_) or creating a pull request. You might want to contact me before you start working so I can coordinate efforts.
|
* Add features by [creating a plugin](How-to-create-a-plug-in_.md) or creating a pull request. You might want to contact me before you start working so I can coordinate efforts.
|
||||||
|
* [Become a GitHub sponsor to boost 🚀 development](https://github.com/sponsors/PhilippC)
|
||||||
* [Make a donation](http://philipp.crocoll.net/donate.php)
|
* [Make a donation](http://philipp.crocoll.net/donate.php)
|
||||||
|
|
||||||
# How do I learn more?
|
# How do I learn more?
|
||||||
Please see the [documentation](Documentation.md).
|
Please see the [documentation](Documentation.md).
|
||||||
|
|
||||||
[](https://www.bitrise.io/app/43a23ab54dee9f7e)
|
# How do I build the project?
|
||||||
|
If you want to build Keepass2Android, check the [build guide](Build.readme.md).
|
||||||
|
|
||||||
|
The project homepage is https://philipp.crocoll.net/keepass2android/index.php
|
||||||
|
|
||||||
|
<img src="https://github.com/PhilippC/keepass2android/actions/workflows/build.yml/badge.svg" alt="build status" /> [Build status](https://github.com/PhilippC/keepass2android/actions)
|
||||||
|
|||||||
1
docs/_config.yml
Normal file
1
docs/_config.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
theme: jekyll-theme-slate
|
||||||
BIN
docs/autofill-facebook.png
Normal file
BIN
docs/autofill-facebook.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 93 KiB |
3287
graphics/launcher_icon/Logo-blue.svg
Normal file
3287
graphics/launcher_icon/Logo-blue.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 353 KiB |
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 |
47
graphics/launcher_icon/Logo-green-foreground.svg
Normal file
47
graphics/launcher_icon/Logo-green-foreground.svg
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
id="Layer_1"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
viewBox="0 0 800 800"
|
||||||
|
enable-background="new 0 0 800 800"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="Logo-green-foreground.svg"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"><metadata
|
||||||
|
id="metadata4969"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs4967" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1017"
|
||||||
|
id="namedview4965"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.75130096"
|
||||||
|
inkscape:cx="413.59403"
|
||||||
|
inkscape:cy="332.90312"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="Layer_1" /><path
|
||||||
|
d="m 318.7,232 c 13.6,0 24.6,10.9 24.6,24.4 0,13.5 -11,24.4 -24.6,24.4 -13.6,0 -24.6,-10.9 -24.6,-24.4 0,-13.5 11,-24.4 24.6,-24.4 z m 134.8,24.4 c 0,13.5 11,24.4 24.6,24.4 13.6,0 24.6,-10.9 24.6,-24.4 0,-13.5 -11,-24.4 -24.6,-24.4 -13.6,0 -24.6,10.9 -24.6,24.4 z M 399.8,177.7 M 140.2,600.6 v 47 h 517.3 v -47 z m 0,-249.7 v 47 h 517.3 v -47 z m -0.1,130.3 h 191.8 c -0.8,-4.1 -1.2,-8.3 -1.2,-12.4 0,-12.4 3.4,-24.2 9.9,-34.6 H 140.1 Z m 517.4,0 v -47 H 454.9 c 6.5,10.4 9.8,22.2 9.8,34.6 0,4.1 -0.4,8.3 -1.2,12.4 z m -517.4,36.2 v 47 h 186.6 l 14.3,-47 z m 314.2,0 14.4,47 h 188.8 v -47 z m -21.6,48.4 -21,-68.9 2.7,-1.6 c 10.3,-5.9 16.7,-16.9 16.7,-28.6 0,-18.2 -15,-33 -33.3,-33 -18.3,0 -33.3,14.8 -33.3,33 0,11.8 6.4,22.7 16.7,28.6 l 2.7,1.6 -21.1,68.9 z m 74.8,-407.3 0.2,-0.3 35.6,-51.3 c 2.4,-3.5 1.8,-8.1 -1.4,-10.3 -3.2,-2.2 -7.7,-1.1 -10.2,2.4 l -37.2,53.5 -0.1,0.3 c -29.3,-11.8 -62.1,-18.5 -96.8,-18.5 -35.2,0 -68.5,6.9 -98.1,19 L 261.8,99 c -2.4,-3.5 -7,-4.6 -10.2,-2.4 -3.2,2.2 -3.8,6.8 -1.4,10.3 l 36.2,52.2 c -66.8,32.2 -111.9,92.4 -111.9,161.3 h 42.9 c 0,-79.1 80.8,-143.5 180.1,-143.5 99.3,0 180.1,64.3 180.1,143.5 h 42.9 c 0.2,-69.3 -45.4,-129.8 -113,-161.9 z"
|
||||||
|
id="path4962"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="clip-rule:evenodd;fill:#ffffff;fill-rule:evenodd" /></svg>
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
3279
graphics/launcher_icon/Logo-green.svg
Normal file
3279
graphics/launcher_icon/Logo-green.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 353 KiB |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages>
|
|
||||||
<package id="Xamarin.GooglePlayServices" version="27.0.0.0" />
|
|
||||||
</packages>
|
|
||||||
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.
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>
|
||||||
@@ -10,8 +10,10 @@
|
|||||||
<RootNamespace>AndroidFileChooserBinding</RootNamespace>
|
<RootNamespace>AndroidFileChooserBinding</RootNamespace>
|
||||||
<AssemblyName>AndroidFileChooserBinding</AssemblyName>
|
<AssemblyName>AndroidFileChooserBinding</AssemblyName>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
|
||||||
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
|
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||||
|
<AndroidCodegenTarget>XAJavaInterop1</AndroidCodegenTarget>
|
||||||
|
<AndroidClassParser>class-parse</AndroidClassParser>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -47,9 +49,6 @@
|
|||||||
<Reference Include="Mono.Android" />
|
<Reference Include="Mono.Android" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Xamarin.Android.Support.v4">
|
|
||||||
<HintPath>..\packages\Xamarin.Android.Support.v4.20.0.0.4\lib\MonoAndroid10\Xamarin.Android.Support.v4.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Xamarin.Android.Support.v4" version="20.0.0.4" targetFramework="MonoAndroid22" requireReinstallation="True" />
|
|
||||||
</packages>
|
</packages>
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
android:hint="@string/http_auth_dialog_password"
|
android:hint="@string/http_auth_dialog_password"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
android:paddingBottom="20dp" />
|
android:paddingBottom="20dp"
|
||||||
|
android:importantForAccessibility="no" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
Binary file not shown.
BIN
src/JavaFileStorageBindings/Jars/dropbox-core-sdk-4.0.0.jar
Normal file
BIN
src/JavaFileStorageBindings/Jars/dropbox-core-sdk-4.0.0.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/JavaFileStorageBindings/Jars/gdrive/grpc-context-1.22.1.jar
Normal file
BIN
src/JavaFileStorageBindings/Jars/gdrive/grpc-context-1.22.1.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/JavaFileStorageBindings/Jars/gdrive/jsr305-3.0.2.jar
Normal file
BIN
src/JavaFileStorageBindings/Jars/gdrive/jsr305-3.0.2.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/JavaFileStorageBindings/Jars/gson-2.8.6.jar
Normal file
BIN
src/JavaFileStorageBindings/Jars/gson-2.8.6.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/JavaFileStorageBindings/Jars/okhttp-4.10.0-RC1.jar
Normal file
BIN
src/JavaFileStorageBindings/Jars/okhttp-4.10.0-RC1.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/JavaFileStorageBindings/Jars/okhttp-digest-2.5.jar
Normal file
BIN
src/JavaFileStorageBindings/Jars/okhttp-digest-2.5.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/JavaFileStorageBindings/Jars/okio-2.9.0.jar
Normal file
BIN
src/JavaFileStorageBindings/Jars/okio-2.9.0.jar
Normal file
Binary file not shown.
@@ -1,5 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.props" Condition="Exists('..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.props')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.props" Condition="Exists('..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
@@ -10,8 +12,12 @@
|
|||||||
<RootNamespace>JavaFileStorageBindings</RootNamespace>
|
<RootNamespace>JavaFileStorageBindings</RootNamespace>
|
||||||
<AssemblyName>JavaFileStorageBindings</AssemblyName>
|
<AssemblyName>JavaFileStorageBindings</AssemblyName>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
|
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||||
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v13.0</TargetFrameworkVersion>
|
||||||
|
<AndroidClassParser>class-parse</AndroidClassParser>
|
||||||
|
<AndroidCodegenTarget>XAJavaInterop1</AndroidCodegenTarget>
|
||||||
|
<NuGetPackageImportStamp>
|
||||||
|
</NuGetPackageImportStamp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -44,20 +50,130 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Java.Interop" />
|
||||||
<Reference Include="Mono.Android" />
|
<Reference Include="Mono.Android" />
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="GooglePlayServicesLib">
|
<Reference Include="System.Net.Http" />
|
||||||
<HintPath>..\Components\googleplayservices-19.0.0\lib\android\GooglePlayServicesLib.dll</HintPath>
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="System.Numerics.Vectors" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Xamarin.AndroidX.Activity, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Activity.1.6.0\lib\monoandroid12.0\Xamarin.AndroidX.Activity.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Android.Support.v4">
|
<Reference Include="Xamarin.AndroidX.Annotation, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\Components\googleplayservices-19.0.0\lib\android\Xamarin.Android.Support.v4.dll</HintPath>
|
<HintPath>..\packages\Xamarin.AndroidX.Annotation.1.5.0\lib\monoandroid12.0\Xamarin.AndroidX.Annotation.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Android.Support.v7.AppCompat">
|
<Reference Include="Xamarin.AndroidX.Annotation.Experimental, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\Components\googleplayservices-19.0.0\lib\android\Xamarin.Android.Support.v7.AppCompat.dll</HintPath>
|
<HintPath>..\packages\Xamarin.AndroidX.Annotation.Experimental.1.3.0\lib\monoandroid12.0\Xamarin.AndroidX.Annotation.Experimental.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Xamarin.Android.Support.v7.MediaRouter">
|
<Reference Include="Xamarin.AndroidX.Arch.Core.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\Components\googleplayservices-19.0.0\lib\android\Xamarin.Android.Support.v7.MediaRouter.dll</HintPath>
|
<HintPath>..\packages\Xamarin.AndroidX.Arch.Core.Common.2.1.0.15\lib\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Arch.Core.Runtime, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Arch.Core.Runtime.2.1.0.15\lib\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Runtime.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Collection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Collection.1.2.0.4\lib\monoandroid12.0\Xamarin.AndroidX.Collection.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Concurrent.Futures, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Concurrent.Futures.1.1.0.9\lib\monoandroid12.0\Xamarin.AndroidX.Concurrent.Futures.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Core.1.9.0\lib\monoandroid12.0\Xamarin.AndroidX.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Core.Core.Ktx, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Core.Core.Ktx.1.9.0\lib\monoandroid12.0\Xamarin.AndroidX.Core.Core.Ktx.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.CustomView, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.CustomView.1.1.0.13\lib\monoandroid12.0\Xamarin.AndroidX.CustomView.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Fragment, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Fragment.1.5.3\lib\monoandroid12.0\Xamarin.AndroidX.Fragment.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Lifecycle.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Lifecycle.Common.2.5.1\lib\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Lifecycle.LiveData.Core.2.5.1\lib\monoandroid12.0\Xamarin.AndroidX.Lifecycle.LiveData.Core.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Lifecycle.Runtime, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Lifecycle.Runtime.2.5.1\lib\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Runtime.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Lifecycle.ViewModel, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Lifecycle.ViewModel.2.5.1\lib\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModel.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Lifecycle.ViewModelSavedState, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.2.5.1\lib\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Loader, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Loader.1.1.0.14\lib\monoandroid12.0\Xamarin.AndroidX.Loader.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.MultiDex, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.MultiDex.2.0.1.13\lib\monoandroid12.0\Xamarin.AndroidX.MultiDex.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.SavedState, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.SavedState.1.2.0\lib\monoandroid12.0\Xamarin.AndroidX.SavedState.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.Tracing.Tracing, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.Tracing.Tracing.1.1.0.1\lib\monoandroid12.0\Xamarin.AndroidX.Tracing.Tracing.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.VersionedParcelable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.VersionedParcelable.1.1.1.14\lib\monoandroid12.0\Xamarin.AndroidX.VersionedParcelable.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.AndroidX.ViewPager, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.AndroidX.ViewPager.1.0.0.14\lib\monoandroid12.0\Xamarin.AndroidX.ViewPager.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Google.Guava, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Google.Guava.28.2.0.1\lib\monoandroid90\Xamarin.Google.Guava.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Google.Guava.FailureAccess, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Google.Guava.FailureAccess.1.0.1.3\lib\monoandroid90\Xamarin.Google.Guava.FailureAccess.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Google.Guava.ListenableFuture, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Google.Guava.ListenableFuture.1.0.0.9\lib\monoandroid12.0\Xamarin.Google.Guava.ListenableFuture.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.GooglePlayServices.Auth, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Auth.120.4.0\lib\monoandroid12.0\Xamarin.GooglePlayServices.Auth.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.GooglePlayServices.Auth.Api.Phone, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Auth.Api.Phone.118.0.1.2\lib\monoandroid12.0\Xamarin.GooglePlayServices.Auth.Api.Phone.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.GooglePlayServices.Auth.Base, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Auth.Base.118.0.6\lib\monoandroid12.0\Xamarin.GooglePlayServices.Auth.Base.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.GooglePlayServices.Base, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Base.118.1.0\lib\monoandroid12.0\Xamarin.GooglePlayServices.Base.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.GooglePlayServices.Basement, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Basement.118.1.0.1\lib\monoandroid12.0\Xamarin.GooglePlayServices.Basement.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.GooglePlayServices.Fido, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Fido.119.0.0\lib\monoandroid12.0\Xamarin.GooglePlayServices.Fido.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.GooglePlayServices.Tasks, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.GooglePlayServices.Tasks.118.0.2\lib\monoandroid12.0\Xamarin.GooglePlayServices.Tasks.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Jetbrains.Annotations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Jetbrains.Annotations.23.0.0.4\lib\monoandroid12.0\Xamarin.Jetbrains.Annotations.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Kotlin.StdLib, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Kotlin.StdLib.1.7.10\lib\monoandroid12.0\Xamarin.Kotlin.StdLib.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Kotlin.StdLib.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Kotlin.StdLib.Common.1.7.10\lib\monoandroid12.0\Xamarin.Kotlin.StdLib.Common.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Kotlin.StdLib.Jdk7, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Kotlin.StdLib.Jdk7.1.7.10\lib\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk7.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.Kotlin.StdLib.Jdk8, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.Kotlin.StdLib.Jdk8.1.7.10\lib\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk8.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.KotlinX.Coroutines.Android, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.KotlinX.Coroutines.Android.1.6.4\lib\monoandroid12.0\Xamarin.KotlinX.Coroutines.Android.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Xamarin.KotlinX.Coroutines.Core.Jvm, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Xamarin.KotlinX.Coroutines.Core.Jvm.1.6.4\lib\monoandroid12.0\Xamarin.KotlinX.Coroutines.Core.Jvm.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -69,6 +185,7 @@
|
|||||||
</LibraryProjectZip>
|
</LibraryProjectZip>
|
||||||
<None Include="Jars\AboutJars.txt" />
|
<None Include="Jars\AboutJars.txt" />
|
||||||
<None Include="Additions\AboutAdditions.txt" />
|
<None Include="Additions\AboutAdditions.txt" />
|
||||||
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<TransformFile Include="Transforms\Metadata.xml" />
|
<TransformFile Include="Transforms\Metadata.xml" />
|
||||||
@@ -90,10 +207,10 @@
|
|||||||
</XamarinComponentReference>
|
</XamarinComponentReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\okhttp-digest-1.7.jar" />
|
<ProjectReference Include="..\PCloudBindings\PCloudBindings.csproj">
|
||||||
</ItemGroup>
|
<Project>{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}</Project>
|
||||||
<ItemGroup>
|
<Name>PCloudBindings</Name>
|
||||||
<EmbeddedReferenceJar Include="Jars\gson-2.3.1.jar" />
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\msa-auth-0.8.6\classes-msa-auth.jar" />
|
<EmbeddedReferenceJar Include="Jars\msa-auth-0.8.6\classes-msa-auth.jar" />
|
||||||
@@ -101,36 +218,15 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\onedrive-sdk-android-1.2.2\classes-onedrive-sdk.jar" />
|
<EmbeddedReferenceJar Include="Jars\onedrive-sdk-android-1.2.2\classes-onedrive-sdk.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\adal-1.1.19\classes-adal.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\commons-logging-1.1.1.jar" />
|
<EmbeddedReferenceJar Include="Jars\gdrive\commons-logging-1.1.1.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-api-client-1.16.0-rc.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-api-client-android-1.16.0-rc.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-api-services-drive-v2-rev102-1.16.0-rc.jar" />
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-api-services-drive-v2-rev102-1.16.0-rc.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-1.16.0-rc.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-android-1.16.0-rc.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-jackson-1.16.0-rc.jar" />
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-jackson-1.16.0-rc.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-jackson2-1.16.0-rc.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-oauth-client-1.16.0-rc.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\httpclient-4.0.3.jar" />
|
<EmbeddedReferenceJar Include="Jars\gdrive\httpclient-4.0.3.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -143,9 +239,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\json_simple-1.1.jar" />
|
<EmbeddedReferenceJar Include="Jars\gdrive\json_simple-1.1.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\jsr305-1.3.9.jar" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-gson-1.16.0-rc.jar" />
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-gson-1.16.0-rc.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -153,12 +246,137 @@
|
|||||||
<EmbeddedReferenceJar Include="Jars\jackson-core-2.7.4.jar" />
|
<EmbeddedReferenceJar Include="Jars\jackson-core-2.7.4.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\okio-1.9.0.jar" />
|
<EmbeddedReferenceJar Include="Jars\okhttp-digest-2.5.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedJar Include="Jars\dropbox-core-sdk-3.0.3.jar" />
|
<EmbeddedReferenceJar Include="Jars\okio-2.9.0.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedReferenceJar Include="Jars\okhttp-3.9.0.jar" />
|
<EmbeddedReferenceJar Include="Jars\okhttp-4.10.0-RC1.jar" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedJar Include="Jars\dropbox-core-sdk-4.0.0.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gson-2.8.6.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-android-1.32.1.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\jsr305-3.0.2.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-1.32.1.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-http-client-jackson2-1.32.1.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-api-client-1.30.5.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-api-client-android-1.30.5.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\google-oauth-client-1.30.4.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\opencensus-contrib-http-util-0.24.0.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\grpc-context-1.22.1.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedReferenceJar Include="Jars\gdrive\opencensus-api-0.24.0.jar" />
|
||||||
|
</ItemGroup>
|
||||||
|
<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.Google.Guava.FailureAccess.1.0.1.3\build\monoandroid90\Xamarin.Google.Guava.FailureAccess.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Google.Guava.FailureAccess.1.0.1.3\build\monoandroid90\Xamarin.Google.Guava.FailureAccess.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Google.Guava.28.2.0.1\build\monoandroid90\Xamarin.Google.Guava.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Google.Guava.28.2.0.1\build\monoandroid90\Xamarin.Google.Guava.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.MultiDex.2.0.1.13\build\monoandroid12.0\Xamarin.AndroidX.MultiDex.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.MultiDex.2.0.1.13\build\monoandroid12.0\Xamarin.AndroidX.MultiDex.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.props'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.props'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Google.Guava.ListenableFuture.1.0.0.9\build\monoandroid12.0\Xamarin.Google.Guava.ListenableFuture.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Google.Guava.ListenableFuture.1.0.0.9\build\monoandroid12.0\Xamarin.Google.Guava.ListenableFuture.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Jetbrains.Annotations.23.0.0.4\build\monoandroid12.0\Xamarin.Jetbrains.Annotations.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Jetbrains.Annotations.23.0.0.4\build\monoandroid12.0\Xamarin.Jetbrains.Annotations.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Kotlin.StdLib.Common.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Kotlin.StdLib.Common.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Common.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Kotlin.StdLib.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Kotlin.StdLib.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Annotation.1.5.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Annotation.1.5.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Annotation.Experimental.1.3.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.Experimental.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Annotation.Experimental.1.3.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.Experimental.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Arch.Core.Common.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Arch.Core.Common.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Common.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Arch.Core.Runtime.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Arch.Core.Runtime.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Runtime.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Collection.1.2.0.4\build\monoandroid12.0\Xamarin.AndroidX.Collection.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Collection.1.2.0.4\build\monoandroid12.0\Xamarin.AndroidX.Collection.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Concurrent.Futures.1.1.0.9\build\monoandroid12.0\Xamarin.AndroidX.Concurrent.Futures.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Concurrent.Futures.1.1.0.9\build\monoandroid12.0\Xamarin.AndroidX.Concurrent.Futures.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Lifecycle.Common.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Lifecycle.Common.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Common.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Lifecycle.LiveData.Core.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.LiveData.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Lifecycle.LiveData.Core.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.LiveData.Core.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Lifecycle.Runtime.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Lifecycle.Runtime.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Runtime.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Lifecycle.ViewModel.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModel.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Lifecycle.ViewModel.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModel.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.SavedState.1.2.0\build\monoandroid12.0\Xamarin.AndroidX.SavedState.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.SavedState.1.2.0\build\monoandroid12.0\Xamarin.AndroidX.SavedState.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Tracing.Tracing.1.1.0.1\build\monoandroid12.0\Xamarin.AndroidX.Tracing.Tracing.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Tracing.Tracing.1.1.0.1\build\monoandroid12.0\Xamarin.AndroidX.Tracing.Tracing.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.VersionedParcelable.1.1.1.14\build\monoandroid12.0\Xamarin.AndroidX.VersionedParcelable.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.VersionedParcelable.1.1.1.14\build\monoandroid12.0\Xamarin.AndroidX.VersionedParcelable.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Core.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Core.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Core.Core.Ktx.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.Core.Ktx.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Core.Core.Ktx.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.Core.Ktx.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.CustomView.1.1.0.13\build\monoandroid12.0\Xamarin.AndroidX.CustomView.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.CustomView.1.1.0.13\build\monoandroid12.0\Xamarin.AndroidX.CustomView.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Loader.1.1.0.14\build\monoandroid12.0\Xamarin.AndroidX.Loader.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Loader.1.1.0.14\build\monoandroid12.0\Xamarin.AndroidX.Loader.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.ViewPager.1.0.0.14\build\monoandroid12.0\Xamarin.AndroidX.ViewPager.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.ViewPager.1.0.0.14\build\monoandroid12.0\Xamarin.AndroidX.ViewPager.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Kotlin.StdLib.Jdk7.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk7.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Kotlin.StdLib.Jdk7.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk7.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.Kotlin.StdLib.Jdk8.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk8.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Kotlin.StdLib.Jdk8.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk8.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.KotlinX.Coroutines.Core.Jvm.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Core.Jvm.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.KotlinX.Coroutines.Core.Jvm.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Core.Jvm.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.KotlinX.Coroutines.Android.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Android.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.KotlinX.Coroutines.Android.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Android.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Activity.1.6.0\build\monoandroid12.0\Xamarin.AndroidX.Activity.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Activity.1.6.0\build\monoandroid12.0\Xamarin.AndroidX.Activity.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.AndroidX.Fragment.1.5.3\build\monoandroid12.0\Xamarin.AndroidX.Fragment.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.AndroidX.Fragment.1.5.3\build\monoandroid12.0\Xamarin.AndroidX.Fragment.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Basement.118.1.0.1\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Basement.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Basement.118.1.0.1\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Basement.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Tasks.118.0.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Tasks.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Tasks.118.0.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Tasks.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Base.118.1.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Base.118.1.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Base.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Auth.Api.Phone.118.0.1.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Api.Phone.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Auth.Api.Phone.118.0.1.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Api.Phone.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Auth.Base.118.0.6\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Auth.Base.118.0.6\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Base.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Fido.119.0.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Fido.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Fido.119.0.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Fido.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Auth.120.4.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Auth.120.4.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.targets'))" />
|
||||||
|
</Target>
|
||||||
|
<Import Project="..\packages\Xamarin.Google.Guava.FailureAccess.1.0.1.3\build\monoandroid90\Xamarin.Google.Guava.FailureAccess.targets" Condition="Exists('..\packages\Xamarin.Google.Guava.FailureAccess.1.0.1.3\build\monoandroid90\Xamarin.Google.Guava.FailureAccess.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Google.Guava.28.2.0.1\build\monoandroid90\Xamarin.Google.Guava.targets" Condition="Exists('..\packages\Xamarin.Google.Guava.28.2.0.1\build\monoandroid90\Xamarin.Google.Guava.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.MultiDex.2.0.1.13\build\monoandroid12.0\Xamarin.AndroidX.MultiDex.targets" Condition="Exists('..\packages\Xamarin.AndroidX.MultiDex.2.0.1.13\build\monoandroid12.0\Xamarin.AndroidX.MultiDex.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Migration.1.0.10\build\monoandroid120\Xamarin.AndroidX.Migration.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.targets" Condition="Exists('..\packages\Xamarin.Build.Download.0.11.4\build\Xamarin.Build.Download.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Google.Guava.ListenableFuture.1.0.0.9\build\monoandroid12.0\Xamarin.Google.Guava.ListenableFuture.targets" Condition="Exists('..\packages\Xamarin.Google.Guava.ListenableFuture.1.0.0.9\build\monoandroid12.0\Xamarin.Google.Guava.ListenableFuture.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Jetbrains.Annotations.23.0.0.4\build\monoandroid12.0\Xamarin.Jetbrains.Annotations.targets" Condition="Exists('..\packages\Xamarin.Jetbrains.Annotations.23.0.0.4\build\monoandroid12.0\Xamarin.Jetbrains.Annotations.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Kotlin.StdLib.Common.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Common.targets" Condition="Exists('..\packages\Xamarin.Kotlin.StdLib.Common.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Common.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Kotlin.StdLib.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.targets" Condition="Exists('..\packages\Xamarin.Kotlin.StdLib.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Annotation.1.5.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Annotation.1.5.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Annotation.Experimental.1.3.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.Experimental.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Annotation.Experimental.1.3.0\build\monoandroid12.0\Xamarin.AndroidX.Annotation.Experimental.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Arch.Core.Common.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Common.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Arch.Core.Common.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Common.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Arch.Core.Runtime.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Runtime.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Arch.Core.Runtime.2.1.0.15\build\monoandroid12.0\Xamarin.AndroidX.Arch.Core.Runtime.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Collection.1.2.0.4\build\monoandroid12.0\Xamarin.AndroidX.Collection.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Collection.1.2.0.4\build\monoandroid12.0\Xamarin.AndroidX.Collection.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Concurrent.Futures.1.1.0.9\build\monoandroid12.0\Xamarin.AndroidX.Concurrent.Futures.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Concurrent.Futures.1.1.0.9\build\monoandroid12.0\Xamarin.AndroidX.Concurrent.Futures.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Lifecycle.Common.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Common.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Lifecycle.Common.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Common.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Lifecycle.LiveData.Core.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.LiveData.Core.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Lifecycle.LiveData.Core.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.LiveData.Core.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Lifecycle.Runtime.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Runtime.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Lifecycle.Runtime.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.Runtime.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Lifecycle.ViewModel.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModel.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Lifecycle.ViewModel.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModel.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.SavedState.1.2.0\build\monoandroid12.0\Xamarin.AndroidX.SavedState.targets" Condition="Exists('..\packages\Xamarin.AndroidX.SavedState.1.2.0\build\monoandroid12.0\Xamarin.AndroidX.SavedState.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Tracing.Tracing.1.1.0.1\build\monoandroid12.0\Xamarin.AndroidX.Tracing.Tracing.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Tracing.Tracing.1.1.0.1\build\monoandroid12.0\Xamarin.AndroidX.Tracing.Tracing.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.VersionedParcelable.1.1.1.14\build\monoandroid12.0\Xamarin.AndroidX.VersionedParcelable.targets" Condition="Exists('..\packages\Xamarin.AndroidX.VersionedParcelable.1.1.1.14\build\monoandroid12.0\Xamarin.AndroidX.VersionedParcelable.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Core.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Core.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Core.Core.Ktx.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.Core.Ktx.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Core.Core.Ktx.1.9.0\build\monoandroid12.0\Xamarin.AndroidX.Core.Core.Ktx.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.CustomView.1.1.0.13\build\monoandroid12.0\Xamarin.AndroidX.CustomView.targets" Condition="Exists('..\packages\Xamarin.AndroidX.CustomView.1.1.0.13\build\monoandroid12.0\Xamarin.AndroidX.CustomView.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Loader.1.1.0.14\build\monoandroid12.0\Xamarin.AndroidX.Loader.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Loader.1.1.0.14\build\monoandroid12.0\Xamarin.AndroidX.Loader.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.ViewPager.1.0.0.14\build\monoandroid12.0\Xamarin.AndroidX.ViewPager.targets" Condition="Exists('..\packages\Xamarin.AndroidX.ViewPager.1.0.0.14\build\monoandroid12.0\Xamarin.AndroidX.ViewPager.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Kotlin.StdLib.Jdk7.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk7.targets" Condition="Exists('..\packages\Xamarin.Kotlin.StdLib.Jdk7.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk7.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.Kotlin.StdLib.Jdk8.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk8.targets" Condition="Exists('..\packages\Xamarin.Kotlin.StdLib.Jdk8.1.7.10\build\monoandroid12.0\Xamarin.Kotlin.StdLib.Jdk8.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.KotlinX.Coroutines.Core.Jvm.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Core.Jvm.targets" Condition="Exists('..\packages\Xamarin.KotlinX.Coroutines.Core.Jvm.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Core.Jvm.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.KotlinX.Coroutines.Android.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Android.targets" Condition="Exists('..\packages\Xamarin.KotlinX.Coroutines.Android.1.6.4\build\monoandroid12.0\Xamarin.KotlinX.Coroutines.Android.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.2.5.1\build\monoandroid12.0\Xamarin.AndroidX.Lifecycle.ViewModelSavedState.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Activity.1.6.0\build\monoandroid12.0\Xamarin.AndroidX.Activity.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Activity.1.6.0\build\monoandroid12.0\Xamarin.AndroidX.Activity.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.AndroidX.Fragment.1.5.3\build\monoandroid12.0\Xamarin.AndroidX.Fragment.targets" Condition="Exists('..\packages\Xamarin.AndroidX.Fragment.1.5.3\build\monoandroid12.0\Xamarin.AndroidX.Fragment.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.GooglePlayServices.Basement.118.1.0.1\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Basement.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Basement.118.1.0.1\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Basement.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.GooglePlayServices.Tasks.118.0.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Tasks.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Tasks.118.0.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Tasks.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.GooglePlayServices.Base.118.1.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Base.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Base.118.1.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Base.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.GooglePlayServices.Auth.Api.Phone.118.0.1.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Api.Phone.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Auth.Api.Phone.118.0.1.2\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Api.Phone.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.GooglePlayServices.Auth.Base.118.0.6\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Base.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Auth.Base.118.0.6\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.Base.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.GooglePlayServices.Fido.119.0.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Fido.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Fido.119.0.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Fido.targets')" />
|
||||||
|
<Import Project="..\packages\Xamarin.GooglePlayServices.Auth.120.4.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Auth.120.4.0\build\MonoAndroid12.0\Xamarin.GooglePlayServices.Auth.targets')" />
|
||||||
</Project>
|
</Project>
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
<remove-node path="/api/package[@name='com.jcraft.jsch.jcraft']" />
|
<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.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']" />
|
||||||
<remove-node path="/api/package[@name='com.dropbox.core.util']" />
|
<remove-node path="/api/package[@name='com.dropbox.core.util']" />
|
||||||
<remove-node path="/api/package[@name='com.dropbox.core.http']" />
|
<remove-node path="/api/package[@name='com.dropbox.core.http']" />
|
||||||
|
|||||||
44
src/JavaFileStorageBindings/packages.config
Normal file
44
src/JavaFileStorageBindings/packages.config
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Xamarin.AndroidX.Activity" version="1.6.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Annotation" version="1.5.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Annotation.Experimental" version="1.3.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Arch.Core.Common" version="2.1.0.15" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Arch.Core.Runtime" version="2.1.0.15" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Collection" version="1.2.0.4" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Concurrent.Futures" version="1.1.0.9" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Core" version="1.9.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Core.Core.Ktx" version="1.9.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.CustomView" version="1.1.0.13" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Fragment" version="1.5.3" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Lifecycle.Common" version="2.5.1" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Lifecycle.LiveData.Core" version="2.5.1" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Lifecycle.Runtime" version="2.5.1" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Lifecycle.ViewModel" version="2.5.1" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Lifecycle.ViewModelSavedState" version="2.5.1" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Loader" version="1.1.0.14" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Migration" version="1.0.10" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.MultiDex" version="2.0.1.13" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.SavedState" version="1.2.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.Tracing.Tracing" version="1.1.0.1" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.VersionedParcelable" version="1.1.1.14" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.AndroidX.ViewPager" version="1.0.0.14" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.Build.Download" version="0.11.4" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.Google.Guava" version="28.2.0.1" targetFramework="monoandroid90" />
|
||||||
|
<package id="Xamarin.Google.Guava.FailureAccess" version="1.0.1.3" targetFramework="monoandroid90" />
|
||||||
|
<package id="Xamarin.Google.Guava.ListenableFuture" version="1.0.0.9" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.GooglePlayServices.Auth" version="120.4.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.GooglePlayServices.Auth.Api.Phone" version="118.0.1.2" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.GooglePlayServices.Auth.Base" version="118.0.6" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.GooglePlayServices.Base" version="118.1.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.GooglePlayServices.Basement" version="118.1.0.1" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.GooglePlayServices.Fido" version="119.0.0" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.GooglePlayServices.Tasks" version="118.0.2" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.Jetbrains.Annotations" version="23.0.0.4" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.Kotlin.StdLib" version="1.7.10" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.Kotlin.StdLib.Common" version="1.7.10" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.Kotlin.StdLib.Jdk7" version="1.7.10" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.Kotlin.StdLib.Jdk8" version="1.7.10" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.KotlinX.Coroutines.Android" version="1.6.4" targetFramework="monoandroid13.0" />
|
||||||
|
<package id="Xamarin.KotlinX.Coroutines.Core.Jvm" version="1.6.4" targetFramework="monoandroid13.0" />
|
||||||
|
</packages>
|
||||||
@@ -10,8 +10,10 @@
|
|||||||
<RootNamespace>KP2AKdbLibraryBinding</RootNamespace>
|
<RootNamespace>KP2AKdbLibraryBinding</RootNamespace>
|
||||||
<AssemblyName>KP2AKdbLibraryBinding</AssemblyName>
|
<AssemblyName>KP2AKdbLibraryBinding</AssemblyName>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
|
||||||
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
|
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||||
|
<AndroidCodegenTarget>XAJavaInterop1</AndroidCodegenTarget>
|
||||||
|
<AndroidClassParser>class-parse</AndroidClassParser>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -52,10 +54,11 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<LibraryProjectZip Include="..\java\KP2AKdbLibrary\app\build\outputs\aar\app-debug.aar">
|
||||||
|
<Link>Jars\app-debug.aar</Link>
|
||||||
|
</LibraryProjectZip>
|
||||||
<None Include="Jars\AboutJars.txt" />
|
<None Include="Jars\AboutJars.txt" />
|
||||||
<None Include="Additions\AboutAdditions.txt" />
|
<None Include="Additions\AboutAdditions.txt" />
|
||||||
<EmbeddedNativeLibrary Include="libs\armeabi-v7a\libfinal-key.so" />
|
|
||||||
<EmbeddedNativeLibrary Include="libs\armeabi\libfinal-key.so" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<TransformFile Include="Transforms\Metadata.xml">
|
<TransformFile Include="Transforms\Metadata.xml">
|
||||||
@@ -65,9 +68,7 @@
|
|||||||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedJar Include="..\java\KP2AKdbLibrary\bin\kp2akdblibrary.jar">
|
<Folder Include="libs\" />
|
||||||
<Link>Jars\kp2akdblibrary.jar</Link>
|
|
||||||
</EmbeddedJar>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
|
<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.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
203
src/KeePass.sln
203
src/KeePass.sln
@@ -1,12 +1,10 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 12.0.31101.0
|
VisualStudioVersion = 17.4.33205.214
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "keepass2android", "keepass2android\keepass2android.csproj", "{A6CF8A86-37C1-4197-80FE-519DE2C842F5}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aKeyboardBinding", "Kp2aKeyboardBinding\Kp2aKeyboardBinding.csproj", "{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aKeyboardBinding", "Kp2aKeyboardBinding\Kp2aKeyboardBinding.csproj", "{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aBusinessLogic", "Kp2aBusinessLogic\Kp2aBusinessLogic.csproj", "{53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aBusinessLogic", "Kp2aBusinessLogic\Kp2aBusinessLogic.csproj", "{53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}"
|
||||||
@@ -23,9 +21,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginSdkBinding", "PluginS
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZlibAndroid", "ZlibAndroid\ZlibAndroid.csproj", "{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZlibAndroid", "ZlibAndroid\ZlibAndroid.csproj", "{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.FtpClient.Android", "netftpandroid\System.Net.FtpClient\System.Net.FtpClient.Android.csproj", "{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCloudBindings", "PCloudBindings\PCloudBindings.csproj", "{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamsungPass", "SamsungPass\Xamarin.SamsungPass\SamsungPass\SamsungPass.csproj", "{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "keepass2android-app", "keepass2android\keepass2android-app.csproj", "{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kp2aAutofillParser", "Kp2aAutofillParser\Kp2aAutofillParser.csproj", "{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aAutofillParserTest", "Kp2aAutofillParserTest\Kp2aAutofillParserTest.csproj", "{3D1560FF-86BB-4CB4-8367-80BA13B81C38}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -65,34 +67,6 @@ Global
|
|||||||
{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
||||||
{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Win32.Build.0 = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Win32.ActiveCfg = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Win32.Build.0 = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Any CPU.Deploy.0 = ReleaseNoNet|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Mixed Platforms.Deploy.0 = ReleaseNoNet|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
|
||||||
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
|
||||||
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
@@ -156,19 +130,25 @@ Global
|
|||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Debug|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.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.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.ActiveCfg = Release|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Mixed Platforms.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
|
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.ActiveCfg = Release|Any CPU
|
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Any CPU.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.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|Mixed Platforms.Build.0 = 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|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{48574278-4779-4B3A-A9E4-9CF1BC285D0B}.ReleaseNoNet|x64.ActiveCfg = Release|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.ActiveCfg = Debug|Any CPU
|
||||||
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Any CPU.Build.0 = 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
|
{3C0F7FE5-639F-4422-A087-8B26CF862D1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
@@ -247,46 +227,121 @@ Global
|
|||||||
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
|
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
|
||||||
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||||
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
|
{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|Win32.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.Release|x64.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{146FD497-BA03-4740-B6C5-5C84EA8FCDE2}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|Win32.Build.0 = ReleaseNoNet|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{2DB80C77-D46F-4970-B967-E9FFA9B2AC2E}.ReleaseNoNet|x64.Build.0 = ReleaseNoNet|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|Win32.ActiveCfg = Release|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.Release|x64.ActiveCfg = Release|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|Win32.Deploy.0 = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{3A4B8E88-FA9B-4663-BCDA-21C12E3AF98A}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|Win32.Deploy.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.Release|x64.Deploy.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|Win32.Deploy.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
|
||||||
|
{D4C32E0A-0193-4496-9DB4-02CC126FD9F3}.ReleaseNoNet|x64.Deploy.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{39B12571-BAFE-4D3A-AEE2-4D74F14DFD96}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|Win32.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|Win32.Build.0 = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|Win32.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{3D1560FF-86BB-4CB4-8367-80BA13B81C38}.ReleaseNoNet|x64.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {2B48EDA2-ABCE-4DB5-A609-DFDF5FAAE767}
|
||||||
|
EndGlobalSection
|
||||||
GlobalSection(MonoDevelopProperties) = preSolution
|
GlobalSection(MonoDevelopProperties) = preSolution
|
||||||
Policies = $0
|
Policies = $0
|
||||||
$0.DotNetNamingPolicy = $1
|
$0.DotNetNamingPolicy = $1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,8 +33,11 @@ namespace KeePassLib.Collections
|
|||||||
private Dictionary<int, ProtectedBinary> m_d =
|
private Dictionary<int, ProtectedBinary> m_d =
|
||||||
new Dictionary<int, ProtectedBinary>();
|
new Dictionary<int, ProtectedBinary>();
|
||||||
|
|
||||||
public ProtectedBinarySet()
|
private readonly bool m_bDedupAdd;
|
||||||
|
|
||||||
|
public ProtectedBinarySet(bool bDedupAdd)
|
||||||
{
|
{
|
||||||
|
m_bDedupAdd = bDedupAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
@@ -47,11 +50,6 @@ namespace KeePassLib.Collections
|
|||||||
return m_d.GetEnumerator();
|
return m_d.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
m_d.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetFreeID()
|
private int GetFreeID()
|
||||||
{
|
{
|
||||||
int i = m_d.Count;
|
int i = m_d.Count;
|
||||||
@@ -105,11 +103,9 @@ namespace KeePassLib.Collections
|
|||||||
{
|
{
|
||||||
if (pb == null) { Debug.Assert(false); return; }
|
if (pb == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
int i = Find(pb);
|
if (m_bDedupAdd && (Find(pb) >= 0)) return; // Exists already
|
||||||
if(i >= 0) return; // Exists already
|
|
||||||
|
|
||||||
i = GetFreeID();
|
m_d[GetFreeID()] = pb;
|
||||||
m_d[i] = pb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddFrom(ProtectedBinaryDictionary d)
|
public void AddFrom(ProtectedBinaryDictionary d)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
using KeePassLib.Interfaces;
|
using KeePassLib.Interfaces;
|
||||||
|
|
||||||
@@ -34,35 +34,47 @@ namespace KeePassLib.Collections
|
|||||||
public sealed class StringDictionaryEx : IDeepCloneable<StringDictionaryEx>,
|
public sealed class StringDictionaryEx : IDeepCloneable<StringDictionaryEx>,
|
||||||
IEnumerable<KeyValuePair<string, string>>, IEquatable<StringDictionaryEx>
|
IEnumerable<KeyValuePair<string, string>>, IEquatable<StringDictionaryEx>
|
||||||
{
|
{
|
||||||
private SortedDictionary<string, string> m_dict =
|
private SortedDictionary<string, string> m_d =
|
||||||
new SortedDictionary<string, string>();
|
new SortedDictionary<string, string>();
|
||||||
|
|
||||||
|
// Non-null if and only if last mod. times should be remembered
|
||||||
|
private Dictionary<string, DateTime> m_dLastMod = null;
|
||||||
|
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
get { return m_dict.Count; }
|
get { return m_d.Count; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDictionaryEx()
|
public StringDictionaryEx()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal StringDictionaryEx(bool bRememberLastMod)
|
||||||
|
{
|
||||||
|
if (bRememberLastMod) m_dLastMod = new Dictionary<string, DateTime>();
|
||||||
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
{
|
{
|
||||||
return m_dict.GetEnumerator();
|
return m_d.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||||
{
|
{
|
||||||
return m_dict.GetEnumerator();
|
return m_d.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringDictionaryEx CloneDeep()
|
public StringDictionaryEx CloneDeep()
|
||||||
{
|
{
|
||||||
StringDictionaryEx sdNew = new StringDictionaryEx();
|
StringDictionaryEx sdNew = new StringDictionaryEx();
|
||||||
|
|
||||||
foreach(KeyValuePair<string, string> kvp in m_dict)
|
foreach (KeyValuePair<string, string> kvp in m_d)
|
||||||
sdNew.m_dict[kvp.Key] = kvp.Value; // Strings are immutable
|
sdNew.m_d[kvp.Key] = kvp.Value;
|
||||||
|
|
||||||
|
if (m_dLastMod != null)
|
||||||
|
sdNew.m_dLastMod = new Dictionary<string, DateTime>(m_dLastMod);
|
||||||
|
|
||||||
|
Debug.Assert(Equals(sdNew));
|
||||||
return sdNew;
|
return sdNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,14 +82,28 @@ namespace KeePassLib.Collections
|
|||||||
{
|
{
|
||||||
if (sdOther == null) { Debug.Assert(false); return false; }
|
if (sdOther == null) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
if(m_dict.Count != sdOther.m_dict.Count) return false;
|
if (m_d.Count != sdOther.m_d.Count) return false;
|
||||||
|
|
||||||
foreach(KeyValuePair<string, string> kvp in sdOther.m_dict)
|
foreach (KeyValuePair<string, string> kvp in sdOther.m_d)
|
||||||
{
|
{
|
||||||
string str = Get(kvp.Key);
|
string str = Get(kvp.Key);
|
||||||
if ((str == null) || (str != kvp.Value)) return false;
|
if ((str == null) || (str != kvp.Value)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cLastModT = ((m_dLastMod != null) ? m_dLastMod.Count : -1);
|
||||||
|
int cLastModO = ((sdOther.m_dLastMod != null) ? sdOther.m_dLastMod.Count : -1);
|
||||||
|
if (cLastModT != cLastModO) return false;
|
||||||
|
|
||||||
|
if (m_dLastMod != null)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, DateTime> kvp in sdOther.m_dLastMod)
|
||||||
|
{
|
||||||
|
DateTime? odt = GetLastModificationTime(kvp.Key);
|
||||||
|
if (!odt.HasValue) return false;
|
||||||
|
if (odt.Value != kvp.Value) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +111,19 @@ namespace KeePassLib.Collections
|
|||||||
{
|
{
|
||||||
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
||||||
|
|
||||||
string s;
|
string str;
|
||||||
if(m_dict.TryGetValue(strName, out s)) return s;
|
m_d.TryGetValue(strName, out str);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DateTime? GetLastModificationTime(string strName)
|
||||||
|
{
|
||||||
|
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
||||||
|
|
||||||
|
if (m_dLastMod == null) return null;
|
||||||
|
|
||||||
|
DateTime dt;
|
||||||
|
if (m_dLastMod.TryGetValue(strName, out dt)) return dt;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,37 +131,40 @@ namespace KeePassLib.Collections
|
|||||||
{
|
{
|
||||||
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
||||||
|
|
||||||
return m_dict.ContainsKey(strName);
|
return m_d.ContainsKey(strName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void Set(string strName, string strValue)
|
||||||
/// Set a string.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="strField">Identifier of the string field to modify.</param>
|
|
||||||
/// <param name="strNewValue">New value. This parameter must not be <c>null</c>.</param>
|
|
||||||
/// <exception cref="System.ArgumentNullException">Thrown if one of the input
|
|
||||||
/// parameters is <c>null</c>.</exception>
|
|
||||||
public void Set(string strField, string strNewValue)
|
|
||||||
{
|
{
|
||||||
if(strField == null) { Debug.Assert(false); throw new ArgumentNullException("strField"); }
|
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
||||||
if(strNewValue == null) { Debug.Assert(false); throw new ArgumentNullException("strNewValue"); }
|
if (strValue == null) { Debug.Assert(false); throw new ArgumentNullException("strValue"); }
|
||||||
|
|
||||||
m_dict[strField] = strNewValue;
|
m_d[strName] = strValue;
|
||||||
|
|
||||||
|
if (m_dLastMod != null) m_dLastMod[strName] = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
internal void Set(string strName, string strValue, DateTime? odtLastMod)
|
||||||
/// Delete a string.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="strField">Name of the string field to delete.</param>
|
|
||||||
/// <returns>Returns <c>true</c> if the field has been successfully
|
|
||||||
/// removed, otherwise the return value is <c>false</c>.</returns>
|
|
||||||
/// <exception cref="System.ArgumentNullException">Thrown if the input
|
|
||||||
/// parameter is <c>null</c>.</exception>
|
|
||||||
public bool Remove(string strField)
|
|
||||||
{
|
{
|
||||||
if(strField == null) { Debug.Assert(false); throw new ArgumentNullException("strField"); }
|
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
||||||
|
if (strValue == null) { Debug.Assert(false); throw new ArgumentNullException("strValue"); }
|
||||||
|
|
||||||
return m_dict.Remove(strField);
|
m_d[strName] = strValue;
|
||||||
|
|
||||||
|
if (m_dLastMod != null)
|
||||||
|
{
|
||||||
|
if (odtLastMod.HasValue) m_dLastMod[strName] = odtLastMod.Value;
|
||||||
|
else m_dLastMod.Remove(strName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(string strName)
|
||||||
|
{
|
||||||
|
if (strName == null) { Debug.Assert(false); throw new ArgumentNullException("strName"); }
|
||||||
|
|
||||||
|
if (m_dLastMod != null) m_dLastMod.Remove(strName);
|
||||||
|
|
||||||
|
return m_d.Remove(strName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,14 +29,28 @@ namespace KeePassLib.Cryptography.Cipher
|
|||||||
{
|
{
|
||||||
public sealed class ChaCha20Engine : ICipherEngine2
|
public sealed class ChaCha20Engine : ICipherEngine2
|
||||||
{
|
{
|
||||||
private PwUuid m_uuid = new PwUuid(new byte[] {
|
private static PwUuid m_uuid = null;
|
||||||
|
|
||||||
|
internal static PwUuid ChaCha20Uuid
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
PwUuid pu = m_uuid;
|
||||||
|
if (pu == null)
|
||||||
|
{
|
||||||
|
pu = new PwUuid(new byte[] {
|
||||||
0xD6, 0x03, 0x8A, 0x2B, 0x8B, 0x6F, 0x4C, 0xB5,
|
0xD6, 0x03, 0x8A, 0x2B, 0x8B, 0x6F, 0x4C, 0xB5,
|
||||||
0xA5, 0x24, 0x33, 0x9A, 0x31, 0xDB, 0xB5, 0x9A
|
0xA5, 0x24, 0x33, 0x9A, 0x31, 0xDB, 0xB5, 0x9A });
|
||||||
});
|
m_uuid = pu;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PwUuid CipherUuid
|
public PwUuid CipherUuid
|
||||||
{
|
{
|
||||||
get { return m_uuid; }
|
get { return ChaCha20Uuid; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DisplayName
|
public string DisplayName
|
||||||
|
|||||||
@@ -367,5 +367,27 @@ namespace KeePassLib.Cryptography
|
|||||||
Debug.Assert(iPos == pbRes.Length);
|
Debug.Assert(iPos == pbRes.Length);
|
||||||
return pbRes;
|
return pbRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static int g_iWeakSeed = 0;
|
||||||
|
public static Random NewWeakRandom()
|
||||||
|
{
|
||||||
|
long s64 = DateTime.UtcNow.ToBinary();
|
||||||
|
int s32 = (int)((s64 >> 32) ^ s64);
|
||||||
|
|
||||||
|
lock (g_oSyncRoot)
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
g_iWeakSeed += 0x78A8C4B7; // Prime number
|
||||||
|
s32 ^= g_iWeakSeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent overflow in the Random constructor of .NET 2.0
|
||||||
|
if (s32 == int.MinValue) s32 = int.MaxValue;
|
||||||
|
|
||||||
|
return new Random(s32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2020 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,18 +20,57 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
#if !KeePassUAP
|
#if !KeePassUAP
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using KeePassLib.Native;
|
||||||
using KeePassLib.Utility;
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
namespace KeePassLib.Cryptography
|
namespace KeePassLib.Cryptography
|
||||||
{
|
{
|
||||||
public static class CryptoUtil
|
public static class CryptoUtil
|
||||||
{
|
{
|
||||||
|
private static bool? g_obProtData = null;
|
||||||
|
public static bool IsProtectedDataSupported
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (g_obProtData.HasValue) return g_obProtData.Value;
|
||||||
|
|
||||||
|
bool b = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Random r = CryptoRandom.NewWeakRandom();
|
||||||
|
|
||||||
|
byte[] pbData = new byte[137];
|
||||||
|
r.NextBytes(pbData);
|
||||||
|
|
||||||
|
byte[] pbEnt = new byte[41];
|
||||||
|
r.NextBytes(pbEnt);
|
||||||
|
|
||||||
|
byte[] pbEnc = ProtectedData.Protect(pbData, pbEnt,
|
||||||
|
DataProtectionScope.CurrentUser);
|
||||||
|
if ((pbEnc != null) && !MemUtil.ArraysEqual(pbEnc, pbData))
|
||||||
|
{
|
||||||
|
byte[] pbDec = ProtectedData.Unprotect(pbEnc, pbEnt,
|
||||||
|
DataProtectionScope.CurrentUser);
|
||||||
|
if ((pbDec != null) && MemUtil.ArraysEqual(pbDec, pbData))
|
||||||
|
b = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception) { Debug.Assert(false); }
|
||||||
|
|
||||||
|
Debug.Assert(b); // Should be supported on all systems
|
||||||
|
g_obProtData = b;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] HashSha256(byte[] pbData)
|
public static byte[] HashSha256(byte[] pbData)
|
||||||
{
|
{
|
||||||
if (pbData == null) throw new ArgumentNullException("pbData");
|
if (pbData == null) throw new ArgumentNullException("pbData");
|
||||||
@@ -66,6 +105,22 @@ namespace KeePassLib.Cryptography
|
|||||||
return pbHash;
|
return pbHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static byte[] HashSha256(string strFilePath)
|
||||||
|
{
|
||||||
|
byte[] pbHash = null;
|
||||||
|
|
||||||
|
using (FileStream fs = new FileStream(strFilePath, FileMode.Open,
|
||||||
|
FileAccess.Read, FileShare.Read))
|
||||||
|
{
|
||||||
|
using (SHA256Managed h = new SHA256Managed())
|
||||||
|
{
|
||||||
|
pbHash = h.ComputeHash(fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pbHash;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a cryptographic key of length <paramref name="cbOut" />
|
/// Create a cryptographic key of length <paramref name="cbOut" />
|
||||||
/// (in bytes) from <paramref name="pbIn" />.
|
/// (in bytes) from <paramref name="pbIn" />.
|
||||||
@@ -125,5 +180,75 @@ namespace KeePassLib.Cryptography
|
|||||||
MemUtil.ZeroByteArray(pbHash);
|
MemUtil.ZeroByteArray(pbHash);
|
||||||
return pbRet;
|
return pbRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !KeePassUAP
|
||||||
|
private static bool? g_obAesCsp = null;
|
||||||
|
internal static SymmetricAlgorithm CreateAes()
|
||||||
|
{
|
||||||
|
if (g_obAesCsp.HasValue)
|
||||||
|
return (g_obAesCsp.Value ? CreateAesCsp() : new RijndaelManaged());
|
||||||
|
|
||||||
|
SymmetricAlgorithm a = CreateAesCsp();
|
||||||
|
g_obAesCsp = (a != null);
|
||||||
|
return (a ?? new RijndaelManaged());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SymmetricAlgorithm CreateAesCsp()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// On Windows, the CSP implementation is only minimally
|
||||||
|
// faster (and for key derivations it's not used anyway,
|
||||||
|
// as KeePass uses a native implementation based on
|
||||||
|
// CNG/BCrypt, which is much faster)
|
||||||
|
if (!NativeLib.IsUnix()) return null;
|
||||||
|
|
||||||
|
string strFqn = Assembly.CreateQualifiedName(
|
||||||
|
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
|
||||||
|
"System.Security.Cryptography.AesCryptoServiceProvider");
|
||||||
|
|
||||||
|
Type t = Type.GetType(strFqn);
|
||||||
|
if (t == null) return null;
|
||||||
|
|
||||||
|
return (Activator.CreateInstance(t) as SymmetricAlgorithm);
|
||||||
|
}
|
||||||
|
catch (Exception) { Debug.Assert(false); }
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static byte[] ProtectData(byte[] pb, byte[] pbOptEntropy,
|
||||||
|
DataProtectionScope s)
|
||||||
|
{
|
||||||
|
return ProtectDataPriv(pb, true, pbOptEntropy, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] UnprotectData(byte[] pb, byte[] pbOptEntropy,
|
||||||
|
DataProtectionScope s)
|
||||||
|
{
|
||||||
|
return ProtectDataPriv(pb, false, pbOptEntropy, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ProtectDataPriv(byte[] pb, bool bProtect,
|
||||||
|
byte[] pbOptEntropy, DataProtectionScope s)
|
||||||
|
{
|
||||||
|
if (pb == null) throw new ArgumentNullException("pb");
|
||||||
|
|
||||||
|
if ((pbOptEntropy != null) && (pbOptEntropy.Length == 0))
|
||||||
|
pbOptEntropy = null;
|
||||||
|
|
||||||
|
if (CryptoUtil.IsProtectedDataSupported)
|
||||||
|
{
|
||||||
|
if (bProtect)
|
||||||
|
return ProtectedData.Protect(pb, pbOptEntropy, s);
|
||||||
|
return ProtectedData.Unprotect(pb, pbOptEntropy, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Assert(false);
|
||||||
|
byte[] pbCopy = new byte[pb.Length];
|
||||||
|
Array.Copy(pb, pbCopy, pb.Length);
|
||||||
|
return pbCopy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using keepass2android;
|
||||||
#if KeePassUAP
|
#if KeePassUAP
|
||||||
using Org.BouncyCastle.Crypto;
|
using Org.BouncyCastle.Crypto;
|
||||||
using Org.BouncyCastle.Crypto.Engines;
|
using Org.BouncyCastle.Crypto.Engines;
|
||||||
@@ -55,6 +55,9 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
get { return "AES-KDF"; }
|
get { return "AES-KDF"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override byte[] GetSeed(KdfParameters p)
|
||||||
|
{ return p.GetByteArray(ParamSeed); }
|
||||||
|
|
||||||
public AesKdf()
|
public AesKdf()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -141,6 +144,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
|
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
|
||||||
ulong uNumRounds)
|
ulong uNumRounds)
|
||||||
{
|
{
|
||||||
|
Kp2aLog.Log("Warning: transforming key managed. Expect this to be slow!");
|
||||||
#if KeePassUAP
|
#if KeePassUAP
|
||||||
KeyParameter kp = new KeyParameter(pbKeySeed32);
|
KeyParameter kp = new KeyParameter(pbKeySeed32);
|
||||||
AesEngine aes = new AesEngine();
|
AesEngine aes = new AesEngine();
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
private const ulong NbBlockSizeInQW = NbBlockSize / 8UL;
|
private const ulong NbBlockSizeInQW = NbBlockSize / 8UL;
|
||||||
private const ulong NbSyncPoints = 4;
|
private const ulong NbSyncPoints = 4;
|
||||||
|
|
||||||
|
private const ulong NbAddressesInBlock = 128;
|
||||||
|
|
||||||
private const int NbPreHashDigestLength = 64;
|
private const int NbPreHashDigestLength = 64;
|
||||||
private const int NbPreHashSeedLength = NbPreHashDigestLength + 8;
|
private const int NbPreHashSeedLength = NbPreHashDigestLength + 8;
|
||||||
|
|
||||||
@@ -56,6 +58,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
|
|
||||||
private sealed class Argon2Ctx
|
private sealed class Argon2Ctx
|
||||||
{
|
{
|
||||||
|
public Argon2Type Type = Argon2Type.D;
|
||||||
public uint Version = 0;
|
public uint Version = 0;
|
||||||
|
|
||||||
public ulong Lanes = 0;
|
public ulong Lanes = 0;
|
||||||
@@ -89,7 +92,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] Argon2d(byte[] pbMsg, byte[] pbSalt, uint uParallel,
|
private byte[] Argon2Transform(byte[] pbMsg, byte[] pbSalt, uint uParallel,
|
||||||
ulong uMem, ulong uIt, int cbOut, uint uVersion, byte[] pbSecretKey,
|
ulong uMem, ulong uIt, int cbOut, uint uVersion, byte[] pbSecretKey,
|
||||||
byte[] pbAssocData)
|
byte[] pbAssocData)
|
||||||
{
|
{
|
||||||
@@ -101,6 +104,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Argon2Ctx ctx = new Argon2Ctx();
|
Argon2Ctx ctx = new Argon2Ctx();
|
||||||
|
ctx.Type = m_t;
|
||||||
ctx.Version = uVersion;
|
ctx.Version = uVersion;
|
||||||
|
|
||||||
ctx.Lanes = uParallel;
|
ctx.Lanes = uParallel;
|
||||||
@@ -137,7 +141,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
||||||
MemUtil.UInt32ToBytesEx(uVersion, pbBuf, 0);
|
MemUtil.UInt32ToBytesEx(uVersion, pbBuf, 0);
|
||||||
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
||||||
MemUtil.UInt32ToBytesEx(0, pbBuf, 0); // Argon2d type = 0
|
MemUtil.UInt32ToBytesEx((uint)m_t, pbBuf, 0);
|
||||||
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
||||||
MemUtil.UInt32ToBytesEx((uint)pbMsg.Length, pbBuf, 0);
|
MemUtil.UInt32ToBytesEx((uint)pbMsg.Length, pbBuf, 0);
|
||||||
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
h.TransformBlock(pbBuf, 0, pbBuf.Length, pbBuf, 0);
|
||||||
@@ -497,8 +501,33 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
Debug.Assert(ctx.Version >= MinVersion);
|
Debug.Assert(ctx.Version >= MinVersion);
|
||||||
bool bCanXor = (ctx.Version >= 0x13U);
|
bool bCanXor = (ctx.Version >= 0x13U);
|
||||||
|
|
||||||
|
ulong[] pbR = new ulong[NbBlockSizeInQW];
|
||||||
|
ulong[] pbTmp = new ulong[NbBlockSizeInQW];
|
||||||
|
ulong[] pbAddrInputZero = null;
|
||||||
|
|
||||||
|
bool bDataIndependentAddr = ((ctx.Type == Argon2Type.ID) &&
|
||||||
|
(ti.Pass == 0) && (ti.Slice < (NbSyncPoints / 2)));
|
||||||
|
if (bDataIndependentAddr)
|
||||||
|
{
|
||||||
|
pbAddrInputZero = new ulong[NbBlockSizeInQW * 3];
|
||||||
|
|
||||||
|
const int iInput = (int)NbBlockSizeInQW;
|
||||||
|
pbAddrInputZero[iInput] = ti.Pass;
|
||||||
|
pbAddrInputZero[iInput + 1] = ti.Lane;
|
||||||
|
pbAddrInputZero[iInput + 2] = ti.Slice;
|
||||||
|
pbAddrInputZero[iInput + 3] = ctx.MemoryBlocks;
|
||||||
|
pbAddrInputZero[iInput + 4] = ctx.TCost;
|
||||||
|
pbAddrInputZero[iInput + 5] = (ulong)ctx.Type;
|
||||||
|
}
|
||||||
|
|
||||||
ulong uStart = 0;
|
ulong uStart = 0;
|
||||||
if((ti.Pass == 0) && (ti.Slice == 0)) uStart = 2;
|
if ((ti.Pass == 0) && (ti.Slice == 0))
|
||||||
|
{
|
||||||
|
uStart = 2;
|
||||||
|
|
||||||
|
if (bDataIndependentAddr)
|
||||||
|
NextAddresses(pbAddrInputZero, pbR, pbTmp);
|
||||||
|
}
|
||||||
|
|
||||||
ulong uCur = (ti.Lane * ctx.LaneLength) + (ti.Slice *
|
ulong uCur = (ti.Lane * ctx.LaneLength) + (ti.Slice *
|
||||||
ctx.SegmentLength) + uStart;
|
ctx.SegmentLength) + uStart;
|
||||||
@@ -506,15 +535,21 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
ulong uPrev = (((uCur % ctx.LaneLength) == 0) ?
|
ulong uPrev = (((uCur % ctx.LaneLength) == 0) ?
|
||||||
(uCur + ctx.LaneLength - 1UL) : (uCur - 1UL));
|
(uCur + ctx.LaneLength - 1UL) : (uCur - 1UL));
|
||||||
|
|
||||||
ulong[] pbR = new ulong[NbBlockSizeInQW];
|
|
||||||
ulong[] pbTmp = new ulong[NbBlockSizeInQW];
|
|
||||||
|
|
||||||
for (ulong i = uStart; i < ctx.SegmentLength; ++i)
|
for (ulong i = uStart; i < ctx.SegmentLength; ++i)
|
||||||
{
|
{
|
||||||
if ((uCur % ctx.LaneLength) == 1)
|
if ((uCur % ctx.LaneLength) == 1)
|
||||||
uPrev = uCur - 1UL;
|
uPrev = uCur - 1UL;
|
||||||
|
|
||||||
ulong uPseudoRand = ctx.Mem[uPrev * NbBlockSizeInQW];
|
ulong uPseudoRand;
|
||||||
|
if (bDataIndependentAddr)
|
||||||
|
{
|
||||||
|
ulong iMod = i % NbAddressesInBlock;
|
||||||
|
if (iMod == 0)
|
||||||
|
NextAddresses(pbAddrInputZero, pbR, pbTmp);
|
||||||
|
uPseudoRand = pbAddrInputZero[iMod];
|
||||||
|
}
|
||||||
|
else uPseudoRand = ctx.Mem[uPrev * NbBlockSizeInQW];
|
||||||
|
|
||||||
ulong uRefLane = (uPseudoRand >> 32) % ctx.Lanes;
|
ulong uRefLane = (uPseudoRand >> 32) % ctx.Lanes;
|
||||||
if ((ti.Pass == 0) && (ti.Slice == 0))
|
if ((ti.Pass == 0) && (ti.Slice == 0))
|
||||||
uRefLane = ti.Lane;
|
uRefLane = ti.Lane;
|
||||||
@@ -536,6 +571,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
|
|
||||||
MemUtil.ZeroArray<ulong>(pbR);
|
MemUtil.ZeroArray<ulong>(pbR);
|
||||||
MemUtil.ZeroArray<ulong>(pbTmp);
|
MemUtil.ZeroArray<ulong>(pbTmp);
|
||||||
|
if (pbAddrInputZero != null) MemUtil.ZeroArray<ulong>(pbAddrInputZero);
|
||||||
}
|
}
|
||||||
catch (Exception) { Debug.Assert(false); }
|
catch (Exception) { Debug.Assert(false); }
|
||||||
|
|
||||||
@@ -610,6 +646,19 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
XorBlock(pMem, uNext, pbR, 0);
|
XorBlock(pMem, uNext, pbR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void NextAddresses(ulong[] pbAddrInputZero, ulong[] pbR,
|
||||||
|
ulong[] pbTmp)
|
||||||
|
{
|
||||||
|
// pbAddrInputZero contains an address block, an input block and a zero block
|
||||||
|
const ulong uAddr = 0;
|
||||||
|
const ulong uInput = NbBlockSizeInQW;
|
||||||
|
const ulong uZero = NbBlockSizeInQW * 2;
|
||||||
|
|
||||||
|
++pbAddrInputZero[uInput + 6];
|
||||||
|
FillBlock(pbAddrInputZero, uZero, uInput, uAddr, false, pbR, pbTmp);
|
||||||
|
FillBlock(pbAddrInputZero, uZero, uAddr, uAddr, false, pbR, pbTmp);
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] FinalHash(Argon2Ctx ctx, int cbOut, Blake2b h)
|
private static byte[] FinalHash(Argon2Ctx ctx, int cbOut, Blake2b h)
|
||||||
{
|
{
|
||||||
ulong[] pqBlockHash = new ulong[NbBlockSizeInQW];
|
ulong[] pqBlockHash = new ulong[NbBlockSizeInQW];
|
||||||
|
|||||||
@@ -20,15 +20,27 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace KeePassLib.Cryptography.KeyDerivation
|
namespace KeePassLib.Cryptography.KeyDerivation
|
||||||
{
|
{
|
||||||
|
public enum Argon2Type
|
||||||
|
{
|
||||||
|
// The values must be the same as in the Argon2 specification
|
||||||
|
D = 0,
|
||||||
|
ID = 2
|
||||||
|
}
|
||||||
public sealed partial class Argon2Kdf : KdfEngine
|
public sealed partial class Argon2Kdf : KdfEngine
|
||||||
{
|
{
|
||||||
private static readonly PwUuid g_uuid = new PwUuid(new byte[] {
|
|
||||||
|
|
||||||
|
private static readonly PwUuid g_uuidD = new PwUuid(new byte[] {
|
||||||
0xEF, 0x63, 0x6D, 0xDF, 0x8C, 0x29, 0x44, 0x4B,
|
0xEF, 0x63, 0x6D, 0xDF, 0x8C, 0x29, 0x44, 0x4B,
|
||||||
0x91, 0xF7, 0xA9, 0xA4, 0x03, 0xE3, 0x0A, 0x0C });
|
0x91, 0xF7, 0xA9, 0xA4, 0x03, 0xE3, 0x0A, 0x0C });
|
||||||
|
private static readonly PwUuid g_uuidID = new PwUuid(new byte[] {
|
||||||
|
0x9E, 0x29, 0x8B, 0x19, 0x56, 0xDB, 0x47, 0x73,
|
||||||
|
0xB2, 0x3D, 0xFC, 0x3E, 0xC6, 0xF0, 0xA1, 0xE6 });
|
||||||
|
|
||||||
public const string ParamSalt = "S"; // Byte[]
|
public const string ParamSalt = "S"; // Byte[]
|
||||||
public const string ParamParallelism = "P"; // UInt32
|
public const string ParamParallelism = "P"; // UInt32
|
||||||
@@ -55,23 +67,35 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
internal const uint MaxParallelism = (1 << 24) - 1;
|
internal const uint MaxParallelism = (1 << 24) - 1;
|
||||||
|
|
||||||
internal const ulong DefaultIterations = 2;
|
internal const ulong DefaultIterations = 2;
|
||||||
internal const ulong DefaultMemory = 1024 * 1024; // 1 MB
|
internal const ulong DefaultMemory = 64 * 1024 * 1024; // 64 MB
|
||||||
internal const uint DefaultParallelism = 2;
|
internal const uint DefaultParallelism = 2;
|
||||||
|
|
||||||
|
private readonly Argon2Type m_t;
|
||||||
|
|
||||||
public override PwUuid Uuid
|
public override PwUuid Uuid
|
||||||
{
|
{
|
||||||
get { return g_uuid; }
|
get { return ((m_t == Argon2Type.D) ? g_uuidD : g_uuidID); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Name
|
public override string Name
|
||||||
{
|
{
|
||||||
get { return "Argon2"; }
|
get { return ((m_t == Argon2Type.D) ? "Argon2d" : "Argon2id"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Argon2Kdf()
|
public Argon2Kdf() : this(Argon2Type.D)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Argon2Kdf(Argon2Type t)
|
||||||
|
{
|
||||||
|
if ((t != Argon2Type.D) && (t != Argon2Type.ID))
|
||||||
|
throw new NotSupportedException();
|
||||||
|
|
||||||
|
m_t = t;
|
||||||
|
}
|
||||||
|
public override byte[] GetSeed(KdfParameters p)
|
||||||
|
{ return p.GetByteArray(ParamSalt); }
|
||||||
|
|
||||||
public override KdfParameters GetDefaultParameters()
|
public override KdfParameters GetDefaultParameters()
|
||||||
{
|
{
|
||||||
KdfParameters p = base.GetDefaultParameters();
|
KdfParameters p = base.GetDefaultParameters();
|
||||||
@@ -88,7 +112,7 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
public override void Randomize(KdfParameters p)
|
public override void Randomize(KdfParameters p)
|
||||||
{
|
{
|
||||||
if(p == null) { Debug.Assert(false); return; }
|
if(p == null) { Debug.Assert(false); return; }
|
||||||
Debug.Assert(g_uuid.Equals(p.KdfUuid));
|
Debug.Assert(p.KdfUuid.Equals(this.Uuid));
|
||||||
|
|
||||||
byte[] pb = CryptoRandom.Instance.GetRandomBytes(32);
|
byte[] pb = CryptoRandom.Instance.GetRandomBytes(32);
|
||||||
p.SetByteArray(ParamSalt, pb);
|
p.SetByteArray(ParamSalt, pb);
|
||||||
@@ -124,8 +148,57 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
byte[] pbSecretKey = p.GetByteArray(ParamSecretKey);
|
byte[] pbSecretKey = p.GetByteArray(ParamSecretKey);
|
||||||
byte[] pbAssocData = p.GetByteArray(ParamAssocData);
|
byte[] pbAssocData = p.GetByteArray(ParamAssocData);
|
||||||
|
|
||||||
|
byte[] pbRet;
|
||||||
|
|
||||||
|
if (m_t == Argon2Type.ID)
|
||||||
|
{
|
||||||
|
pbRet = Argon2Transform(pbMsg, pbSalt, uPar, uMem,
|
||||||
|
uIt, 32, v, pbSecretKey, pbAssocData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pbSecretKey != null)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbSecretKey");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pbAssocData != null)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbAssocData");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
byte[] pbRet = Argon2d(pbMsg, pbSalt, uPar, uMem, uIt,
|
byte[] pbRet = Argon2d(pbMsg, pbSalt, uPar, uMem, uIt,
|
||||||
32, v, pbSecretKey, pbAssocData);
|
32, v, pbSecretKey, pbAssocData);
|
||||||
|
*/
|
||||||
|
|
||||||
|
IntPtr msgPtr = Marshal.AllocHGlobal(pbMsg.Length);
|
||||||
|
IntPtr saltPtr = Marshal.AllocHGlobal(pbSalt.Length);
|
||||||
|
IntPtr retPtr = Marshal.AllocHGlobal(32);
|
||||||
|
Marshal.Copy(pbMsg, 0, msgPtr, pbMsg.Length);
|
||||||
|
Marshal.Copy(pbSalt, 0, saltPtr, pbSalt.Length);
|
||||||
|
|
||||||
|
const UInt32 Argon2_d = 0;
|
||||||
|
|
||||||
|
int ret = argon2_hash(
|
||||||
|
(UInt32)uIt, (UInt32)(uMem / 1024), uPar,
|
||||||
|
msgPtr, (IntPtr)pbMsg.Length,
|
||||||
|
saltPtr, (IntPtr)pbSalt.Length,
|
||||||
|
retPtr, (IntPtr)32,
|
||||||
|
(IntPtr)0, (IntPtr)0, Argon2_d, v);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
throw new Exception("argon2_hash failed with " + ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
pbRet = new byte[32];
|
||||||
|
Marshal.Copy(retPtr, pbRet, 0, 32);
|
||||||
|
|
||||||
|
Marshal.FreeHGlobal(msgPtr);
|
||||||
|
Marshal.FreeHGlobal(saltPtr);
|
||||||
|
Marshal.FreeHGlobal(retPtr);
|
||||||
|
}
|
||||||
|
|
||||||
if(uMem > (100UL * 1024UL * 1024UL)) GC.Collect();
|
if(uMem > (100UL * 1024UL * 1024UL)) GC.Collect();
|
||||||
return pbRet;
|
return pbRet;
|
||||||
@@ -140,5 +213,14 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
MaxIterations, uMilliseconds, true);
|
MaxIterations, uMilliseconds, true);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DllImport("argon2")]
|
||||||
|
static extern int argon2_hash(
|
||||||
|
UInt32 t_cost, UInt32 m_cost, UInt32 parallelism,
|
||||||
|
IntPtr pwd, IntPtr pwdlen,
|
||||||
|
IntPtr salt, IntPtr saltlen,
|
||||||
|
IntPtr hash, IntPtr hashlen,
|
||||||
|
IntPtr encoded, IntPtr encodedlen,
|
||||||
|
UInt32 type, UInt32 version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract byte[] GetSeed(KdfParameters p);
|
||||||
|
|
||||||
public virtual KdfParameters GetDefaultParameters()
|
public virtual KdfParameters GetDefaultParameters()
|
||||||
{
|
{
|
||||||
return new KdfParameters(this.Uuid);
|
return new KdfParameters(this.Uuid);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2020 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2020 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -41,10 +41,11 @@ namespace KeePassLib.Cryptography.KeyDerivation
|
|||||||
|
|
||||||
private static void EnsureInitialized()
|
private static void EnsureInitialized()
|
||||||
{
|
{
|
||||||
if(g_l.Count > 0) return;
|
if(g_l.Count != 0) return;
|
||||||
|
|
||||||
g_l.Add(new AesKdf());
|
g_l.Add(new AesKdf());
|
||||||
g_l.Add(new Argon2Kdf());
|
g_l.Add(new Argon2Kdf(Argon2Type.D));
|
||||||
|
g_l.Add(new Argon2Kdf(Argon2Type.ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static KdfParameters GetDefaultParameters()
|
internal static KdfParameters GetDefaultParameters()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,5 +33,10 @@ namespace KeePassLib.Interfaces
|
|||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PwUuid PreviousParentGroup
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||||
<AndroidResgenClass>Resource</AndroidResgenClass>
|
<AndroidResgenClass>Resource</AndroidResgenClass>
|
||||||
<AssemblyName>KeePassLib2Android</AssemblyName>
|
<AssemblyName>KeePassLib2Android</AssemblyName>
|
||||||
<TargetFrameworkVersion>v7.1</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
|
||||||
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk>
|
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||||
<NuGetPackageImportStamp>8482b288</NuGetPackageImportStamp>
|
<NuGetPackageImportStamp>8482b288</NuGetPackageImportStamp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
<HintPath>..\ProtoBuf\protobuf-net.dll</HintPath>
|
<HintPath>..\ProtoBuf\protobuf-net.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Security" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="Mono.Android" />
|
<Reference Include="Mono.Android" />
|
||||||
@@ -71,7 +72,9 @@
|
|||||||
<Compile Include="Cryptography\KeyDerivation\KdfParameters.cs" />
|
<Compile Include="Cryptography\KeyDerivation\KdfParameters.cs" />
|
||||||
<Compile Include="Cryptography\KeyDerivation\KdfPool.cs" />
|
<Compile Include="Cryptography\KeyDerivation\KdfPool.cs" />
|
||||||
<Compile Include="IDatabaseFormat.cs" />
|
<Compile Include="IDatabaseFormat.cs" />
|
||||||
|
<Compile Include="Keys\KcpKeyFile.Xml.cs" />
|
||||||
<Compile Include="Kp2aLog.cs" />
|
<Compile Include="Kp2aLog.cs" />
|
||||||
|
<Compile Include="PwGroup.Search.cs" />
|
||||||
<Compile Include="Resources\Resource.designer.cs" />
|
<Compile Include="Resources\Resource.designer.cs" />
|
||||||
<Compile Include="Resources\KLRes.Generated.cs" />
|
<Compile Include="Resources\KLRes.Generated.cs" />
|
||||||
<Compile Include="Resources\KSRes.Generated.cs" />
|
<Compile Include="Resources\KSRes.Generated.cs" />
|
||||||
@@ -160,6 +163,7 @@
|
|||||||
<Compile Include="Utility\UrlUtil.cs" />
|
<Compile Include="Utility\UrlUtil.cs" />
|
||||||
<Compile Include="Utility\TimeUtil.cs" />
|
<Compile Include="Utility\TimeUtil.cs" />
|
||||||
<Compile Include="Delegates\Handlers.cs" />
|
<Compile Include="Delegates\Handlers.cs" />
|
||||||
|
<Compile Include="Utility\XmlUtilEx.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
|||||||
@@ -20,11 +20,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
using KeePassLib.Cryptography;
|
using KeePassLib.Cryptography;
|
||||||
using KeePassLib.Cryptography.KeyDerivation;
|
using KeePassLib.Cryptography.KeyDerivation;
|
||||||
using KeePassLib.Native;
|
|
||||||
using KeePassLib.Resources;
|
using KeePassLib.Resources;
|
||||||
using KeePassLib.Security;
|
using KeePassLib.Security;
|
||||||
using KeePassLib.Utility;
|
using KeePassLib.Utility;
|
||||||
@@ -168,7 +165,7 @@ namespace KeePassLib.Keys
|
|||||||
/// Creates the composite key from the supplied user key sources (password,
|
/// Creates the composite key from the supplied user key sources (password,
|
||||||
/// key file, user account, computer ID, etc.).
|
/// key file, user account, computer ID, etc.).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed)
|
private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed, byte[] mPbKdfSeed)
|
||||||
{
|
{
|
||||||
ValidateUserKeys();
|
ValidateUserKeys();
|
||||||
|
|
||||||
@@ -178,7 +175,7 @@ namespace KeePassLib.Keys
|
|||||||
foreach(IUserKey pKey in m_vUserKeys)
|
foreach(IUserKey pKey in m_vUserKeys)
|
||||||
{
|
{
|
||||||
if (pKey is ISeedBasedUserKey)
|
if (pKey is ISeedBasedUserKey)
|
||||||
((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed);
|
((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed, mPbKdfSeed);
|
||||||
ProtectedBinary b = pKey.KeyData;
|
ProtectedBinary b = pKey.KeyData;
|
||||||
if(b != null)
|
if(b != null)
|
||||||
{
|
{
|
||||||
@@ -211,9 +208,6 @@ namespace KeePassLib.Keys
|
|||||||
{
|
{
|
||||||
if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); }
|
if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); }
|
||||||
|
|
||||||
byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed);
|
|
||||||
if((pbRaw32 == null) || (pbRaw32.Length != 32))
|
|
||||||
{ Debug.Assert(false); return null; }
|
|
||||||
|
|
||||||
KdfEngine kdf = KdfPool.Get(p.KdfUuid);
|
KdfEngine kdf = KdfPool.Get(p.KdfUuid);
|
||||||
if (kdf == null) // CryptographicExceptions are translated to "file corrupted"
|
if (kdf == null) // CryptographicExceptions are translated to "file corrupted"
|
||||||
@@ -221,6 +215,11 @@ namespace KeePassLib.Keys
|
|||||||
KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
|
KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
|
||||||
"UUID: " + p.KdfUuid.ToHexString() + ".");
|
"UUID: " + p.KdfUuid.ToHexString() + ".");
|
||||||
|
|
||||||
|
byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed, kdf.GetSeed(p));
|
||||||
|
if((pbRaw32 == null) || (pbRaw32.Length != 32))
|
||||||
|
{ Debug.Assert(false); return null; }
|
||||||
|
|
||||||
|
|
||||||
byte[] pbTrf32 = kdf.Transform(pbRaw32, p);
|
byte[] pbTrf32 = kdf.Transform(pbRaw32, p);
|
||||||
if(pbTrf32 == null) { Debug.Assert(false); return null; }
|
if(pbTrf32 == null) { Debug.Assert(false); return null; }
|
||||||
|
|
||||||
@@ -256,7 +255,7 @@ namespace KeePassLib.Keys
|
|||||||
|
|
||||||
public interface ISeedBasedUserKey
|
public interface ISeedBasedUserKey
|
||||||
{
|
{
|
||||||
void SetParams(byte[] masterSeed);
|
void SetParams(byte[] masterSeed, byte[] mPbKdfSeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class InvalidCompositeKeyException : Exception
|
public sealed class InvalidCompositeKeyException : Exception
|
||||||
|
|||||||
@@ -42,5 +42,7 @@ namespace KeePassLib.Keys
|
|||||||
// /// Clear the key and securely erase all security-critical information.
|
// /// Clear the key and securely erase all security-critical information.
|
||||||
// /// </summary>
|
// /// </summary>
|
||||||
// void Clear();
|
// void Clear();
|
||||||
|
|
||||||
|
uint GetMinKdbxVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ namespace KeePassLib.Keys
|
|||||||
get { return m_pbKey; }
|
get { return m_pbKey; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint GetMinKdbxVersion()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash)
|
public KcpCustomKey(string strName, byte[] pbKeyData, bool bPerformHash)
|
||||||
{
|
{
|
||||||
Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName");
|
Debug.Assert(strName != null); if(strName == null) throw new ArgumentNullException("strName");
|
||||||
|
|||||||
281
src/KeePassLib2Android/Keys/KcpKeyFile.Xml.cs
Normal file
281
src/KeePassLib2Android/Keys/KcpKeyFile.Xml.cs
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
using KeePassLib.Resources;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
|
namespace KeePassLib.Keys
|
||||||
|
{
|
||||||
|
[XmlType("KeyFile")]
|
||||||
|
public sealed class KfxFile
|
||||||
|
{
|
||||||
|
private const ulong KfxVersionCriticalMask = 0xFFFF000000000000UL;
|
||||||
|
private const int KfxDataHashLength = 4;
|
||||||
|
|
||||||
|
private KfxMeta m_meta = new KfxMeta();
|
||||||
|
public KfxMeta Meta
|
||||||
|
{
|
||||||
|
get { return m_meta; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(value == null) throw new ArgumentNullException("value");
|
||||||
|
m_meta = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private KfxKey m_key = new KfxKey();
|
||||||
|
public KfxKey Key
|
||||||
|
{
|
||||||
|
get { return m_key; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(value == null) throw new ArgumentNullException("value");
|
||||||
|
m_key = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KfxFile Create(ulong uVersion, byte[] pbKey, byte[] pbHash)
|
||||||
|
{
|
||||||
|
if(pbKey == null) throw new ArgumentNullException("pbKey");
|
||||||
|
if(pbKey.Length == 0) throw new ArgumentOutOfRangeException("pbKey");
|
||||||
|
|
||||||
|
if(uVersion == 0) uVersion = 0x0002000000000000;
|
||||||
|
|
||||||
|
// Null hash: generate one, empty hash: store no hash
|
||||||
|
if(pbHash == null) pbHash = HashData(pbKey);
|
||||||
|
VerifyHash(pbKey, pbHash);
|
||||||
|
|
||||||
|
KfxFile kf = new KfxFile();
|
||||||
|
|
||||||
|
if(uVersion == 0x0001000000000000)
|
||||||
|
kf.Meta.Version = "1.00"; // KeePass <= 2.46 used two zeros
|
||||||
|
else kf.Meta.Version = StrUtil.VersionToString(uVersion, 2);
|
||||||
|
|
||||||
|
if(uVersion == 0x0001000000000000)
|
||||||
|
kf.Key.Data.Value = Convert.ToBase64String(pbKey);
|
||||||
|
else if(uVersion == 0x0002000000000000)
|
||||||
|
{
|
||||||
|
kf.Key.Data.Value = FormatKeyHex(pbKey, 3);
|
||||||
|
|
||||||
|
if(pbHash.Length != 0)
|
||||||
|
kf.Key.Data.Hash = MemUtil.ByteArrayToHexString(pbHash);
|
||||||
|
}
|
||||||
|
else throw new NotSupportedException(KLRes.FileVersionUnsupported);
|
||||||
|
|
||||||
|
return kf;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static KfxFile Create(ulong uVersion, string strKey, string strHash)
|
||||||
|
{
|
||||||
|
byte[] pbKey = ParseKey(uVersion, strKey);
|
||||||
|
byte[] pbHash = ((strHash != null) ? ParseHash(strHash) : null);
|
||||||
|
|
||||||
|
return Create(uVersion, pbKey, pbHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool CanLoad(string strFilePath)
|
||||||
|
{
|
||||||
|
if(string.IsNullOrEmpty(strFilePath)) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFilePath);
|
||||||
|
using(Stream s = IOConnection.OpenRead(ioc))
|
||||||
|
{
|
||||||
|
return (Load(s) != null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception) { }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KfxFile Load(Stream s)
|
||||||
|
{
|
||||||
|
return XmlUtilEx.Deserialize<KfxFile>(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(Stream s)
|
||||||
|
{
|
||||||
|
XmlUtilEx.Serialize<KfxFile>(s, this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatKeyHex(byte[] pb, int cTabs)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
string str = MemUtil.ByteArrayToHexString(pb);
|
||||||
|
|
||||||
|
for(int i = 0; i < str.Length; ++i)
|
||||||
|
{
|
||||||
|
if((i & 0x1F) == 0)
|
||||||
|
{
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.Append('\t', cTabs);
|
||||||
|
}
|
||||||
|
else if((i & 0x07) == 0) sb.Append(' ');
|
||||||
|
|
||||||
|
sb.Append(str[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
if(cTabs > 0) sb.Append('\t', cTabs - 1);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong GetVersion()
|
||||||
|
{
|
||||||
|
string str = m_meta.Version;
|
||||||
|
if(string.IsNullOrEmpty(str)) return 0;
|
||||||
|
|
||||||
|
return StrUtil.ParseVersion(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetKey()
|
||||||
|
{
|
||||||
|
ulong uVersion = GetVersion();
|
||||||
|
|
||||||
|
byte[] pbKey = ParseKey(uVersion, m_key.Data.Value);
|
||||||
|
if((pbKey == null) || (pbKey.Length == 0))
|
||||||
|
throw new FormatException(KLRes.FileCorrupted);
|
||||||
|
|
||||||
|
byte[] pbHash = ParseHash(m_key.Data.Hash);
|
||||||
|
VerifyHash(pbKey, pbHash);
|
||||||
|
|
||||||
|
return pbKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] HashData(byte[] pb)
|
||||||
|
{
|
||||||
|
return MemUtil.Mid(CryptoUtil.HashSha256(pb), 0, KfxDataHashLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void VerifyHash(byte[] pbKey, byte[] pbHash)
|
||||||
|
{
|
||||||
|
// The hash is optional; empty hash means success
|
||||||
|
if((pbHash == null) || (pbHash.Length == 0)) return;
|
||||||
|
|
||||||
|
byte[] pbHashCmp = HashData(pbKey);
|
||||||
|
if(!MemUtil.ArraysEqual(pbHash, pbHashCmp))
|
||||||
|
throw new Exception("Keyfile hash mismatch!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ParseKey(ulong uVersion, string strKey)
|
||||||
|
{
|
||||||
|
if(strKey == null) throw new ArgumentNullException("strKey");
|
||||||
|
|
||||||
|
strKey = StrUtil.RemoveWhiteSpace(strKey);
|
||||||
|
if(string.IsNullOrEmpty(strKey)) return MemUtil.EmptyByteArray;
|
||||||
|
|
||||||
|
uVersion &= KfxVersionCriticalMask;
|
||||||
|
|
||||||
|
byte[] pbKey;
|
||||||
|
if(uVersion == 0x0001000000000000)
|
||||||
|
pbKey = Convert.FromBase64String(strKey);
|
||||||
|
else if(uVersion == 0x0002000000000000)
|
||||||
|
pbKey = ParseHex(strKey);
|
||||||
|
else throw new NotSupportedException(KLRes.FileVersionUnsupported);
|
||||||
|
|
||||||
|
return pbKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ParseHash(string strHash)
|
||||||
|
{
|
||||||
|
return ParseHex(strHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ParseHex(string str)
|
||||||
|
{
|
||||||
|
if(str == null) throw new ArgumentNullException("str");
|
||||||
|
if(str.Length == 0) return MemUtil.EmptyByteArray;
|
||||||
|
|
||||||
|
if(((str.Length & 1) != 0) || !StrUtil.IsHexString(str, true))
|
||||||
|
throw new FormatException();
|
||||||
|
|
||||||
|
return MemUtil.HexStringToByteArray(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class KfxMeta
|
||||||
|
{
|
||||||
|
private string m_strVersion = string.Empty;
|
||||||
|
[DefaultValue("")]
|
||||||
|
public string Version
|
||||||
|
{
|
||||||
|
get { return m_strVersion; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(value == null) throw new ArgumentNullException("value");
|
||||||
|
m_strVersion = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class KfxKey
|
||||||
|
{
|
||||||
|
private KfxData m_data = new KfxData();
|
||||||
|
public KfxData Data
|
||||||
|
{
|
||||||
|
get { return m_data; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(value == null) throw new ArgumentNullException("value");
|
||||||
|
m_data = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class KfxData
|
||||||
|
{
|
||||||
|
private string m_strHash = string.Empty;
|
||||||
|
[DefaultValue("")]
|
||||||
|
[XmlAttribute("Hash")]
|
||||||
|
public string Hash
|
||||||
|
{
|
||||||
|
get { return m_strHash; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(value == null) throw new ArgumentNullException("value");
|
||||||
|
m_strHash = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string m_strValue = string.Empty;
|
||||||
|
[DefaultValue("")]
|
||||||
|
[XmlText]
|
||||||
|
public string Value
|
||||||
|
{
|
||||||
|
get { return m_strValue; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(value == null) throw new ArgumentNullException("value");
|
||||||
|
m_strValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,6 +64,11 @@ namespace KeePassLib.Keys
|
|||||||
get { return m_pbKeyData; }
|
get { return m_pbKeyData; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint GetMinKdbxVersion()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public IOConnectionInfo Ioc
|
public IOConnectionInfo Ioc
|
||||||
{
|
{
|
||||||
get { return m_ioc; }
|
get { return m_ioc; }
|
||||||
@@ -122,8 +127,7 @@ namespace KeePassLib.Keys
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] pbKey = LoadXmlKeyFile(pbFileData);
|
byte[] pbKey = LoadKeyFile(pbFileData);
|
||||||
if(pbKey == null) pbKey = LoadKeyFile(pbFileData);
|
|
||||||
|
|
||||||
if (pbKey == null) throw new InvalidOperationException();
|
if (pbKey == null) throw new InvalidOperationException();
|
||||||
|
|
||||||
@@ -147,52 +151,58 @@ namespace KeePassLib.Keys
|
|||||||
|
|
||||||
private static byte[] LoadKeyFile(byte[] pbFileData)
|
private static byte[] LoadKeyFile(byte[] pbFileData)
|
||||||
{
|
{
|
||||||
if(pbFileData == null) { Debug.Assert(false); return null; }
|
if (pbFileData == null) throw new ArgumentNullException("pbFileData");
|
||||||
|
|
||||||
int iLength = pbFileData.Length;
|
byte[] pbKey = LoadKeyFileXml(pbFileData);
|
||||||
|
if (pbKey != null) return pbKey;
|
||||||
|
|
||||||
byte[] pbKey = null;
|
int cb = pbFileData.Length;
|
||||||
if(iLength == 32) pbKey = LoadBinaryKey32(pbFileData);
|
if (cb == 32) return pbFileData;
|
||||||
else if(iLength == 64) pbKey = LoadHexKey32(pbFileData);
|
|
||||||
|
|
||||||
if(pbKey == null)
|
if (cb == 64)
|
||||||
pbKey = CryptoUtil.HashSha256(pbFileData);
|
{
|
||||||
|
pbKey = LoadKeyFileHex(pbFileData);
|
||||||
return pbKey;
|
if (pbKey != null) return pbKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] LoadBinaryKey32(byte[] pbFileData)
|
return CryptoUtil.HashSha256(pbFileData);
|
||||||
{
|
|
||||||
if(pbFileData == null) { Debug.Assert(false); return null; }
|
|
||||||
if(pbFileData.Length != 32) { Debug.Assert(false); return null; }
|
|
||||||
|
|
||||||
return pbFileData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] LoadHexKey32(byte[] pbFileData)
|
private static byte[] LoadKeyFileXml(byte[] pbFileData)
|
||||||
|
{
|
||||||
|
KfxFile kf;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (MemoryStream ms = new MemoryStream(pbFileData, false))
|
||||||
|
{
|
||||||
|
kf = KfxFile.Load(ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception) { return null; }
|
||||||
|
|
||||||
|
// We have a syntactically valid XML key file;
|
||||||
|
// failing to verify the key should throw an exception
|
||||||
|
return ((kf != null) ? kf.GetKey() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] LoadKeyFileHex(byte[] pbFileData)
|
||||||
{
|
{
|
||||||
if (pbFileData == null) { Debug.Assert(false); return null; }
|
if (pbFileData == null) { Debug.Assert(false); return null; }
|
||||||
if(pbFileData.Length != 64) { Debug.Assert(false); return null; }
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
int cc = pbFileData.Length;
|
||||||
|
if ((cc & 1) != 0) { Debug.Assert(false); return null; }
|
||||||
|
|
||||||
if (!StrUtil.IsHexString(pbFileData, true)) return null;
|
if (!StrUtil.IsHexString(pbFileData, true)) return null;
|
||||||
|
|
||||||
string strHex = StrUtil.Utf8.GetString(pbFileData);
|
string strHex = StrUtil.Utf8.GetString(pbFileData);
|
||||||
byte[] pbKey = MemUtil.HexStringToByteArray(strHex);
|
return MemUtil.HexStringToByteArray(strHex);
|
||||||
if((pbKey == null) || (pbKey.Length != 32))
|
|
||||||
{
|
|
||||||
Debug.Assert(false);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pbKey;
|
|
||||||
}
|
}
|
||||||
catch (Exception) { Debug.Assert(false); }
|
catch (Exception) { Debug.Assert(false); }
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new, random key-file.
|
/// Create a new, random key-file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ namespace KeePassLib.Keys
|
|||||||
get { return m_pbKeyData; }
|
get { return m_pbKeyData; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint GetMinKdbxVersion()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public KcpPassword(byte[] pbPasswordUtf8)
|
public KcpPassword(byte[] pbPasswordUtf8)
|
||||||
{
|
{
|
||||||
SetKey(pbPasswordUtf8);
|
SetKey(pbPasswordUtf8);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
using System.Security;
|
using System.Security;
|
||||||
|
|
||||||
#if !KeePassUAP
|
#if !KeePassUAP
|
||||||
@@ -60,6 +59,11 @@ namespace KeePassLib.Keys
|
|||||||
get { return m_pbKeyData; }
|
get { return m_pbKeyData; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint GetMinKdbxVersion()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Construct a user account key.
|
/// Construct a user account key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -73,25 +77,6 @@ namespace KeePassLib.Keys
|
|||||||
// m_pbKeyData = null;
|
// m_pbKeyData = null;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private static string GetUserKeyFilePath(bool bCreate)
|
|
||||||
{
|
|
||||||
#if KeePassRT
|
|
||||||
string strUserDir = Windows.Storage.ApplicationData.Current.RoamingFolder.Path;
|
|
||||||
#else
|
|
||||||
string strUserDir = Environment.GetFolderPath(
|
|
||||||
Environment.SpecialFolder.ApplicationData);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
|
|
||||||
strUserDir += PwDefs.ShortProductName;
|
|
||||||
|
|
||||||
if (bCreate && !Directory.Exists(strUserDir))
|
|
||||||
Directory.CreateDirectory(strUserDir);
|
|
||||||
|
|
||||||
strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false);
|
|
||||||
return strUserDir + UserKeyFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] LoadUserKey(bool bShowWarning)
|
private static byte[] LoadUserKey(bool bShowWarning)
|
||||||
{
|
{
|
||||||
byte[] pbKey = null;
|
byte[] pbKey = null;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace keepass2android
|
|||||||
{
|
{
|
||||||
if (!File.Exists(LogFilename))
|
if (!File.Exists(LogFilename))
|
||||||
{
|
{
|
||||||
File.Create(LogFilename);
|
File.Create(LogFilename).Dispose();
|
||||||
_logToFile = true;
|
_logToFile = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,5 +118,10 @@ namespace keepass2android
|
|||||||
sendIntent.SetType("text/plain");
|
sendIntent.SetType("text/plain");
|
||||||
ctx.StartActivity(Intent.CreateChooser(sendIntent, "Send log to..."));
|
ctx.StartActivity(Intent.CreateChooser(sendIntent, "Send log to..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void LogTask(object task, string activityName)
|
||||||
|
{
|
||||||
|
Log($"Task in activity {activityName} changed to {task?.GetType()?.Name ?? "null"}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,7 +302,7 @@ namespace KeePassLib.Native
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Kp2aLog.Log(e.Message);
|
Kp2aLog.Log(e.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2013 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
Modified to be used with Mono for Android. Changes Copyright (C) 2013 Philipp Crocoll
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,61 +18,106 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
#if !KeePassUAP
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
#endif
|
||||||
|
|
||||||
using KeePassLib.Utility;
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
|
|
||||||
namespace KeePassLib
|
namespace KeePassLib
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Custom icon. <c>PwCustomIcon</c> objects are immutable.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class PwCustomIcon
|
public sealed class PwCustomIcon
|
||||||
{
|
{
|
||||||
private PwUuid m_pwUuid;
|
// Recommended maximum sizes, not obligatory
|
||||||
private byte[] m_pbImageDataPng;
|
internal const int MaxWidth = 128;
|
||||||
private Android.Graphics.Bitmap m_pCachedImage;
|
internal const int MaxHeight = 128;
|
||||||
|
|
||||||
|
private readonly PwUuid m_uuid;
|
||||||
|
private readonly byte[] m_pbImageDataPng;
|
||||||
|
|
||||||
|
private string m_strName = string.Empty;
|
||||||
|
private DateTime? m_odtLastMod = null;
|
||||||
|
|
||||||
|
private Dictionary<long, Android.Graphics.Bitmap> m_dImageCache = new Dictionary<long, Android.Graphics.Bitmap>();
|
||||||
|
|
||||||
public PwUuid Uuid
|
public PwUuid Uuid
|
||||||
{
|
{
|
||||||
get { return m_pwUuid; }
|
get { return m_uuid; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ImageDataPng
|
public byte[] ImageDataPng
|
||||||
{
|
{
|
||||||
get { return m_pbImageDataPng; }
|
get { return m_pbImageDataPng; }
|
||||||
|
// When allowing 'set', do not copy the cache in 'Clone'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return m_strName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null) throw new ArgumentNullException("value");
|
||||||
|
m_strName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime? LastModificationTime
|
||||||
|
{
|
||||||
|
get { return m_odtLastMod; }
|
||||||
|
set { m_odtLastMod = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use GetImage instead.")]
|
||||||
public Android.Graphics.Bitmap Image
|
public Android.Graphics.Bitmap Image
|
||||||
{
|
{
|
||||||
get { return m_pCachedImage; }
|
get { return GetImage(); } // Backward compatibility
|
||||||
}
|
}
|
||||||
|
|
||||||
public PwCustomIcon(PwUuid pwUuid, byte[] pbImageDataPng)
|
public PwCustomIcon(PwUuid pu, byte[] pbImageDataPng)
|
||||||
{
|
{
|
||||||
Debug.Assert(pwUuid != null);
|
if (pu == null) { Debug.Assert(false); throw new ArgumentNullException("pu"); }
|
||||||
if(pwUuid == null) throw new ArgumentNullException("pwUuid");
|
if (pu.Equals(PwUuid.Zero)) { Debug.Assert(false); throw new ArgumentOutOfRangeException("pu"); }
|
||||||
Debug.Assert(!pwUuid.Equals(PwUuid.Zero));
|
if (pbImageDataPng == null) { Debug.Assert(false); throw new ArgumentNullException("pbImageDataPng"); }
|
||||||
if(pwUuid.Equals(PwUuid.Zero)) throw new ArgumentException("pwUuid == 0");
|
|
||||||
|
|
||||||
Debug.Assert(pbImageDataPng != null);
|
m_uuid = pu;
|
||||||
if(pbImageDataPng == null) throw new ArgumentNullException("pbImageDataPng");
|
|
||||||
|
|
||||||
m_pwUuid = pwUuid;
|
|
||||||
m_pbImageDataPng = pbImageDataPng;
|
m_pbImageDataPng = pbImageDataPng;
|
||||||
|
}
|
||||||
|
|
||||||
#if !KeePassLibSD
|
private static long GetKey(int w, int h)
|
||||||
// MemoryStream ms = new MemoryStream(m_pbImageDataPng, false);
|
{
|
||||||
// m_pCachedImage = Image.FromStream(ms);
|
return (((long)w << 32) ^ (long)h);
|
||||||
// ms.Close();
|
}
|
||||||
m_pCachedImage = GfxUtil.LoadImage(m_pbImageDataPng);
|
|
||||||
#else
|
/// <summary>
|
||||||
m_pCachedImage = null;
|
/// Get the icon as an <c>Image</c> (original size).
|
||||||
#endif
|
/// </summary>
|
||||||
|
public Android.Graphics.Bitmap GetImage()
|
||||||
|
{
|
||||||
|
const long lKey = -1;
|
||||||
|
|
||||||
|
Android.Graphics.Bitmap img;
|
||||||
|
if (m_dImageCache.TryGetValue(lKey, out img)) return img;
|
||||||
|
|
||||||
|
try { img = GfxUtil.LoadImage(m_pbImageDataPng); }
|
||||||
|
catch (Exception) { Debug.Assert(false); }
|
||||||
|
|
||||||
|
m_dImageCache[lKey] = img;
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal PwCustomIcon Clone()
|
||||||
|
{
|
||||||
|
PwCustomIcon ico = new PwCustomIcon(m_uuid, m_pbImageDataPng);
|
||||||
|
|
||||||
|
ico.m_strName = m_strName;
|
||||||
|
ico.m_odtLastMod = m_odtLastMod;
|
||||||
|
|
||||||
|
ico.m_dImageCache = m_dImageCache; // Same image data
|
||||||
|
|
||||||
|
return ico;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ namespace KeePassLib
|
|||||||
private int m_nHistoryMaxItems = DefaultHistoryMaxItems;
|
private int m_nHistoryMaxItems = DefaultHistoryMaxItems;
|
||||||
private long m_lHistoryMaxSize = DefaultHistoryMaxSize; // In bytes
|
private long m_lHistoryMaxSize = DefaultHistoryMaxSize; // In bytes
|
||||||
|
|
||||||
private StringDictionaryEx m_dCustomData = new StringDictionaryEx();
|
private StringDictionaryEx m_dCustomData = new StringDictionaryEx(true);
|
||||||
private VariantDictionary m_dPublicCustomData = new VariantDictionary();
|
private VariantDictionary m_dPublicCustomData = new VariantDictionary();
|
||||||
|
|
||||||
private byte[] m_pbHashOfFileOnDisk = null;
|
private byte[] m_pbHashOfFileOnDisk = null;
|
||||||
@@ -485,12 +485,6 @@ namespace KeePassLib
|
|||||||
set { m_pbHashOfLastIO = value; }
|
set { m_pbHashOfLastIO = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UseFileTransactions
|
|
||||||
{
|
|
||||||
get { return m_bUseFileTransactions; }
|
|
||||||
set { m_bUseFileTransactions = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool UseFileLocks
|
public bool UseFileLocks
|
||||||
{
|
{
|
||||||
get { return m_bUseFileLocks; }
|
get { return m_bUseFileLocks; }
|
||||||
@@ -593,7 +587,7 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ioConnection">IO connection of the new database.</param>
|
/// <param name="ioConnection">IO connection of the new database.</param>
|
||||||
/// <param name="pwKey">Key to open the database.</param>
|
/// <param name="pwKey">Key to open the database.</param>
|
||||||
public void New(IOConnectionInfo ioConnection, CompositeKey pwKey)
|
public void New(IOConnectionInfo ioConnection, CompositeKey pwKey, string filenameWithoutPathAndExt)
|
||||||
{
|
{
|
||||||
Debug.Assert(ioConnection != null);
|
Debug.Assert(ioConnection != null);
|
||||||
if(ioConnection == null) throw new ArgumentNullException("ioConnection");
|
if(ioConnection == null) throw new ArgumentNullException("ioConnection");
|
||||||
@@ -608,26 +602,11 @@ namespace KeePassLib
|
|||||||
m_bDatabaseOpened = true;
|
m_bDatabaseOpened = true;
|
||||||
m_bModified = true;
|
m_bModified = true;
|
||||||
|
|
||||||
m_pgRootGroup = new PwGroup(true, true,
|
m_pgRootGroup = new PwGroup(true, true, filenameWithoutPathAndExt,
|
||||||
UrlUtil.StripExtension(UrlUtil.GetFileName(ioConnection.Path)),
|
|
||||||
PwIcon.FolderOpen);
|
PwIcon.FolderOpen);
|
||||||
m_pgRootGroup.IsExpanded = true;
|
m_pgRootGroup.IsExpanded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Open a database. The URL may point to any supported data source.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ioSource">IO connection to load the database from.</param>
|
|
||||||
/// <param name="pwKey">Key used to open the specified database.</param>
|
|
||||||
/// <param name="slLogger">Logger, which gets all status messages.</param>
|
|
||||||
public void Open(IOConnectionInfo ioSource, CompositeKey pwKey,
|
|
||||||
IStatusLogger slLogger, IDatabaseFormat format)
|
|
||||||
|
|
||||||
{
|
|
||||||
Open(IOConnection.OpenRead(ioSource), UrlUtil.StripExtension(
|
|
||||||
UrlUtil.GetFileName(ioSource.Path)), ioSource, pwKey, slLogger, format);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open a database. The URL may point to any supported data source.
|
/// Open a database. The URL may point to any supported data source.
|
||||||
@@ -676,36 +655,6 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Save the currently opened database. The file is written to the location
|
|
||||||
/// it has been opened from.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="slLogger">Logger that recieves status information.</param>
|
|
||||||
public void Save(IStatusLogger slLogger)
|
|
||||||
{
|
|
||||||
Debug.Assert(!HasDuplicateUuids());
|
|
||||||
|
|
||||||
FileLock fl = null;
|
|
||||||
if(m_bUseFileLocks) fl = new FileLock(m_ioSource);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
FileTransactionEx ft = new FileTransactionEx(m_ioSource,
|
|
||||||
m_bUseFileTransactions);
|
|
||||||
Stream s = ft.OpenWrite();
|
|
||||||
|
|
||||||
KdbxFile kdb = new KdbxFile(this);
|
|
||||||
kdb.Save(s, null, KdbpFile.GetFormatToUse(m_ioSource), slLogger);
|
|
||||||
|
|
||||||
ft.CommitWrite();
|
|
||||||
|
|
||||||
m_pbHashOfLastIO = kdb.HashOfFileOnDisk;
|
|
||||||
m_pbHashOfFileOnDisk = kdb.HashOfFileOnDisk;
|
|
||||||
Debug.Assert(m_pbHashOfFileOnDisk != null);
|
|
||||||
}
|
|
||||||
finally { if(fl != null) fl.Dispose(); }
|
|
||||||
|
|
||||||
m_bModified = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save the currently opened database. The file is written to the given stream which is expected to be the original location.
|
/// Save the currently opened database. The file is written to the given stream which is expected to be the original location.
|
||||||
@@ -723,46 +672,6 @@ namespace KeePassLib
|
|||||||
m_bModified = false;
|
m_bModified = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Save the currently opened database to a different location. If
|
|
||||||
/// <paramref name="bIsPrimaryNow" /> is <c>true</c>, the specified
|
|
||||||
/// location is made the default location for future saves
|
|
||||||
/// using <c>SaveDatabase</c>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ioConnection">New location to serialize the database to.</param>
|
|
||||||
/// <param name="bIsPrimaryNow">If <c>true</c>, the new location is made the
|
|
||||||
/// standard location for the database. If <c>false</c>, a copy of the currently
|
|
||||||
/// opened database is saved to the specified location, but it isn't
|
|
||||||
/// made the default location (i.e. no lock files will be moved for
|
|
||||||
/// example).</param>
|
|
||||||
/// <param name="slLogger">Logger that recieves status information.</param>
|
|
||||||
public void SaveAs(IOConnectionInfo ioConnection, bool bIsPrimaryNow,
|
|
||||||
IStatusLogger slLogger)
|
|
||||||
{
|
|
||||||
Debug.Assert(ioConnection != null);
|
|
||||||
if(ioConnection == null) throw new ArgumentNullException("ioConnection");
|
|
||||||
|
|
||||||
IOConnectionInfo ioCurrent = m_ioSource; // Remember current
|
|
||||||
m_ioSource = ioConnection;
|
|
||||||
|
|
||||||
byte[] pbHashCopy = m_pbHashOfFileOnDisk;
|
|
||||||
|
|
||||||
try { this.Save(slLogger); }
|
|
||||||
catch(Exception)
|
|
||||||
{
|
|
||||||
m_ioSource = ioCurrent; // Restore
|
|
||||||
m_pbHashOfFileOnDisk = pbHashCopy;
|
|
||||||
|
|
||||||
m_pbHashOfLastIO = null;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!bIsPrimaryNow)
|
|
||||||
{
|
|
||||||
m_ioSource = ioCurrent; // Restore
|
|
||||||
m_pbHashOfFileOnDisk = pbHashCopy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Closes the currently opened database. No confirmation message is shown
|
/// Closes the currently opened database. No confirmation message is shown
|
||||||
@@ -830,6 +739,12 @@ namespace KeePassLib
|
|||||||
pgNew.Uuid = pg.Uuid;
|
pgNew.Uuid = pg.Uuid;
|
||||||
pgNew.AssignProperties(pg, false, true);
|
pgNew.AssignProperties(pg, false, true);
|
||||||
|
|
||||||
|
if (!pgLocalContainer.CanAddGroup(pgNew))
|
||||||
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
|
pgLocalContainer = m_pgRootGroup;
|
||||||
|
pgLocalContainer.CheckCanAddGroup(pgNew);
|
||||||
|
}
|
||||||
// pgLocalContainer.AddGroup(pgNew, true);
|
// pgLocalContainer.AddGroup(pgNew, true);
|
||||||
InsertObjectAtBestPos<PwGroup>(pgLocalContainer.Groups, pgNew, ppSrc);
|
InsertObjectAtBestPos<PwGroup>(pgLocalContainer.Groups, pgNew, ppSrc);
|
||||||
pgNew.ParentGroup = pgLocalContainer;
|
pgNew.ParentGroup = pgLocalContainer;
|
||||||
@@ -929,24 +844,24 @@ namespace KeePassLib
|
|||||||
MergeInLocationChanged(m_pgRootGroup, ppOrg, ppSrc);
|
MergeInLocationChanged(m_pgRootGroup, ppOrg, ppSrc);
|
||||||
ppOrg = null; // Pools are now invalid, because the location
|
ppOrg = null; // Pools are now invalid, because the location
|
||||||
ppSrc = null; // changed times have been merged in
|
ppSrc = null; // changed times have been merged in
|
||||||
|
|
||||||
// Delete *after* relocating, because relocating might
|
|
||||||
// empty some groups that are marked for deletion (and
|
|
||||||
// objects that weren't relocated yet might prevent the
|
|
||||||
// deletion)
|
|
||||||
Dictionary<PwUuid, PwDeletedObject> dOrgDel = CreateDeletedObjectsPool();
|
|
||||||
MergeInDeletionInfo(pdSource.m_vDeletedObjects, dOrgDel);
|
|
||||||
ApplyDeletions(m_pgRootGroup, dOrgDel);
|
|
||||||
|
|
||||||
// The list and the dictionary should be kept in sync
|
|
||||||
Debug.Assert(m_vDeletedObjects.UCount == (uint)dOrgDel.Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete *after* relocating, because relocating might empty
|
||||||
|
// some groups that are marked for deletion (and objects
|
||||||
|
// that weren't relocated yet might prevent the deletion)
|
||||||
|
Dictionary<PwUuid, PwDeletedObject> dDel = CreateDeletedObjectsPool();
|
||||||
|
if (mm == PwMergeMethod.Synchronize)
|
||||||
|
MergeInDeletionInfo(pdSource.m_vDeletedObjects, dDel);
|
||||||
|
ApplyDeletions(m_pgRootGroup, dDel);
|
||||||
|
// The list and the dictionary should be kept in sync
|
||||||
|
Debug.Assert(m_vDeletedObjects.UCount == (uint)dDel.Count);
|
||||||
|
|
||||||
// Must be called *after* merging groups, because group UUIDs
|
// Must be called *after* merging groups, because group UUIDs
|
||||||
// are required for recycle bin and entry template UUIDs
|
// are required for recycle bin and entry template UUIDs
|
||||||
MergeInDbProperties(pdSource, mm);
|
MergeInDbProperties(pdSource, mm);
|
||||||
|
|
||||||
MergeInCustomIcons(pdSource);
|
MergeInCustomIcons(pdSource, dDel);
|
||||||
|
Debug.Assert(m_vDeletedObjects.UCount == (uint)dDel.Count);
|
||||||
|
|
||||||
MaintainBackups();
|
MaintainBackups();
|
||||||
|
|
||||||
@@ -954,15 +869,79 @@ namespace KeePassLib
|
|||||||
m_slStatus = slPrevStatus;
|
m_slStatus = slPrevStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MergeInCustomIcons(PwDatabase pdSource)
|
|
||||||
{
|
|
||||||
foreach(PwCustomIcon pwci in pdSource.CustomIcons)
|
|
||||||
{
|
|
||||||
if(GetCustomIconIndex(pwci.Uuid) >= 0) continue;
|
|
||||||
|
|
||||||
m_vCustomIcons.Add(pwci); // PwCustomIcon is immutable
|
private void MergeInCustomIcons(PwDatabase pdSource,
|
||||||
m_bUINeedsIconUpdate = true;
|
Dictionary<PwUuid, PwDeletedObject> dDel)
|
||||||
|
{
|
||||||
|
bool bIconsMod = false;
|
||||||
|
|
||||||
|
Dictionary<PwUuid, int> d = new Dictionary<PwUuid, int>();
|
||||||
|
for (int i = m_vCustomIcons.Count - 1; i >= 0; --i)
|
||||||
|
d[m_vCustomIcons[i].Uuid] = i;
|
||||||
|
Debug.Assert(d.Count == m_vCustomIcons.Count); // UUIDs unique
|
||||||
|
|
||||||
|
foreach (PwCustomIcon ciS in pdSource.m_vCustomIcons)
|
||||||
|
{
|
||||||
|
int iT;
|
||||||
|
if (d.TryGetValue(ciS.Uuid, out iT))
|
||||||
|
{
|
||||||
|
PwCustomIcon ciT = m_vCustomIcons[iT];
|
||||||
|
|
||||||
|
DateTime? odtT = ciT.LastModificationTime;
|
||||||
|
DateTime? odtS = ciS.LastModificationTime;
|
||||||
|
|
||||||
|
if (odtT.HasValue && odtS.HasValue)
|
||||||
|
{
|
||||||
|
if (odtT.Value >= odtS.Value) continue;
|
||||||
}
|
}
|
||||||
|
else if (odtT.HasValue) continue;
|
||||||
|
else if (!odtS.HasValue) continue; // Both no time
|
||||||
|
|
||||||
|
m_vCustomIcons[iT] = ciS.Clone();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d[ciS.Uuid] = m_vCustomIcons.Count;
|
||||||
|
m_vCustomIcons.Add(ciS.Clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
bIconsMod = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PwDeletedObject> lObsoleteDel = new List<PwDeletedObject>();
|
||||||
|
foreach (KeyValuePair<PwUuid, PwDeletedObject> kvpDel in dDel)
|
||||||
|
{
|
||||||
|
int iT;
|
||||||
|
if (d.TryGetValue(kvpDel.Key, out iT))
|
||||||
|
{
|
||||||
|
PwCustomIcon ci = m_vCustomIcons[iT];
|
||||||
|
if (ci == null) { Debug.Assert(false); continue; } // Dup. del. obj.?
|
||||||
|
|
||||||
|
DateTime? odt = ci.LastModificationTime;
|
||||||
|
|
||||||
|
if (odt.HasValue && (odt.Value > kvpDel.Value.DeletionTime))
|
||||||
|
lObsoleteDel.Add(kvpDel.Value);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_vCustomIcons[iT] = null; // Preserve indices, removed below
|
||||||
|
bIconsMod = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Predicate<PwCustomIcon> f = delegate (PwCustomIcon ci) { return (ci == null); };
|
||||||
|
m_vCustomIcons.RemoveAll(f);
|
||||||
|
|
||||||
|
foreach (PwDeletedObject pdo in lObsoleteDel)
|
||||||
|
{
|
||||||
|
// Prevent future deletion attempts
|
||||||
|
if (!m_vDeletedObjects.Remove(pdo)) { Debug.Assert(false); }
|
||||||
|
if (!dDel.Remove(pdo.Uuid)) { Debug.Assert(false); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bIconsMod) m_bUINeedsIconUpdate = true;
|
||||||
|
|
||||||
|
FixCustomIconRefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<PwUuid, PwDeletedObject> CreateDeletedObjectsPool()
|
private Dictionary<PwUuid, PwDeletedObject> CreateDeletedObjectsPool()
|
||||||
@@ -1303,7 +1282,9 @@ namespace KeePassLib
|
|||||||
PwObjectBlock<T> b = new PwObjectBlock<T>();
|
PwObjectBlock<T> b = new PwObjectBlock<T>();
|
||||||
|
|
||||||
DateTime dtLoc;
|
DateTime dtLoc;
|
||||||
PwObjectPoolEx pPool = GetBestPool(t, ppOrg, ppSrc, out dtLoc);
|
PwUuid puPrevParent;
|
||||||
|
PwObjectPoolEx pPool = GetBestPool(t, ppOrg, ppSrc, out dtLoc,
|
||||||
|
out puPrevParent);
|
||||||
b.Add(t, dtLoc, pPool);
|
b.Add(t, dtLoc, pPool);
|
||||||
|
|
||||||
lBlocks.Add(b);
|
lBlocks.Add(b);
|
||||||
@@ -1338,7 +1319,7 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
if(idSrcNext == 0) break;
|
if(idSrcNext == 0) break;
|
||||||
|
|
||||||
pPool = GetBestPool(tNext, ppOrg, ppSrc, out dtLoc);
|
pPool = GetBestPool(tNext, ppOrg, ppSrc, out dtLoc, out puPrevParent);
|
||||||
b.Add(tNext, dtLoc, pPool);
|
b.Add(tNext, dtLoc, pPool);
|
||||||
|
|
||||||
++u;
|
++u;
|
||||||
@@ -1351,16 +1332,18 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static PwObjectPoolEx GetBestPool<T>(T t, PwObjectPoolEx ppOrg,
|
private static PwObjectPoolEx GetBestPool<T>(T t, PwObjectPoolEx ppOrg,
|
||||||
PwObjectPoolEx ppSrc, out DateTime dtLoc)
|
PwObjectPoolEx ppSrc, out DateTime dtLoc, out PwUuid puPrevParent)
|
||||||
where T : class, ITimeLogger, IStructureItem, IDeepCloneable<T>
|
where T : class, ITimeLogger, IStructureItem, IDeepCloneable<T>
|
||||||
{
|
{
|
||||||
PwObjectPoolEx p = null;
|
PwObjectPoolEx p = null;
|
||||||
dtLoc = TimeUtil.SafeMinValueUtc;
|
dtLoc = TimeUtil.SafeMinValueUtc;
|
||||||
|
puPrevParent = PwUuid.Zero;
|
||||||
|
|
||||||
IStructureItem ptOrg = ppOrg.GetItemByUuid(t.Uuid);
|
IStructureItem ptOrg = ppOrg.GetItemByUuid(t.Uuid);
|
||||||
if (ptOrg != null)
|
if (ptOrg != null)
|
||||||
{
|
{
|
||||||
dtLoc = ptOrg.LocationChanged;
|
dtLoc = ptOrg.LocationChanged;
|
||||||
|
puPrevParent = ptOrg.PreviousParentGroup;
|
||||||
p = ppOrg;
|
p = ppOrg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1368,6 +1351,7 @@ namespace KeePassLib
|
|||||||
if ((ptSrc != null) && (ptSrc.LocationChanged > dtLoc))
|
if ((ptSrc != null) && (ptSrc.LocationChanged > dtLoc))
|
||||||
{
|
{
|
||||||
dtLoc = ptSrc.LocationChanged;
|
dtLoc = ptSrc.LocationChanged;
|
||||||
|
puPrevParent = ptSrc.PreviousParentGroup;
|
||||||
p = ppSrc;
|
p = ppSrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1404,8 +1388,13 @@ namespace KeePassLib
|
|||||||
GroupHandler gh = delegate (PwGroup pgSub)
|
GroupHandler gh = delegate (PwGroup pgSub)
|
||||||
{
|
{
|
||||||
DateTime dt;
|
DateTime dt;
|
||||||
if(GetBestPool<PwGroup>(pgSub, ppOrg, ppSrc, out dt) != null)
|
PwUuid puPrevParent;
|
||||||
|
if (GetBestPool<PwGroup>(pgSub, ppOrg, ppSrc, out dt,
|
||||||
|
out puPrevParent) != null)
|
||||||
|
{
|
||||||
pgSub.LocationChanged = dt;
|
pgSub.LocationChanged = dt;
|
||||||
|
pgSub.PreviousParentGroup = puPrevParent;
|
||||||
|
}
|
||||||
else { Debug.Assert(false); }
|
else { Debug.Assert(false); }
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -1413,8 +1402,13 @@ namespace KeePassLib
|
|||||||
EntryHandler eh = delegate (PwEntry pe)
|
EntryHandler eh = delegate (PwEntry pe)
|
||||||
{
|
{
|
||||||
DateTime dt;
|
DateTime dt;
|
||||||
if(GetBestPool<PwEntry>(pe, ppOrg, ppSrc, out dt) != null)
|
PwUuid puPrevParent;
|
||||||
|
if (GetBestPool<PwEntry>(pe, ppOrg, ppSrc, out dt,
|
||||||
|
out puPrevParent) != null)
|
||||||
|
{
|
||||||
pe.LocationChanged = dt;
|
pe.LocationChanged = dt;
|
||||||
|
pe.PreviousParentGroup = puPrevParent;
|
||||||
|
}
|
||||||
else { Debug.Assert(false); }
|
else { Debug.Assert(false); }
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -1536,12 +1530,18 @@ namespace KeePassLib
|
|||||||
foreach(KeyValuePair<string, string> kvp in pdSource.m_dCustomData)
|
foreach(KeyValuePair<string, string> kvp in pdSource.m_dCustomData)
|
||||||
{
|
{
|
||||||
if(bSourceNewer || !m_dCustomData.Exists(kvp.Key))
|
if(bSourceNewer || !m_dCustomData.Exists(kvp.Key))
|
||||||
m_dCustomData.Set(kvp.Key, kvp.Value);
|
m_dCustomData.Set(kvp.Key, kvp.Value, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantDictionary vdLocal = m_dPublicCustomData; // Backup
|
// 'Clone' duplicates deep values (e.g. byte arrays)
|
||||||
m_dPublicCustomData = (VariantDictionary)pdSource.m_dPublicCustomData.Clone();
|
VariantDictionary vdS = (VariantDictionary)pdSource.m_dPublicCustomData.Clone();
|
||||||
if(!bSourceNewer) vdLocal.CopyTo(m_dPublicCustomData); // Merge
|
if (bForce || bSourceNewer)
|
||||||
|
vdS.CopyTo(m_dPublicCustomData);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_dPublicCustomData.CopyTo(vdS);
|
||||||
|
m_dPublicCustomData = vdS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MergeEntryHistory(PwEntry pe, PwEntry peSource,
|
private void MergeEntryHistory(PwEntry pe, PwEntry peSource,
|
||||||
@@ -1676,68 +1676,64 @@ namespace KeePassLib
|
|||||||
else { Debug.Assert(false); return null; }
|
else { Debug.Assert(false); return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DeleteCustomIcons(List<PwUuid> vUuidsToDelete)
|
public bool DeleteCustomIcons(List<PwUuid> lUuids)
|
||||||
{
|
{
|
||||||
Debug.Assert(vUuidsToDelete != null);
|
if (lUuids == null) { Debug.Assert(false); throw new ArgumentNullException("lUuids"); }
|
||||||
if(vUuidsToDelete == null) throw new ArgumentNullException("vUuidsToDelete");
|
if (lUuids.Count == 0) return false;
|
||||||
if(vUuidsToDelete.Count <= 0) return true;
|
|
||||||
|
Dictionary<PwUuid, bool> dToDel = new Dictionary<PwUuid, bool>();
|
||||||
|
foreach (PwUuid pu in lUuids) { dToDel[pu] = true; }
|
||||||
|
|
||||||
|
DateTime dt = DateTime.UtcNow;
|
||||||
|
for (int i = m_vCustomIcons.Count - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
PwUuid pu = m_vCustomIcons[i].Uuid;
|
||||||
|
if (dToDel.ContainsKey(pu))
|
||||||
|
{
|
||||||
|
m_vCustomIcons[i] = null; // Removed below
|
||||||
|
m_vDeletedObjects.Add(new PwDeletedObject(pu, dt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Predicate<PwCustomIcon> f = delegate (PwCustomIcon ci) { return (ci == null); };
|
||||||
|
m_vCustomIcons.RemoveAll(f);
|
||||||
|
|
||||||
|
FixCustomIconRefs();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixCustomIconRefs()
|
||||||
|
{
|
||||||
|
Dictionary<PwUuid, bool> d = new Dictionary<PwUuid, bool>();
|
||||||
|
foreach (PwCustomIcon ci in m_vCustomIcons) { d[ci.Uuid] = true; }
|
||||||
|
|
||||||
GroupHandler gh = delegate (PwGroup pg)
|
GroupHandler gh = delegate (PwGroup pg)
|
||||||
{
|
{
|
||||||
PwUuid uuidThis = pg.CustomIconUuid;
|
PwUuid pu = pg.CustomIconUuid;
|
||||||
if(uuidThis.Equals(PwUuid.Zero)) return true;
|
if (pu.Equals(PwUuid.Zero)) return true;
|
||||||
|
if (!d.ContainsKey(pu)) pg.CustomIconUuid = PwUuid.Zero;
|
||||||
foreach(PwUuid uuidDelete in vUuidsToDelete)
|
|
||||||
{
|
|
||||||
if(uuidThis.Equals(uuidDelete))
|
|
||||||
{
|
|
||||||
pg.CustomIconUuid = PwUuid.Zero;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
EntryHandler eh = delegate (PwEntry pe)
|
EntryHandler eh = delegate (PwEntry pe)
|
||||||
{
|
{
|
||||||
RemoveCustomIconUuid(pe, vUuidsToDelete);
|
FixCustomIconRefs(pe, d);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
gh(m_pgRootGroup);
|
gh(m_pgRootGroup);
|
||||||
if(!m_pgRootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh))
|
m_pgRootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh);
|
||||||
{
|
|
||||||
Debug.Assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(PwUuid pwUuid in vUuidsToDelete)
|
private void FixCustomIconRefs(PwEntry pe, Dictionary<PwUuid, bool> d)
|
||||||
{
|
{
|
||||||
int nIndex = GetCustomIconIndex(pwUuid);
|
PwUuid pu = pe.CustomIconUuid;
|
||||||
if(nIndex >= 0) m_vCustomIcons.RemoveAt(nIndex);
|
if (pu.Equals(PwUuid.Zero)) return;
|
||||||
|
if (!d.ContainsKey(pu)) pe.CustomIconUuid = PwUuid.Zero;
|
||||||
|
|
||||||
|
foreach (PwEntry peH in pe.History) FixCustomIconRefs(peH, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RemoveCustomIconUuid(PwEntry pe, List<PwUuid> vToDelete)
|
|
||||||
{
|
|
||||||
PwUuid uuidThis = pe.CustomIconUuid;
|
|
||||||
if(uuidThis.Equals(PwUuid.Zero)) return;
|
|
||||||
|
|
||||||
foreach(PwUuid uuidDelete in vToDelete)
|
|
||||||
{
|
|
||||||
if(uuidThis.Equals(uuidDelete))
|
|
||||||
{
|
|
||||||
pe.CustomIconUuid = PwUuid.Zero;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(PwEntry peHistory in pe.History)
|
|
||||||
RemoveCustomIconUuid(peHistory, vToDelete);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetTotalObjectUuidCount()
|
private int GetTotalObjectUuidCount()
|
||||||
{
|
{
|
||||||
@@ -2026,61 +2022,119 @@ namespace KeePassLib
|
|||||||
return uDeleted;
|
return uDeleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public uint DeleteUnusedCustomIcons()
|
public uint DeleteUnusedCustomIcons()
|
||||||
{
|
{
|
||||||
List<PwUuid> lToDelete = new List<PwUuid>();
|
Dictionary<PwUuid, bool> dToDel = new Dictionary<PwUuid, bool>();
|
||||||
foreach(PwCustomIcon pwci in m_vCustomIcons)
|
foreach (PwCustomIcon ci in m_vCustomIcons) { dToDel[ci.Uuid] = true; }
|
||||||
lToDelete.Add(pwci.Uuid);
|
|
||||||
|
|
||||||
GroupHandler gh = delegate (PwGroup pg)
|
GroupHandler gh = delegate (PwGroup pg)
|
||||||
{
|
{
|
||||||
PwUuid pwUuid = pg.CustomIconUuid;
|
PwUuid pu = pg.CustomIconUuid;
|
||||||
if((pwUuid == null) || pwUuid.Equals(PwUuid.Zero)) return true;
|
if (!pu.Equals(PwUuid.Zero)) dToDel.Remove(pu);
|
||||||
|
|
||||||
for(int i = 0; i < lToDelete.Count; ++i)
|
|
||||||
{
|
|
||||||
if(lToDelete[i].Equals(pwUuid))
|
|
||||||
{
|
|
||||||
lToDelete.RemoveAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
EntryHandler eh = delegate (PwEntry pe)
|
EntryHandler eh = delegate (PwEntry pe)
|
||||||
{
|
{
|
||||||
PwUuid pwUuid = pe.CustomIconUuid;
|
RemoveCustomIconsFromDict(dToDel, pe);
|
||||||
if((pwUuid == null) || pwUuid.Equals(PwUuid.Zero)) return true;
|
|
||||||
|
|
||||||
for(int i = 0; i < lToDelete.Count; ++i)
|
|
||||||
{
|
|
||||||
if(lToDelete[i].Equals(pwUuid))
|
|
||||||
{
|
|
||||||
lToDelete.RemoveAt(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
gh(m_pgRootGroup);
|
gh(m_pgRootGroup);
|
||||||
m_pgRootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh);
|
m_pgRootGroup.TraverseTree(TraversalMethod.PreOrder, gh, eh);
|
||||||
|
|
||||||
uint uDeleted = 0;
|
uint cDel = (uint)dToDel.Count;
|
||||||
foreach(PwUuid pwDel in lToDelete)
|
if (cDel != 0)
|
||||||
{
|
{
|
||||||
int nIndex = GetCustomIconIndex(pwDel);
|
DeleteCustomIcons(new List<PwUuid>(dToDel.Keys));
|
||||||
if(nIndex < 0) { Debug.Assert(false); continue; }
|
m_bUINeedsIconUpdate = true;
|
||||||
|
|
||||||
m_vCustomIcons.RemoveAt(nIndex);
|
|
||||||
++uDeleted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(uDeleted > 0) m_bUINeedsIconUpdate = true;
|
return cDel;
|
||||||
return uDeleted;
|
}
|
||||||
|
|
||||||
|
private static void RemoveCustomIconsFromDict(Dictionary<PwUuid, bool> d,
|
||||||
|
PwEntry pe)
|
||||||
|
{
|
||||||
|
PwUuid pu = pe.CustomIconUuid;
|
||||||
|
if (!pu.Equals(PwUuid.Zero)) d.Remove(pu);
|
||||||
|
|
||||||
|
foreach (PwEntry peH in pe.History) RemoveCustomIconsFromDict(d, peH);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CopyCustomIcons(PwDatabase pdFrom, PwDatabase pdTo,
|
||||||
|
PwGroup pgSelect, bool bResetIfUnknown)
|
||||||
|
{
|
||||||
|
if (pgSelect == null) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
|
Dictionary<PwUuid, PwCustomIcon> dFrom = new Dictionary<PwUuid, PwCustomIcon>();
|
||||||
|
if (pdFrom != null)
|
||||||
|
{
|
||||||
|
foreach (PwCustomIcon ci in pdFrom.m_vCustomIcons)
|
||||||
|
dFrom[ci.Uuid] = ci;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<PwUuid, int> dTo = new Dictionary<PwUuid, int>();
|
||||||
|
if (pdTo != null)
|
||||||
|
{
|
||||||
|
for (int i = pdTo.m_vCustomIcons.Count - 1; i >= 0; --i)
|
||||||
|
dTo[pdTo.m_vCustomIcons[i].Uuid] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Func<PwUuid, bool> fEnsureIcon = delegate (PwUuid puIcon)
|
||||||
|
{
|
||||||
|
if (puIcon.Equals(PwUuid.Zero)) return true;
|
||||||
|
if (pdTo == null) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
|
PwCustomIcon ciFrom;
|
||||||
|
if (!dFrom.TryGetValue(puIcon, out ciFrom)) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
|
int iTo;
|
||||||
|
if (dTo.TryGetValue(puIcon, out iTo))
|
||||||
|
{
|
||||||
|
PwCustomIcon ciTo = pdTo.m_vCustomIcons[iTo];
|
||||||
|
|
||||||
|
DateTime? odtFrom = ciFrom.LastModificationTime;
|
||||||
|
DateTime? odtTo = ciTo.LastModificationTime;
|
||||||
|
|
||||||
|
if (odtFrom.HasValue && odtTo.HasValue)
|
||||||
|
{
|
||||||
|
if (odtFrom.Value <= odtTo.Value) return true;
|
||||||
|
}
|
||||||
|
else if (odtTo.HasValue) return true;
|
||||||
|
else if (!odtFrom.HasValue) return true; // Both no time
|
||||||
|
|
||||||
|
pdTo.m_vCustomIcons[iTo] = ciFrom.Clone();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dTo[puIcon] = pdTo.m_vCustomIcons.Count;
|
||||||
|
pdTo.m_vCustomIcons.Add(ciFrom.Clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
pdTo.Modified = true;
|
||||||
|
pdTo.UINeedsIconUpdate = true;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
GroupHandler gh = delegate (PwGroup pgCur)
|
||||||
|
{
|
||||||
|
bool bTo = fEnsureIcon(pgCur.CustomIconUuid);
|
||||||
|
if (!bTo && bResetIfUnknown) pgCur.CustomIconUuid = PwUuid.Zero;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryHandler eh = delegate (PwEntry peCur)
|
||||||
|
{
|
||||||
|
bool bTo = fEnsureIcon(peCur.CustomIconUuid);
|
||||||
|
if (!bTo && bResetIfUnknown) peCur.CustomIconUuid = PwUuid.Zero;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
gh(pgSelect);
|
||||||
|
pgSelect.TraverseTree(TraversalMethod.PreOrder, gh, eh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -228,6 +228,18 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class SearchParameters
|
public sealed class SearchParameters
|
||||||
{
|
{
|
||||||
|
private string m_strName = string.Empty;
|
||||||
|
[DefaultValue("")]
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return m_strName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null) throw new ArgumentNullException("value");
|
||||||
|
m_strName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string m_strText = string.Empty;
|
private string m_strText = string.Empty;
|
||||||
[DefaultValue("")]
|
[DefaultValue("")]
|
||||||
public string SearchString
|
public string SearchString
|
||||||
@@ -240,12 +252,20 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool m_bRegex = false;
|
private PwSearchMode m_sm = PwSearchMode.Simple;
|
||||||
|
public PwSearchMode SearchMode
|
||||||
|
{
|
||||||
|
get { return m_sm; }
|
||||||
|
set { m_sm = value; }
|
||||||
|
}
|
||||||
|
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
|
[Obsolete]
|
||||||
|
[XmlIgnore]
|
||||||
public bool RegularExpression
|
public bool RegularExpression
|
||||||
{
|
{
|
||||||
get { return m_bRegex; }
|
get { return (m_sm == PwSearchMode.Regular); }
|
||||||
set { m_bRegex = value; }
|
set { m_sm = (value ? PwSearchMode.Regular : PwSearchMode.Simple); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool m_bSearchInTitles = true;
|
private bool m_bSearchInTitles = true;
|
||||||
@@ -296,6 +316,22 @@ namespace KeePassLib
|
|||||||
set { m_bSearchInOther = value; }
|
set { m_bSearchInOther = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool m_bSearchInStringNames = false;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool SearchInStringNames
|
||||||
|
{
|
||||||
|
get { return m_bSearchInStringNames; }
|
||||||
|
set { m_bSearchInStringNames = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool m_bSearchInTags = true;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool SearchInTags
|
||||||
|
{
|
||||||
|
get { return m_bSearchInTags; }
|
||||||
|
set { m_bSearchInTags = value; }
|
||||||
|
}
|
||||||
|
|
||||||
private bool m_bSearchInUuids = false;
|
private bool m_bSearchInUuids = false;
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
public bool SearchInUuids
|
public bool SearchInUuids
|
||||||
@@ -304,6 +340,14 @@ namespace KeePassLib
|
|||||||
set { m_bSearchInUuids = value; }
|
set { m_bSearchInUuids = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool m_bSearchInGroupPaths = false;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool SearchInGroupPaths
|
||||||
|
{
|
||||||
|
get { return m_bSearchInGroupPaths; }
|
||||||
|
set { m_bSearchInGroupPaths = value; }
|
||||||
|
}
|
||||||
|
|
||||||
private bool m_bSearchInGroupNames = false;
|
private bool m_bSearchInGroupNames = false;
|
||||||
[DefaultValue(false)]
|
[DefaultValue(false)]
|
||||||
public bool SearchInGroupNames
|
public bool SearchInGroupNames
|
||||||
@@ -312,12 +356,12 @@ namespace KeePassLib
|
|||||||
set { m_bSearchInGroupNames = value; }
|
set { m_bSearchInGroupNames = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool m_bSearchInTags = true;
|
private bool m_bSearchInHistory = false;
|
||||||
[DefaultValue(true)]
|
[DefaultValue(false)]
|
||||||
public bool SearchInTags
|
public bool SearchInHistory
|
||||||
{
|
{
|
||||||
get { return m_bSearchInTags; }
|
get { return m_bSearchInHistory; }
|
||||||
set { m_bSearchInTags = value; }
|
set { m_bSearchInHistory = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#if KeePassUAP
|
#if KeePassUAP
|
||||||
@@ -381,20 +425,24 @@ namespace KeePassLib
|
|||||||
{
|
{
|
||||||
SearchParameters sp = new SearchParameters();
|
SearchParameters sp = new SearchParameters();
|
||||||
|
|
||||||
// sp.m_strText = string.Empty;
|
Debug.Assert(sp.m_strName.Length == 0);
|
||||||
// sp.m_bRegex = false;
|
Debug.Assert(sp.m_strText.Length == 0);
|
||||||
|
Debug.Assert(sp.m_sm == PwSearchMode.Simple);
|
||||||
sp.m_bSearchInTitles = false;
|
sp.m_bSearchInTitles = false;
|
||||||
sp.m_bSearchInUserNames = false;
|
sp.m_bSearchInUserNames = false;
|
||||||
// sp.m_bSearchInPasswords = false;
|
Debug.Assert(!sp.m_bSearchInPasswords);
|
||||||
sp.m_bSearchInUrls = false;
|
sp.m_bSearchInUrls = false;
|
||||||
sp.m_bSearchInNotes = false;
|
sp.m_bSearchInNotes = false;
|
||||||
sp.m_bSearchInOther = false;
|
sp.m_bSearchInOther = false;
|
||||||
// sp.m_bSearchInUuids = false;
|
Debug.Assert(!sp.m_bSearchInStringNames);
|
||||||
// sp.SearchInGroupNames = false;
|
|
||||||
sp.m_bSearchInTags = false;
|
sp.m_bSearchInTags = false;
|
||||||
// sp.m_scType = StringComparison.InvariantCultureIgnoreCase;
|
Debug.Assert(!sp.m_bSearchInUuids);
|
||||||
// sp.m_bExcludeExpired = false;
|
Debug.Assert(!sp.m_bSearchInGroupPaths);
|
||||||
// m_bRespectEntrySearchingDisabled = true;
|
Debug.Assert(!sp.m_bSearchInGroupNames);
|
||||||
|
Debug.Assert(!sp.m_bSearchInHistory);
|
||||||
|
// Debug.Assert(sp.m_scType == StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
Debug.Assert(!sp.m_bExcludeExpired);
|
||||||
|
Debug.Assert(sp.m_bRespectEntrySearchingDisabled);
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -42,14 +42,15 @@ namespace KeePassLib
|
|||||||
private PwUuid m_uuid = PwUuid.Zero;
|
private PwUuid m_uuid = PwUuid.Zero;
|
||||||
private PwGroup m_pParentGroup = null;
|
private PwGroup m_pParentGroup = null;
|
||||||
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
||||||
|
private PwUuid m_puPrevParentGroup = PwUuid.Zero;
|
||||||
|
|
||||||
private ProtectedStringDictionary m_listStrings = new ProtectedStringDictionary();
|
private ProtectedStringDictionary m_dStrings = new ProtectedStringDictionary();
|
||||||
private ProtectedBinaryDictionary m_listBinaries = new ProtectedBinaryDictionary();
|
private ProtectedBinaryDictionary m_dBinaries = new ProtectedBinaryDictionary();
|
||||||
private AutoTypeConfig m_listAutoType = new AutoTypeConfig();
|
private AutoTypeConfig m_cfgAutoType = new AutoTypeConfig();
|
||||||
private PwObjectList<PwEntry> m_listHistory = new PwObjectList<PwEntry>();
|
private PwObjectList<PwEntry> m_lHistory = new PwObjectList<PwEntry>();
|
||||||
|
|
||||||
private PwIcon m_pwIcon = PwIcon.Key;
|
private PwIcon m_pwIcon = PwIcon.Key;
|
||||||
private PwUuid m_pwCustomIconID = PwUuid.Zero;
|
private PwUuid m_puCustomIcon = PwUuid.Zero;
|
||||||
|
|
||||||
private Color m_clrForeground = Color.Empty;
|
private Color m_clrForeground = Color.Empty;
|
||||||
private Color m_clrBackground = Color.Empty;
|
private Color m_clrBackground = Color.Empty;
|
||||||
@@ -62,20 +63,21 @@ namespace KeePassLib
|
|||||||
private ulong m_uUsageCount = 0;
|
private ulong m_uUsageCount = 0;
|
||||||
|
|
||||||
private string m_strOverrideUrl = string.Empty;
|
private string m_strOverrideUrl = string.Empty;
|
||||||
|
private bool m_bQualityCheck = true;
|
||||||
|
|
||||||
private List<string> m_vTags = new List<string>();
|
private List<string> m_lTags = new List<string>();
|
||||||
|
|
||||||
private StringDictionaryEx m_dCustomData = new StringDictionaryEx();
|
private StringDictionaryEx m_dCustomData = new StringDictionaryEx();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UUID of this entry.
|
/// UUID of this entry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// </summary>
|
|
||||||
public PwUuid Uuid
|
public PwUuid Uuid
|
||||||
{
|
{
|
||||||
get { return m_uuid; }
|
get { return m_uuid; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_uuid = value;
|
m_uuid = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,7 +89,7 @@ namespace KeePassLib
|
|||||||
{
|
{
|
||||||
get { return m_pParentGroup; }
|
get { return m_pParentGroup; }
|
||||||
|
|
||||||
/// Plugins: use <c>PwGroup.AddEntry</c> instead.
|
// Plugins: use <c>PwGroup.AddEntry</c> instead.
|
||||||
internal set { m_pParentGroup = value; }
|
internal set { m_pParentGroup = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,17 +102,26 @@ namespace KeePassLib
|
|||||||
set { m_tParentGroupLastMod = value; }
|
set { m_tParentGroupLastMod = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PwUuid PreviousParentGroup
|
||||||
|
{
|
||||||
|
get { return m_puPrevParentGroup; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
|
m_puPrevParentGroup = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get or set all entry strings.
|
/// Get or set all entry strings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProtectedStringDictionary Strings
|
public ProtectedStringDictionary Strings
|
||||||
{
|
{
|
||||||
get { return m_listStrings; }
|
get { return m_dStrings; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_listStrings = value;
|
m_dStrings = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,11 +130,11 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ProtectedBinaryDictionary Binaries
|
public ProtectedBinaryDictionary Binaries
|
||||||
{
|
{
|
||||||
get { return m_listBinaries; }
|
get { return m_dBinaries; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_listBinaries = value;
|
m_dBinaries = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,11 +143,11 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoTypeConfig AutoType
|
public AutoTypeConfig AutoType
|
||||||
{
|
{
|
||||||
get { return m_listAutoType; }
|
get { return m_cfgAutoType; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_listAutoType = value;
|
m_cfgAutoType = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,11 +156,11 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public PwObjectList<PwEntry> History
|
public PwObjectList<PwEntry> History
|
||||||
{
|
{
|
||||||
get { return m_listHistory; }
|
get { return m_lHistory; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_listHistory = value;
|
m_lHistory = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,11 +180,11 @@ namespace KeePassLib
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public PwUuid CustomIconUuid
|
public PwUuid CustomIconUuid
|
||||||
{
|
{
|
||||||
get { return m_pwCustomIconID; }
|
get { return m_puCustomIcon; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_pwCustomIconID = value;
|
m_puCustomIcon = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,28 +263,34 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entry-specific override URL. If this string is non-empty,
|
/// Entry-specific override URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OverrideUrl
|
public string OverrideUrl
|
||||||
{
|
{
|
||||||
get { return m_strOverrideUrl; }
|
get { return m_strOverrideUrl; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_strOverrideUrl = value;
|
m_strOverrideUrl = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool QualityCheck
|
||||||
|
{
|
||||||
|
get { return m_bQualityCheck; }
|
||||||
|
set { m_bQualityCheck = value; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of tags associated with this entry.
|
/// List of tags associated with this entry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Tags
|
public List<string> Tags
|
||||||
{
|
{
|
||||||
get { return m_vTags; }
|
get { StrUtil.NormalizeTags(m_lTags); return m_lTags; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_vTags = value;
|
m_lTags = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,19 +366,19 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
/// <summary>
|
// For display in debugger
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return (@"PwEntry '" + m_listStrings.ReadSafe(PwDefs.TitleField) + @"'");
|
return ("PwEntry '" + m_dStrings.ReadSafe(PwDefs.TitleField) + "'");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// Clone the current entry. The returned entry is an exact value copy
|
/// Clone the current entry. The returned entry is an exact value copy
|
||||||
/// of the current entry (including UUID and parent group reference).
|
/// of the current entry (including UUID and parent group reference).
|
||||||
/// All mutable members are cloned.
|
/// All mutable members are cloned.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Exact value clone. All references to mutable values changed.</returns>
|
/// <returns>Exact value clone. All references to mutable values changed.</returns>
|
||||||
/// </summary>
|
|
||||||
/// <returns>Exact value clone. All references to mutable values changed.</returns>
|
|
||||||
public PwEntry CloneDeep()
|
public PwEntry CloneDeep()
|
||||||
{
|
{
|
||||||
PwEntry peNew = new PwEntry(false, false);
|
PwEntry peNew = new PwEntry(false, false);
|
||||||
@@ -369,14 +386,15 @@ namespace KeePassLib
|
|||||||
peNew.m_uuid = m_uuid; // PwUuid is immutable
|
peNew.m_uuid = m_uuid; // PwUuid is immutable
|
||||||
peNew.m_pParentGroup = m_pParentGroup;
|
peNew.m_pParentGroup = m_pParentGroup;
|
||||||
peNew.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
peNew.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
||||||
|
peNew.m_puPrevParentGroup = m_puPrevParentGroup;
|
||||||
|
|
||||||
peNew.m_listStrings = m_listStrings.CloneDeep();
|
peNew.m_dStrings = m_dStrings.CloneDeep();
|
||||||
peNew.m_listBinaries = m_listBinaries.CloneDeep();
|
peNew.m_dBinaries = m_dBinaries.CloneDeep();
|
||||||
peNew.m_listAutoType = m_listAutoType.CloneDeep();
|
peNew.m_cfgAutoType = m_cfgAutoType.CloneDeep();
|
||||||
peNew.m_listHistory = m_listHistory.CloneDeep();
|
peNew.m_lHistory = m_lHistory.CloneDeep();
|
||||||
|
|
||||||
peNew.m_pwIcon = m_pwIcon;
|
peNew.m_pwIcon = m_pwIcon;
|
||||||
peNew.m_pwCustomIconID = m_pwCustomIconID;
|
peNew.m_puCustomIcon = m_puCustomIcon;
|
||||||
|
|
||||||
peNew.m_clrForeground = m_clrForeground;
|
peNew.m_clrForeground = m_clrForeground;
|
||||||
peNew.m_clrBackground = m_clrBackground;
|
peNew.m_clrBackground = m_clrBackground;
|
||||||
@@ -389,8 +407,9 @@ namespace KeePassLib
|
|||||||
peNew.m_uUsageCount = m_uUsageCount;
|
peNew.m_uUsageCount = m_uUsageCount;
|
||||||
|
|
||||||
peNew.m_strOverrideUrl = m_strOverrideUrl;
|
peNew.m_strOverrideUrl = m_strOverrideUrl;
|
||||||
|
peNew.m_bQualityCheck = m_bQualityCheck;
|
||||||
|
|
||||||
peNew.m_vTags = new List<string>(m_vTags);
|
peNew.m_lTags.AddRange(m_lTags);
|
||||||
|
|
||||||
peNew.m_dCustomData = m_dCustomData.CloneDeep();
|
peNew.m_dCustomData = m_dCustomData.CloneDeep();
|
||||||
|
|
||||||
@@ -457,27 +476,29 @@ namespace KeePassLib
|
|||||||
if (m_pParentGroup != pe.m_pParentGroup) return false;
|
if (m_pParentGroup != pe.m_pParentGroup) return false;
|
||||||
if (!bIgnoreLastMod && (m_tParentGroupLastMod != pe.m_tParentGroupLastMod))
|
if (!bIgnoreLastMod && (m_tParentGroupLastMod != pe.m_tParentGroupLastMod))
|
||||||
return false;
|
return false;
|
||||||
|
if (!m_puPrevParentGroup.Equals(pe.m_puPrevParentGroup))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_listStrings.EqualsDictionary(pe.m_listStrings, pwOpt, mpCmpStr))
|
if (!m_dStrings.EqualsDictionary(pe.m_dStrings, pwOpt, mpCmpStr))
|
||||||
return false;
|
return false;
|
||||||
if (!m_listBinaries.EqualsDictionary(pe.m_listBinaries)) return false;
|
if (!m_dBinaries.EqualsDictionary(pe.m_dBinaries)) return false;
|
||||||
|
|
||||||
if (!m_listAutoType.Equals(pe.m_listAutoType)) return false;
|
if (!m_cfgAutoType.Equals(pe.m_cfgAutoType)) return false;
|
||||||
|
|
||||||
if ((pwOpt & PwCompareOptions.IgnoreHistory) == PwCompareOptions.None)
|
if ((pwOpt & PwCompareOptions.IgnoreHistory) == PwCompareOptions.None)
|
||||||
{
|
{
|
||||||
bool bIgnoreLastBackup = ((pwOpt & PwCompareOptions.IgnoreLastBackup) !=
|
bool bIgnoreLastBackup = ((pwOpt & PwCompareOptions.IgnoreLastBackup) !=
|
||||||
PwCompareOptions.None);
|
PwCompareOptions.None);
|
||||||
|
|
||||||
if (!bIgnoreLastBackup && (m_listHistory.UCount != pe.m_listHistory.UCount))
|
if (!bIgnoreLastBackup && (m_lHistory.UCount != pe.m_lHistory.UCount))
|
||||||
return false;
|
return false;
|
||||||
if (bIgnoreLastBackup && (m_listHistory.UCount == 0))
|
if (bIgnoreLastBackup && (m_lHistory.UCount == 0))
|
||||||
{
|
{
|
||||||
Debug.Assert(false);
|
Debug.Assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (bIgnoreLastBackup && ((m_listHistory.UCount - 1) != pe.m_listHistory.UCount))
|
if (bIgnoreLastBackup && ((m_lHistory.UCount - 1) != pe.m_lHistory.UCount))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PwCompareOptions cmpSub = PwCompareOptions.IgnoreParentGroup;
|
PwCompareOptions cmpSub = PwCompareOptions.IgnoreParentGroup;
|
||||||
@@ -485,16 +506,16 @@ namespace KeePassLib
|
|||||||
if (bIgnoreLastMod) cmpSub |= PwCompareOptions.IgnoreLastMod;
|
if (bIgnoreLastMod) cmpSub |= PwCompareOptions.IgnoreLastMod;
|
||||||
if (bIgnoreLastAccess) cmpSub |= PwCompareOptions.IgnoreLastAccess;
|
if (bIgnoreLastAccess) cmpSub |= PwCompareOptions.IgnoreLastAccess;
|
||||||
|
|
||||||
for (uint uHist = 0; uHist < pe.m_listHistory.UCount; ++uHist)
|
for (uint uHist = 0; uHist < pe.m_lHistory.UCount; ++uHist)
|
||||||
{
|
{
|
||||||
if (!m_listHistory.GetAt(uHist).EqualsEntry(pe.m_listHistory.GetAt(
|
if (!m_lHistory.GetAt(uHist).EqualsEntry(pe.m_lHistory.GetAt(
|
||||||
uHist), cmpSub, MemProtCmpMode.None))
|
uHist), cmpSub, MemProtCmpMode.None))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pwIcon != pe.m_pwIcon) return false;
|
if (m_pwIcon != pe.m_pwIcon) return false;
|
||||||
if (!m_pwCustomIconID.Equals(pe.m_pwCustomIconID)) return false;
|
if (!m_puCustomIcon.Equals(pe.m_puCustomIcon)) return false;
|
||||||
|
|
||||||
if (m_clrForeground != pe.m_clrForeground) return false;
|
if (m_clrForeground != pe.m_clrForeground) return false;
|
||||||
if (m_clrBackground != pe.m_clrBackground) return false;
|
if (m_clrBackground != pe.m_clrBackground) return false;
|
||||||
@@ -507,12 +528,10 @@ namespace KeePassLib
|
|||||||
if (!bIgnoreLastAccess && (m_uUsageCount != pe.m_uUsageCount)) return false;
|
if (!bIgnoreLastAccess && (m_uUsageCount != pe.m_uUsageCount)) return false;
|
||||||
|
|
||||||
if (m_strOverrideUrl != pe.m_strOverrideUrl) return false;
|
if (m_strOverrideUrl != pe.m_strOverrideUrl) return false;
|
||||||
|
if (m_bQualityCheck != pe.m_bQualityCheck) return false;
|
||||||
|
|
||||||
if (m_vTags.Count != pe.m_vTags.Count) return false;
|
// The Tags property normalizes
|
||||||
for (int iTag = 0; iTag < m_vTags.Count; ++iTag)
|
if (!MemUtil.ListsEqual<string>(this.Tags, pe.Tags)) return false;
|
||||||
{
|
|
||||||
if (m_vTags[iTag] != pe.m_vTags[iTag]) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_dCustomData.Equals(pe.m_dCustomData)) return false;
|
if (!m_dCustomData.Equals(pe.m_dCustomData)) return false;
|
||||||
|
|
||||||
@@ -543,16 +562,19 @@ namespace KeePassLib
|
|||||||
m_uuid = peTemplate.m_uuid;
|
m_uuid = peTemplate.m_uuid;
|
||||||
|
|
||||||
if (bAssignLocationChanged)
|
if (bAssignLocationChanged)
|
||||||
|
{
|
||||||
m_tParentGroupLastMod = peTemplate.m_tParentGroupLastMod;
|
m_tParentGroupLastMod = peTemplate.m_tParentGroupLastMod;
|
||||||
|
m_puPrevParentGroup = peTemplate.m_puPrevParentGroup;
|
||||||
|
}
|
||||||
|
|
||||||
m_listStrings = peTemplate.m_listStrings.CloneDeep();
|
m_dStrings = peTemplate.m_dStrings.CloneDeep();
|
||||||
m_listBinaries = peTemplate.m_listBinaries.CloneDeep();
|
m_dBinaries = peTemplate.m_dBinaries.CloneDeep();
|
||||||
m_listAutoType = peTemplate.m_listAutoType.CloneDeep();
|
m_cfgAutoType = peTemplate.m_cfgAutoType.CloneDeep();
|
||||||
if (bIncludeHistory)
|
if (bIncludeHistory)
|
||||||
m_listHistory = peTemplate.m_listHistory.CloneDeep();
|
m_lHistory = peTemplate.m_lHistory.CloneDeep();
|
||||||
|
|
||||||
m_pwIcon = peTemplate.m_pwIcon;
|
m_pwIcon = peTemplate.m_pwIcon;
|
||||||
m_pwCustomIconID = peTemplate.m_pwCustomIconID; // Immutable
|
m_puCustomIcon = peTemplate.m_puCustomIcon; // Immutable
|
||||||
|
|
||||||
m_clrForeground = peTemplate.m_clrForeground;
|
m_clrForeground = peTemplate.m_clrForeground;
|
||||||
m_clrBackground = peTemplate.m_clrBackground;
|
m_clrBackground = peTemplate.m_clrBackground;
|
||||||
@@ -565,8 +587,9 @@ namespace KeePassLib
|
|||||||
m_uUsageCount = peTemplate.m_uUsageCount;
|
m_uUsageCount = peTemplate.m_uUsageCount;
|
||||||
|
|
||||||
m_strOverrideUrl = peTemplate.m_strOverrideUrl;
|
m_strOverrideUrl = peTemplate.m_strOverrideUrl;
|
||||||
|
m_bQualityCheck = peTemplate.m_bQualityCheck;
|
||||||
|
|
||||||
m_vTags = new List<string>(peTemplate.m_vTags);
|
m_lTags = new List<string>(peTemplate.m_lTags);
|
||||||
|
|
||||||
m_dCustomData = peTemplate.m_dCustomData.CloneDeep();
|
m_dCustomData = peTemplate.m_dCustomData.CloneDeep();
|
||||||
}
|
}
|
||||||
@@ -629,9 +652,9 @@ namespace KeePassLib
|
|||||||
public void CreateBackup(PwDatabase pwHistMntcSettings)
|
public void CreateBackup(PwDatabase pwHistMntcSettings)
|
||||||
{
|
{
|
||||||
PwEntry peCopy = CloneDeep();
|
PwEntry peCopy = CloneDeep();
|
||||||
peCopy.History = new PwObjectList<PwEntry>(); // Remove history
|
peCopy.m_lHistory.Clear();
|
||||||
|
|
||||||
m_listHistory.Add(peCopy); // Must be added at end, see EqualsEntry
|
m_lHistory.Add(peCopy); // Must be added at end, see EqualsEntry
|
||||||
|
|
||||||
if (pwHistMntcSettings != null) MaintainBackups(pwHistMntcSettings);
|
if (pwHistMntcSettings != null) MaintainBackups(pwHistMntcSettings);
|
||||||
}
|
}
|
||||||
@@ -658,12 +681,14 @@ namespace KeePassLib
|
|||||||
/// This parameter may be <c>null</c> (no maintenance then).</param>
|
/// This parameter may be <c>null</c> (no maintenance then).</param>
|
||||||
public void RestoreFromBackup(uint uBackupIndex, PwDatabase pwHistMntcSettings)
|
public void RestoreFromBackup(uint uBackupIndex, PwDatabase pwHistMntcSettings)
|
||||||
{
|
{
|
||||||
Debug.Assert(uBackupIndex < m_listHistory.UCount);
|
if (uBackupIndex >= m_lHistory.UCount)
|
||||||
if (uBackupIndex >= m_listHistory.UCount)
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
throw new ArgumentOutOfRangeException("uBackupIndex");
|
throw new ArgumentOutOfRangeException("uBackupIndex");
|
||||||
|
}
|
||||||
|
|
||||||
PwEntry pe = m_listHistory.GetAt(uBackupIndex);
|
PwEntry pe = m_lHistory.GetAt(uBackupIndex);
|
||||||
Debug.Assert(pe != null); if (pe == null) throw new InvalidOperationException();
|
if (pe == null) { Debug.Assert(false); throw new InvalidOperationException(); }
|
||||||
|
|
||||||
CreateBackup(pwHistMntcSettings); // Backup current data before restoring
|
CreateBackup(pwHistMntcSettings); // Backup current data before restoring
|
||||||
AssignProperties(pe, false, false, false);
|
AssignProperties(pe, false, false, false);
|
||||||
@@ -679,7 +704,7 @@ namespace KeePassLib
|
|||||||
if (bIgnoreLastMod) cmpOpt |= PwCompareOptions.IgnoreLastMod;
|
if (bIgnoreLastMod) cmpOpt |= PwCompareOptions.IgnoreLastMod;
|
||||||
if (bIgnoreLastAccess) cmpOpt |= PwCompareOptions.IgnoreLastAccess;
|
if (bIgnoreLastAccess) cmpOpt |= PwCompareOptions.IgnoreLastAccess;
|
||||||
|
|
||||||
foreach (PwEntry pe in m_listHistory)
|
foreach (PwEntry pe in m_lHistory)
|
||||||
{
|
{
|
||||||
if (pe.EqualsEntry(peData, cmpOpt, MemProtCmpMode.None)) return true;
|
if (pe.EqualsEntry(peData, cmpOpt, MemProtCmpMode.None)) return true;
|
||||||
}
|
}
|
||||||
@@ -688,21 +713,28 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete old history items if there are too many or the history
|
/// Delete old history entries if there are too many or the
|
||||||
/// size is too large.
|
/// history size is too large.
|
||||||
/// <returns>If one or more history items have been deleted, <c>true</c>
|
/// <returns>If one or more history entries have been deleted,
|
||||||
/// is returned. Otherwise <c>false</c>.</returns>
|
/// <c>true</c> is returned. Otherwise <c>false</c>.</returns>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool MaintainBackups(PwDatabase pwSettings)
|
public bool MaintainBackups(PwDatabase pwSettings)
|
||||||
{
|
{
|
||||||
if (pwSettings == null) { Debug.Assert(false); return false; }
|
if (pwSettings == null) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
|
// Fix UUIDs of history entries; should not be necessary
|
||||||
|
PwUuid pu = m_uuid;
|
||||||
|
foreach (PwEntry pe in m_lHistory)
|
||||||
|
{
|
||||||
|
if (!pe.Uuid.Equals(pu)) { Debug.Assert(false); pe.Uuid = pu; }
|
||||||
|
}
|
||||||
|
|
||||||
bool bDeleted = false;
|
bool bDeleted = false;
|
||||||
|
|
||||||
int nMaxItems = pwSettings.HistoryMaxItems;
|
int nMaxItems = pwSettings.HistoryMaxItems;
|
||||||
if (nMaxItems >= 0)
|
if (nMaxItems >= 0)
|
||||||
{
|
{
|
||||||
while (m_listHistory.UCount > (uint)nMaxItems)
|
while (m_lHistory.UCount > (uint)nMaxItems)
|
||||||
{
|
{
|
||||||
RemoveOldestBackup();
|
RemoveOldestBackup();
|
||||||
bDeleted = true;
|
bDeleted = true;
|
||||||
@@ -715,7 +747,7 @@ namespace KeePassLib
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
ulong uHistSize = 0;
|
ulong uHistSize = 0;
|
||||||
foreach (PwEntry pe in m_listHistory) { uHistSize += pe.GetSize(); }
|
foreach (PwEntry pe in m_lHistory) { uHistSize += pe.GetSize(); }
|
||||||
|
|
||||||
if (uHistSize > (ulong)lMaxSize)
|
if (uHistSize > (ulong)lMaxSize)
|
||||||
{
|
{
|
||||||
@@ -734,9 +766,9 @@ namespace KeePassLib
|
|||||||
DateTime dtMin = TimeUtil.SafeMaxValueUtc;
|
DateTime dtMin = TimeUtil.SafeMaxValueUtc;
|
||||||
uint idxRemove = uint.MaxValue;
|
uint idxRemove = uint.MaxValue;
|
||||||
|
|
||||||
for (uint u = 0; u < m_listHistory.UCount; ++u)
|
for (uint u = 0; u < m_lHistory.UCount; ++u)
|
||||||
{
|
{
|
||||||
PwEntry pe = m_listHistory.GetAt(u);
|
PwEntry pe = m_lHistory.GetAt(u);
|
||||||
if (TimeUtil.Compare(pe.LastModificationTime, dtMin, true) < 0)
|
if (TimeUtil.Compare(pe.LastModificationTime, dtMin, true) < 0)
|
||||||
{
|
{
|
||||||
idxRemove = u;
|
idxRemove = u;
|
||||||
@@ -744,12 +776,12 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idxRemove != uint.MaxValue) m_listHistory.RemoveAt(idxRemove);
|
if (idxRemove != uint.MaxValue) m_lHistory.RemoveAt(idxRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetAutoTypeEnabled()
|
public bool GetAutoTypeEnabled()
|
||||||
{
|
{
|
||||||
if (!m_listAutoType.Enabled) return false;
|
if (!m_cfgAutoType.Enabled) return false;
|
||||||
|
|
||||||
if (m_pParentGroup != null)
|
if (m_pParentGroup != null)
|
||||||
return m_pParentGroup.GetAutoTypeEnabledInherited();
|
return m_pParentGroup.GetAutoTypeEnabledInherited();
|
||||||
@@ -759,7 +791,7 @@ namespace KeePassLib
|
|||||||
|
|
||||||
public string GetAutoTypeSequence()
|
public string GetAutoTypeSequence()
|
||||||
{
|
{
|
||||||
string strSeq = m_listAutoType.DefaultSequence;
|
string strSeq = m_cfgAutoType.DefaultSequence;
|
||||||
|
|
||||||
PwGroup pg = m_pParentGroup;
|
PwGroup pg = m_pParentGroup;
|
||||||
while (pg != null)
|
while (pg != null)
|
||||||
@@ -785,69 +817,67 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Approximate the total size of this entry in bytes (including
|
/// Approximate the total size (in process memory) of this entry
|
||||||
/// strings, binaries and history entries).
|
/// in bytes (including strings, binaries and history entries).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Size in bytes.</returns>
|
/// <returns>Size in bytes.</returns>
|
||||||
public ulong GetSize()
|
public ulong GetSize()
|
||||||
{
|
{
|
||||||
ulong uSize = 128; // Approx fixed length data
|
// This method assumes 64-bit pointers/references and Unicode
|
||||||
|
// strings (i.e. 2 bytes per character)
|
||||||
|
|
||||||
foreach (KeyValuePair<string, ProtectedString> kvpStr in m_listStrings)
|
ulong cb = 276; // Number of bytes; approx. fixed length data
|
||||||
|
ulong cc = 0; // Number of characters
|
||||||
|
|
||||||
|
cb += (ulong)m_dStrings.UCount * 40;
|
||||||
|
foreach (KeyValuePair<string, ProtectedString> kvpStr in m_dStrings)
|
||||||
|
cc += (ulong)kvpStr.Key.Length + (ulong)kvpStr.Value.Length;
|
||||||
|
|
||||||
|
cb += (ulong)m_dBinaries.UCount * 65;
|
||||||
|
foreach (KeyValuePair<string, ProtectedBinary> kvpBin in m_dBinaries)
|
||||||
{
|
{
|
||||||
uSize += (ulong)kvpStr.Key.Length;
|
cc += (ulong)kvpBin.Key.Length;
|
||||||
uSize += (ulong)kvpStr.Value.Length;
|
cb += (ulong)kvpBin.Value.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (KeyValuePair<string, ProtectedBinary> kvpBin in m_listBinaries)
|
cc += (ulong)m_cfgAutoType.DefaultSequence.Length;
|
||||||
{
|
cb += (ulong)m_cfgAutoType.AssociationsCount * 24;
|
||||||
uSize += (ulong)kvpBin.Key.Length;
|
foreach (AutoTypeAssociation a in m_cfgAutoType.Associations)
|
||||||
uSize += kvpBin.Value.Length;
|
cc += (ulong)a.WindowName.Length + (ulong)a.Sequence.Length;
|
||||||
}
|
|
||||||
|
|
||||||
uSize += (ulong)m_listAutoType.DefaultSequence.Length;
|
cb += (ulong)m_lHistory.UCount * 8;
|
||||||
foreach (AutoTypeAssociation a in m_listAutoType.Associations)
|
foreach (PwEntry peHistory in m_lHistory)
|
||||||
{
|
cb += peHistory.GetSize();
|
||||||
uSize += (ulong)a.WindowName.Length;
|
|
||||||
uSize += (ulong)a.Sequence.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (PwEntry peHistory in m_listHistory)
|
cc += (ulong)m_strOverrideUrl.Length;
|
||||||
uSize += peHistory.GetSize();
|
|
||||||
|
|
||||||
uSize += (ulong)m_strOverrideUrl.Length;
|
cb += (ulong)m_lTags.Count * 8;
|
||||||
|
foreach (string strTag in m_lTags)
|
||||||
foreach (string strTag in m_vTags)
|
cc += (ulong)strTag.Length;
|
||||||
uSize += (ulong)strTag.Length;
|
|
||||||
|
|
||||||
|
cb += (ulong)m_dCustomData.Count * 16;
|
||||||
foreach (KeyValuePair<string, string> kvp in m_dCustomData)
|
foreach (KeyValuePair<string, string> kvp in m_dCustomData)
|
||||||
uSize += (ulong)kvp.Key.Length + (ulong)kvp.Value.Length;
|
cc += (ulong)kvp.Key.Length + (ulong)kvp.Value.Length;
|
||||||
|
|
||||||
return uSize;
|
return (cb + (cc << 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasTag(string strTag)
|
public bool HasTag(string strTag)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(strTag)) { Debug.Assert(false); return false; }
|
if (string.IsNullOrEmpty(strTag)) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
for (int i = 0; i < m_vTags.Count; ++i)
|
// this.Tags normalizes
|
||||||
{
|
return this.Tags.Contains(StrUtil.NormalizeTag(strTag));
|
||||||
if (m_vTags[i].Equals(strTag, StrUtil.CaseIgnoreCmp)) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AddTag(string strTag)
|
public bool AddTag(string strTag)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(strTag)) { Debug.Assert(false); return false; }
|
if (string.IsNullOrEmpty(strTag)) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
for (int i = 0; i < m_vTags.Count; ++i)
|
strTag = StrUtil.NormalizeTag(strTag);
|
||||||
{
|
if (this.Tags.Contains(strTag)) return false; // this.Tags normalizes
|
||||||
if (m_vTags[i].Equals(strTag, StrUtil.CaseIgnoreCmp)) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_vTags.Add(strTag);
|
m_lTags.Add(strTag);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,16 +885,17 @@ namespace KeePassLib
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(strTag)) { Debug.Assert(false); return false; }
|
if (string.IsNullOrEmpty(strTag)) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
for (int i = 0; i < m_vTags.Count; ++i)
|
// this.Tags normalizes
|
||||||
{
|
return this.Tags.Remove(StrUtil.NormalizeTag(strTag));
|
||||||
if (m_vTags[i].Equals(strTag, StrUtil.CaseIgnoreCmp))
|
|
||||||
{
|
|
||||||
m_vTags.RemoveAt(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
internal List<string> GetTagsInherited()
|
||||||
|
{
|
||||||
|
List<string> l = ((m_pParentGroup != null) ?
|
||||||
|
m_pParentGroup.GetTagsInherited(false) : new List<string>());
|
||||||
|
l.AddRange(this.Tags);
|
||||||
|
StrUtil.NormalizeTags(l);
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsContainedIn(PwGroup pgContainer)
|
public bool IsContainedIn(PwGroup pgContainer)
|
||||||
@@ -886,12 +917,10 @@ namespace KeePassLib
|
|||||||
|
|
||||||
if (bAlsoChangeHistoryUuids)
|
if (bAlsoChangeHistoryUuids)
|
||||||
{
|
{
|
||||||
foreach (PwEntry peHist in m_listHistory)
|
foreach (PwEntry peHist in m_lHistory)
|
||||||
{
|
|
||||||
peHist.Uuid = pwNewUuid;
|
peHist.Uuid = pwNewUuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void SetCreatedNow()
|
public void SetCreatedNow()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -316,4 +316,13 @@ namespace KeePassLib
|
|||||||
Cinnamon,
|
Cinnamon,
|
||||||
Pantheon
|
Pantheon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public enum PwSearchMode
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Simple,
|
||||||
|
Regular,
|
||||||
|
XPath
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
372
src/KeePassLib2Android/PwGroup.Search.cs
Normal file
372
src/KeePassLib2Android/PwGroup.Search.cs
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
/*
|
||||||
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.XPath;
|
||||||
|
|
||||||
|
using KeePassLib.Collections;
|
||||||
|
using KeePassLib.Delegates;
|
||||||
|
using KeePassLib.Interfaces;
|
||||||
|
using KeePassLib.Security;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
|
namespace KeePassLib
|
||||||
|
{
|
||||||
|
public sealed partial class PwGroup
|
||||||
|
{
|
||||||
|
private const int SearchContextStringMaxLength = 50; // Note, doesn't include elipsis, if added
|
||||||
|
public const string SearchContextUuid = "Uuid";
|
||||||
|
public const string SearchContextParentGroup = "Parent Group";
|
||||||
|
public const string SearchContextTags = "Tags";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search this group and all subgroups for entries.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sp">Specifies the search method.</param>
|
||||||
|
/// <param name="listStorage">Entry list in which the search results will
|
||||||
|
/// be stored.</param>
|
||||||
|
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage)
|
||||||
|
{
|
||||||
|
SearchEntries(sp, listStorage, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search this group and all subgroups for entries.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sp">Specifies the search method.</param>
|
||||||
|
/// <param name="listStorage">Entry list in which the search results will
|
||||||
|
/// be stored.</param>
|
||||||
|
/// <param name="slStatus">Optional status reporting object.</param>
|
||||||
|
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage,
|
||||||
|
IStatusLogger slStatus)
|
||||||
|
{
|
||||||
|
SearchEntries(sp, listStorage, null, slStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search this group and all subgroups for entries.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sp">Specifies the search method.</param>
|
||||||
|
/// <param name="listStorage">Entry list in which the search results will
|
||||||
|
/// be stored.</param>
|
||||||
|
/// <param name="resultContexts">Dictionary that will be populated with text fragments indicating the context of why each entry (keyed by Uuid) was returned</param>
|
||||||
|
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage,
|
||||||
|
IDictionary<PwUuid, KeyValuePair<string, string>> resultContexts,
|
||||||
|
IStatusLogger slStatus)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (sp == null)
|
||||||
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listStorage == null)
|
||||||
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong uCurEntries = 0, uTotalEntries = 0;
|
||||||
|
|
||||||
|
List<string> lTerms = StrUtil.SplitSearchTerms(sp.SearchString);
|
||||||
|
if ((lTerms.Count <= 1) || sp.RegularExpression)
|
||||||
|
{
|
||||||
|
if (slStatus != null) uTotalEntries = GetEntriesCount(true);
|
||||||
|
SearchEntriesSingle(sp, listStorage, resultContexts, slStatus, ref uCurEntries,
|
||||||
|
uTotalEntries);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search longer strings first (for improved performance)
|
||||||
|
lTerms.Sort(StrUtil.CompareLengthGt);
|
||||||
|
|
||||||
|
string strFullSearch = sp.SearchString; // Backup
|
||||||
|
|
||||||
|
PwGroup pg = this;
|
||||||
|
for (int iTerm = 0; iTerm < lTerms.Count; ++iTerm)
|
||||||
|
{
|
||||||
|
// Update counters for a better state guess
|
||||||
|
if (slStatus != null)
|
||||||
|
{
|
||||||
|
ulong uRemRounds = (ulong) (lTerms.Count - iTerm);
|
||||||
|
uTotalEntries = uCurEntries + (uRemRounds *
|
||||||
|
pg.GetEntriesCount(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
PwGroup pgNew = new PwGroup();
|
||||||
|
|
||||||
|
sp.SearchString = lTerms[iTerm];
|
||||||
|
|
||||||
|
bool bNegate = false;
|
||||||
|
if (sp.SearchString.StartsWith("-"))
|
||||||
|
{
|
||||||
|
sp.SearchString = sp.SearchString.Substring(1);
|
||||||
|
bNegate = (sp.SearchString.Length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pg.SearchEntriesSingle(sp, pgNew.Entries, resultContexts, slStatus,
|
||||||
|
ref uCurEntries, uTotalEntries))
|
||||||
|
{
|
||||||
|
pg = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bNegate)
|
||||||
|
{
|
||||||
|
PwObjectList<PwEntry> lCand = pg.GetEntries(true);
|
||||||
|
|
||||||
|
pg = new PwGroup();
|
||||||
|
foreach (PwEntry peCand in lCand)
|
||||||
|
{
|
||||||
|
if (pgNew.Entries.IndexOf(peCand) < 0) pg.Entries.Add(peCand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else pg = pgNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pg != null) listStorage.Add(pg.Entries);
|
||||||
|
sp.SearchString = strFullSearch; // Restore
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SearchEntriesSingle(SearchParameters spIn,
|
||||||
|
PwObjectList<PwEntry> listStorage, IDictionary<PwUuid, KeyValuePair<string, string>> resultContexts,
|
||||||
|
IStatusLogger slStatus,
|
||||||
|
ref ulong uCurEntries, ulong uTotalEntries)
|
||||||
|
{
|
||||||
|
SearchParameters sp = spIn.Clone();
|
||||||
|
if (sp.SearchString == null)
|
||||||
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp.SearchString = sp.SearchString.Trim();
|
||||||
|
|
||||||
|
bool bTitle = sp.SearchInTitles;
|
||||||
|
bool bUserName = sp.SearchInUserNames;
|
||||||
|
bool bPassword = sp.SearchInPasswords;
|
||||||
|
bool bUrl = sp.SearchInUrls;
|
||||||
|
bool bNotes = sp.SearchInNotes;
|
||||||
|
bool bOther = sp.SearchInOther;
|
||||||
|
bool bUuids = sp.SearchInUuids;
|
||||||
|
bool bGroupName = sp.SearchInGroupNames;
|
||||||
|
bool bTags = sp.SearchInTags;
|
||||||
|
bool bExcludeExpired = sp.ExcludeExpired;
|
||||||
|
bool bRespectEntrySearchingDisabled = sp.RespectEntrySearchingDisabled;
|
||||||
|
|
||||||
|
DateTime dtNow = DateTime.Now;
|
||||||
|
|
||||||
|
Regex rx = null;
|
||||||
|
if (sp.RegularExpression)
|
||||||
|
{
|
||||||
|
RegexOptions ro = RegexOptions.None; // RegexOptions.Compiled
|
||||||
|
if ((sp.ComparisonMode == StringComparison.CurrentCultureIgnoreCase) ||
|
||||||
|
#if !KeePassUAP
|
||||||
|
(sp.ComparisonMode == StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
#endif
|
||||||
|
(sp.ComparisonMode == StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
ro |= RegexOptions.IgnoreCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
rx = new Regex(sp.SearchString, ro);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong uLocalCurEntries = uCurEntries;
|
||||||
|
|
||||||
|
EntryHandler eh = null;
|
||||||
|
if (sp.SearchString.Length <= 0) // Report all
|
||||||
|
{
|
||||||
|
eh = delegate(PwEntry pe)
|
||||||
|
{
|
||||||
|
if (slStatus != null)
|
||||||
|
{
|
||||||
|
if (!slStatus.SetProgress((uint) ((uLocalCurEntries *
|
||||||
|
100UL) / uTotalEntries))) return false;
|
||||||
|
++uLocalCurEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bRespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
||||||
|
return true; // Skip
|
||||||
|
if (bExcludeExpired && pe.Expires && (dtNow > pe.ExpiryTime))
|
||||||
|
return true; // Skip
|
||||||
|
|
||||||
|
listStorage.Add(pe);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eh = delegate(PwEntry pe)
|
||||||
|
{
|
||||||
|
if (slStatus != null)
|
||||||
|
{
|
||||||
|
if (!slStatus.SetProgress((uint) ((uLocalCurEntries *
|
||||||
|
100UL) / uTotalEntries))) return false;
|
||||||
|
++uLocalCurEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bRespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
||||||
|
return true; // Skip
|
||||||
|
if (bExcludeExpired && pe.Expires && (dtNow > pe.ExpiryTime))
|
||||||
|
return true; // Skip
|
||||||
|
|
||||||
|
uint uInitialResults = listStorage.UCount;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<string, ProtectedString> kvp in pe.Strings)
|
||||||
|
{
|
||||||
|
string strKey = kvp.Key;
|
||||||
|
|
||||||
|
if (strKey == PwDefs.TitleField)
|
||||||
|
{
|
||||||
|
if (bTitle)
|
||||||
|
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
|
}
|
||||||
|
else if (strKey == PwDefs.UserNameField)
|
||||||
|
{
|
||||||
|
if (bUserName)
|
||||||
|
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
|
}
|
||||||
|
else if (strKey == PwDefs.PasswordField)
|
||||||
|
{
|
||||||
|
if (bPassword)
|
||||||
|
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
|
}
|
||||||
|
else if (strKey == PwDefs.UrlField)
|
||||||
|
{
|
||||||
|
if (bUrl)
|
||||||
|
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
|
}
|
||||||
|
else if (strKey == PwDefs.NotesField)
|
||||||
|
{
|
||||||
|
if (bNotes)
|
||||||
|
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
|
}
|
||||||
|
else if (bOther)
|
||||||
|
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
||||||
|
rx, pe, listStorage, resultContexts, strKey);
|
||||||
|
|
||||||
|
// An entry can match only once => break if we have added it
|
||||||
|
if (listStorage.UCount > uInitialResults) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bUuids && (listStorage.UCount == uInitialResults))
|
||||||
|
SearchEvalAdd(sp, pe.Uuid.ToHexString(), rx, pe, listStorage, resultContexts,
|
||||||
|
SearchContextTags);
|
||||||
|
|
||||||
|
if (bGroupName && (listStorage.UCount == uInitialResults) &&
|
||||||
|
(pe.ParentGroup != null))
|
||||||
|
SearchEvalAdd(sp, pe.ParentGroup.Name, rx, pe, listStorage, resultContexts,
|
||||||
|
SearchContextParentGroup);
|
||||||
|
|
||||||
|
if (bTags)
|
||||||
|
{
|
||||||
|
foreach (string strTag in pe.Tags)
|
||||||
|
{
|
||||||
|
if (listStorage.UCount != uInitialResults) break; // Match
|
||||||
|
|
||||||
|
SearchEvalAdd(sp, strTag, rx, pe, listStorage, resultContexts, SearchContextTags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PreOrderTraverseTree(null, eh)) return false;
|
||||||
|
uCurEntries = uLocalCurEntries;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SearchEvalAdd(SearchParameters sp, string strDataField,
|
||||||
|
Regex rx, PwEntry pe, PwObjectList<PwEntry> lResults,
|
||||||
|
IDictionary<PwUuid, KeyValuePair<string, string>> resultContexts, string contextFieldName)
|
||||||
|
{
|
||||||
|
bool bMatch = false;
|
||||||
|
int matchPos;
|
||||||
|
if (rx == null)
|
||||||
|
{
|
||||||
|
matchPos = strDataField.IndexOf(sp.SearchString, sp.ComparisonMode);
|
||||||
|
bMatch = matchPos >= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var match = rx.Match(strDataField);
|
||||||
|
bMatch = match.Success;
|
||||||
|
matchPos = match.Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bMatch && (sp.DataTransformationFn != null))
|
||||||
|
{
|
||||||
|
string strCmp = sp.DataTransformationFn(strDataField, pe);
|
||||||
|
if (!object.ReferenceEquals(strCmp, strDataField))
|
||||||
|
{
|
||||||
|
if (rx == null)
|
||||||
|
{
|
||||||
|
matchPos = strCmp.IndexOf(sp.SearchString, sp.ComparisonMode);
|
||||||
|
bMatch = matchPos >= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var match = rx.Match(strCmp);
|
||||||
|
bMatch = match.Success;
|
||||||
|
matchPos = match.Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bMatch)
|
||||||
|
{
|
||||||
|
lResults.Add(pe);
|
||||||
|
|
||||||
|
if (resultContexts != null)
|
||||||
|
{
|
||||||
|
// Trim the value if necessary
|
||||||
|
var contextString = strDataField;
|
||||||
|
if (contextString.Length > SearchContextStringMaxLength)
|
||||||
|
{
|
||||||
|
// Start 10% before actual data, and don't run over
|
||||||
|
var startPos = Math.Max(0,
|
||||||
|
Math.Min(matchPos - (SearchContextStringMaxLength / 10),
|
||||||
|
contextString.Length - SearchContextStringMaxLength));
|
||||||
|
contextString = "… " + contextString.Substring(startPos, SearchContextStringMaxLength) +
|
||||||
|
((startPos + SearchContextStringMaxLength < contextString.Length)
|
||||||
|
? " …"
|
||||||
|
: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
resultContexts[pe.Uuid] = new KeyValuePair<string, string>(contextFieldName, contextString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,35 +20,36 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text;
|
||||||
|
|
||||||
using KeePassLib.Collections;
|
using KeePassLib.Collections;
|
||||||
using KeePassLib.Delegates;
|
using KeePassLib.Delegates;
|
||||||
using KeePassLib.Interfaces;
|
using KeePassLib.Interfaces;
|
||||||
using KeePassLib.Security;
|
using KeePassLib.Resources;
|
||||||
using KeePassLib.Utility;
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
namespace KeePassLib
|
namespace KeePassLib
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A group containing several password entries.
|
/// A group containing subgroups and entries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class PwGroup : ITimeLogger, IStructureItem, IDeepCloneable<PwGroup>
|
public sealed partial class PwGroup : ITimeLogger, IStructureItem, IDeepCloneable<PwGroup>
|
||||||
{
|
{
|
||||||
private const int SearchContextStringMaxLength = 50; // Note, doesn't include elipsis, if added
|
|
||||||
public const string SearchContextUuid = "Uuid";
|
|
||||||
public const string SearchContextParentGroup = "Parent Group";
|
|
||||||
public const string SearchContextTags = "Tags";
|
|
||||||
|
|
||||||
public const bool DefaultAutoTypeEnabled = true;
|
public const bool DefaultAutoTypeEnabled = true;
|
||||||
public const bool DefaultSearchingEnabled = true;
|
public const bool DefaultSearchingEnabled = true;
|
||||||
|
|
||||||
private PwObjectList<PwGroup> m_listGroups = new PwObjectList<PwGroup>();
|
// In the tree view of Windows 10, the X coordinate is reset
|
||||||
private PwObjectList<PwEntry> m_listEntries = new PwObjectList<PwEntry>();
|
// to 0 after 256 nested nodes
|
||||||
private PwGroup m_pParentGroup = null;
|
private const uint MaxDepth = 126; // Depth 126 = level 127 < 256/2
|
||||||
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
|
||||||
|
|
||||||
private PwUuid m_uuid = PwUuid.Zero;
|
private PwUuid m_uuid = PwUuid.Zero;
|
||||||
|
private PwGroup m_pParentGroup = null;
|
||||||
|
private DateTime m_tParentGroupLastMod = PwDefs.DtDefaultNow;
|
||||||
|
private PwUuid m_puPrevParentGroup = PwUuid.Zero;
|
||||||
|
|
||||||
|
private PwObjectList<PwGroup> m_listGroups = new PwObjectList<PwGroup>();
|
||||||
|
private PwObjectList<PwEntry> m_listEntries = new PwObjectList<PwEntry>();
|
||||||
|
|
||||||
private string m_strName = string.Empty;
|
private string m_strName = string.Empty;
|
||||||
private string m_strNotes = string.Empty;
|
private string m_strNotes = string.Empty;
|
||||||
|
|
||||||
@@ -72,6 +73,8 @@ namespace KeePassLib
|
|||||||
|
|
||||||
private PwUuid m_pwLastTopVisibleEntry = PwUuid.Zero;
|
private PwUuid m_pwLastTopVisibleEntry = PwUuid.Zero;
|
||||||
|
|
||||||
|
private List<string> m_lTags = new List<string>();
|
||||||
|
|
||||||
private StringDictionaryEx m_dCustomData = new StringDictionaryEx();
|
private StringDictionaryEx m_dCustomData = new StringDictionaryEx();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -82,11 +85,42 @@ namespace KeePassLib
|
|||||||
get { return m_uuid; }
|
get { return m_uuid; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_uuid = value;
|
m_uuid = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reference to the group to which this group belongs. May be <c>null</c>.
|
||||||
|
/// </summary>
|
||||||
|
public PwGroup ParentGroup
|
||||||
|
{
|
||||||
|
get { return m_pParentGroup; }
|
||||||
|
|
||||||
|
// Plugins: use the PwGroup.AddGroup method instead.
|
||||||
|
// Internal: check depth using CanAddGroup/CheckCanAddGroup.
|
||||||
|
internal set { Debug.Assert(value != this); m_pParentGroup = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The date/time when the location of the object was last changed.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime LocationChanged
|
||||||
|
{
|
||||||
|
get { return m_tParentGroupLastMod; }
|
||||||
|
set { m_tParentGroupLastMod = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public PwUuid PreviousParentGroup
|
||||||
|
{
|
||||||
|
get { return m_puPrevParentGroup; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
|
m_puPrevParentGroup = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this group. Cannot be <c>null</c>.
|
/// The name of this group. Cannot be <c>null</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -95,7 +129,7 @@ namespace KeePassLib
|
|||||||
get { return m_strName; }
|
get { return m_strName; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_strName = value;
|
m_strName = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +142,7 @@ namespace KeePassLib
|
|||||||
get { return m_strNotes; }
|
get { return m_strNotes; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_strNotes = value;
|
m_strNotes = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,31 +166,11 @@ namespace KeePassLib
|
|||||||
get { return m_pwCustomIconID; }
|
get { return m_pwCustomIconID; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_pwCustomIconID = value;
|
m_pwCustomIconID = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reference to the group to which this group belongs. May be <c>null</c>.
|
|
||||||
/// </summary>
|
|
||||||
public PwGroup ParentGroup
|
|
||||||
{
|
|
||||||
get { return m_pParentGroup; }
|
|
||||||
|
|
||||||
// Plugins: use <c>PwGroup.AddGroup</c> instead.
|
|
||||||
internal set { Debug.Assert(value != this); m_pParentGroup = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The date/time when the location of the object was last changed.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime LocationChanged
|
|
||||||
{
|
|
||||||
get { return m_tParentGroupLastMod; }
|
|
||||||
set { m_tParentGroupLastMod = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A flag that specifies if the group is shown as expanded or
|
/// A flag that specifies if the group is shown as expanded or
|
||||||
/// collapsed in the user interface.
|
/// collapsed in the user interface.
|
||||||
@@ -261,7 +275,7 @@ namespace KeePassLib
|
|||||||
get { return m_strDefaultAutoTypeSequence; }
|
get { return m_strDefaultAutoTypeSequence; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_strDefaultAutoTypeSequence = value;
|
m_strDefaultAutoTypeSequence = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,11 +297,21 @@ namespace KeePassLib
|
|||||||
get { return m_pwLastTopVisibleEntry; }
|
get { return m_pwLastTopVisibleEntry; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Debug.Assert(value != null); if (value == null) throw new ArgumentNullException("value");
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
m_pwLastTopVisibleEntry = value;
|
m_pwLastTopVisibleEntry = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<string> Tags
|
||||||
|
{
|
||||||
|
get { StrUtil.NormalizeTags(m_lTags); return m_lTags; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null) { Debug.Assert(false); throw new ArgumentNullException("value"); }
|
||||||
|
m_lTags = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom data container that can be used by plugins to store
|
/// Custom data container that can be used by plugins to store
|
||||||
/// own data in KeePass groups.
|
/// own data in KeePass groups.
|
||||||
@@ -326,8 +350,11 @@ namespace KeePassLib
|
|||||||
|
|
||||||
if (bSetTimes)
|
if (bSetTimes)
|
||||||
{
|
{
|
||||||
m_tCreation = m_tLastMod = m_tLastAccess =
|
DateTime dtNow = DateTime.UtcNow;
|
||||||
m_tParentGroupLastMod = DateTime.Now;
|
m_tCreation = dtNow;
|
||||||
|
m_tLastMod = dtNow;
|
||||||
|
m_tLastAccess = dtNow;
|
||||||
|
m_tParentGroupLastMod = dtNow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,8 +371,11 @@ namespace KeePassLib
|
|||||||
|
|
||||||
if (bSetTimes)
|
if (bSetTimes)
|
||||||
{
|
{
|
||||||
m_tCreation = m_tLastMod = m_tLastAccess =
|
DateTime dtNow = DateTime.UtcNow;
|
||||||
m_tParentGroupLastMod = DateTime.Now;
|
m_tCreation = dtNow;
|
||||||
|
m_tLastMod = dtNow;
|
||||||
|
m_tLastAccess = dtNow;
|
||||||
|
m_tParentGroupLastMod = dtNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strName != null) m_strName = strName;
|
if (strName != null) m_strName = strName;
|
||||||
@@ -374,8 +404,11 @@ namespace KeePassLib
|
|||||||
|
|
||||||
pg.m_listGroups = m_listGroups.CloneDeep();
|
pg.m_listGroups = m_listGroups.CloneDeep();
|
||||||
pg.m_listEntries = m_listEntries.CloneDeep();
|
pg.m_listEntries = m_listEntries.CloneDeep();
|
||||||
|
pg.TakeOwnership(true, true, false);
|
||||||
|
|
||||||
pg.m_pParentGroup = m_pParentGroup;
|
pg.m_pParentGroup = m_pParentGroup;
|
||||||
pg.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
pg.m_tParentGroupLastMod = m_tParentGroupLastMod;
|
||||||
|
pg.m_puPrevParentGroup = m_puPrevParentGroup;
|
||||||
|
|
||||||
pg.m_strName = m_strName;
|
pg.m_strName = m_strName;
|
||||||
pg.m_strNotes = m_strNotes;
|
pg.m_strNotes = m_strNotes;
|
||||||
@@ -400,6 +433,8 @@ namespace KeePassLib
|
|||||||
|
|
||||||
pg.m_pwLastTopVisibleEntry = m_pwLastTopVisibleEntry;
|
pg.m_pwLastTopVisibleEntry = m_pwLastTopVisibleEntry;
|
||||||
|
|
||||||
|
pg.m_lTags.AddRange(m_lTags);
|
||||||
|
|
||||||
pg.m_dCustomData = m_dCustomData.CloneDeep();
|
pg.m_dCustomData = m_dCustomData.CloneDeep();
|
||||||
|
|
||||||
return pg;
|
return pg;
|
||||||
@@ -438,6 +473,8 @@ namespace KeePassLib
|
|||||||
if (m_pParentGroup != pg.m_pParentGroup) return false;
|
if (m_pParentGroup != pg.m_pParentGroup) return false;
|
||||||
if (!bIgnoreLastMod && (m_tParentGroupLastMod != pg.m_tParentGroupLastMod))
|
if (!bIgnoreLastMod && (m_tParentGroupLastMod != pg.m_tParentGroupLastMod))
|
||||||
return false;
|
return false;
|
||||||
|
if (!m_puPrevParentGroup.Equals(pg.m_puPrevParentGroup))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_strName != pg.m_strName) return false;
|
if (m_strName != pg.m_strName) return false;
|
||||||
@@ -470,6 +507,9 @@ namespace KeePassLib
|
|||||||
|
|
||||||
if (!m_pwLastTopVisibleEntry.Equals(pg.m_pwLastTopVisibleEntry)) return false;
|
if (!m_pwLastTopVisibleEntry.Equals(pg.m_pwLastTopVisibleEntry)) return false;
|
||||||
|
|
||||||
|
// The Tags property normalizes
|
||||||
|
if (!MemUtil.ListsEqual<string>(this.Tags, pg.Tags)) return false;
|
||||||
|
|
||||||
if (!m_dCustomData.Equals(pg.m_dCustomData)) return false;
|
if (!m_dCustomData.Equals(pg.m_dCustomData)) return false;
|
||||||
|
|
||||||
if ((pwOpt & PwCompareOptions.PropertiesOnly) == PwCompareOptions.None)
|
if ((pwOpt & PwCompareOptions.PropertiesOnly) == PwCompareOptions.None)
|
||||||
@@ -516,7 +556,10 @@ namespace KeePassLib
|
|||||||
m_uuid = pgTemplate.m_uuid;
|
m_uuid = pgTemplate.m_uuid;
|
||||||
|
|
||||||
if (bAssignLocationChanged)
|
if (bAssignLocationChanged)
|
||||||
|
{
|
||||||
m_tParentGroupLastMod = pgTemplate.m_tParentGroupLastMod;
|
m_tParentGroupLastMod = pgTemplate.m_tParentGroupLastMod;
|
||||||
|
m_puPrevParentGroup = pgTemplate.m_puPrevParentGroup;
|
||||||
|
}
|
||||||
|
|
||||||
m_strName = pgTemplate.m_strName;
|
m_strName = pgTemplate.m_strName;
|
||||||
m_strNotes = pgTemplate.m_strNotes;
|
m_strNotes = pgTemplate.m_strNotes;
|
||||||
@@ -538,6 +581,8 @@ namespace KeePassLib
|
|||||||
|
|
||||||
m_pwLastTopVisibleEntry = pgTemplate.m_pwLastTopVisibleEntry;
|
m_pwLastTopVisibleEntry = pgTemplate.m_pwLastTopVisibleEntry;
|
||||||
|
|
||||||
|
m_lTags = new List<string>(pgTemplate.m_lTags);
|
||||||
|
|
||||||
m_dCustomData = pgTemplate.m_dCustomData.CloneDeep();
|
m_dCustomData = pgTemplate.m_dCustomData.CloneDeep();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +607,7 @@ namespace KeePassLib
|
|||||||
/// get touched, too.</param>
|
/// get touched, too.</param>
|
||||||
public void Touch(bool bModified, bool bTouchParents)
|
public void Touch(bool bModified, bool bTouchParents)
|
||||||
{
|
{
|
||||||
m_tLastAccess = DateTime.Now;
|
m_tLastAccess = DateTime.UtcNow;
|
||||||
++m_uUsageCount;
|
++m_uUsageCount;
|
||||||
|
|
||||||
if (bModified) m_tLastMod = m_tLastAccess;
|
if (bModified) m_tLastMod = m_tLastAccess;
|
||||||
@@ -667,21 +712,15 @@ namespace KeePassLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (PwGroup pg in m_listGroups)
|
||||||
|
{
|
||||||
if (groupHandler != null)
|
if (groupHandler != null)
|
||||||
{
|
|
||||||
foreach(PwGroup pg in m_listGroups)
|
|
||||||
{
|
{
|
||||||
if (!groupHandler(pg)) return false;
|
if (!groupHandler(pg)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
pg.PreOrderTraverseTree(groupHandler, entryHandler);
|
if (!pg.PreOrderTraverseTree(groupHandler, entryHandler))
|
||||||
}
|
return false;
|
||||||
}
|
|
||||||
else // groupHandler == null
|
|
||||||
{
|
|
||||||
foreach(PwGroup pg in m_listGroups)
|
|
||||||
{
|
|
||||||
pg.PreOrderTraverseTree(null, entryHandler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -768,357 +807,95 @@ namespace KeePassLib
|
|||||||
return PreOrderTraverseTree(null, eh);
|
return PreOrderTraverseTree(null, eh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
internal List<string> GetTagsInherited(bool bNormalize)
|
||||||
/// Search this group and all subgroups for entries.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sp">Specifies the search method.</param>
|
|
||||||
/// <param name="listStorage">Entry list in which the search results will
|
|
||||||
/// be stored.</param>
|
|
||||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage)
|
|
||||||
{
|
{
|
||||||
SearchEntries(sp, listStorage, null);
|
List<string> l = new List<string>();
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Search this group and all subgroups for entries.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sp">Specifies the search method.</param>
|
|
||||||
/// <param name="listStorage">Entry list in which the search results will
|
|
||||||
/// be stored.</param>
|
|
||||||
/// <param name="slStatus">Optional status reporting object.</param>
|
|
||||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage,
|
|
||||||
IStatusLogger slStatus)
|
|
||||||
{
|
|
||||||
SearchEntries(sp, listStorage, null, slStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Search this group and all subgroups for entries.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sp">Specifies the search method.</param>
|
|
||||||
/// <param name="listStorage">Entry list in which the search results will
|
|
||||||
/// be stored.</param>
|
|
||||||
/// <param name="resultContexts">Dictionary that will be populated with text fragments indicating the context of why each entry (keyed by Uuid) was returned</param>
|
|
||||||
public void SearchEntries(SearchParameters sp, PwObjectList<PwEntry> listStorage, IDictionary<PwUuid, KeyValuePair<string, string>> resultContexts,
|
|
||||||
IStatusLogger slStatus)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (sp == null) { Debug.Assert(false); return; }
|
|
||||||
if (listStorage == null) { Debug.Assert(false); return; }
|
|
||||||
|
|
||||||
ulong uCurEntries = 0, uTotalEntries = 0;
|
|
||||||
|
|
||||||
List<string> lTerms = StrUtil.SplitSearchTerms(sp.SearchString);
|
|
||||||
if ((lTerms.Count <= 1) || sp.RegularExpression)
|
|
||||||
{
|
|
||||||
if (slStatus != null) uTotalEntries = GetEntriesCount(true);
|
|
||||||
SearchEntriesSingle(sp, listStorage, resultContexts, slStatus, ref uCurEntries,
|
|
||||||
uTotalEntries);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search longer strings first (for improved performance)
|
|
||||||
lTerms.Sort(StrUtil.CompareLengthGt);
|
|
||||||
|
|
||||||
string strFullSearch = sp.SearchString; // Backup
|
|
||||||
|
|
||||||
PwGroup pg = this;
|
PwGroup pg = this;
|
||||||
for (int iTerm = 0; iTerm < lTerms.Count; ++iTerm)
|
while (pg != null)
|
||||||
{
|
{
|
||||||
// Update counters for a better state guess
|
l.AddRange(pg.Tags);
|
||||||
if (slStatus != null)
|
pg = pg.m_pParentGroup;
|
||||||
{
|
|
||||||
ulong uRemRounds = (ulong)(lTerms.Count - iTerm);
|
|
||||||
uTotalEntries = uCurEntries + (uRemRounds *
|
|
||||||
pg.GetEntriesCount(true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PwGroup pgNew = new PwGroup();
|
if (bNormalize) StrUtil.NormalizeTags(l);
|
||||||
|
return l;
|
||||||
sp.SearchString = lTerms[iTerm];
|
|
||||||
|
|
||||||
bool bNegate = false;
|
|
||||||
if (sp.SearchString.StartsWith("-"))
|
|
||||||
{
|
|
||||||
sp.SearchString = sp.SearchString.Substring(1);
|
|
||||||
bNegate = (sp.SearchString.Length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pg.SearchEntriesSingle(sp, pgNew.Entries, resultContexts, slStatus,
|
|
||||||
ref uCurEntries, uTotalEntries))
|
|
||||||
{
|
|
||||||
pg = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bNegate)
|
|
||||||
{
|
|
||||||
PwObjectList<PwEntry> lCand = pg.GetEntries(true);
|
|
||||||
|
|
||||||
pg = new PwGroup();
|
|
||||||
foreach (PwEntry peCand in lCand)
|
|
||||||
{
|
|
||||||
if (pgNew.Entries.IndexOf(peCand) < 0) pg.Entries.Add(peCand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else pg = pgNew;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pg != null) listStorage.Add(pg.Entries);
|
|
||||||
sp.SearchString = strFullSearch; // Restore
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool SearchEntriesSingle(SearchParameters spIn,
|
|
||||||
PwObjectList<PwEntry> listStorage, IDictionary<PwUuid, KeyValuePair<string, string>> resultContexts, IStatusLogger slStatus,
|
|
||||||
ref ulong uCurEntries, ulong uTotalEntries)
|
|
||||||
{
|
|
||||||
SearchParameters sp = spIn.Clone();
|
|
||||||
if (sp.SearchString == null) { Debug.Assert(false); return true; }
|
|
||||||
sp.SearchString = sp.SearchString.Trim();
|
|
||||||
|
|
||||||
bool bTitle = sp.SearchInTitles;
|
|
||||||
bool bUserName = sp.SearchInUserNames;
|
|
||||||
bool bPassword = sp.SearchInPasswords;
|
|
||||||
bool bUrl = sp.SearchInUrls;
|
|
||||||
bool bNotes = sp.SearchInNotes;
|
|
||||||
bool bOther = sp.SearchInOther;
|
|
||||||
bool bUuids = sp.SearchInUuids;
|
|
||||||
bool bGroupName = sp.SearchInGroupNames;
|
|
||||||
bool bTags = sp.SearchInTags;
|
|
||||||
bool bExcludeExpired = sp.ExcludeExpired;
|
|
||||||
bool bRespectEntrySearchingDisabled = sp.RespectEntrySearchingDisabled;
|
|
||||||
|
|
||||||
DateTime dtNow = DateTime.Now;
|
|
||||||
|
|
||||||
Regex rx = null;
|
|
||||||
if (sp.RegularExpression)
|
|
||||||
{
|
|
||||||
RegexOptions ro = RegexOptions.None; // RegexOptions.Compiled
|
|
||||||
if ((sp.ComparisonMode == StringComparison.CurrentCultureIgnoreCase) ||
|
|
||||||
#if !KeePassUAP
|
|
||||||
(sp.ComparisonMode == StringComparison.InvariantCultureIgnoreCase) ||
|
|
||||||
#endif
|
|
||||||
(sp.ComparisonMode == StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
ro |= RegexOptions.IgnoreCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
rx = new Regex(sp.SearchString, ro);
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong uLocalCurEntries = uCurEntries;
|
|
||||||
|
|
||||||
EntryHandler eh = null;
|
|
||||||
if (sp.SearchString.Length <= 0) // Report all
|
|
||||||
{
|
|
||||||
eh = delegate(PwEntry pe)
|
|
||||||
{
|
|
||||||
if (slStatus != null)
|
|
||||||
{
|
|
||||||
if (!slStatus.SetProgress((uint)((uLocalCurEntries *
|
|
||||||
100UL) / uTotalEntries))) return false;
|
|
||||||
++uLocalCurEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bRespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
|
||||||
return true; // Skip
|
|
||||||
if (bExcludeExpired && pe.Expires && (dtNow > pe.ExpiryTime))
|
|
||||||
return true; // Skip
|
|
||||||
|
|
||||||
listStorage.Add(pe);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
eh = delegate(PwEntry pe)
|
|
||||||
{
|
|
||||||
if (slStatus != null)
|
|
||||||
{
|
|
||||||
if (!slStatus.SetProgress((uint)((uLocalCurEntries *
|
|
||||||
100UL) / uTotalEntries))) return false;
|
|
||||||
++uLocalCurEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bRespectEntrySearchingDisabled && !pe.GetSearchingEnabled())
|
|
||||||
return true; // Skip
|
|
||||||
if (bExcludeExpired && pe.Expires && (dtNow > pe.ExpiryTime))
|
|
||||||
return true; // Skip
|
|
||||||
|
|
||||||
uint uInitialResults = listStorage.UCount;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, ProtectedString> kvp in pe.Strings)
|
|
||||||
{
|
|
||||||
string strKey = kvp.Key;
|
|
||||||
|
|
||||||
if (strKey == PwDefs.TitleField)
|
|
||||||
{
|
|
||||||
if (bTitle) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
|
||||||
rx, pe, listStorage, resultContexts, strKey);
|
|
||||||
}
|
|
||||||
else if (strKey == PwDefs.UserNameField)
|
|
||||||
{
|
|
||||||
if (bUserName) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
|
||||||
rx, pe, listStorage, resultContexts, strKey);
|
|
||||||
}
|
|
||||||
else if (strKey == PwDefs.PasswordField)
|
|
||||||
{
|
|
||||||
if (bPassword) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
|
||||||
rx, pe, listStorage, resultContexts, strKey);
|
|
||||||
}
|
|
||||||
else if (strKey == PwDefs.UrlField)
|
|
||||||
{
|
|
||||||
if (bUrl) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
|
||||||
rx, pe, listStorage, resultContexts, strKey);
|
|
||||||
}
|
|
||||||
else if (strKey == PwDefs.NotesField)
|
|
||||||
{
|
|
||||||
if (bNotes) SearchEvalAdd(sp, kvp.Value.ReadString(),
|
|
||||||
rx, pe, listStorage, resultContexts, strKey);
|
|
||||||
}
|
|
||||||
else if (bOther)
|
|
||||||
SearchEvalAdd(sp, kvp.Value.ReadString(),
|
|
||||||
rx, pe, listStorage, resultContexts, strKey);
|
|
||||||
|
|
||||||
// An entry can match only once => break if we have added it
|
|
||||||
if (listStorage.UCount > uInitialResults) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bUuids && (listStorage.UCount == uInitialResults))
|
|
||||||
SearchEvalAdd(sp, pe.Uuid.ToHexString(), rx, pe, listStorage, resultContexts, SearchContextTags);
|
|
||||||
|
|
||||||
if (bGroupName && (listStorage.UCount == uInitialResults) &&
|
|
||||||
(pe.ParentGroup != null))
|
|
||||||
SearchEvalAdd(sp, pe.ParentGroup.Name, rx, pe, listStorage, resultContexts, SearchContextParentGroup);
|
|
||||||
|
|
||||||
if (bTags)
|
|
||||||
{
|
|
||||||
foreach (string strTag in pe.Tags)
|
|
||||||
{
|
|
||||||
if (listStorage.UCount != uInitialResults) break; // Match
|
|
||||||
|
|
||||||
SearchEvalAdd(sp, strTag, rx, pe, listStorage, resultContexts, SearchContextTags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PreOrderTraverseTree(null, eh)) return false;
|
|
||||||
uCurEntries = uLocalCurEntries;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SearchEvalAdd(SearchParameters sp, string strDataField,
|
|
||||||
Regex rx, PwEntry pe, PwObjectList<PwEntry> lResults, IDictionary<PwUuid, KeyValuePair<string, string>> resultContexts, string contextFieldName)
|
|
||||||
{
|
|
||||||
bool bMatch = false;
|
|
||||||
int matchPos;
|
|
||||||
if (rx == null)
|
|
||||||
{
|
|
||||||
matchPos = strDataField.IndexOf(sp.SearchString, sp.ComparisonMode);
|
|
||||||
bMatch = matchPos >= 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var match = rx.Match(strDataField);
|
|
||||||
bMatch = match.Success;
|
|
||||||
matchPos = match.Index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bMatch && (sp.DataTransformationFn != null))
|
|
||||||
{
|
|
||||||
string strCmp = sp.DataTransformationFn(strDataField, pe);
|
|
||||||
if (!object.ReferenceEquals(strCmp, strDataField))
|
|
||||||
{
|
|
||||||
if (rx == null)
|
|
||||||
{
|
|
||||||
matchPos = strCmp.IndexOf(sp.SearchString, sp.ComparisonMode);
|
|
||||||
bMatch = matchPos >= 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var match = rx.Match(strCmp);
|
|
||||||
bMatch = match.Success;
|
|
||||||
matchPos = match.Index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bMatch)
|
|
||||||
{
|
|
||||||
lResults.Add(pe);
|
|
||||||
|
|
||||||
if (resultContexts != null)
|
|
||||||
{
|
|
||||||
// Trim the value if necessary
|
|
||||||
var contextString = strDataField;
|
|
||||||
if (contextString.Length > SearchContextStringMaxLength)
|
|
||||||
{
|
|
||||||
// Start 10% before actual data, and don't run over
|
|
||||||
var startPos = Math.Max(0, Math.Min(matchPos - (SearchContextStringMaxLength / 10), contextString.Length - SearchContextStringMaxLength));
|
|
||||||
contextString = "<22> " + contextString.Substring(startPos, SearchContextStringMaxLength) + ((startPos + SearchContextStringMaxLength < contextString.Length) ? " <20>" : null);
|
|
||||||
}
|
|
||||||
resultContexts[pe.Uuid] = new KeyValuePair<string, string>(contextFieldName, contextString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> BuildEntryTagsList()
|
public List<string> BuildEntryTagsList()
|
||||||
{
|
{
|
||||||
return BuildEntryTagsList(false);
|
return BuildEntryTagsList(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> BuildEntryTagsList(bool bSort)
|
public List<string> BuildEntryTagsList(bool bSort)
|
||||||
{
|
{
|
||||||
List<string> vTags = new List<string>();
|
return BuildEntryTagsList(bSort, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal List<string> BuildEntryTagsList(bool bSort, bool bGroupTags)
|
||||||
|
{
|
||||||
|
Dictionary<string, bool> d = new Dictionary<string, bool>();
|
||||||
|
|
||||||
|
GroupHandler gh = null;
|
||||||
|
if (bGroupTags)
|
||||||
|
{
|
||||||
|
gh = delegate (PwGroup pg)
|
||||||
|
{
|
||||||
|
foreach (string strTag in pg.Tags) d[strTag] = true;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
EntryHandler eh = delegate (PwEntry pe)
|
EntryHandler eh = delegate (PwEntry pe)
|
||||||
{
|
{
|
||||||
foreach (string strTag in pe.Tags)
|
foreach (string strTag in pe.Tags) d[strTag] = true;
|
||||||
{
|
|
||||||
bool bFound = false;
|
|
||||||
for (int i = 0; i < vTags.Count; ++i)
|
|
||||||
{
|
|
||||||
if (vTags[i].Equals(strTag, StrUtil.CaseIgnoreCmp))
|
|
||||||
{
|
|
||||||
bFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bFound) vTags.Add(strTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
TraverseTree(TraversalMethod.PreOrder, null, eh);
|
if (gh != null) gh(this);
|
||||||
if (bSort) vTags.Sort(StrUtil.CaseIgnoreComparer);
|
TraverseTree(TraversalMethod.PreOrder, gh, eh);
|
||||||
return vTags;
|
|
||||||
|
List<string> l = new List<string>(d.Keys);
|
||||||
|
if (bSort) l.Sort(StrUtil.CompareNaturally);
|
||||||
|
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !KeePassLibSD
|
#if !KeePassLibSD
|
||||||
public IDictionary<string, uint> BuildEntryTagsDict(bool bSort)
|
public IDictionary<string, uint> BuildEntryTagsDict(bool bSort)
|
||||||
{
|
{
|
||||||
IDictionary<string, uint> d;
|
Debug.Assert(!bSort); // Obsolete
|
||||||
if (!bSort) d = new Dictionary<string, uint>(StrUtil.CaseIgnoreComparer);
|
|
||||||
else d = new SortedDictionary<string, uint>(StrUtil.CaseIgnoreComparer);
|
|
||||||
|
|
||||||
EntryHandler eh = delegate(PwEntry pe)
|
IDictionary<string, uint> d;
|
||||||
|
if (!bSort) d = new Dictionary<string, uint>();
|
||||||
|
else d = new SortedDictionary<string, uint>();
|
||||||
|
|
||||||
|
GroupHandler gh = delegate (PwGroup pg)
|
||||||
{
|
{
|
||||||
foreach (string strTag in pe.Tags)
|
foreach (string strTag in pg.Tags)
|
||||||
{
|
{
|
||||||
uint u;
|
// For groups without entries
|
||||||
if (d.TryGetValue(strTag, out u)) d[strTag] = u + 1;
|
if (!d.ContainsKey(strTag)) d[strTag] = 0;
|
||||||
else d[strTag] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
TraverseTree(TraversalMethod.PreOrder, null, eh);
|
EntryHandler eh = delegate (PwEntry pe)
|
||||||
|
{
|
||||||
|
foreach (string strTag in pe.GetTagsInherited())
|
||||||
|
{
|
||||||
|
uint u;
|
||||||
|
d.TryGetValue(strTag, out u);
|
||||||
|
d[strTag] = u + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
gh(this);
|
||||||
|
TraverseTree(TraversalMethod.PreOrder, gh, eh);
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1127,24 +904,29 @@ namespace KeePassLib
|
|||||||
bool bSearchRecursive)
|
bool bSearchRecursive)
|
||||||
{
|
{
|
||||||
if (strTag == null) throw new ArgumentNullException("strTag");
|
if (strTag == null) throw new ArgumentNullException("strTag");
|
||||||
if (strTag.Length == 0) return;
|
|
||||||
|
|
||||||
foreach (PwEntry pe in m_listEntries)
|
strTag = StrUtil.NormalizeTag(strTag);
|
||||||
|
if (string.IsNullOrEmpty(strTag)) return;
|
||||||
|
|
||||||
|
EntryHandler eh = delegate (PwEntry pe)
|
||||||
{
|
{
|
||||||
foreach (string strEntryTag in pe.Tags)
|
foreach (string strEntryTag in pe.GetTagsInherited())
|
||||||
{
|
{
|
||||||
if (strEntryTag.Equals(strTag, StrUtil.CaseIgnoreCmp))
|
if (strEntryTag == strTag)
|
||||||
{
|
{
|
||||||
listStorage.Add(pe);
|
listStorage.Add(pe);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
if (bSearchRecursive)
|
if (bSearchRecursive)
|
||||||
|
TraverseTree(TraversalMethod.PreOrder, null, eh);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
foreach (PwGroup pg in m_listGroups)
|
foreach (PwEntry pe in m_listEntries) eh(pe);
|
||||||
pg.FindEntriesByTag(strTag, listStorage, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1279,7 +1061,7 @@ namespace KeePassLib
|
|||||||
PwGroup pg = m_pParentGroup;
|
PwGroup pg = m_pParentGroup;
|
||||||
while (pg != null)
|
while (pg != null)
|
||||||
{
|
{
|
||||||
if ((!bIncludeTopMostGroup) && (pg.m_pParentGroup == null))
|
if (!bIncludeTopMostGroup && (pg.m_pParentGroup == null))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
strPath = pg.Name + strSeparator + strPath;
|
strPath = pg.Name + strSeparator + strPath;
|
||||||
@@ -1402,21 +1184,34 @@ namespace KeePassLib
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the level of the group (i.e. the number of parent groups).
|
/// Get the depth of this group (i.e. the number of ancestors).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Number of parent groups.</returns>
|
/// <returns>Depth of this group.</returns>
|
||||||
public uint GetLevel()
|
public uint GetDepth()
|
||||||
{
|
{
|
||||||
PwGroup pg = m_pParentGroup;
|
PwGroup pg = m_pParentGroup;
|
||||||
uint uLevel = 0;
|
uint d = 0;
|
||||||
|
|
||||||
while (pg != null)
|
while (pg != null)
|
||||||
{
|
{
|
||||||
pg = pg.ParentGroup;
|
pg = pg.m_pParentGroup;
|
||||||
++uLevel;
|
++d;
|
||||||
}
|
}
|
||||||
|
|
||||||
return uLevel;
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint GetHeight()
|
||||||
|
{
|
||||||
|
if (m_listGroups.UCount == 0) return 0;
|
||||||
|
|
||||||
|
uint h = 0;
|
||||||
|
foreach (PwGroup pgSub in m_listGroups)
|
||||||
|
{
|
||||||
|
h = Math.Max(h, pgSub.GetHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (h + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetAutoTypeSequenceInherited()
|
public string GetAutoTypeSequenceInherited()
|
||||||
@@ -1460,7 +1255,7 @@ namespace KeePassLib
|
|||||||
/// subgroups.</returns>
|
/// subgroups.</returns>
|
||||||
public PwObjectList<PwGroup> GetGroups(bool bRecursive)
|
public PwObjectList<PwGroup> GetGroups(bool bRecursive)
|
||||||
{
|
{
|
||||||
if (bRecursive == false) return m_listGroups;
|
if (!bRecursive) return m_listGroups;
|
||||||
|
|
||||||
PwObjectList<PwGroup> list = m_listGroups.CloneShallow();
|
PwObjectList<PwGroup> list = m_listGroups.CloneShallow();
|
||||||
foreach (PwGroup pgSub in m_listGroups)
|
foreach (PwGroup pgSub in m_listGroups)
|
||||||
@@ -1473,15 +1268,20 @@ namespace KeePassLib
|
|||||||
|
|
||||||
public PwObjectList<PwEntry> GetEntries(bool bIncludeSubGroupEntries)
|
public PwObjectList<PwEntry> GetEntries(bool bIncludeSubGroupEntries)
|
||||||
{
|
{
|
||||||
if (bIncludeSubGroupEntries == false) return m_listEntries;
|
PwObjectList<PwEntry> l = new PwObjectList<PwEntry>();
|
||||||
|
|
||||||
PwObjectList<PwEntry> list = m_listEntries.CloneShallow();
|
GroupHandler gh = delegate (PwGroup pg)
|
||||||
foreach (PwGroup pgSub in m_listGroups)
|
|
||||||
{
|
{
|
||||||
list.Add(pgSub.GetEntries(true));
|
l.Add(pg.Entries);
|
||||||
}
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
return list;
|
gh(this);
|
||||||
|
if (bIncludeSubGroupEntries)
|
||||||
|
PreOrderTraverseTree(gh, null);
|
||||||
|
|
||||||
|
Debug.Assert(l.UCount == GetEntriesCount(bIncludeSubGroupEntries));
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1550,11 +1350,29 @@ namespace KeePassLib
|
|||||||
{
|
{
|
||||||
if (subGroup == null) throw new ArgumentNullException("subGroup");
|
if (subGroup == null) throw new ArgumentNullException("subGroup");
|
||||||
|
|
||||||
|
CheckCanAddGroup(subGroup);
|
||||||
m_listGroups.Add(subGroup);
|
m_listGroups.Add(subGroup);
|
||||||
|
|
||||||
if (bTakeOwnership) subGroup.m_pParentGroup = this;
|
if (bTakeOwnership) subGroup.ParentGroup = this;
|
||||||
|
|
||||||
if (bUpdateLocationChangedOfSub) subGroup.LocationChanged = DateTime.Now;
|
if (bUpdateLocationChangedOfSub) subGroup.LocationChanged = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool CanAddGroup(PwGroup pgSub)
|
||||||
|
{
|
||||||
|
if (pgSub == null) { Debug.Assert(false); return false; }
|
||||||
|
|
||||||
|
uint dCur = GetDepth(), hSub = pgSub.GetHeight();
|
||||||
|
return ((dCur + hSub + 1) <= MaxDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CheckCanAddGroup(PwGroup pgSub)
|
||||||
|
{
|
||||||
|
if (!CanAddGroup(pgSub))
|
||||||
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
|
throw new InvalidOperationException(KLRes.StructsTooDeep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1589,7 +1407,7 @@ namespace KeePassLib
|
|||||||
// only assign it to the new one
|
// only assign it to the new one
|
||||||
if (bTakeOwnership) pe.ParentGroup = this;
|
if (bTakeOwnership) pe.ParentGroup = this;
|
||||||
|
|
||||||
if (bUpdateLocationChangedOfEntry) pe.LocationChanged = DateTime.Now;
|
if (bUpdateLocationChangedOfEntry) pe.LocationChanged = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SortSubGroups(bool bRecursive)
|
public void SortSubGroups(bool bRecursive)
|
||||||
@@ -1605,7 +1423,7 @@ namespace KeePassLib
|
|||||||
|
|
||||||
public void DeleteAllObjects(PwDatabase pdContext)
|
public void DeleteAllObjects(PwDatabase pdContext)
|
||||||
{
|
{
|
||||||
DateTime dtNow = DateTime.Now;
|
DateTime dtNow = DateTime.UtcNow;
|
||||||
|
|
||||||
foreach (PwEntry pe in m_listEntries)
|
foreach (PwEntry pe in m_listEntries)
|
||||||
{
|
{
|
||||||
@@ -1649,7 +1467,7 @@ namespace KeePassLib
|
|||||||
|
|
||||||
public void SetCreatedNow(bool bRecursive)
|
public void SetCreatedNow(bool bRecursive)
|
||||||
{
|
{
|
||||||
DateTime dt = DateTime.Now;
|
DateTime dt = DateTime.UtcNow;
|
||||||
|
|
||||||
m_tCreation = dt;
|
m_tCreation = dt;
|
||||||
m_tLastAccess = dt;
|
m_tLastAccess = dt;
|
||||||
@@ -1682,10 +1500,63 @@ namespace KeePassLib
|
|||||||
|
|
||||||
pg.SetCreatedNow(true);
|
pg.SetCreatedNow(true);
|
||||||
|
|
||||||
pg.TakeOwnership(true, true, true);
|
|
||||||
|
|
||||||
return pg;
|
return pg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
internal string[] GetAutoTypeSequences(bool bWithStd)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, bool> d = new Dictionary<string, bool>();
|
||||||
|
|
||||||
|
Action<string> fAdd = delegate (string str)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(str)) d[str] = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bWithStd)
|
||||||
|
{
|
||||||
|
fAdd(PwDefs.DefaultAutoTypeSequence);
|
||||||
|
fAdd(PwDefs.DefaultAutoTypeSequenceTan);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupHandler gh = delegate (PwGroup pg)
|
||||||
|
{
|
||||||
|
fAdd(pg.DefaultAutoTypeSequence);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryHandler eh = delegate (PwEntry pe)
|
||||||
|
{
|
||||||
|
AutoTypeConfig c = pe.AutoType;
|
||||||
|
|
||||||
|
fAdd(c.DefaultSequence);
|
||||||
|
foreach (AutoTypeAssociation a in c.Associations)
|
||||||
|
{
|
||||||
|
fAdd(a.Sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
gh(this);
|
||||||
|
TraverseTree(TraversalMethod.PreOrder, gh, eh);
|
||||||
|
|
||||||
|
string[] v = new string[d.Count];
|
||||||
|
if (d.Count != 0)
|
||||||
|
{
|
||||||
|
d.Keys.CopyTo(v, 0);
|
||||||
|
Array.Sort<string>(v, StrUtil.CaseIgnoreComparer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
catch (Exception) { Debug.Assert(false); }
|
||||||
|
|
||||||
|
return new string[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class PwGroupComparer : IComparer<PwGroup>
|
public sealed class PwGroupComparer : IComparer<PwGroup>
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace KeePassLib.Resources
|
|||||||
{
|
{
|
||||||
if (dictNew == null) throw new ArgumentNullException("dictNew");
|
if (dictNew == null) throw new ArgumentNullException("dictNew");
|
||||||
|
|
||||||
|
m_strAlgorithmUnknown = TryGetEx(dictNew, "AlgorithmUnknown", m_strAlgorithmUnknown);
|
||||||
|
m_strCharSetInvalid = TryGetEx(dictNew, "CharSetInvalid", m_strCharSetInvalid);
|
||||||
|
m_strCharSetTooFewChars = TryGetEx(dictNew, "CharSetTooFewChars", m_strCharSetTooFewChars);
|
||||||
m_strCryptoStreamFailed = TryGetEx(dictNew, "CryptoStreamFailed", m_strCryptoStreamFailed);
|
m_strCryptoStreamFailed = TryGetEx(dictNew, "CryptoStreamFailed", m_strCryptoStreamFailed);
|
||||||
m_strEncDataTooLarge = TryGetEx(dictNew, "EncDataTooLarge", m_strEncDataTooLarge);
|
m_strEncDataTooLarge = TryGetEx(dictNew, "EncDataTooLarge", m_strEncDataTooLarge);
|
||||||
m_strErrorInClipboard = TryGetEx(dictNew, "ErrorInClipboard", m_strErrorInClipboard);
|
m_strErrorInClipboard = TryGetEx(dictNew, "ErrorInClipboard", m_strErrorInClipboard);
|
||||||
@@ -41,7 +44,7 @@ namespace KeePassLib.Resources
|
|||||||
m_strFileNewVerOrPlgReq = TryGetEx(dictNew, "FileNewVerOrPlgReq", m_strFileNewVerOrPlgReq);
|
m_strFileNewVerOrPlgReq = TryGetEx(dictNew, "FileNewVerOrPlgReq", m_strFileNewVerOrPlgReq);
|
||||||
m_strFileNewVerReq = TryGetEx(dictNew, "FileNewVerReq", m_strFileNewVerReq);
|
m_strFileNewVerReq = TryGetEx(dictNew, "FileNewVerReq", m_strFileNewVerReq);
|
||||||
m_strFileSaveCorruptionWarning = TryGetEx(dictNew, "FileSaveCorruptionWarning", m_strFileSaveCorruptionWarning);
|
m_strFileSaveCorruptionWarning = TryGetEx(dictNew, "FileSaveCorruptionWarning", m_strFileSaveCorruptionWarning);
|
||||||
m_strFileSaveFailed = TryGetEx(dictNew, "FileSaveFailed", m_strFileSaveFailed);
|
m_strFileSaveFailed2 = TryGetEx(dictNew, "FileSaveFailed2", m_strFileSaveFailed2);
|
||||||
m_strFileSigInvalid = TryGetEx(dictNew, "FileSigInvalid", m_strFileSigInvalid);
|
m_strFileSigInvalid = TryGetEx(dictNew, "FileSigInvalid", m_strFileSigInvalid);
|
||||||
m_strFileUnknownCipher = TryGetEx(dictNew, "FileUnknownCipher", m_strFileUnknownCipher);
|
m_strFileUnknownCipher = TryGetEx(dictNew, "FileUnknownCipher", m_strFileUnknownCipher);
|
||||||
m_strFileUnknownCompression = TryGetEx(dictNew, "FileUnknownCompression", m_strFileUnknownCompression);
|
m_strFileUnknownCompression = TryGetEx(dictNew, "FileUnknownCompression", m_strFileUnknownCompression);
|
||||||
@@ -55,12 +58,18 @@ namespace KeePassLib.Resources
|
|||||||
m_strKeePass1xHint = TryGetEx(dictNew, "KeePass1xHint", m_strKeePass1xHint);
|
m_strKeePass1xHint = TryGetEx(dictNew, "KeePass1xHint", m_strKeePass1xHint);
|
||||||
m_strKeyBits = TryGetEx(dictNew, "KeyBits", m_strKeyBits);
|
m_strKeyBits = TryGetEx(dictNew, "KeyBits", m_strKeyBits);
|
||||||
m_strKeyFileDbSel = TryGetEx(dictNew, "KeyFileDbSel", m_strKeyFileDbSel);
|
m_strKeyFileDbSel = TryGetEx(dictNew, "KeyFileDbSel", m_strKeyFileDbSel);
|
||||||
|
m_strKeyHashMismatch = TryGetEx(dictNew, "KeyHashMismatch", m_strKeyHashMismatch);
|
||||||
m_strMasterSeedLengthInvalid = TryGetEx(dictNew, "MasterSeedLengthInvalid", m_strMasterSeedLengthInvalid);
|
m_strMasterSeedLengthInvalid = TryGetEx(dictNew, "MasterSeedLengthInvalid", m_strMasterSeedLengthInvalid);
|
||||||
m_strOldFormat = TryGetEx(dictNew, "OldFormat", m_strOldFormat);
|
m_strOldFormat = TryGetEx(dictNew, "OldFormat", m_strOldFormat);
|
||||||
m_strPassive = TryGetEx(dictNew, "Passive", m_strPassive);
|
m_strPassive = TryGetEx(dictNew, "Passive", m_strPassive);
|
||||||
|
m_strPathBackslash = TryGetEx(dictNew, "PathBackslash", m_strPathBackslash);
|
||||||
|
m_strPatternInvalid = TryGetEx(dictNew, "PatternInvalid", m_strPatternInvalid);
|
||||||
m_strPreAuth = TryGetEx(dictNew, "PreAuth", m_strPreAuth);
|
m_strPreAuth = TryGetEx(dictNew, "PreAuth", m_strPreAuth);
|
||||||
|
m_strPwGenFailed = TryGetEx(dictNew, "PwGenFailed", m_strPwGenFailed);
|
||||||
|
m_strStructsTooDeep = TryGetEx(dictNew, "StructsTooDeep", m_strStructsTooDeep);
|
||||||
m_strTimeout = TryGetEx(dictNew, "Timeout", m_strTimeout);
|
m_strTimeout = TryGetEx(dictNew, "Timeout", m_strTimeout);
|
||||||
m_strTryAgainSecs = TryGetEx(dictNew, "TryAgainSecs", m_strTryAgainSecs);
|
m_strTryAgainSecs = TryGetEx(dictNew, "TryAgainSecs", m_strTryAgainSecs);
|
||||||
|
m_strUnknownError = TryGetEx(dictNew, "UnknownError", m_strUnknownError);
|
||||||
m_strUnknownHeaderId = TryGetEx(dictNew, "UnknownHeaderId", m_strUnknownHeaderId);
|
m_strUnknownHeaderId = TryGetEx(dictNew, "UnknownHeaderId", m_strUnknownHeaderId);
|
||||||
m_strUnknownKdf = TryGetEx(dictNew, "UnknownKdf", m_strUnknownKdf);
|
m_strUnknownKdf = TryGetEx(dictNew, "UnknownKdf", m_strUnknownKdf);
|
||||||
m_strUserAccountKeyError = TryGetEx(dictNew, "UserAccountKeyError", m_strUserAccountKeyError);
|
m_strUserAccountKeyError = TryGetEx(dictNew, "UserAccountKeyError", m_strUserAccountKeyError);
|
||||||
@@ -68,6 +77,9 @@ namespace KeePassLib.Resources
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string[] m_vKeyNames = {
|
private static readonly string[] m_vKeyNames = {
|
||||||
|
"AlgorithmUnknown",
|
||||||
|
"CharSetInvalid",
|
||||||
|
"CharSetTooFewChars",
|
||||||
"CryptoStreamFailed",
|
"CryptoStreamFailed",
|
||||||
"EncDataTooLarge",
|
"EncDataTooLarge",
|
||||||
"ErrorInClipboard",
|
"ErrorInClipboard",
|
||||||
@@ -83,7 +95,7 @@ namespace KeePassLib.Resources
|
|||||||
"FileNewVerOrPlgReq",
|
"FileNewVerOrPlgReq",
|
||||||
"FileNewVerReq",
|
"FileNewVerReq",
|
||||||
"FileSaveCorruptionWarning",
|
"FileSaveCorruptionWarning",
|
||||||
"FileSaveFailed",
|
"FileSaveFailed2",
|
||||||
"FileSigInvalid",
|
"FileSigInvalid",
|
||||||
"FileUnknownCipher",
|
"FileUnknownCipher",
|
||||||
"FileUnknownCompression",
|
"FileUnknownCompression",
|
||||||
@@ -97,12 +109,18 @@ namespace KeePassLib.Resources
|
|||||||
"KeePass1xHint",
|
"KeePass1xHint",
|
||||||
"KeyBits",
|
"KeyBits",
|
||||||
"KeyFileDbSel",
|
"KeyFileDbSel",
|
||||||
|
"KeyHashMismatch",
|
||||||
"MasterSeedLengthInvalid",
|
"MasterSeedLengthInvalid",
|
||||||
"OldFormat",
|
"OldFormat",
|
||||||
"Passive",
|
"Passive",
|
||||||
|
"PathBackslash",
|
||||||
|
"PatternInvalid",
|
||||||
"PreAuth",
|
"PreAuth",
|
||||||
|
"PwGenFailed",
|
||||||
|
"StructsTooDeep",
|
||||||
"Timeout",
|
"Timeout",
|
||||||
"TryAgainSecs",
|
"TryAgainSecs",
|
||||||
|
"UnknownError",
|
||||||
"UnknownHeaderId",
|
"UnknownHeaderId",
|
||||||
"UnknownKdf",
|
"UnknownKdf",
|
||||||
"UserAccountKeyError",
|
"UserAccountKeyError",
|
||||||
@@ -114,6 +132,39 @@ namespace KeePassLib.Resources
|
|||||||
return m_vKeyNames;
|
return m_vKeyNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string m_strAlgorithmUnknown =
|
||||||
|
@"The algorithm is unknown.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'The algorithm is unknown.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string AlgorithmUnknown
|
||||||
|
{
|
||||||
|
get { return m_strAlgorithmUnknown; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string m_strCharSetInvalid =
|
||||||
|
@"The character set is invalid.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'The character set is invalid.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string CharSetInvalid
|
||||||
|
{
|
||||||
|
get { return m_strCharSetInvalid; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string m_strCharSetTooFewChars =
|
||||||
|
@"There are too few characters in the character set.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'There are too few characters in the character set.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string CharSetTooFewChars
|
||||||
|
{
|
||||||
|
get { return m_strCharSetTooFewChars; }
|
||||||
|
}
|
||||||
|
|
||||||
private static string m_strCryptoStreamFailed =
|
private static string m_strCryptoStreamFailed =
|
||||||
@"Failed to initialize encryption/decryption stream!";
|
@"Failed to initialize encryption/decryption stream!";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -279,15 +330,15 @@ namespace KeePassLib.Resources
|
|||||||
get { return m_strFileSaveCorruptionWarning; }
|
get { return m_strFileSaveCorruptionWarning; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string m_strFileSaveFailed =
|
private static string m_strFileSaveFailed2 =
|
||||||
@"Failed to save the current database to the specified location!";
|
@"Failed to save to the specified file!";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Look up a localized string similar to
|
/// Look up a localized string similar to
|
||||||
/// 'Failed to save the current database to the specified location!'.
|
/// 'Failed to save to the specified file!'.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string FileSaveFailed
|
public static string FileSaveFailed2
|
||||||
{
|
{
|
||||||
get { return m_strFileSaveFailed; }
|
get { return m_strFileSaveFailed2; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string m_strFileSigInvalid =
|
private static string m_strFileSigInvalid =
|
||||||
@@ -346,10 +397,10 @@ namespace KeePassLib.Resources
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static string m_strFrameworkNotImplExcp =
|
private static string m_strFrameworkNotImplExcp =
|
||||||
@"The .NET framework/runtime under which KeePass is currently running does not support this operation.";
|
@"The .NET Framework/runtime under which KeePass is currently running does not support this operation.";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Look up a localized string similar to
|
/// Look up a localized string similar to
|
||||||
/// 'The .NET framework/runtime under which KeePass is currently running does not support this operation.'.
|
/// 'The .NET Framework/runtime under which KeePass is currently running does not support this operation.'.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string FrameworkNotImplExcp
|
public static string FrameworkNotImplExcp
|
||||||
{
|
{
|
||||||
@@ -368,10 +419,10 @@ namespace KeePassLib.Resources
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static string m_strInvalidCompositeKey =
|
private static string m_strInvalidCompositeKey =
|
||||||
@"The composite key is invalid!";
|
@"The master key is invalid!";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Look up a localized string similar to
|
/// Look up a localized string similar to
|
||||||
/// 'The composite key is invalid!'.
|
/// 'The master key is invalid!'.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string InvalidCompositeKey
|
public static string InvalidCompositeKey
|
||||||
{
|
{
|
||||||
@@ -379,10 +430,10 @@ namespace KeePassLib.Resources
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static string m_strInvalidCompositeKeyHint =
|
private static string m_strInvalidCompositeKeyHint =
|
||||||
@"Make sure the composite key is correct and try again.";
|
@"Make sure that the master key is correct and try it again.";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Look up a localized string similar to
|
/// Look up a localized string similar to
|
||||||
/// 'Make sure the composite key is correct and try again.'.
|
/// 'Make sure that the master key is correct and try it again.'.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string InvalidCompositeKeyHint
|
public static string InvalidCompositeKeyHint
|
||||||
{
|
{
|
||||||
@@ -433,6 +484,17 @@ namespace KeePassLib.Resources
|
|||||||
get { return m_strKeyFileDbSel; }
|
get { return m_strKeyFileDbSel; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string m_strKeyHashMismatch =
|
||||||
|
@"The key and the hash do not match, i.e. the key or the hash is invalid.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'The key and the hash do not match, i.e. the key or the hash is invalid.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string KeyHashMismatch
|
||||||
|
{
|
||||||
|
get { return m_strKeyHashMismatch; }
|
||||||
|
}
|
||||||
|
|
||||||
private static string m_strMasterSeedLengthInvalid =
|
private static string m_strMasterSeedLengthInvalid =
|
||||||
@"The length of the master key seed is invalid!";
|
@"The length of the master key seed is invalid!";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -466,6 +528,28 @@ namespace KeePassLib.Resources
|
|||||||
get { return m_strPassive; }
|
get { return m_strPassive; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string m_strPathBackslash =
|
||||||
|
@"The path contains a backslash. Such paths are not supported (for security reasons).";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'The path contains a backslash. Such paths are not supported (for security reasons).'.
|
||||||
|
/// </summary>
|
||||||
|
public static string PathBackslash
|
||||||
|
{
|
||||||
|
get { return m_strPathBackslash; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string m_strPatternInvalid =
|
||||||
|
@"The pattern is invalid.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'The pattern is invalid.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string PatternInvalid
|
||||||
|
{
|
||||||
|
get { return m_strPatternInvalid; }
|
||||||
|
}
|
||||||
|
|
||||||
private static string m_strPreAuth =
|
private static string m_strPreAuth =
|
||||||
@"Pre-authenticate";
|
@"Pre-authenticate";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -477,6 +561,28 @@ namespace KeePassLib.Resources
|
|||||||
get { return m_strPreAuth; }
|
get { return m_strPreAuth; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string m_strPwGenFailed =
|
||||||
|
@"Failed to generate a password.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'Failed to generate a password.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string PwGenFailed
|
||||||
|
{
|
||||||
|
get { return m_strPwGenFailed; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string m_strStructsTooDeep =
|
||||||
|
@"Structures are nested too deeply.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'Structures are nested too deeply.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string StructsTooDeep
|
||||||
|
{
|
||||||
|
get { return m_strStructsTooDeep; }
|
||||||
|
}
|
||||||
|
|
||||||
private static string m_strTimeout =
|
private static string m_strTimeout =
|
||||||
@"Timeout";
|
@"Timeout";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -499,6 +605,17 @@ namespace KeePassLib.Resources
|
|||||||
get { return m_strTryAgainSecs; }
|
get { return m_strTryAgainSecs; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string m_strUnknownError =
|
||||||
|
@"An unknown error occurred.";
|
||||||
|
/// <summary>
|
||||||
|
/// Look up a localized string similar to
|
||||||
|
/// 'An unknown error occurred.'.
|
||||||
|
/// </summary>
|
||||||
|
public static string UnknownError
|
||||||
|
{
|
||||||
|
get { return m_strUnknownError; }
|
||||||
|
}
|
||||||
|
|
||||||
private static string m_strUnknownHeaderId =
|
private static string m_strUnknownHeaderId =
|
||||||
@"Unknown header ID!";
|
@"Unknown header ID!";
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,11 +33,11 @@ using KeePassLibSD;
|
|||||||
namespace KeePassLib.Security
|
namespace KeePassLib.Security
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an in-memory encrypted string.
|
/// A string that is protected in process memory.
|
||||||
/// <c>ProtectedString</c> objects are immutable and thread-safe.
|
/// <c>ProtectedString</c> objects are immutable and thread-safe.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if (DEBUG && !KeePassLibSD)
|
#if (DEBUG && !KeePassLibSD)
|
||||||
[DebuggerDisplay(@"{ReadString()}")]
|
[DebuggerDisplay("{ReadString()}")]
|
||||||
#endif
|
#endif
|
||||||
public sealed class ProtectedString
|
public sealed class ProtectedString
|
||||||
{
|
{
|
||||||
@@ -48,11 +48,24 @@ namespace KeePassLib.Security
|
|||||||
private bool m_bIsProtected;
|
private bool m_bIsProtected;
|
||||||
|
|
||||||
private static readonly ProtectedString m_psEmpty = new ProtectedString();
|
private static readonly ProtectedString m_psEmpty = new ProtectedString();
|
||||||
|
/// <summary>
|
||||||
|
/// Get an empty <c>ProtectedString</c> object, without protection.
|
||||||
|
/// </summary>
|
||||||
public static ProtectedString Empty
|
public static ProtectedString Empty
|
||||||
{
|
{
|
||||||
get { return m_psEmpty; }
|
get { return m_psEmpty; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly ProtectedString m_psEmptyEx = new ProtectedString(
|
||||||
|
true, new byte[0]);
|
||||||
|
/// <summary>
|
||||||
|
/// Get an empty <c>ProtectedString</c> object, with protection turned on.
|
||||||
|
/// </summary>
|
||||||
|
public static ProtectedString EmptyEx
|
||||||
|
{
|
||||||
|
get { return m_psEmptyEx; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A flag specifying whether the <c>ProtectedString</c> object
|
/// A flag specifying whether the <c>ProtectedString</c> object
|
||||||
/// has turned on memory protection or not.
|
/// has turned on memory protection or not.
|
||||||
@@ -66,8 +79,8 @@ namespace KeePassLib.Security
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
ProtectedBinary pBin = m_pbUtf8; // Local ref for thread-safety
|
ProtectedBinary p = m_pbUtf8; // Local ref for thread-safety
|
||||||
if(pBin != null) return (pBin.Length == 0);
|
if (p != null) return (p.Length == 0);
|
||||||
|
|
||||||
Debug.Assert(m_strPlainText != null);
|
Debug.Assert(m_strPlainText != null);
|
||||||
return (m_strPlainText.Length == 0);
|
return (m_strPlainText.Length == 0);
|
||||||
@@ -75,18 +88,21 @@ namespace KeePassLib.Security
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int m_nCachedLength = -1;
|
private int m_nCachedLength = -1;
|
||||||
|
/// <summary>
|
||||||
|
/// Length of the protected string, in characters.
|
||||||
|
/// </summary>
|
||||||
public int Length
|
public int Length
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (m_nCachedLength >= 0) return m_nCachedLength;
|
if (m_nCachedLength >= 0) return m_nCachedLength;
|
||||||
|
|
||||||
ProtectedBinary pBin = m_pbUtf8; // Local ref for thread-safety
|
ProtectedBinary p = m_pbUtf8; // Local ref for thread-safety
|
||||||
if(pBin != null)
|
if (p != null)
|
||||||
{
|
{
|
||||||
byte[] pbPlain = pBin.ReadData();
|
byte[] pbPlain = p.ReadData();
|
||||||
m_nCachedLength = StrUtil.Utf8.GetCharCount(pbPlain);
|
try { m_nCachedLength = StrUtil.Utf8.GetCharCount(pbPlain); }
|
||||||
MemUtil.ZeroByteArray(pbPlain);
|
finally { MemUtil.ZeroByteArray(pbPlain); }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -140,18 +156,16 @@ namespace KeePassLib.Security
|
|||||||
/// to the value passed in the <c>XorredBuffer</c> object.
|
/// to the value passed in the <c>XorredBuffer</c> object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bEnableProtection">Enable protection or not.</param>
|
/// <param name="bEnableProtection">Enable protection or not.</param>
|
||||||
/// <param name="xbProtected"><c>XorredBuffer</c> object containing the
|
/// <param name="xb"><c>XorredBuffer</c> object containing the
|
||||||
/// string in UTF-8 representation. The UTF-8 string must not
|
/// string in UTF-8 representation. The UTF-8 string must not
|
||||||
/// be <c>null</c>-terminated.</param>
|
/// be <c>null</c>-terminated.</param>
|
||||||
public ProtectedString(bool bEnableProtection, XorredBuffer xbProtected)
|
public ProtectedString(bool bEnableProtection, XorredBuffer xb)
|
||||||
{
|
{
|
||||||
Debug.Assert(xbProtected != null);
|
if (xb == null) { Debug.Assert(false); throw new ArgumentNullException("xb"); }
|
||||||
if(xbProtected == null) throw new ArgumentNullException("xbProtected");
|
|
||||||
|
|
||||||
byte[] pb = xbProtected.ReadPlainText();
|
byte[] pb = xb.ReadPlainText();
|
||||||
Init(bEnableProtection, pb);
|
try { Init(bEnableProtection, pb); }
|
||||||
|
finally { if (bEnableProtection) MemUtil.ZeroByteArray(pb); }
|
||||||
if(bEnableProtection) MemUtil.ZeroByteArray(pb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Init(bool bEnableProtection, string str)
|
private void Init(bool bEnableProtection, string str)
|
||||||
@@ -160,7 +174,7 @@ namespace KeePassLib.Security
|
|||||||
|
|
||||||
m_bIsProtected = bEnableProtection;
|
m_bIsProtected = bEnableProtection;
|
||||||
|
|
||||||
// The string already is in memory and immutable,
|
// As the string already is in memory and immutable,
|
||||||
// protection would be useless
|
// protection would be useless
|
||||||
m_strPlainText = str;
|
m_strPlainText = str;
|
||||||
}
|
}
|
||||||
@@ -178,8 +192,8 @@ namespace KeePassLib.Security
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert the protected string to a normal string object.
|
/// Convert the protected string to a standard string object.
|
||||||
/// Be careful with this function, the returned string object
|
/// Be careful with this function, as the returned string object
|
||||||
/// isn't protected anymore and stored in plain-text in the
|
/// isn't protected anymore and stored in plain-text in the
|
||||||
/// process memory.
|
/// process memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -194,46 +208,64 @@ namespace KeePassLib.Security
|
|||||||
// No need to clear pb
|
// No need to clear pb
|
||||||
|
|
||||||
// As the text is now visible in process memory anyway,
|
// As the text is now visible in process memory anyway,
|
||||||
// there's no need to protect it anymore
|
// there's no need to protect it anymore (strings are
|
||||||
|
// immutable and thus cannot be overwritten)
|
||||||
m_strPlainText = str;
|
m_strPlainText = str;
|
||||||
m_pbUtf8 = null; // Thread-safe order
|
m_pbUtf8 = null; // Thread-safe order
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read out the string and return it as a char array.
|
||||||
|
/// The returned array is not protected and should be cleared by
|
||||||
|
/// the caller.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Plain-text char array.</returns>
|
||||||
|
public char[] ReadChars()
|
||||||
|
{
|
||||||
|
if (m_strPlainText != null) return m_strPlainText.ToCharArray();
|
||||||
|
|
||||||
|
byte[] pb = ReadUtf8();
|
||||||
|
char[] v;
|
||||||
|
try { v = StrUtil.Utf8.GetChars(pb); }
|
||||||
|
finally { MemUtil.ZeroByteArray(pb); }
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read out the string and return a byte array that contains the
|
/// Read out the string and return a byte array that contains the
|
||||||
/// string encoded using UTF-8. The returned string is not protected
|
/// string encoded using UTF-8.
|
||||||
/// anymore!
|
/// The returned array is not protected and should be cleared by
|
||||||
|
/// the caller.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Plain-text UTF-8 byte array.</returns>
|
/// <returns>Plain-text UTF-8 byte array.</returns>
|
||||||
public byte[] ReadUtf8()
|
public byte[] ReadUtf8()
|
||||||
{
|
{
|
||||||
ProtectedBinary pBin = m_pbUtf8; // Local ref for thread-safety
|
ProtectedBinary p = m_pbUtf8; // Local ref for thread-safety
|
||||||
if(pBin != null) return pBin.ReadData();
|
if (p != null) return p.ReadData();
|
||||||
|
|
||||||
return StrUtil.Utf8.GetBytes(m_strPlainText);
|
return StrUtil.Utf8.GetBytes(m_strPlainText);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read the protected string and return it protected with a sequence
|
/// Get the string as an UTF-8 sequence xorred with bytes
|
||||||
/// of bytes generated by a random stream.
|
/// from a <c>CryptoRandomStream</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="crsRandomSource">Random number source.</param>
|
|
||||||
/// <returns>Protected string.</returns>
|
|
||||||
public byte[] ReadXorredString(CryptoRandomStream crsRandomSource)
|
public byte[] ReadXorredString(CryptoRandomStream crsRandomSource)
|
||||||
{
|
{
|
||||||
Debug.Assert(crsRandomSource != null); if(crsRandomSource == null) throw new ArgumentNullException("crsRandomSource");
|
if (crsRandomSource == null) { Debug.Assert(false); throw new ArgumentNullException("crsRandomSource"); }
|
||||||
|
|
||||||
byte[] pbData = ReadUtf8();
|
byte[] pbData = ReadUtf8();
|
||||||
uint uLen = (uint)pbData.Length;
|
int cb = pbData.Length;
|
||||||
|
|
||||||
byte[] randomPad = crsRandomSource.GetRandomBytes(uLen);
|
byte[] pbPad = crsRandomSource.GetRandomBytes((uint)cb);
|
||||||
Debug.Assert(randomPad.Length == pbData.Length);
|
Debug.Assert(pbPad.Length == cb);
|
||||||
|
|
||||||
for(uint i = 0; i < uLen; ++i)
|
for (int i = 0; i < cb; ++i)
|
||||||
pbData[i] ^= randomPad[i];
|
pbData[i] ^= pbPad[i];
|
||||||
|
|
||||||
|
MemUtil.ZeroByteArray(pbPad);
|
||||||
return pbData;
|
return pbData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,10 +274,34 @@ namespace KeePassLib.Security
|
|||||||
if (bProtect == m_bIsProtected) return this;
|
if (bProtect == m_bIsProtected) return this;
|
||||||
|
|
||||||
byte[] pb = ReadUtf8();
|
byte[] pb = ReadUtf8();
|
||||||
ProtectedString ps = new ProtectedString(bProtect, pb);
|
|
||||||
|
|
||||||
if(bProtect) MemUtil.ZeroByteArray(pb);
|
// No need to clear pb; either the current or the new object is unprotected
|
||||||
return ps;
|
return new ProtectedString(bProtect, pb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(ProtectedString ps, bool bCheckProtEqual)
|
||||||
|
{
|
||||||
|
if (ps == null) throw new ArgumentNullException("ps");
|
||||||
|
if (object.ReferenceEquals(this, ps)) return true; // Perf. opt.
|
||||||
|
|
||||||
|
bool bPA = m_bIsProtected, bPB = ps.m_bIsProtected;
|
||||||
|
if (bCheckProtEqual && (bPA != bPB)) return false;
|
||||||
|
if (!bPA && !bPB) return (ReadString() == ps.ReadString());
|
||||||
|
|
||||||
|
byte[] pbA = ReadUtf8(), pbB = null;
|
||||||
|
bool bEq;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pbB = ps.ReadUtf8();
|
||||||
|
bEq = MemUtil.ArraysEqual(pbA, pbB);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (bPA) MemUtil.ZeroByteArray(pbA);
|
||||||
|
if (bPB && (pbB != null)) MemUtil.ZeroByteArray(pbB);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bEq;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProtectedString Insert(int iStart, string strInsert)
|
public ProtectedString Insert(int iStart, string strInsert)
|
||||||
@@ -254,18 +310,14 @@ namespace KeePassLib.Security
|
|||||||
if (strInsert == null) throw new ArgumentNullException("strInsert");
|
if (strInsert == null) throw new ArgumentNullException("strInsert");
|
||||||
if (strInsert.Length == 0) return this;
|
if (strInsert.Length == 0) return this;
|
||||||
|
|
||||||
// Only operate directly with strings when m_bIsProtected is
|
|
||||||
// false, not in the case of non-null m_strPlainText, because
|
|
||||||
// the operation creates a new sequence in memory
|
|
||||||
if (!m_bIsProtected)
|
if (!m_bIsProtected)
|
||||||
return new ProtectedString(false, ReadString().Insert(
|
return new ProtectedString(false, ReadString().Insert(
|
||||||
iStart, strInsert));
|
iStart, strInsert));
|
||||||
|
|
||||||
UTF8Encoding utf8 = StrUtil.Utf8;
|
UTF8Encoding utf8 = StrUtil.Utf8;
|
||||||
|
char[] v = ReadChars(), vNew = null;
|
||||||
byte[] pb = ReadUtf8();
|
byte[] pbNew = null;
|
||||||
char[] v = utf8.GetChars(pb);
|
ProtectedString ps;
|
||||||
char[] vNew;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -279,21 +331,20 @@ namespace KeePassLib.Security
|
|||||||
Array.Copy(vIns, 0, vNew, iStart, vIns.Length);
|
Array.Copy(vIns, 0, vNew, iStart, vIns.Length);
|
||||||
Array.Copy(v, iStart, vNew, iStart + vIns.Length,
|
Array.Copy(v, iStart, vNew, iStart + vIns.Length,
|
||||||
v.Length - iStart);
|
v.Length - iStart);
|
||||||
|
|
||||||
|
pbNew = utf8.GetBytes(vNew);
|
||||||
|
ps = new ProtectedString(true, pbNew);
|
||||||
|
|
||||||
|
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
|
||||||
|
ReadString().Insert(iStart, strInsert));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
MemUtil.ZeroArray<char>(v);
|
MemUtil.ZeroArray<char>(v);
|
||||||
MemUtil.ZeroByteArray(pb);
|
if (vNew != null) MemUtil.ZeroArray<char>(vNew);
|
||||||
|
if (pbNew != null) MemUtil.ZeroByteArray(pbNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] pbNew = utf8.GetBytes(vNew);
|
|
||||||
ProtectedString ps = new ProtectedString(m_bIsProtected, pbNew);
|
|
||||||
|
|
||||||
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
|
|
||||||
ReadString().Insert(iStart, strInsert));
|
|
||||||
|
|
||||||
MemUtil.ZeroArray<char>(vNew);
|
|
||||||
MemUtil.ZeroByteArray(pbNew);
|
|
||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,44 +354,81 @@ namespace KeePassLib.Security
|
|||||||
if (nCount < 0) throw new ArgumentOutOfRangeException("nCount");
|
if (nCount < 0) throw new ArgumentOutOfRangeException("nCount");
|
||||||
if (nCount == 0) return this;
|
if (nCount == 0) return this;
|
||||||
|
|
||||||
// Only operate directly with strings when m_bIsProtected is
|
|
||||||
// false, not in the case of non-null m_strPlainText, because
|
|
||||||
// the operation creates a new sequence in memory
|
|
||||||
if (!m_bIsProtected)
|
if (!m_bIsProtected)
|
||||||
return new ProtectedString(false, ReadString().Remove(
|
return new ProtectedString(false, ReadString().Remove(
|
||||||
iStart, nCount));
|
iStart, nCount));
|
||||||
|
|
||||||
UTF8Encoding utf8 = StrUtil.Utf8;
|
UTF8Encoding utf8 = StrUtil.Utf8;
|
||||||
|
char[] v = ReadChars(), vNew = null;
|
||||||
byte[] pb = ReadUtf8();
|
byte[] pbNew = null;
|
||||||
char[] v = utf8.GetChars(pb);
|
ProtectedString ps;
|
||||||
char[] vNew;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ((iStart + nCount) > v.Length)
|
if ((iStart + nCount) > v.Length)
|
||||||
throw new ArgumentException("iStart + nCount");
|
throw new ArgumentException("(iStart + nCount) > v.Length");
|
||||||
|
|
||||||
vNew = new char[v.Length - nCount];
|
vNew = new char[v.Length - nCount];
|
||||||
Array.Copy(v, 0, vNew, 0, iStart);
|
Array.Copy(v, 0, vNew, 0, iStart);
|
||||||
Array.Copy(v, iStart + nCount, vNew, iStart, v.Length -
|
Array.Copy(v, iStart + nCount, vNew, iStart, v.Length -
|
||||||
(iStart + nCount));
|
(iStart + nCount));
|
||||||
|
|
||||||
|
pbNew = utf8.GetBytes(vNew);
|
||||||
|
ps = new ProtectedString(true, pbNew);
|
||||||
|
|
||||||
|
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
|
||||||
|
ReadString().Remove(iStart, nCount));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
MemUtil.ZeroArray<char>(v);
|
MemUtil.ZeroArray<char>(v);
|
||||||
MemUtil.ZeroByteArray(pb);
|
if (vNew != null) MemUtil.ZeroArray<char>(vNew);
|
||||||
|
if (pbNew != null) MemUtil.ZeroByteArray(pbNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] pbNew = utf8.GetBytes(vNew);
|
|
||||||
ProtectedString ps = new ProtectedString(m_bIsProtected, pbNew);
|
|
||||||
|
|
||||||
Debug.Assert(utf8.GetString(pbNew, 0, pbNew.Length) ==
|
|
||||||
ReadString().Remove(iStart, nCount));
|
|
||||||
|
|
||||||
MemUtil.ZeroArray<char>(vNew);
|
|
||||||
MemUtil.ZeroByteArray(pbNew);
|
|
||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ProtectedString operator +(ProtectedString a, ProtectedString b)
|
||||||
|
{
|
||||||
|
if (a == null) throw new ArgumentNullException("a");
|
||||||
|
if (b == null) throw new ArgumentNullException("b");
|
||||||
|
|
||||||
|
if (b.IsEmpty) return a.WithProtection(a.IsProtected || b.IsProtected);
|
||||||
|
if (a.IsEmpty) return b.WithProtection(a.IsProtected || b.IsProtected);
|
||||||
|
if (!a.IsProtected && !b.IsProtected)
|
||||||
|
return new ProtectedString(false, a.ReadString() + b.ReadString());
|
||||||
|
|
||||||
|
char[] vA = a.ReadChars(), vB = null, vNew = null;
|
||||||
|
byte[] pbNew = null;
|
||||||
|
ProtectedString ps;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
vB = b.ReadChars();
|
||||||
|
|
||||||
|
vNew = new char[vA.Length + vB.Length];
|
||||||
|
Array.Copy(vA, vNew, vA.Length);
|
||||||
|
Array.Copy(vB, 0, vNew, vA.Length, vB.Length);
|
||||||
|
|
||||||
|
pbNew = StrUtil.Utf8.GetBytes(vNew);
|
||||||
|
ps = new ProtectedString(true, pbNew);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
MemUtil.ZeroArray<char>(vA);
|
||||||
|
if (vB != null) MemUtil.ZeroArray<char>(vB);
|
||||||
|
if (vNew != null) MemUtil.ZeroArray<char>(vNew);
|
||||||
|
if (pbNew != null) MemUtil.ZeroByteArray(pbNew);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProtectedString operator +(ProtectedString a, string b)
|
||||||
|
{
|
||||||
|
ProtectedString psB = new ProtectedString(false, b);
|
||||||
|
return (a + psB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,97 +20,90 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using KeePassLib.Utility;
|
||||||
|
|
||||||
namespace KeePassLib.Security
|
namespace KeePassLib.Security
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an object that is encrypted using a XOR pad until
|
/// A <c>XorredBuffer</c> object stores data that is encrypted
|
||||||
/// it is read. <c>XorredBuffer</c> objects are immutable and
|
/// using a XOR pad.
|
||||||
/// thread-safe.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class XorredBuffer
|
public sealed class XorredBuffer : IDisposable
|
||||||
{
|
{
|
||||||
private byte[] m_pbData; // Never null
|
private byte[] m_pbCT;
|
||||||
private byte[] m_pbXorPad; // Always valid for m_pbData
|
private byte[] m_pbXorPad;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Length of the protected data in bytes.
|
|
||||||
/// </summary>
|
|
||||||
public uint Length
|
public uint Length
|
||||||
{
|
{
|
||||||
get { return (uint)m_pbData.Length; }
|
get
|
||||||
|
{
|
||||||
|
if (m_pbCT == null) { Debug.Assert(false); throw new ObjectDisposedException(null); }
|
||||||
|
return (uint)m_pbCT.Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Construct a new XOR-protected object using a protected byte array
|
/// Construct a new <c>XorredBuffer</c> object.
|
||||||
/// and a XOR pad that decrypts the protected data. The
|
/// The <paramref name="pbCT" /> byte array must have the same
|
||||||
/// <paramref name="pbProtectedData" /> byte array must have the same size
|
/// length as the <paramref name="pbXorPad" /> byte array.
|
||||||
/// as the <paramref name="pbXorPad" /> byte array.
|
|
||||||
/// The <c>XorredBuffer</c> object takes ownership of the two byte
|
/// The <c>XorredBuffer</c> object takes ownership of the two byte
|
||||||
/// arrays, i.e. the caller must not use or modify them afterwards.
|
/// arrays, i.e. the caller must not use them afterwards.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pbProtectedData">Protected data (XOR pad applied).</param>
|
/// <param name="pbCT">Data with XOR pad applied.</param>
|
||||||
/// <param name="pbXorPad">XOR pad that can be used to decrypt the
|
/// <param name="pbXorPad">XOR pad that can be used to decrypt the
|
||||||
/// <paramref name="pbProtectedData" /> parameter.</param>
|
/// <paramref name="pbCT" /> byte array.</param>
|
||||||
/// <exception cref="System.ArgumentNullException">Thrown if one of the input
|
public XorredBuffer(byte[] pbCT, byte[] pbXorPad)
|
||||||
/// parameters is <c>null</c>.</exception>
|
|
||||||
/// <exception cref="System.ArgumentException">Thrown if the byte arrays are
|
|
||||||
/// of different size.</exception>
|
|
||||||
public XorredBuffer(byte[] pbProtectedData, byte[] pbXorPad)
|
|
||||||
{
|
{
|
||||||
if(pbProtectedData == null) { Debug.Assert(false); throw new ArgumentNullException("pbProtectedData"); }
|
if (pbCT == null) { Debug.Assert(false); throw new ArgumentNullException("pbCT"); }
|
||||||
if (pbXorPad == null) { Debug.Assert(false); throw new ArgumentNullException("pbXorPad"); }
|
if (pbXorPad == null) { Debug.Assert(false); throw new ArgumentNullException("pbXorPad"); }
|
||||||
|
if (pbCT.Length != pbXorPad.Length)
|
||||||
|
{
|
||||||
|
Debug.Assert(false);
|
||||||
|
throw new ArgumentOutOfRangeException("pbXorPad");
|
||||||
|
}
|
||||||
|
|
||||||
Debug.Assert(pbProtectedData.Length == pbXorPad.Length);
|
m_pbCT = pbCT;
|
||||||
if(pbProtectedData.Length != pbXorPad.Length) throw new ArgumentException();
|
|
||||||
|
|
||||||
m_pbData = pbProtectedData;
|
|
||||||
m_pbXorPad = pbXorPad;
|
m_pbXorPad = pbXorPad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
~XorredBuffer()
|
||||||
|
{
|
||||||
|
Debug.Assert((m_pbCT == null) && (m_pbXorPad == null));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (m_pbCT == null) return;
|
||||||
|
|
||||||
|
MemUtil.ZeroByteArray(m_pbCT);
|
||||||
|
m_pbCT = null;
|
||||||
|
|
||||||
|
MemUtil.ZeroByteArray(m_pbXorPad);
|
||||||
|
m_pbXorPad = null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a copy of the plain-text. The caller is responsible
|
/// Get a copy of the plain-text. The caller is responsible
|
||||||
/// for clearing the byte array safely after using it.
|
/// for clearing the byte array safely after using it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Unprotected plain-text byte array.</returns>
|
/// <returns>Plain-text byte array.</returns>
|
||||||
public byte[] ReadPlainText()
|
public byte[] ReadPlainText()
|
||||||
{
|
{
|
||||||
byte[] pbPlain = new byte[m_pbData.Length];
|
byte[] pbCT = m_pbCT, pbX = m_pbXorPad;
|
||||||
|
if ((pbCT == null) || (pbX == null) || (pbCT.Length != pbX.Length))
|
||||||
for(int i = 0; i < pbPlain.Length; ++i)
|
|
||||||
pbPlain[i] = (byte)(m_pbData[i] ^ m_pbXorPad[i]);
|
|
||||||
|
|
||||||
return pbPlain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public bool EqualsValue(XorredBuffer xb)
|
|
||||||
{
|
{
|
||||||
if(xb == null) { Debug.Assert(false); throw new ArgumentNullException("xb"); }
|
Debug.Assert(false);
|
||||||
|
throw new ObjectDisposedException(null);
|
||||||
if(xb.m_pbData.Length != m_pbData.Length) return false;
|
|
||||||
|
|
||||||
for(int i = 0; i < m_pbData.Length; ++i)
|
|
||||||
{
|
|
||||||
byte bt1 = (byte)(m_pbData[i] ^ m_pbXorPad[i]);
|
|
||||||
byte bt2 = (byte)(xb.m_pbData[i] ^ xb.m_pbXorPad[i]);
|
|
||||||
|
|
||||||
if(bt1 != bt2) return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
byte[] pbPT = new byte[pbCT.Length];
|
||||||
}
|
|
||||||
|
|
||||||
public bool EqualsValue(byte[] pb)
|
for (int i = 0; i < pbPT.Length; ++i)
|
||||||
{
|
pbPT[i] = (byte)(pbCT[i] ^ pbX[i]);
|
||||||
if(pb == null) { Debug.Assert(false); throw new ArgumentNullException("pb"); }
|
|
||||||
|
|
||||||
if(pb.Length != m_pbData.Length) return false;
|
return pbPT;
|
||||||
|
}
|
||||||
for(int i = 0; i < m_pbData.Length; ++i)
|
|
||||||
{
|
|
||||||
if((byte)(m_pbData[i] ^ m_pbXorPad[i]) != pb[i]) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,5 +360,12 @@ namespace KeePassLib.Serialization
|
|||||||
m_ioCredProtMode = IOCredProtMode.None;
|
m_ioCredProtMode = IOCredProtMode.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsSameFileAs(IOConnectionInfo other)
|
||||||
|
{
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
return Path == other.Path && UserName == other.UserName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user