mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Compare commits
136 Commits
social-bac
...
remote-wip
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48d943d98e | ||
|
|
fabd8298ef | ||
|
|
3ca23652ae | ||
|
|
55efa9dad9 | ||
|
|
bf1b5c0c95 | ||
|
|
ac685a82e6 | ||
|
|
97c49d75f8 | ||
|
|
088a4ee7b2 | ||
|
|
60d0665ad6 | ||
|
|
9a99b24fe8 | ||
|
|
7be5cba64a | ||
|
|
d463d69971 | ||
|
|
255ce7d0a5 | ||
|
|
fcfbf8e72b | ||
|
|
90d0a772be | ||
|
|
07a556c40f | ||
|
|
5374a27bff | ||
|
|
f7894dd159 | ||
|
|
5e0f7219c5 | ||
|
|
f29278b436 | ||
|
|
5bd4ab689b | ||
|
|
a665179377 | ||
|
|
d84d638f7c | ||
|
|
a6b85e5979 | ||
|
|
4453d7b36d | ||
|
|
9b5e10baf2 | ||
|
|
24c95236f0 | ||
|
|
91e5d7c70f | ||
|
|
99ffbfd5ae | ||
|
|
189dd6f7e5 | ||
|
|
4f60873e2a | ||
|
|
cf5522e7fb | ||
|
|
3f19aeb2d7 | ||
|
|
bb30fe622d | ||
|
|
0ae3ace1da | ||
|
|
f1d803820c | ||
|
|
6d6cbaf769 | ||
|
|
02743867df | ||
|
|
36d83c8974 | ||
|
|
c9ddcf50f1 | ||
|
|
12148201e4 | ||
|
|
2ec7c2d6fc | ||
|
|
deaadd6505 | ||
|
|
fa639ec45d | ||
|
|
b9363b16b7 | ||
|
|
ba9661f7c8 | ||
|
|
b2341e6392 | ||
|
|
b9c614acfb | ||
|
|
336866da51 | ||
|
|
342cfeab08 | ||
|
|
5895bc3427 | ||
|
|
bb775901e3 | ||
|
|
c76d419ecb | ||
|
|
581ecc9aaa | ||
|
|
18d1dd041d | ||
|
|
03a624ab8f | ||
|
|
9a28203437 | ||
|
|
d81964844f | ||
|
|
a26df1d11a | ||
|
|
1ae5de8b2f | ||
|
|
7119771c6e | ||
|
|
6e67c1dfbf | ||
|
|
25029e1fca | ||
|
|
0c4ad98839 | ||
|
|
8605ead547 | ||
|
|
6c6d41e2cb | ||
|
|
29bc2a5ee9 | ||
|
|
f8f573e150 | ||
|
|
c6af32650d | ||
|
|
2d5e0ee840 | ||
|
|
c64815ca16 | ||
|
|
5d6a76d64a | ||
|
|
7ff6a72ca1 | ||
|
|
68c880b257 | ||
|
|
04e18a79bd | ||
|
|
1217c2affb | ||
|
|
736651051d | ||
|
|
2177036044 | ||
|
|
ab136d3167 | ||
|
|
61bae55d7c | ||
|
|
aa9216a21e | ||
|
|
6bdfeb68a6 | ||
|
|
985779c633 | ||
|
|
9c0a58e3ac | ||
|
|
a448211549 | ||
|
|
b4de33c58d | ||
|
|
6b10c88858 | ||
|
|
b453f9b33a | ||
|
|
ec21df55f8 | ||
|
|
a8bef40fee | ||
|
|
d42c25ebf7 | ||
|
|
76c37431ba | ||
|
|
a183f16a3d | ||
|
|
cc37529f9f | ||
|
|
7eea532a81 | ||
|
|
4d5bad13ca | ||
|
|
ef7d182a74 | ||
|
|
0fe699c9b5 | ||
|
|
29ef603122 | ||
|
|
67015d7294 | ||
|
|
78a91d43b2 | ||
|
|
d8a0b6f877 | ||
|
|
7d86ec5510 | ||
|
|
6f8f9eaf9f | ||
|
|
60065fe38f | ||
|
|
ff493273c1 | ||
|
|
308b9b3ec1 | ||
|
|
31950aef9a | ||
|
|
f0d42e0d4f | ||
|
|
f2f70fa110 | ||
|
|
024511aefc | ||
|
|
2de10e6f1b | ||
|
|
92d31aa106 | ||
|
|
71c502df52 | ||
|
|
fd015d4992 | ||
|
|
5f3ec0846e | ||
|
|
892943ddf9 | ||
|
|
ad14a0cef8 | ||
|
|
3404a7d02a | ||
|
|
c8c28eb6a0 | ||
|
|
d45b4be453 | ||
|
|
f998482e93 | ||
|
|
7fb986ea9a | ||
|
|
d9fe8d962f | ||
|
|
cfc705ca41 | ||
|
|
e97114e322 | ||
|
|
eb4146b175 | ||
|
|
7659b9decb | ||
|
|
a93cbf852b | ||
|
|
fe79a18061 | ||
|
|
ae1ad4be24 | ||
|
|
014db8d45f | ||
|
|
f089c0da3e | ||
|
|
7b9d2621b7 | ||
|
|
0aea84a1b5 | ||
|
|
0224733b10 |
@@ -1,39 +1,39 @@
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
|
||||
'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
|
||||
'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
|
||||
'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
|
||||
'com.android.tools.analytics-library:protos:27.2.2:protos-27.2.2.jar:02482564443c294dfe87c5f2b25387f724a698a09ed58e0cf0127400caa35a19',
|
||||
'com.android.tools.analytics-library:shared:27.2.2:shared-27.2.2.jar:0efe017ca17ee775c5af386475a09799a1282faa04821d54810c1a34f6348d9c',
|
||||
'com.android.tools.analytics-library:tracker:27.2.2:tracker-27.2.2.jar:62489d84192dc06219664945c43201654ff85c3b715f46550751512a880d0e39',
|
||||
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
|
||||
'com.android.tools.build:apksig:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
|
||||
'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
|
||||
'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
|
||||
'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
|
||||
'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
|
||||
'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
|
||||
'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
|
||||
'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
|
||||
'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
|
||||
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
|
||||
'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
|
||||
'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
|
||||
'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
|
||||
'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
|
||||
'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
|
||||
'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
|
||||
'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
|
||||
'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
|
||||
'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
|
||||
'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
|
||||
'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
|
||||
'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
|
||||
'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
|
||||
'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
|
||||
'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
|
||||
'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
|
||||
'com.android.tools.build:apksig:4.2.2:apksig-4.2.2.jar:632690bf641b429dcb31650e6b2f6a2e87c4ac8afd45a6ba3cbc99fb1612178f',
|
||||
'com.android.tools.build:apkzlib:4.2.2:apkzlib-4.2.2.jar:3b5167c1265e97f65201c4d2be6a6f72165a3aa2fe9e0594a59b67af9e9e97b9',
|
||||
'com.android.tools.build:builder-model:4.2.2:builder-model-4.2.2.jar:41868de0cb88ae70b828eee4191c13e0233f433abb1becdf6a2bd391bd446bc0',
|
||||
'com.android.tools.build:builder-test-api:4.2.2:builder-test-api-4.2.2.jar:2f305c6d3a7b637d736b821bad372dcabd959e979f2065a9f65bac1e7b4d1875',
|
||||
'com.android.tools.build:builder:4.2.2:builder-4.2.2.jar:40fedd0d16db8f34ddb4eaf812d966b90ef1764f65cf119030442823bcf995cd',
|
||||
'com.android.tools.build:gradle-api:4.2.2:gradle-api-4.2.2.jar:dd4ef35bbbfb8fc2d20e3311c76b516bc1672e82b61cb3a59fc877da0f9b4f61',
|
||||
'com.android.tools.build:manifest-merger:27.2.2:manifest-merger-27.2.2.jar:971974756f32d9e94c857d92772b1499b0b0f5d9c70cb8ebbd20d9bbf804a923',
|
||||
'com.android.tools.ddms:ddmlib:27.2.2:ddmlib-27.2.2.jar:9ab0f9b58737c316af454184705854c75936ca3531f21acc29bd68a3343334d1',
|
||||
'com.android.tools.external.com-intellij:intellij-core:27.2.2:intellij-core-27.2.2.jar:01619d5dc28ec909cbdee699f1f13056e84462faf6dccf4817561293fb28bef0',
|
||||
'com.android.tools.external.com-intellij:kotlin-compiler:27.2.2:kotlin-compiler-27.2.2.jar:71bd460199ce7293ecc54b91a115319c1e4b585eca5a5b3699f6a406f29e626c',
|
||||
'com.android.tools.external.org-jetbrains:uast:27.2.2:uast-27.2.2.jar:efa59302fd433015e993143530cecb456b63d10d0b89bd1d3b1a016904338a65',
|
||||
'com.android.tools.layoutlib:layoutlib-api:27.2.2:layoutlib-api-27.2.2.jar:f0901f2295d814e82ad95850ea2103dd89d8489e01727fafa55ccccc0dccd163',
|
||||
'com.android.tools.lint:lint-api:27.2.2:lint-api-27.2.2.jar:1ecb5959c8e624ee49cdf9178de67bb0e823b4382ed253410eb36afe5c458b05',
|
||||
'com.android.tools.lint:lint-checks:27.2.2:lint-checks-27.2.2.jar:989e545a6b5e398e63a9f3608da02d6111f2241faec1baa0a3b4492cb03aeaf2',
|
||||
'com.android.tools.lint:lint-gradle-api:27.2.2:lint-gradle-api-27.2.2.jar:2be9c69d6fbbfb012ff6521fdfcb22eb7cfaa57d108e07bb1d4143dae9c1b433',
|
||||
'com.android.tools.lint:lint-gradle:27.2.2:lint-gradle-27.2.2.jar:742dedd5ccb459a245a35bf4fa16dfecc762da1a6b1741332cfe5228e812301a',
|
||||
'com.android.tools.lint:lint-model:27.2.2:lint-model-27.2.2.jar:ee31012586462bea2d591b6175934e5f29b6f781a78fda50f79387972364b9ab',
|
||||
'com.android.tools.lint:lint:27.2.2:lint-27.2.2.jar:7247016af7fba8cabee6ae887515b144f5a2ff7823422654daf23be9202f8fb1',
|
||||
'com.android.tools:annotations:27.2.2:annotations-27.2.2.jar:9375fb2df5c0cf1b46fef9e65b3a27ac88925ccf90054b19ae0ca0adc7036fe1',
|
||||
'com.android.tools:common:27.2.2:common-27.2.2.jar:a76f4e10cad39bed317be031fee915d280aa8bc11616c58ab94e051b1e38769d',
|
||||
'com.android.tools:dvlib:27.2.2:dvlib-27.2.2.jar:9931c6b57460b5f8cc2613ca5ff8596aa089a67655ace13d173f90538ecb4301',
|
||||
'com.android.tools:repository:27.2.2:repository-27.2.2.jar:ac5f9b19dc5d9d08e80b57da76059f5760ca76c221e40ffd4bf43d7b13991674',
|
||||
'com.android.tools:sdk-common:27.2.2:sdk-common-27.2.2.jar:b147acc13850808d61fc391ccfeeebdf90841b461a7042acb2d92e466da8e674',
|
||||
'com.android.tools:sdklib:27.2.2:sdklib-27.2.2.jar:fae0bafbe8b4f546cf64986a22b7d8ed108d45519366ff22f0170a9cf3ea7f34',
|
||||
'com.android:signflinger:4.2.2:signflinger-4.2.2.jar:4d7aafd9666707b483b1ad2c466824287cf2e379dda1d204dd3b7e453ffcf760',
|
||||
'com.android:zipflinger:4.2.2:zipflinger-4.2.2.jar:8e4677086c9a8f4a67374a4edc31db7e481f0d9b85907263c51ca72452c23a93',
|
||||
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
|
||||
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||
'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
|
||||
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
|
||||
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
|
||||
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
|
||||
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
|
||||
@@ -54,17 +54,19 @@ dependencyVerification {
|
||||
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
|
||||
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
|
||||
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
||||
'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
|
||||
'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
|
||||
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
|
||||
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
|
||||
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
|
||||
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
|
||||
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
|
||||
'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
|
||||
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
|
||||
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
|
||||
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
|
||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
|
||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
|
||||
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
|
||||
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
|
||||
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
|
||||
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
|
||||
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
|
||||
@@ -84,24 +86,24 @@ dependencyVerification {
|
||||
'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0',
|
||||
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
|
||||
'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d',
|
||||
'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
|
||||
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
|
||||
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
|
||||
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
|
||||
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
|
||||
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
|
||||
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
|
||||
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
|
||||
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
||||
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
|
||||
'org.jetbrains.kotlin:kotlin-reflect:1.4.31:kotlin-reflect-1.4.31.jar:91fad0b42974a7d5811e30a61f05706e176b144235717c6de7e81e3a781028f2',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.31:kotlin-stdlib-common-1.4.31.jar:57962f44371a746b678218a0802a8712c6255206de9a69ede215e3aa4b044708',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.31:kotlin-stdlib-jdk7-1.4.31.jar:1f966e54e86cf4b7d7014afdce04e0f3ee4625084cda3494edccc7b84af52664',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.31:kotlin-stdlib-jdk8-1.4.31.jar:b2f8364435ebcb0106ff9d4415a11ffdef8ec7786ee6e5ed465a01556cbd1683',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib:1.4.31:kotlin-stdlib-1.4.31.jar:76a599d88b167e8ac90879b6daa722c6ad3452ba714c9aba19bd196544b97f1c',
|
||||
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
||||
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
|
||||
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
|
||||
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
|
||||
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
|
||||
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
|
||||
'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
|
||||
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
|
||||
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
|
||||
'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
|
||||
'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
|
||||
@@ -109,5 +111,7 @@ dependencyVerification {
|
||||
'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
|
||||
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
|
||||
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
|
||||
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
|
||||
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ apply from: '../dagger.gradle'
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':bramble-api', configuration: 'default')
|
||||
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
|
||||
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
|
||||
implementation 'org.bitlet:weupnp:0.1.4'
|
||||
implementation 'net.i2p.crypto:eddsa:0.2.0'
|
||||
|
||||
@@ -21,9 +21,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.SecureRandomProvider;
|
||||
import org.briarproject.bramble.util.ByteUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.spongycastle.crypto.CryptoException;
|
||||
import org.spongycastle.crypto.Digest;
|
||||
import org.spongycastle.crypto.digests.Blake2bDigest;
|
||||
import org.bouncycastle.crypto.CryptoException;
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.digests.Blake2bDigest;
|
||||
import org.whispersystems.curve25519.Curve25519;
|
||||
import org.whispersystems.curve25519.Curve25519KeyPair;
|
||||
|
||||
|
||||
@@ -6,33 +6,33 @@ import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
|
||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.spongycastle.crypto.BasicAgreement;
|
||||
import org.spongycastle.crypto.BlockCipher;
|
||||
import org.spongycastle.crypto.CipherParameters;
|
||||
import org.spongycastle.crypto.CryptoException;
|
||||
import org.spongycastle.crypto.DerivationFunction;
|
||||
import org.spongycastle.crypto.KeyEncoder;
|
||||
import org.spongycastle.crypto.Mac;
|
||||
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
|
||||
import org.spongycastle.crypto.digests.SHA256Digest;
|
||||
import org.spongycastle.crypto.engines.AESLightEngine;
|
||||
import org.spongycastle.crypto.engines.IESEngine;
|
||||
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.spongycastle.crypto.generators.EphemeralKeyPairGenerator;
|
||||
import org.spongycastle.crypto.generators.KDF2BytesGenerator;
|
||||
import org.spongycastle.crypto.macs.HMac;
|
||||
import org.spongycastle.crypto.modes.CBCBlockCipher;
|
||||
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||||
import org.spongycastle.crypto.params.AsymmetricKeyParameter;
|
||||
import org.spongycastle.crypto.params.ECDomainParameters;
|
||||
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.spongycastle.crypto.params.IESWithCipherParameters;
|
||||
import org.spongycastle.crypto.parsers.ECIESPublicKeyParser;
|
||||
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
|
||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.bouncycastle.crypto.BasicAgreement;
|
||||
import org.bouncycastle.crypto.BlockCipher;
|
||||
import org.bouncycastle.crypto.CipherParameters;
|
||||
import org.bouncycastle.crypto.CryptoException;
|
||||
import org.bouncycastle.crypto.DerivationFunction;
|
||||
import org.bouncycastle.crypto.KeyEncoder;
|
||||
import org.bouncycastle.crypto.Mac;
|
||||
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
|
||||
import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
import org.bouncycastle.crypto.engines.AESLightEngine;
|
||||
import org.bouncycastle.crypto.engines.IESEngine;
|
||||
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
|
||||
import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
|
||||
import org.bouncycastle.crypto.macs.HMac;
|
||||
import org.bouncycastle.crypto.modes.CBCBlockCipher;
|
||||
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
|
||||
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.crypto.params.IESWithCipherParameters;
|
||||
import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.spongycastle.crypto.generators.SCrypt;
|
||||
import org.bouncycastle.crypto.generators.SCrypt;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import org.briarproject.bramble.api.crypto.KeyParser;
|
||||
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.spongycastle.crypto.params.ECDomainParameters;
|
||||
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.spongycastle.math.ec.ECCurve;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.transport.IncomingKeys;
|
||||
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||
import org.spongycastle.crypto.Digest;
|
||||
import org.spongycastle.crypto.digests.Blake2bDigest;
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.digests.Blake2bDigest;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ package org.briarproject.bramble.crypto;
|
||||
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.spongycastle.crypto.DataLengthException;
|
||||
import org.spongycastle.crypto.engines.XSalsa20Engine;
|
||||
import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
|
||||
import org.spongycastle.crypto.macs.Poly1305;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
import org.spongycastle.crypto.params.ParametersWithIV;
|
||||
import org.bouncycastle.crypto.DataLengthException;
|
||||
import org.bouncycastle.crypto.engines.XSalsa20Engine;
|
||||
import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
|
||||
import org.bouncycastle.crypto.macs.Poly1305;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
||||
|
||||
import org.briarproject.bramble.util.Base32;
|
||||
import org.spongycastle.crypto.Digest;
|
||||
import org.spongycastle.crypto.digests.SHA3Digest;
|
||||
import org.spongycastle.util.encoders.Base64;
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.digests.SHA3Digest;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ package org.briarproject.bramble.rendezvous;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
|
||||
import org.spongycastle.crypto.engines.Salsa20Engine;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
import org.spongycastle.crypto.params.ParametersWithIV;
|
||||
import org.bouncycastle.crypto.engines.Salsa20Engine;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto;
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.crypto.digests.Blake2bDigest;
|
||||
import org.bouncycastle.crypto.digests.Blake2bDigest;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
|
||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
|
||||
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.spongycastle.crypto.params.ECDomainParameters;
|
||||
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.spongycastle.math.ec.ECCurve;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class EllipticCurveMultiplicationTest extends BrambleTestCase {
|
||||
|
||||
@Test
|
||||
public void testMultiplierProducesSameResultsAsDefault() throws Exception {
|
||||
// Instantiate the default implementation of the curve
|
||||
X9ECParameters defaultX9Parameters =
|
||||
TeleTrusTNamedCurves.getByName("brainpoolp256r1");
|
||||
ECCurve defaultCurve = defaultX9Parameters.getCurve();
|
||||
ECPoint defaultG = defaultX9Parameters.getG();
|
||||
BigInteger defaultN = defaultX9Parameters.getN();
|
||||
BigInteger defaultH = defaultX9Parameters.getH();
|
||||
ECDomainParameters defaultParameters = new ECDomainParameters(
|
||||
defaultCurve, defaultG, defaultN, defaultH);
|
||||
// Instantiate an implementation using the Montgomery ladder multiplier
|
||||
ECDomainParameters montgomeryParameters =
|
||||
constantTime(defaultParameters);
|
||||
// Generate two key pairs with each set of parameters, using the same
|
||||
// deterministic PRNG for both sets of parameters
|
||||
byte[] seed = new byte[32];
|
||||
new SecureRandom().nextBytes(seed);
|
||||
// Montgomery ladder multiplier
|
||||
SecureRandom random = new PseudoSecureRandom(seed);
|
||||
ECKeyGenerationParameters montgomeryGeneratorParams =
|
||||
new ECKeyGenerationParameters(montgomeryParameters, random);
|
||||
ECKeyPairGenerator montgomeryGenerator = new ECKeyPairGenerator();
|
||||
montgomeryGenerator.init(montgomeryGeneratorParams);
|
||||
AsymmetricCipherKeyPair montgomeryKeyPair1 =
|
||||
montgomeryGenerator.generateKeyPair();
|
||||
ECPrivateKeyParameters montgomeryPrivate1 =
|
||||
(ECPrivateKeyParameters) montgomeryKeyPair1.getPrivate();
|
||||
ECPublicKeyParameters montgomeryPublic1 =
|
||||
(ECPublicKeyParameters) montgomeryKeyPair1.getPublic();
|
||||
AsymmetricCipherKeyPair montgomeryKeyPair2 =
|
||||
montgomeryGenerator.generateKeyPair();
|
||||
ECPrivateKeyParameters montgomeryPrivate2 =
|
||||
(ECPrivateKeyParameters) montgomeryKeyPair2.getPrivate();
|
||||
ECPublicKeyParameters montgomeryPublic2 =
|
||||
(ECPublicKeyParameters) montgomeryKeyPair2.getPublic();
|
||||
// Default multiplier
|
||||
random = new PseudoSecureRandom(seed);
|
||||
ECKeyGenerationParameters defaultGeneratorParams =
|
||||
new ECKeyGenerationParameters(defaultParameters, random);
|
||||
ECKeyPairGenerator defaultGenerator = new ECKeyPairGenerator();
|
||||
defaultGenerator.init(defaultGeneratorParams);
|
||||
AsymmetricCipherKeyPair defaultKeyPair1 =
|
||||
defaultGenerator.generateKeyPair();
|
||||
ECPrivateKeyParameters defaultPrivate1 =
|
||||
(ECPrivateKeyParameters) defaultKeyPair1.getPrivate();
|
||||
ECPublicKeyParameters defaultPublic1 =
|
||||
(ECPublicKeyParameters) defaultKeyPair1.getPublic();
|
||||
AsymmetricCipherKeyPair defaultKeyPair2 =
|
||||
defaultGenerator.generateKeyPair();
|
||||
ECPrivateKeyParameters defaultPrivate2 =
|
||||
(ECPrivateKeyParameters) defaultKeyPair2.getPrivate();
|
||||
ECPublicKeyParameters defaultPublic2 =
|
||||
(ECPublicKeyParameters) defaultKeyPair2.getPublic();
|
||||
// The key pairs generated with both sets of parameters should be equal
|
||||
assertEquals(montgomeryPrivate1.getD(), defaultPrivate1.getD());
|
||||
assertEquals(montgomeryPublic1.getQ(), defaultPublic1.getQ());
|
||||
assertEquals(montgomeryPrivate2.getD(), defaultPrivate2.getD());
|
||||
assertEquals(montgomeryPublic2.getQ(), defaultPublic2.getQ());
|
||||
// OK, all of the above was just sanity checks - now for the test!
|
||||
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
|
||||
agreement.init(montgomeryPrivate1);
|
||||
BigInteger sharedSecretMontgomeryMontgomery =
|
||||
agreement.calculateAgreement(montgomeryPublic2);
|
||||
agreement.init(montgomeryPrivate1);
|
||||
BigInteger sharedSecretMontgomeryDefault =
|
||||
agreement.calculateAgreement(defaultPublic2);
|
||||
agreement.init(defaultPrivate1);
|
||||
BigInteger sharedSecretDefaultMontgomery =
|
||||
agreement.calculateAgreement(montgomeryPublic2);
|
||||
agreement.init(defaultPrivate1);
|
||||
BigInteger sharedSecretDefaultDefault =
|
||||
agreement.calculateAgreement(defaultPublic2);
|
||||
// Shared secrets calculated with different multipliers should be equal
|
||||
assertEquals(sharedSecretMontgomeryMontgomery,
|
||||
sharedSecretMontgomeryDefault);
|
||||
assertEquals(sharedSecretMontgomeryMontgomery,
|
||||
sharedSecretDefaultMontgomery);
|
||||
assertEquals(sharedSecretMontgomeryMontgomery,
|
||||
sharedSecretDefaultDefault);
|
||||
}
|
||||
|
||||
private static ECDomainParameters constantTime(ECDomainParameters in) {
|
||||
ECCurve curve = in.getCurve().configure().setMultiplier(
|
||||
new MontgomeryLadderMultiplier()).create();
|
||||
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
|
||||
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
|
||||
ECPoint g = curve.createPoint(x, y);
|
||||
return new ECDomainParameters(curve, g, in.getN(), in.getH());
|
||||
}
|
||||
}
|
||||
@@ -3,30 +3,26 @@ package org.briarproject.bramble.crypto;
|
||||
import net.i2p.crypto.eddsa.EdDSASecurityProvider;
|
||||
import net.i2p.crypto.eddsa.KeyPairGenerator;
|
||||
|
||||
import org.spongycastle.asn1.sec.SECNamedCurves;
|
||||
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
|
||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.spongycastle.crypto.BasicAgreement;
|
||||
import org.spongycastle.crypto.Digest;
|
||||
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
|
||||
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
|
||||
import org.spongycastle.crypto.digests.Blake2bDigest;
|
||||
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.spongycastle.crypto.params.ECDomainParameters;
|
||||
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.spongycastle.crypto.params.ParametersWithRandom;
|
||||
import org.spongycastle.crypto.signers.DSADigestSigner;
|
||||
import org.spongycastle.crypto.signers.DSAKCalculator;
|
||||
import org.spongycastle.crypto.signers.ECDSASigner;
|
||||
import org.spongycastle.crypto.signers.HMacDSAKCalculator;
|
||||
import org.spongycastle.math.ec.ECCurve;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
|
||||
import org.bouncycastle.asn1.sec.SECNamedCurves;
|
||||
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
|
||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
|
||||
import org.bouncycastle.crypto.BasicAgreement;
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
|
||||
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
|
||||
import org.bouncycastle.crypto.digests.Blake2bDigest;
|
||||
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
|
||||
import org.bouncycastle.crypto.params.ParametersWithRandom;
|
||||
import org.bouncycastle.crypto.signers.DSADigestSigner;
|
||||
import org.bouncycastle.crypto.signers.DSAKCalculator;
|
||||
import org.bouncycastle.crypto.signers.ECDSASigner;
|
||||
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
|
||||
import org.whispersystems.curve25519.Curve25519;
|
||||
import org.whispersystems.curve25519.Curve25519KeyPair;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.Provider;
|
||||
@@ -55,14 +51,12 @@ public class EllipticCurvePerformanceTest {
|
||||
for (String name : SEC_NAMES) {
|
||||
ECDomainParameters params =
|
||||
convertParams(SECNamedCurves.getByName(name));
|
||||
runTest(name + " default", params);
|
||||
runTest(name + " constant", constantTime(params));
|
||||
runTest(name, params);
|
||||
}
|
||||
for (String name : BRAINPOOL_NAMES) {
|
||||
ECDomainParameters params =
|
||||
convertParams(TeleTrusTNamedCurves.getByName(name));
|
||||
runTest(name + " default", params);
|
||||
runTest(name + " constant", constantTime(params));
|
||||
runTest(name, params);
|
||||
}
|
||||
runCurve25519Test();
|
||||
runEd25519Test();
|
||||
@@ -193,13 +187,4 @@ public class EllipticCurvePerformanceTest {
|
||||
return new ECDomainParameters(in.getCurve(), in.getG(), in.getN(),
|
||||
in.getH());
|
||||
}
|
||||
|
||||
private static ECDomainParameters constantTime(ECDomainParameters in) {
|
||||
ECCurve curve = in.getCurve().configure().setMultiplier(
|
||||
new MontgomeryLadderMultiplier()).create();
|
||||
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
|
||||
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
|
||||
ECPoint g = curve.createPoint(x, y);
|
||||
return new ECDomainParameters(curve, g, in.getN(), in.getH());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.crypto.CryptoException;
|
||||
import org.bouncycastle.crypto.CryptoException;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package org.briarproject.bramble.crypto;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.spongycastle.crypto.Digest;
|
||||
import org.spongycastle.crypto.digests.Blake2bDigest;
|
||||
import org.spongycastle.crypto.engines.Salsa20Engine;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
import org.spongycastle.crypto.params.ParametersWithIV;
|
||||
import org.bouncycastle.crypto.Digest;
|
||||
import org.bouncycastle.crypto.digests.Blake2bDigest;
|
||||
import org.bouncycastle.crypto.engines.Salsa20Engine;
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ dependencyVerification {
|
||||
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
|
||||
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
|
||||
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
|
||||
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
|
||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
@@ -27,6 +26,7 @@ dependencyVerification {
|
||||
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
|
||||
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
|
||||
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
||||
'org.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
|
||||
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
|
||||
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
|
||||
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
|
||||
|
||||
@@ -464,6 +464,42 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/TranslucentTheme">
|
||||
<intent-filter>
|
||||
<action android:name="org.briarproject.briar.android.AndroidNotifiactionManager" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.remotewipe.RemoteWipeSetupActivity"
|
||||
android:label="@string/activity_name_remote_wipe"
|
||||
android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.briarproject.briar.android.settings.SettingsActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity"
|
||||
android:label="@string/activity_name_activate_remote_wipe"
|
||||
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity"
|
||||
android:label="@string/activity_name_revoke_remote_wipe"
|
||||
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.logout.ExitActivity"
|
||||
android:theme="@android:style/Theme.NoDisplay" />
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.briarproject.briar.android.forum.ForumActivity;
|
||||
import org.briarproject.briar.android.login.SignInReminderReceiver;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity;
|
||||
import org.briarproject.briar.android.splash.SplashScreenActivity;
|
||||
import org.briarproject.briar.android.util.BriarNotificationBuilder;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
|
||||
@@ -39,6 +39,7 @@ import org.briarproject.briar.android.login.LoginModule;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerModule;
|
||||
import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule;
|
||||
import org.briarproject.briar.android.privategroup.list.GroupListModule;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeModule;
|
||||
import org.briarproject.briar.android.reporting.DevReportModule;
|
||||
import org.briarproject.briar.android.settings.SettingsModule;
|
||||
import org.briarproject.briar.android.sharing.SharingModule;
|
||||
@@ -96,6 +97,7 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||
SharingModule.class,
|
||||
OwnerReturnShardModule.class,
|
||||
CustodianReturnShardModule.class,
|
||||
RemoteWipeModule.class,
|
||||
SocialBackupSetupModule.class
|
||||
})
|
||||
public class AppModule {
|
||||
|
||||
@@ -18,14 +18,19 @@ import com.bumptech.glide.Glide;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.logout.HideUiActivity;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeActivatedEvent;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -62,7 +67,7 @@ import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGO
|
||||
import static org.briarproject.briar.api.android.LockManager.ACTION_LOCK;
|
||||
import static org.briarproject.briar.api.android.LockManager.EXTRA_PID;
|
||||
|
||||
public class BriarService extends Service {
|
||||
public class BriarService extends Service implements EventListener {
|
||||
|
||||
public static String EXTRA_START_RESULT =
|
||||
"org.briarproject.briar.START_RESULT";
|
||||
@@ -96,6 +101,8 @@ public class BriarService extends Service {
|
||||
@Inject
|
||||
volatile AndroidExecutor androidExecutor;
|
||||
private volatile boolean started = false;
|
||||
@Inject
|
||||
volatile EventBus eventBus;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
@@ -173,6 +180,8 @@ public class BriarService extends Service {
|
||||
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF");
|
||||
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF");
|
||||
registerReceiver(receiver, filter);
|
||||
|
||||
eventBus.addListener(this);
|
||||
}, "LifecycleStartup");
|
||||
}
|
||||
|
||||
@@ -239,6 +248,7 @@ public class BriarService extends Service {
|
||||
wakeLockManager.executeWakefully(() -> {
|
||||
if (started) lifecycleManager.stopServices();
|
||||
}, "LifecycleShutdown");
|
||||
eventBus.removeListener(this);
|
||||
}, "LifecycleShutdown");
|
||||
}
|
||||
|
||||
@@ -327,6 +337,19 @@ public class BriarService extends Service {
|
||||
stopSelf(); // This will call onDestroy()
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for the remote wipe event
|
||||
*/
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof RemoteWipeActivatedEvent) {
|
||||
Intent i = new Intent(this, RemoteWipeActivatedActivity.class);
|
||||
i.addFlags(FLAG_ACTIVITY_NEW_TASK
|
||||
| FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivity(i);
|
||||
}
|
||||
}
|
||||
|
||||
public class BriarBinder extends Binder {
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,6 +63,15 @@ import org.briarproject.briar.android.privategroup.memberlist.GroupMemberModule;
|
||||
import org.briarproject.briar.android.privategroup.reveal.GroupRevealModule;
|
||||
import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
|
||||
import org.briarproject.briar.android.privategroup.reveal.RevealContactsFragment;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeDisplayFragment;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeSetupActivity;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeSetupExplainerFragment;
|
||||
import org.briarproject.briar.android.remotewipe.WiperSelectorFragment;
|
||||
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity;
|
||||
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeExplainerFragment;
|
||||
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity;
|
||||
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeSuccessFragment;
|
||||
import org.briarproject.briar.android.reporting.CrashFragment;
|
||||
import org.briarproject.briar.android.reporting.CrashReportActivity;
|
||||
import org.briarproject.briar.android.reporting.ReportFormFragment;
|
||||
@@ -209,6 +218,14 @@ public interface ActivityComponent {
|
||||
|
||||
void inject(RestoreAccountActivity restoreAccountActivity);
|
||||
|
||||
void inject(RemoteWipeSetupActivity remoteWipeSetupActivity);
|
||||
|
||||
void inject(ActivateRemoteWipeActivity activateRemoteWipeActivity);
|
||||
|
||||
void inject(RemoteWipeActivatedActivity remoteWipeActivatedActivity);
|
||||
|
||||
void inject(RevokeRemoteWipeActivity revokeRemoteWipeActivity);
|
||||
|
||||
// Fragments
|
||||
|
||||
void inject(AuthorNameFragment fragment);
|
||||
@@ -295,5 +312,15 @@ public interface ActivityComponent {
|
||||
|
||||
void inject(CustodianReturnShardErrorFragment custodianReturnShardErrorFragment);
|
||||
|
||||
void inject(WiperSelectorFragment wiperSelectorFragment);
|
||||
|
||||
void inject(RemoteWipeDisplayFragment remoteWipeDisplayFragment);
|
||||
|
||||
void inject(ActivateRemoteWipeExplainerFragment activateRemoteWipeExplainerFragment);
|
||||
|
||||
void inject(RevokeRemoteWipeSuccessFragment revokeRemoteWipeSuccessFragment);
|
||||
|
||||
void inject(RemoteWipeSetupExplainerFragment remoteWipeSetupExplainerFragment);
|
||||
|
||||
void inject(SetupExplainerFragment setupExplainerFragment);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ import org.briarproject.briar.android.conversation.ConversationVisitor.TextCache
|
||||
import org.briarproject.briar.android.forum.ForumActivity;
|
||||
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity;
|
||||
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity;
|
||||
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardActivity;
|
||||
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
|
||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||
@@ -371,6 +373,20 @@ public class ConversationActivity extends BriarActivity
|
||||
observeOnce(viewModel.getContactItem(), this, contact ->
|
||||
menu.findItem(R.id.action_set_alias).setEnabled(true));
|
||||
|
||||
// enable remote wipe action if available
|
||||
observeOnce(viewModel.amRemoteWiper(), this, amWiper -> {
|
||||
if (amWiper != null && amWiper) {
|
||||
menu.findItem(R.id.action_remote_wipe).setEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
// enable revoke remote wipe action if available
|
||||
observeOnce(viewModel.isRemoteWiper(), this, isWiper -> {
|
||||
if (isWiper != null && isWiper) {
|
||||
menu.findItem(R.id.action_revoke_remote_wipe).setEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
// enable help recover account action if available
|
||||
observeOnce(viewModel.amCustodian(), this, enable -> {
|
||||
if (enable) {
|
||||
@@ -410,6 +426,18 @@ public class ConversationActivity extends BriarActivity
|
||||
i.putExtra(CONTACT_ID, contactId.getInt());
|
||||
startActivity(i);
|
||||
return true;
|
||||
case R.id.action_remote_wipe:
|
||||
if (contactId == null) return false;
|
||||
Intent r = new Intent(this, ActivateRemoteWipeActivity.class);
|
||||
r.putExtra(CONTACT_ID, contactId.getInt());
|
||||
startActivity(r);
|
||||
return true;
|
||||
case R.id.action_revoke_remote_wipe:
|
||||
if (contactId == null) return false;
|
||||
Intent s = new Intent(this, RevokeRemoteWipeActivity.class);
|
||||
s.putExtra(CONTACT_ID, contactId.getInt());
|
||||
startActivity(s);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.android.conversation;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.api.conversation.ConversationRequest;
|
||||
import org.briarproject.briar.api.conversation.ConversationResponse;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
|
||||
import org.briarproject.briar.api.socialbackup.ShardMessageHeader;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -38,6 +39,13 @@ class ConversationNoticeItem extends ConversationItem {
|
||||
this.msgText = null;
|
||||
}
|
||||
|
||||
ConversationNoticeItem(@LayoutRes int layoutRes, String text,
|
||||
RemoteWipeMessageHeader r) {
|
||||
super(layoutRes, r);
|
||||
this.text = text;
|
||||
this.msgText = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
String getMsgText() {
|
||||
return msgText;
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.messaging.event.AttachmentReceivedEvent;
|
||||
import org.briarproject.briar.api.socialbackup.SocialBackup;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -86,6 +86,7 @@ public class ConversationViewModel extends DbViewModel
|
||||
private final PrivateMessageFactory privateMessageFactory;
|
||||
private final AttachmentRetriever attachmentRetriever;
|
||||
private final AttachmentCreator attachmentCreator;
|
||||
private final RemoteWipeManager remoteWipeManager;
|
||||
private final SocialBackupManager socialBackupManager;
|
||||
|
||||
@Nullable
|
||||
@@ -107,6 +108,8 @@ public class ConversationViewModel extends DbViewModel
|
||||
new MutableLiveData<>();
|
||||
private final MutableLiveEvent<PrivateMessageHeader> addedHeader =
|
||||
new MutableLiveEvent<>();
|
||||
private final MutableLiveData<Boolean> amRemoteWiper = new MutableLiveData<>();
|
||||
private final MutableLiveData<Boolean> isRemoteWiper = new MutableLiveData<>();
|
||||
private final MutableLiveData<Boolean> amCustodian = new MutableLiveData<>();
|
||||
|
||||
@Inject
|
||||
@@ -122,6 +125,7 @@ public class ConversationViewModel extends DbViewModel
|
||||
SettingsManager settingsManager,
|
||||
PrivateMessageFactory privateMessageFactory,
|
||||
AttachmentRetriever attachmentRetriever,
|
||||
RemoteWipeManager remoteWipeManager,
|
||||
AttachmentCreator attachmentCreator,
|
||||
SocialBackupManager socialBackupManager) {
|
||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
|
||||
@@ -134,6 +138,7 @@ public class ConversationViewModel extends DbViewModel
|
||||
this.privateMessageFactory = privateMessageFactory;
|
||||
this.attachmentRetriever = attachmentRetriever;
|
||||
this.attachmentCreator = attachmentCreator;
|
||||
this.remoteWipeManager = remoteWipeManager;
|
||||
this.socialBackupManager = socialBackupManager;
|
||||
messagingGroupId = map(contactItem, c ->
|
||||
messagingManager.getContactGroup(c.getContact()).getId());
|
||||
@@ -303,11 +308,18 @@ public class ConversationViewModel extends DbViewModel
|
||||
showIntroductionOnboarding.postEvent(true);
|
||||
}
|
||||
|
||||
// Check if we are a remote wiper for this contact
|
||||
boolean amWiper = db.transactionWithResult(true,
|
||||
txn -> remoteWipeManager.amWiper(txn, c));
|
||||
amRemoteWiper.postValue(amWiper);
|
||||
|
||||
boolean isWiper = db.transactionWithResult(true,
|
||||
txn -> remoteWipeManager.isWiper(txn, c));
|
||||
isRemoteWiper.postValue(isWiper);
|
||||
// Check if we are a social backup custodian for this contact
|
||||
boolean amCustodianBool = db.transactionWithResult(true,
|
||||
txn -> socialBackupManager.amCustodian(txn, c));
|
||||
amCustodian.postValue(amCustodianBool);
|
||||
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
@@ -393,6 +405,14 @@ public class ConversationViewModel extends DbViewModel
|
||||
return addedHeader;
|
||||
}
|
||||
|
||||
LiveData<Boolean> amRemoteWiper() {
|
||||
return amRemoteWiper;
|
||||
}
|
||||
|
||||
LiveData<Boolean> isRemoteWiper() {
|
||||
return isRemoteWiper;
|
||||
}
|
||||
|
||||
LiveData<Boolean> amCustodian() {
|
||||
return amCustodian;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.attachment.AttachmentItem;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
import org.briarproject.briar.api.blog.BlogInvitationRequest;
|
||||
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageVisitor;
|
||||
@@ -16,6 +17,7 @@ import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
|
||||
import org.briarproject.briar.api.socialbackup.ShardMessageHeader;
|
||||
|
||||
import java.util.List;
|
||||
@@ -308,6 +310,55 @@ class ConversationVisitor implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConversationItem visitRemoteWipeMessage(RemoteWipeMessageHeader r) {
|
||||
switch (r.getMessageType()) {
|
||||
case SETUP:
|
||||
if (r.isLocal()) {
|
||||
String text = ctx.getString(R.string.remote_wipe_setup_sent,
|
||||
contactName.getValue());
|
||||
return new ConversationNoticeItem(
|
||||
R.layout.list_item_conversation_notice_out, text,
|
||||
r);
|
||||
} else {
|
||||
String text =
|
||||
ctx.getString(R.string.remote_wipe_setup_received,
|
||||
contactName.getValue());
|
||||
return new ConversationNoticeItem(
|
||||
R.layout.list_item_conversation_notice_in, text, r);
|
||||
}
|
||||
case WIPE:
|
||||
String text = ctx.getString(R.string.remote_wipe_wipe_sent,
|
||||
contactName.getValue()) + " " + UiUtils
|
||||
.formatDateAbsolute(ctx, r.getMessageExpiry());
|
||||
return new ConversationNoticeItem(
|
||||
R.layout.list_item_conversation_notice_out, text, r);
|
||||
case CONFIRM:
|
||||
System.out.println("Processing confirm message");
|
||||
String confirmText =
|
||||
ctx.getString(R.string.remote_wipe_confirm_received,
|
||||
contactName.getValue());
|
||||
return new ConversationNoticeItem(
|
||||
R.layout.list_item_conversation_notice_in, confirmText, r);
|
||||
default: // REVOKE
|
||||
String revokeText;
|
||||
if (r.isLocal()) {
|
||||
revokeText = ctx.getString(R.string.remote_wipe_revoke_sent,
|
||||
contactName.getValue());
|
||||
return new ConversationNoticeItem(
|
||||
R.layout.list_item_conversation_notice_out,
|
||||
revokeText, r);
|
||||
} else {
|
||||
revokeText =
|
||||
ctx.getString(R.string.remote_wipe_revoke_received,
|
||||
contactName.getValue());
|
||||
return new ConversationNoticeItem(
|
||||
R.layout.list_item_conversation_notice_in,
|
||||
revokeText, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface TextCache {
|
||||
@Nullable
|
||||
String getText(MessageId m);
|
||||
|
||||
@@ -138,6 +138,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
||||
navDrawerViewModel.showExpiryWarning()
|
||||
.observe(this, this::showExpiryWarning);
|
||||
}
|
||||
|
||||
navDrawerViewModel.shouldAskForDozeWhitelisting().observe(this, ask -> {
|
||||
if (ask) showDozeDialog(getString(R.string.setup_doze_intro));
|
||||
});
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
|
||||
public class RemoteWipeActivatedActivity extends BriarActivity {
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
RemoteWipeActivatedViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
|
||||
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||
.get(RemoteWipeActivatedViewModel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
viewModel.getConfirmSent()
|
||||
.observeEvent(this, confirmed -> {
|
||||
if (confirmed) {
|
||||
signOut(true, true);
|
||||
}
|
||||
});
|
||||
|
||||
viewModel.sendConfirmMessages();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
|
||||
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
|
||||
public class RemoteWipeActivatedViewModel extends AndroidViewModel implements
|
||||
EventListener {
|
||||
private final RemoteWipeManager remoteWipeManager;
|
||||
private final DatabaseComponent db;
|
||||
private final MutableLiveEvent<Boolean> confirmSent =
|
||||
new MutableLiveEvent<>();
|
||||
private int numberOfConfirmMessages;
|
||||
private int messagesSent = 0;
|
||||
|
||||
@Inject
|
||||
RemoteWipeActivatedViewModel(
|
||||
@NonNull Application application,
|
||||
RemoteWipeManager remoteWipeManager,
|
||||
DatabaseComponent db, EventBus eventBus) {
|
||||
super(application);
|
||||
this.remoteWipeManager = remoteWipeManager;
|
||||
this.db = db;
|
||||
|
||||
eventBus.addListener(this);
|
||||
}
|
||||
|
||||
public void sendConfirmMessages() {
|
||||
try {
|
||||
numberOfConfirmMessages = db.transactionWithResult(false,
|
||||
remoteWipeManager::sendConfirmMessages);
|
||||
} catch (DbException | FormatException e) {
|
||||
// If there is a problem sending the messages, just wipe
|
||||
confirmSent.postEvent(true);
|
||||
}
|
||||
}
|
||||
|
||||
public LiveEvent<Boolean> getConfirmSent() {
|
||||
return confirmSent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
// As soon as we know the confirm messages are sent, we can wipe
|
||||
if (e instanceof MessagesSentEvent) {
|
||||
messagesSent++;
|
||||
if (messagesSent >= numberOfConfirmMessages) {
|
||||
confirmSent.postEvent(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.contact.ContactListAdapter;
|
||||
import org.briarproject.briar.android.contact.ContactListItem;
|
||||
import org.briarproject.briar.android.contact.OnContactClickListener;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
public class RemoteWipeDisplayFragment extends BaseFragment
|
||||
implements OnContactClickListener<ContactListItem> {
|
||||
|
||||
public static final String TAG = RemoteWipeDisplayFragment.class.getName();
|
||||
|
||||
private final ContactListAdapter adapter = new ContactListAdapter(this);
|
||||
private BriarRecyclerView list;
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
private RemoteWipeSetupViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||
.get(RemoteWipeSetupViewModel.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
|
||||
// change toolbar text (relevant when navigating back to this fragment)
|
||||
requireActivity().setTitle(R.string.assigned_wipers);
|
||||
|
||||
View contentView = inflater.inflate(R.layout.fragment_remote_wipe_display, container, false);
|
||||
|
||||
viewModel.getWiperContactIds();
|
||||
list = contentView.findViewById(R.id.wiperList);
|
||||
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
list.setAdapter(adapter);
|
||||
list.setEmptyText(R.string.no_contacts);
|
||||
|
||||
viewModel.getContactListItems().observe(getViewLifecycleOwner(),
|
||||
result -> result.onError(this::handleException)
|
||||
.onSuccess(adapter::submitList)
|
||||
);
|
||||
|
||||
Button changeWipersButton = contentView.findViewById(R.id.button_change);
|
||||
changeWipersButton.setOnClickListener(e -> viewModel.onModifyWipers());
|
||||
|
||||
Button disableRemoteWipeButton = contentView.findViewById(R.id.button_cancel);
|
||||
disableRemoteWipeButton.setOnClickListener(e -> viewModel.onDisableRemoteWipe());
|
||||
|
||||
viewModel.getState().observe(getViewLifecycleOwner(), this::onStateChanged);
|
||||
return contentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(View view, ContactListItem item) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
list.startPeriodicUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
list.stopPeriodicUpdate();
|
||||
}
|
||||
|
||||
private void onStateChanged(RemoteWipeSetupState state) {
|
||||
if (state.equals(RemoteWipeSetupState.DISABLED)) {
|
||||
showDisabledDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void showDisabledDialog() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(R.string.remote_wipe_disable_success);
|
||||
builder.setMessage(R.string.remote_wipe_disable_success_explain);
|
||||
builder.setPositiveButton(R.string.ok,
|
||||
(dialog, which) -> viewModel.onSuccessDismissed());
|
||||
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeViewModel;
|
||||
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeViewModel;
|
||||
import org.briarproject.briar.android.viewmodel.ViewModelKey;
|
||||
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.multibindings.IntoMap;
|
||||
|
||||
@Module
|
||||
public abstract class RemoteWipeModule {
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(RemoteWipeSetupViewModel.class)
|
||||
abstract ViewModel bindRemoteWipeSetupViewModel(
|
||||
RemoteWipeSetupViewModel remoteWipeSetupViewModel);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(ActivateRemoteWipeViewModel.class)
|
||||
abstract ViewModel bindActivateRemoteWipeViewModel(
|
||||
ActivateRemoteWipeViewModel activateRemoteWipeViewModel);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(RevokeRemoteWipeViewModel.class)
|
||||
abstract ViewModel bindRevokeRemoteWipeViewModel(
|
||||
RevokeRemoteWipeViewModel RevokeRemoteWipeViewModel);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(RemoteWipeActivatedViewModel.class)
|
||||
abstract ViewModel bindRemoteWipeActivatedViewModel(
|
||||
RemoteWipeActivatedViewModel remoteWipeActivatedViewModel);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.contactselection.ContactSelectorListener;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.socialbackup.ThresholdSelectorFragment;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
public class RemoteWipeSetupActivity extends BriarActivity implements
|
||||
BaseFragment.BaseFragmentListener, ContactSelectorListener {
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
RemoteWipeSetupViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
|
||||
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||
.get(RemoteWipeSetupViewModel.class);
|
||||
|
||||
viewModel.getState().observe(this, this::onStateChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_distributed_backup);
|
||||
if (viewModel.remoteWipeIsSetup()) {
|
||||
showInitialFragment(new RemoteWipeDisplayFragment());
|
||||
} else {
|
||||
showInitialFragment(new RemoteWipeSetupExplainerFragment());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contactsSelected(Collection<ContactId> contacts) {
|
||||
Toast.makeText(this,
|
||||
String.format("Selected %d contacts", contacts.size()),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
try {
|
||||
viewModel.setupRemoteWipe(contacts);
|
||||
} catch (Exception e) {
|
||||
// Display error fragment
|
||||
}
|
||||
}
|
||||
|
||||
private void onStateChanged(RemoteWipeSetupState state) {
|
||||
if (state.equals(RemoteWipeSetupState.FAILED)) {
|
||||
Toast.makeText(this,
|
||||
R.string.remote_wipe_setup_failed,
|
||||
Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
} else if (state.equals(RemoteWipeSetupState.SELECTING)) {
|
||||
showNextFragment(WiperSelectorFragment.newInstance());
|
||||
} else if (state.equals(RemoteWipeSetupState.FINISHED)) {
|
||||
finish();
|
||||
} else if (state.equals(RemoteWipeSetupState.MODIFY)) {
|
||||
showNextFragment(WiperSelectorFragment.newInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
public class RemoteWipeSetupExplainerFragment extends
|
||||
BaseFragment {
|
||||
|
||||
public static final String TAG =
|
||||
RemoteWipeSetupExplainerFragment.class.getName();
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
private RemoteWipeSetupViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||
.get(RemoteWipeSetupViewModel.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_remote_wipe_setup_explainer,
|
||||
container, false);
|
||||
|
||||
Button confirmButton = view.findViewById(R.id.button_confirm);
|
||||
confirmButton.setOnClickListener(e -> viewModel.onExplainerConfirmed());
|
||||
|
||||
Button cancelButton = view.findViewById(R.id.button_cancel);
|
||||
cancelButton.setOnClickListener(e -> viewModel.onExplainerCancelled());
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
public enum RemoteWipeSetupState {
|
||||
FAILED,
|
||||
SUCCESS,
|
||||
FINISHED,
|
||||
SELECTING,
|
||||
MODIFY,
|
||||
DISABLED
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.connection.ConnectionRegistry;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.android.contact.ContactsViewModel;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.identity.AuthorManager;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
@NotNullByDefault
|
||||
public class RemoteWipeSetupViewModel extends ContactsViewModel {
|
||||
private final RemoteWipeManager remoteWipeManager;
|
||||
private final DatabaseComponent db;
|
||||
private List<ContactId> wiperContactIds;
|
||||
private final MutableLiveData<RemoteWipeSetupState> state =
|
||||
new MutableLiveData<>();
|
||||
|
||||
private final ContactManager contactManager;
|
||||
private final AuthorManager authorManager;
|
||||
|
||||
@Inject
|
||||
RemoteWipeSetupViewModel(
|
||||
@NonNull Application application,
|
||||
RemoteWipeManager remoteWipeManager,
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager,
|
||||
AuthorManager authorManager,
|
||||
ConversationManager conversationManager,
|
||||
ConnectionRegistry connectionRegistry,
|
||||
EventBus eventBus,
|
||||
AndroidExecutor androidExecutor,
|
||||
ContactManager contactManager,
|
||||
DatabaseComponent db) {
|
||||
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
|
||||
contactManager, authorManager, conversationManager,
|
||||
connectionRegistry, eventBus);
|
||||
this.remoteWipeManager = remoteWipeManager;
|
||||
this.contactManager = contactManager;
|
||||
this.authorManager = authorManager;
|
||||
this.db = db;
|
||||
getWiperContactIds();
|
||||
loadContacts();
|
||||
}
|
||||
|
||||
public boolean remoteWipeIsSetup() {
|
||||
try {
|
||||
return db.transactionWithResult(true,
|
||||
txn -> {
|
||||
boolean isSetup = remoteWipeManager.remoteWipeIsSetup(txn);
|
||||
if (isSetup) wiperContactIds = remoteWipeManager.getWiperContactIds(txn);
|
||||
return isSetup;
|
||||
});
|
||||
} catch (DbException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public List<ContactId> getWiperContactIds() {
|
||||
try {
|
||||
wiperContactIds = db.transactionWithResult(true,
|
||||
remoteWipeManager::getWiperContactIds);
|
||||
} catch (DbException ignored) {
|
||||
return new ArrayList<ContactId>();
|
||||
}
|
||||
return wiperContactIds;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void onExplainerConfirmed() {
|
||||
state.postValue(RemoteWipeSetupState.SELECTING);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void onExplainerCancelled() {
|
||||
state.postValue(RemoteWipeSetupState.FINISHED);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void onSuccessDismissed() {
|
||||
state.postValue(RemoteWipeSetupState.FINISHED);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void onModifyWipers() {
|
||||
state.postValue(RemoteWipeSetupState.MODIFY);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void onDisableRemoteWipe() {
|
||||
try {
|
||||
db.transaction(false, remoteWipeManager::revokeAll);
|
||||
state.postValue(RemoteWipeSetupState.DISABLED);
|
||||
} catch (DbException | FormatException e) {
|
||||
e.printStackTrace();
|
||||
state.postValue(RemoteWipeSetupState.FINISHED);
|
||||
}
|
||||
}
|
||||
|
||||
public void setupRemoteWipe(Collection<ContactId> wipers)
|
||||
throws DbException, FormatException {
|
||||
db.transaction(false, txn -> {
|
||||
remoteWipeManager.setup(txn, (List<ContactId>) wipers);
|
||||
state.postValue(RemoteWipeSetupState.SUCCESS);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean displayContact(ContactId contactId) {
|
||||
// Check if contact is a wiper
|
||||
return wiperContactIds.contains(contactId);
|
||||
}
|
||||
|
||||
public MutableLiveData<RemoteWipeSetupState> getState() {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package org.briarproject.briar.android.remotewipe;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.contactselection.BaseContactSelectorAdapter;
|
||||
import org.briarproject.briar.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.briar.android.contactselection.ContactSelectorFragment;
|
||||
import org.briarproject.briar.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.briar.android.socialbackup.creation.CreateBackupController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class WiperSelectorFragment extends ContactSelectorFragment {
|
||||
|
||||
public static final String TAG = WiperSelectorFragment.class.getName();
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
private RemoteWipeSetupViewModel viewModel;
|
||||
|
||||
@Inject
|
||||
CreateBackupController controller;
|
||||
|
||||
public static WiperSelectorFragment newInstance() {
|
||||
Bundle args = new Bundle();
|
||||
|
||||
WiperSelectorFragment
|
||||
fragment = new WiperSelectorFragment();
|
||||
fragment.setArguments(args);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||
.get(RemoteWipeSetupViewModel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
selectedContacts.addAll(viewModel.getWiperContactIds());
|
||||
requireActivity().setTitle(R.string.title_select_wipers);
|
||||
|
||||
viewModel.getState().observe(this, this::onStateChanged);
|
||||
}
|
||||
|
||||
private void onStateChanged(RemoteWipeSetupState state) {
|
||||
if (state.equals(RemoteWipeSetupState.SUCCESS)) {
|
||||
showSuccessDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContactSelectorController<SelectableContactItem> getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged() {
|
||||
super.onSelectionChanged();
|
||||
if (menu == null) return;
|
||||
MenuItem item = menu.findItem(R.id.action_contacts_selected);
|
||||
if (item == null) return;
|
||||
|
||||
BaseContactSelectorAdapter a = adapter;
|
||||
selectedContacts = a.getSelectedContactIds();
|
||||
|
||||
int n = selectedContacts.size();
|
||||
int min = 2;
|
||||
boolean enough = n >= min;
|
||||
|
||||
item.setVisible(enough);
|
||||
if (n == 0) {
|
||||
Toast.makeText(getContext(), String.format(getString(R.string.select_at_least_n_contacts), min),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
} else if (n < min) {
|
||||
Toast.makeText(getContext(), String.format(getString(R.string.select_at_least_n_more_contacts), min - n),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void showSuccessDialog() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(R.string.remote_wipe_setup_success);
|
||||
builder.setPositiveButton(R.string.ok,
|
||||
(dialog, which) -> viewModel.onSuccessDismissed());
|
||||
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.briarproject.briar.android.remotewipe.activate;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
|
||||
|
||||
public class ActivateRemoteWipeActivity extends BriarActivity implements
|
||||
BaseFragment.BaseFragmentListener {
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
ActivateRemoteWipeViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
|
||||
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||
.get(ActivateRemoteWipeViewModel.class);
|
||||
|
||||
viewModel.getState().observe(this, this::onStateChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_distributed_backup);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
Intent intent = getIntent();
|
||||
int id = intent.getIntExtra(CONTACT_ID, -1);
|
||||
if (id == -1) throw new IllegalStateException("No ContactId");
|
||||
ContactId contactId = new ContactId(id);
|
||||
viewModel.setContactId(contactId);
|
||||
showInitialFragment(new ActivateRemoteWipeExplainerFragment());
|
||||
}
|
||||
}
|
||||
|
||||
private void onStateChanged(ActivateRemoteWipeState state) {
|
||||
switch(state) {
|
||||
case FAILED:
|
||||
Toast.makeText(this,
|
||||
R.string.remote_wipe_activate_failure,
|
||||
Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case SUCCESS:
|
||||
// Handled by the popup dialog on the explainer
|
||||
break;
|
||||
default: // FINISHED or CANCELLED
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.briarproject.briar.android.remotewipe.activate;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
public class ActivateRemoteWipeExplainerFragment extends BaseFragment {
|
||||
|
||||
public static final String TAG =
|
||||
ActivateRemoteWipeExplainerFragment.class.getName();
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
private ActivateRemoteWipeViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||
.get(ActivateRemoteWipeViewModel.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_activate_remote_wipe_explainer,
|
||||
container, false);
|
||||
|
||||
TextView titleText = view.findViewById(R.id.textView);
|
||||
titleText.setText(String.format(getString(R.string.remote_wipe_activate_explain_short), viewModel.getContactName()));
|
||||
|
||||
TextView explainText = view.findViewById(R.id.textViewExplain);
|
||||
explainText.setText(String.format(getString(R.string.remote_wipe_activate_explain_long), viewModel.getContactName()));
|
||||
|
||||
Button cancelButton = view.findViewById(R.id.button_cancel);
|
||||
cancelButton.setOnClickListener(e -> viewModel.onCancelClicked());
|
||||
|
||||
Button confirmButton = view.findViewById(R.id.button_confirm);
|
||||
confirmButton.setOnClickListener(e -> viewModel.onConfirmClicked());
|
||||
|
||||
viewModel.getState().observe(getViewLifecycleOwner(), this::onStateChanged);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void onStateChanged(ActivateRemoteWipeState state) {
|
||||
if (state == ActivateRemoteWipeState.SUCCESS) {
|
||||
showSuccessDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
private void showSuccessDialog() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(R.string.remote_wipe_activate_success);
|
||||
builder.setPositiveButton(R.string.ok,
|
||||
(dialog, which) -> viewModel.onSuccessDismissed());
|
||||
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.briarproject.briar.android.remotewipe.activate;
|
||||
|
||||
public enum ActivateRemoteWipeState {
|
||||
FAILED,
|
||||
SUCCESS,
|
||||
FINISHED,
|
||||
CANCELLED
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.briarproject.briar.android.remotewipe.activate;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.briar.android.remotewipe.RemoteWipeSetupState;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
|
||||
import java.text.Normalizer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
public class ActivateRemoteWipeViewModel extends AndroidViewModel {
|
||||
|
||||
private final RemoteWipeManager remoteWipeManager;
|
||||
private final ContactManager contactManager;
|
||||
private final DatabaseComponent db;
|
||||
private final MutableLiveData<ActivateRemoteWipeState> state = new MutableLiveData<>();
|
||||
private ContactId contactId;
|
||||
private String contactName;
|
||||
|
||||
@Inject
|
||||
public ActivateRemoteWipeViewModel(
|
||||
@NonNull Application application,
|
||||
RemoteWipeManager remoteWipeManager,
|
||||
ContactManager contactManager,
|
||||
DatabaseComponent db) {
|
||||
super(application);
|
||||
this.remoteWipeManager = remoteWipeManager;
|
||||
this.contactManager = contactManager;
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
private void activateWipe() {
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
try {
|
||||
remoteWipeManager.wipe(txn, db.getContact(txn, contactId));
|
||||
} catch (DbException e) {
|
||||
state.postValue(ActivateRemoteWipeState.FAILED);
|
||||
} catch (FormatException e) {
|
||||
state.postValue(ActivateRemoteWipeState.FAILED);
|
||||
}
|
||||
state.postValue(ActivateRemoteWipeState.SUCCESS);
|
||||
});
|
||||
} catch (DbException e) {
|
||||
state.postValue(ActivateRemoteWipeState.FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
public MutableLiveData<ActivateRemoteWipeState> getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setContactId(ContactId c) {
|
||||
contactId = c;
|
||||
|
||||
try {
|
||||
contactName = UiUtils.getContactDisplayName(contactManager.getContact(c));
|
||||
} catch (DbException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public String getContactName() {
|
||||
return contactName;
|
||||
}
|
||||
|
||||
public void onCancelClicked() {
|
||||
state.postValue(ActivateRemoteWipeState.CANCELLED);
|
||||
}
|
||||
|
||||
public void onSuccessDismissed() {
|
||||
state.postValue(ActivateRemoteWipeState.FINISHED);
|
||||
}
|
||||
|
||||
public void onConfirmClicked() {
|
||||
activateWipe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.briarproject.briar.android.remotewipe.revoke;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
|
||||
|
||||
public class RevokeRemoteWipeActivity extends BriarActivity implements
|
||||
BaseFragment.BaseFragmentListener {
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
RevokeRemoteWipeViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
|
||||
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||
.get(RevokeRemoteWipeViewModel.class);
|
||||
|
||||
viewModel.getState().observe(this, this::onStateChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_distributed_backup);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
Intent intent = getIntent();
|
||||
int id = intent.getIntExtra(CONTACT_ID, -1);
|
||||
if (id == -1) throw new IllegalStateException("No ContactId");
|
||||
ContactId contactId = new ContactId(id);
|
||||
viewModel.revokeRemoteWipeStatus(contactId);
|
||||
// showInitialFragment(new ActivateRemoteWipeExplainerFragment());
|
||||
}
|
||||
}
|
||||
|
||||
private void onStateChanged(RevokeRemoteWipeState state) {
|
||||
switch(state) {
|
||||
case FAILED:
|
||||
// TODO change text
|
||||
Toast.makeText(this,
|
||||
R.string.remote_wipe_activate_failure,
|
||||
Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case SUCCESS:
|
||||
showNextFragment(new RevokeRemoteWipeSuccessFragment());
|
||||
break;
|
||||
default: // FINISHED or CANCELLED
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.briarproject.briar.android.remotewipe.revoke;
|
||||
|
||||
public enum RevokeRemoteWipeState {
|
||||
FAILED,
|
||||
SUCCESS,
|
||||
FINISHED
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.briarproject.briar.android.remotewipe.revoke;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
public class RevokeRemoteWipeSuccessFragment extends BaseFragment {
|
||||
|
||||
public static final String TAG =
|
||||
RevokeRemoteWipeSuccessFragment.class.getName();
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
private RevokeRemoteWipeViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||
.get(RevokeRemoteWipeViewModel.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_revoke_remote_wipe_success,
|
||||
container, false);
|
||||
|
||||
Button button = view.findViewById(R.id.button);
|
||||
button.setOnClickListener(e -> viewModel.onSuccessDismissed());
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.briarproject.briar.android.remotewipe.revoke;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeState;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
public class RevokeRemoteWipeViewModel extends AndroidViewModel {
|
||||
|
||||
private final RemoteWipeManager remoteWipeManager;
|
||||
private final DatabaseComponent db;
|
||||
private final MutableLiveData<RevokeRemoteWipeState> state = new MutableLiveData<>();
|
||||
private ContactId contactId;
|
||||
|
||||
@Inject
|
||||
public RevokeRemoteWipeViewModel(
|
||||
@NonNull Application application,
|
||||
RemoteWipeManager remoteWipeManager,
|
||||
DatabaseComponent db) {
|
||||
super(application);
|
||||
this.remoteWipeManager = remoteWipeManager;
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
public MutableLiveData<RevokeRemoteWipeState> getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void revokeRemoteWipeStatus(ContactId c) {
|
||||
contactId = c;
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
remoteWipeManager.revoke(txn, contactId);
|
||||
});
|
||||
} catch (DbException e) {
|
||||
state.postValue(RevokeRemoteWipeState.FAILED);
|
||||
} catch (FormatException e) {
|
||||
state.postValue(RevokeRemoteWipeState.FAILED);
|
||||
}
|
||||
state.postValue(RevokeRemoteWipeState.SUCCESS);
|
||||
}
|
||||
|
||||
public void onCancelClicked() {
|
||||
// state.postValue(ActivateRemoteWipeState.CANCELLED);
|
||||
}
|
||||
|
||||
public void onSuccessDismissed() {
|
||||
state.postValue(RevokeRemoteWipeState.FINISHED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.briarproject.briar.android.socialbackup;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.contact.BaseContactListAdapter;
|
||||
import org.briarproject.briar.android.contact.ContactItem;
|
||||
import org.briarproject.briar.android.contact.ContactItemViewHolder;
|
||||
|
||||
public class CustodianStatusAdapter extends BaseContactListAdapter<ContactItem, ContactItemViewHolder<ContactItem>> {
|
||||
|
||||
CustodianStatusAdapter(Context context) {
|
||||
super(context, ContactItem.class, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactItemViewHolder<ContactItem> onCreateViewHolder(
|
||||
ViewGroup viewGroup, int i) {
|
||||
View v = LayoutInflater.from(viewGroup.getContext()).inflate(
|
||||
R.layout.list_item_contact_small, viewGroup, false);
|
||||
return new ContactItemViewHolder<>(v);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="409.2dp"
|
||||
android:height="161.7dp"
|
||||
android:viewportHeight="161.7"
|
||||
android:viewportWidth="409.2">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M369.8,157.4l-4.3,-4.3l-7.1,-2.4c-3.9,-1.3 -8.7,-3 -10.7,-3.7l-3.7,-1.3l3.5,-0.2c8.2,-0.4 13,-4 14.3,-10.9c0.8,-4.1 1.1,-17.3 0.8,-33c-0.2,-8.1 -0.2,-15.4 0,-16.3c0.1,-0.9 0.5,-2.4 0.9,-3.4c1.2,-3.5 0.3,-11.9 -1.9,-17.6c-0.3,-0.9 -1.9,-4.2 -3.5,-7.4c-4.2,-8.2 -4.5,-8.9 -4.9,-10.5c-0.5,-1.8 -0.2,-5.4 0.5,-6.8c0.7,-1.3 2.2,-2.9 3.2,-3.5c1.3,-0.7 2.6,0.1 4.7,2.9c3.4,4.5 14,19.4 15.7,22.2c3.7,6 6,11.2 8,18.8c0.7,2.5 1.9,7 2.7,10.1c0.8,3.1 2.7,10.2 4.1,15.8l2.6,10.2l4.6,5.2c2.6,2.9 5.8,6.5 7.2,8c1.4,1.6 2.5,3 2.5,3.2c0,0.3 -34.5,29.3 -34.9,29.3C374.2,161.7 372.2,159.7 369.8,157.4zM275.9,141c-1.3,-0.6 -2.2,-1.4 -2.9,-2.3c-2.1,-2.7 -2,2.4 -1.9,-68.5l0.1,-64l0.7,-1.2c1,-1.9 2,-2.9 3.7,-3.9l1.6,-0.9l37.8,-0.1c42.5,-0.1 39.4,-0.2 42.1,2.2c0.9,0.8 1.8,2 2.2,2.9c0.7,1.6 0.7,1.6 0.8,14.2l0.1,12.6l-1.8,-0.1c-1.4,-0.1 -2.1,0 -3.2,0.5c-2,1 -3.9,2.9 -5.1,5.1l-1,2l0,-12.8l0,-12.8h-33.6h-33.6v51.3v51.3h33.6h33.6l0.1,-34.4c0.1,-33 0.1,-34.4 0.6,-32.9c0.3,0.8 1.8,4 3.4,7c5.5,10.6 5.4,9.9 5.4,47.2c0,27.6 -0.1,30 -1.7,33.1c-1.1,2.2 -2.7,3.7 -5.1,4.7l-1.7,0.7L314,141.8l-36.2,0.1L275.9,141L275.9,141zM318.3,135.9c2.9,-1.3 4.5,-3.7 4.4,-6.6c0,-4.1 -3.1,-7.2 -7.1,-7.2c-2.1,0 -3.6,0.6 -5.2,2.2c-2.2,2.2 -2.8,5.4 -1.3,8.3c0.7,1.4 2.5,3 4,3.5C314.6,136.6 317,136.6 318.3,135.9z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M39.4,157.4l4.3,-4.3l7.1,-2.4c3.9,-1.3 8.7,-3 10.7,-3.7l3.7,-1.3l-3.5,-0.2c-8.2,-0.4 -13,-4 -14.3,-10.9c-0.8,-4.1 -1.1,-17.3 -0.8,-33c0.2,-8.1 0.2,-15.4 0,-16.3c-0.1,-0.9 -0.5,-2.4 -0.9,-3.4c-1.2,-3.5 -0.3,-11.9 1.9,-17.6c0.3,-0.9 1.9,-4.2 3.5,-7.4c4.2,-8.2 4.5,-8.9 4.9,-10.5c0.5,-1.8 0.2,-5.4 -0.5,-6.8c-0.7,-1.3 -2.2,-2.9 -3.2,-3.5c-1.3,-0.7 -2.6,0.1 -4.7,2.9c-3.4,4.5 -14,19.4 -15.7,22.2c-3.7,6 -6,11.2 -8,18.8c-0.7,2.5 -1.9,7 -2.7,10.1c-0.8,3.1 -2.7,10.2 -4.1,15.8l-2.6,10.2l-4.6,5.2c-2.6,2.9 -5.8,6.5 -7.2,8s-2.5,3 -2.5,3.2c0,0.3 34.5,29.3 34.9,29.3C35,161.7 37.1,159.7 39.4,157.4zM133.3,141c1.3,-0.6 2.2,-1.4 2.9,-2.3c2.1,-2.7 2,2.4 1.9,-68.5l-0.1,-64l-0.7,-1.2c-1,-1.9 -2,-2.9 -3.7,-3.9l-1.6,-0.9l-37.8,-0.1c-42.5,-0.1 -39.4,-0.2 -42.1,2.2c-0.9,0.8 -1.8,2 -2.2,2.9c-0.7,1.6 -0.7,1.6 -0.8,14.2L49,32l1.8,-0.1c1.4,-0.1 2.1,0 3.2,0.5c2,1 3.9,2.9 5.1,5.1l1,2l0,-12.8l0,-12.8h33.6h33.6v51.3v51.3L93.8,116.5L60.2,116.5l-0.1,-34.4c-0.1,-33 -0.1,-34.4 -0.6,-32.9c-0.3,0.8 -1.8,4 -3.4,7c-5.5,10.6 -5.4,9.9 -5.4,47.2c0,27.6 0.1,30 1.7,33.1c1.1,2.2 2.7,3.7 5.1,4.7l1.7,0.7l36.2,0.1l36.2,0.1L133.3,141L133.3,141zM90.9,135.9c-2.9,-1.3 -4.5,-3.7 -4.4,-6.6c0,-4.1 3.1,-7.2 7.1,-7.2c2.1,0 3.6,0.6 5.2,2.2c2.2,2.2 2.8,5.4 1.3,8.3c-0.7,1.4 -2.5,3 -4,3.5C94.6,136.6 92.3,136.6 90.9,135.9z"/>
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M 207.61295,88.782357 h -6.42588 v -12.85177 h 6.42588 m 0,25.703533 h -6.42588 v -6.425883 h 6.42588 m -38.5553,16.064713 h 70.68472 L 204.40001,50.227047 Z"
|
||||
android:strokeWidth="3.21294165"/>
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M90.58,50.42A8.19,8.01 0 0,1 98.77,42.42A8.19,8.01 0 0,1 106.96,50.42C106.96,51.46 107.79,52.27 108.85,52.27C109.91,52.27 110.74,51.46 110.74,50.42V48.58H113.99V50.42A5.67,5.54 0 0,1 108.85,55.97A5.67,5.54 0 0,1 103.18,50.42A4.41,4.31 0 0,0 98.77,46.11A4.41,4.31 0 0,0 94.36,50.42H97.35V53.6C104.79,55.71 110.11,62.31 110.11,70.14A17.64,17.25 0 0,1 92.47,87.38A17.64,17.25 0 0,1 74.83,70.14C74.83,62.31 80.15,55.71 87.43,53.6V50.42H90.58M117.67,50.42H122.6V52.89H117.67V50.42M110.11,45.5V40.57H112.57V45.5H110.11M114.92,46.42L118.5,42.92L120.29,44.68L116.71,48.18L114.92,46.42Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_medium"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:paddingBottom="@dimen/margin_medium"
|
||||
tools:ignore="VectorDrawableCompat">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/remote_wipe_activate_explain_short"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_editor_absoluteX="16dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView"
|
||||
app:srcCompat="@drawable/remote_wipe_activate_explain" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewExplain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/remote_wipe_activate_explain_long"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView"
|
||||
tools:layout_editor_absoluteX="16dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_confirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/remote_wipe_activate_button_confirm"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewExplain" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_cancel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/remote_wipe_activate_button_cancel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button_confirm" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,130 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_medium"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:paddingBottom="@dimen/margin_medium">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Backup creation" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonSelectThreshold"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Select Threshold" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonShardsSent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Shards sent" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Setup" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonWelcome"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Welcome" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recovery from secrect owner's point of view" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonOwnerRecoveryExplainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Explainer" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonOwnerRecoveryReceivedShard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Shard received" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonOwnerRecoveryMain1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Main (0 shards)" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonOwnerRecoveryMain2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Main (1 shard)" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonOwnerRecoveryMain3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Recovering account…" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonOwnerRecoveryAccountRecovered"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Account recovered" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonOwnerRecoveryErrorExplainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Error" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recovery from custodian's point of view" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonCustodianRecoveryExplainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Explainer" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonCustodianRecoveryErrorExplainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Error" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/buttonCustodianRecoveryDone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/ic_security"
|
||||
android:text="Done" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_medium"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:paddingBottom="@dimen/margin_medium"
|
||||
tools:ignore="VectorDrawableCompat">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_view_explain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/remote_wipe_display_explain"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_editor_absoluteX="16dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_cancel"
|
||||
style="@style/BriarButtonFlat.Negative.Tiny"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/remote_wipe_disable"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button_change"
|
||||
app:layout_constraintEnd_toStartOf="@id/button_change"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_view_explain" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_change"
|
||||
style="@style/BriarButtonFlat.Positive.Tiny"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/remote_wipe_modify_contacts"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/button_cancel"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_view_explain" />
|
||||
|
||||
<org.briarproject.briar.android.view.BriarRecyclerView
|
||||
android:id="@+id/wiperList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_change"
|
||||
app:scrollToEnd="false" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_medium"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:paddingBottom="@dimen/margin_medium"
|
||||
tools:ignore="VectorDrawableCompat">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/remote_wipe_setup_explain_title"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_editor_absoluteX="16dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView"
|
||||
app:srcCompat="@drawable/remote_wipe_activate_explain" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewExplain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/remote_wipe_setup_explain_long"
|
||||
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView"
|
||||
tools:layout_editor_absoluteX="16dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_confirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/title_select_wipers"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textViewExplain" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_cancel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:text="@string/remote_wipe_activate_button_cancel"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/button_confirm" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="@dimen/margin_large"
|
||||
android:paddingTop="@dimen/margin_medium"
|
||||
android:paddingRight="@dimen/margin_large"
|
||||
android:paddingBottom="@dimen/margin_medium">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="@string/button_confirm"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/remote_wipe_revoke_success"
|
||||
android:textSize="30sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView2" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginLeft="32dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginRight="32dp"
|
||||
app:layout_constraintDimensionRatio="1:1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_baseline_done_outline_24" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
@@ -33,4 +33,18 @@
|
||||
android:title="@string/help_recover_account"
|
||||
android:enabled="false"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_remote_wipe"
|
||||
android:icon="@drawable/action_delete_white"
|
||||
android:title="@string/activate_remote_wipe"
|
||||
android:enabled="false"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_revoke_remote_wipe"
|
||||
android:icon="@drawable/action_delete_white"
|
||||
android:title="@string/revoke_remote_wipe"
|
||||
android:enabled="false"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
||||
524
briar-android/src/main/res/values-in/strings.xml
Normal file
524
briar-android/src/main/res/values-in/strings.xml
Normal file
@@ -0,0 +1,524 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
<!-- Setup -->
|
||||
<string name="setup_title">Selamat Datang di Briar</string>
|
||||
<string name="setup_name_explanation">Nama panggilan Anda akan terlihat pada setiap materi yang Anda unggah. Anda tidak bisa mengubah setelah membuatnya.</string>
|
||||
<string name="setup_next">Selanjutnya</string>
|
||||
<string name="setup_password_intro">Pilih Kata Sandi</string>
|
||||
<string name="setup_password_explanation">Akun Briar Anda tersimpan dalam perangkat terenkripsi, bukan di komputasi awan. Jika lupa kata sandi atau menghapus aplikasi Briar, Anda hanya bisa mengembalikan akun jika sudah membuat pencadangan sosial.\n\nBuatlah kata sandi panjang yang susah ditebak, misalnya empat kata acak atau sepuluh huruf, angka, dan simbol acak.</string>
|
||||
<string name="setup_doze_title">Sambungan Belakang</string>
|
||||
<string name="setup_doze_intro">Untuk menerima pesan, Briar perlu tetap terkoneksi dengan sambungan belakang.</string>
|
||||
<string name="setup_doze_explanation">Untuk menerima pesan, Briar perlu tetap terkoneksi dengan sambungan belakang. Silakan nonaktifkan pengoptimalan baterai agar Briar tetap bisa terkoneksi.</string>
|
||||
<string name="setup_doze_button">Izinkan Koneksi</string>
|
||||
<string name="choose_nickname">Pilih nama panggilan Anda</string>
|
||||
<string name="choose_password">Pilih kata sandi Anda</string>
|
||||
<string name="confirm_password">Konfirmasi kata sandi Anda</string>
|
||||
<string name="name_too_long">Nama terlalu panjang</string>
|
||||
<string name="password_too_weak">Kata sandi terlalu lemah</string>
|
||||
<string name="passwords_do_not_match">Kata sandi tidak cocok</string>
|
||||
<string name="create_account_button">Buat Akun</string>
|
||||
<string name="more_info">Informasi Selanjutnya</string>
|
||||
<string name="don_t_ask_again">Jangan tanya lagi</string>
|
||||
|
||||
<string name="setup_huawei_text">Silakan ketuk tombol di bawah dan pastikan Briar terlindungi di layar \"Aplikasi Terlindungi\".</string>
|
||||
<string name="setup_huawei_button">Lindungi Briar</string>
|
||||
<string name="setup_huawei_help">Jika tidak dimasukkan dalam daftar aplikasi terlindungi, Briar tidak akan bisa berfungsi di sambungan belakang.</string>
|
||||
<string name="warning_dozed">%tidak bisa berfungsi di sambungan belakang</string>
|
||||
|
||||
<!-- Login -->
|
||||
<string name="enter_password">Kata Sandi</string>
|
||||
<string name="try_again">Kata sandi salah, coba lagi</string>
|
||||
<string name="dialog_title_cannot_check_password">Tidak Bisa Memeriksa Kata Sandi</string>
|
||||
<string name="dialog_message_cannot_check_password">Briar tidak bisa memeriksa kata sandi Anda. Silakan booting ulang perangkat untuk memecahkan masalah Anda.</string>
|
||||
<string name="sign_in_button">Masuk</string>
|
||||
<string name="forgotten_password">Saya lupa kata sandi</string>
|
||||
<string name="dialog_title_lost_password">Kata sandi hilang</string>
|
||||
<string name="dialog_message_lost_password">Akun Briar Anda tersimpan dalam perangkat terenkripsi, bukan di komputasi awan, jadi kami tidak bisa membuat ulang kata sandi Anda. Jika Anda memiliki cadangan sosial, Anda bisa menghapus akun Anda dan membuat kata sandi baru ketika Anda mengembalikan. Apakah Anda mau menghapus akun dan memulai lagi?\n\nPerhatian: Identitas, kontak, dan pesan Anda akan sepenuhnya hilang jika Anda tidak punya cadangan.</string>
|
||||
<string name="startup_failed_notification_title">Briar tidak bisa memulai</string>
|
||||
<string name="startup_failed_notification_text">Ketuk untuk informasi selanjutnya.</string>
|
||||
<string name="startup_failed_activity_title">Briar Gagal Memulai</string>
|
||||
<string name="startup_failed_db_error">Karena beberapa alasan, pangkalan data Briar Anda rusak dan tidak bisa diperbaiki. Akun, data, dan semua kontak Anda hilang. Sayangnya, Anda perlu memasang ulang Briar atau membuat akun baru dengan memilih \'Saya lupa kata sandi\' pada bagian kata sandi.</string>
|
||||
<string name="startup_failed_data_too_old_error">Akun Anda dibuat menggunakan versi lama aplikasi ini dan tidak bisa dibuka dengan versi sekarang. Anda harus memasang ulang versi lama atau membuat akun baru dengan memilih \'Saya lupa kata sandi\' pada bagian kata sandi.</string>
|
||||
<string name="startup_failed_data_too_new_error">Versi aplikasi ini sudah usang. Silakan naikkan ke versi terbaru dan coba lagi.</string>
|
||||
<string name="startup_failed_service_error">Briar tidak bisa memulai pengaya yang diperlukan. Memasang ulang Briar biasanya memecahkan masalah. Namun, harap diperhatikan bahwa Anda akan kehilangan semua data karena Briar tidak menggunakan peladen terpusat untuk menyimpan data Anda.</string>
|
||||
<plurals name="expiry_warning">
|
||||
<item quantity="other">Ini adalah Briar versi percobaan. Akun Anda akan kedaluwarsa pada % hari dan tidak bisa diperbarui.</item>
|
||||
</plurals>
|
||||
|
||||
<string name="expiry_date_reached">Perangkat lunak ini sudah kedaluwarsa.\nTerima kasih sudah mencoba!</string>
|
||||
<string name="download_briar">Untuk lanjut menggunakan Briar, silakan unduh versi terbaru.</string>
|
||||
<string name="create_new_account">Anda akan perlu membuat akun baru, tetapi bisa menggunakan nama sama.</string>
|
||||
<string name="download_briar_button">Unduh Keluaran Terbaru</string>
|
||||
<string name="startup_open_database">Mendekrip Pangkalan Data…</string>
|
||||
<string name="startup_migrate_database">Meningkatkan Pangkalan Data…</string>
|
||||
<string name="startup_compact_database">Meringkas Pangkalan Data…</string>
|
||||
|
||||
<!-- Navigation Drawer -->
|
||||
<string name="nav_drawer_open_description">Buka penarik navigasi</string>
|
||||
<string name="nav_drawer_close_description">Tutup penarik navigasi</string>
|
||||
<string name="contact_list_button">Kontak</string>
|
||||
<string name="groups_button">Group Pribadi</string>
|
||||
<string name="forums_button">Forum</string>
|
||||
<string name="blogs_button">Blog</string>
|
||||
<!-- This is part of the main menu. The app will be locked when this is tapped. -->
|
||||
<string name="lock_button">Kunci Aplikasi</string>
|
||||
<string name="settings_button">Pengaturan</string>
|
||||
<string name="sign_out_button">Keluar</string>
|
||||
<string name="transports_onboarding_text">Ketuk di sini untuk mengontrol bagaimana Briar tersambung dengan kontak Anda.</string>
|
||||
|
||||
<!-- Transports: Tor -->
|
||||
<string name="transport_tor">Internet</string>
|
||||
<string name="tor_device_status_online_wifi">Ponsel Anda punya akses Internet lewat Wi-Fi</string>
|
||||
<string name="tor_device_status_online_mobile">Ponsel Anda punya akses Internet lewat paket data</string>
|
||||
<string name="tor_device_status_offline">Ponsel Anda tidak punya akses Internet</string>
|
||||
<string name="tor_plugin_status_enabling">Briar menyambung ke Internet</string>
|
||||
<string name="tor_plugin_status_active">Briar tersambung Internet</string>
|
||||
<string name="tor_plugin_status_inactive">Briar tidak bisa menyambung ke Internet</string>
|
||||
<string name="tor_plugin_status_disabled">Briar dikonfigurasi tidak menggunakan Internet</string>
|
||||
<string name="tor_plugin_status_disabled_mobile_data">Briar dikonfigurasi tidak menggunakan paket data</string>
|
||||
<string name="tor_plugin_status_disabled_battery">Briar dikonfigurasi tidak menggunakan Internet ketika menggunakan baterai</string>
|
||||
<string name="tor_plugin_status_disabled_country_blocked">Briar dikonfigurasi tidak menggunakan Internet di negara ini</string>
|
||||
|
||||
<!-- Transports: Wi-Fi -->
|
||||
<string name="transport_lan">Wi-Fi</string>
|
||||
<string name="transport_lan_long">Jaringan Wi-Fi Sama</string>
|
||||
<string name="lan_device_status_on">Ponsel Anda tersambung Wi-Fi</string>
|
||||
<string name="lan_device_status_off">Ponsel Anda tidak tersambung Wi-Fi</string>
|
||||
<string name="lan_plugin_status_enabling">Briar menyambung ke Wi-Fi</string>
|
||||
<string name="lan_plugin_status_active">Briar tersambung Wi-Fi</string>
|
||||
<string name="lan_plugin_status_inactive">Briar tidak tersambung Wi-Fi</string>
|
||||
<string name="lan_plugin_status_disabled">Briar dikonfigutasi tidak menggunakan Wi-Fi</string>
|
||||
|
||||
<!-- Transports: Bluetooth -->
|
||||
<string name="transport_bt">Bluetooth</string>
|
||||
<string name="bt_device_status_on">Bluetooth ponsel Anda hidup</string>
|
||||
<string name="bt_device_status_off">Bluetooth ponsel Anda mati</string>
|
||||
<string name="bt_plugin_status_enabling">Briar menyambung ke Bluetooth</string>
|
||||
<string name="bt_plugin_status_active">Briar tersambung Bluetooth</string>
|
||||
<string name="bt_plugin_status_inactive">Briar tidak bisa tersambung Bluetooth</string>
|
||||
<string name="bt_plugin_status_disabled">Briar dikonfigurasi tidak menggunakan Bluetooth</string>
|
||||
|
||||
<!-- Notifications -->
|
||||
<string name="reminder_notification_title">Keluar Briar</string>
|
||||
<string name="reminder_notification_text">Ketuk untuk masuk kembali.</string>
|
||||
<string name="reminder_notification_channel_title">Pengingat Masuk Briar</string>
|
||||
<string name="reminder_notification_dismiss">Singkirkan</string>
|
||||
<string name="ongoing_notification_title">Masuk Briar</string>
|
||||
<string name="ongoing_notification_text">Sentuh untuk membuka Briar.</string>
|
||||
<plurals name="private_message_notification_text">
|
||||
<item quantity="other">%d Pesan-pesan pribadi baru.</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Misc -->
|
||||
<string name="now">sekarang</string>
|
||||
<string name="show">Tunjukkan</string>
|
||||
<string name="hide">Sembunyikan</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="cancel">Batal</string>
|
||||
<string name="got_it">Paham</string>
|
||||
<string name="delete">Hapus</string>
|
||||
<string name="accept">Terima</string>
|
||||
<string name="decline">Tolak</string>
|
||||
<string name="online">Daring</string>
|
||||
<string name="offline">Luring</string>
|
||||
<string name="send">Kirim</string>
|
||||
<string name="allow">Izinkan</string>
|
||||
<string name="open">Buka</string>
|
||||
<string name="change">Ubah</string>
|
||||
<string name="no_data">Tidak Ada Data</string>
|
||||
<string name="ellipsis">…</string>
|
||||
<string name="text_too_long">Teks yang dimasukkan terlalu panjang</string>
|
||||
<string name="show_onboarding">Perlihatkan Dialog Bantuan</string>
|
||||
<string name="fix">Bereskan</string>
|
||||
<string name="help">Bantu</string>
|
||||
<string name="sorry">Maaf</string>
|
||||
<string name="error_start_activity">Tidak tersedia di sistem Anda</string>
|
||||
<string name="status_heading">Status:</string>
|
||||
|
||||
<!-- Contacts and Private Conversations-->
|
||||
<string name="no_contacts">Tidak ada kontak untuk diperlihatkan</string>
|
||||
<string name="no_contacts_action">Ketuk ikon + untuk menambah kontak</string>
|
||||
<string name="date_no_private_messages">Tidak ada pesan.</string>
|
||||
<string name="no_private_messages">Tidak ada pesan untuk diperlihatkan</string>
|
||||
<string name="message_hint">Tulisa pesan</string>
|
||||
<string name="image_caption_hint">Tambahkan keterangan (pilihan)</string>
|
||||
<string name="image_attach">Lampirkan gambar</string>
|
||||
<string name="image_attach_error">Tidak bisa melampirkan gambar</string>
|
||||
<string name="image_attach_error_too_big">Gambar terlalu besar. Batasnya %d MB.</string>
|
||||
<string name="image_attach_error_invalid_mime_type">Format gambar tidak mendukung: %s</string>
|
||||
<string name="set_contact_alias">Ubah nama kontak</string>
|
||||
<string name="set_contact_alias_hint">Nama kontak</string>
|
||||
<string name="delete_all_messages">Hapus semua pesan</string>
|
||||
<string name="dialog_title_delete_all_messages">Konfirmasi Penghapusan Pesan</string>
|
||||
<string name="dialog_message_delete_all_messages">Anda yakin untuk menghapus semua pesan?</string>
|
||||
<string name="dialog_title_not_all_messages_deleted">Tidak bisa menghapus semua pesan</string>
|
||||
<string name="delete_contact">Hapus kontak</string>
|
||||
<string name="dialog_title_delete_contact">Konfirmasi Penghapusan Kontak</string>
|
||||
<string name="dialog_message_delete_contact">Apakah Anda yakin akan menghapus kontak ini dan semua pesannya?</string>
|
||||
<string name="contact_deleted_toast">Kontak Dihapus</string>
|
||||
<!-- This is shown in the action bar when opening an image in fullscreen that the user sent -->
|
||||
<string name="you">Anda</string>
|
||||
<string name="save_image">Simpan gambar</string>
|
||||
<string name="dialog_title_save_image">Simpan gambar?</string>
|
||||
<string name="save_image_success">Gambar tersimpan</string>
|
||||
<string name="save_image_error">Tidak bisa menghapus gambar</string>
|
||||
<string name="dialog_title_no_image_support">Gambar tidak tersedia</string>
|
||||
|
||||
<!-- Adding Contacts -->
|
||||
|
||||
<string name="add_contact_title">Tambah Kontak Sekitar</string>
|
||||
<string name="face_to_face">Anda harus bertemu dengan orang yang ingin Anda tambahkan sebagai kontak.\n\nHal ini ubtuk mencegah orang lain membuat akun tiruan atau membaca pesan Anda di kemudian hari.</string>
|
||||
<string name="continue_button">Lanjut</string>
|
||||
<string name="try_again_button">Coba Lagi</string>
|
||||
<string name="waiting_for_contact_to_scan">Menunggu kontak untuk memindai dan menyambung\u2026</string>
|
||||
<string name="exchanging_contact_details">Bertukar detail kontak\u2026</string>
|
||||
<string name="contact_added_toast">Kontak ditambahkan: %s</string>
|
||||
<string name="contact_already_exists">%s kontak sudah ada</string>
|
||||
<string name="qr_code_invalid">Kode batang salah</string>
|
||||
<string name="qr_code_too_old">Kode batang yang Anda pindai adalah versi lebih lama %s.\n\nSilakan minta kontak Anda untuk menaikkan ke versi terbaru dan coba lagi.</string>
|
||||
<string name="qr_code_too_new">Kode batang yang Anda pindai adalah versi lebih mutakhir %s.\n\nSilakan naikkan ke versi terbaru dan coba lagi.</string>
|
||||
<string name="camera_error">Kamera Rusak</string>
|
||||
<string name="connecting_to_device">Menyambung ke perangkat\u2026</string>
|
||||
<string name="authenticating_with_device">Mengautentikasi ke perangkat\u2026</string>
|
||||
<string name="connection_error_title">Tidak bisa menyambung dengan kontak Anda</string>
|
||||
<string name="connection_error_feedback">Jika masalah ini berulang, silakan <a href="feedback">kirim umpan balik</a> untuk memperbaiki aplikasi.</string>
|
||||
|
||||
<!-- Adding Contacts Remotely -->
|
||||
|
||||
<string name="add_contact_remotely_title_case">Tambahkan kontak jarak jauh</string>
|
||||
<string name="add_contact_nearby_title">Tambahkan kontak di dekat Anda</string>
|
||||
<string name="add_contact_remotely_title">Tambahkan kontak jarak jauh</string>
|
||||
<string name="contact_link_intro">Masukkan tautan dari kontak Anda di sini</string>
|
||||
<string name="contact_link_hint">Tautan kontak</string>
|
||||
<string name="paste_button">Tempel</string>
|
||||
<string name="add_contact_button">Tambahkan kontak</string>
|
||||
<string name="copy_button">Salin</string>
|
||||
<string name="share_button">Bagi</string>
|
||||
<string name="send_link_title">Tukar tautan</string>
|
||||
<string name="add_contact_choose_nickname">Pilih Nama Panggilan</string>
|
||||
<string name="add_contact_choose_a_nickname">Masukkan Nama Panggilan</string>
|
||||
<string name="nickname_intro">Berikan kontak Anda nama panggilan. Hanya Anda yang bisa melihat.</string>
|
||||
<string name="your_link">Beri tautan ini pada kontak yang ingin Anda tambahkan</string>
|
||||
<string name="link_clip_label">Tautan Briar</string>
|
||||
<string name="link_copied_toast">Tautan Tersalin</string>
|
||||
<string name="adding_contact_error">Ada masalah ketika menambah kontak.</string>
|
||||
<string name="pending_contact_requests_snackbar">Ada permintaan kontak yang tertunda</string>
|
||||
<string name="pending_contact_requests">Permintaan Kontak Tertunda</string>
|
||||
<string name="no_pending_contacts">Tidak ada kontak tertunda</string>
|
||||
<string name="waiting_for_contact_to_come_online">Menunggu kontak untuk daring…</string>
|
||||
<string name="connecting">Menyambung…</string>
|
||||
<string name="adding_contact">Menambah kontak…</string>
|
||||
<string name="adding_contact_failed">Penambahan kontak gagal</string>
|
||||
<string name="dialog_title_remove_pending_contact">Konfirmasi Penghapusan</string>
|
||||
<string name="dialog_message_remove_pending_contact">Kontak ini masih sedang ditambahkan. Jika Anda menghapusnya, kontak tidak akan ditambahkan.</string>
|
||||
<string name="own_link_error">Masukkan tautan kontak Anda, bukan tautan Anda sendiri</string>
|
||||
<string name="nickname_missing">Masukkan nama panggilan</string>
|
||||
<string name="invalid_link">Tautan Keliru</string>
|
||||
<string name="unsupported_link">Tautan ini dari Briar versi lebih mutakhir. Silakan naikkan ke versi terbaru dan coba lagi.</string>
|
||||
<string name="intent_own_link">Anda membuka tautan Anda sendiri. Gunakan dari kontak yang ingin Anda tambahkan!</string>
|
||||
<string name="missing_link">Masukkan tautan</string>
|
||||
<!-- This is a numeral indicating the first step in a series of screens -->
|
||||
<string name="step_1">1</string>
|
||||
<!-- This is a numeral indicating the second step in a series of screens -->
|
||||
<string name="step_2">2</string>
|
||||
|
||||
<plurals name="contact_added_notification_text">
|
||||
<item quantity="other">%d kontak baru ditambahkan.</item>
|
||||
</plurals>
|
||||
|
||||
<string name="offline_state">Tidak ada koneksi Internet</string>
|
||||
<string name="duplicate_link_dialog_title">Gandakan Tautan</string>
|
||||
<string name="duplicate_link_dialog_text_1">Anda memiliki kontak tertunda dengan tautan berikut: %s</string>
|
||||
<string name="duplicate_link_dialog_text_1_contact">Anda sudah memiliki kontak dengan tautan berikut: %s</string>
|
||||
<!-- This is a question asking whether two nicknames refer to the same person -->
|
||||
<string name="duplicate_link_dialog_text_2">Apakah %s and %s adalah orang yang sama?</string>
|
||||
<!-- This is a button for answering that two nicknames do indeed refer to the same person. This
|
||||
string will be used in a dialog button, so if the translation of this string is longer than 20
|
||||
characters, please use "Yes" instead, and use "No" for the "Different Person" button -->
|
||||
<string name="same_person_button">Orang Sama</string>
|
||||
<!-- This is a button for answering that two nicknames refer to different people. This string
|
||||
will be used in a dialog button, so if the translation of this string longer than 20 characters,
|
||||
please use "No" instead, and use "Yes" for the "Same Person" button -->
|
||||
<string name="different_person_button">Orang Berbeda</string>
|
||||
<string name="duplicate_link_dialog_text_3">%s dan %s mengirimkan tautan yang sama.\n\nSalah satu dari mereka mungkin sedang mencoba menemukan siapa kontak Anda.\n\nJangan beritahu bahwa Anda menerima tautan sama dari orang lain.</string>
|
||||
<string name="pending_contact_updated_toast">Menunda pembaruan kontak</string>
|
||||
|
||||
<!-- Settings Profile Picture -->
|
||||
<string name="change_profile_picture">Ketuk untuk mengubah gambar profil Anda</string>
|
||||
<string name="dialog_confirm_profile_picture_title">Ubah gambar profil Anda</string>
|
||||
<string name="dialog_confirm_profile_picture_remark">Hanya kontak Anda yang bisa melihat gambar ini</string>
|
||||
<string name="change_profile_picture_failed_message">Mohon maaf, tetapi ada masalah ketika Anda memutakhirkan gambar profil Anda</string>
|
||||
|
||||
<!-- Settings Display -->
|
||||
<string name="pref_language_title">Bahasa & region</string>
|
||||
<string name="pref_language_changed">Pengaturan ini akan mempengaruhi ketika Anda memulai ulang Briar. Silakan keluar dan mulai ulang Briar.</string>
|
||||
<string name="pref_language_default">Bawaan sistem</string>
|
||||
<string name="display_settings_title">Tampilan</string>
|
||||
<string name="pref_theme_title">Tema</string>
|
||||
<string name="pref_theme_light">Terang</string>
|
||||
<string name="pref_theme_dark">Gelap</string>
|
||||
<string name="pref_theme_auto">Otomatis (Siang)</string>
|
||||
<string name="pref_theme_system">Bawaan sistem</string>
|
||||
|
||||
<!-- Settings Connections -->
|
||||
<string name="network_settings_title">Koneksi</string>
|
||||
<string name="bluetooth_setting">Menyambung kontak lewat Bluetooth</string>
|
||||
<string name="wifi_setting">Menyambung kontak di Wi-Fi yang Sama</string>
|
||||
<string name="tor_enable_title">Menyambung kontak lewat Internet</string>
|
||||
<string name="tor_enable_summary">Semua koneksi melalui jaringan Tor untuk privasi</string>
|
||||
<string name="tor_network_setting">Metode koneksi untuk jaringan Tor</string>
|
||||
<string name="tor_network_setting_automatic">Otomatis sesuai lokasi</string>
|
||||
<string name="tor_network_setting_without_bridges">Gunakan jaringan Tor tanpa jembatan</string>
|
||||
<string name="tor_network_setting_with_bridges">Gunakan jaringan Tor dengan jembatan</string>
|
||||
<string name="tor_network_setting_never">Jangan sambungkan ke Internet</string>
|
||||
<!-- How and when Briar will connect to Tor: E.g. "Don't connect to the Internet (in China)" or "Use Tor network with bridges (in Belarus)" -->
|
||||
<string name="tor_network_setting_summary">Otomatis: %1$s (di %2$s)</string>
|
||||
<string name="tor_mobile_data_title">Gunakan paket data</string>
|
||||
<string name="tor_only_when_charging_title">Sambungkan ke Internet hanya ketika mengisi daya</string>
|
||||
<string name="tor_only_when_charging_summary">Nonaktifkan koneksi Internet ketika perangkat menggunakan baterai</string>
|
||||
|
||||
<!-- Settings Security and Panic -->
|
||||
<string name="security_settings_title">Keamanan</string>
|
||||
<string name="pref_lock_title">Kunci Aplikasi</string>
|
||||
<string name="pref_lock_summary">Gunakan kunci layar perangkat untuk melindungi Briar ketika masuk</string>
|
||||
<string name="pref_lock_disabled_summary">untuk menggunakan fitur ini, gunakan kunci layar untuk perangkat Anda</string>
|
||||
<string name="pref_lock_timeout_title">Waktu ketidakaktifan kunci selesai</string>
|
||||
<!-- The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour -->
|
||||
<string name="pref_lock_timeout_summary">Ketika tidak menggunakan Briar, otomatis akan mengunci setelah %s</string>
|
||||
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
|
||||
<string name="pref_lock_timeout_1">1 menit</string>
|
||||
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
|
||||
<string name="pref_lock_timeout_5">5 menit</string>
|
||||
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
|
||||
<string name="pref_lock_timeout_15">15 menit</string>
|
||||
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
|
||||
<string name="pref_lock_timeout_30">30 menit</string>
|
||||
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
|
||||
<string name="pref_lock_timeout_60">1 jama</string>
|
||||
<string name="pref_lock_timeout_never">Tidak Usah</string>
|
||||
<string name="pref_lock_timeout_never_summary">Jangan pernah kunci Briar secara otomatis</string>
|
||||
|
||||
<string name="change_password">Ubah kata sandi</string>
|
||||
<string name="current_password">Kata sandi saat ini</string>
|
||||
<string name="choose_new_password">Kata sandi baru</string>
|
||||
<string name="confirm_new_password">Konfirmasi kata sandi baru</string>
|
||||
<string name="password_changed">Kata sandi telah diubah.</string>
|
||||
<string name="panic_setting">Pengaturan tombol darurat</string>
|
||||
<string name="panic_setting_title">Tombol darurat</string>
|
||||
<string name="panic_setting_hint">Konfigurasikan bagaimana Briar akan bereaksi ketika Anda menggunakan aplikasi tombol darurat</string>
|
||||
<string name="panic_app_setting_title">Aplikasi Tombol Darurat</string>
|
||||
<string name="unknown_app">aplikasi tidak dikenal</string>
|
||||
<string name="panic_app_setting_summary">Tidak ada aplikasi yang diatur</string>
|
||||
<string name="panic_app_setting_none">Tidak Ada</string>
|
||||
<string name="dialog_title_connect_panic_app">Konfirmasi Aplikasi Darurat</string>
|
||||
<string name="dialog_message_connect_panic_app">Apakah Anda yakin mengizinkan %1$s untuk memicu tindakan merusak tombol darurat?</string>
|
||||
<string name="panic_setting_destructive_action">Tindak Merusak</string>
|
||||
<string name="panic_setting_signout_title">Keluar</string>
|
||||
<string name="panic_setting_signout_summary">Keluar dari Briar jika tombol darurat ditekan</string>
|
||||
<string name="purge_setting_title">Hapus Akun</string>
|
||||
<string name="purge_setting_summary">Hapus akun Briar Anda jika tombol darurat ditekan. Perhatian: Tindakan ini akan menghapus semua identitas, kontak, dan pesan Anda.</string>
|
||||
|
||||
<!-- Settings Notifications -->
|
||||
<string name="notification_settings_title">Notifikasi</string>
|
||||
<string name="notify_sign_in_title">Ingatkan saya untuk masuk</string>
|
||||
<string name="notify_sign_in_summary">Tunjukkan pengingat ketika ponsel mulai atau aplikasi telah diperbarui</string>
|
||||
<string name="notify_private_messages_setting_title">Pesan pribadi</string>
|
||||
<string name="notify_private_messages_setting_summary">Tunjukkan peringatan pesan pribadi</string>
|
||||
<string name="notify_private_messages_setting_summary_26">Konfigurasi peringatan pesan pribadi</string>
|
||||
<string name="notify_group_messages_setting_title">Pesan grup</string>
|
||||
<string name="notify_group_messages_setting_summary">Tunjukkan peringatan pesan grup</string>
|
||||
<string name="notify_group_messages_setting_summary_26">Konfigurasi peringatan pesan grup</string>
|
||||
<string name="notify_forum_posts_setting_title">Unggahan forum</string>
|
||||
<string name="notify_forum_posts_setting_summary">Tunjukkan peringatan unggahan forum</string>
|
||||
<string name="notify_forum_posts_setting_summary_26">Konfigurasi peringatan unggahan forum</string>
|
||||
<string name="notify_blog_posts_setting_title">Unggahan blog</string>
|
||||
<string name="notify_blog_posts_setting_summary">Tunjukkan peringatan unggahan blog</string>
|
||||
<string name="notify_blog_posts_setting_summary_26">Konfigurasi peringatan unggahan blog</string>
|
||||
<string name="notify_vibration_setting">Getar</string>
|
||||
<string name="notify_sound_setting">Suara</string>
|
||||
<string name="notify_sound_setting_default">Nada dering bawaan</string>
|
||||
<string name="notify_sound_setting_disabled">Tidak ada</string>
|
||||
<string name="choose_ringtone_title">Pilih nada dering</string>
|
||||
<string name="cannot_load_ringtone">Tidak bisa memuat nada dering</string>
|
||||
|
||||
<!-- Settings Feedback -->
|
||||
<string name="feedback_settings_title">Umpan balik</string>
|
||||
<string name="send_feedback">Kirim umpan balik</string>
|
||||
|
||||
<!-- Crash Reporter -->
|
||||
<string name="crash_report_title">Laporan Kerusakan Briar</string>
|
||||
<string name="briar_crashed">Maaf, Briar Rusak.</string>
|
||||
<string name="not_your_fault">Ini bukan kesalahan Anda.</string>
|
||||
<string name="please_send_report">Silakan bantu kami untuk membuat Briar lebih baik dengan mengirimkan laporan kerusakan.</string>
|
||||
<string name="report_is_encrypted">Kami berjanji laporan Anda terenkripsi dan dikirim dengan aman.</string>
|
||||
<string name="feedback_title">Umpan balik</string>
|
||||
<string name="describe_crash">Jelaskan apa yang terjadi (pilihan)</string>
|
||||
<string name="enter_feedback">Masukkan masukan Anda</string>
|
||||
<string name="optional_contact_email">Surel Anda (pilihan)</string>
|
||||
<string name="include_debug_report_crash">Sertakan data anonimus kerusakan</string>
|
||||
<string name="include_debug_report_feedback">Sertakan data anonimus perangkat</string>
|
||||
<string name="dev_report_basic_info">Informasi dasar</string>
|
||||
<string name="dev_report_device_info">Informasi perangkat</string>
|
||||
<string name="dev_report_stacktrace">Jejak tumpukan</string>
|
||||
<string name="dev_report_time_info">Informasi waktu</string>
|
||||
<string name="dev_report_memory">Memori</string>
|
||||
<string name="dev_report_storage">Penyimpanan</string>
|
||||
<string name="dev_report_connectivity">Konektivitas</string>
|
||||
<string name="dev_report_build_config">Bua konfigurasi</string>
|
||||
<string name="dev_report_logcat">Catatan aplikasi</string>
|
||||
<string name="dev_report_device_features">Fitur Perangkat</string>
|
||||
<string name="send_report">Kirim laporan</string>
|
||||
<string name="close">Tutup</string>
|
||||
<string name="dev_report_sending">Mengirim umpan balik…</string>
|
||||
<string name="dev_report_sent">Kirim balik terkirim</string>
|
||||
<string name="dev_report_saved">Laporan tersimpan. Akan dikirim pada saat Anda masuk Briar.</string>
|
||||
<string name="dev_report_error">Masalah: Pengiriman laporan gagal</string>
|
||||
|
||||
<!-- Sign Out -->
|
||||
<string name="progress_title_logout">Keluar dari Briar…</string>
|
||||
|
||||
<!-- Permission Requests -->
|
||||
<string name="permission_camera_title">Izin Kamera</string>
|
||||
<string name="permission_camera_request_body">Untuk memindai kode batang, Briar memerlukan akses ke kamera.</string>
|
||||
<string name="permission_location_title">Izin lokasi</string>
|
||||
<string name="permission_location_request_body">Untuk menemukan Bluetooth perangkat, Briar memerlukan izin untuk mengakses lokasi Anda.\n\nBriar tidak menyimpan lokasi Anda atau membaginya kepada orang lain.</string>
|
||||
<string name="permission_camera_location_title">Kamera dan lokasi</string>
|
||||
<string name="permission_camera_location_request_body">Untuk memindai kode batang, Briar memerlukan akses ke kamera.\n\nUntuk menemukan Bluetooth perangkat, Briar memerlukan izin untuk mengakses lokasi Anda.\n\nBriar tidak menyimpan lokasi Anda atau membaginya kepada orang lain.</string>
|
||||
<string name="permission_camera_denied_body">Anda sudah menolak akses ke kamera, tetapi menambahkan kontak memerlukan penggunaan kamera.\n\nHarap pertimbangkan memberikan akses.</string>
|
||||
<string name="permission_location_denied_body">Anda sudah menolak akses ke lokasi, tetapi Briar memerlukan izin tersebut untuk menemukan Bluetooth perangkat. Harap pertimbangkan memberikan akses.</string>
|
||||
<string name="permission_location_setting_title">Pengaturan Lokasi</string>
|
||||
<string name="permission_location_setting_body">Pengaturan lokasi perangkat Anda harus diaktifkan untuk menemukan perangkat lain melalui Bluetooth. Harap hidupkan lokasi untuk melanjutkan. Anda bisa mematikan setelahnya.</string>
|
||||
<string name="permission_location_setting_button">Aktifkan Lokasi</string>
|
||||
<string name="qr_code">Kode Batang</string>
|
||||
<string name="show_qr_code_fullscreen">Tunjukkan Kode Batang Tampilan Penuh</string>
|
||||
|
||||
<!-- App Locking -->
|
||||
<string name="lock_unlock">Buka Biar</string>
|
||||
<string name="lock_unlock_verbose">Masukkan PIN, pola, atau kata sandi untuk membuka perangkat Anda</string>
|
||||
<string name="lock_unlock_password">Gunakan kata sandi</string>
|
||||
<string name="lock_is_locked">Briar terkunci</string>
|
||||
<string name="lock_tap_to_unlock">Ketuk untuk membuka</string>
|
||||
|
||||
<!-- Connections Screen -->
|
||||
<string name="transports_help_text">Briar bisa tersambung dengan kontak Anda lewat Internet, Wi-Fi, Bluetooth.\n\nSemua akses Internet menggunakan jaringan Tor untuk privasi.\n\nJika salah satu kontak tidak bisa dijangkau melalui beberapa cara, Briar akan menggunakannya secara bersamaan.</string>
|
||||
|
||||
<!-- Social Backup Feature -->
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="pref_distributed_backup_title">Pencadangan Sosial</string>
|
||||
<string name="pref_distributed_backup_summary">Cadangkan akun Anda menggunakan kontak tepercaya</string>
|
||||
<string name="pref_distributed_old_backup_title">Cadangan Sosial yang Ada</string>
|
||||
<string name="pref_distributed_old_backup_summary">Informasi tentang pencadangan sosial terbaru Anda</string>
|
||||
|
||||
<!-- Social backup setup -->
|
||||
<string name="select_custodians">Pilih Kontak Tepercaya:</string>
|
||||
<string name="select_at_least_n_contacts">Pilih setidaknya %d kontak</string>
|
||||
<string name="select_at_least_n_more_contacts">Harap pilih setidaknya %d kontak lagi</string>
|
||||
<string name="threshold">Pilih angka minimal kontak tepercaya yang diperlukan untuk mengembalikan akun Anda</string>
|
||||
<string name="threshold_disabled">Dua kontak tepercaya diperlukan untuk mengembalikan akun Anda</string>
|
||||
<string name="threshold_secure">Aman</string>
|
||||
<string name="threshold_recommended">Aman - jejak tumpukan direkomendasikan</string>
|
||||
<string name="threshold_low_insecure">Tidak Aman - jejak tumpukan lebih tinggi direkomendasikan</string>
|
||||
<string name="threshold_high_insecure">Bahaya kehilangan – ambang lebih rendah direkomendasikan</string>
|
||||
<string name="threshold_defined">Pilih Ambang</string>
|
||||
<string name="threshold_m_of_n">%d dari %d kontak diperlukan untuk memulihkan akun Anda</string>
|
||||
<string name="backup_done_info">Data cadangan dikirim ke kontak tepercaya</string>
|
||||
|
||||
<!-- Recovery from the secret owner's POV -->
|
||||
<string name="recovery_explainer">Anda perlu bertemu langsung kontak tepercaya Anda untuk menerima data</string>
|
||||
<string name="recovery_explainer_extra">Kontak tepercaya Anda harus memindai kode batang untuk memulai pemindahan.\n\nAnda berdua harus tersambung melalui Wi-Fi yang sama</string>
|
||||
<string name="recovery_begin">Mulai</string>
|
||||
<string name="recovery_failed_to_receive">Gagal menerima data cadangan</string>
|
||||
<string name="recovery_helpful_suggestions">Pastikan Anda berdua tersambung Wi-Fi yang sama dan coba lagi</string>
|
||||
<string name="recovery_retry">Ulangi</string>
|
||||
<string name="recovery_recovered_shards">Data cadangan dikembalikan:</string>
|
||||
<string name="recovery_scan_qr_code">Tunjukkan kode batang</string>
|
||||
<string name="recovery_recovering_account">Memulihkan akun…</string>
|
||||
<string name="recovery_shard_received">Data cadangan akun diterima</string>
|
||||
<string name="recovery_account_recovered">Akun dipulihkan</string>
|
||||
<string name="recovery_account_recovered_explain">Anda harus membuat kata sandi baru untuk akun Anda sekarang</string>
|
||||
<string name="recovery_sending_ack">Mengirim pernyataan</string>
|
||||
|
||||
<!-- Recovery from the custodian's POV -->
|
||||
<string name="custodian_recovery_explainer">Anda harus bertemu langsung untuk memindahkan data cadangan</string>
|
||||
<string name="custodian_recovery_explainer_extra">Pastikan Anda berdua tersambung Wi-Fi yang sama, dan pindai ulang kode batang di perangkat kontak Anda untuk mulai memindahkan data cadangan</string>
|
||||
<string name="custodian_recovery_failed_to_send">Gagal mengirim data cadangan</string>
|
||||
<string name="custodian_scan_code">Memindai kode</string>
|
||||
<string name="custodian_shard_sent">Data cadangan akun dipindahkan</string>
|
||||
|
||||
<!-- Titles for the app bar -->
|
||||
<string name="title_distributed_backup">Pencadangan Sosial</string>
|
||||
<string name="title_select_custodians">Pilih Kontak Tepercaya</string>
|
||||
<string name="title_define_threshold">Ambang Batas</string>
|
||||
<string name="title_recovery_mode">Model Pemulihan</string>
|
||||
<string name="title_help_recover">Bantu memulihkan akun</string>
|
||||
|
||||
<!-- Conversation action for custodian -->
|
||||
<string name="help_recover_account">Bantu mengembalikan akun</string>
|
||||
|
||||
<!-- Setup screen -->
|
||||
<string name="setup_new_account">Buat akun baru</string>
|
||||
<string name="setup_restore_account">Mengembalikan akun dari cadangan</string>
|
||||
|
||||
<!-- Symbols for visualising threshold values for social backup -->
|
||||
<string name="filled_bullet">\u25CF</string>
|
||||
<string name="linear_bullet">\u25CB</string>
|
||||
|
||||
<!-- Activity names -->
|
||||
<string name="activity_name_distributed_backup">Pencadangan Sosial</string>
|
||||
<string name="activity_name_restore_account">Mengembalikan Akun</string>
|
||||
|
||||
<!-- Conversation -->
|
||||
<string name="social_backup_shard_received">%1$s mengirimi Anda data cadangan sosial.</string>
|
||||
<string name="social_backup_shard_sent">Anda sudah mengirim data cadangan ke %1$s.</string>
|
||||
|
||||
<string name="activity_name_new_or_recover_account">Buat akun baru atau pulihkan akun yang ada</string>
|
||||
<string name="activity_name_recovery">Memulihkan Akun</string>
|
||||
<string name="activity_name_custodian_help_recovery">Bantu memulihkan akun</string>
|
||||
<string name="existing_backup_explain">%d kontak berikut diperlukan untuk mengembalikan akun Anda:</string>
|
||||
|
||||
<string name="social_backup_not_enough_contacts">Untuk membuat pencadangan sosial, Anda harus memilih minimal 2 kontak dari daftar kontak Anda</string>
|
||||
<string name="reading_contacts_error">Ada masalah ketika membaca daftar kontak Anda</string>
|
||||
|
||||
<!-- Remote Wipe Feature -->
|
||||
|
||||
<!-- Setup -->
|
||||
<string name="remote_wipe_setup_success">Penghapusan jarak jauh diaktifkan</string>
|
||||
<string name="remote_wipe_setup_failed">Gagal mengaktifkan penghapusan jarak jauh</string>
|
||||
<string name="remote_wipe_setup_explain_title">Mengaktifkan fungsi penghapusan jarak jauh</string>
|
||||
<string name="remote_wipe_setup_explain_long">Anda bisa memilih sejumlah kontak tepercaya yang akan bisa mengaktifkan penghapusan jarak jauh semua data Briar Anda.\nPengahpusan jarak jauh bisa diaktifkan oleh salah satu dari dua kontak.</string>
|
||||
|
||||
<!-- Settings menu -->
|
||||
<string name="pref_remote_wipe_summary">Izinkan kontak tepercaya untuk mengaktifkan penghapusan akun jarak jauh</string>
|
||||
<string name="pref_remote_wipe_title">Penghapusan Jarak Jauh</string>
|
||||
|
||||
<!-- Titles for the app bar -->
|
||||
<string name="title_select_wipers">Pilih Kontak Tepercaya</string>
|
||||
|
||||
<!-- Conversation -->
|
||||
<string name="remote_wipe_setup_received">%1$s telah ditambahkan sebagai penghapus jarak jauh Anda.</string>
|
||||
<string name="remote_wipe_setup_sent">Anda sudah menambahkan %1$s sebagai penghapus jarak jauh.</string>
|
||||
<string name="remote_wipe_wipe_sent">Anda sudah mengirim sinyal mengaktifkan penghapusan jarak jauh kepada %1$s. Sudah kedaluwarsa </string>
|
||||
<string name="activity_name_remote_wipe">Penghapusan Jarak Jauh</string>
|
||||
<string name="assigned_wipers">Kontak tepercaya yang ditentukan</string>
|
||||
<string name="activate_remote_wipe">Mengaktifkan penghapusan jarak jauh</string>
|
||||
<string name="remote_wipe_revoke_sent">Anda sudah menghapus %1$s sebagai penghapus jarak jauh.</string>
|
||||
<string name="remote_wipe_revoke_received">Anda sudah tidak bisa mengaktifkan penghapusan jarak jauh kepada %1$s.</string>
|
||||
|
||||
<!-- Activate -->
|
||||
<string name="activity_name_activate_remote_wipe">Aktifkan Penghapusan Jarak Jauh</string>
|
||||
<string name="remote_wipe_activate_success">Sinyal penghapusan jarak terkirim</string>
|
||||
<string name="remote_wipe_activate_failure">Gagal mengirimkan sinyal penghapusan jarak jauh</string>
|
||||
<string name="remote_wipe_activate_button_confirm">Mengaktifkan penghapusan jarak jauh</string>
|
||||
<string name="remote_wipe_activate_button_cancel">Batal</string>
|
||||
<string name="remote_wipe_activate_explain_short">Mengaktifkan penghapusan jarak jauh kepada %1$s</string>
|
||||
<string name="remote_wipe_activate_explain_long">Jika dikonfirmasi oleh kontak kedua, mengirim sinyal ini akan menghapus semua data Briar dari perangkat %1$s\.</string>
|
||||
|
||||
<!-- Revoke -->
|
||||
<string name="activity_name_revoke_remote_wipe">Cabut Penghapusan Jarak Jauh</string>
|
||||
<string name="revoke_remote_wipe">Cabut Penghapusan Status Jarak Jauh</string>
|
||||
<string name="remote_wipe_revoke_success">Penghapusan Status Jarak Jauh Tercabut</string>
|
||||
<string name="remote_wipe_modify_contacts">Ubah Penghapus Jarak Jauh</string>
|
||||
|
||||
<string name="button_confirm">Oke</string>
|
||||
</resources>
|
||||
@@ -32,6 +32,7 @@
|
||||
<item>he</item>
|
||||
<item>hi</item>
|
||||
<item>hu</item>
|
||||
<item>in</item>
|
||||
<item>is</item>
|
||||
<item>it</item>
|
||||
<item>ja</item>
|
||||
|
||||
@@ -641,20 +641,17 @@
|
||||
<!-- This is a message to be used in screenshots. -->
|
||||
<string name="screenshot_message_3">No problem, hope you like it 😀</string>
|
||||
|
||||
<!-- social backup -->
|
||||
|
||||
<!-- settings -->
|
||||
<!-- Social Backup Feature -->
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="pref_distributed_backup_title">Social backup</string>
|
||||
<string name="pref_distributed_backup_summary">Backup your account using trusted contacts</string>
|
||||
|
||||
<string name="pref_distributed_old_backup_title">Existing Social backup</string>
|
||||
<string name="pref_distributed_old_backup_summary">Information about your most recent social backup</string>
|
||||
|
||||
<!-- social backup procedure -->
|
||||
<!-- Social backup setup -->
|
||||
|
||||
<string name="select_custodians">Select Trusted Contacts</string>
|
||||
|
||||
<string name="select_at_least_n_contacts">Please select at least %d contacts</string>
|
||||
<string name="select_at_least_n_more_contacts">Please select at least %d more contacts</string>
|
||||
<string name="select_no_more_than_n_contacts">Too many! Please select no more than %d contacts</string>
|
||||
@@ -668,6 +665,8 @@
|
||||
<string name="threshold_defined">Choose Minimum Needed</string>
|
||||
<string name="threshold_m_of_n">%d of %d contacts needed to recover your account</string>
|
||||
|
||||
<!-- Recovery from the secret owner's POV -->
|
||||
|
||||
<string name="backup_created">Social Backup created</string>
|
||||
<string name="backup_done_info">Backup pieces sent to trusted contacts</string>
|
||||
|
||||
@@ -694,36 +693,34 @@
|
||||
<string name="recovery_account_recovered_explain">You must now set a new password for your account</string>
|
||||
<string name="recovery_sending_ack">Sending acknowledgement</string>
|
||||
|
||||
<!-- recovery from the custodian's POV -->
|
||||
|
||||
<!-- Recovery from the custodian's POV -->
|
||||
<string name="custodian_recovery_explainer">You need to meet in-person to transfer backup piece</string>
|
||||
<string name="custodian_recovery_explainer_extra">Make sure you are both connected to the same wifi network, and scan the QR code on your contact\'s device to begin transferring the backup piece</string>
|
||||
<string name="custodian_recovery_failed_to_send">Failed to send backup piece</string>
|
||||
<string name="custodian_scan_code">Scan code</string>
|
||||
<string name="custodian_shard_sent">Account backup piece transmitted</string>
|
||||
|
||||
<!-- titles for the app bar -->
|
||||
|
||||
<!-- Titles for the app bar -->
|
||||
<string name="title_distributed_backup">Social Backup</string>
|
||||
<string name="title_select_custodians">Select Trusted Contacts</string>
|
||||
<string name="title_define_threshold">Minimum Needed</string>
|
||||
<string name="title_recovery_mode">Recovery Mode</string>
|
||||
<string name="title_help_recover">Help recover account</string>
|
||||
|
||||
<!-- conversation action for custodian -->
|
||||
|
||||
<!-- Conversation action for custodian -->
|
||||
<string name="help_recover_account">Help recover account</string>
|
||||
|
||||
<!-- setup screen -->
|
||||
|
||||
<!-- Setup screen -->
|
||||
<string name="setup_new_account">Create new account</string>
|
||||
<string name="setup_restore_account">Restore account from backup</string>
|
||||
|
||||
<!-- activity names -->
|
||||
|
||||
<!-- Activity names -->
|
||||
|
||||
<string name="activity_name_distributed_backup">Social Backup</string>
|
||||
<string name="activity_name_restore_account">Restore Account</string>
|
||||
|
||||
<!-- conversation -->
|
||||
<!-- Conversation -->
|
||||
<string name="social_backup_shard_received">%1$s has sent you a social backup piece.</string>
|
||||
<string name="social_backup_shard_sent">You have sent a social backup piece to %1$s.</string>
|
||||
|
||||
@@ -736,5 +733,55 @@
|
||||
<string name="reading_contacts_error">There was an error reading your contacts list</string>
|
||||
|
||||
<!-- Display existing backup -->
|
||||
|
||||
<string name="social_backup_trusted_contacts">Trusted Contacts</string>
|
||||
|
||||
<!-- Remote Wipe Feature -->
|
||||
|
||||
<!-- Setup -->
|
||||
<string name="remote_wipe_setup_success">Remote wipe is set up</string>
|
||||
<string name="remote_wipe_setup_failed">Failed to set up remote wipe</string>
|
||||
<string name="remote_wipe_setup_explain_title">Setup remote wipe function</string>
|
||||
<string name="remote_wipe_setup_explain_long">You can choose a set of trusted contacts who are able to activate a remote wipe of all Briar data.\nThe wipe may be activated by any two contacts from the set.</string>
|
||||
<string name="remote_wipe_display_explain">Any two of these trusted contacts may activate a wipe of all Briar data from your device.</string>
|
||||
|
||||
<!-- Settings menu -->
|
||||
<string name="pref_remote_wipe_summary">Allow trusted contacts to activate an account wipe remotely</string>
|
||||
<string name="pref_remote_wipe_title">Remote Wipe</string>
|
||||
|
||||
<!-- Titles for the app bar -->
|
||||
<string name="title_select_wipers">Select Trusted Contacts</string>
|
||||
|
||||
<!-- Conversation -->
|
||||
<string name="remote_wipe_setup_received">%1$s has added you as a remote wiper.</string>
|
||||
<string name="remote_wipe_setup_sent">You have added %1$s as a remote wiper.</string>
|
||||
<string name="remote_wipe_wipe_sent">You have sent an activate remote wipe signal to %1$s. It expires </string>
|
||||
<string name="activity_name_remote_wipe">Remote Wipe</string>
|
||||
<string name="assigned_wipers">Your assigned trusted wipers</string>
|
||||
<string name="activate_remote_wipe">Activate remote wipe</string>
|
||||
<string name="remote_wipe_revoke_sent">You have removed %1$s as a remote wiper.</string>
|
||||
<string name="remote_wipe_revoke_received">You can no longer activate a remote wipe for %1$s.</string>
|
||||
|
||||
<!-- Activate -->
|
||||
<string name="activity_name_activate_remote_wipe">Activate Remote Wipe</string>
|
||||
<string name="remote_wipe_activate_success">Remote wipe signal sent</string>
|
||||
<string name="remote_wipe_activate_failure">Failed to send remote wipe signal</string>
|
||||
<string name="remote_wipe_activate_button_confirm">Activate remote wipe</string>
|
||||
<string name="remote_wipe_activate_button_cancel">Cancel</string>
|
||||
<string name="remote_wipe_activate_explain_short">Activate a remote wipe for %1$s</string>
|
||||
<string name="remote_wipe_activate_explain_long">If confirmed by a second contact, sending this signal will remove all Briar data from %1$s\'s device.</string>
|
||||
|
||||
<!-- Revoke -->
|
||||
<string name="activity_name_revoke_remote_wipe">Revoke Remote Wipe</string>
|
||||
<string name="revoke_remote_wipe">Revoke remote wipe status</string>
|
||||
<string name="remote_wipe_revoke_success">Remote wipe status revoked</string>
|
||||
<string name="remote_wipe_modify_contacts">Change remote wipers</string>
|
||||
<string name="remote_wipe_disable">Disable remote wipe</string>
|
||||
<string name="remote_wipe_disable_success">Remote wipe is disabled</string>
|
||||
<string name="remote_wipe_disable_success_explain">None of your contacts are able to activate a wipe.</string>
|
||||
|
||||
<string name="remote_wipe_confirm_received">Briar data has been wiped from %1$s\'s device. They will be unreachable until they recover their account.</string>
|
||||
|
||||
<string name="button_confirm">Ok</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -65,6 +65,12 @@
|
||||
<item name="android:minWidth">@dimen/button_size</item>
|
||||
</style>
|
||||
|
||||
<style name="BriarButtonFlat.Negative.Tiny" parent="BriarButtonFlat.Negative">
|
||||
<item name="android:textSize">@dimen/text_size_tiny</item>
|
||||
<item name="android:padding">@dimen/margin_medium</item>
|
||||
<item name="android:minWidth">@dimen/button_size</item>
|
||||
</style>
|
||||
|
||||
<style name="Divider">
|
||||
<item name="android:background">@color/divider</item>
|
||||
</style>
|
||||
|
||||
@@ -101,6 +101,17 @@
|
||||
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
android:summary="@string/pref_remote_wipe_summary"
|
||||
android:title="@string/pref_remote_wipe_title"
|
||||
app:iconSpaceReserved="false">
|
||||
|
||||
<intent
|
||||
android:targetClass="org.briarproject.briar.android.remotewipe.RemoteWipeSetupActivity"
|
||||
android:targetPackage="@string/app_package" />
|
||||
|
||||
</Preference>
|
||||
|
||||
<SwitchPreference
|
||||
android:enabled="false"
|
||||
android:key="pref_key_lock"
|
||||
|
||||
@@ -67,36 +67,36 @@ dependencyVerification {
|
||||
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
|
||||
'classworlds:classworlds:1.1-alpha-2:classworlds-1.1-alpha-2.jar:2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3',
|
||||
'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
|
||||
'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
|
||||
'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
|
||||
'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
|
||||
'com.android.tools.analytics-library:protos:27.2.2:protos-27.2.2.jar:02482564443c294dfe87c5f2b25387f724a698a09ed58e0cf0127400caa35a19',
|
||||
'com.android.tools.analytics-library:shared:27.2.2:shared-27.2.2.jar:0efe017ca17ee775c5af386475a09799a1282faa04821d54810c1a34f6348d9c',
|
||||
'com.android.tools.analytics-library:tracker:27.2.2:tracker-27.2.2.jar:62489d84192dc06219664945c43201654ff85c3b715f46550751512a880d0e39',
|
||||
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
|
||||
'com.android.tools.build:apksig:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
|
||||
'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
|
||||
'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
|
||||
'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
|
||||
'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
|
||||
'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
|
||||
'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
|
||||
'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
|
||||
'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
|
||||
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
|
||||
'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
|
||||
'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
|
||||
'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
|
||||
'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
|
||||
'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
|
||||
'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
|
||||
'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
|
||||
'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
|
||||
'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
|
||||
'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
|
||||
'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
|
||||
'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
|
||||
'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
|
||||
'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
|
||||
'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
|
||||
'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
|
||||
'com.android.tools.build:apksig:4.2.2:apksig-4.2.2.jar:632690bf641b429dcb31650e6b2f6a2e87c4ac8afd45a6ba3cbc99fb1612178f',
|
||||
'com.android.tools.build:apkzlib:4.2.2:apkzlib-4.2.2.jar:3b5167c1265e97f65201c4d2be6a6f72165a3aa2fe9e0594a59b67af9e9e97b9',
|
||||
'com.android.tools.build:builder-model:4.2.2:builder-model-4.2.2.jar:41868de0cb88ae70b828eee4191c13e0233f433abb1becdf6a2bd391bd446bc0',
|
||||
'com.android.tools.build:builder-test-api:4.2.2:builder-test-api-4.2.2.jar:2f305c6d3a7b637d736b821bad372dcabd959e979f2065a9f65bac1e7b4d1875',
|
||||
'com.android.tools.build:builder:4.2.2:builder-4.2.2.jar:40fedd0d16db8f34ddb4eaf812d966b90ef1764f65cf119030442823bcf995cd',
|
||||
'com.android.tools.build:gradle-api:4.2.2:gradle-api-4.2.2.jar:dd4ef35bbbfb8fc2d20e3311c76b516bc1672e82b61cb3a59fc877da0f9b4f61',
|
||||
'com.android.tools.build:manifest-merger:27.2.2:manifest-merger-27.2.2.jar:971974756f32d9e94c857d92772b1499b0b0f5d9c70cb8ebbd20d9bbf804a923',
|
||||
'com.android.tools.ddms:ddmlib:27.2.2:ddmlib-27.2.2.jar:9ab0f9b58737c316af454184705854c75936ca3531f21acc29bd68a3343334d1',
|
||||
'com.android.tools.external.com-intellij:intellij-core:27.2.2:intellij-core-27.2.2.jar:01619d5dc28ec909cbdee699f1f13056e84462faf6dccf4817561293fb28bef0',
|
||||
'com.android.tools.external.com-intellij:kotlin-compiler:27.2.2:kotlin-compiler-27.2.2.jar:71bd460199ce7293ecc54b91a115319c1e4b585eca5a5b3699f6a406f29e626c',
|
||||
'com.android.tools.external.org-jetbrains:uast:27.2.2:uast-27.2.2.jar:efa59302fd433015e993143530cecb456b63d10d0b89bd1d3b1a016904338a65',
|
||||
'com.android.tools.layoutlib:layoutlib-api:27.2.2:layoutlib-api-27.2.2.jar:f0901f2295d814e82ad95850ea2103dd89d8489e01727fafa55ccccc0dccd163',
|
||||
'com.android.tools.lint:lint-api:27.2.2:lint-api-27.2.2.jar:1ecb5959c8e624ee49cdf9178de67bb0e823b4382ed253410eb36afe5c458b05',
|
||||
'com.android.tools.lint:lint-checks:27.2.2:lint-checks-27.2.2.jar:989e545a6b5e398e63a9f3608da02d6111f2241faec1baa0a3b4492cb03aeaf2',
|
||||
'com.android.tools.lint:lint-gradle-api:27.2.2:lint-gradle-api-27.2.2.jar:2be9c69d6fbbfb012ff6521fdfcb22eb7cfaa57d108e07bb1d4143dae9c1b433',
|
||||
'com.android.tools.lint:lint-gradle:27.2.2:lint-gradle-27.2.2.jar:742dedd5ccb459a245a35bf4fa16dfecc762da1a6b1741332cfe5228e812301a',
|
||||
'com.android.tools.lint:lint-model:27.2.2:lint-model-27.2.2.jar:ee31012586462bea2d591b6175934e5f29b6f781a78fda50f79387972364b9ab',
|
||||
'com.android.tools.lint:lint:27.2.2:lint-27.2.2.jar:7247016af7fba8cabee6ae887515b144f5a2ff7823422654daf23be9202f8fb1',
|
||||
'com.android.tools:annotations:27.2.2:annotations-27.2.2.jar:9375fb2df5c0cf1b46fef9e65b3a27ac88925ccf90054b19ae0ca0adc7036fe1',
|
||||
'com.android.tools:common:27.2.2:common-27.2.2.jar:a76f4e10cad39bed317be031fee915d280aa8bc11616c58ab94e051b1e38769d',
|
||||
'com.android.tools:dvlib:27.2.2:dvlib-27.2.2.jar:9931c6b57460b5f8cc2613ca5ff8596aa089a67655ace13d173f90538ecb4301',
|
||||
'com.android.tools:repository:27.2.2:repository-27.2.2.jar:ac5f9b19dc5d9d08e80b57da76059f5760ca76c221e40ffd4bf43d7b13991674',
|
||||
'com.android.tools:sdk-common:27.2.2:sdk-common-27.2.2.jar:b147acc13850808d61fc391ccfeeebdf90841b461a7042acb2d92e466da8e674',
|
||||
'com.android.tools:sdklib:27.2.2:sdklib-27.2.2.jar:fae0bafbe8b4f546cf64986a22b7d8ed108d45519366ff22f0170a9cf3ea7f34',
|
||||
'com.android:signflinger:4.2.2:signflinger-4.2.2.jar:4d7aafd9666707b483b1ad2c466824287cf2e379dda1d204dd3b7e453ffcf760',
|
||||
'com.android:zipflinger:4.2.2:zipflinger-4.2.2.jar:8e4677086c9a8f4a67374a4edc31db7e481f0d9b85907263c51ca72452c23a93',
|
||||
'com.github.bumptech.glide:annotations:4.11.0:annotations-4.11.0.jar:d219d238006d824962176229d4708abcdddcfe342c6a18a5d0fa48d6f0479b3e',
|
||||
'com.github.bumptech.glide:compiler:4.11.0:compiler-4.11.0.jar:a98cdf265c36261b1d523448b05c322ec290afa865946425eded6361980e8770',
|
||||
'com.github.bumptech.glide:gifdecoder:4.11.0:gifdecoder-4.11.0.aar:197a1cd5b76855aa02b230c13974e293229b901dc2b96fab4315201e78baa804',
|
||||
@@ -110,7 +110,6 @@ dependencyVerification {
|
||||
'com.google.auto:auto-common:0.8:auto-common-0.8.jar:97db1709f57b91b32edacb596ef4641872f227b7d99ad90e467f0d77f5ba134a',
|
||||
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
|
||||
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||
'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
|
||||
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
|
||||
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
|
||||
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
|
||||
@@ -136,13 +135,12 @@ dependencyVerification {
|
||||
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
|
||||
'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
|
||||
'com.jraska:falcon:2.1.1:falcon-2.1.1.aar:827f06556b7fa599f29a48a5277df39ca3dce5080d4ea6f9ea1f9c7b6b78bb7a',
|
||||
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
|
||||
'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e',
|
||||
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
|
||||
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
||||
'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
|
||||
'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
|
||||
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
|
||||
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
|
||||
'com.vanniktech:emoji-google:0.6.0:emoji-google-0.6.0.aar:029d6a954cebfe3f0a5bac0c9539a054fa7db2e1272d006a8f0e850f3794d44b',
|
||||
'com.vanniktech:emoji:0.6.0:emoji-0.6.0.aar:a5fcde58902305c004f03c6dc2241e718400ac4162226079791d87fac83ef639',
|
||||
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
|
||||
@@ -150,12 +148,12 @@ dependencyVerification {
|
||||
'de.hdodenhof:circleimageview:3.0.1:circleimageview-3.0.1.aar:7b0f088436ad4dcbb36d779fd09bf2192d9cc1e1a734bb6337904a7648f97617',
|
||||
'info.guardianproject.panic:panic:1.0:panic-1.0.jar:35116ab95212e67f94577faf67b88c11a6b21cbf9178b3f5b51d3dff45203ffd',
|
||||
'info.guardianproject.trustedintents:trustedintents:0.2:trustedintents-0.2.jar:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
|
||||
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
|
||||
'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
|
||||
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
|
||||
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
|
||||
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
|
||||
'javax.annotation:javax.annotation-api:1.3.2:javax.annotation-api-1.3.2.jar:e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b',
|
||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
|
||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||
'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
|
||||
'nekohtml:nekohtml:1.9.6.2:nekohtml-1.9.6.2.jar:fdff6cfa9ed9cc911c842a5d2395f209ec621ef1239d46810e9e495809d3ae09',
|
||||
@@ -163,7 +161,9 @@ dependencyVerification {
|
||||
'net.bytebuddy:byte-buddy-agent:1.10.20:byte-buddy-agent-1.10.20.jar:b592a6c43e752bf41659717956c57fbb790394d2ee5f8941876659f9c5c0e7e8',
|
||||
'net.bytebuddy:byte-buddy:1.10.20:byte-buddy-1.10.20.jar:5fcad05da791e9a22811c255a4a74b7ea094b7243d9dbf3e6fc578c8c94290ac',
|
||||
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
||||
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
|
||||
'net.java.dev.jna:jna:5.5.0:jna-5.5.0.aar:12ef4a3c2ea685c9c816caa6a77ae8f17bb7727d8460f249925409acda270101',
|
||||
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
|
||||
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
|
||||
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
|
||||
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
|
||||
@@ -190,8 +190,8 @@ dependencyVerification {
|
||||
'org.apache.maven:maven-repository-metadata:2.2.1:maven-repository-metadata-2.2.1.jar:5fe283f47b0e7f7d95a4252af3fa7a0db4d8f080cd9df308608c0472b8f168a1',
|
||||
'org.apache.maven:maven-settings:2.2.1:maven-settings-2.2.1.jar:9a9f556713a404e770c9dbdaed7eb086078014c989291960c76fdde6db4192f7',
|
||||
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
||||
'org.bouncycastle:bcprov-jdk15on:1.52:bcprov-jdk15on-1.52.jar:0dc4d181e4d347893c2ddbd2e6cd5d7287fc651c03648fa64b2341c7366b1773',
|
||||
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
||||
'org.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
|
||||
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
|
||||
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
|
||||
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
|
||||
@@ -202,31 +202,31 @@ dependencyVerification {
|
||||
'org.codehaus.plexus:plexus-container-default:1.0-alpha-9-stable-1:plexus-container-default-1.0-alpha-9-stable-1.jar:7c758612888782ccfe376823aee7cdcc7e0cdafb097f7ef50295a0b0c3a16edf',
|
||||
'org.codehaus.plexus:plexus-interpolation:1.11:plexus-interpolation-1.11.jar:fd9507feb858fa620d1b4aa4b7039fdea1a77e09d3fd28cfbddfff468d9d8c28',
|
||||
'org.codehaus.plexus:plexus-utils:1.5.15:plexus-utils-1.5.15.jar:2ca121831e597b4d8f2cb22d17c5c041fc23a7777ceb6bfbdd4dfb34bbe7d997',
|
||||
'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
|
||||
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
|
||||
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
|
||||
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
|
||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
|
||||
'org.hamcrest:hamcrest-integration:1.3:hamcrest-integration-1.3.jar:70f418efbb506c5155da5f9a5a33262ea08a9e4d7fea186aa9015c41a7224ac2',
|
||||
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
|
||||
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
|
||||
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
|
||||
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
|
||||
'org.jetbrains.kotlin:kotlin-reflect:1.4.31:kotlin-reflect-1.4.31.jar:91fad0b42974a7d5811e30a61f05706e176b144235717c6de7e81e3a781028f2',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50:kotlin-stdlib-common-1.3.50.jar:8ce678e88e4ba018b66dacecf952471e4d7dfee156a8a819760a5a5ff29d323c',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.31:kotlin-stdlib-common-1.4.31.jar:57962f44371a746b678218a0802a8712c6255206de9a69ede215e3aa4b044708',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.31:kotlin-stdlib-jdk7-1.4.31.jar:1f966e54e86cf4b7d7014afdce04e0f3ee4625084cda3494edccc7b84af52664',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.31:kotlin-stdlib-jdk8-1.4.31.jar:b2f8364435ebcb0106ff9d4415a11ffdef8ec7786ee6e5ed465a01556cbd1683',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib:1.3.50:kotlin-stdlib-1.3.50.jar:e6f05746ee0366d0b52825a090fac474dcf44082c9083bbb205bd16976488d6c',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
|
||||
'org.jetbrains.kotlin:kotlin-stdlib:1.4.31:kotlin-stdlib-1.4.31.jar:76a599d88b167e8ac90879b6daa722c6ad3452ba714c9aba19bd196544b97f1c',
|
||||
'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0:kotlinx-coroutines-android-1.3.0.jar:c80aaadf041f044d324a19a73f88879dfd1e4d026b14e3230075ff9081942ae3',
|
||||
'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0:kotlinx-coroutines-core-1.3.0.jar:6f3a60fea2403b80385b399952aeb3a4cf0985a45b8da04b6f31825171901a1d',
|
||||
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
||||
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
||||
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
|
||||
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
|
||||
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
|
||||
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
|
||||
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
|
||||
'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
|
||||
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
|
||||
'org.magmacollective.darkcrystal:dark-crystal-key-backup-crypto:1.0.0:dark-crystal-key-backup-crypto-1.0.0.jar:7c808f30314f7bc0c715b53415b07bd7e9a6bbcc55e5f672a296e5298d335f78',
|
||||
'org.magmacollective.darkcrystal:dark-crystal-secret-sharing-wrapper:1.1.0:dark-crystal-secret-sharing-wrapper-1.1.0.aar:b8cac2348b9e652de413fa587168e9bb6ff36f6eea4bd1c72d3ecd56fc186e09',
|
||||
'org.magmacollective.darkcrystal:shamir-secret-sharing-jna:1.0.0:shamir-secret-sharing-jna-1.0.0.aar:cdccfaf74dc1fcf30799a45d034c406315ce8507a8f4382eee118a66fb229ced',
|
||||
@@ -252,5 +252,7 @@ dependencyVerification {
|
||||
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
|
||||
'tools.fastlane:screengrab:2.0.0:screengrab-2.0.0.aar:15ac15eb7c371db05e721be8d466567c2b7274b767d91478e781b6d89ee5d3d0',
|
||||
'uk.co.samuelwall:material-tap-target-prompt:3.0.0:material-tap-target-prompt-3.0.0.aar:e4d3c472b2d378e39a6535b7788e6c790fc9dde2d7659974e006ed8c7260911d',
|
||||
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
|
||||
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
|
||||
import org.briarproject.briar.api.socialbackup.ShardMessageHeader;
|
||||
|
||||
@NotNullByDefault
|
||||
@@ -34,4 +35,6 @@ public interface ConversationMessageVisitor<T> {
|
||||
T visitIntroductionResponse(IntroductionResponse r);
|
||||
|
||||
T visitShardMessage(ShardMessageHeader r);
|
||||
|
||||
T visitRemoteWipeMessage(RemoteWipeMessageHeader r);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
public interface MessageEncoder {
|
||||
byte[] encodeSetupMessage();
|
||||
|
||||
byte[] encodeRevokeMessage();
|
||||
|
||||
byte[] encodeWipeMessage();
|
||||
|
||||
byte[] encodeConfirmMessage();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
|
||||
public interface MessageParser {
|
||||
void parseSetupMessage(BdfList body) throws FormatException;
|
||||
|
||||
void parseWipeMessage(BdfList body) throws FormatException;
|
||||
|
||||
void parseRevokeMessage(BdfList body) throws FormatException;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public enum MessageType {
|
||||
|
||||
SETUP(0), WIPE(1), REVOKE(2), CONFIRM(3);
|
||||
|
||||
private final int value;
|
||||
|
||||
MessageType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static MessageType fromValue(int value) throws
|
||||
FormatException {
|
||||
for (MessageType m : values()) if (m.value == value) return m;
|
||||
throw new FormatException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* An event which is activated when a critical amount of
|
||||
* remote wipe messages are received.
|
||||
*/
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class RemoteWipeActivatedEvent extends Event {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
public interface RemoteWipeConstants {
|
||||
|
||||
int THRESHOLD = 2;
|
||||
long MAX_MESSAGE_AGE = 24 * 60 * 60 * 1000;
|
||||
|
||||
// Group metadata keys
|
||||
String GROUP_KEY_CONTACT_ID = "contactId";
|
||||
String GROUP_KEY_WIPERS = "wipers";
|
||||
String GROUP_KEY_RECEIVED_WIPE = "receivedWipe";
|
||||
String GROUP_KEY_AM_WIPER = "amWiper";
|
||||
|
||||
// Message metadata keys
|
||||
String MSG_KEY_TIMESTAMP = "timestamp";
|
||||
String MSG_KEY_MESSAGE_TYPE = "messageType";
|
||||
String MSG_KEY_LOCAL = "local";
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientId;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask;
|
||||
|
||||
import java.text.Normalizer;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface RemoteWipeManager extends ConversationManager.ConversationClient {
|
||||
|
||||
interface Observer {
|
||||
void onPanic();
|
||||
}
|
||||
|
||||
/**
|
||||
* The unique ID of the remote wipe client.
|
||||
*/
|
||||
ClientId CLIENT_ID = new ClientId("pw.darkcrystal.remotewipe");
|
||||
|
||||
/**
|
||||
* The current major version of the remote wipe client.
|
||||
*/
|
||||
int MAJOR_VERSION = 0;
|
||||
|
||||
/**
|
||||
* The current minor version of the remote wipe client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
|
||||
void listenForPanic(Observer observer);
|
||||
|
||||
void setup(Transaction txn, List<ContactId> wipers)
|
||||
throws DbException, FormatException;
|
||||
|
||||
void wipe(Transaction txn, Contact contact)
|
||||
throws DbException, FormatException;
|
||||
|
||||
boolean amWiper(Transaction txn, ContactId contactId);
|
||||
|
||||
boolean isWiper(Transaction txn, ContactId contactId);
|
||||
|
||||
void revoke(Transaction txn, ContactId contactId)
|
||||
throws DbException, FormatException;
|
||||
|
||||
void revokeAll(Transaction txn) throws DbException, FormatException;
|
||||
|
||||
boolean remoteWipeIsSetup(Transaction txn);
|
||||
|
||||
List<Author> getWipers(Transaction txn) throws DbException;
|
||||
|
||||
List<ContactId> getWiperContactIds(Transaction txn);
|
||||
|
||||
int sendConfirmMessages(Transaction txn) throws DbException,
|
||||
FormatException;
|
||||
|
||||
@Override
|
||||
Collection<ConversationMessageHeader> getMessageHeaders(
|
||||
Transaction txn, ContactId contactId) throws DbException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class RemoteWipeMessageHeader extends ConversationMessageHeader {
|
||||
|
||||
private final List<AttachmentHeader> attachmentHeaders;
|
||||
private final MessageType type;
|
||||
|
||||
public RemoteWipeMessageHeader(MessageId id, GroupId groupId, long timestamp,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
List<AttachmentHeader> headers, MessageType type) {
|
||||
super(id, groupId, timestamp, local, read, sent, seen);
|
||||
this.attachmentHeaders = headers;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public List<AttachmentHeader> getAttachmentHeaders() {
|
||||
return attachmentHeaders;
|
||||
}
|
||||
|
||||
public MessageType getMessageType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public long getMessageExpiry() {
|
||||
return (getTimestamp() + RemoteWipeConstants.MAX_MESSAGE_AGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ConversationMessageVisitor<T> v) {
|
||||
return v.visitRemoteWipeMessage(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.briarproject.briar.api.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.api.conversation.event.ConversationMessageReceivedEvent;
|
||||
|
||||
import jdk.nashorn.internal.ir.annotations.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class RemoteWipeReceivedEvent
|
||||
extends ConversationMessageReceivedEvent<RemoteWipeMessageHeader> {
|
||||
|
||||
public RemoteWipeReceivedEvent(RemoteWipeMessageHeader messageHeader,
|
||||
ContactId contactId) {
|
||||
super(messageHeader, contactId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,9 +10,9 @@ import org.briarproject.briar.introduction.IntroductionModule;
|
||||
import org.briarproject.briar.messaging.MessagingModule;
|
||||
import org.briarproject.briar.privategroup.PrivateGroupModule;
|
||||
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
|
||||
import org.briarproject.briar.remotewipe.RemoteWipeModule;
|
||||
import org.briarproject.briar.sharing.SharingModule;
|
||||
import org.briarproject.briar.socialbackup.SocialBackupModule;
|
||||
//import org.briarproject.briar.socialbackup.DefaultSocialBackupModule;
|
||||
|
||||
public interface BriarCoreEagerSingletons {
|
||||
|
||||
@@ -38,6 +38,8 @@ public interface BriarCoreEagerSingletons {
|
||||
|
||||
void inject(SocialBackupModule.EagerSingletons init);
|
||||
|
||||
void inject(RemoteWipeModule.EagerSingletons init);
|
||||
|
||||
void inject(HandshakeKeyExchangeModule.EagerSingletons init);
|
||||
|
||||
class Helper {
|
||||
@@ -54,6 +56,7 @@ public interface BriarCoreEagerSingletons {
|
||||
c.inject(new IdentityModule.EagerSingletons());
|
||||
c.inject(new IntroductionModule.EagerSingletons());
|
||||
c.inject(new SocialBackupModule.EagerSingletons());
|
||||
c.inject(new RemoteWipeModule.EagerSingletons());
|
||||
c.inject(new HandshakeKeyExchangeModule.EagerSingletons());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.briarproject.briar.introduction.IntroductionModule;
|
||||
import org.briarproject.briar.messaging.MessagingModule;
|
||||
import org.briarproject.briar.privategroup.PrivateGroupModule;
|
||||
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
|
||||
import org.briarproject.briar.remotewipe.RemoteWipeModule;
|
||||
import org.briarproject.briar.sharing.SharingModule;
|
||||
import org.briarproject.briar.socialbackup.SocialBackupModule;
|
||||
import org.briarproject.briar.test.TestModule;
|
||||
@@ -32,6 +33,7 @@ import dagger.Module;
|
||||
AttachmentModule.class,
|
||||
MessagingModule.class,
|
||||
PrivateGroupModule.class,
|
||||
RemoteWipeModule.class,
|
||||
SharingModule.class,
|
||||
SocialBackupModule.class,
|
||||
HandshakeKeyExchangeModule.class,
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.briarproject.briar.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.briar.api.remotewipe.MessageEncoder;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.CONFIRM;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.SETUP;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.WIPE;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.REVOKE;
|
||||
|
||||
public class MessageEncoderImpl implements MessageEncoder {
|
||||
|
||||
private final ClientHelper clientHelper;
|
||||
|
||||
@Inject
|
||||
MessageEncoderImpl(ClientHelper clientHelper) {
|
||||
this.clientHelper = clientHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeSetupMessage() {
|
||||
BdfList body = BdfList.of(
|
||||
SETUP.getValue()
|
||||
);
|
||||
return encodeBody(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeRevokeMessage() {
|
||||
BdfList body = BdfList.of(
|
||||
REVOKE.getValue()
|
||||
);
|
||||
return encodeBody(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeWipeMessage() {
|
||||
BdfList body = BdfList.of(
|
||||
WIPE.getValue()
|
||||
);
|
||||
return encodeBody(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encodeConfirmMessage() {
|
||||
BdfList body = BdfList.of(
|
||||
CONFIRM.getValue()
|
||||
);
|
||||
return encodeBody(body);
|
||||
}
|
||||
|
||||
private byte[] encodeBody(BdfList body) {
|
||||
try {
|
||||
return clientHelper.toByteArray(body);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.briarproject.briar.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.briar.api.remotewipe.MessageParser;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class MessageParserImpl implements MessageParser {
|
||||
|
||||
@Inject
|
||||
MessageParserImpl () {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSetupMessage(BdfList body) throws FormatException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseWipeMessage(BdfList body) throws FormatException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRevokeMessage(BdfList body) throws FormatException {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,656 @@
|
||||
package org.briarproject.briar.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfEntry;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.data.MetadataParser;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
import org.briarproject.briar.api.conversation.DeletionResult;
|
||||
import org.briarproject.briar.api.remotewipe.MessageEncoder;
|
||||
import org.briarproject.briar.api.remotewipe.MessageParser;
|
||||
import org.briarproject.briar.api.remotewipe.MessageType;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeActivatedEvent;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeReceivedEvent;
|
||||
import org.briarproject.briar.client.ConversationClientImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.CONFIRM;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.REVOKE;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.SETUP;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.WIPE;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.GROUP_KEY_AM_WIPER;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.GROUP_KEY_CONTACT_ID;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.GROUP_KEY_RECEIVED_WIPE;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.GROUP_KEY_WIPERS;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.MAX_MESSAGE_AGE;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.MSG_KEY_MESSAGE_TYPE;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.MSG_KEY_TIMESTAMP;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeConstants.THRESHOLD;
|
||||
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
|
||||
|
||||
public class RemoteWipeManagerImpl extends ConversationClientImpl
|
||||
implements RemoteWipeManager, ContactManager.ContactHook,
|
||||
ClientVersioningManager.ClientVersioningHook,
|
||||
LifecycleManager.OpenDatabaseHook {
|
||||
|
||||
private final ClientVersioningManager clientVersioningManager;
|
||||
private final Group localGroup;
|
||||
private final Clock clock;
|
||||
private final ContactGroupFactory contactGroupFactory;
|
||||
private final ContactManager contactManager;
|
||||
private final MessageEncoder messageEncoder;
|
||||
private final MessageParser messageParser;
|
||||
private RemoteWipeManager.Observer observer;
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(RemoteWipeManager.class.getName());
|
||||
|
||||
@Inject
|
||||
protected RemoteWipeManagerImpl(
|
||||
DatabaseComponent db,
|
||||
ClientHelper clientHelper,
|
||||
MetadataParser metadataParser,
|
||||
MessageTracker messageTracker,
|
||||
Clock clock,
|
||||
MessageEncoder messageEncoder,
|
||||
MessageParser messageParser,
|
||||
ContactManager contactManager,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
ContactGroupFactory contactGroupFactory) {
|
||||
super(db, clientHelper, metadataParser, messageTracker);
|
||||
this.clock = clock;
|
||||
this.contactGroupFactory = contactGroupFactory;
|
||||
this.contactManager = contactManager;
|
||||
this.clientVersioningManager = clientVersioningManager;
|
||||
this.messageEncoder = messageEncoder;
|
||||
this.messageParser = messageParser;
|
||||
localGroup =
|
||||
contactGroupFactory.createLocalGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listenForPanic(RemoteWipeManager.Observer observer) {
|
||||
this.observer = observer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatabaseOpened(Transaction txn) throws DbException {
|
||||
if (db.containsGroup(txn, localGroup.getId())) return;
|
||||
db.addGroup(txn, localGroup);
|
||||
// Set things up for any pre-existing contacts
|
||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||
}
|
||||
|
||||
private void setContactId(Transaction txn, GroupId g, ContactId c)
|
||||
throws DbException {
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
d.put(GROUP_KEY_CONTACT_ID, c.getInt());
|
||||
try {
|
||||
clientHelper.mergeGroupMetadata(txn, g, d);
|
||||
} catch (FormatException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean incomingMessage(Transaction txn, Message m, BdfList body,
|
||||
BdfDictionary meta) throws DbException, FormatException {
|
||||
LOG.info("Incoming remote wipe message");
|
||||
MessageType type = MessageType
|
||||
.fromValue(body.getLong(0).intValue());
|
||||
if (type == SETUP) {
|
||||
messageTracker.trackIncomingMessage(txn, m);
|
||||
ContactId contactId = getContactId(txn, m.getGroupId());
|
||||
|
||||
MessageStatus status = db.getMessageStatus(txn, contactId,
|
||||
m.getId());
|
||||
txn.attach(new RemoteWipeReceivedEvent(
|
||||
createMessageHeader(m, meta, status, type), contactId));
|
||||
|
||||
// Update our local record
|
||||
BdfDictionary localRecord = new BdfDictionary();
|
||||
localRecord.put(GROUP_KEY_AM_WIPER, true);
|
||||
|
||||
if (!db.containsGroup(txn, localGroup.getId()))
|
||||
db.addGroup(txn, localGroup);
|
||||
clientHelper
|
||||
.mergeGroupMetadata(txn, localGroup.getId(), localRecord);
|
||||
} else if (type == WIPE) {
|
||||
if (!remoteWipeIsSetup(txn)) return false;
|
||||
if (clock.currentTimeMillis() - m.getTimestamp() > MAX_MESSAGE_AGE)
|
||||
return false;
|
||||
|
||||
ContactId contactId = getContactId(txn, m.getGroupId());
|
||||
// Check if contact is in list of wipers
|
||||
if (isWiper(txn, contactId)) {
|
||||
LOG.info("Got a valid wipe message from a wiper");
|
||||
|
||||
BdfDictionary existingMeta =
|
||||
clientHelper.getGroupMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
BdfList receivedWipeMessages =
|
||||
existingMeta.getOptionalList(GROUP_KEY_RECEIVED_WIPE);
|
||||
|
||||
if (receivedWipeMessages == null)
|
||||
receivedWipeMessages = new BdfList();
|
||||
|
||||
// Traverse the list backwards to avoid problems when removing items
|
||||
for (int i = receivedWipeMessages.size() - 1; i >= 0; --i) {
|
||||
BdfList receivedWipeMessage =
|
||||
receivedWipeMessages.getList(i);
|
||||
|
||||
long timestamp = receivedWipeMessage.getLong(1);
|
||||
LOG.info("Message age: " +
|
||||
(clock.currentTimeMillis() - timestamp));
|
||||
// Filter the messages for old ones
|
||||
if (clock.currentTimeMillis() - timestamp >
|
||||
MAX_MESSAGE_AGE) {
|
||||
LOG.info("Removing outdated wipe message");
|
||||
receivedWipeMessages.remove(i);
|
||||
} else if (receivedWipeMessage.getLong(0).intValue() ==
|
||||
contactId.getInt()) {
|
||||
|
||||
// If we already have one from this contact, ignore
|
||||
LOG.info(
|
||||
"Duplicate wipe message received - ignoring");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (receivedWipeMessages.size() + 1 == THRESHOLD) {
|
||||
LOG.warning("Threshold number of remote wipe signals reached - panic!");
|
||||
|
||||
// Send a CONFIRM message to each wiper
|
||||
// sendConfirmMessages(txn);
|
||||
|
||||
if (observer != null) {
|
||||
observer.onPanic();
|
||||
}
|
||||
txn.attach(new RemoteWipeActivatedEvent());
|
||||
} else {
|
||||
BdfList newReceivedWipeMessage = new BdfList();
|
||||
newReceivedWipeMessage.add(contactId.getInt());
|
||||
newReceivedWipeMessage.add(m.getTimestamp());
|
||||
receivedWipeMessages.add(newReceivedWipeMessage);
|
||||
BdfDictionary newMeta = new BdfDictionary();
|
||||
newMeta.put(GROUP_KEY_RECEIVED_WIPE, receivedWipeMessages);
|
||||
clientHelper.mergeGroupMetadata(txn, localGroup.getId(),
|
||||
newMeta);
|
||||
}
|
||||
}
|
||||
} else if (type == REVOKE) {
|
||||
messageTracker.trackIncomingMessage(txn, m);
|
||||
ContactId contactId = getContactId(txn, m.getGroupId());
|
||||
|
||||
MessageStatus status = db.getMessageStatus(txn, contactId,
|
||||
m.getId());
|
||||
txn.attach(new RemoteWipeReceivedEvent(
|
||||
createMessageHeader(m, meta, status, type), contactId));
|
||||
|
||||
// Update our local record
|
||||
BdfDictionary localRecord = new BdfDictionary();
|
||||
localRecord.put(GROUP_KEY_AM_WIPER, false);
|
||||
|
||||
if (!db.containsGroup(txn, localGroup.getId()))
|
||||
db.addGroup(txn, localGroup);
|
||||
clientHelper
|
||||
.mergeGroupMetadata(txn, localGroup.getId(), localRecord);
|
||||
} else if (type == CONFIRM) {
|
||||
messageTracker.trackIncomingMessage(txn, m);
|
||||
ContactId contactId = getContactId(txn, m.getGroupId());
|
||||
|
||||
MessageStatus status = db.getMessageStatus(txn, contactId,
|
||||
m.getId());
|
||||
txn.attach(new RemoteWipeReceivedEvent(
|
||||
createMessageHeader(m, meta, status, type), contactId));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isInList(Transaction txn, Author a, List<ContactId> wipers)
|
||||
throws DbException {
|
||||
for (ContactId c : wipers) {
|
||||
if (contactManager.getContact(txn, c).getAuthor().equals(a))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setup(Transaction txn, List<ContactId> wipers)
|
||||
throws DbException, FormatException {
|
||||
if (remoteWipeIsSetup(txn)) {
|
||||
// Revoke existing wipers who are not present in the new list
|
||||
List<Author> existingWipers = getWipers(txn);
|
||||
for (Author existingWiper : existingWipers) {
|
||||
if (!isInList(txn, existingWiper, wipers)) {
|
||||
LOG.info("Revoking an existing wiper");
|
||||
sendRevokeMessage(txn, contactManager.getContact(txn,
|
||||
authorToContactId(txn, existingWiper)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wipers.size() < 2) throw new FormatException();
|
||||
|
||||
BdfList wipersMetadata = new BdfList();
|
||||
|
||||
for (ContactId c : wipers) {
|
||||
Contact contact = contactManager.getContact(txn, c);
|
||||
sendSetupMessage(txn, contact);
|
||||
wipersMetadata.add(clientHelper.toList(contact.getAuthor()));
|
||||
}
|
||||
|
||||
LOG.info("All remote wipe setup messages sent");
|
||||
|
||||
// Make a record of this locally
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(GROUP_KEY_WIPERS, wipersMetadata);
|
||||
|
||||
if (!db.containsGroup(txn, localGroup.getId()))
|
||||
db.addGroup(txn, localGroup);
|
||||
clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta);
|
||||
}
|
||||
|
||||
private void sendSetupMessage(Transaction txn, Contact contact)
|
||||
throws DbException, FormatException {
|
||||
Group group = getContactGroup(contact);
|
||||
GroupId g = group.getId();
|
||||
if (!db.containsGroup(txn, g)) db.addGroup(txn, group);
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
|
||||
byte[] body = messageEncoder.encodeSetupMessage();
|
||||
|
||||
Message m = clientHelper.createMessage(g, timestamp, body);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, SETUP.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true),
|
||||
new BdfEntry(MSG_KEY_TIMESTAMP, timestamp)
|
||||
);
|
||||
clientHelper.addLocalMessage(txn, m, meta, true, false);
|
||||
messageTracker.trackOutgoingMessage(txn, m);
|
||||
}
|
||||
|
||||
private void sendRevokeMessage(Transaction txn, Contact contact)
|
||||
throws DbException, FormatException {
|
||||
Group group = getContactGroup(contact);
|
||||
GroupId g = group.getId();
|
||||
if (!db.containsGroup(txn, g)) db.addGroup(txn, group);
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
|
||||
byte[] body = messageEncoder.encodeRevokeMessage();
|
||||
|
||||
Message m = clientHelper.createMessage(g, timestamp, body);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, REVOKE.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true),
|
||||
new BdfEntry(MSG_KEY_TIMESTAMP, timestamp)
|
||||
);
|
||||
clientHelper.addLocalMessage(txn, m, meta, true, false);
|
||||
messageTracker.trackOutgoingMessage(txn, m);
|
||||
}
|
||||
|
||||
public int sendConfirmMessages(Transaction txn)
|
||||
throws DbException, FormatException {
|
||||
List<ContactId> wipers = getWiperContactIds(txn);
|
||||
for (ContactId c : wipers) {
|
||||
Contact contact = contactManager.getContact(txn, c);
|
||||
sendConfirmMessage(txn, contact);
|
||||
}
|
||||
return wipers.size();
|
||||
}
|
||||
|
||||
private void sendConfirmMessage(Transaction txn, Contact contact)
|
||||
throws DbException, FormatException {
|
||||
Group group = getContactGroup(contact);
|
||||
GroupId g = group.getId();
|
||||
if (!db.containsGroup(txn, g)) db.addGroup(txn, group);
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
|
||||
byte[] body = messageEncoder.encodeConfirmMessage();
|
||||
|
||||
Message m = clientHelper.createMessage(g, timestamp, body);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, CONFIRM.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true),
|
||||
new BdfEntry(MSG_KEY_TIMESTAMP, timestamp)
|
||||
);
|
||||
clientHelper.addLocalMessage(txn, m, meta, true, false);
|
||||
messageTracker.trackOutgoingMessage(txn, m);
|
||||
}
|
||||
|
||||
public void wipe(Transaction txn, Contact contact)
|
||||
throws DbException, FormatException {
|
||||
// Check that we have wiper status
|
||||
if (!amWiper(txn, contact.getId())) throw new DbException();
|
||||
|
||||
Group group = getContactGroup(contact);
|
||||
GroupId g = group.getId();
|
||||
if (!db.containsGroup(txn, g)) db.addGroup(txn, group);
|
||||
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
|
||||
byte[] body = messageEncoder.encodeWipeMessage();
|
||||
|
||||
Message m = clientHelper.createMessage(g, timestamp, body);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_TIMESTAMP, timestamp),
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, WIPE.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true)
|
||||
);
|
||||
clientHelper.addLocalMessage(txn, m, meta, true, false);
|
||||
messageTracker.trackOutgoingMessage(txn, m);
|
||||
}
|
||||
|
||||
public boolean isWiper(Transaction txn, ContactId contactId) {
|
||||
try {
|
||||
Author author =
|
||||
contactManager.getContact(txn, contactId).getAuthor();
|
||||
List<Author> currentWipers = getWipers(txn);
|
||||
for (Author a : currentWipers) {
|
||||
if (a.getId().equals(author.getId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (DbException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean amWiper(Transaction txn, ContactId contactId) {
|
||||
try {
|
||||
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
return meta.getBoolean(GROUP_KEY_AM_WIPER, false);
|
||||
} catch (DbException | FormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void revoke(Transaction txn, ContactId contactId)
|
||||
throws DbException, FormatException {
|
||||
// Revoke a contact's wiper status
|
||||
Contact contactToRevoke = contactManager.getContact(txn, contactId);
|
||||
Author authorToRevoke = contactToRevoke.getAuthor();
|
||||
|
||||
List<Author> currentWipers = getWipers(txn);
|
||||
BdfList newWipers = new BdfList();
|
||||
|
||||
for (Author a : currentWipers) {
|
||||
if (a.getId().equals(authorToRevoke.getId())) {
|
||||
sendRevokeMessage(txn, contactToRevoke);
|
||||
} else {
|
||||
newWipers.add(clientHelper.toList(a));
|
||||
}
|
||||
}
|
||||
// If we revoked someone, update our list
|
||||
if (newWipers.size() < currentWipers.size()) {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(GROUP_KEY_WIPERS, newWipers);
|
||||
|
||||
if (!db.containsGroup(txn, localGroup.getId()))
|
||||
db.addGroup(txn, localGroup);
|
||||
clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta);
|
||||
}
|
||||
}
|
||||
|
||||
public void revokeAll(Transaction txn) throws DbException, FormatException {
|
||||
List<ContactId> currentWipers = getWiperContactIds(txn);
|
||||
for (ContactId c : currentWipers) {
|
||||
sendRevokeMessage(txn, db.getContact(txn, c));
|
||||
}
|
||||
|
||||
BdfList noWipers = new BdfList();
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(GROUP_KEY_WIPERS, noWipers);
|
||||
|
||||
if (!db.containsGroup(txn, localGroup.getId()))
|
||||
db.addGroup(txn, localGroup);
|
||||
clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group getContactGroup(Contact c) {
|
||||
return contactGroupFactory.createContactGroup(CLIENT_ID,
|
||||
MAJOR_VERSION, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ConversationMessageHeader> getMessageHeaders(
|
||||
Transaction txn, ContactId contactId) throws DbException {
|
||||
try {
|
||||
Contact contact = db.getContact(txn, contactId);
|
||||
GroupId contactGroupId = getContactGroup(contact).getId();
|
||||
Map<MessageId, BdfDictionary> messages = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, contactGroupId);
|
||||
List<ConversationMessageHeader> headers =
|
||||
new ArrayList<>();
|
||||
for (Map.Entry<MessageId, BdfDictionary> messageEntry : messages
|
||||
.entrySet()) {
|
||||
BdfDictionary meta = messageEntry.getValue();
|
||||
if (meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue() ==
|
||||
SETUP.getValue()) {
|
||||
Message message = clientHelper
|
||||
.getMessage(txn, messageEntry.getKey());
|
||||
MessageStatus status = db.getMessageStatus(txn, contactId,
|
||||
messageEntry.getKey());
|
||||
headers.add(
|
||||
createMessageHeader(message, meta, status, SETUP));
|
||||
} else if (meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue() ==
|
||||
WIPE.getValue()) {
|
||||
Message message = clientHelper
|
||||
.getMessage(txn, messageEntry.getKey());
|
||||
MessageStatus status = db.getMessageStatus(txn, contactId,
|
||||
messageEntry.getKey());
|
||||
if (meta.getBoolean(MSG_KEY_LOCAL)) {
|
||||
headers.add(
|
||||
createMessageHeader(message, meta, status,
|
||||
WIPE));
|
||||
}
|
||||
} else if (meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue() ==
|
||||
REVOKE.getValue()) {
|
||||
Message message = clientHelper
|
||||
.getMessage(txn, messageEntry.getKey());
|
||||
MessageStatus status = db.getMessageStatus(txn, contactId,
|
||||
messageEntry.getKey());
|
||||
headers.add(
|
||||
createMessageHeader(message, meta, status, REVOKE));
|
||||
} else if (meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue() ==
|
||||
CONFIRM.getValue()) {
|
||||
Message message = clientHelper
|
||||
.getMessage(txn, messageEntry.getKey());
|
||||
MessageStatus status = db.getMessageStatus(txn, contactId,
|
||||
messageEntry.getKey());
|
||||
headers.add(
|
||||
createMessageHeader(message, meta, status, CONFIRM));
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private RemoteWipeMessageHeader createMessageHeader(
|
||||
Message message, BdfDictionary meta, MessageStatus status,
|
||||
MessageType type
|
||||
)
|
||||
throws FormatException {
|
||||
|
||||
boolean isLocal = meta.getBoolean(MSG_KEY_LOCAL);
|
||||
boolean read = meta.getBoolean(MSG_KEY_READ, false);
|
||||
long timestamp;
|
||||
if (isLocal) {
|
||||
timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
|
||||
} else {
|
||||
timestamp = message.getTimestamp();
|
||||
}
|
||||
List<AttachmentHeader> attachmentHeaders =
|
||||
new ArrayList<>();
|
||||
return new RemoteWipeMessageHeader(
|
||||
message.getId(), message.getGroupId(), timestamp,
|
||||
isLocal, read, status.isSent(), status.isSeen(),
|
||||
attachmentHeaders, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MessageId> getMessageIds(Transaction txn, ContactId contactId)
|
||||
throws DbException {
|
||||
Contact contact = db.getContact(txn, contactId);
|
||||
GroupId contactGroupId = getContactGroup(contact).getId();
|
||||
try {
|
||||
Map<MessageId, BdfDictionary> messages = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, contactGroupId);
|
||||
return messages.keySet();
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeletionResult deleteAllMessages(Transaction txn, ContactId c)
|
||||
throws DbException {
|
||||
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
|
||||
for (MessageId messageId : db.getMessageIds(txn, g)) {
|
||||
db.deleteMessage(txn, messageId);
|
||||
db.deleteMessageMetadata(txn, messageId);
|
||||
}
|
||||
messageTracker.initializeGroupCount(txn, g);
|
||||
return new DeletionResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeletionResult deleteMessages(Transaction txn, ContactId c,
|
||||
Set<MessageId> messageIds) throws DbException {
|
||||
for (MessageId m : messageIds) {
|
||||
db.deleteMessage(txn, m);
|
||||
db.deleteMessageMetadata(txn, m);
|
||||
}
|
||||
return new DeletionResult();
|
||||
}
|
||||
|
||||
private ContactId getContactId(Transaction txn, GroupId g)
|
||||
throws DbException {
|
||||
try {
|
||||
BdfDictionary meta =
|
||||
clientHelper.getGroupMetadataAsDictionary(txn, g);
|
||||
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientVisibilityChanging(Transaction txn, Contact c,
|
||||
Group.Visibility v) throws DbException {
|
||||
// Apply the client's visibility to the contact group
|
||||
Group g = getContactGroup(c);
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addingContact(Transaction txn, Contact c) throws DbException {
|
||||
// Create a group to share with the contact
|
||||
Group g = getContactGroup(c);
|
||||
db.addGroup(txn, g);
|
||||
// Apply the client's visibility to the contact group
|
||||
Group.Visibility client =
|
||||
clientVersioningManager.getClientVisibility(txn,
|
||||
c.getId(), CLIENT_ID, MAJOR_VERSION);
|
||||
db.setGroupVisibility(txn, c.getId(), g.getId(), client);
|
||||
// Attach the contact ID to the group
|
||||
setContactId(txn, g.getId(), c.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removingContact(Transaction txn, Contact c) throws DbException {
|
||||
db.removeGroup(txn, getContactGroup(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remoteWipeIsSetup(Transaction txn) {
|
||||
try {
|
||||
return getWipers(txn).size() > 0;
|
||||
} catch (DbException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Author> getWipers(Transaction txn) throws DbException {
|
||||
try {
|
||||
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
BdfList bdfWipers = meta.getList(GROUP_KEY_WIPERS);
|
||||
|
||||
List<Author> wipers = new ArrayList<>(bdfWipers.size());
|
||||
for (int i = 0; i < bdfWipers.size(); i++) {
|
||||
BdfList author = bdfWipers.getList(i);
|
||||
wipers.add(clientHelper.parseAndValidateAuthor(author));
|
||||
}
|
||||
return wipers;
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ContactId> getWiperContactIds(Transaction txn) {
|
||||
ArrayList<ContactId> wiperContactIds = new ArrayList<>();
|
||||
try {
|
||||
List<Author> wipers = getWipers(txn);
|
||||
for (Author wiper : wipers) {
|
||||
wiperContactIds.add(authorToContactId(txn, wiper));
|
||||
}
|
||||
} catch (DbException ignored) {
|
||||
// Will return an empty list
|
||||
}
|
||||
return wiperContactIds;
|
||||
}
|
||||
|
||||
private ContactId authorToContactId(Transaction txn, Author author)
|
||||
throws DbException {
|
||||
ArrayList<Contact> contacts =
|
||||
(ArrayList<Contact>) contactManager.getContacts(txn);
|
||||
for (Contact c : contacts) {
|
||||
if (c.getAuthor().equals(author)) return c.getId();
|
||||
}
|
||||
throw new DbException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.briarproject.briar.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.remotewipe.MessageEncoder;
|
||||
import org.briarproject.briar.api.remotewipe.MessageParser;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeManager.CLIENT_ID;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeManager.MAJOR_VERSION;
|
||||
import static org.briarproject.briar.api.remotewipe.RemoteWipeManager.MINOR_VERSION;
|
||||
|
||||
@Module
|
||||
public class RemoteWipeModule {
|
||||
public static class EagerSingletons {
|
||||
@Inject
|
||||
RemoteWipeManager remoteWipeManager;
|
||||
@Inject
|
||||
RemoteWipeValidator remoteWipeValidator;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
RemoteWipeManager remoteWipeManager(
|
||||
LifecycleManager lifecycleManager,
|
||||
ValidationManager validationManager,
|
||||
ConversationManager conversationManager,
|
||||
ContactManager contactManager,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
RemoteWipeManagerImpl remoteWipeManager) {
|
||||
lifecycleManager.registerOpenDatabaseHook(remoteWipeManager);
|
||||
validationManager
|
||||
.registerIncomingMessageHook(RemoteWipeManager.CLIENT_ID,
|
||||
RemoteWipeManager.MAJOR_VERSION, remoteWipeManager);
|
||||
|
||||
contactManager.registerContactHook(remoteWipeManager);
|
||||
clientVersioningManager.registerClient(CLIENT_ID, MAJOR_VERSION,
|
||||
MINOR_VERSION, remoteWipeManager);
|
||||
conversationManager.registerConversationClient(remoteWipeManager);
|
||||
return remoteWipeManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
RemoteWipeValidator remoteWipeValidator(
|
||||
ValidationManager validationManager,
|
||||
ClientHelper clientHelper,
|
||||
MetadataEncoder metadataEncoder,
|
||||
Clock clock) {
|
||||
RemoteWipeValidator validator =
|
||||
new RemoteWipeValidator(clientHelper, metadataEncoder, clock);
|
||||
validationManager.registerMessageValidator(CLIENT_ID, MAJOR_VERSION,
|
||||
validator);
|
||||
return validator;
|
||||
}
|
||||
|
||||
@Provides
|
||||
MessageEncoder messageEncoder(MessageEncoderImpl messageEncoder) {
|
||||
return messageEncoder;
|
||||
}
|
||||
|
||||
@Provides
|
||||
MessageParser messageParser(MessageParserImpl messageParser) {
|
||||
return messageParser;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.briarproject.briar.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.client.BdfMessageContext;
|
||||
import org.briarproject.bramble.api.client.BdfMessageValidator;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfEntry;
|
||||
import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.CONFIRM;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.REVOKE;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.SETUP;
|
||||
import static org.briarproject.briar.api.remotewipe.MessageType.WIPE;
|
||||
import static org.briarproject.briar.socialbackup.SocialBackupConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.briar.socialbackup.SocialBackupConstants.MSG_KEY_MESSAGE_TYPE;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class RemoteWipeValidator extends BdfMessageValidator {
|
||||
|
||||
@Inject
|
||||
RemoteWipeValidator(ClientHelper clientHelper,
|
||||
MetadataEncoder metadataEncoder, Clock clock) {
|
||||
super(clientHelper, metadataEncoder, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||
BdfList body) throws FormatException {
|
||||
org.briarproject.briar.api.remotewipe.MessageType
|
||||
type = org.briarproject.briar.api.remotewipe.MessageType
|
||||
.fromValue(body.getLong(0).intValue());
|
||||
if (type == SETUP) return validateSetupMessage(body);
|
||||
else if (type == WIPE) return validateWipeMessage(body);
|
||||
else if (type == REVOKE) return validateRevokeMessage(body);
|
||||
else if (type == CONFIRM) return validateConfirmMessage(body);
|
||||
else throw new AssertionError();
|
||||
}
|
||||
|
||||
private BdfMessageContext validateSetupMessage(BdfList body)
|
||||
throws FormatException {
|
||||
checkSize(body, 1);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, SETUP.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
|
||||
private BdfMessageContext validateWipeMessage(BdfList body)
|
||||
throws FormatException {
|
||||
checkSize(body, 1);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, WIPE.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
|
||||
private BdfMessageContext validateRevokeMessage(BdfList body)
|
||||
throws FormatException {
|
||||
checkSize(body, 1);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, REVOKE.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
|
||||
private BdfMessageContext validateConfirmMessage(BdfList body)
|
||||
throws FormatException {
|
||||
checkSize(body, 1);
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_MESSAGE_TYPE, CONFIRM.getValue()),
|
||||
new BdfEntry(MSG_KEY_LOCAL, false));
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
}
|
||||
@@ -268,6 +268,7 @@ class SocialBackupManagerImpl extends ConversationClientImpl
|
||||
try {
|
||||
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
|
||||
return backupMetadataParser.parseBackupMetadata(meta);
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
package org.briarproject.briar.remotewipe;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.test.TestDatabaseConfigModule;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
|
||||
import org.briarproject.briar.test.BriarIntegrationTest;
|
||||
import org.briarproject.briar.test.BriarIntegrationTestComponent;
|
||||
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class RemoteWipeIntegrationTest extends BriarIntegrationTest<BriarIntegrationTestComponent> implements RemoteWipeManager.Observer {
|
||||
|
||||
private RemoteWipeManager remoteWipeManager0;
|
||||
private RemoteWipeManager remoteWipeManager1;
|
||||
private RemoteWipeManager remoteWipeManager2;
|
||||
|
||||
private Group g1From0;
|
||||
private Group g0From1;
|
||||
private Group g2From0;
|
||||
private Group g0From2;
|
||||
|
||||
private boolean panicCalled = false;
|
||||
|
||||
@Before
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
remoteWipeManager0 = c0.getRemoteWipeManager();
|
||||
remoteWipeManager1 = c1.getRemoteWipeManager();
|
||||
remoteWipeManager2 = c2.getRemoteWipeManager();
|
||||
|
||||
g1From0 = remoteWipeManager0.getContactGroup(contact1From0);
|
||||
g0From1 = remoteWipeManager1.getContactGroup(contact0From1);
|
||||
g2From0 = remoteWipeManager0.getContactGroup(contact2From0);
|
||||
g0From2 = remoteWipeManager2.getContactGroup(contact0From2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createComponents() {
|
||||
BriarIntegrationTestComponent component =
|
||||
DaggerBriarIntegrationTestComponent.builder().build();
|
||||
BriarIntegrationTestComponent.Helper.injectEagerSingletons(component);
|
||||
component.inject(this);
|
||||
|
||||
c0 = DaggerBriarIntegrationTestComponent.builder()
|
||||
.testDatabaseConfigModule(new TestDatabaseConfigModule(t0Dir))
|
||||
.build();
|
||||
BriarIntegrationTestComponent.Helper.injectEagerSingletons(c0);
|
||||
|
||||
c1 = DaggerBriarIntegrationTestComponent.builder()
|
||||
.testDatabaseConfigModule(new TestDatabaseConfigModule(t1Dir))
|
||||
.build();
|
||||
BriarIntegrationTestComponent.Helper.injectEagerSingletons(c1);
|
||||
|
||||
c2 = DaggerBriarIntegrationTestComponent.builder()
|
||||
.testDatabaseConfigModule(new TestDatabaseConfigModule(t2Dir))
|
||||
.build();
|
||||
BriarIntegrationTestComponent.Helper.injectEagerSingletons(c2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteWipe() throws Exception {
|
||||
remoteWipeManager0.listenForPanic(this);
|
||||
db0.transaction(false, txn -> {
|
||||
// Assert that we do not already have a wipe setup
|
||||
assertFalse(remoteWipeManager0.remoteWipeIsSetup(txn));
|
||||
remoteWipeManager0.setup(txn,
|
||||
asList(contactId1From0, contactId2From0));
|
||||
// Now check that we do have a wipe setup
|
||||
assertTrue(remoteWipeManager0.remoteWipeIsSetup(txn));
|
||||
});
|
||||
// Sync the setup messages to the contacts
|
||||
sync0To1(1, true);
|
||||
sync0To2(1, true);
|
||||
|
||||
// The setup message from 0 should have arrived at 1
|
||||
Collection<ConversationMessageHeader> messages0At1 =
|
||||
getMessages0At1();
|
||||
assertEquals(1, messages0At1.size());
|
||||
|
||||
Collection<ConversationMessageHeader> messages0At2 =
|
||||
getMessages0At2();
|
||||
assertEquals(1, messages0At2.size());
|
||||
|
||||
for (ConversationMessageHeader h : messages0At1) {
|
||||
assertTrue(h instanceof RemoteWipeMessageHeader);
|
||||
RemoteWipeMessageHeader r = (RemoteWipeMessageHeader) h;
|
||||
assertFalse(r.isLocal());
|
||||
}
|
||||
|
||||
// The wipers check that they are now wipers
|
||||
db1.transaction(false, txn -> {
|
||||
assertTrue(remoteWipeManager1.amWiper(txn, contactId0From1));
|
||||
remoteWipeManager1.wipe(txn, contact0From1);
|
||||
});
|
||||
|
||||
db2.transaction(false, txn -> {
|
||||
assertTrue(remoteWipeManager2.amWiper(txn, contactId0From2));
|
||||
remoteWipeManager2.wipe(txn, contact0From2);
|
||||
});
|
||||
|
||||
// Sync the wipe messages to the wipee
|
||||
sync1To0(1, true);
|
||||
sync2To0(1, true);
|
||||
|
||||
Collection<ConversationMessageHeader> messages1At0 =
|
||||
getMessages1At0();
|
||||
assertEquals(1, messages1At0.size());
|
||||
|
||||
Collection<ConversationMessageHeader> messages2At0 =
|
||||
getMessages2At0();
|
||||
assertEquals(1, messages2At0.size());
|
||||
|
||||
assertTrue(panicCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteWipeFailsOnDuplicateMessage() throws Exception {
|
||||
remoteWipeManager0.listenForPanic(this);
|
||||
db0.transaction(false, txn -> {
|
||||
// Assert that we do not already have a wipe setup
|
||||
assertFalse(remoteWipeManager0.remoteWipeIsSetup(txn));
|
||||
remoteWipeManager0.setup(txn,
|
||||
asList(contactId1From0, contactId2From0));
|
||||
// Now check that we do have a wipe setup
|
||||
assertTrue(remoteWipeManager0.remoteWipeIsSetup(txn));
|
||||
});
|
||||
// Sync the setup messages to the contacts
|
||||
sync0To1(1, true);
|
||||
sync0To2(1, true);
|
||||
|
||||
// The setup message from 0 should have arrived at 1
|
||||
Collection<ConversationMessageHeader> messages0At1 =
|
||||
getMessages0At1();
|
||||
assertEquals(1, messages0At1.size());
|
||||
|
||||
Collection<ConversationMessageHeader> messages0At2 =
|
||||
getMessages0At2();
|
||||
assertEquals(1, messages0At2.size());
|
||||
|
||||
for (ConversationMessageHeader h : messages0At1) {
|
||||
assertTrue(h instanceof RemoteWipeMessageHeader);
|
||||
RemoteWipeMessageHeader r = (RemoteWipeMessageHeader) h;
|
||||
assertFalse(r.isLocal());
|
||||
}
|
||||
|
||||
// The wipers check that they are now wipers
|
||||
db1.transaction(false, txn -> {
|
||||
assertTrue(remoteWipeManager1.amWiper(txn, contactId0From1));
|
||||
remoteWipeManager1.wipe(txn, contact0From1);
|
||||
Thread.sleep(100);
|
||||
remoteWipeManager1.wipe(txn, contact0From1);
|
||||
});
|
||||
|
||||
db2.transaction(false, txn -> {
|
||||
assertTrue(remoteWipeManager2.amWiper(txn, contactId0From2));
|
||||
// remoteWipeManager2.wipe(txn, contact0From2);
|
||||
});
|
||||
|
||||
// Sync the wipe messages to the wipee
|
||||
sync1To0(2, true);
|
||||
// sync2To0(1, true);
|
||||
|
||||
Collection<ConversationMessageHeader> messages1At0 =
|
||||
getMessages1At0();
|
||||
assertEquals(1, messages1At0.size());
|
||||
|
||||
Collection<ConversationMessageHeader> messages2At0 =
|
||||
getMessages2At0();
|
||||
assertEquals(1, messages2At0.size());
|
||||
|
||||
assertFalse(panicCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoteWipeWithRevoke() throws Exception {
|
||||
remoteWipeManager0.listenForPanic(this);
|
||||
db0.transaction(false, txn -> {
|
||||
// Assert that we do not already have a wipe setup
|
||||
assertFalse(remoteWipeManager0.remoteWipeIsSetup(txn));
|
||||
remoteWipeManager0.setup(txn,
|
||||
asList(contactId1From0, contactId2From0));
|
||||
// Now check that we do have a wipe setup
|
||||
assertTrue(remoteWipeManager0.remoteWipeIsSetup(txn));
|
||||
// Check we have 2 wipers
|
||||
assertEquals(remoteWipeManager0.getWipers(txn).size(), 2);
|
||||
});
|
||||
// Sync the setup messages to the contacts
|
||||
sync0To1(1, true);
|
||||
sync0To2(1, true);
|
||||
|
||||
// The setup message from 0 should have arrived at 1
|
||||
Collection<ConversationMessageHeader> messages0At1 =
|
||||
getMessages0At1();
|
||||
assertEquals(1, messages0At1.size());
|
||||
|
||||
Collection<ConversationMessageHeader> messages0At2 =
|
||||
getMessages0At2();
|
||||
assertEquals(1, messages0At2.size());
|
||||
|
||||
for (ConversationMessageHeader h : messages0At1) {
|
||||
assertTrue(h instanceof RemoteWipeMessageHeader);
|
||||
RemoteWipeMessageHeader r = (RemoteWipeMessageHeader) h;
|
||||
assertFalse(r.isLocal());
|
||||
}
|
||||
|
||||
// Revoke contact 1's wiper status
|
||||
db0.transaction(false, txn -> {
|
||||
remoteWipeManager0.revoke(txn, contactId1From0);
|
||||
// Check we now only have one wiper
|
||||
assertEquals(remoteWipeManager0.getWipers(txn).size(), 1);
|
||||
});
|
||||
|
||||
|
||||
// Sync the revoke message
|
||||
sync0To1(1, true);
|
||||
|
||||
// The wipers check if they are now wipers
|
||||
db1.transaction(false, txn -> {
|
||||
assertFalse(remoteWipeManager1.amWiper(txn, contactId0From1));
|
||||
boolean cannotWipe = false;
|
||||
try {
|
||||
remoteWipeManager1.wipe(txn, contact0From1);
|
||||
} catch(DbException e) {
|
||||
cannotWipe = true;
|
||||
} finally {
|
||||
assertTrue(cannotWipe);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
private Collection<ConversationMessageHeader> getMessages1At0()
|
||||
throws DbException {
|
||||
return db0.transactionWithResult(true, txn -> remoteWipeManager0
|
||||
.getMessageHeaders(txn, contactId1From0));
|
||||
}
|
||||
|
||||
private Collection<ConversationMessageHeader> getMessages2At0()
|
||||
throws DbException {
|
||||
return db0.transactionWithResult(true, txn -> remoteWipeManager0
|
||||
.getMessageHeaders(txn, contactId2From0));
|
||||
}
|
||||
|
||||
private Collection<ConversationMessageHeader> getMessages0At1()
|
||||
throws DbException {
|
||||
return db1.transactionWithResult(true, txn -> remoteWipeManager1
|
||||
.getMessageHeaders(txn, contactId0From1));
|
||||
}
|
||||
|
||||
private Collection<ConversationMessageHeader> getMessages0At2()
|
||||
throws DbException {
|
||||
return db1.transactionWithResult(true, txn -> remoteWipeManager2
|
||||
.getMessageHeaders(txn, contactId0From2));
|
||||
}
|
||||
|
||||
public static void assertGroupCount(MessageTracker tracker, GroupId g,
|
||||
long msgCount, long unreadCount) throws DbException {
|
||||
MessageTracker.GroupCount c1 = tracker.getGroupCount(g);
|
||||
assertEquals(msgCount, c1.getMsgCount());
|
||||
assertEquals(unreadCount, c1.getUnreadCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPanic() {
|
||||
panicCalled = true;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
|
||||
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
|
||||
import org.briarproject.briar.avatar.AvatarModule;
|
||||
import org.briarproject.briar.blog.BlogModule;
|
||||
@@ -36,6 +37,7 @@ import org.briarproject.briar.introduction.IntroductionModule;
|
||||
import org.briarproject.briar.messaging.MessagingModule;
|
||||
import org.briarproject.briar.privategroup.PrivateGroupModule;
|
||||
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
|
||||
import org.briarproject.briar.remotewipe.RemoteWipeModule;
|
||||
import org.briarproject.briar.sharing.SharingModule;
|
||||
import org.briarproject.briar.socialbackup.DefaultDarkCrystalModule;
|
||||
import org.briarproject.briar.socialbackup.SocialBackupModule;
|
||||
@@ -76,6 +78,8 @@ public interface BriarIntegrationTestComponent
|
||||
|
||||
void inject(SocialBackupModule.EagerSingletons init);
|
||||
|
||||
void inject(RemoteWipeModule.EagerSingletons init);
|
||||
|
||||
LifecycleManager getLifecycleManager();
|
||||
|
||||
EventBus getEventBus();
|
||||
@@ -124,6 +128,8 @@ public interface BriarIntegrationTestComponent
|
||||
|
||||
SocialBackupManager getSocialBackupManager();
|
||||
|
||||
RemoteWipeManager getRemoteWipeManager();
|
||||
|
||||
class Helper {
|
||||
|
||||
public static void injectEagerSingletons(
|
||||
@@ -140,6 +146,7 @@ public interface BriarIntegrationTestComponent
|
||||
c.inject(new PrivateGroupModule.EagerSingletons());
|
||||
c.inject(new SharingModule.EagerSingletons());
|
||||
c.inject(new SocialBackupModule.EagerSingletons());
|
||||
c.inject(new RemoteWipeModule.EagerSingletons());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.github.ajalt.clikt.parameters.types.int
|
||||
import org.briarproject.bramble.BrambleCoreEagerSingletons
|
||||
import org.briarproject.briar.BriarCoreEagerSingletons
|
||||
import org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY
|
||||
import org.spongycastle.util.encoders.Base64.toBase64String
|
||||
import org.bouncycastle.util.encoders.Base64.toBase64String
|
||||
import java.io.File
|
||||
import java.io.File.separator
|
||||
import java.io.IOException
|
||||
|
||||
@@ -31,8 +31,8 @@ import org.briarproject.briar.headless.getFromJson
|
||||
import org.briarproject.briar.headless.json.JsonDict
|
||||
import org.eclipse.jetty.http.HttpStatus.BAD_REQUEST_400
|
||||
import org.eclipse.jetty.http.HttpStatus.FORBIDDEN_403
|
||||
import org.spongycastle.util.encoders.Base64
|
||||
import org.spongycastle.util.encoders.DecoderException
|
||||
import org.bouncycastle.util.encoders.Base64
|
||||
import org.bouncycastle.util.encoders.DecoderException
|
||||
import java.security.GeneralSecurityException
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -31,14 +31,15 @@ import org.briarproject.briar.api.messaging.PrivateMessageFactory
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest
|
||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse
|
||||
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader
|
||||
import org.briarproject.briar.api.socialbackup.ShardMessageHeader
|
||||
import org.briarproject.briar.headless.event.WebSocketController
|
||||
import org.briarproject.briar.headless.event.output
|
||||
import org.briarproject.briar.headless.getContactIdFromPathParam
|
||||
import org.briarproject.briar.headless.getFromJson
|
||||
import org.briarproject.briar.headless.json.JsonDict
|
||||
import org.spongycastle.util.encoders.Base64
|
||||
import org.spongycastle.util.encoders.DecoderException
|
||||
import org.bouncycastle.util.encoders.Base64
|
||||
import org.bouncycastle.util.encoders.DecoderException
|
||||
import java.util.concurrent.Executor
|
||||
import javax.annotation.concurrent.Immutable
|
||||
import javax.inject.Inject
|
||||
@@ -172,4 +173,6 @@ private class JsonVisitor(
|
||||
override fun visitIntroductionResponse(r: IntroductionResponse) = r.output(contactId)
|
||||
|
||||
override fun visitShardMessage(r: ShardMessageHeader) = r.output(contactId)
|
||||
|
||||
override fun visitRemoteWipeMessage(r: RemoteWipeMessageHeader) = r.output(contactId)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.briarproject.briar.headless.json.JsonDict
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.spongycastle.util.encoders.Base64
|
||||
import org.bouncycastle.util.encoders.Base64
|
||||
import kotlin.random.Random
|
||||
|
||||
internal class MessagingControllerImplTest : ControllerTest() {
|
||||
@@ -205,7 +205,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
|
||||
@Test
|
||||
fun markMessageRead() {
|
||||
mockkStatic("org.briarproject.briar.headless.RouterKt")
|
||||
mockkStatic("org.spongycastle.util.encoders.Base64")
|
||||
mockkStatic("org.bouncycastle.util.encoders.Base64")
|
||||
expectGetContact()
|
||||
|
||||
val messageIdString = message.id.bytes.toString()
|
||||
|
||||
@@ -29,10 +29,11 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||
classpath 'com.android.tools.build:gradle:4.2.2'
|
||||
classpath 'ru.vyarus:gradle-animalsniffer-plugin:1.5.0'
|
||||
classpath files('libs/gradle-witness.jar')
|
||||
}
|
||||
|
||||
// ext.dagger_version = "2.33"
|
||||
ext.junit_version = "4.12"
|
||||
ext.jmock_version = '2.12.0'
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
|
||||
Reference in New Issue
Block a user