mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Compare commits
104 Commits
release-1.
...
tor-probe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f840d25d9 | ||
|
|
389b2b5b8e | ||
|
|
78abfa3698 | ||
|
|
e47d41596a | ||
|
|
8cf54bcedb | ||
|
|
89d5145665 | ||
|
|
0706498b03 | ||
|
|
b296500e7a | ||
|
|
60a8b03344 | ||
|
|
ae16a93522 | ||
|
|
c9a2ff71ae | ||
|
|
16f4c60a56 | ||
|
|
76121eb871 | ||
|
|
47c91a96ae | ||
|
|
14befb957b | ||
|
|
b464fe1653 | ||
|
|
09c6f09805 | ||
|
|
a93093182d | ||
|
|
e776ee02b0 | ||
|
|
c0553ec11f | ||
|
|
75a871a2f8 | ||
|
|
d6d3d5acef | ||
|
|
a361a2613c | ||
|
|
b68dbd6a75 | ||
|
|
f1e89a3ff4 | ||
|
|
056c23167d | ||
|
|
79d5612645 | ||
|
|
a030f92275 | ||
|
|
b3615b4a77 | ||
|
|
8a15fb242a | ||
|
|
e3686186ee | ||
|
|
18ae388137 | ||
|
|
775031e893 | ||
|
|
9f91b91a4f | ||
|
|
280f3ba1fc | ||
|
|
66619fd3a4 | ||
|
|
c7eb0cbb6d | ||
|
|
1617a95bb9 | ||
|
|
6f54718756 | ||
|
|
ea749f2128 | ||
|
|
b4b0d3daa6 | ||
|
|
609c90f57e | ||
|
|
5cf68fa134 | ||
|
|
61c9c6b8eb | ||
|
|
e97608da40 | ||
|
|
0bb80b1a15 | ||
|
|
bda52ea548 | ||
|
|
cf033dc29d | ||
|
|
c12cedc371 | ||
|
|
4b5e9bd64f | ||
|
|
8d55911dab | ||
|
|
e381f83512 | ||
|
|
e4c7f13832 | ||
|
|
b089a204d3 | ||
|
|
85fcb34997 | ||
|
|
d6d132a9cf | ||
|
|
98d1ea7730 | ||
|
|
159fd34c0c | ||
|
|
9e7a387ea4 | ||
|
|
138e520e6c | ||
|
|
5783c1dfd8 | ||
|
|
348968018a | ||
|
|
33c509cd1f | ||
|
|
bea77151bd | ||
|
|
787e62345f | ||
|
|
48f6a3b91f | ||
|
|
a798e25bf2 | ||
|
|
31e4045cf7 | ||
|
|
5334a8c9ca | ||
|
|
d11f1d2805 | ||
|
|
0d1ebddcd2 | ||
|
|
6c296c1348 | ||
|
|
87701e5f07 | ||
|
|
3aae01d152 | ||
|
|
bc298ba68a | ||
|
|
2623eaa149 | ||
|
|
7359b6942a | ||
|
|
3bcc532b4b | ||
|
|
4d08c69779 | ||
|
|
a6cd8937f7 | ||
|
|
e8566906ef | ||
|
|
929102ed60 | ||
|
|
3b871f5932 | ||
|
|
b972d1fc13 | ||
|
|
ccbeee60a7 | ||
|
|
074b10e177 | ||
|
|
031516ccce | ||
|
|
7d2f1abb94 | ||
|
|
00b9c76bb8 | ||
|
|
4d9fab85cb | ||
|
|
bd2514a299 | ||
|
|
e795efc7fc | ||
|
|
6691d2164f | ||
|
|
a384450c36 | ||
|
|
b375e9873c | ||
|
|
cb30c3885a | ||
|
|
6ee81eb24c | ||
|
|
c14ebe82ce | ||
|
|
00e9f894b1 | ||
|
|
499c586a59 | ||
|
|
64f9ce7306 | ||
|
|
071d961ed1 | ||
|
|
cb9efc5fec | ||
|
|
f9e292f734 |
9
.idea/codeStyles/Project.xml
generated
9
.idea/codeStyles/Project.xml
generated
@@ -36,6 +36,9 @@
|
|||||||
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
|
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
|
||||||
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
|
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
|
||||||
</JavaCodeStyleSettings>
|
</JavaCodeStyleSettings>
|
||||||
|
<JetCodeStyleSettings>
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
</JetCodeStyleSettings>
|
||||||
<Objective-C-extensions>
|
<Objective-C-extensions>
|
||||||
<file>
|
<file>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
@@ -257,5 +260,11 @@
|
|||||||
</rules>
|
</rules>
|
||||||
</arrangement>
|
</arrangement>
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
|
<codeStyleSettings language="kotlin">
|
||||||
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
|
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
|
||||||
|
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
|
||||||
|
<option name="ENUM_CONSTANTS_WRAP" value="1" />
|
||||||
|
</codeStyleSettings>
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
||||||
20
.idea/runConfigurations/All_in_briar_headless.xml
generated
Normal file
20
.idea/runConfigurations/All_in_briar_headless.xml
generated
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="All in briar-headless" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true">
|
||||||
|
<module name="briar-headless" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
|
<option name="PACKAGE_NAME" value="" />
|
||||||
|
<option name="MAIN_CLASS_NAME" value="" />
|
||||||
|
<option name="METHOD_NAME" value="" />
|
||||||
|
<option name="TEST_OBJECT" value="package" />
|
||||||
|
<option name="VM_PARAMETERS" value="" />
|
||||||
|
<option name="PARAMETERS" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-headless" />
|
||||||
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
|
<value defaultName="singleModule" />
|
||||||
|
</option>
|
||||||
|
<patterns />
|
||||||
|
<method />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
3
.idea/runConfigurations/All_tests.xml
generated
3
.idea/runConfigurations/All_tests.xml
generated
@@ -24,6 +24,7 @@
|
|||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All in briar-headless" run_configuration_type="AndroidJUnit" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="bramble-android" />
|
<module name="bramble-android" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="bramble-api" />
|
<module name="bramble-api" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="bramble-core" />
|
<module name="bramble-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="bramble-java" />
|
<module name="bramble-java" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
|
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="briar-android" />
|
<module name="briar-android" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="briar-core" />
|
<module name="briar-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
3
.idea/runConfigurations/H2_Performance_Test.xml
generated
3
.idea/runConfigurations/H2_Performance_Test.xml
generated
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="bramble-core" />
|
<module name="bramble-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="" />
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<module name="bramble-core" />
|
<module name="bramble-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -11,12 +10,10 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="" />
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
<option name="ENV_VARIABLES" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
<envs />
|
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
17
.idea/runConfigurations/briar_headless.xml
generated
Normal file
17
.idea/runConfigurations/briar_headless.xml
generated
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="briar-headless" type="JetRunConfigurationType" factoryName="Kotlin" singleton="true">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
|
<option name="VM_PARAMETERS" value="" />
|
||||||
|
<option name="PROGRAM_PARAMETERS" value="-v" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
|
<option name="MAIN_CLASS_NAME" value="org.briarproject.briar.headless.MainKt" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
|
<module name="briar-headless" />
|
||||||
|
<envs />
|
||||||
|
<method>
|
||||||
|
<option name="Gradle.BeforeRunTask" enabled="true" tasks="jar" externalProjectPath="$PROJECT_DIR$/briar-headless" vmOptions="" scriptParameters="" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -3,14 +3,14 @@ apply plugin: 'witness'
|
|||||||
apply from: 'witness.gradle'
|
apply from: 'witness.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 27
|
compileSdkVersion 28
|
||||||
buildToolsVersion '27.0.3'
|
buildToolsVersion '28.0.3'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 10102
|
versionCode 10103
|
||||||
versionName "1.1.2"
|
versionName "1.1.3"
|
||||||
consumerProguardFiles 'proguard-rules.txt'
|
consumerProguardFiles 'proguard-rules.txt'
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
@@ -28,7 +28,7 @@ configurations {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
tor 'org.briarproject:tor-android:0.2.9.16@zip'
|
tor 'org.briarproject:tor-android:0.3.4.8@zip'
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import org.spongycastle.crypto.tls.Certificate;
|
||||||
|
import org.spongycastle.crypto.tls.CipherSuite;
|
||||||
|
import org.spongycastle.crypto.tls.DefaultTlsClient;
|
||||||
|
import org.spongycastle.crypto.tls.ServerOnlyTlsAuthentication;
|
||||||
|
import org.spongycastle.crypto.tls.TlsAuthentication;
|
||||||
|
import org.spongycastle.crypto.tls.TlsClientProtocol;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
|
|
||||||
|
public class TorProbe {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(TorProbe.class.getName());
|
||||||
|
|
||||||
|
private static final int READ_TIMEOUT = 10 * 1000;
|
||||||
|
|
||||||
|
// https://trac.torproject.org/projects/tor/wiki/org/projects/Tor/TLSHistory
|
||||||
|
private static final int SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA = 0xfeff;
|
||||||
|
|
||||||
|
// https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt#n347
|
||||||
|
private static final int[] TOR_CIPHER_SUITES = new int[] {
|
||||||
|
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
||||||
|
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
||||||
|
CipherSuite.TLS_RSA_WITH_RC4_128_MD5,
|
||||||
|
CipherSuite.TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
|
||||||
|
CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt#n412
|
||||||
|
private static final byte[] VERSIONS_CELL = new byte[] {
|
||||||
|
0x00, 0x00, // Circuit ID: 0
|
||||||
|
0x07, // Command: Versions
|
||||||
|
0x00, 0x06, // Payload length: 6 bytes
|
||||||
|
0x00, 0x03, 0x00, 0x04, 0x00, 0x05 // Supported versions: 3, 4, 5
|
||||||
|
};
|
||||||
|
|
||||||
|
public List<Integer> probe(String address, int port) throws IOException {
|
||||||
|
if (LOG.isLoggable(INFO))
|
||||||
|
LOG.info("Connecting to " + address + ":" + port);
|
||||||
|
Socket socket = new Socket(address, port);
|
||||||
|
LOG.info("Connected");
|
||||||
|
TlsClientProtocol client = new TlsClientProtocol(
|
||||||
|
socket.getInputStream(), socket.getOutputStream(),
|
||||||
|
new SecureRandom());
|
||||||
|
client.connect(new TorTlsClient());
|
||||||
|
LOG.info("TLS handshake succeeded");
|
||||||
|
socket.setSoTimeout(READ_TIMEOUT);
|
||||||
|
try {
|
||||||
|
// Send a versions cell
|
||||||
|
OutputStream out = client.getOutputStream();
|
||||||
|
out.write(VERSIONS_CELL);
|
||||||
|
out.flush();
|
||||||
|
LOG.info("Sent versions cell");
|
||||||
|
|
||||||
|
// Expect a versions cell in response
|
||||||
|
List<Integer> versions = new ArrayList<>();
|
||||||
|
DataInputStream in = new DataInputStream(client.getInputStream());
|
||||||
|
int circuitId = in.readUnsignedShort();
|
||||||
|
if (circuitId != 0)
|
||||||
|
throw new IOException("Unexpected circuit ID: " + circuitId);
|
||||||
|
int command = in.readUnsignedByte();
|
||||||
|
if (command != 7)
|
||||||
|
throw new IOException("Unexpected command: " + command);
|
||||||
|
int payloadLength = in.readUnsignedShort();
|
||||||
|
if (payloadLength == 0 || payloadLength % 2 != 0) {
|
||||||
|
throw new IOException("Invalid payload length: "
|
||||||
|
+ payloadLength);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < payloadLength / 2; i++) {
|
||||||
|
int version = in.readUnsignedShort();
|
||||||
|
versions.add(version);
|
||||||
|
}
|
||||||
|
if (LOG.isLoggable(INFO))
|
||||||
|
LOG.info("Supported versions: " + versions);
|
||||||
|
return versions;
|
||||||
|
} finally {
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
if (args.length != 2) {
|
||||||
|
System.err.println("Usage: TorProbe <address> <port>");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
String address = args[0];
|
||||||
|
int port = Integer.parseInt(args[1]);
|
||||||
|
new TorProbe().probe(address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TorTlsClient extends DefaultTlsClient {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TlsAuthentication getAuthentication() {
|
||||||
|
return new ServerOnlyTlsAuthentication() {
|
||||||
|
@Override
|
||||||
|
public void notifyServerCertificate(Certificate cert)
|
||||||
|
throws IOException {
|
||||||
|
LOG.info("Received server certificate");
|
||||||
|
org.spongycastle.asn1.x509.Certificate[] chain =
|
||||||
|
cert.getCertificateList();
|
||||||
|
if (chain.length != 1)
|
||||||
|
throw new IOException("Certificate is not self-signed");
|
||||||
|
for (org.spongycastle.asn1.x509.Certificate c : chain) {
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Subject: " + c.getSubject());
|
||||||
|
LOG.info("Issuer: " + c.getIssuer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getCipherSuites() {
|
||||||
|
return TOR_CIPHER_SUITES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +1,42 @@
|
|||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
|
'com.android.tools.analytics-library:protos:26.2.1:protos-26.2.1.jar:2f371f5b1f551e85ab08be4d6a2873471b3d44afd1ebf6aa3298f3b796bf691f',
|
||||||
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
|
'com.android.tools.analytics-library:shared:26.2.1:shared-26.2.1.jar:4c1e4e705fa4d45f23aaea230557f6508155012d9c296337787c1d7b26a97f5a',
|
||||||
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
|
'com.android.tools.analytics-library:tracker:26.2.1:tracker-26.2.1.jar:4a624ecc976539f755ddb0bb8dfc2dd3d08326cfec59a098dbd70f701ca7fb75',
|
||||||
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
|
'com.android.tools.build:aapt2:3.2.1-4818971:aapt2-3.2.1-4818971-linux.jar:f431b6f96c91a2c155144b091a9c97d9805c589fe8efc9c930b6cd346cb60a1e',
|
||||||
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
|
'com.android.tools.build:apksig:3.2.1:apksig-3.2.1.jar:2b46f2feffea66037aab29e4261b2433c190194a6ef97b958511eb157f2ccba5',
|
||||||
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
|
'com.android.tools.build:apkzlib:3.2.1:apkzlib-3.2.1.jar:c39ad0313905932431fe81c8899c2cf39a4d92ad6c4edcaa4b25432f461452aa',
|
||||||
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
|
'com.android.tools.build:builder-model:3.2.1:builder-model-3.2.1.jar:a9f68e6abcec122f9cb5ad352d3f05a3eb03acbcdca95e4d25c16310c2c965ff',
|
||||||
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
|
'com.android.tools.build:builder-test-api:3.2.1:builder-test-api-3.2.1.jar:533ac6c2b5884bb54967a33791f2628dfdfac7981af39417a333b43d4379b6be',
|
||||||
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
|
'com.android.tools.build:builder:3.2.1:builder-3.2.1.jar:aedcbfd115dbe91d09b4113e66ef50589b558d0aa3b2f133b1d867c9b87fae83',
|
||||||
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
|
'com.android.tools.build:gradle-api:3.2.1:gradle-api-3.2.1.jar:57cf0ac5ac1dca8afdb3f62b94265e776e7dcfa641cc3844fb53a05193de208d',
|
||||||
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
|
'com.android.tools.build:manifest-merger:26.2.1:manifest-merger-26.2.1.jar:8830573263361035d38cfdcb51e2db94029c93865b21334f5fbf8a27984281a6',
|
||||||
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
|
'com.android.tools.ddms:ddmlib:26.2.1:ddmlib-26.2.1.jar:a4bf0a29a19980bf27269465cc782064656750b77c26728f82f9e148b705218b',
|
||||||
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
|
'com.android.tools.external.com-intellij:intellij-core:26.2.1:intellij-core-26.2.1.jar:4925ad1892c2687cb1a63427d440ef519c8c59215fefe0dc5d541d5d411fcafe',
|
||||||
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
|
'com.android.tools.external.com-intellij:kotlin-compiler:26.2.1:kotlin-compiler-26.2.1.jar:daa064fd708f340ee25fb9823c4c74104ac77f1370b76d907eb9ae6daec0a2ae',
|
||||||
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
|
'com.android.tools.external.org-jetbrains:uast:26.2.1:uast-26.2.1.jar:f10f7258d2ab9189562cc0f9ad838c0378fdba439229173390a99de02ebac75b',
|
||||||
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
|
'com.android.tools.layoutlib:layoutlib-api:26.2.1:layoutlib-api-26.2.1.jar:ddbf4fca123733fa011595b1cc1f4ac2937ed327b60990711fafc33c775c2ade',
|
||||||
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
|
'com.android.tools.lint:lint-api:26.2.1:lint-api-26.2.1.jar:3b57e739de567b98bc9ab56c2c0ee66fc026b4adf5843e8f9804ca0666a6f66e',
|
||||||
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
|
'com.android.tools.lint:lint-checks:26.2.1:lint-checks-26.2.1.jar:c86f4cc9aaee722ee4ad70062f7b5af91e9b041914af27adc09f545ab0fb3bc6',
|
||||||
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
|
'com.android.tools.lint:lint-gradle-api:26.2.1:lint-gradle-api-26.2.1.jar:2283e7af32e301565f2a797e531f0fc8c648077d457afb3ffdddbee638976c2f',
|
||||||
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
|
'com.android.tools.lint:lint-gradle:26.2.1:lint-gradle-26.2.1.jar:8fd90b2f3ec788cbb9801c07ab3e1ea2255aa31a6093157d7ea0ff13d0315ecb',
|
||||||
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
|
'com.android.tools.lint:lint-kotlin:26.2.1:lint-kotlin-26.2.1.jar:7a6a5d2b18f69cf1b900d857c2632b4c683713c533295933b8b759f8cab4a877',
|
||||||
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
|
'com.android.tools.lint:lint:26.2.1:lint-26.2.1.jar:7848b82ae988b90dee259ae7c7e86e05cbf52db6cd21c8bbd38ce7df08f3f8c5',
|
||||||
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
|
'com.android.tools:annotations:26.2.1:annotations-26.2.1.jar:7391c6a1e080174b96e64ceb078dadd31ce4d8a2d2fee0ec65be202126f90f24',
|
||||||
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
|
'com.android.tools:common:26.2.1:common-26.2.1.jar:a50aab2d6411ff68f4004a87c7e93d87d8e980a0ec3b352246549897ea2d78e5',
|
||||||
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
|
'com.android.tools:dvlib:26.2.1:dvlib-26.2.1.jar:72a83bf2839b1df9b1fbf67ba45d1bfb9f966cd774da4320c762b2be8f1688aa',
|
||||||
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
|
'com.android.tools:repository:26.2.1:repository-26.2.1.jar:fa74dae09103faef703df38550ad8fa244c5b6d1bf90d6198be932292b3d9cc1',
|
||||||
|
'com.android.tools:sdk-common:26.2.1:sdk-common-26.2.1.jar:759d4b292ca69a35cf961fca377b54158fc6c88108978006999442e80a011cf4',
|
||||||
|
'com.android.tools:sdklib:26.2.1:sdklib-26.2.1.jar:248df7ad5eac4aeb6f96c394c76760de4b7b89ac056e54d0c21a739368b91b45',
|
||||||
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
||||||
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
|
'com.google.code.gson:gson:2.8.0:gson-2.8.0.jar:c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825',
|
||||||
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||||
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
||||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
|
'com.google.guava:guava:23.0:guava-23.0.jar:7baa80df284117e5b945b19b98d367a85ea7b7801bd358ff657946c3bd1b6596',
|
||||||
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
||||||
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
||||||
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
||||||
@@ -43,8 +45,8 @@ dependencyVerification {
|
|||||||
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
||||||
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
||||||
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
|
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
|
||||||
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
|
'commons-codec:commons-codec:1.9:commons-codec-1.9.jar:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce',
|
||||||
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
|
'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',
|
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
|
||||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
@@ -55,13 +57,13 @@ dependencyVerification {
|
|||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
|
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
|
||||||
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
|
'org.apache.httpcomponents:httpclient:4.5.2:httpclient-4.5.2.jar:0dffc621400d6c632f55787d996b8aeca36b30746a716e079a985f24d8074057',
|
||||||
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
|
'org.apache.httpcomponents:httpcore:4.4.5:httpcore-4.4.5.jar:64d5453874cab7e40a7065cb01a9a9ca1053845a9786b478878b679e0580cec3',
|
||||||
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
|
'org.apache.httpcomponents:httpmime:4.5.2:httpmime-4.5.2.jar:231a3f7e4962053db2be8461d5422e68fc458a3a7dd7d8ada803a348e21f8f07',
|
||||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
||||||
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
||||||
'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
|
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926',
|
||||||
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
||||||
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
||||||
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
||||||
@@ -70,9 +72,10 @@ dependencyVerification {
|
|||||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||||
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
|
'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71:kotlin-stdlib-common-1.2.71.jar:63999687ff2fce8a592dd180ffbbf8f1d21c26b4044c55cdc74ff3cf3b3cf328',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
|
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71:kotlin-stdlib-jdk7-1.2.71.jar:b136bd61b240e07d4d92ce00d3bd1dbf584400a7bf5f220c2f3cd22446858082',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
|
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71:kotlin-stdlib-jdk8-1.2.71.jar:ac3c8abf47790b64b4f7e2509a53f0c145e061ac1612a597520535d199946ea9',
|
||||||
|
'org.jetbrains.kotlin:kotlin-stdlib:1.2.71:kotlin-stdlib-1.2.71.jar:4c895c270b87f5fec2a2796e1d89c15407ee821de961527c28588bb46afbc68b',
|
||||||
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
||||||
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
||||||
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
@@ -81,11 +84,11 @@ dependencyVerification {
|
|||||||
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
|
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
|
||||||
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
|
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
|
||||||
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
||||||
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
|
'org.ow2.asm:asm-analysis:6.0:asm-analysis-6.0.jar:2f1a6387219c3a6cc4856481f221b03bd9f2408a326d416af09af5d6f608c1f4',
|
||||||
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
|
'org.ow2.asm:asm-commons:6.0:asm-commons-6.0.jar:f1bce5c648a96a017bdcd01fe5d59af9845297fd7b79b81c015a6fbbd9719abf',
|
||||||
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
|
'org.ow2.asm:asm-tree:6.0:asm-tree-6.0.jar:887998fb69727c8759e4d253f856822801e33f9fd4caa566b3ac58ee92106215',
|
||||||
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
|
'org.ow2.asm:asm-util:6.0:asm-util-6.0.jar:356afebdb0f870175262e5188f8709a3b17aa2a5a6a4b0340b04d4b449bca5f6',
|
||||||
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
|
'org.ow2.asm:asm:6.0:asm-6.0.jar:dd8971c74a4e697899a8e95caae4ea8760ea6c486dc6b97b1795e75760420461',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,4 +38,18 @@ public abstract class StringMap extends Hashtable<String, String> {
|
|||||||
public void putInt(String key, int value) {
|
public void putInt(String key, int value) {
|
||||||
put(key, String.valueOf(value));
|
put(key, String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getLong(String key, long defaultValue) {
|
||||||
|
String s = get(key);
|
||||||
|
if (s == null) return defaultValue;
|
||||||
|
try {
|
||||||
|
return Long.valueOf(s);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putLong(String key, long value) {
|
||||||
|
put(key, String.valueOf(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,8 @@ public abstract class BdfMessageValidator implements MessageValidator {
|
|||||||
throw new InvalidMessageException(
|
throw new InvalidMessageException(
|
||||||
"Timestamp is too far in the future");
|
"Timestamp is too far in the future");
|
||||||
}
|
}
|
||||||
byte[] body = m.getBody();
|
|
||||||
if (body.length == 0) {
|
|
||||||
throw new InvalidMessageException("Message is too short");
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
BdfList bodyList = clientHelper.toList(body);
|
BdfList bodyList = clientHelper.toList(m.getBody());
|
||||||
BdfMessageContext result = validateMessage(m, g, bodyList);
|
BdfMessageContext result = validateMessage(m, g, bodyList);
|
||||||
Metadata meta = metadataEncoder.encode(result.getDictionary());
|
Metadata meta = metadataEncoder.encode(result.getDictionary());
|
||||||
return new MessageContext(meta, result.getDependencies());
|
return new MessageContext(meta, result.getDependencies());
|
||||||
|
|||||||
@@ -76,6 +76,19 @@ public interface DatabaseComponent {
|
|||||||
*/
|
*/
|
||||||
void endTransaction(Transaction txn);
|
void endTransaction(Transaction txn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the given task within a transaction.
|
||||||
|
*/
|
||||||
|
<E extends Exception> void transaction(boolean readOnly,
|
||||||
|
DbRunnable<E> task) throws DbException, E;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the given task within a transaction and returns the result of the
|
||||||
|
* task.
|
||||||
|
*/
|
||||||
|
<R, E extends Exception> R transactionWithResult(boolean readOnly,
|
||||||
|
DbCallable<R, E> task) throws DbException, E;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a contact associated with the given local and remote pseudonyms,
|
* Stores a contact associated with the given local and remote pseudonyms,
|
||||||
* and returns an ID for the contact.
|
* and returns an ID for the contact.
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.briarproject.bramble.api.db;
|
||||||
|
|
||||||
|
public interface DbCallable<R, E extends Exception> {
|
||||||
|
|
||||||
|
R call(Transaction txn) throws DbException, E;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.briarproject.bramble.api.db;
|
||||||
|
|
||||||
|
public interface DbRunnable<E extends Exception> {
|
||||||
|
|
||||||
|
void run(Transaction txn) throws DbException, E;
|
||||||
|
}
|
||||||
@@ -6,6 +6,10 @@ public interface MigrationListener {
|
|||||||
* This is called when a migration is started while opening the database.
|
* This is called when a migration is started while opening the database.
|
||||||
* It will be called once for each migration being applied.
|
* It will be called once for each migration being applied.
|
||||||
*/
|
*/
|
||||||
void onMigrationRun();
|
void onDatabaseMigration();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is called when compaction is started while opening the database.
|
||||||
|
*/
|
||||||
|
void onDatabaseCompaction();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ public interface LifecycleManager {
|
|||||||
*/
|
*/
|
||||||
enum LifecycleState {
|
enum LifecycleState {
|
||||||
|
|
||||||
STARTING, MIGRATING_DATABASE, STARTING_SERVICES, RUNNING, STOPPING;
|
STARTING, MIGRATING_DATABASE, COMPACTING_DATABASE, STARTING_SERVICES,
|
||||||
|
RUNNING, STOPPING;
|
||||||
|
|
||||||
public boolean isAfter(LifecycleState state) {
|
public boolean isAfter(LifecycleState state) {
|
||||||
return ordinal() > state.ordinal();
|
return ordinal() > state.ordinal();
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ public interface TorConstants {
|
|||||||
|
|
||||||
TransportId ID = new TransportId("org.briarproject.bramble.tor");
|
TransportId ID = new TransportId("org.briarproject.bramble.tor");
|
||||||
|
|
||||||
String PROP_ONION = "onion";
|
String PROP_ONION_V2 = "onion";
|
||||||
|
String PROP_ONION_V3 = "onion3";
|
||||||
|
|
||||||
int SOCKS_PORT = 59050;
|
int SOCKS_PORT = 59050;
|
||||||
int CONTROL_PORT = 59051;
|
int CONTROL_PORT = 59051;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public class Message {
|
|||||||
private final byte[] body;
|
private final byte[] body;
|
||||||
|
|
||||||
public Message(MessageId id, GroupId groupId, long timestamp, byte[] body) {
|
public Message(MessageId id, GroupId groupId, long timestamp, byte[] body) {
|
||||||
|
if (body.length == 0) throw new IllegalArgumentException();
|
||||||
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package org.briarproject.bramble.test;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class SettableClock implements Clock {
|
||||||
|
|
||||||
|
private final AtomicLong time;
|
||||||
|
|
||||||
|
public SettableClock(AtomicLong time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long currentTimeMillis() {
|
||||||
|
return time.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sleep(long milliseconds) throws InterruptedException {
|
||||||
|
Thread.sleep(milliseconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ dependencies {
|
|||||||
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
|
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
|
||||||
implementation 'org.bitlet:weupnp:0.1.4'
|
implementation 'org.bitlet:weupnp:0.1.4'
|
||||||
implementation 'net.i2p.crypto:eddsa:0.2.0'
|
implementation 'net.i2p.crypto:eddsa:0.2.0'
|
||||||
implementation 'org.whispersystems:curve25519-java:0.4.1'
|
implementation 'org.whispersystems:curve25519-java:0.5.0'
|
||||||
implementation 'org.briarproject:jtorctl:0.3'
|
implementation 'org.briarproject:jtorctl:0.3'
|
||||||
|
|
||||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
|
|||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
|
import org.briarproject.bramble.api.db.DbCallable;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.DbRunnable;
|
||||||
import org.briarproject.bramble.api.db.Metadata;
|
import org.briarproject.bramble.api.db.Metadata;
|
||||||
import org.briarproject.bramble.api.db.MigrationListener;
|
import org.briarproject.bramble.api.db.MigrationListener;
|
||||||
import org.briarproject.bramble.api.db.NoSuchContactException;
|
import org.briarproject.bramble.api.db.NoSuchContactException;
|
||||||
@@ -166,6 +168,31 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
for (Event e : transaction.getEvents()) eventBus.broadcast(e);
|
for (Event e : transaction.getEvents()) eventBus.broadcast(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <E extends Exception> void transaction(boolean readOnly,
|
||||||
|
DbRunnable<E> task) throws DbException, E {
|
||||||
|
Transaction txn = startTransaction(readOnly);
|
||||||
|
try {
|
||||||
|
task.run(txn);
|
||||||
|
commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
endTransaction(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R, E extends Exception> R transactionWithResult(boolean readOnly,
|
||||||
|
DbCallable<R, E> task) throws DbException, E {
|
||||||
|
Transaction txn = startTransaction(readOnly);
|
||||||
|
try {
|
||||||
|
R result = task.call(txn);
|
||||||
|
commitTransaction(txn);
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
endTransaction(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private T unbox(Transaction transaction) {
|
private T unbox(Transaction transaction) {
|
||||||
if (transaction.isCommitted()) throw new IllegalStateException();
|
if (transaction.isCommitted()) throw new IllegalStateException();
|
||||||
return txnClass.cast(transaction.unbox());
|
return txnClass.cast(transaction.unbox());
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package org.briarproject.bramble.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
|
||||||
|
import static java.util.concurrent.TimeUnit.DAYS;
|
||||||
|
|
||||||
interface DatabaseConstants {
|
interface DatabaseConstants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,4 +25,16 @@ interface DatabaseConstants {
|
|||||||
*/
|
*/
|
||||||
String SCHEMA_VERSION_KEY = "schemaVersion";
|
String SCHEMA_VERSION_KEY = "schemaVersion";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Settings} key under which the time of the last database
|
||||||
|
* compaction is stored.
|
||||||
|
*/
|
||||||
|
String LAST_COMPACTED_KEY = "lastCompacted";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum time between database compactions in milliseconds. When the
|
||||||
|
* database is opened it will be compacted if more than this amount of time
|
||||||
|
* has passed since the last compaction.
|
||||||
|
*/
|
||||||
|
long MAX_COMPACTION_INTERVAL_MS = DAYS.toMillis(30);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.io.File;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -106,4 +107,22 @@ class H2Database extends JdbcDatabase {
|
|||||||
String getUrl() {
|
String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void compactAndClose() throws DbException {
|
||||||
|
Connection c = null;
|
||||||
|
Statement s = null;
|
||||||
|
try {
|
||||||
|
c = createConnection();
|
||||||
|
closeAllConnections();
|
||||||
|
s = c.createStatement();
|
||||||
|
s.execute("SHUTDOWN COMPACT");
|
||||||
|
s.close();
|
||||||
|
c.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(s);
|
||||||
|
tryToClose(c);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,14 +61,18 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws DbException {
|
public void close() throws DbException {
|
||||||
|
Connection c = null;
|
||||||
|
Statement s = null;
|
||||||
try {
|
try {
|
||||||
super.closeAllConnections();
|
super.closeAllConnections();
|
||||||
Connection c = createConnection();
|
c = createConnection();
|
||||||
Statement s = c.createStatement();
|
s = c.createStatement();
|
||||||
s.executeQuery("SHUTDOWN");
|
s.executeQuery("SHUTDOWN");
|
||||||
s.close();
|
s.close();
|
||||||
c.close();
|
c.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
tryToClose(s);
|
||||||
|
tryToClose(c);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,4 +108,22 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
String hex = StringUtils.toHexString(key.getBytes());
|
String hex = StringUtils.toHexString(key.getBytes());
|
||||||
return DriverManager.getConnection(url + ";crypt_key=" + hex);
|
return DriverManager.getConnection(url + ";crypt_key=" + hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void compactAndClose() throws DbException {
|
||||||
|
Connection c = null;
|
||||||
|
Statement s = null;
|
||||||
|
try {
|
||||||
|
super.closeAllConnections();
|
||||||
|
c = createConnection();
|
||||||
|
s = c.createStatement();
|
||||||
|
s.executeQuery("SHUTDOWN COMPACT");
|
||||||
|
s.close();
|
||||||
|
c.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(s);
|
||||||
|
tryToClose(c);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,9 +67,13 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERE
|
|||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||||
|
import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY;
|
||||||
|
import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
||||||
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic database implementation that can be used with any JDBC-compatible
|
* A generic database implementation that can be used with any JDBC-compatible
|
||||||
@@ -317,9 +321,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private int openConnections = 0; // Locking: connectionsLock
|
private int openConnections = 0; // Locking: connectionsLock
|
||||||
private boolean closed = false; // Locking: connectionsLock
|
private boolean closed = false; // Locking: connectionsLock
|
||||||
|
|
||||||
@Nullable
|
|
||||||
protected abstract Connection createConnection() throws SQLException;
|
protected abstract Connection createConnection() throws SQLException;
|
||||||
|
|
||||||
|
protected abstract void compactAndClose() throws DbException;
|
||||||
|
|
||||||
private final Lock connectionsLock = new ReentrantLock();
|
private final Lock connectionsLock = new ReentrantLock();
|
||||||
private final Condition connectionsChanged = connectionsLock.newCondition();
|
private final Condition connectionsChanged = connectionsLock.newCondition();
|
||||||
|
|
||||||
@@ -344,13 +349,16 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
// Open the database and create the tables and indexes if necessary
|
// Open the database and create the tables and indexes if necessary
|
||||||
|
boolean compact;
|
||||||
Connection txn = startTransaction();
|
Connection txn = startTransaction();
|
||||||
try {
|
try {
|
||||||
if (reopen) {
|
if (reopen) {
|
||||||
checkSchemaVersion(txn, listener);
|
Settings s = getSettings(txn, DB_SETTINGS_NAMESPACE);
|
||||||
|
compact = migrateSchema(txn, s, listener) || isCompactionDue(s);
|
||||||
} else {
|
} else {
|
||||||
createTables(txn);
|
createTables(txn);
|
||||||
storeSchemaVersion(txn, CODE_SCHEMA_VERSION);
|
initialiseSettings(txn);
|
||||||
|
compact = false;
|
||||||
}
|
}
|
||||||
createIndexes(txn);
|
createIndexes(txn);
|
||||||
commitTransaction(txn);
|
commitTransaction(txn);
|
||||||
@@ -358,6 +366,25 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
abortTransaction(txn);
|
abortTransaction(txn);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
// Compact the database if necessary
|
||||||
|
if (compact) {
|
||||||
|
if (listener != null) listener.onDatabaseCompaction();
|
||||||
|
long start = now();
|
||||||
|
compactAndClose();
|
||||||
|
logDuration(LOG, "Compacting database", start);
|
||||||
|
// Allow the next transaction to reopen the DB
|
||||||
|
synchronized (connectionsLock) {
|
||||||
|
closed = false;
|
||||||
|
}
|
||||||
|
txn = startTransaction();
|
||||||
|
try {
|
||||||
|
storeLastCompacted(txn);
|
||||||
|
commitTransaction(txn);
|
||||||
|
} catch (DbException e) {
|
||||||
|
abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -365,17 +392,18 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
* version used by the current code and applies any suitable migrations to
|
* version used by the current code and applies any suitable migrations to
|
||||||
* the data if necessary.
|
* the data if necessary.
|
||||||
*
|
*
|
||||||
|
* @return true if any migrations were applied, false if the schema was
|
||||||
|
* already current
|
||||||
* @throws DataTooNewException if the data uses a newer schema than the
|
* @throws DataTooNewException if the data uses a newer schema than the
|
||||||
* current code
|
* current code
|
||||||
* @throws DataTooOldException if the data uses an older schema than the
|
* @throws DataTooOldException if the data uses an older schema than the
|
||||||
* current code and cannot be migrated
|
* current code and cannot be migrated
|
||||||
*/
|
*/
|
||||||
private void checkSchemaVersion(Connection txn,
|
private boolean migrateSchema(Connection txn, Settings s,
|
||||||
@Nullable MigrationListener listener) throws DbException {
|
@Nullable MigrationListener listener) throws DbException {
|
||||||
Settings s = getSettings(txn, DB_SETTINGS_NAMESPACE);
|
|
||||||
int dataSchemaVersion = s.getInt(SCHEMA_VERSION_KEY, -1);
|
int dataSchemaVersion = s.getInt(SCHEMA_VERSION_KEY, -1);
|
||||||
if (dataSchemaVersion == -1) throw new DbException();
|
if (dataSchemaVersion == -1) throw new DbException();
|
||||||
if (dataSchemaVersion == CODE_SCHEMA_VERSION) return;
|
if (dataSchemaVersion == CODE_SCHEMA_VERSION) return false;
|
||||||
if (CODE_SCHEMA_VERSION < dataSchemaVersion)
|
if (CODE_SCHEMA_VERSION < dataSchemaVersion)
|
||||||
throw new DataTooNewException();
|
throw new DataTooNewException();
|
||||||
// Apply any suitable migrations in order
|
// Apply any suitable migrations in order
|
||||||
@@ -384,7 +412,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
if (start == dataSchemaVersion) {
|
if (start == dataSchemaVersion) {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Migrating from schema " + start + " to " + end);
|
LOG.info("Migrating from schema " + start + " to " + end);
|
||||||
if (listener != null) listener.onMigrationRun();
|
if (listener != null) listener.onDatabaseMigration();
|
||||||
// Apply the migration
|
// Apply the migration
|
||||||
m.migrate(txn);
|
m.migrate(txn);
|
||||||
// Store the new schema version
|
// Store the new schema version
|
||||||
@@ -394,6 +422,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
if (dataSchemaVersion != CODE_SCHEMA_VERSION)
|
if (dataSchemaVersion != CODE_SCHEMA_VERSION)
|
||||||
throw new DataTooOldException();
|
throw new DataTooOldException();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package access for testing
|
// Package access for testing
|
||||||
@@ -401,6 +430,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
return Arrays.asList(new Migration38_39(), new Migration39_40());
|
return Arrays.asList(new Migration38_39(), new Migration39_40());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isCompactionDue(Settings s) {
|
||||||
|
long lastCompacted = s.getLong(LAST_COMPACTED_KEY, 0);
|
||||||
|
long elapsed = clock.currentTimeMillis() - lastCompacted;
|
||||||
|
if (LOG.isLoggable(INFO))
|
||||||
|
LOG.info(elapsed + " ms since last compaction");
|
||||||
|
return elapsed > MAX_COMPACTION_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
private void storeSchemaVersion(Connection txn, int version)
|
private void storeSchemaVersion(Connection txn, int version)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
@@ -408,6 +445,19 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void storeLastCompacted(Connection txn) throws DbException {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putLong(LAST_COMPACTED_KEY, clock.currentTimeMillis());
|
||||||
|
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialiseSettings(Connection txn) throws DbException {
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.putInt(SCHEMA_VERSION_KEY, CODE_SCHEMA_VERSION);
|
||||||
|
s.putLong(LAST_COMPACTED_KEY, clock.currentTimeMillis());
|
||||||
|
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
||||||
|
}
|
||||||
|
|
||||||
private void tryToClose(@Nullable ResultSet rs) {
|
private void tryToClose(@Nullable ResultSet rs) {
|
||||||
try {
|
try {
|
||||||
if (rs != null) rs.close();
|
if (rs != null) rs.close();
|
||||||
@@ -416,7 +466,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToClose(@Nullable Statement s) {
|
protected void tryToClose(@Nullable Statement s) {
|
||||||
try {
|
try {
|
||||||
if (s != null) s.close();
|
if (s != null) s.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@@ -424,6 +474,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void tryToClose(@Nullable Connection c) {
|
||||||
|
try {
|
||||||
|
if (c != null) c.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void createTables(Connection txn) throws DbException {
|
private void createTables(Connection txn) throws DbException {
|
||||||
Statement s = null;
|
Statement s = null;
|
||||||
try {
|
try {
|
||||||
@@ -489,7 +547,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
if (txn == null) {
|
if (txn == null) {
|
||||||
// Open a new connection
|
// Open a new connection
|
||||||
txn = createConnection();
|
txn = createConnection();
|
||||||
if (txn == null) throw new DbException();
|
|
||||||
txn.setAutoCommit(false);
|
txn.setAutoCommit(false);
|
||||||
connectionsLock.lock();
|
connectionsLock.lock();
|
||||||
try {
|
try {
|
||||||
@@ -1508,7 +1565,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
if (raw == null) throw new MessageDeletedException();
|
if (raw == null) throw new MessageDeletedException();
|
||||||
if (raw.length < MESSAGE_HEADER_LENGTH) throw new AssertionError();
|
if (raw.length <= MESSAGE_HEADER_LENGTH) throw new AssertionError();
|
||||||
byte[] body = new byte[raw.length - MESSAGE_HEADER_LENGTH];
|
byte[] body = new byte[raw.length - MESSAGE_HEADER_LENGTH];
|
||||||
System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length);
|
System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length);
|
||||||
return new Message(m, g, timestamp, body);
|
return new Message(m, g, timestamp, body);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import javax.inject.Inject;
|
|||||||
import static java.util.logging.Level.FINE;
|
import static java.util.logging.Level.FINE;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING;
|
||||||
@@ -159,11 +160,17 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMigrationRun() {
|
public void onDatabaseMigration() {
|
||||||
state = MIGRATING_DATABASE;
|
state = MIGRATING_DATABASE;
|
||||||
eventBus.broadcast(new LifecycleEvent(MIGRATING_DATABASE));
|
eventBus.broadcast(new LifecycleEvent(MIGRATING_DATABASE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDatabaseCompaction() {
|
||||||
|
state = COMPACTING_DATABASE;
|
||||||
|
eventBus.broadcast(new LifecycleEvent(COMPACTING_DATABASE));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopServices() {
|
public void stopServices() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import org.briarproject.bramble.api.system.Clock;
|
|||||||
import org.briarproject.bramble.api.system.LocationUtils;
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
import org.briarproject.bramble.util.IoUtils;
|
import org.briarproject.bramble.util.IoUtils;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
@@ -70,9 +69,11 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
|
|||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V2;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -87,7 +88,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
private static final String OWNER = "__OwningControllerProcess";
|
private static final String OWNER = "__OwningControllerProcess";
|
||||||
private static final int COOKIE_TIMEOUT_MS = 3000;
|
private static final int COOKIE_TIMEOUT_MS = 3000;
|
||||||
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
||||||
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
|
private static final Pattern ONION_V2 = Pattern.compile("[a-z2-7]{16}");
|
||||||
|
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
|
||||||
|
|
||||||
private final Executor ioExecutor, connectionStatusExecutor;
|
private final Executor ioExecutor, connectionStatusExecutor;
|
||||||
private final NetworkManager networkManager;
|
private final NetworkManager networkManager;
|
||||||
@@ -362,7 +364,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
// If there's already a port number stored in config, reuse it
|
// If there's already a port number stored in config, reuse it
|
||||||
String portString = settings.get(PREF_TOR_PORT);
|
String portString = settings.get(PREF_TOR_PORT);
|
||||||
int port;
|
int port;
|
||||||
if (StringUtils.isNullOrEmpty(portString)) port = 0;
|
if (isNullOrEmpty(portString)) port = 0;
|
||||||
else port = Integer.parseInt(portString);
|
else port = Integer.parseInt(portString);
|
||||||
// Bind a server socket to receive connections from Tor
|
// Bind a server socket to receive connections from Tor
|
||||||
ServerSocket ss = null;
|
ServerSocket ss = null;
|
||||||
@@ -427,11 +429,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Publish the hidden service's onion hostname in transport properties
|
// Publish the hidden service's onion hostname in transport properties
|
||||||
String hostname = response.get(HS_ADDRESS);
|
String onion2 = response.get(HS_ADDRESS);
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Hidden service " + scrubOnion(hostname));
|
LOG.info("Hidden service " + scrubOnion(onion2));
|
||||||
TransportProperties p = new TransportProperties();
|
TransportProperties p = new TransportProperties();
|
||||||
p.put(PROP_ONION, hostname);
|
p.put(PROP_ONION_V2, onion2);
|
||||||
callback.mergeLocalProperties(p);
|
callback.mergeLocalProperties(p);
|
||||||
if (privKey == null) {
|
if (privKey == null) {
|
||||||
// Save the hidden service's private key for next time
|
// Save the hidden service's private key for next time
|
||||||
@@ -530,26 +532,41 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public DuplexTransportConnection createConnection(TransportProperties p) {
|
public DuplexTransportConnection createConnection(TransportProperties p) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
String onion = p.get(PROP_ONION);
|
String bestOnion = null;
|
||||||
if (StringUtils.isNullOrEmpty(onion)) return null;
|
String onion2 = p.get(PROP_ONION_V2);
|
||||||
if (!ONION.matcher(onion).matches()) {
|
String onion3 = p.get(PROP_ONION_V3);
|
||||||
// not scrubbing this address, so we are able to find the problem
|
if (!isNullOrEmpty(onion2)) {
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Invalid hostname: " + onion);
|
if (ONION_V2.matcher(onion2).matches()) {
|
||||||
return null;
|
bestOnion = onion2;
|
||||||
|
} else {
|
||||||
|
// Don't scrub the address so we can find the problem
|
||||||
|
if (LOG.isLoggable(INFO))
|
||||||
|
LOG.info("Invalid v2 hostname: " + onion2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!isNullOrEmpty(onion3)) {
|
||||||
|
if (ONION_V3.matcher(onion3).matches()) {
|
||||||
|
bestOnion = onion3;
|
||||||
|
} else {
|
||||||
|
// Don't scrub the address so we can find the problem
|
||||||
|
if (LOG.isLoggable(INFO))
|
||||||
|
LOG.info("Invalid v3 hostname: " + onion3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestOnion == null) return null;
|
||||||
Socket s = null;
|
Socket s = null;
|
||||||
try {
|
try {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Connecting to " + scrubOnion(onion));
|
LOG.info("Connecting to " + scrubOnion(bestOnion));
|
||||||
s = torSocketFactory.createSocket(onion + ".onion", 80);
|
s = torSocketFactory.createSocket(bestOnion + ".onion", 80);
|
||||||
s.setSoTimeout(socketTimeout);
|
s.setSoTimeout(socketTimeout);
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Connected to " + scrubOnion(onion));
|
LOG.info("Connected to " + scrubOnion(bestOnion));
|
||||||
return new TorTransportConnection(this, s);
|
return new TorTransportConnection(this, s);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
|
LOG.info("Could not connect to " + scrubOnion(bestOnion)
|
||||||
e.toString());
|
+ ": " + e.toString());
|
||||||
}
|
}
|
||||||
tryToClose(s);
|
tryToClose(s);
|
||||||
return null;
|
return null;
|
||||||
@@ -627,6 +644,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (s.getNamespace().equals(ID.getString())) {
|
if (s.getNamespace().equals(ID.getString())) {
|
||||||
LOG.info("Tor settings updated");
|
LOG.info("Tor settings updated");
|
||||||
settings = s.getSettings();
|
settings = s.getSettings();
|
||||||
|
// Works around a bug introduced in Tor 0.3.4.8. Could be
|
||||||
|
// replaced with callback.transportDisabled() when fixed.
|
||||||
|
disableNetwork();
|
||||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
}
|
}
|
||||||
} else if (e instanceof NetworkStatusEvent) {
|
} else if (e instanceof NetworkStatusEvent) {
|
||||||
@@ -634,6 +654,16 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void disableNetwork() {
|
||||||
|
connectionStatusExecutor.execute(() -> {
|
||||||
|
try {
|
||||||
|
enableNetwork(false);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logException(LOG, WARNING, ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void updateConnectionStatus(NetworkStatus status) {
|
private void updateConnectionStatus(NetworkStatus status) {
|
||||||
connectionStatusExecutor.execute(() -> {
|
connectionStatusExecutor.execute(() -> {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message createMessage(GroupId g, long timestamp, byte[] body) {
|
public Message createMessage(GroupId g, long timestamp, byte[] body) {
|
||||||
|
if (body.length == 0) throw new IllegalArgumentException();
|
||||||
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
MessageId id = getMessageId(g, timestamp, body);
|
MessageId id = getMessageId(g, timestamp, body);
|
||||||
@@ -54,7 +55,7 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message createMessage(byte[] raw) {
|
public Message createMessage(byte[] raw) {
|
||||||
if (raw.length < MESSAGE_HEADER_LENGTH)
|
if (raw.length <= MESSAGE_HEADER_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (raw.length > MAX_MESSAGE_LENGTH)
|
if (raw.length > MAX_MESSAGE_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
|||||||
@@ -124,7 +124,8 @@ class SyncRecordReaderImpl implements SyncRecordReader {
|
|||||||
if (!hasMessage()) throw new FormatException();
|
if (!hasMessage()) throw new FormatException();
|
||||||
if (nextRecord == null) throw new AssertionError();
|
if (nextRecord == null) throw new AssertionError();
|
||||||
byte[] payload = nextRecord.getPayload();
|
byte[] payload = nextRecord.getPayload();
|
||||||
if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException();
|
if (payload.length <= MESSAGE_HEADER_LENGTH)
|
||||||
|
throw new FormatException();
|
||||||
// Validate timestamp
|
// Validate timestamp
|
||||||
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
|
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
|
||||||
if (timestamp < 0) throw new FormatException();
|
if (timestamp < 0) throw new FormatException();
|
||||||
|
|||||||
@@ -79,18 +79,6 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
assertSame(meta, messageContext.getMetadata());
|
assertSame(meta, messageContext.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = InvalidMessageException.class)
|
|
||||||
public void testRejectsTooShortMessage() throws Exception {
|
|
||||||
Message invalidMessage = getMessage(groupId, 0);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(clock).currentTimeMillis();
|
|
||||||
will(returnValue(timestamp));
|
|
||||||
}});
|
|
||||||
|
|
||||||
failIfSubclassIsCalled.validateMessage(invalidMessage, group);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAcceptsMinLengthMessage() throws Exception {
|
public void testAcceptsMinLengthMessage() throws Exception {
|
||||||
Message shortMessage = getMessage(groupId, 1);
|
Message shortMessage = getMessage(groupId, 1);
|
||||||
|
|||||||
@@ -26,11 +26,10 @@ import org.briarproject.bramble.api.transport.KeySetId;
|
|||||||
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
import org.briarproject.bramble.system.SystemClock;
|
import org.briarproject.bramble.system.SystemClock;
|
||||||
import org.briarproject.bramble.test.ArrayClock;
|
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
|
import org.briarproject.bramble.test.SettableClock;
|
||||||
import org.briarproject.bramble.test.TestDatabaseConfig;
|
import org.briarproject.bramble.test.TestDatabaseConfig;
|
||||||
import org.briarproject.bramble.test.TestMessageFactory;
|
import org.briarproject.bramble.test.TestMessageFactory;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -46,6 +45,7 @@ import java.util.Map.Entry;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.emptyMap;
|
import static java.util.Collections.emptyMap;
|
||||||
@@ -61,6 +61,9 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERE
|
|||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
|
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||||
|
import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY;
|
||||||
|
import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS;
|
||||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getClientId;
|
import static org.briarproject.bramble.test.TestUtils.getClientId;
|
||||||
@@ -1818,10 +1821,9 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMessageRetransmission() throws Exception {
|
public void testMessageRetransmission() throws Exception {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
long steps[] = {now, now, now + MAX_LATENCY * 2 - 1,
|
AtomicLong time = new AtomicLong(now);
|
||||||
now + MAX_LATENCY * 2};
|
|
||||||
Database<Connection> db =
|
Database<Connection> db =
|
||||||
open(false, new TestMessageFactory(), new ArrayClock(steps));
|
open(false, new TestMessageFactory(), new SettableClock(time));
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a shared group and a shared message
|
// Add a contact, a shared group and a shared message
|
||||||
@@ -1847,11 +1849,13 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
|
|
||||||
// Time: now + MAX_LATENCY * 2 - 1
|
// Time: now + MAX_LATENCY * 2 - 1
|
||||||
// The message should not yet be sendable
|
// The message should not yet be sendable
|
||||||
|
time.set(now + MAX_LATENCY * 2 - 1);
|
||||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
||||||
assertTrue(ids.isEmpty());
|
assertTrue(ids.isEmpty());
|
||||||
|
|
||||||
// Time: now + MAX_LATENCY * 2
|
// Time: now + MAX_LATENCY * 2
|
||||||
// The message should have expired and should now be sendable
|
// The message should have expired and should now be sendable
|
||||||
|
time.set(now + MAX_LATENCY * 2);
|
||||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
||||||
assertEquals(singletonList(messageId), ids);
|
assertEquals(singletonList(messageId), ids);
|
||||||
|
|
||||||
@@ -1859,13 +1863,12 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFasterMessageRetransmission() throws Exception {
|
public void testFasterMessageRetransmission() throws Exception {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
long steps[] = {now, now, now, now, now + 1};
|
AtomicLong time = new AtomicLong(now);
|
||||||
Database<Connection> db =
|
Database<Connection> db =
|
||||||
open(false, new TestMessageFactory(), new ArrayClock(steps));
|
open(false, new TestMessageFactory(), new SettableClock(time));
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a shared group and a shared message
|
// Add a contact, a shared group and a shared message
|
||||||
@@ -1903,6 +1906,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
// Time: now + 1
|
// Time: now + 1
|
||||||
// The message should no longer be sendable via the faster transport,
|
// The message should no longer be sendable via the faster transport,
|
||||||
// as the ETA is now equal
|
// as the ETA is now equal
|
||||||
|
time.set(now + 1);
|
||||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE,
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE,
|
||||||
MAX_LATENCY - 1);
|
MAX_LATENCY - 1);
|
||||||
assertTrue(ids.isEmpty());
|
assertTrue(ids.isEmpty());
|
||||||
@@ -1911,6 +1915,45 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompactionTime() throws Exception {
|
||||||
|
MessageFactory messageFactory = new TestMessageFactory();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
AtomicLong time = new AtomicLong(now);
|
||||||
|
Clock clock = new SettableClock(time);
|
||||||
|
|
||||||
|
// Time: now
|
||||||
|
// The last compaction time should be initialised to the current time
|
||||||
|
Database<Connection> db = open(false, messageFactory, clock);
|
||||||
|
Connection txn = db.startTransaction();
|
||||||
|
Settings s = db.getSettings(txn, DB_SETTINGS_NAMESPACE);
|
||||||
|
assertEquals(now, s.getLong(LAST_COMPACTED_KEY, 0));
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
db.close();
|
||||||
|
|
||||||
|
// Time: now + MAX_COMPACTION_INTERVAL_MS
|
||||||
|
// The DB should not be compacted, so the last compaction time should
|
||||||
|
// not be updated
|
||||||
|
time.set(now + MAX_COMPACTION_INTERVAL_MS);
|
||||||
|
db = open(true, messageFactory, clock);
|
||||||
|
txn = db.startTransaction();
|
||||||
|
s = db.getSettings(txn, DB_SETTINGS_NAMESPACE);
|
||||||
|
assertEquals(now, s.getLong(LAST_COMPACTED_KEY, 0));
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
db.close();
|
||||||
|
|
||||||
|
// Time: now + MAX_COMPACTION_INTERVAL_MS + 1
|
||||||
|
// The DB should be compacted, so the last compaction time should be
|
||||||
|
// updated
|
||||||
|
time.set(now + MAX_COMPACTION_INTERVAL_MS + 1);
|
||||||
|
db = open(true, messageFactory, clock);
|
||||||
|
txn = db.startTransaction();
|
||||||
|
s = db.getSettings(txn, DB_SETTINGS_NAMESPACE);
|
||||||
|
assertEquals(now + MAX_COMPACTION_INTERVAL_MS + 1,
|
||||||
|
s.getLong(LAST_COMPACTED_KEY, 0));
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
private Database<Connection> open(boolean resume) throws Exception {
|
private Database<Connection> open(boolean resume) throws Exception {
|
||||||
return open(resume, new TestMessageFactory(), new SystemClock());
|
return open(resume, new TestMessageFactory(), new SystemClock());
|
||||||
@@ -1921,7 +1964,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
Database<Connection> db =
|
Database<Connection> db =
|
||||||
createDatabase(new TestDatabaseConfig(testDir, MAX_SIZE),
|
createDatabase(new TestDatabaseConfig(testDir, MAX_SIZE),
|
||||||
messageFactory, clock);
|
messageFactory, clock);
|
||||||
if (!resume) TestUtils.deleteTestDirectory(testDir);
|
if (!resume) deleteTestDirectory(testDir);
|
||||||
db.open(key, null);
|
db.open(key, null);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ dependencyVerification {
|
|||||||
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
||||||
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
||||||
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
'org.whispersystems:curve25519-java:0.4.1:curve25519-java-0.4.1.jar:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
|
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ configurations {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
implementation fileTree(dir: 'libs', include: '*.jar')
|
implementation fileTree(dir: 'libs', include: '*.jar')
|
||||||
implementation 'net.java.dev.jna:jna:4.4.0'
|
implementation 'net.java.dev.jna:jna:4.5.2'
|
||||||
implementation 'net.java.dev.jna:jna-platform:4.4.0'
|
implementation 'net.java.dev.jna:jna-platform:4.5.2'
|
||||||
tor 'org.briarproject:tor:0.2.9.16@zip'
|
tor 'org.briarproject:tor:0.3.4.8@zip'
|
||||||
|
|
||||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ dependencyVerification {
|
|||||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
|
'net.java.dev.jna:jna-platform:4.5.2:jna-platform-4.5.2.jar:f1d00c167d8921c6e23c626ef9f1c3ae0be473c95c68ffa012bc7ae55a87e2d6',
|
||||||
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
|
'net.java.dev.jna:jna:4.5.2:jna-4.5.2.jar:0c8eb7acf67261656d79005191debaba3b6bf5dd60a43735a245429381dbecff',
|
||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
'org.briarproject:tor:0.2.9.16:tor-0.2.9.16.zip:f33091ba414d6a952263981d9059b3d0a9093fd277ae887b3cdd02e8f1936558',
|
'org.briarproject:tor:0.3.4.8:tor-0.3.4.8.zip:bc0158c34002f471a4fe14a6a481816c918eb520a220bb027f64be902beb757f',
|
||||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||||
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ def getStdout = { command, defaultValue ->
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
buildToolsVersion '28.0.2'
|
buildToolsVersion '28.0.3'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 10102
|
versionCode 10103
|
||||||
versionName "1.1.2"
|
versionName "1.1.3"
|
||||||
applicationId "org.briarproject.briar.android"
|
applicationId "org.briarproject.briar.android"
|
||||||
buildConfigField "String", "GitHash",
|
buildConfigField "String", "GitHash",
|
||||||
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
|
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
|
||||||
@@ -90,7 +90,7 @@ dependencies {
|
|||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
implementation project(':bramble-android')
|
implementation project(':bramble-android')
|
||||||
|
|
||||||
def supportVersion = '27.1.1'
|
def supportVersion = '28.0.0'
|
||||||
implementation "com.android.support:support-v4:$supportVersion"
|
implementation "com.android.support:support-v4:$supportVersion"
|
||||||
implementation("com.android.support:appcompat-v7:$supportVersion") {
|
implementation("com.android.support:appcompat-v7:$supportVersion") {
|
||||||
exclude module: 'support-v4'
|
exclude module: 'support-v4'
|
||||||
@@ -106,15 +106,15 @@ dependencies {
|
|||||||
implementation "com.android.support:support-annotations:$supportVersion"
|
implementation "com.android.support:support-annotations:$supportVersion"
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||||
|
|
||||||
implementation('ch.acra:acra:4.9.1') {
|
implementation('ch.acra:acra:4.11') {
|
||||||
exclude module: 'support-v4'
|
exclude module: 'support-v4'
|
||||||
exclude module: 'support-annotations'
|
exclude module: 'support-annotations'
|
||||||
}
|
}
|
||||||
implementation 'info.guardianproject.panic:panic:0.5'
|
implementation 'info.guardianproject.panic:panic:0.5'
|
||||||
implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
|
implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
|
||||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||||
implementation 'com.google.zxing:core:3.3.0'
|
implementation 'com.google.zxing:core:3.3.3'
|
||||||
implementation 'uk.co.samuelwall:material-tap-target-prompt:2.8.0'
|
implementation 'uk.co.samuelwall:material-tap-target-prompt:2.12.4'
|
||||||
implementation 'com.vanniktech:emoji-google:0.5.1'
|
implementation 'com.vanniktech:emoji-google:0.5.1'
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
-dontnote com.android.org.conscrypt.SSLParametersImpl
|
-dontnote com.android.org.conscrypt.SSLParametersImpl
|
||||||
-dontnote org.apache.harmony.xnet.provider.jsse.SSLParametersImpl
|
-dontnote org.apache.harmony.xnet.provider.jsse.SSLParametersImpl
|
||||||
-dontnote sun.security.ssl.SSLContextImpl
|
-dontnote sun.security.ssl.SSLContextImpl
|
||||||
|
-dontwarn org.conscrypt.OpenSSLProvider
|
||||||
|
-dontwarn org.conscrypt.Conscrypt
|
||||||
|
|
||||||
# HTML sanitiser
|
# HTML sanitiser
|
||||||
-keep class org.jsoup.safety.Whitelist
|
-keep class org.jsoup.safety.Whitelist
|
||||||
|
|||||||
@@ -387,7 +387,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name="org.briarproject.briar.android.panic.PanicResponderActivity"
|
android:name="org.briarproject.briar.android.panic.PanicResponderActivity"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@style/Theme.AppCompat.NoActionBar">
|
||||||
<!-- this can never have launchMode singleTask or singleInstance! -->
|
<!-- this can never have launchMode singleTask or singleInstance! -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="info.guardianproject.panic.action.TRIGGER"/>
|
<action android:name="info.guardianproject.panic.action.TRIGGER"/>
|
||||||
@@ -397,12 +397,12 @@
|
|||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.briarproject.briar.android.logout.ExitActivity"
|
android:name="org.briarproject.briar.android.logout.ExitActivity"
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@style/Theme.AppCompat.NoActionBar">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.logout.HideUiActivity"
|
android:name=".android.logout.HideUiActivity"
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@style/Theme.AppCompat.NoActionBar">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
|||||||
import org.briarproject.briar.android.forum.ForumModule;
|
import org.briarproject.briar.android.forum.ForumModule;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
||||||
|
import org.briarproject.briar.android.reporting.DevReportActivity;
|
||||||
import org.briarproject.briar.android.util.UiUtils;
|
import org.briarproject.briar.android.util.UiUtils;
|
||||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
||||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
||||||
@@ -37,11 +38,16 @@ import java.util.List;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static android.arch.lifecycle.Lifecycle.State.STARTED;
|
||||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||||
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
||||||
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning: Some activities don't extend {@link BaseActivity}.
|
||||||
|
* E.g. {@link DevReportActivity}
|
||||||
|
*/
|
||||||
public abstract class BaseActivity extends AppCompatActivity
|
public abstract class BaseActivity extends AppCompatActivity
|
||||||
implements DestroyableContext, OnTapFilteredListener {
|
implements DestroyableContext, OnTapFilteredListener {
|
||||||
|
|
||||||
@@ -143,6 +149,7 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void showNextFragment(BaseFragment f) {
|
public void showNextFragment(BaseFragment f) {
|
||||||
|
if (!getLifecycle().getCurrentState().isAtLeast(STARTED)) return;
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.setCustomAnimations(R.anim.step_next_in,
|
.setCustomAnimations(R.anim.step_next_in,
|
||||||
R.anim.step_previous_out, R.anim.step_previous_in,
|
R.anim.step_previous_out, R.anim.step_previous_in,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
|||||||
protected final IdentityManager identityManager;
|
protected final IdentityManager identityManager;
|
||||||
protected final BlogManager blogManager;
|
protected final BlogManager blogManager;
|
||||||
|
|
||||||
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
|
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
||||||
private final Map<MessageId, BlogPostHeader> headerCache =
|
private final Map<MessageId, BlogPostHeader> headerCache =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -129,17 +129,17 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
|||||||
public void loadBlogPost(BlogPostHeader header,
|
public void loadBlogPost(BlogPostHeader header,
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler) {
|
ResultExceptionHandler<BlogPostItem, DbException> handler) {
|
||||||
|
|
||||||
String body = bodyCache.get(header.getId());
|
String text = textCache.get(header.getId());
|
||||||
if (body != null) {
|
if (text != null) {
|
||||||
LOG.info("Loaded body from cache");
|
LOG.info("Loaded text from cache");
|
||||||
handler.onResult(new BlogPostItem(header, body));
|
handler.onResult(new BlogPostItem(header, text));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
BlogPostItem item = getItem(header);
|
BlogPostItem item = getItem(header);
|
||||||
logDuration(LOG, "Loading body", start);
|
logDuration(LOG, "Loading text", start);
|
||||||
handler.onResult(item);
|
handler.onResult(item);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -200,28 +200,28 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
|||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private BlogPostItem getItem(BlogPostHeader h) throws DbException {
|
private BlogPostItem getItem(BlogPostHeader h) throws DbException {
|
||||||
String body;
|
String text;
|
||||||
if (h instanceof BlogCommentHeader) {
|
if (h instanceof BlogCommentHeader) {
|
||||||
BlogCommentHeader c = (BlogCommentHeader) h;
|
BlogCommentHeader c = (BlogCommentHeader) h;
|
||||||
BlogCommentItem item = new BlogCommentItem(c);
|
BlogCommentItem item = new BlogCommentItem(c);
|
||||||
body = getPostBody(item.getPostHeader().getId());
|
text = getPostText(item.getPostHeader().getId());
|
||||||
item.setBody(body);
|
item.setText(text);
|
||||||
return item;
|
return item;
|
||||||
} else {
|
} else {
|
||||||
body = getPostBody(h.getId());
|
text = getPostText(h.getId());
|
||||||
return new BlogPostItem(h, body);
|
return new BlogPostItem(h, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private String getPostBody(MessageId m) throws DbException {
|
private String getPostText(MessageId m) throws DbException {
|
||||||
String body = bodyCache.get(m);
|
String text = textCache.get(m);
|
||||||
if (body == null) {
|
if (text == null) {
|
||||||
body = HtmlUtils.clean(blogManager.getPostBody(m), ARTICLE);
|
text = HtmlUtils.clean(blogManager.getPostText(m), ARTICLE);
|
||||||
bodyCache.put(m, body);
|
textCache.put(m, text);
|
||||||
}
|
}
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
return body;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ class BlogCommentItem extends BlogPostItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBody(String body) {
|
public void setText(String text) {
|
||||||
this.body = body;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
public class BlogPostItem implements Comparable<BlogPostItem> {
|
public class BlogPostItem implements Comparable<BlogPostItem> {
|
||||||
|
|
||||||
private final BlogPostHeader header;
|
private final BlogPostHeader header;
|
||||||
protected String body;
|
protected String text;
|
||||||
private boolean read;
|
private boolean read;
|
||||||
|
|
||||||
BlogPostItem(BlogPostHeader header, @Nullable String body) {
|
BlogPostItem(BlogPostHeader header, @Nullable String text) {
|
||||||
this.header = header;
|
this.header = header;
|
||||||
this.body = body;
|
this.text = text;
|
||||||
this.read = header.isRead();
|
this.read = header.isRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,8 +44,8 @@ public class BlogPostItem implements Comparable<BlogPostItem> {
|
|||||||
return header.getAuthorStatus();
|
return header.getAuthorStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBody() {
|
public String getText() {
|
||||||
return body;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRssFeed() {
|
public boolean isRssFeed() {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
private final AuthorView reblogger;
|
private final AuthorView reblogger;
|
||||||
private final AuthorView author;
|
private final AuthorView author;
|
||||||
private final ImageButton reblogButton;
|
private final ImageButton reblogButton;
|
||||||
private final TextView body;
|
private final TextView text;
|
||||||
private final ViewGroup commentContainer;
|
private final ViewGroup commentContainer;
|
||||||
private final boolean fullText;
|
private final boolean fullText;
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
reblogger = v.findViewById(R.id.rebloggerView);
|
reblogger = v.findViewById(R.id.rebloggerView);
|
||||||
author = v.findViewById(R.id.authorView);
|
author = v.findViewById(R.id.authorView);
|
||||||
reblogButton = v.findViewById(R.id.commentView);
|
reblogButton = v.findViewById(R.id.commentView);
|
||||||
body = v.findViewById(R.id.bodyView);
|
text = v.findViewById(R.id.textView);
|
||||||
commentContainer = v.findViewById(R.id.commentContainer);
|
commentContainer = v.findViewById(R.id.commentContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,17 +111,17 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
author.setAuthorNotClickable();
|
author.setAuthorNotClickable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// post body
|
// post text
|
||||||
Spanned bodyText = getSpanned(item.getBody());
|
Spanned postText = getSpanned(item.getText());
|
||||||
if (fullText) {
|
if (fullText) {
|
||||||
body.setText(bodyText);
|
text.setText(postText);
|
||||||
body.setTextIsSelectable(true);
|
text.setTextIsSelectable(true);
|
||||||
makeLinksClickable(body, fragmentManager);
|
makeLinksClickable(text, fragmentManager);
|
||||||
} else {
|
} else {
|
||||||
body.setTextIsSelectable(false);
|
text.setTextIsSelectable(false);
|
||||||
if (bodyText.length() > TEASER_LENGTH)
|
if (postText.length() > TEASER_LENGTH)
|
||||||
bodyText = getTeaser(ctx, bodyText);
|
postText = getTeaser(ctx, postText);
|
||||||
body.setText(bodyText);
|
text.setText(postText);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reblog button
|
// reblog button
|
||||||
@@ -163,15 +163,15 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
commentContainer, false);
|
commentContainer, false);
|
||||||
|
|
||||||
AuthorView author = v.findViewById(R.id.authorView);
|
AuthorView author = v.findViewById(R.id.authorView);
|
||||||
TextView body = v.findViewById(R.id.bodyView);
|
TextView text = v.findViewById(R.id.textView);
|
||||||
|
|
||||||
author.setAuthor(c.getAuthor());
|
author.setAuthor(c.getAuthor());
|
||||||
author.setAuthorStatus(c.getAuthorStatus());
|
author.setAuthorStatus(c.getAuthorStatus());
|
||||||
author.setDate(c.getTimestamp());
|
author.setDate(c.getTimestamp());
|
||||||
// TODO make author clickable #624
|
// TODO make author clickable #624
|
||||||
|
|
||||||
body.setText(c.getComment());
|
text.setText(c.getComment());
|
||||||
if (fullText) body.setTextIsSelectable(true);
|
if (fullText) text.setTextIsSelectable(true);
|
||||||
|
|
||||||
commentContainer.addView(v);
|
commentContainer.addView(v);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import static android.view.View.GONE;
|
|||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
|
import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_TEXT_LENGTH;
|
||||||
|
|
||||||
public class WriteBlogPostActivity extends BriarActivity
|
public class WriteBlogPostActivity extends BriarActivity
|
||||||
implements OnEditorActionListener, TextInputListener {
|
implements OnEditorActionListener, TextInputListener {
|
||||||
@@ -70,7 +70,7 @@ public class WriteBlogPostActivity extends BriarActivity
|
|||||||
|
|
||||||
setContentView(R.layout.activity_write_blog_post);
|
setContentView(R.layout.activity_write_blog_post);
|
||||||
|
|
||||||
input = findViewById(R.id.bodyInput);
|
input = findViewById(R.id.textInput);
|
||||||
input.setSendButtonEnabled(false);
|
input.setSendButtonEnabled(false);
|
||||||
input.addTextChangedListener(new TextWatcher() {
|
input.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
@@ -132,23 +132,23 @@ public class WriteBlogPostActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSendClick(String body) {
|
public void onSendClick(String text) {
|
||||||
// hide publish button, show progress bar
|
// hide publish button, show progress bar
|
||||||
input.hideSoftKeyboard();
|
input.hideSoftKeyboard();
|
||||||
input.setVisibility(GONE);
|
input.setVisibility(GONE);
|
||||||
progressBar.setVisibility(VISIBLE);
|
progressBar.setVisibility(VISIBLE);
|
||||||
|
|
||||||
body = StringUtils.truncateUtf8(body, MAX_BLOG_POST_BODY_LENGTH);
|
text = StringUtils.truncateUtf8(text, MAX_BLOG_POST_TEXT_LENGTH);
|
||||||
storePost(body);
|
storePost(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storePost(String body) {
|
private void storePost(String text) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
LocalAuthor author = identityManager.getLocalAuthor();
|
LocalAuthor author = identityManager.getLocalAuthor();
|
||||||
BlogPost p = blogPostFactory
|
BlogPost p = blogPostFactory
|
||||||
.createBlogPost(groupId, timestamp, null, author, body);
|
.createBlogPost(groupId, timestamp, null, author, text);
|
||||||
blogManager.addLocalPost(p);
|
blogManager.addLocalPost(p);
|
||||||
postPublished();
|
postPublished();
|
||||||
} catch (DbException | GeneralSecurityException
|
} catch (DbException | GeneralSecurityException
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import org.briarproject.briar.R;
|
|||||||
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
|
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||||
import org.briarproject.briar.android.util.UiUtils;
|
import org.briarproject.briar.android.util.UiUtils;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static android.support.v4.view.ViewCompat.setTransitionName;
|
import static android.support.v4.view.ViewCompat.setTransitionName;
|
||||||
@@ -36,7 +38,7 @@ class ContactListItemViewHolder extends ContactItemViewHolder<ContactListItem> {
|
|||||||
// unread count
|
// unread count
|
||||||
int unreadCount = item.getUnreadCount();
|
int unreadCount = item.getUnreadCount();
|
||||||
if (unreadCount > 0) {
|
if (unreadCount > 0) {
|
||||||
unread.setText(String.valueOf(unreadCount));
|
unread.setText(String.format(Locale.getDefault(), "%d", unreadCount));
|
||||||
unread.setVisibility(View.VISIBLE);
|
unread.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
unread.setVisibility(View.INVISIBLE);
|
unread.setVisibility(View.INVISIBLE);
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ import org.briarproject.briar.android.activity.ActivityComponent;
|
|||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.blog.BlogActivity;
|
import org.briarproject.briar.android.blog.BlogActivity;
|
||||||
import org.briarproject.briar.android.contact.ConversationAdapter.ConversationListener;
|
import org.briarproject.briar.android.contact.ConversationAdapter.ConversationListener;
|
||||||
import org.briarproject.briar.android.contact.ConversationVisitor.BodyCache;
|
import org.briarproject.briar.android.contact.ConversationVisitor.TextCache;
|
||||||
import org.briarproject.briar.android.forum.ForumActivity;
|
import org.briarproject.briar.android.forum.ForumActivity;
|
||||||
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
||||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||||
@@ -105,7 +105,7 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_INTRO
|
|||||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
|
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getBulbTransitionName;
|
import static org.briarproject.briar.android.util.UiUtils.getBulbTransitionName;
|
||||||
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
|
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_TEXT_LENGTH;
|
||||||
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED;
|
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED;
|
||||||
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED;
|
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED;
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.S
|
|||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class ConversationActivity extends BriarActivity
|
public class ConversationActivity extends BriarActivity
|
||||||
implements EventListener, ConversationListener, TextInputListener,
|
implements EventListener, ConversationListener, TextInputListener,
|
||||||
BodyCache {
|
TextCache {
|
||||||
|
|
||||||
public static final String CONTACT_ID = "briar.CONTACT_ID";
|
public static final String CONTACT_ID = "briar.CONTACT_ID";
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ public class ConversationActivity extends BriarActivity
|
|||||||
@CryptoExecutor
|
@CryptoExecutor
|
||||||
Executor cryptoExecutor;
|
Executor cryptoExecutor;
|
||||||
|
|
||||||
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
|
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
||||||
private final MutableLiveData<String> contactName = new MutableLiveData<>();
|
private final MutableLiveData<String> contactName = new MutableLiveData<>();
|
||||||
|
|
||||||
private ConversationVisitor visitor;
|
private ConversationVisitor visitor;
|
||||||
@@ -370,28 +370,28 @@ public class ConversationActivity extends BriarActivity
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMessageBody(MessageId m) {
|
private void loadMessageText(MessageId m) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
String body = messagingManager.getMessageBody(m);
|
String text = messagingManager.getMessageText(m);
|
||||||
logDuration(LOG, "Loading body", start);
|
logDuration(LOG, "Loading text", start);
|
||||||
displayMessageBody(m, body);
|
displayMessageText(m, text);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayMessageBody(MessageId m, String body) {
|
private void displayMessageText(MessageId m, String text) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
bodyCache.put(m, body);
|
textCache.put(m, text);
|
||||||
SparseArray<ConversationItem> messages =
|
SparseArray<ConversationItem> messages =
|
||||||
adapter.getPrivateMessages();
|
adapter.getPrivateMessages();
|
||||||
for (int i = 0; i < messages.size(); i++) {
|
for (int i = 0; i < messages.size(); i++) {
|
||||||
ConversationItem item = messages.valueAt(i);
|
ConversationItem item = messages.valueAt(i);
|
||||||
if (item.getId().equals(m)) {
|
if (item.getId().equals(m)) {
|
||||||
item.setBody(body);
|
item.setText(text);
|
||||||
adapter.notifyItemChanged(messages.keyAt(i));
|
adapter.notifyItemChanged(messages.keyAt(i));
|
||||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||||
return;
|
return;
|
||||||
@@ -470,7 +470,7 @@ public class ConversationActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addConversationItem(h.accept(visitor));
|
addConversationItem(h.accept(visitor));
|
||||||
loadMessageBody(h.getId());
|
loadMessageText(h.getId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -495,8 +495,8 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSendClick(String text) {
|
public void onSendClick(String text) {
|
||||||
if (text.equals("")) return;
|
if (text.isEmpty()) return;
|
||||||
text = StringUtils.truncateUtf8(text, MAX_PRIVATE_MESSAGE_BODY_LENGTH);
|
text = StringUtils.truncateUtf8(text, MAX_PRIVATE_MESSAGE_TEXT_LENGTH);
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||||
if (messagingGroupId == null) loadGroupId(text, timestamp);
|
if (messagingGroupId == null) loadGroupId(text, timestamp);
|
||||||
@@ -510,12 +510,12 @@ public class ConversationActivity extends BriarActivity
|
|||||||
return item == null ? 0 : item.getTime() + 1;
|
return item == null ? 0 : item.getTime() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadGroupId(String body, long timestamp) {
|
private void loadGroupId(String text, long timestamp) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
messagingGroupId =
|
messagingGroupId =
|
||||||
messagingManager.getConversationId(contactId);
|
messagingManager.getConversationId(contactId);
|
||||||
createMessage(body, timestamp);
|
createMessage(text, timestamp);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
@@ -523,19 +523,19 @@ public class ConversationActivity extends BriarActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMessage(String body, long timestamp) {
|
private void createMessage(String text, long timestamp) {
|
||||||
cryptoExecutor.execute(() -> {
|
cryptoExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
//noinspection ConstantConditions init in loadGroupId()
|
//noinspection ConstantConditions init in loadGroupId()
|
||||||
storeMessage(privateMessageFactory.createPrivateMessage(
|
storeMessage(privateMessageFactory.createPrivateMessage(
|
||||||
messagingGroupId, timestamp, body), body);
|
messagingGroupId, timestamp, text), text);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeMessage(PrivateMessage m, String body) {
|
private void storeMessage(PrivateMessage m, String text) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
@@ -545,7 +545,7 @@ public class ConversationActivity extends BriarActivity
|
|||||||
PrivateMessageHeader h = new PrivateMessageHeader(
|
PrivateMessageHeader h = new PrivateMessageHeader(
|
||||||
message.getId(), message.getGroupId(),
|
message.getId(), message.getGroupId(),
|
||||||
message.getTimestamp(), true, false, false, false);
|
message.getTimestamp(), true, false, false, false);
|
||||||
bodyCache.put(message.getId(), body);
|
textCache.put(message.getId(), text);
|
||||||
addConversationItem(h.accept(visitor));
|
addConversationItem(h.accept(visitor));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -761,9 +761,9 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String getBody(MessageId m) {
|
public String getText(MessageId m) {
|
||||||
String body = bodyCache.get(m);
|
String text = textCache.get(m);
|
||||||
if (body == null) loadMessageBody(m);
|
if (text == null) loadMessageText(m);
|
||||||
return body;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
abstract class ConversationItem {
|
abstract class ConversationItem {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected String body;
|
protected String text;
|
||||||
private final MessageId id;
|
private final MessageId id;
|
||||||
private final GroupId groupId;
|
private final GroupId groupId;
|
||||||
private final long time;
|
private final long time;
|
||||||
private boolean read;
|
private boolean read;
|
||||||
|
|
||||||
ConversationItem(MessageId id, GroupId groupId, @Nullable String body,
|
ConversationItem(MessageId id, GroupId groupId, @Nullable String text,
|
||||||
long time, boolean read) {
|
long time, boolean read) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.body = body;
|
this.text = text;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
this.read = read;
|
this.read = read;
|
||||||
}
|
}
|
||||||
@@ -37,13 +37,13 @@ abstract class ConversationItem {
|
|||||||
return groupId;
|
return groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBody(String body) {
|
void setText(String text) {
|
||||||
this.body = body;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getBody() {
|
public String getText() {
|
||||||
return body;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
long getTime() {
|
long getTime() {
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ class ConversationItemViewHolder extends ViewHolder {
|
|||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
void bind(ConversationItem item) {
|
void bind(ConversationItem item) {
|
||||||
if (item.getBody() == null) {
|
if (item.getText() == null) {
|
||||||
text.setText("\u2026");
|
text.setText("\u2026");
|
||||||
} else {
|
} else {
|
||||||
text.setText(StringUtils.trim(item.getBody()));
|
text.setText(StringUtils.trim(item.getText()));
|
||||||
}
|
}
|
||||||
|
|
||||||
long timestamp = item.getTime();
|
long timestamp = item.getTime();
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ class ConversationNoticeInViewHolder extends ConversationItemViewHolder {
|
|||||||
ConversationNoticeInItem item =
|
ConversationNoticeInItem item =
|
||||||
(ConversationNoticeInItem) conversationItem;
|
(ConversationNoticeInItem) conversationItem;
|
||||||
|
|
||||||
String message = item.getMsgText();
|
String text = item.getMsgText();
|
||||||
if (StringUtils.isNullOrEmpty(message)) {
|
if (StringUtils.isNullOrEmpty(text)) {
|
||||||
msgText.setVisibility(GONE);
|
msgText.setVisibility(GONE);
|
||||||
layout.setBackgroundResource(R.drawable.notice_in);
|
layout.setBackgroundResource(R.drawable.notice_in);
|
||||||
} else {
|
} else {
|
||||||
msgText.setVisibility(VISIBLE);
|
msgText.setVisibility(VISIBLE);
|
||||||
msgText.setText(StringUtils.trim(message));
|
msgText.setText(StringUtils.trim(text));
|
||||||
layout.setBackgroundResource(R.drawable.notice_in_bottom);
|
layout.setBackgroundResource(R.drawable.notice_in_bottom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class ConversationNoticeOutItem extends ConversationOutItem {
|
|||||||
ConversationNoticeOutItem(String text, PrivateRequest r) {
|
ConversationNoticeOutItem(String text, PrivateRequest r) {
|
||||||
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isSent(),
|
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isSent(),
|
||||||
r.isSeen());
|
r.isSeen());
|
||||||
this.msgText = r.getMessage();
|
this.msgText = r.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationNoticeOutItem(String text, PrivateResponse r) {
|
ConversationNoticeOutItem(String text, PrivateResponse r) {
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ class ConversationNoticeOutViewHolder extends ConversationOutItemViewHolder {
|
|||||||
ConversationNoticeOutItem item =
|
ConversationNoticeOutItem item =
|
||||||
(ConversationNoticeOutItem) conversationItem;
|
(ConversationNoticeOutItem) conversationItem;
|
||||||
|
|
||||||
String message = item.getMsgText();
|
String text = item.getMsgText();
|
||||||
if (StringUtils.isNullOrEmpty(message)) {
|
if (StringUtils.isNullOrEmpty(text)) {
|
||||||
msgText.setVisibility(GONE);
|
msgText.setVisibility(GONE);
|
||||||
layout.setBackgroundResource(R.drawable.notice_out);
|
layout.setBackgroundResource(R.drawable.notice_out);
|
||||||
} else {
|
} else {
|
||||||
msgText.setVisibility(VISIBLE);
|
msgText.setVisibility(VISIBLE);
|
||||||
msgText.setText(StringUtils.trim(message));
|
msgText.setText(StringUtils.trim(text));
|
||||||
layout.setBackgroundResource(R.drawable.notice_out_bottom);
|
layout.setBackgroundResource(R.drawable.notice_out_bottom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class ConversationRequestItem extends ConversationNoticeInItem {
|
|||||||
private boolean answered;
|
private boolean answered;
|
||||||
|
|
||||||
ConversationRequestItem(String text, RequestType type, PrivateRequest r) {
|
ConversationRequestItem(String text, RequestType type, PrivateRequest r) {
|
||||||
super(r.getId(), r.getGroupId(), text, r.getMessage(),
|
super(r.getId(), r.getGroupId(), text, r.getText(),
|
||||||
r.getTimestamp(), r.isRead());
|
r.getTimestamp(), r.isRead());
|
||||||
this.requestType = type;
|
this.requestType = type;
|
||||||
this.sessionId = r.getSessionId();
|
this.sessionId = r.getSessionId();
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ import static org.briarproject.briar.android.contact.ConversationRequestItem.Req
|
|||||||
class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
||||||
|
|
||||||
private final Context ctx;
|
private final Context ctx;
|
||||||
private final BodyCache bodyCache;
|
private final TextCache textCache;
|
||||||
private final LiveData<String> contactName;
|
private final LiveData<String> contactName;
|
||||||
|
|
||||||
ConversationVisitor(Context ctx, BodyCache bodyCache,
|
ConversationVisitor(Context ctx, TextCache textCache,
|
||||||
LiveData<String> contactName) {
|
LiveData<String> contactName) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.bodyCache = bodyCache;
|
this.textCache = textCache;
|
||||||
this.contactName = contactName;
|
this.contactName = contactName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,8 +45,8 @@ class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
|||||||
ConversationItem item;
|
ConversationItem item;
|
||||||
if (h.isLocal()) item = new ConversationMessageOutItem(h);
|
if (h.isLocal()) item = new ConversationMessageOutItem(h);
|
||||||
else item = new ConversationMessageInItem(h);
|
else item = new ConversationMessageInItem(h);
|
||||||
String body = bodyCache.getBody(h.getId());
|
String text = textCache.getText(h.getId());
|
||||||
if (body != null) item.setBody(body);
|
if (text != null) item.setText(text);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,8 +239,8 @@ class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BodyCache {
|
interface TextCache {
|
||||||
@Nullable
|
@Nullable
|
||||||
String getBody(MessageId m);
|
String getText(MessageId m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import javax.inject.Inject;
|
|||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_SHARE_FORUM;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_SHARE_FORUM;
|
||||||
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_TEXT_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -130,8 +130,8 @@ public class ForumActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getMaxBodyLength() {
|
protected int getMaxTextLength() {
|
||||||
return MAX_FORUM_POST_BODY_LENGTH;
|
return MAX_FORUM_POST_TEXT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class ForumControllerImpl extends
|
|||||||
ForumPostReceivedEvent f = (ForumPostReceivedEvent) e;
|
ForumPostReceivedEvent f = (ForumPostReceivedEvent) e;
|
||||||
if (f.getGroupId().equals(getGroupId())) {
|
if (f.getGroupId().equals(getGroupId())) {
|
||||||
LOG.info("Forum post received, adding...");
|
LOG.info("Forum post received, adding...");
|
||||||
onForumPostReceived(f.getHeader(), f.getBody());
|
onForumPostReceived(f.getHeader(), f.getText());
|
||||||
}
|
}
|
||||||
} else if (e instanceof ForumInvitationResponseReceivedEvent) {
|
} else if (e instanceof ForumInvitationResponseReceivedEvent) {
|
||||||
ForumInvitationResponseReceivedEvent f =
|
ForumInvitationResponseReceivedEvent f =
|
||||||
@@ -109,8 +109,8 @@ class ForumControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String loadMessageBody(ForumPostHeader h) throws DbException {
|
protected String loadMessageText(ForumPostHeader h) throws DbException {
|
||||||
return forumManager.getPostBody(h.getId());
|
return forumManager.getPostText(h.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -137,7 +137,7 @@ class ForumControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createAndStoreMessage(String body,
|
public void createAndStoreMessage(String text,
|
||||||
@Nullable ForumItem parentItem,
|
@Nullable ForumItem parentItem,
|
||||||
ResultExceptionHandler<ForumItem, DbException> handler) {
|
ResultExceptionHandler<ForumItem, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
@@ -148,7 +148,7 @@ class ForumControllerImpl extends
|
|||||||
clock.currentTimeMillis());
|
clock.currentTimeMillis());
|
||||||
MessageId parentId = parentItem != null ?
|
MessageId parentId = parentItem != null ?
|
||||||
parentItem.getId() : null;
|
parentItem.getId() : null;
|
||||||
createMessage(body, timestamp, parentId, author, handler);
|
createMessage(text, timestamp, parentId, author, handler);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
handler.onException(e);
|
handler.onException(e);
|
||||||
@@ -156,14 +156,14 @@ class ForumControllerImpl extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMessage(String body, long timestamp,
|
private void createMessage(String text, long timestamp,
|
||||||
@Nullable MessageId parentId, LocalAuthor author,
|
@Nullable MessageId parentId, LocalAuthor author,
|
||||||
ResultExceptionHandler<ForumItem, DbException> handler) {
|
ResultExceptionHandler<ForumItem, DbException> handler) {
|
||||||
cryptoExecutor.execute(() -> {
|
cryptoExecutor.execute(() -> {
|
||||||
LOG.info("Creating forum post...");
|
LOG.info("Creating forum post...");
|
||||||
ForumPost msg = forumManager.createLocalPost(getGroupId(), body,
|
ForumPost msg = forumManager.createLocalPost(getGroupId(), text,
|
||||||
timestamp, parentId, author);
|
timestamp, parentId, author);
|
||||||
storePost(msg, body, handler);
|
storePost(msg, text, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,12 +179,12 @@ class ForumControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ForumItem buildItem(ForumPostHeader header, String body) {
|
protected ForumItem buildItem(ForumPostHeader header, String text) {
|
||||||
return new ForumItem(header, body);
|
return new ForumItem(header, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onForumPostReceived(ForumPostHeader h, String body) {
|
private void onForumPostReceived(ForumPostHeader h, String text) {
|
||||||
ForumItem item = buildItem(h, body);
|
ForumItem item = buildItem(h, text);
|
||||||
listener.runOnUiThreadUnlessDestroyed(
|
listener.runOnUiThreadUnlessDestroyed(
|
||||||
() -> listener.onItemReceived(item));
|
() -> listener.onItemReceived(item));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
class ForumItem extends ThreadItem {
|
class ForumItem extends ThreadItem {
|
||||||
|
|
||||||
ForumItem(ForumPostHeader h, String body) {
|
ForumItem(ForumPostHeader h, String text) {
|
||||||
super(h.getId(), h.getParentId(), body, h.getTimestamp(), h.getAuthor(),
|
super(h.getId(), h.getParentId(), text, h.getTimestamp(), h.getAuthor(),
|
||||||
h.getAuthorStatus(), h.isRead());
|
h.getAuthorStatus(), h.isRead());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ import static android.view.View.VISIBLE;
|
|||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_TEXT_LENGTH;
|
||||||
|
|
||||||
public class IntroductionMessageFragment extends BaseFragment
|
public class IntroductionMessageFragment extends BaseFragment
|
||||||
implements TextInputListener {
|
implements TextInputListener {
|
||||||
@@ -187,10 +187,10 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
// disable button to prevent accidental double invitations
|
// disable button to prevent accidental double invitations
|
||||||
ui.message.setSendButtonEnabled(false);
|
ui.message.setSendButtonEnabled(false);
|
||||||
|
|
||||||
String msg = ui.message.getText().toString();
|
String txt = ui.message.getText().toString();
|
||||||
if (msg.equals("")) msg = null;
|
if (txt.isEmpty()) txt = null;
|
||||||
else msg = StringUtils.truncateUtf8(msg, MAX_REQUEST_MESSAGE_LENGTH);
|
else txt = StringUtils.truncateUtf8(txt, MAX_INTRODUCTION_TEXT_LENGTH);
|
||||||
makeIntroduction(contact1, contact2, msg);
|
makeIntroduction(contact1, contact2, txt);
|
||||||
|
|
||||||
// don't wait for the introduction to be made before finishing activity
|
// don't wait for the introduction to be made before finishing activity
|
||||||
introductionActivity.hideSoftKeyboard(ui.message);
|
introductionActivity.hideSoftKeyboard(ui.message);
|
||||||
@@ -199,12 +199,12 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void makeIntroduction(Contact c1, Contact c2,
|
private void makeIntroduction(Contact c1, Contact c2,
|
||||||
@Nullable String msg) {
|
@Nullable String text) {
|
||||||
introductionActivity.runOnDbThread(() -> {
|
introductionActivity.runOnDbThread(() -> {
|
||||||
// actually make the introduction
|
// actually make the introduction
|
||||||
try {
|
try {
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
introductionManager.makeIntroduction(c1, c2, msg, timestamp);
|
introductionManager.makeIntroduction(c1, c2, text, timestamp);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
introductionError();
|
introductionError();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
|||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
|
|
||||||
private TextView textView;
|
private TextView textView;
|
||||||
private ImageView imageView;
|
private ImageView imageView;
|
||||||
private boolean showingMigration = false;
|
private boolean showingMigration = false, showingCompaction = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
@@ -57,6 +58,7 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
finishAndStartApp();
|
finishAndStartApp();
|
||||||
} else {
|
} else {
|
||||||
if (state == MIGRATING_DATABASE) showMigration();
|
if (state == MIGRATING_DATABASE) showMigration();
|
||||||
|
else if (state == COMPACTING_DATABASE) showCompaction();
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,6 +77,8 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
runOnUiThreadUnlessDestroyed(this::finishAndStartApp);
|
runOnUiThreadUnlessDestroyed(this::finishAndStartApp);
|
||||||
else if (state == MIGRATING_DATABASE)
|
else if (state == MIGRATING_DATABASE)
|
||||||
runOnUiThreadUnlessDestroyed(this::showMigration);
|
runOnUiThreadUnlessDestroyed(this::showMigration);
|
||||||
|
else if (state == COMPACTING_DATABASE)
|
||||||
|
runOnUiThreadUnlessDestroyed(this::showCompaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +89,13 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
showingMigration = true;
|
showingMigration = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showCompaction() {
|
||||||
|
if (showingCompaction) return;
|
||||||
|
textView.setText(R.string.startup_compact_database);
|
||||||
|
imageView.setImageResource(R.drawable.startup_migration);
|
||||||
|
showingCompaction = true;
|
||||||
|
}
|
||||||
|
|
||||||
private void finishAndStartApp() {
|
private void finishAndStartApp() {
|
||||||
startActivity(new Intent(this, NavDrawerActivity.class));
|
startActivity(new Intent(this, NavDrawerActivity.class));
|
||||||
supportFinishAfterTransition();
|
supportFinishAfterTransition();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.briar.android.panic;
|
package org.briarproject.briar.android.panic;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -22,9 +21,14 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import info.guardianproject.panic.Panic;
|
|
||||||
import info.guardianproject.panic.PanicResponder;
|
import info.guardianproject.panic.PanicResponder;
|
||||||
|
|
||||||
|
import static android.app.Activity.RESULT_CANCELED;
|
||||||
|
import static android.app.Activity.RESULT_OK;
|
||||||
|
import static android.content.Intent.ACTION_VIEW;
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
|
import static info.guardianproject.panic.Panic.PACKAGE_NAME_NONE;
|
||||||
|
|
||||||
public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
@@ -42,7 +46,9 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle bundle, String s) {
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
addPreferencesFromResource(R.xml.panic_preferences);
|
addPreferencesFromResource(R.xml.panic_preferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePreferences() {
|
||||||
pm = getActivity().getPackageManager();
|
pm = getActivity().getPackageManager();
|
||||||
|
|
||||||
lockPref = (SwitchPreference) findPreference(KEY_LOCK);
|
lockPref = (SwitchPreference) findPreference(KEY_LOCK);
|
||||||
@@ -74,7 +80,7 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
ArrayList<CharSequence> entries = new ArrayList<>();
|
ArrayList<CharSequence> entries = new ArrayList<>();
|
||||||
ArrayList<CharSequence> entryValues = new ArrayList<>();
|
ArrayList<CharSequence> entryValues = new ArrayList<>();
|
||||||
entries.add(0, getString(R.string.panic_app_setting_none));
|
entries.add(0, getString(R.string.panic_app_setting_none));
|
||||||
entryValues.add(0, Panic.PACKAGE_NAME_NONE);
|
entryValues.add(0, PACKAGE_NAME_NONE);
|
||||||
|
|
||||||
for (ResolveInfo resolveInfo : PanicResponder.resolveTriggerApps(pm)) {
|
for (ResolveInfo resolveInfo : PanicResponder.resolveTriggerApps(pm)) {
|
||||||
if (resolveInfo.activityInfo == null)
|
if (resolveInfo.activityInfo == null)
|
||||||
@@ -83,21 +89,19 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
entryValues.add(resolveInfo.activityInfo.packageName);
|
entryValues.add(resolveInfo.activityInfo.packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
panicAppPref.setEntries(
|
panicAppPref.setEntries(entries.toArray(new CharSequence[0]));
|
||||||
entries.toArray(new CharSequence[entries.size()]));
|
panicAppPref.setEntryValues(entryValues.toArray(new CharSequence[0]));
|
||||||
panicAppPref.setEntryValues(
|
panicAppPref.setDefaultValue(PACKAGE_NAME_NONE);
|
||||||
entryValues.toArray(new CharSequence[entryValues.size()]));
|
|
||||||
panicAppPref.setDefaultValue(Panic.PACKAGE_NAME_NONE);
|
|
||||||
|
|
||||||
panicAppPref.setOnPreferenceChangeListener((preference, newValue) -> {
|
panicAppPref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
String packageName = (String) newValue;
|
String packageName = (String) newValue;
|
||||||
PanicResponder.setTriggerPackageName(getActivity(), packageName);
|
PanicResponder.setTriggerPackageName(getActivity(), packageName);
|
||||||
showPanicApp(packageName);
|
showPanicApp(packageName);
|
||||||
|
|
||||||
if (packageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
if (packageName.equals(PACKAGE_NAME_NONE)) {
|
||||||
purgePref.setChecked(false);
|
purgePref.setChecked(false);
|
||||||
purgePref.setEnabled(false);
|
purgePref.setEnabled(false);
|
||||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
getActivity().setResult(RESULT_CANCELED);
|
||||||
} else {
|
} else {
|
||||||
purgePref.setEnabled(true);
|
purgePref.setEnabled(true);
|
||||||
}
|
}
|
||||||
@@ -107,16 +111,18 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
|
|
||||||
if (entries.size() <= 1) {
|
if (entries.size() <= 1) {
|
||||||
panicAppPref.setOnPreferenceClickListener(preference -> {
|
panicAppPref.setOnPreferenceClickListener(preference -> {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(
|
intent.setData(Uri.parse(
|
||||||
"market://details?id=info.guardianproject.ripple"));
|
"market://details?id=info.guardianproject.ripple"));
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||||
if (intent.resolveActivity(getActivity().getPackageManager())
|
if (intent.resolveActivity(getActivity().getPackageManager())
|
||||||
!= null) {
|
!= null) {
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
panicAppPref.setOnPreferenceClickListener(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +131,7 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
super.onStart();
|
super.onStart();
|
||||||
getPreferenceScreen().getSharedPreferences()
|
getPreferenceScreen().getSharedPreferences()
|
||||||
.registerOnSharedPreferenceChangeListener(this);
|
.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
updatePreferences();
|
||||||
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,9 +159,9 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
|
|
||||||
private void showPanicApp(String triggerPackageName) {
|
private void showPanicApp(String triggerPackageName) {
|
||||||
if (TextUtils.isEmpty(triggerPackageName)
|
if (TextUtils.isEmpty(triggerPackageName)
|
||||||
|| triggerPackageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
|| triggerPackageName.equals(PACKAGE_NAME_NONE)) {
|
||||||
// no panic app set
|
// no panic app set
|
||||||
panicAppPref.setValue(Panic.PACKAGE_NAME_NONE);
|
panicAppPref.setValue(PACKAGE_NAME_NONE);
|
||||||
panicAppPref
|
panicAppPref
|
||||||
.setSummary(getString(R.string.panic_app_setting_summary));
|
.setSummary(getString(R.string.panic_app_setting_summary));
|
||||||
panicAppPref.setIcon(
|
panicAppPref.setIcon(
|
||||||
@@ -176,8 +183,8 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
// revert back to no app, just to be safe
|
// revert back to no app, just to be safe
|
||||||
PanicResponder.setTriggerPackageName(getActivity(),
|
PanicResponder.setTriggerPackageName(getActivity(),
|
||||||
Panic.PACKAGE_NAME_NONE);
|
PACKAGE_NAME_NONE);
|
||||||
showPanicApp(Panic.PACKAGE_NAME_NONE);
|
showPanicApp(PACKAGE_NAME_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,10 +193,10 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
||||||
PanicResponder.setTriggerPackageName(getActivity());
|
PanicResponder.setTriggerPackageName(getActivity());
|
||||||
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
||||||
getActivity().setResult(Activity.RESULT_OK);
|
getActivity().setResult(RESULT_OK);
|
||||||
};
|
};
|
||||||
DialogInterface.OnClickListener cancelListener = (dialog, which) -> {
|
DialogInterface.OnClickListener cancelListener = (dialog, which) -> {
|
||||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
getActivity().setResult(RESULT_CANCELED);
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import javax.inject.Inject;
|
|||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_GROUP_INVITE;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_GROUP_INVITE;
|
||||||
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
|
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_TEXT_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -179,8 +179,8 @@ public class GroupActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getMaxBodyLength() {
|
protected int getMaxTextLength() {
|
||||||
return MAX_GROUP_POST_BODY_LENGTH;
|
return MAX_GROUP_POST_TEXT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class GroupControllerImpl extends
|
|||||||
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
|
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
|
||||||
if (!g.isLocal() && g.getGroupId().equals(getGroupId())) {
|
if (!g.isLocal() && g.getGroupId().equals(getGroupId())) {
|
||||||
LOG.info("Group message received, adding...");
|
LOG.info("Group message received, adding...");
|
||||||
GroupMessageItem item = buildItem(g.getHeader(), g.getBody());
|
GroupMessageItem item = buildItem(g.getHeader(), g.getText());
|
||||||
listener.runOnUiThreadUnlessDestroyed(
|
listener.runOnUiThreadUnlessDestroyed(
|
||||||
() -> listener.onItemReceived(item));
|
() -> listener.onItemReceived(item));
|
||||||
}
|
}
|
||||||
@@ -124,13 +124,13 @@ class GroupControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String loadMessageBody(GroupMessageHeader header)
|
protected String loadMessageText(GroupMessageHeader header)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
if (header instanceof JoinMessageHeader) {
|
if (header instanceof JoinMessageHeader) {
|
||||||
// will be looked up later
|
// will be looked up later
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return privateGroupManager.getMessageBody(header.getId());
|
return privateGroupManager.getMessageText(header.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -159,7 +159,7 @@ class GroupControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createAndStoreMessage(String body,
|
public void createAndStoreMessage(String text,
|
||||||
@Nullable GroupMessageItem parentItem,
|
@Nullable GroupMessageItem parentItem,
|
||||||
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
@@ -173,7 +173,7 @@ class GroupControllerImpl extends
|
|||||||
long timestamp = count.getLatestMsgTime();
|
long timestamp = count.getLatestMsgTime();
|
||||||
if (parentItem != null) parentId = parentItem.getId();
|
if (parentItem != null) parentId = parentItem.getId();
|
||||||
timestamp = max(clock.currentTimeMillis(), timestamp + 1);
|
timestamp = max(clock.currentTimeMillis(), timestamp + 1);
|
||||||
createMessage(body, timestamp, parentId, author, previousMsgId,
|
createMessage(text, timestamp, parentId, author, previousMsgId,
|
||||||
handler);
|
handler);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -182,7 +182,7 @@ class GroupControllerImpl extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMessage(String body, long timestamp,
|
private void createMessage(String text, long timestamp,
|
||||||
@Nullable MessageId parentId, LocalAuthor author,
|
@Nullable MessageId parentId, LocalAuthor author,
|
||||||
MessageId previousMsgId,
|
MessageId previousMsgId,
|
||||||
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||||
@@ -190,8 +190,8 @@ class GroupControllerImpl extends
|
|||||||
LOG.info("Creating group message...");
|
LOG.info("Creating group message...");
|
||||||
GroupMessage msg = groupMessageFactory
|
GroupMessage msg = groupMessageFactory
|
||||||
.createGroupMessage(getGroupId(), timestamp,
|
.createGroupMessage(getGroupId(), timestamp,
|
||||||
parentId, author, body, previousMsgId);
|
parentId, author, text, previousMsgId);
|
||||||
storePost(msg, body, handler);
|
storePost(msg, text, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,11 +208,11 @@ class GroupControllerImpl extends
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GroupMessageItem buildItem(GroupMessageHeader header,
|
protected GroupMessageItem buildItem(GroupMessageHeader header,
|
||||||
String body) {
|
String text) {
|
||||||
if (header instanceof JoinMessageHeader) {
|
if (header instanceof JoinMessageHeader) {
|
||||||
return new JoinMessageItem((JoinMessageHeader) header, body);
|
return new JoinMessageItem((JoinMessageHeader) header, text);
|
||||||
}
|
}
|
||||||
return new GroupMessageItem(header, body);
|
return new GroupMessageItem(header, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ public interface CreateGroupController
|
|||||||
ResultExceptionHandler<GroupId, DbException> result);
|
ResultExceptionHandler<GroupId, DbException> result);
|
||||||
|
|
||||||
void sendInvitation(GroupId g, Collection<ContactId> contacts,
|
void sendInvitation(GroupId g, Collection<ContactId> contacts,
|
||||||
String message, ResultExceptionHandler<Void, DbException> result);
|
String text, ResultExceptionHandler<Void, DbException> result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendInvitation(GroupId g, Collection<ContactId> contactIds,
|
public void sendInvitation(GroupId g, Collection<ContactId> contactIds,
|
||||||
String message, ResultExceptionHandler<Void, DbException> handler) {
|
String text, ResultExceptionHandler<Void, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||||
@@ -135,7 +135,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
// Continue
|
// Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signInvitations(g, localAuthor, contacts, message, handler);
|
signInvitations(g, localAuthor, contacts, text, handler);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
handler.onException(e);
|
handler.onException(e);
|
||||||
@@ -144,7 +144,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void signInvitations(GroupId g, LocalAuthor localAuthor,
|
private void signInvitations(GroupId g, LocalAuthor localAuthor,
|
||||||
Collection<Contact> contacts, String message,
|
Collection<Contact> contacts, String text,
|
||||||
ResultExceptionHandler<Void, DbException> handler) {
|
ResultExceptionHandler<Void, DbException> handler) {
|
||||||
cryptoExecutor.execute(() -> {
|
cryptoExecutor.execute(() -> {
|
||||||
long timestamp = clock.currentTimeMillis();
|
long timestamp = clock.currentTimeMillis();
|
||||||
@@ -155,20 +155,20 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
contexts.add(new InvitationContext(c.getId(), timestamp,
|
contexts.add(new InvitationContext(c.getId(), timestamp,
|
||||||
signature));
|
signature));
|
||||||
}
|
}
|
||||||
sendInvitations(g, contexts, message, handler);
|
sendInvitations(g, contexts, text, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendInvitations(GroupId g,
|
private void sendInvitations(GroupId g,
|
||||||
Collection<InvitationContext> contexts, String message,
|
Collection<InvitationContext> contexts, String text,
|
||||||
ResultExceptionHandler<Void, DbException> handler) {
|
ResultExceptionHandler<Void, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
String msg = message.isEmpty() ? null : message;
|
String txt = text.isEmpty() ? null : text;
|
||||||
for (InvitationContext context : contexts) {
|
for (InvitationContext context : contexts) {
|
||||||
try {
|
try {
|
||||||
groupInvitationManager.sendInvitation(g,
|
groupInvitationManager.sendInvitation(g,
|
||||||
context.contactId, msg, context.timestamp,
|
context.contactId, txt, context.timestamp,
|
||||||
context.signature);
|
context.signature);
|
||||||
} catch (NoSuchContactException e) {
|
} catch (NoSuchContactException e) {
|
||||||
// Continue
|
// Continue
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.util.Collection;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
|
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_TEXT_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -55,10 +55,10 @@ public class GroupInviteActivity extends ContactSelectorActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onButtonClick(String message) {
|
public boolean onButtonClick(String text) {
|
||||||
if (groupId == null)
|
if (groupId == null)
|
||||||
throw new IllegalStateException("GroupId was not initialized");
|
throw new IllegalStateException("GroupId was not initialized");
|
||||||
controller.sendInvitation(groupId, contacts, message,
|
controller.sendInvitation(groupId, contacts, text,
|
||||||
new UiResultExceptionHandler<Void, DbException>(this) {
|
new UiResultExceptionHandler<Void, DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onResultUi(Void result) {
|
public void onResultUi(Void result) {
|
||||||
@@ -76,7 +76,7 @@ public class GroupInviteActivity extends ContactSelectorActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaximumMessageLength() {
|
public int getMaximumTextLength() {
|
||||||
return MAX_GROUP_INVITATION_MSG_LENGTH;
|
return MAX_GROUP_INVITATION_TEXT_LENGTH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.support.annotation.NonNull;
|
|||||||
import org.acra.collector.CrashReportData;
|
import org.acra.collector.CrashReportData;
|
||||||
import org.acra.sender.ReportSender;
|
import org.acra.sender.ReportSender;
|
||||||
import org.acra.sender.ReportSenderException;
|
import org.acra.sender.ReportSenderException;
|
||||||
import org.acra.util.JSONReportBuilder.JSONReportException;
|
|
||||||
import org.briarproject.bramble.api.reporting.DevReporter;
|
import org.briarproject.bramble.api.reporting.DevReporter;
|
||||||
import org.briarproject.bramble.util.AndroidUtils;
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
import org.briarproject.briar.android.AndroidComponent;
|
import org.briarproject.briar.android.AndroidComponent;
|
||||||
@@ -34,12 +33,7 @@ public class BriarReportSender implements ReportSender {
|
|||||||
@NonNull CrashReportData errorContent)
|
@NonNull CrashReportData errorContent)
|
||||||
throws ReportSenderException {
|
throws ReportSenderException {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
String crashReport;
|
String crashReport = errorContent.toJSON().toString();
|
||||||
try {
|
|
||||||
crashReport = errorContent.toJSON().toString();
|
|
||||||
} catch (JSONReportException e) {
|
|
||||||
throw new ReportSenderException("Couldn't create JSON", e);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
File reportDir = AndroidUtils.getReportDir(ctx);
|
File reportDir = AndroidUtils.getReportDir(ctx);
|
||||||
String reportId = errorContent.getProperty(REPORT_ID);
|
String reportId = errorContent.getProperty(REPORT_ID);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.briar.android.reporting;
|
package org.briarproject.briar.android.reporting;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -23,8 +24,11 @@ import org.acra.ReportField;
|
|||||||
import org.acra.collector.CrashReportData;
|
import org.acra.collector.CrashReportData;
|
||||||
import org.acra.dialog.BaseCrashReportDialog;
|
import org.acra.dialog.BaseCrashReportDialog;
|
||||||
import org.acra.file.CrashReportPersister;
|
import org.acra.file.CrashReportPersister;
|
||||||
|
import org.acra.model.Element;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
|
import org.briarproject.briar.android.Localizer;
|
||||||
import org.briarproject.briar.android.util.UserFeedback;
|
import org.briarproject.briar.android.util.UserFeedback;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -38,6 +42,7 @@ import static android.os.Build.VERSION.SDK_INT;
|
|||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.INVISIBLE;
|
import static android.view.View.INVISIBLE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||||
import static android.view.inputmethod.InputMethodManager.SHOW_FORCED;
|
import static android.view.inputmethod.InputMethodManager.SHOW_FORCED;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.acra.ACRAConstants.EXTRA_REPORT_FILE;
|
import static org.acra.ACRAConstants.EXTRA_REPORT_FILE;
|
||||||
@@ -47,6 +52,7 @@ import static org.acra.ReportField.APP_VERSION_NAME;
|
|||||||
import static org.acra.ReportField.PACKAGE_NAME;
|
import static org.acra.ReportField.PACKAGE_NAME;
|
||||||
import static org.acra.ReportField.REPORT_ID;
|
import static org.acra.ReportField.REPORT_ID;
|
||||||
import static org.acra.ReportField.STACK_TRACE;
|
import static org.acra.ReportField.STACK_TRACE;
|
||||||
|
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
||||||
|
|
||||||
public class DevReportActivity extends BaseCrashReportDialog
|
public class DevReportActivity extends BaseCrashReportDialog
|
||||||
implements CompoundButton.OnCheckedChangeListener {
|
implements CompoundButton.OnCheckedChangeListener {
|
||||||
@@ -107,6 +113,8 @@ public class DevReportActivity extends BaseCrashReportDialog
|
|||||||
public void init(Bundle state) {
|
public void init(Bundle state) {
|
||||||
super.init(state);
|
super.init(state);
|
||||||
|
|
||||||
|
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
|
||||||
|
|
||||||
getDelegate().setContentView(R.layout.activity_dev_report);
|
getDelegate().setContentView(R.layout.activity_dev_report);
|
||||||
|
|
||||||
Toolbar tb = findViewById(R.id.toolbar);
|
Toolbar tb = findViewById(R.id.toolbar);
|
||||||
@@ -166,6 +174,12 @@ public class DevReportActivity extends BaseCrashReportDialog
|
|||||||
requestReport.setVisibility(VISIBLE);
|
requestReport.setVisibility(VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void attachBaseContext(Context base) {
|
||||||
|
super.attachBaseContext(
|
||||||
|
Localizer.getInstance().setLocale(base));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPostCreate(Bundle state) {
|
public void onPostCreate(Bundle state) {
|
||||||
super.onPostCreate(state);
|
super.onPostCreate(state);
|
||||||
@@ -270,7 +284,7 @@ public class DevReportActivity extends BaseCrashReportDialog
|
|||||||
CrashReportPersister persister = new CrashReportPersister();
|
CrashReportPersister persister = new CrashReportPersister();
|
||||||
try {
|
try {
|
||||||
return persister.load(reportFile);
|
return persister.load(reportFile);
|
||||||
} catch (IOException e) {
|
} catch (IOException | JSONException e) {
|
||||||
LOG.log(WARNING, "Could not load report file", e);
|
LOG.log(WARNING, "Could not load report file", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -280,9 +294,10 @@ public class DevReportActivity extends BaseCrashReportDialog
|
|||||||
protected void onPostExecute(CrashReportData crashData) {
|
protected void onPostExecute(CrashReportData crashData) {
|
||||||
LayoutInflater inflater = getLayoutInflater();
|
LayoutInflater inflater = getLayoutInflater();
|
||||||
if (crashData != null) {
|
if (crashData != null) {
|
||||||
for (Entry<ReportField, String> e : crashData.entrySet()) {
|
for (Entry<ReportField, Element> e : crashData.entrySet()) {
|
||||||
ReportField field = e.getKey();
|
ReportField field = e.getKey();
|
||||||
String value = e.getValue().replaceAll("\\\\n", "\n");
|
String value = e.getValue().toString()
|
||||||
|
.replaceAll("\\\\n", "\n");
|
||||||
boolean required = requiredFields.contains(field);
|
boolean required = requiredFields.contains(field);
|
||||||
boolean excluded = excludedFields.contains(field);
|
boolean excluded = excludedFields.contains(field);
|
||||||
View v = inflater.inflate(R.layout.list_item_crash,
|
View v = inflater.inflate(R.layout.list_item_crash,
|
||||||
@@ -331,10 +346,10 @@ public class DevReportActivity extends BaseCrashReportDialog
|
|||||||
data.remove(field);
|
data.remove(field);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Iterator<Entry<ReportField, String>> iter =
|
Iterator<Entry<ReportField, Element>> iter =
|
||||||
data.entrySet().iterator();
|
data.entrySet().iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
Entry<ReportField, String> e = iter.next();
|
Entry<ReportField, Element> e = iter.next();
|
||||||
if (!requiredFields.contains(e.getKey())) {
|
if (!requiredFields.contains(e.getKey())) {
|
||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
@@ -342,7 +357,7 @@ public class DevReportActivity extends BaseCrashReportDialog
|
|||||||
}
|
}
|
||||||
persister.store(data, reportFile);
|
persister.store(data, reportFile);
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException | JSONException e) {
|
||||||
LOG.log(WARNING, "Error processing report file", e);
|
LOG.log(WARNING, "Error processing report file", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.android.view.LargeTextInputView;
|
import org.briarproject.briar.android.view.LargeTextInputView;
|
||||||
@@ -19,7 +18,8 @@ import org.briarproject.briar.android.view.TextInputView.TextInputListener;
|
|||||||
|
|
||||||
import static android.support.design.widget.Snackbar.LENGTH_SHORT;
|
import static android.support.design.widget.Snackbar.LENGTH_SHORT;
|
||||||
import static org.briarproject.bramble.util.StringUtils.truncateUtf8;
|
import static org.briarproject.bramble.util.StringUtils.truncateUtf8;
|
||||||
import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_MESSAGE_LENGTH;
|
import static org.briarproject.bramble.util.StringUtils.utf8IsTooLong;
|
||||||
|
import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_TEXT_LENGTH;
|
||||||
|
|
||||||
public abstract class BaseMessageFragment extends BaseFragment
|
public abstract class BaseMessageFragment extends BaseFragment
|
||||||
implements TextInputListener {
|
implements TextInputListener {
|
||||||
@@ -76,8 +76,8 @@ public abstract class BaseMessageFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSendClick(String msg) {
|
public void onSendClick(String text) {
|
||||||
if (StringUtils.utf8IsTooLong(msg, listener.getMaximumMessageLength())) {
|
if (utf8IsTooLong(text, listener.getMaximumTextLength())) {
|
||||||
Snackbar.make(message, R.string.text_too_long, LENGTH_SHORT).show();
|
Snackbar.make(message, R.string.text_too_long, LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -86,8 +86,8 @@ public abstract class BaseMessageFragment extends BaseFragment
|
|||||||
message.setSendButtonEnabled(false);
|
message.setSendButtonEnabled(false);
|
||||||
message.hideSoftKeyboard();
|
message.hideSoftKeyboard();
|
||||||
|
|
||||||
msg = truncateUtf8(msg, MAX_INVITATION_MESSAGE_LENGTH);
|
text = truncateUtf8(text, MAX_INVITATION_TEXT_LENGTH);
|
||||||
if(!listener.onButtonClick(msg)) {
|
if(!listener.onButtonClick(text)) {
|
||||||
message.setSendButtonEnabled(true);
|
message.setSendButtonEnabled(true);
|
||||||
message.showSoftKeyboard();
|
message.showSoftKeyboard();
|
||||||
}
|
}
|
||||||
@@ -102,9 +102,9 @@ public abstract class BaseMessageFragment extends BaseFragment
|
|||||||
void setTitle(@StringRes int titleRes);
|
void setTitle(@StringRes int titleRes);
|
||||||
|
|
||||||
/** Returns true when the button click has been consumed. */
|
/** Returns true when the button click has been consumed. */
|
||||||
boolean onButtonClick(String message);
|
boolean onButtonClick(String text);
|
||||||
|
|
||||||
int getMaximumMessageLength();
|
int getMaximumTextLength();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ public abstract class ShareActivity extends ContactSelectorActivity
|
|||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@Override
|
@Override
|
||||||
public boolean onButtonClick(String message) {
|
public boolean onButtonClick(String text) {
|
||||||
share(contacts, message);
|
share(contacts, text);
|
||||||
setResult(RESULT_OK);
|
setResult(RESULT_OK);
|
||||||
supportFinishAfterTransition();
|
supportFinishAfterTransition();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void share(Collection<ContactId> contacts, String msg);
|
abstract void share(Collection<ContactId> contacts, String text);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_TEXT_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -46,13 +46,13 @@ public class ShareBlogActivity extends ShareActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaximumMessageLength() {
|
public int getMaximumTextLength() {
|
||||||
return MAX_MESSAGE_BODY_LENGTH;
|
return MAX_INVITATION_TEXT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void share(Collection<ContactId> contacts, String msg) {
|
void share(Collection<ContactId> contacts, String text) {
|
||||||
controller.share(groupId, contacts, msg,
|
controller.share(groupId, contacts, text,
|
||||||
new UiExceptionHandler<DbException>(this) {
|
new UiExceptionHandler<DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onExceptionUi(DbException exception) {
|
public void onExceptionUi(DbException exception) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import java.util.Collection;
|
|||||||
public interface ShareBlogController
|
public interface ShareBlogController
|
||||||
extends ContactSelectorController<SelectableContactItem> {
|
extends ContactSelectorController<SelectableContactItem> {
|
||||||
|
|
||||||
void share(GroupId g, Collection<ContactId> contacts, String msg,
|
void share(GroupId g, Collection<ContactId> contacts, String text,
|
||||||
ExceptionHandler<DbException> handler);
|
ExceptionHandler<DbException> handler);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,17 +56,17 @@ class ShareBlogControllerImpl extends ContactSelectorControllerImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void share(GroupId g, Collection<ContactId> contacts, String message,
|
public void share(GroupId g, Collection<ContactId> contacts, String text,
|
||||||
ExceptionHandler<DbException> handler) {
|
ExceptionHandler<DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
String msg = isNullOrEmpty(message) ? null : message;
|
String txt = isNullOrEmpty(text) ? null : text;
|
||||||
for (ContactId c : contacts) {
|
for (ContactId c : contacts) {
|
||||||
try {
|
try {
|
||||||
long time = Math.max(clock.currentTimeMillis(),
|
long time = Math.max(clock.currentTimeMillis(),
|
||||||
conversationManager.getGroupCount(c)
|
conversationManager.getGroupCount(c)
|
||||||
.getLatestMsgTime() + 1);
|
.getLatestMsgTime() + 1);
|
||||||
blogSharingManager.sendInvitation(g, c, msg, time);
|
blogSharingManager.sendInvitation(g, c, txt, time);
|
||||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
import static org.briarproject.briar.api.sharing.SharingConstants.MAX_INVITATION_TEXT_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -46,13 +46,13 @@ public class ShareForumActivity extends ShareActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaximumMessageLength() {
|
public int getMaximumTextLength() {
|
||||||
return MAX_MESSAGE_BODY_LENGTH;
|
return MAX_INVITATION_TEXT_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void share(Collection<ContactId> contacts, String msg) {
|
void share(Collection<ContactId> contacts, String text) {
|
||||||
controller.share(groupId, contacts, msg,
|
controller.share(groupId, contacts, text,
|
||||||
new UiExceptionHandler<DbException>(this) {
|
new UiExceptionHandler<DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onExceptionUi(DbException exception) {
|
public void onExceptionUi(DbException exception) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import java.util.Collection;
|
|||||||
public interface ShareForumController
|
public interface ShareForumController
|
||||||
extends ContactSelectorController<SelectableContactItem> {
|
extends ContactSelectorController<SelectableContactItem> {
|
||||||
|
|
||||||
void share(GroupId g, Collection<ContactId> contacts, String msg,
|
void share(GroupId g, Collection<ContactId> contacts, String text,
|
||||||
ExceptionHandler<DbException> handler);
|
ExceptionHandler<DbException> handler);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,16 +57,16 @@ class ShareForumControllerImpl extends ContactSelectorControllerImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void share(GroupId g, Collection<ContactId> contacts,
|
public void share(GroupId g, Collection<ContactId> contacts,
|
||||||
String message, ExceptionHandler<DbException> handler) {
|
String text, ExceptionHandler<DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
String msg = isNullOrEmpty(message) ? null : message;
|
String txt = isNullOrEmpty(text) ? null : text;
|
||||||
for (ContactId c : contacts) {
|
for (ContactId c : contacts) {
|
||||||
try {
|
try {
|
||||||
long time = Math.max(clock.currentTimeMillis(),
|
long time = Math.max(clock.currentTimeMillis(),
|
||||||
conversationManager.getGroupCount(c)
|
conversationManager.getGroupCount(c)
|
||||||
.getLatestMsgTime() + 1);
|
.getLatestMsgTime() + 1);
|
||||||
forumSharingManager.sendInvitation(g, c, msg, time);
|
forumSharingManager.sendInvitation(g, c, txt, time);
|
||||||
} catch (NoSuchContactException | NoSuchGroupException e) {
|
} catch (NoSuchContactException | NoSuchGroupException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.controller.SharingController;
|
import org.briarproject.briar.android.controller.SharingController;
|
||||||
@@ -43,6 +42,7 @@ import static android.support.design.widget.Snackbar.make;
|
|||||||
import static android.support.v7.widget.RecyclerView.NO_POSITION;
|
import static android.support.v7.widget.RecyclerView.NO_POSITION;
|
||||||
import static android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE;
|
import static android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.utf8IsTooLong;
|
||||||
import static org.briarproject.briar.android.threaded.ThreadItemAdapter.UnreadCount;
|
import static org.briarproject.briar.android.threaded.ThreadItemAdapter.UnreadCount;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -351,7 +351,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
public void onSendClick(String text) {
|
public void onSendClick(String text) {
|
||||||
if (text.trim().length() == 0)
|
if (text.trim().length() == 0)
|
||||||
return;
|
return;
|
||||||
if (StringUtils.utf8IsTooLong(text, getMaxBodyLength())) {
|
if (utf8IsTooLong(text, getMaxTextLength())) {
|
||||||
displaySnackbar(R.string.text_too_long);
|
displaySnackbar(R.string.text_too_long);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -375,7 +375,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
updateTextInput();
|
updateTextInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract int getMaxBodyLength();
|
protected abstract int getMaxTextLength();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemReceived(I item) {
|
public void onItemReceived(I item) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public interface ThreadListController<G extends NamedGroup, I extends ThreadItem
|
|||||||
|
|
||||||
void markItemsRead(Collection<I> items);
|
void markItemsRead(Collection<I> items);
|
||||||
|
|
||||||
void createAndStoreMessage(String body, @Nullable I parentItem,
|
void createAndStoreMessage(String text, @Nullable I parentItem,
|
||||||
ResultExceptionHandler<I, DbException> handler);
|
ResultExceptionHandler<I, DbException> handler);
|
||||||
|
|
||||||
void deleteNamedGroup(ExceptionHandler<DbException> handler);
|
void deleteNamedGroup(ExceptionHandler<DbException> handler);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
Logger.getLogger(ThreadListControllerImpl.class.getName());
|
Logger.getLogger(ThreadListControllerImpl.class.getName());
|
||||||
|
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
|
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
||||||
private volatile GroupId groupId;
|
private volatile GroupId groupId;
|
||||||
|
|
||||||
protected final IdentityManager identityManager;
|
protected final IdentityManager identityManager;
|
||||||
@@ -161,9 +161,9 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
// Load bodies into cache
|
// Load bodies into cache
|
||||||
start = now();
|
start = now();
|
||||||
for (H header : headers) {
|
for (H header : headers) {
|
||||||
if (!bodyCache.containsKey(header.getId())) {
|
if (!textCache.containsKey(header.getId())) {
|
||||||
bodyCache.put(header.getId(),
|
textCache.put(header.getId(),
|
||||||
loadMessageBody(header));
|
loadMessageText(header));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logDuration(LOG, "Loading bodies", start);
|
logDuration(LOG, "Loading bodies", start);
|
||||||
@@ -181,7 +181,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
protected abstract Collection<H> loadHeaders() throws DbException;
|
protected abstract Collection<H> loadHeaders() throws DbException;
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
protected abstract String loadMessageBody(H header) throws DbException;
|
protected abstract String loadMessageText(H header) throws DbException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void markItemRead(I item) {
|
public void markItemRead(I item) {
|
||||||
@@ -206,15 +206,15 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
protected abstract void markRead(MessageId id) throws DbException;
|
protected abstract void markRead(MessageId id) throws DbException;
|
||||||
|
|
||||||
protected void storePost(M msg, String body,
|
protected void storePost(M msg, String text,
|
||||||
ResultExceptionHandler<I, DbException> resultHandler) {
|
ResultExceptionHandler<I, DbException> resultHandler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
H header = addLocalMessage(msg);
|
H header = addLocalMessage(msg);
|
||||||
bodyCache.put(msg.getMessage().getId(), body);
|
textCache.put(msg.getMessage().getId(), text);
|
||||||
logDuration(LOG, "Storing message", start);
|
logDuration(LOG, "Storing message", start);
|
||||||
resultHandler.onResult(buildItem(header, body));
|
resultHandler.onResult(buildItem(header, text));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
resultHandler.onException(e);
|
resultHandler.onException(e);
|
||||||
@@ -247,7 +247,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
throws DbException {
|
throws DbException {
|
||||||
ThreadItemList<I> items = new ThreadItemListImpl<>();
|
ThreadItemList<I> items = new ThreadItemListImpl<>();
|
||||||
for (H h : headers) {
|
for (H h : headers) {
|
||||||
items.add(buildItem(h, bodyCache.get(h.getId())));
|
items.add(buildItem(h, textCache.get(h.getId())));
|
||||||
}
|
}
|
||||||
MessageId msgId = messageTracker.loadStoredMessageId(groupId);
|
MessageId msgId = messageTracker.loadStoredMessageId(groupId);
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
@@ -256,7 +256,7 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract I buildItem(H header, String body);
|
protected abstract I buildItem(H header, String text);
|
||||||
|
|
||||||
protected GroupId getGroupId() {
|
protected GroupId getGroupId() {
|
||||||
checkGroupId();
|
checkGroupId();
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
|
import org.briarproject.briar.android.threaded.ThreadItemAdapter.ThreadItemListener;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
@@ -45,7 +47,8 @@ public class ThreadPostViewHolder<I extends ThreadItem>
|
|||||||
}
|
}
|
||||||
if (item.getLevel() > 5) {
|
if (item.getLevel() > 5) {
|
||||||
lvlText.setVisibility(VISIBLE);
|
lvlText.setVisibility(VISIBLE);
|
||||||
lvlText.setText(String.valueOf(item.getLevel()));
|
lvlText.setText(
|
||||||
|
String.format(Locale.getDefault(), "%d", item.getLevel()));
|
||||||
} else {
|
} else {
|
||||||
lvlText.setVisibility(GONE);
|
lvlText.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,13 +106,13 @@ public class UiUtils {
|
|||||||
return (int) daysBeforeExpiry;
|
return (int) daysBeforeExpiry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SpannableStringBuilder getTeaser(Context ctx, Spanned body) {
|
public static SpannableStringBuilder getTeaser(Context ctx, Spanned text) {
|
||||||
if (body.length() < TEASER_LENGTH)
|
if (text.length() < TEASER_LENGTH)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"String is shorter than TEASER_LENGTH");
|
"String is shorter than TEASER_LENGTH");
|
||||||
|
|
||||||
SpannableStringBuilder builder =
|
SpannableStringBuilder builder =
|
||||||
new SpannableStringBuilder(body.subSequence(0, TEASER_LENGTH));
|
new SpannableStringBuilder(text.subSequence(0, TEASER_LENGTH));
|
||||||
String ellipsis = ctx.getString(R.string.ellipsis);
|
String ellipsis = ctx.getString(R.string.ellipsis);
|
||||||
builder.append(ellipsis).append(" ");
|
builder.append(ellipsis).append(" ");
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
import de.hdodenhof.circleimageview.CircleImageView;
|
||||||
@@ -44,7 +46,7 @@ public class TextAvatarView extends FrameLayout {
|
|||||||
|
|
||||||
public void setUnreadCount(int count) {
|
public void setUnreadCount(int count) {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
badge.setText(String.valueOf(count));
|
badge.setText(String.format(Locale.getDefault(), "%d", count));
|
||||||
badge.setVisibility(VISIBLE);
|
badge.setVisibility(VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
badge.setVisibility(INVISIBLE);
|
badge.setVisibility(INVISIBLE);
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import android.widget.TextView;
|
|||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@@ -69,7 +71,7 @@ public class UnreadMessageButton extends FrameLayout {
|
|||||||
} else {
|
} else {
|
||||||
fab.show();
|
fab.show();
|
||||||
unread.setVisibility(VISIBLE);
|
unread.setVisibility(VISIBLE);
|
||||||
unread.setText(String.valueOf(count));
|
unread.setText(String.format(Locale.getDefault(), "%d", count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
tools:context=".android.blog.WriteBlogPostActivity">
|
tools:context=".android.blog.WriteBlogPostActivity">
|
||||||
|
|
||||||
<org.briarproject.briar.android.view.LargeTextInputView
|
<org.briarproject.briar.android.view.LargeTextInputView
|
||||||
android:id="@+id/bodyInput"
|
android:id="@+id/textInput"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="bottom"
|
android:gravity="bottom"
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:keepScreenOn="true">
|
||||||
|
|
||||||
<org.briarproject.briar.android.keyagreement.CameraView
|
<org.briarproject.briar.android.keyagreement.CameraView
|
||||||
android:id="@+id/camera_view"
|
android:id="@+id/camera_view"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
app:persona="commenter"/>
|
app:persona="commenter"/>
|
||||||
|
|
||||||
<com.vanniktech.emoji.EmojiTextView
|
<com.vanniktech.emoji.EmojiTextView
|
||||||
android:id="@+id/bodyView"
|
android:id="@+id/textView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="@dimen/listitem_vertical_margin"
|
android:paddingBottom="@dimen/listitem_vertical_margin"
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
app:tint="?attr/colorControlNormal"/>
|
app:tint="?attr/colorControlNormal"/>
|
||||||
|
|
||||||
<com.vanniktech.emoji.EmojiTextView
|
<com.vanniktech.emoji.EmojiTextView
|
||||||
android:id="@+id/bodyView"
|
android:id="@+id/textView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/listitem_vertical_margin"
|
android:layout_margin="@dimen/listitem_vertical_margin"
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/listitem_vertical_margin"
|
android:layout_marginTop="@dimen/listitem_vertical_margin"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/bodyView">
|
app:layout_constraintTop_toBottomOf="@+id/textView">
|
||||||
|
|
||||||
<include
|
<include
|
||||||
layout="@layout/list_item_blog_comment"
|
layout="@layout/list_item_blog_comment"
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
<string name="setup_name_explanation">سيتم إظهار اسمك المستعار بجانب كل ما تنشره من محتوى. لا يمكنك تغيير الاسم بعد إنشاء حسابك.</string>
|
<string name="setup_name_explanation">سيتم إظهار اسمك المستعار بجانب كل ما تنشره من محتوى. لا يمكنك تغيير الاسم بعد إنشاء حسابك.</string>
|
||||||
<string name="setup_next">التالي</string>
|
<string name="setup_next">التالي</string>
|
||||||
<string name="setup_password_intro">اختيار كلمة السر</string>
|
<string name="setup_password_intro">اختيار كلمة السر</string>
|
||||||
<string name="setup_password_explanation">حسابك على Briar (براير) سيتم تخزينه مشفرا على جهازك، وليس على الإنترنت. لذا فإنك إذا نسيت كلمة السر الخاصة بك أو قمت بإلغاء تثبيت Briar (براير)، فلا توجد طريقه لاسترجاع حسابك.\n\nاختر كلمة سر طويلة يصعب تخمينها مثل أربعة كلمات عشوائية أو عشر حروف عشوائية مع أرقام ورموز.</string>
|
<string name="setup_password_explanation">سيتم تخزين حسابك على Briar (براير) مشفرا على جهازك، وليس على الإنترنت. لذا في حالة نسيان كلمة السر الخاصة بك أو إلغاء تثبيت Briar (براير) لا توجد طريقه لاسترجاع حسابك.\n\nالرجاء اختيار كلمة سر طويلة يصعب تخمينها مثل أربع كلمات عشوائية أو عشرة حروف عشوائية مع أرقام ورموز.</string>
|
||||||
<string name="setup_doze_title">اتصالات الخلفية</string>
|
<string name="setup_doze_title">الاتصالات الخلفية</string>
|
||||||
<string name="setup_doze_intro">لاستقبال الرسائل، يحتاج Briar (براير) أن يبقى متصلا في الخلفية.</string>
|
<string name="setup_doze_intro">لاستقبال الرسائل، يحتاج Briar (براير) أن يبقى متصلا في الخلفية.</string>
|
||||||
<string name="setup_doze_explanation">لاستقبال الرسائل، يحتاج Briar (براير) أن يبقى متصلا في الخلفية. الرجاء تعطيل تحسين البطارية حتى يتمكن Briar (براير) من البقاء متصلا.</string>
|
<string name="setup_doze_explanation">لاستقبال الرسائل، يحتاج Briar (براير) أن يبقى متصلا في الخلفية. الرجاء تعطيل تحسين البطارية حتى يتمكن Briar (براير) من البقاء متصلا.</string>
|
||||||
<string name="setup_doze_button">السماح بالاتصالات</string>
|
<string name="setup_doze_button">السماح بالاتصالات</string>
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
<string name="create_account_button">إنشاء الحساب</string>
|
<string name="create_account_button">إنشاء الحساب</string>
|
||||||
<string name="more_info">معلومات أكثر</string>
|
<string name="more_info">معلومات أكثر</string>
|
||||||
<string name="don_t_ask_again">عدم الطلب مرة أخرى</string>
|
<string name="don_t_ask_again">عدم الطلب مرة أخرى</string>
|
||||||
<string name="setup_huawei_text">الرجاء الظغط على الزر في الأسفل والتأكد من أن Briar (براير) محمى في شاشة \"التطبيقات المحمية\".</string>
|
<string name="setup_huawei_text">الرجاء الضغط على الزر في الأسفل والتأكد من أن Briar (براير) محمى في شاشة \"التطبيقات المحمية\".</string>
|
||||||
<string name="setup_huawei_button">حماية Briar (براير)</string>
|
<string name="setup_huawei_button">حماية Briar (براير)</string>
|
||||||
<string name="setup_huawei_help">إذا لم يتم إضافة Briar (براير) في قائمة التطبيقات المحمية، فلن يتمكن من العمل في الخلفية.</string>
|
<string name="setup_huawei_help">إذا لم يتم إضافة Briar (براير) في قائمة التطبيقات المحمية، فلن يتمكن من العمل في الخلفية.</string>
|
||||||
<string name="warning_dozed">%s لم يمكن تشغيله في الخلفية</string>
|
<string name="warning_dozed">%s لم يتمكن من الاشتغال في الخلفية</string>
|
||||||
<!--Login-->
|
<!--Login-->
|
||||||
<string name="enter_password">كلمة السّر</string>
|
<string name="enter_password">كلمة السّر</string>
|
||||||
<string name="try_again">كلمة السرّ خاطئة, الرجاء المحاولة مجدّدا</string>
|
<string name="try_again">كلمة السرّ خاطئة, الرجاء المحاولة مجدّدا</string>
|
||||||
@@ -31,12 +31,12 @@
|
|||||||
<string name="dialog_title_lost_password">فقدت كلمة السر</string>
|
<string name="dialog_title_lost_password">فقدت كلمة السر</string>
|
||||||
<string name="dialog_message_lost_password">حسابك على Briar (براير) سيتم تخزينه مشفرا على جهازك، وليس على الإنترنت. لذا فلا يمكننا إعادة تعيين كلمة السر الخاصة بك. فهل تودّ/ين حذف حسابك والبدء من جديد؟\n\nتحذير: سيتمّ حذف هويّاتك وجهات اتصالك ورسائلك الى الأبد.</string>
|
<string name="dialog_message_lost_password">حسابك على Briar (براير) سيتم تخزينه مشفرا على جهازك، وليس على الإنترنت. لذا فلا يمكننا إعادة تعيين كلمة السر الخاصة بك. فهل تودّ/ين حذف حسابك والبدء من جديد؟\n\nتحذير: سيتمّ حذف هويّاتك وجهات اتصالك ورسائلك الى الأبد.</string>
|
||||||
<string name="startup_failed_notification_title">Briar (براير) لم يمكنه البدء</string>
|
<string name="startup_failed_notification_title">Briar (براير) لم يمكنه البدء</string>
|
||||||
<string name="startup_failed_notification_text">المس لمزيد من المعلومات</string>
|
<string name="startup_failed_notification_text">المس/ي لمزيد من المعلومات</string>
|
||||||
<string name="startup_failed_activity_title">فشل تشغيل Briar (براير)</string>
|
<string name="startup_failed_activity_title">فشل تشغيل Briar (براير)</string>
|
||||||
<string name="startup_failed_db_error">لسبب ما، فإن قاعدة بيانات Briar (براير) قد تلفت ولم يعد من الممكن إصلاحها. حسابك وبياناتك وكل جهات اتصالك قد فقدت. للأسف، يلزم إعادة تثبيت Briar (براير) أو إنشاء حساب جديد عن طريق خيار \"نسيت كلمة السر\" عند سؤالك عنها.</string>
|
<string name="startup_failed_db_error">لسبب ما، فإن قاعدة بيانات Briar (براير) قد تلفت ولم يعد من الممكن إصلاحها. حسابك وبياناتك وكل جهات اتصالك قد فقدت. للأسف، يلزم إعادة تثبيت Briar (براير) أو إنشاء حساب جديد عن طريق خيار \"نسيت كلمة السر\" عند سؤالك عنها.</string>
|
||||||
<string name="startup_failed_data_too_old_error">حسابك تم إنشاؤه بواسطة إصدار قديم من هذا التطبيق ولا يمكن فتحه بهذا الإصدار. يتوجب إعادة تثبيت الإصدار القديم أو أن تنشئ حسابا جديدًا باختيار \"نسيت كلمة السر\" عند سؤالك عنها.</string>
|
<string name="startup_failed_data_too_old_error">حسابك تم إنشاؤه بواسطة إصدار قديم من هذا التطبيق ولا يمكن فتحه بهذا الإصدار. يتوجب إعادة تثبيت الإصدار القديم أو أن تنشئ حسابا جديدًا باختيار \"نسيت كلمة السر\" عند سؤالك عنها.</string>
|
||||||
<string name="startup_failed_data_too_new_error">هذا الإصدار من التطبيق قديم جدًا. من فضلك قم بالتحديث لآخر إصدار ثم حاول مجددًا.</string>
|
<string name="startup_failed_data_too_new_error">هذا الإصدار من التطبيق قديم جدًا. الرجاء التحديث لآخر إصدار ثم المحاولة مجددًا.</string>
|
||||||
<string name="startup_failed_service_error">Briar (براير) لم يستطع تشغيل إضافة لازمة. إعادة تشغيل Briar (براير) يحل مثل هذه المشكلة عادة. لكن ذلك يعني أنك ستفقد حسابك وكل بياناتك عليه حيث أن Briar (براير) لا يستعمل خوادم مركزية لتخزين بياناتك.</string>
|
<string name="startup_failed_service_error">Briar (براير) لم يستطع تشغيل إضافة لازمة. إعادة تشغيل Briar (براير) يحل مثل هذه المشكلة عادة. لكن ذلك يعني أنك فقدان حسابك وكل بياناتك عليه حيث أن Briar (براير) لا يستعمل خوادم مركزية لتخزين بياناتك.</string>
|
||||||
<plurals name="expiry_warning">
|
<plurals name="expiry_warning">
|
||||||
<item quantity="zero">هذا إصدار تجريبي من Briar (براير). حسابك سينتهي اليوم ولن يمكن تجديده.</item>
|
<item quantity="zero">هذا إصدار تجريبي من Briar (براير). حسابك سينتهي اليوم ولن يمكن تجديده.</item>
|
||||||
<item quantity="one">هذا إصدار تجريبي من Briar (براير). حسابك سينتهي خلال يوم ولن يمكن تجديده.</item>
|
<item quantity="one">هذا إصدار تجريبي من Briar (براير). حسابك سينتهي خلال يوم ولن يمكن تجديده.</item>
|
||||||
@@ -47,14 +47,14 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="expiry_update">تم تمديد تاريخ انتهاء التجربة. حسابك الآن سوف ينتهي بعد %d يوم.</string>
|
<string name="expiry_update">تم تمديد تاريخ انتهاء التجربة. حسابك الآن سوف ينتهي بعد %d يوم.</string>
|
||||||
<string name="expiry_date_reached">هذا البرنامج قد انتهت مدته.\nشكرا لك للتجربة!</string>
|
<string name="expiry_date_reached">هذا البرنامج قد انتهت مدته.\nشكرا لك للتجربة!</string>
|
||||||
<string name="download_briar">لتستمر في إستعمال Briar (براير)، من فضلك قم بتحميل إصدار رقم 1.0.</string>
|
<string name="download_briar">للاستمرار في إستعمال Briar (براير)، من فضلك قم بتحميل إصدار رقم 1.0.</string>
|
||||||
<string name="create_new_account">تحتاج أن تنشئ حساب جديد، لكن يمكنك استعمال نفس الاسم المستعار.</string>
|
<string name="create_new_account">انت في حاجة لانشاء حساب جديد، لكن يمكنك استعمال نفس الاسم المستعار.</string>
|
||||||
<string name="download_briar_button">تحميل Briar (براير) 1.0</string>
|
<string name="download_briar_button">تحميل Briar (براير) 1.0</string>
|
||||||
<string name="startup_open_database">جارِ فك تشفير قاعدة البيانات...</string>
|
<string name="startup_open_database">جارِ فك تشفير قاعدة البيانات...</string>
|
||||||
<string name="startup_migrate_database">جارِ ترقية قاعدة البيانات...</string>
|
<string name="startup_migrate_database">جارِ ترقية قاعدة البيانات...</string>
|
||||||
<!--Navigation Drawer-->
|
<!--Navigation Drawer-->
|
||||||
<string name="nav_drawer_open_description">إفتح راسم التصفح</string>
|
<string name="nav_drawer_open_description">فتح راسم التصفح</string>
|
||||||
<string name="nav_drawer_close_description">أغلق راسم التصفح</string>
|
<string name="nav_drawer_close_description">غلق راسم التصفح</string>
|
||||||
<string name="contact_list_button">جهات الاتصال</string>
|
<string name="contact_list_button">جهات الاتصال</string>
|
||||||
<string name="groups_button">المجموعات الخاصة</string>
|
<string name="groups_button">المجموعات الخاصة</string>
|
||||||
<string name="forums_button">المنتديات</string>
|
<string name="forums_button">المنتديات</string>
|
||||||
@@ -64,16 +64,16 @@
|
|||||||
<string name="settings_button">الإعدادات</string>
|
<string name="settings_button">الإعدادات</string>
|
||||||
<string name="sign_out_button">تسجيل الخروج</string>
|
<string name="sign_out_button">تسجيل الخروج</string>
|
||||||
<!--Transports-->
|
<!--Transports-->
|
||||||
<string name="transport_tor">الإنترنت</string>
|
<string name="transport_tor">إنترنت</string>
|
||||||
<string name="transport_bt">بلوتوث</string>
|
<string name="transport_bt">بلوتوث</string>
|
||||||
<string name="transport_lan">واي-فاي</string>
|
<string name="transport_lan">واي-فاي</string>
|
||||||
<!--Notifications-->
|
<!--Notifications-->
|
||||||
<string name="reminder_notification_title">تم تسجيل الخروج من Briar (براير)</string>
|
<string name="reminder_notification_title">تم تسجيل الخروج من Briar (براير)</string>
|
||||||
<string name="reminder_notification_text">المس لإعادة الدخول</string>
|
<string name="reminder_notification_text">الرجاء اللمس لإعادة الدخول</string>
|
||||||
<string name="reminder_notification_channel_title">التذكير بتسجيل الدخول إلى Briar (براير)</string>
|
<string name="reminder_notification_channel_title">التذكير بتسجيل الدخول إلى Briar (براير)</string>
|
||||||
<string name="reminder_notification_dismiss">رفض</string>
|
<string name="reminder_notification_dismiss">رفض</string>
|
||||||
<string name="ongoing_notification_title">سجِل الدخول إلى Briar (براير)</string>
|
<string name="ongoing_notification_title">تم تسجيل الدخول إلى Briar (براير)</string>
|
||||||
<string name="ongoing_notification_text">المس لفتح Briar (براير).</string>
|
<string name="ongoing_notification_text">الرجاء اللمس لفتح Briar (براير).</string>
|
||||||
<plurals name="private_message_notification_text">
|
<plurals name="private_message_notification_text">
|
||||||
<item quantity="zero">لا رسائل خاصة جديدة.</item>
|
<item quantity="zero">لا رسائل خاصة جديدة.</item>
|
||||||
<item quantity="one"> رسالة خاصة جديدة.</item>
|
<item quantity="one"> رسالة خاصة جديدة.</item>
|
||||||
@@ -110,41 +110,41 @@
|
|||||||
<string name="now">الآن</string>
|
<string name="now">الآن</string>
|
||||||
<string name="show">عرض</string>
|
<string name="show">عرض</string>
|
||||||
<string name="hide">إخفاء</string>
|
<string name="hide">إخفاء</string>
|
||||||
<string name="ok">موافق</string>
|
<string name="ok">موافقة</string>
|
||||||
<string name="cancel">إلغاء</string>
|
<string name="cancel">إلغاء</string>
|
||||||
<string name="got_it">فهمت ذلك</string>
|
<string name="got_it">فهمت ذلك</string>
|
||||||
<string name="delete">حذف</string>
|
<string name="delete">حذف</string>
|
||||||
<string name="accept">قبول</string>
|
<string name="accept">قبول</string>
|
||||||
<string name="decline">إرفض</string>
|
<string name="decline">رفض</string>
|
||||||
<string name="options">الخيارات</string>
|
<string name="options">الخيارات</string>
|
||||||
<string name="online">متصل</string>
|
<string name="online">متصل</string>
|
||||||
<string name="offline">غير متصل</string>
|
<string name="offline">غير متصل</string>
|
||||||
<string name="send">أرسلْ</string>
|
<string name="send">ارسال</string>
|
||||||
<string name="allow">إسمح</string>
|
<string name="allow">السماح</string>
|
||||||
<string name="open">فتح</string>
|
<string name="open">فتح</string>
|
||||||
<string name="no_data">لا يوجد بيانات</string>
|
<string name="no_data">لا يوجد بيانات</string>
|
||||||
<string name="ellipsis">...</string>
|
<string name="ellipsis">...</string>
|
||||||
<string name="text_too_long">النص المُدخل طويل جدًا</string>
|
<string name="text_too_long">النص المُدخل طويل جدًا</string>
|
||||||
<string name="show_onboarding">أظهر نافذة المساعدة</string>
|
<string name="show_onboarding">اظهار نافذة المساعدة</string>
|
||||||
<string name="fix">إصلاح</string>
|
<string name="fix">إصلاح</string>
|
||||||
<string name="help">مساعدة</string>
|
<string name="help">مساعدة</string>
|
||||||
<string name="sorry">معذرة</string>
|
<string name="sorry">معذرة</string>
|
||||||
<!--Contacts and Private Conversations-->
|
<!--Contacts and Private Conversations-->
|
||||||
<string name="no_contacts">لا جهات اتصال للعرض</string>
|
<string name="no_contacts">لا جهات اتصال للعرض</string>
|
||||||
<string name="no_contacts_action">المس علامة + لإضافة جهة إتصال</string>
|
<string name="no_contacts_action">لمس علامة + لإضافة جهة إتصال</string>
|
||||||
<string name="date_no_private_messages">لا رسائل.</string>
|
<string name="date_no_private_messages">لا رسائل.</string>
|
||||||
<string name="no_private_messages">لا رسائل للعرض.</string>
|
<string name="no_private_messages">لا رسائل للعرض.</string>
|
||||||
<string name="message_hint">أكتب رسالة</string>
|
<string name="message_hint">كتابة رسالة</string>
|
||||||
<string name="delete_contact">حذف جهة الإتصال</string>
|
<string name="delete_contact">حذف جهة الإتصال</string>
|
||||||
<string name="dialog_title_delete_contact">تأكيد حذف جهة الإتصال</string>
|
<string name="dialog_title_delete_contact">تأكيد حذف جهة الإتصال</string>
|
||||||
<string name="dialog_message_delete_contact">هل متأكد من أنك تريد حذف جهة الإتصال هذه وكل الرسائل المتبادلة بينكما؟</string>
|
<string name="dialog_message_delete_contact">هل أنت متأكد/ة من أنك تريد حذف جهة الإتصال هذه وكل الرسائل المتبادلة بينكما؟</string>
|
||||||
<string name="contact_deleted_toast">تم حذف جهة اتصال</string>
|
<string name="contact_deleted_toast">تم حذف جهة اتصال</string>
|
||||||
<!--Adding Contacts-->
|
<!--Adding Contacts-->
|
||||||
<string name="add_contact_title">إضافة جهة اتصال</string>
|
<string name="add_contact_title">إضافة جهة اتصال</string>
|
||||||
<string name="face_to_face">لابد أن تقابل الشخص الذي تريد إضافته كجهة اتصال.\n\nهذا سيمنع أي شخص من انتحال شخصيتك أو قراءة رسائلك في المستقبل.</string>
|
<string name="face_to_face">لا بد من مقابلة الشخص الذي تريد/ين إضافته كجهة اتصال.\n\nهذا سيمنع أي شخص من انتحال شخصيتك أو قراءة رسائلك في المستقبل.</string>
|
||||||
<string name="continue_button">إستمرار</string>
|
<string name="continue_button">إستمرار</string>
|
||||||
<string name="try_again_button">حاول مجددًا</string>
|
<string name="try_again_button">الرجاء المحاولة مجددًا</string>
|
||||||
<string name="waiting_for_contact_to_scan">بإنتظار جهة الإتصال ليقوم بالمسح والإتصال\u2026</string>
|
<string name="waiting_for_contact_to_scan">بإنتظار أن تقوم جهة الإتصال بالمسح والإتصال\u2026</string>
|
||||||
<string name="exchanging_contact_details">يتم تبادل معلومات جهة الإتصال\u2026</string>
|
<string name="exchanging_contact_details">يتم تبادل معلومات جهة الإتصال\u2026</string>
|
||||||
<string name="contact_added_toast">تم إضافة جهة إتصال: %s</string>
|
<string name="contact_added_toast">تم إضافة جهة إتصال: %s</string>
|
||||||
<string name="contact_already_exists">جهة الإتصال %s بالفعل موجودة</string>
|
<string name="contact_already_exists">جهة الإتصال %s بالفعل موجودة</string>
|
||||||
@@ -172,11 +172,11 @@
|
|||||||
<string name="introduction_request_exists_received">قد طلب %1$s أن يقدمك إلى %2$s، لكن %2$s هو بالفعل في قائمة جهات اتصالك. حيث أن %1$s قد لا يعرف هذا، فلا زال يمكنك الرد:</string>
|
<string name="introduction_request_exists_received">قد طلب %1$s أن يقدمك إلى %2$s، لكن %2$s هو بالفعل في قائمة جهات اتصالك. حيث أن %1$s قد لا يعرف هذا، فلا زال يمكنك الرد:</string>
|
||||||
<string name="introduction_request_answered_received">لقد طلب %1$s أن يقوم بتقديمك إلى %2$s.</string>
|
<string name="introduction_request_answered_received">لقد طلب %1$s أن يقوم بتقديمك إلى %2$s.</string>
|
||||||
<string name="introduction_response_accepted_sent">لقد قبلت التقديم إلى %1$s.</string>
|
<string name="introduction_response_accepted_sent">لقد قبلت التقديم إلى %1$s.</string>
|
||||||
<string name="introduction_response_accepted_sent_info">قبل أن يتم إضافة %1$s إلى جهات اتصالك، يحتاج أن يقبل هو أيضًا التقديم. هذا يمكن أن يستغرق بعض الوقت.</string>
|
<string name="introduction_response_accepted_sent_info">قبل أن يتم إضافة %1$s إلى جهات اتصالك، يحتاج أن ي/تقبل هو/هي أيضًا التقديم. هذا يمكن أن يستغرق بعض الوقت.</string>
|
||||||
<string name="introduction_response_declined_sent">لقد رفضت التقديم إلى %1$s.</string>
|
<string name="introduction_response_declined_sent">لقد رفضت التقديم إلى %1$s.</string>
|
||||||
<string name="introduction_response_accepted_received">لقد وافق %1$s على تقديمه إلى %2$s.</string>
|
<string name="introduction_response_accepted_received">لقد وافق/ت %1$s على تقديمه/ها إلى %2$s.</string>
|
||||||
<string name="introduction_response_declined_received">لقد رفض %1$sتقديمه إلى %2$s.</string>
|
<string name="introduction_response_declined_received">لقد رفض/ت %1$sتقديمه/ا إلى %2$s.</string>
|
||||||
<string name="introduction_response_declined_received_by_introducee">يقول %1$sأن %2$s قد رفض التقدمة.</string>
|
<string name="introduction_response_declined_received_by_introducee">ي/تقول %1$sأن %2$s قد رفض/ت التقدمة.</string>
|
||||||
<plurals name="introduction_notification_text">
|
<plurals name="introduction_notification_text">
|
||||||
<item quantity="zero">لا جهة اتصال تم إضافتها.</item>
|
<item quantity="zero">لا جهة اتصال تم إضافتها.</item>
|
||||||
<item quantity="one">جهة اتصال تم إضافتها.</item>
|
<item quantity="one">جهة اتصال تم إضافتها.</item>
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<!--Private Groups-->
|
<!--Private Groups-->
|
||||||
<string name="groups_list_empty">لا مجموعات للعرض</string>
|
<string name="groups_list_empty">لا مجموعات للعرض</string>
|
||||||
<string name="groups_list_empty_action">المس علامة + لإنشاء مجموعة، أو اطلب من جهات إتصالك مشاركتك في مجموعاتهم</string>
|
<string name="groups_list_empty_action">الرجاء لمس علامة + لإنشاء مجموعة، أو اطلب من جهات إتصالك مشاركتك في مجموعاتهم</string>
|
||||||
<string name="groups_created_by">تم إنشاؤها بواسطة %s</string>
|
<string name="groups_created_by">تم إنشاؤها بواسطة %s</string>
|
||||||
<plurals name="messages">
|
<plurals name="messages">
|
||||||
<item quantity="zero">%d رسالة</item>
|
<item quantity="zero">%d رسالة</item>
|
||||||
@@ -200,26 +200,26 @@
|
|||||||
<string name="groups_group_is_empty">هذه المجموعة فارغة</string>
|
<string name="groups_group_is_empty">هذه المجموعة فارغة</string>
|
||||||
<string name="groups_group_is_dissolved">هذه المجموعة قد تلاشت</string>
|
<string name="groups_group_is_dissolved">هذه المجموعة قد تلاشت</string>
|
||||||
<string name="groups_remove">حذف</string>
|
<string name="groups_remove">حذف</string>
|
||||||
<string name="groups_create_group_title">قم بإنشاء مجموعة خاصة</string>
|
<string name="groups_create_group_title">إنشاء مجموعة خاصة</string>
|
||||||
<string name="groups_create_group_button">أنشئ مجموعة</string>
|
<string name="groups_create_group_button">إنشاء مجموعة</string>
|
||||||
<string name="groups_create_group_invitation_button">أرسل دعوة</string>
|
<string name="groups_create_group_invitation_button">إرسال دعوة</string>
|
||||||
<string name="groups_create_group_hint">اختر اسمًا لمجموعتك الخاصة</string>
|
<string name="groups_create_group_hint">اختيار اسم لمجموعتك الخاصة</string>
|
||||||
<string name="groups_invitation_sent">تم إرسال دعوة للمجموعة</string>
|
<string name="groups_invitation_sent">تم إرسال دعوة للمجموعة</string>
|
||||||
<string name="groups_message_sent">تم إرسال الرسالة</string>
|
<string name="groups_message_sent">تم إرسال الرسالة</string>
|
||||||
<string name="groups_member_list">قائمة الأعضاء</string>
|
<string name="groups_member_list">قائمة الأعضاء</string>
|
||||||
<string name="groups_invite_members">دعوة أعضاء</string>
|
<string name="groups_invite_members">دعوة أعضاء</string>
|
||||||
<string name="groups_member_created_you">أنت أنشأت المجموعة</string>
|
<string name="groups_member_created_you">أنت أنشأت المجموعة</string>
|
||||||
<string name="groups_member_created">%s أنشأ المجموعة</string>
|
<string name="groups_member_created">%s أنشأ المجموعة</string>
|
||||||
<string name="groups_member_joined_you">قد انضممت للمجموعة</string>
|
<string name="groups_member_joined_you">قد انضممت/ي للمجموعة</string>
|
||||||
<string name="groups_member_joined">قد انضم %s للمجموعة</string>
|
<string name="groups_member_joined">قد انضم/ت %s للمجموعة</string>
|
||||||
<string name="groups_leave">غادر المجموعة</string>
|
<string name="groups_leave">مغادرة المجموعة</string>
|
||||||
<string name="groups_leave_dialog_title">تأكيد مغادرة المجموعة</string>
|
<string name="groups_leave_dialog_title">تأكيد مغادرة المجموعة</string>
|
||||||
<string name="groups_leave_dialog_message">هل متأكد من مغادرة هذه المجموعة؟</string>
|
<string name="groups_leave_dialog_message">هل أنت متأكد/ة من مغادرة هذه المجموعة؟</string>
|
||||||
<string name="groups_dissolve">حلّ المجموعة</string>
|
<string name="groups_dissolve">حلّ المجموعة</string>
|
||||||
<string name="groups_dissolve_dialog_title">أكد حلّ وتلاشي المجموعة</string>
|
<string name="groups_dissolve_dialog_title">تأكيد حلّ المجموعة</string>
|
||||||
<string name="groups_dissolve_dialog_message">هل متأكد أنك تريد حلّ هذه المجموعة؟\n\nجميع الأعضاء الآخرين لن يتمكنوا من استكمال حوارهم وربما لن يستقبلوا الرسائل الأخيرة.</string>
|
<string name="groups_dissolve_dialog_message">هل تريد/ين فعلا حلّ هذه المجموعة؟\n\nجميع الأعضاء الآخرين لن يتمكنوا من استكمال حوارهم وربما لن يستقبلوا الرسائل الأخيرة.</string>
|
||||||
<string name="groups_dissolve_button">حلّ</string>
|
<string name="groups_dissolve_button">حلّ</string>
|
||||||
<string name="groups_dissolved_dialog_title">تم حلّ المجموعة وتلاشيها</string>
|
<string name="groups_dissolved_dialog_title">تم حلّ المجموعة </string>
|
||||||
<string name="groups_dissolved_dialog_message">منشئ هذه المجموعة قام بحلّها.\n\n لن يمكنك كتابة رسائل إلى المجموعة كما ويحتمل أنك لم تستقبل جميع الرسائل التي تم كتابتها.</string>
|
<string name="groups_dissolved_dialog_message">منشئ هذه المجموعة قام بحلّها.\n\n لن يمكنك كتابة رسائل إلى المجموعة كما ويحتمل أنك لم تستقبل جميع الرسائل التي تم كتابتها.</string>
|
||||||
<!--Private Group Invitations-->
|
<!--Private Group Invitations-->
|
||||||
<string name="groups_invitations_title">دعوات المجموعة</string>
|
<string name="groups_invitations_title">دعوات المجموعة</string>
|
||||||
@@ -233,26 +233,27 @@
|
|||||||
<item quantity="two">دعوتيْ مجموعة مفتوحتين</item>
|
<item quantity="two">دعوتيْ مجموعة مفتوحتين</item>
|
||||||
<item quantity="few">%d دعوات مجموعة مفتوحة</item>
|
<item quantity="few">%d دعوات مجموعة مفتوحة</item>
|
||||||
<item quantity="many">%d دعوة مجموعة مفتوحة</item>
|
<item quantity="many">%d دعوة مجموعة مفتوحة</item>
|
||||||
<item quantity="other">%d دعوة مجموعة مفتوحة</item>
|
<item quantity="other">%d
|
||||||
|
فتح دعوات المجموعات</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="groups_invitations_response_accepted_sent">قد قبلت دعوة الانضمام للمجموعة من %s.</string>
|
<string name="groups_invitations_response_accepted_sent">قد قبلت دعوة الانضمام للمجموعة من %s.</string>
|
||||||
<string name="groups_invitations_response_declined_sent">قد رفضت دعوة الانضمام للمجموعة من %s.</string>
|
<string name="groups_invitations_response_declined_sent">قد رفضت دعوة الانضمام للمجموعة من %s.</string>
|
||||||
<string name="groups_invitations_response_accepted_received">قبل %s دعوة الانضمام للمجموعة.</string>
|
<string name="groups_invitations_response_accepted_received">قبل/ت %s دعوة الانضمام للمجموعة.</string>
|
||||||
<string name="groups_invitations_response_declined_received">رفض %s دعوة الانضمام للمجموعة.</string>
|
<string name="groups_invitations_response_declined_received">رفض/ت %s دعوة الانضمام للمجموعة.</string>
|
||||||
<string name="sharing_status_groups">فقط المُنشئ يمكنه دعوة أعضاء جدد للمجموعة. في الأسفل جميع الأعضاء الحاليين بالمجموعة.</string>
|
<string name="sharing_status_groups">فقط مُنشئ/ة المجموعة يمكنه/ها دعوة أعضاء جدد. في الأسفل جميع الأعضاء الحاليين بالمجموعة.</string>
|
||||||
<!--Private Groups Revealing Contacts-->
|
<!--Private Groups Revealing Contacts-->
|
||||||
<string name="groups_reveal_contacts">أظهر الأعضاء</string>
|
<string name="groups_reveal_contacts">اظهار الأعضاء</string>
|
||||||
<string name="groups_reveal_dialog_message">يمكن أن تختار إظهار جميع جهات الاتصال الحالية والمستقبلية في هذه المجموعة لبعضهم البعض.\n\nإظهار جهات الاتصال سيجعل اتصالك بالمجموعة أسرع وأفضل اعتمادية، حيث سيمكن التواصل بين جهات الاتصال الظاهرة حتى لو كان منشئ المجموعة غير متصل.</string>
|
<string name="groups_reveal_dialog_message">يمكن اختيار إظهار جميع جهات الاتصال الحالية والمستقبلية في هذه المجموعة لبعضهم البعض.\n\nإظهار جهات الاتصال سيجعل اتصالك بالمجموعة أسرع وأفضل اعتمادية، حيث سيمكن التواصل بين جهات الاتصال الظاهرة حتى لو كان منشئ المجموعة غير متصل.</string>
|
||||||
<string name="groups_reveal_visible">علاقات جهات الاتصال ستكون ظاهرة للمجموعة</string>
|
<string name="groups_reveal_visible">علاقات جهات الاتصال ستكون ظاهرة للمجموعة</string>
|
||||||
<string name="groups_reveal_visible_revealed_by_us">علاقات جهات الاتصال ظاهرة للمجموعة (قمت أنت بكشفها)</string>
|
<string name="groups_reveal_visible_revealed_by_us">علاقات جهات الاتصال ظاهرة للمجموعة (قمت/ي أنت بكشفها)</string>
|
||||||
<string name="groups_reveal_visible_revealed_by_contact">علاقات جهات الاتصال ظاهرة للمجموعة (قام %s بكشفها)</string>
|
<string name="groups_reveal_visible_revealed_by_contact">علاقات جهات الاتصال ظاهرة للمجموعة (قام/ت %s بكشفها)</string>
|
||||||
<string name="groups_reveal_invisible">علاقات جهات الاتصال غير ظاهرة للمجموعة</string>
|
<string name="groups_reveal_invisible">علاقات جهات الاتصال غير ظاهرة للمجموعة</string>
|
||||||
<!--Forums-->
|
<!--Forums-->
|
||||||
<string name="no_forums">لا منتديات للعرض</string>
|
<string name="no_forums">لا منتديات للعرض</string>
|
||||||
<string name="no_forums_action">المس علامة + لإنشاء منتدى، أو اطلب من جهات اتصالك مشاركتك في منتدياتهم</string>
|
<string name="no_forums_action">الرجاء لمس علامة + لإنشاء منتدى، أو طلب من جهات اتصالك مشاركتك في منتدياتهم</string>
|
||||||
<string name="create_forum_title">أنشئ منتدىَ</string>
|
<string name="create_forum_title">انشاء منتدى</string>
|
||||||
<string name="choose_forum_hint">اختر إسم لمنتداك</string>
|
<string name="choose_forum_hint">اختيار إسم لمنتداك</string>
|
||||||
<string name="create_forum_button">أنشئ منتدىَ</string>
|
<string name="create_forum_button">انشاء منتدى</string>
|
||||||
<string name="forum_created_toast">تم إنشاء المنتدى</string>
|
<string name="forum_created_toast">تم إنشاء المنتدى</string>
|
||||||
<string name="no_forum_posts">لا منشورات للعرض</string>
|
<string name="no_forum_posts">لا منشورات للعرض</string>
|
||||||
<string name="no_posts">لا منشورات</string>
|
<string name="no_posts">لا منشورات</string>
|
||||||
@@ -270,7 +271,7 @@
|
|||||||
<string name="btn_reply">الرد</string>
|
<string name="btn_reply">الرد</string>
|
||||||
<string name="forum_leave">مغادرة المنتدى</string>
|
<string name="forum_leave">مغادرة المنتدى</string>
|
||||||
<string name="dialog_title_leave_forum">تأكيد مغادرة المنتدى</string>
|
<string name="dialog_title_leave_forum">تأكيد مغادرة المنتدى</string>
|
||||||
<string name="dialog_message_leave_forum">هل متأكد من رغبتك في مغادرة المنتدى؟\n\nأي جهة اتصال قمت بمشاركة هذا المنتدى معها قد يتوقف عنها استلام التحديثات.</string>
|
<string name="dialog_message_leave_forum">هل أنت متأكد/ة من رغبتك في مغادرة المنتدى؟\n\nأي جهة اتصال قمت/ي بمشاركة هذا المنتدى معها قد يتوقف عنها استلام التحديثات.</string>
|
||||||
<string name="dialog_button_leave">مغادرة</string>
|
<string name="dialog_button_leave">مغادرة</string>
|
||||||
<string name="forum_left_toast">تم مغادرة المنتدى</string>
|
<string name="forum_left_toast">تم مغادرة المنتدى</string>
|
||||||
<!--Forum Sharing-->
|
<!--Forum Sharing-->
|
||||||
@@ -278,25 +279,25 @@
|
|||||||
<string name="contacts_selected">جهات الاتصال المختارة</string>
|
<string name="contacts_selected">جهات الاتصال المختارة</string>
|
||||||
<string name="activity_share_toolbar_header">إختر جهات الاتصال</string>
|
<string name="activity_share_toolbar_header">إختر جهات الاتصال</string>
|
||||||
<string name="no_contacts_selector">لا جهات إتصال للعرض</string>
|
<string name="no_contacts_selector">لا جهات إتصال للعرض</string>
|
||||||
<string name="no_contacts_selector_action">رجاءًا العودة لاحقًا هنا بعد إضافة جهة إتصال</string>
|
<string name="no_contacts_selector_action">الرجاء العودة لاحقًا هنا بعد إضافة جهة إتصال</string>
|
||||||
<string name="forum_shared_snackbar">تم مشاركة المنتدى مع جهات الاتصال المختارة</string>
|
<string name="forum_shared_snackbar">تم مشاركة المنتدى مع جهات الاتصال المختارة</string>
|
||||||
<string name="forum_share_message">أضف رسالة (إختياري)</string>
|
<string name="forum_share_message">اضافة رسالة (إختياري)</string>
|
||||||
<string name="forum_share_error">حدث خطأ أثناء مشاركة المنتدى</string>
|
<string name="forum_share_error">حدث خطأ أثناء مشاركة المنتدى</string>
|
||||||
<string name="forum_invitation_received">قام %1$s بمشاركة المنتدى \"%2$s\" معك.</string>
|
<string name="forum_invitation_received">قام/ت %1$s بمشاركة المنتدى \"%2$s\" معك.</string>
|
||||||
<string name="forum_invitation_sent">لقد قمت بمشاركة المنتدى \"%1$s\" مع %2$s.</string>
|
<string name="forum_invitation_sent">لقد قمت/ي بمشاركة المنتدى \"%1$s\" مع %2$s.</string>
|
||||||
<string name="forum_invitations_title">دعوات المنتدى</string>
|
<string name="forum_invitations_title">دعوات المنتدى</string>
|
||||||
<string name="forum_invitation_exists">لقد قمت بالفعل بقبول دعوة لهذا المنتدى.\n\nقبول دعوات إضافية سيجعل اتصالك مع المنتدى أسرع وأكثر اعتمادية.</string>
|
<string name="forum_invitation_exists">لقد قمت/ي بالفعل بقبول دعوة لهذا المنتدى.\n\nقبول دعوات إضافية سيجعل اتصالك مع المنتدى أسرع وأكثر اعتمادية.</string>
|
||||||
<string name="forum_joined_toast">تم الإنضمام للمنتدى</string>
|
<string name="forum_joined_toast">تم الإنضمام للمنتدى</string>
|
||||||
<string name="forum_declined_toast">تم رفض الدعوة</string>
|
<string name="forum_declined_toast">تم رفض الدعوة</string>
|
||||||
<string name="shared_by_format">شورٍك بواسطة %s</string>
|
<string name="shared_by_format">تمت المشاركة بواسطة %s</string>
|
||||||
<string name="forum_invitation_already_sharing">مُشارك بالفعل</string>
|
<string name="forum_invitation_already_sharing">في طور المشاركة</string>
|
||||||
<string name="forum_invitation_response_accepted_sent">لقد قبلت دعوة المنتدى من %s.</string>
|
<string name="forum_invitation_response_accepted_sent">لقد قبلت دعوة المنتدى من %s.</string>
|
||||||
<string name="forum_invitation_response_declined_sent">لقد رفضت دعوة المنتدى من %s.</string>
|
<string name="forum_invitation_response_declined_sent">لقد رفضت دعوة المنتدى من %s.</string>
|
||||||
<string name="forum_invitation_response_accepted_received">قبل %s دعوة المنتدى.</string>
|
<string name="forum_invitation_response_accepted_received">قبل/ت %s دعوة المنتدى.</string>
|
||||||
<string name="forum_invitation_response_declined_received">رفض %s دعوة المنتدى.</string>
|
<string name="forum_invitation_response_declined_received">رفض/ت %s دعوة المنتدى.</string>
|
||||||
<string name="sharing_status">حالة المشاركة</string>
|
<string name="sharing_status">حالة المشاركة</string>
|
||||||
<string name="sharing_status_forum">أي عضو بالمنتدى يمكنه مشاركته مع جهات إتصاله. أنت تشارك هذا المنتدى مع جهات الإتصال هذه. قد يكون هناك أعضاء آخرين لا يمكنك رؤيتهم.</string>
|
<string name="sharing_status_forum">أي عضو بالمنتدى يمكنه مشاركته مع جهات إتصاله. يمكنك مشاركة هذا المنتدى مع جهات الإتصال هذه. قد يكون هناك أعضاء آخرين لا يمكنك/ي رؤيتهم.</string>
|
||||||
<string name="shared_with">مشارك مع %1$d (%2$d متصل)</string>
|
<string name="shared_with">تمت المشاركة مع %1$d (%2$d متصل)</string>
|
||||||
<plurals name="forums_shared">
|
<plurals name="forums_shared">
|
||||||
<item quantity="zero">لا منتدى مُشارَك من جهات الاتصال</item>
|
<item quantity="zero">لا منتدى مُشارَك من جهات الاتصال</item>
|
||||||
<item quantity="one">منتدى مُشارَك من جهات الاتصال</item>
|
<item quantity="one">منتدى مُشارَك من جهات الاتصال</item>
|
||||||
@@ -308,54 +309,54 @@
|
|||||||
<string name="nobody">لا أحد</string>
|
<string name="nobody">لا أحد</string>
|
||||||
<!--Blogs-->
|
<!--Blogs-->
|
||||||
<string name="blogs_other_blog_empty_state">لا منشورات للعرض</string>
|
<string name="blogs_other_blog_empty_state">لا منشورات للعرض</string>
|
||||||
<string name="read_more">اقرأ المزيد</string>
|
<string name="read_more">قراءة المزيد</string>
|
||||||
<string name="blogs_write_blog_post">أكتب تدوينة</string>
|
<string name="blogs_write_blog_post">كتابة تدوينة</string>
|
||||||
<string name="blogs_write_blog_post_body_hint">أكتب تدوينتك</string>
|
<string name="blogs_write_blog_post_body_hint">كتابة تدوينتك</string>
|
||||||
<string name="blogs_publish_blog_post">نشر</string>
|
<string name="blogs_publish_blog_post">نشر</string>
|
||||||
<string name="blogs_blog_post_created">تم إنشاء تدوينة</string>
|
<string name="blogs_blog_post_created">تم إنشاء تدوينة</string>
|
||||||
<string name="blogs_blog_post_received">تم إستلام تدوينة جديدة</string>
|
<string name="blogs_blog_post_received">تم إستلام تدوينة جديدة</string>
|
||||||
<string name="blogs_blog_post_scroll_to">إنزل إلى</string>
|
<string name="blogs_blog_post_scroll_to">النزول إلى</string>
|
||||||
<string name="blogs_feed_empty_state">لا منشورات للعرض</string>
|
<string name="blogs_feed_empty_state">لا منشورات للعرض</string>
|
||||||
<string name="blogs_feed_empty_state_action">التدوينات من جهات اتصالك والمدونات التي تشترك بها ستظهر هنا\n\nالمس أيقونة القلم لتكتب تدوينة</string>
|
<string name="blogs_feed_empty_state_action">التدوينات من جهات اتصالك والمدونات التي تشترك/ين بها ستظهر هنا\n\nالرجاء لمس أيقونة القلم لكتابة تدوينة</string>
|
||||||
<string name="blogs_remove_blog">احذف المدونة</string>
|
<string name="blogs_remove_blog">حذف المدونة</string>
|
||||||
<string name="blogs_remove_blog_dialog_message">هل متأكد أنك تريد حذف هذه المدونة؟\n\nالتدوينات سيتم حذفها من جهازك فقط وليس من أجهزة الآخرين.\n\nأي جهة اتصال قمت بمشاركة المدونة معه قد لا يتمكن من استلام التحديثات.</string>
|
<string name="blogs_remove_blog_dialog_message">هل أنت متأكد/ة من أنك تريد/ين حذف هذه المدونة؟\n\nالتدوينات سيتم حذفها من جهازك فقط وليس من أجهزة الآخرين.\n\nأي جهة اتصال قمت/ي بمشاركة المدونة معها قد لا تتمكن من استلام التحديثات.</string>
|
||||||
<string name="blogs_remove_blog_ok">أزِل</string>
|
<string name="blogs_remove_blog_ok">حذف</string>
|
||||||
<string name="blogs_blog_removed">تم حذف المدونة</string>
|
<string name="blogs_blog_removed">تم حذف المدونة</string>
|
||||||
<string name="blogs_reblog_comment_hint">أضف تعليق (إختياري)</string>
|
<string name="blogs_reblog_comment_hint">اضافة تعليق (إختياري)</string>
|
||||||
<string name="blogs_reblog_button">أعد التدوين</string>
|
<string name="blogs_reblog_button">اعادة التدوين</string>
|
||||||
<!--Blog Sharing-->
|
<!--Blog Sharing-->
|
||||||
<string name="blogs_sharing_share">شارك المدونة</string>
|
<string name="blogs_sharing_share">مشاركة المدونة</string>
|
||||||
<string name="blogs_sharing_error">حدث خطأ في مشاركة هذه المدونة.</string>
|
<string name="blogs_sharing_error">حدث خطأ في مشاركة هذه المدونة.</string>
|
||||||
<string name="blogs_sharing_button">شارك المدونة</string>
|
<string name="blogs_sharing_button">مشاركة المدونة</string>
|
||||||
<string name="blogs_sharing_snackbar">تم مشاركة المدونة مع جهات الاتصال المختارة</string>
|
<string name="blogs_sharing_snackbar">تم مشاركة المدونة مع جهات الاتصال المختارة</string>
|
||||||
<string name="blogs_sharing_response_accepted_sent">لقد قبلت دعوة المدونة من %s.</string>
|
<string name="blogs_sharing_response_accepted_sent">لقد قبلت دعوة المدونة من %s.</string>
|
||||||
<string name="blogs_sharing_response_declined_sent">لقد رفضت دعوة المدونة من %s.</string>
|
<string name="blogs_sharing_response_declined_sent">لقد رفضت دعوة المدونة من %s.</string>
|
||||||
<string name="blogs_sharing_response_accepted_received">قبل %s دعوة المدونة.</string>
|
<string name="blogs_sharing_response_accepted_received">قبل/ت %s دعوة المدونة.</string>
|
||||||
<string name="blogs_sharing_response_declined_received">رفض %s دعوة المدونة.</string>
|
<string name="blogs_sharing_response_declined_received">رفض/ت %s دعوة المدونة.</string>
|
||||||
<string name="blogs_sharing_invitation_received">قام %1$s بمشاركة المدونة \"%2$s\" معك.</string>
|
<string name="blogs_sharing_invitation_received">قام/ت %1$s بمشاركة المدونة \"%2$s\" معك.</string>
|
||||||
<string name="blogs_sharing_invitation_sent">قمت بمشاركة المدونة \"%1$s\" مع %2$s.</string>
|
<string name="blogs_sharing_invitation_sent">تمت مشاركة المدونة \"%1$s\" مع %2$s.</string>
|
||||||
<string name="blogs_sharing_invitations_title">دعوات المدونة</string>
|
<string name="blogs_sharing_invitations_title">دعوات المدونة</string>
|
||||||
<string name="blogs_sharing_joined_toast">أشترك في المدونة</string>
|
<string name="blogs_sharing_joined_toast">مشترك/ة في المدونة</string>
|
||||||
<string name="blogs_sharing_declined_toast">تم رفض الدعوة</string>
|
<string name="blogs_sharing_declined_toast">تم رفض الدعوة</string>
|
||||||
<string name="sharing_status_blog">أي شخص أشترك في مدونة يمكنه مشاركتها مع جهات اتصاله. أنت تشارك هذه المدونة مع جهات الإتصال التالية. قد يكون هناك مشتركون آخرون لا يمكنك رؤيتهم.</string>
|
<string name="sharing_status_blog">أي شخص أشترك في مدونة يمكنه مشاركتها مع جهات اتصاله. أنت تشارك/ين هذه المدونة مع جهات الإتصال التالية. قد يكون هناك مشتركون آخرون لا يمكن رؤيتهم.</string>
|
||||||
<!--RSS Feeds-->
|
<!--RSS Feeds-->
|
||||||
<string name="blogs_rss_feeds_import">إستيراد تحديثات RSS</string>
|
<string name="blogs_rss_feeds_import">إستيراد تحديثات RSS</string>
|
||||||
<string name="blogs_rss_feeds_import_button">إستيراد</string>
|
<string name="blogs_rss_feeds_import_button">إستيراد</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">أدخل رابط تحديثات RSS</string>
|
<string name="blogs_rss_feeds_import_hint">ادخال رابط تحديثات RSS</string>
|
||||||
<string name="blogs_rss_feeds_import_error">معذرة! حدث خطأ في استيراد التحديثات.</string>
|
<string name="blogs_rss_feeds_import_error">معذرة! حدث خطأ في استيراد التحديثات.</string>
|
||||||
<string name="blogs_rss_feeds_manage">إدارة تحديثات RSS</string>
|
<string name="blogs_rss_feeds_manage">إدارة تحديثات RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">مستوردة:</string>
|
<string name="blogs_rss_feeds_manage_imported">تم استيراد:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">المؤلف:</string>
|
<string name="blogs_rss_feeds_manage_author">المؤلف/ة:</string>
|
||||||
<string name="blogs_rss_feeds_manage_updated">آخر تحديث:</string>
|
<string name="blogs_rss_feeds_manage_updated">آخر تحديث:</string>
|
||||||
<string name="blogs_rss_remove_feed">أزل الخلاصة</string>
|
<string name="blogs_rss_remove_feed">ازالة الخلاصة</string>
|
||||||
<string name="blogs_rss_remove_feed_dialog_message">هل متأكد من رغبتك في حذف هذه الخلاصة؟\n\nالمنشورات ستحذف من جهازك وليس من أجهزة الآخرين.\n\nأي جهة اتصال قمت بمشاركة هذه الخلاصة معهم قد لا يتمكنون من استلام التحديثات.</string>
|
<string name="blogs_rss_remove_feed_dialog_message">هل أنت متأكد/ة من رغبتك في حذف هذه الخلاصة؟\n\nالمنشورات ستحذف من جهازك وليس من أجهزة الآخرين.\n\nأي جهة اتصال قمت/ي بمشاركة هذه الخلاصة معها قد لا تتمكن من استلام التحديثات.</string>
|
||||||
<string name="blogs_rss_remove_feed_ok">أزِل</string>
|
<string name="blogs_rss_remove_feed_ok">حذف</string>
|
||||||
<string name="blogs_rss_feeds_manage_delete_error">لا يمكن حذف الخلاصة!</string>
|
<string name="blogs_rss_feeds_manage_delete_error">لا يمكن حذف الخلاصة!</string>
|
||||||
<string name="blogs_rss_feeds_manage_empty_state">لا خلاصات RSS للعرض\n\nالمس علامة + لإستيراد خلاصة.</string>
|
<string name="blogs_rss_feeds_manage_empty_state">لا خلاصات RSS للعرض\n\nالرجاء لمس علامة + لإستيراد خلاصة.</string>
|
||||||
<string name="blogs_rss_feeds_manage_error">حدث خطأ في جلب خلاصاتك. من فضلك حاول لاحقًا.</string>
|
<string name="blogs_rss_feeds_manage_error">حدث خطأ في جلب خلاصاتك. الرجاء المحاولة لاحقًا.</string>
|
||||||
<!--Settings Display-->
|
<!--Settings Display-->
|
||||||
<string name="pref_language_title">اللغة & المنطقة</string>
|
<string name="pref_language_title">اللغة & المنطقة</string>
|
||||||
<string name="pref_language_changed">هذا الإعداد سيتفعل بعد إعادة تشغيل Briar (براير). من فضلك سجل الخروج ثم أعد تشغيل Briar (براير).</string>
|
<string name="pref_language_changed">هذا الإعداد سيتفعل بعد إعادة تشغيل Briar (براير). الرجاء تسجيل الخروج ثم اعادة تشغيل Briar (براير).</string>
|
||||||
<string name="pref_language_default">النظام الإفتراضي</string>
|
<string name="pref_language_default">النظام الإفتراضي</string>
|
||||||
<string name="display_settings_title">العرض</string>
|
<string name="display_settings_title">العرض</string>
|
||||||
<string name="pref_theme_title">السمة</string>
|
<string name="pref_theme_title">السمة</string>
|
||||||
@@ -368,20 +369,20 @@
|
|||||||
<string name="bluetooth_setting">الإتصال عبر بلوتوث</string>
|
<string name="bluetooth_setting">الإتصال عبر بلوتوث</string>
|
||||||
<string name="bluetooth_setting_enabled">متى ما كان أحد جهات الاتصال قريبًا</string>
|
<string name="bluetooth_setting_enabled">متى ما كان أحد جهات الاتصال قريبًا</string>
|
||||||
<string name="bluetooth_setting_disabled">فقط عند إضافة جهة إتصال</string>
|
<string name="bluetooth_setting_disabled">فقط عند إضافة جهة إتصال</string>
|
||||||
<string name="tor_network_setting">اتصل عبر الانترنت (تور)</string>
|
<string name="tor_network_setting">اتصال عبر الانترنت (تور)</string>
|
||||||
<string name="tor_network_setting_automatic">تلقائيًا حسب الموقع</string>
|
<string name="tor_network_setting_automatic">تلقائيًا حسب الموقع</string>
|
||||||
<string name="tor_network_setting_without_bridges">استخدم تور بلا جسور</string>
|
<string name="tor_network_setting_without_bridges">استخدام تور بلا جسور</string>
|
||||||
<string name="tor_network_setting_with_bridges">استخدم تور مع الجسور</string>
|
<string name="tor_network_setting_with_bridges">استخدام تور مع الجسور</string>
|
||||||
<string name="tor_network_setting_never">لا تتصل</string>
|
<string name="tor_network_setting_never">عدم الاتصال</string>
|
||||||
<!--How and when Tor will connect after Automatic: E.g. Don't connect (in China) or Use Tor with bridges (in Belarus)-->
|
<!--How and when Tor will connect after Automatic: E.g. Don't connect (in China) or Use Tor with bridges (in Belarus)-->
|
||||||
<string name="tor_network_setting_summary">تلقائيا: %1$s (في %2$s)</string>
|
<string name="tor_network_setting_summary">تلقائيا: %1$s (في %2$s)</string>
|
||||||
<string name="tor_mobile_data_title">إستخدم بيانات الجوال</string>
|
<string name="tor_mobile_data_title">إستخدام بيانات الجوال</string>
|
||||||
<!--Settings Security and Panic-->
|
<!--Settings Security and Panic-->
|
||||||
<string name="security_settings_title">الأمان</string>
|
<string name="security_settings_title">الأمان</string>
|
||||||
<string name="pref_lock_summary">استخدم قفل شاشة الجهاز لحماية Briar (براير) في حال تسجيل الدخول</string>
|
<string name="pref_lock_summary">الرجاء استخدام قفل شاشة الجهاز لحماية Briar (براير) في حال تسجيل الدخول</string>
|
||||||
<string name="pref_lock_disabled_summary">لاستخدام هذه الميزة، قم بإعداد قفل شاشة لجهازك</string>
|
<string name="pref_lock_disabled_summary">لاستخدام هذه الميزة، الرجاء إعداد قفل شاشة لجهازك</string>
|
||||||
<!--The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour-->
|
<!--The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour-->
|
||||||
<string name="pref_lock_timeout_summary">حينما لا تستخدم Briar (براير)، أقفله تلقائيا بعد %s</string>
|
<string name="pref_lock_timeout_summary">في حالة عدم استعمال Briar (براير)، يقفل تلقائيا بعد %s</string>
|
||||||
<!--Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s"-->
|
<!--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 دقيقة</string>
|
<string name="pref_lock_timeout_1">1 دقيقة</string>
|
||||||
<!--Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s"-->
|
<!--Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s"-->
|
||||||
@@ -409,7 +410,7 @@
|
|||||||
<string name="dialog_title_connect_panic_app">تأكيد تطبيق الذعر</string>
|
<string name="dialog_title_connect_panic_app">تأكيد تطبيق الذعر</string>
|
||||||
<string name="dialog_message_connect_panic_app">هل متأكد أنك تريد السماح ل %1$s أن يقوم بتفعيل إجراءات زر الذعر؟</string>
|
<string name="dialog_message_connect_panic_app">هل متأكد أنك تريد السماح ل %1$s أن يقوم بتفعيل إجراءات زر الذعر؟</string>
|
||||||
<string name="panic_setting_signout_title">تسجيل الخروج</string>
|
<string name="panic_setting_signout_title">تسجيل الخروج</string>
|
||||||
<string name="panic_setting_signout_summary">سجل الخروج من Briar (براير) إذا تم ضغط زر الذعر</string>
|
<string name="panic_setting_signout_summary">تسجيل الخروج من Briar (براير) عند ضغط زر الذعر</string>
|
||||||
<string name="purge_setting_title">حذف الحساب</string>
|
<string name="purge_setting_title">حذف الحساب</string>
|
||||||
<string name="purge_setting_summary">احذف حساب Briar (براير) إذا تم ضغط زر الذعر. انتبه: هذا سيسبب حذف دائم لكل معرفات وحساباتك ورسائلك.</string>
|
<string name="purge_setting_summary">احذف حساب Briar (براير) إذا تم ضغط زر الذعر. انتبه: هذا سيسبب حذف دائم لكل معرفات وحساباتك ورسائلك.</string>
|
||||||
<string name="uninstall_setting_title">ألغ تثبيت Briar (براير)</string>
|
<string name="uninstall_setting_title">ألغ تثبيت Briar (براير)</string>
|
||||||
@@ -440,44 +441,51 @@
|
|||||||
<string name="feedback_settings_title">الإفادة حول التطبيق</string>
|
<string name="feedback_settings_title">الإفادة حول التطبيق</string>
|
||||||
<string name="send_feedback">أرسل ملاحظاتك</string>
|
<string name="send_feedback">أرسل ملاحظاتك</string>
|
||||||
<!--Link Warning-->
|
<!--Link Warning-->
|
||||||
<string name="link_warning_title">تنبيه الرابط</string>
|
<string name="link_warning_title">تنبيه بوجود رابط</string>
|
||||||
<string name="link_warning_intro">أنت بصدد فتح هذا الرابط في تطبيق خارجي</string>
|
<string name="link_warning_intro">أنت بصدد فتح هذا الرابط في تطبيق خارجي</string>
|
||||||
<string name="link_warning_text">يمكن أن يستعمل هذا في تحديد هويتك. تأمل في مدى ثقتك بالشخص الذي أرسل لك هذا الرابط ويفضل بالنظر بفتحه بإستعمال أورفوكس.</string>
|
<string name="link_warning_text">يمكن أن يستعمل هذا في تحديد هويتك. يرجى التفكير في مدى ثقتك بالشخص الذي أرسل لك هذا الرابط و من الأفضل فتحه بإستعمال أورفوكس.</string>
|
||||||
<string name="link_warning_open_link">افتح الرابط</string>
|
<string name="link_warning_open_link">افتح الرابط</string>
|
||||||
<!--Crash Reporter-->
|
<!--Crash Reporter-->
|
||||||
<string name="crash_report_title">تقرير إنهيار Briar (براير)</string>
|
<string name="crash_report_title">تقرير إنهيار Briar (براير)</string>
|
||||||
<string name="briar_crashed">معذرة، لقد انهار Briar (براير).</string>
|
<string name="briar_crashed">معذرة، لقد انهار Briar (براير).</string>
|
||||||
<string name="not_your_fault">هذا ليس خطؤك.</string>
|
<string name="not_your_fault">هذا ليس خطؤك.</string>
|
||||||
<string name="please_send_report">من فضلك ساعدنا في تحسين Briar (براير) عبر إرسال تقرير الإنهيار.</string>
|
<string name="please_send_report">الرجاء مساعدتنا في تحسين Briar (براير) عبر إرسال تقرير الإنهيار.</string>
|
||||||
<string name="report_is_encrypted">نعدك بأن التقرير سيرسل مشفرًا وبشكل آمن.</string>
|
<string name="report_is_encrypted">نعدك بأن التقرير سيرسل مشفرًا وبشكل آمن.</string>
|
||||||
<string name="feedback_title">الإفادة حول التطبيق</string>
|
<string name="feedback_title">الإفادة حول التطبيق</string>
|
||||||
<string name="describe_crash">صف ما حدث (إختياري)</string>
|
<string name="describe_crash">وصف ما حدث (إختياري)</string>
|
||||||
<string name="enter_feedback">أدخل ملاحظاتك</string>
|
<string name="enter_feedback">ادخال ملاحظاتك</string>
|
||||||
<string name="optional_contact_email">بريدك الالكتروني (إختياري)</string>
|
<string name="optional_contact_email">بريدك الالكتروني (إختياري)</string>
|
||||||
<string name="include_debug_report_crash">ضمن بيانات مجهولة عن الإنهيار</string>
|
<string name="include_debug_report_crash">تضمين بيانات مجهولة عن الإنهيار</string>
|
||||||
<string name="include_debug_report_feedback">ضمن بيانات مجهولة عن هذا الجهاز</string>
|
<string name="include_debug_report_feedback">تضمين بيانات مجهولة عن هذا الجهاز</string>
|
||||||
<string name="could_not_load_report_data">لم يمكن تحميل بيانات التقرير.</string>
|
<string name="could_not_load_report_data">لم يمكن تحميل بيانات التقرير.</string>
|
||||||
<string name="send_report">أرسل التقرير</string>
|
<string name="send_report">ارسال التقرير</string>
|
||||||
<string name="close">إغلاق</string>
|
<string name="close">إغلاق</string>
|
||||||
<string name="dev_report_saved">تم حفظ التقرير. سيتم إرساله عند تسجيل الدخول إلى Briar (براير) في المرة القادمة.</string>
|
<string name="dev_report_saved">تم حفظ التقرير. سيتم إرساله عند تسجيل الدخول إلى Briar (براير) في المرة القادمة.</string>
|
||||||
<!--Sign Out-->
|
<!--Sign Out-->
|
||||||
<string name="progress_title_logout">تسجيل الخروج من Briar (براير)...</string>
|
<string name="progress_title_logout">تسجيل الخروج من Briar (براير)...</string>
|
||||||
<!--Screen Filters & Tapjacking-->
|
<!--Screen Filters & Tapjacking-->
|
||||||
<string name="screen_filter_title">تم إكتشاف غلاف شاشة</string>
|
<string name="screen_filter_title">تم إكتشاف غلاف شاشة</string>
|
||||||
<string name="screen_filter_body">تطبيق آخر يعمل كغلاف فوق Briar (براير). لحماية أمنك فإن Briar (براير) لن يستجيب للمس طالما كان تطبيق آخر فوقه.\n\nيحتمل أن يكون أحد هذه التطبيقات الذي يعمل بالفوق:\n\n %1$s</string>
|
<string name="screen_filter_body">تطبيق آخر يعمل كغلاف فوق Briar (براير). لحماية أمنك فإن Briar (براير) لن يستجيب للمس طالما كان تطبيق آخر فوقه.\n\nيحتمل أن تكون أحد هذه التطبيقات التي تعمل بالفوق:\n\n %1$s</string>
|
||||||
<string name="screen_filter_allow">إسمح لهذه التطبيقات بالعمل فوق غيرها</string>
|
<string name="screen_filter_allow">السماح لهذه التطبيقات بالعمل فوق غيرها</string>
|
||||||
<!--Permission Requests-->
|
<!--Permission Requests-->
|
||||||
<string name="permission_camera_title">إذن الكاميرا</string>
|
<string name="permission_camera_title">إذن الكاميرا</string>
|
||||||
<string name="permission_camera_request_body">لتقم بمسح رمز QR، يحتاج Briar (براير) إلى إستعمال الكاميرا.</string>
|
<string name="permission_camera_request_body">للتمكن من مسح رمز QR، يحتاج Briar (براير) إلى إستعمال الكاميرا.</string>
|
||||||
<string name="permission_camera_denied_body">قد رفضت إعطاء إذن الكاميرا، لكن إضافة جهات إتصال يتطلب إستعمال الكاميرا.\n\nمن فضلك إمنحنا الإذن.</string>
|
<string name="permission_camera_denied_body">قد رفضت إعطاء إذن الكاميرا، لكن إضافة جهات إتصال يتطلب إستعمال الكاميرا.\n\nالرجاء منح الإذن.</string>
|
||||||
<string name="permission_camera_denied_toast">لم يتم منح الإذن بإستعمال الكاميرا</string>
|
<string name="permission_camera_denied_toast">لم يتم منح الإذن بإستعمال الكاميرا</string>
|
||||||
<string name="qr_code">رمز QR</string>
|
<string name="qr_code">رمز QR</string>
|
||||||
<string name="show_qr_code_fullscreen">أظهر رمز QR بوضع ملء الشاشة</string>
|
<string name="show_qr_code_fullscreen">اظهار رمز QR بوضع ملء الشاشة</string>
|
||||||
<!--App Locking-->
|
<!--App Locking-->
|
||||||
<string name="lock_unlock">فك قفل Briar (براير)</string>
|
<string name="lock_unlock">فك قفل Briar (براير)</string>
|
||||||
<string name="lock_unlock_verbose">أدخل رمز، نمط أو كلمة سر جهازك لإلغاء قفل Briar (براير)</string>
|
<string name="lock_unlock_verbose">ادخال رمز، نمط أو كلمة سر جهازك لإلغاء قفل Briar (براير)</string>
|
||||||
<string name="lock_unlock_fingerprint_description">المس حساس البصمة ببصمتك المسجلة للإستمرار</string>
|
<string name="lock_unlock_fingerprint_description">لمس حساس البصمة ببصمتك المسجلة للإستمرار</string>
|
||||||
<string name="lock_unlock_password">استخدم كلمة السر</string>
|
<string name="lock_unlock_password">استخدام كلمة السر</string>
|
||||||
<string name="lock_is_locked">Briar (براير) مقفل</string>
|
<string name="lock_is_locked">Briar (براير) مقفل</string>
|
||||||
<string name="lock_tap_to_unlock">إلمس لفك القفل</string>
|
<string name="lock_tap_to_unlock">الرجاء اللمس لفك القفل</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -440,4 +440,11 @@
|
|||||||
<string name="lock_unlock_password">Usa la contrasenya</string>
|
<string name="lock_unlock_password">Usa la contrasenya</string>
|
||||||
<string name="lock_is_locked">Briar està bloquejat</string>
|
<string name="lock_is_locked">Briar està bloquejat</string>
|
||||||
<string name="lock_tap_to_unlock">Toqueu per desbloquejar-lo</string>
|
<string name="lock_tap_to_unlock">Toqueu per desbloquejar-lo</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -407,4 +407,11 @@
|
|||||||
<string name="qr_code">QR kód</string>
|
<string name="qr_code">QR kód</string>
|
||||||
<string name="show_qr_code_fullscreen">Zobrazit QR kód na celou obrazovku</string>
|
<string name="show_qr_code_fullscreen">Zobrazit QR kód na celou obrazovku</string>
|
||||||
<!--App Locking-->
|
<!--App Locking-->
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -440,4 +440,11 @@
|
|||||||
<string name="lock_unlock_password">Benutze Passwort</string>
|
<string name="lock_unlock_password">Benutze Passwort</string>
|
||||||
<string name="lock_is_locked">Briar ist gesperrt</string>
|
<string name="lock_is_locked">Briar ist gesperrt</string>
|
||||||
<string name="lock_tap_to_unlock">Zum Entsperren antippen</string>
|
<string name="lock_tap_to_unlock">Zum Entsperren antippen</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -445,4 +445,17 @@
|
|||||||
<string name="lock_unlock_password">Usa la contraseña</string>
|
<string name="lock_unlock_password">Usa la contraseña</string>
|
||||||
<string name="lock_is_locked">Briar está bloqueado</string>
|
<string name="lock_is_locked">Briar está bloqueado</string>
|
||||||
<string name="lock_tap_to_unlock">Golpear para desbloquear</string>
|
<string name="lock_tap_to_unlock">Golpear para desbloquear</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_alice">Alicia</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_bob">Roberto</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_carol">Carolina</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<string name="screenshot_message_1">¡Hola Roberto!</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<string name="screenshot_message_2">¡Hola Alicia! ¡Gracias por contarme acerca de Briar!</string>
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
|
<string name="screenshot_message_3">Sin problema, espero que te guste 😀</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -129,6 +129,8 @@
|
|||||||
<string name="contact_added_toast">Kontaktua gehitu da: %s</string>
|
<string name="contact_added_toast">Kontaktua gehitu da: %s</string>
|
||||||
<string name="contact_already_exists">%s kontaktua badago aurretik ere</string>
|
<string name="contact_already_exists">%s kontaktua badago aurretik ere</string>
|
||||||
<string name="qr_code_invalid">QR kodea baliogabea da</string>
|
<string name="qr_code_invalid">QR kodea baliogabea da</string>
|
||||||
|
<string name="qr_code_too_old">Eskaneatu duzun QR kodea %s aplikazioaren bertsio zaharrago batetik dator.\n\nEskatu mesedez zure kontaktuari azken bertsiora eguneratu dezala eta saiatu berriro.</string>
|
||||||
|
<string name="qr_code_too_new">Eskaneatu duzun QR kodea %s aplikazioaren bertsio berriago batetik dator.\n\nEguneratu azken bertsiora eta saiatu berriro.</string>
|
||||||
<string name="camera_error">Kameraren errorea</string>
|
<string name="camera_error">Kameraren errorea</string>
|
||||||
<string name="connecting_to_device">Gailura konektatzen\u2026</string>
|
<string name="connecting_to_device">Gailura konektatzen\u2026</string>
|
||||||
<string name="authenticating_with_device">Gailuarekin autentifikatzen\u2026</string>
|
<string name="authenticating_with_device">Gailuarekin autentifikatzen\u2026</string>
|
||||||
@@ -338,8 +340,10 @@
|
|||||||
<string name="tor_mobile_data_title">Erabili datu mugikorrak</string>
|
<string name="tor_mobile_data_title">Erabili datu mugikorrak</string>
|
||||||
<!--Settings Security and Panic-->
|
<!--Settings Security and Panic-->
|
||||||
<string name="security_settings_title">Segurtasuna</string>
|
<string name="security_settings_title">Segurtasuna</string>
|
||||||
|
<string name="pref_lock_title">Aplikazioaren blokeoa</string>
|
||||||
<string name="pref_lock_summary">Erabili gailuaren pantaila-blokeoa Briar babesteko saioa irekita dagoen bitartean</string>
|
<string name="pref_lock_summary">Erabili gailuaren pantaila-blokeoa Briar babesteko saioa irekita dagoen bitartean</string>
|
||||||
<string name="pref_lock_disabled_summary">Eginbide hau erabiltzeko, ezarri zure gailuarentzako pantaila-blokeo bat</string>
|
<string name="pref_lock_disabled_summary">Eginbide hau erabiltzeko, ezarri zure gailuarentzako pantaila-blokeo bat</string>
|
||||||
|
<string name="pref_lock_timeout_title">Aplikazioa blokeatzeko jarduera ezaren denbora-muga</string>
|
||||||
<!--The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour-->
|
<!--The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour-->
|
||||||
<string name="pref_lock_timeout_summary">Briar ez erabiltzean, hura automatikoki blokeatu %s eta gero</string>
|
<string name="pref_lock_timeout_summary">Briar ez erabiltzean, hura automatikoki blokeatu %s eta gero</string>
|
||||||
<!--Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s"-->
|
<!--Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s"-->
|
||||||
@@ -368,6 +372,7 @@
|
|||||||
<string name="panic_app_setting_none">Bat ere ez</string>
|
<string name="panic_app_setting_none">Bat ere ez</string>
|
||||||
<string name="dialog_title_connect_panic_app">Baieztatu larrialdi-aplikazioa</string>
|
<string name="dialog_title_connect_panic_app">Baieztatu larrialdi-aplikazioa</string>
|
||||||
<string name="dialog_message_connect_panic_app">Ziur zaude %1$s larrialdi-botoiaren ekintza suntsitzaileak eragitera baimendu nahi duzula?</string>
|
<string name="dialog_message_connect_panic_app">Ziur zaude %1$s larrialdi-botoiaren ekintza suntsitzaileak eragitera baimendu nahi duzula?</string>
|
||||||
|
<string name="panic_setting_destructive_action">Ekintza suntsigarriak</string>
|
||||||
<string name="panic_setting_signout_title">Amaitu saioa</string>
|
<string name="panic_setting_signout_title">Amaitu saioa</string>
|
||||||
<string name="panic_setting_signout_summary">Amaitu Briar saioa larrialdi-botoia zapaltzen bada</string>
|
<string name="panic_setting_signout_summary">Amaitu Briar saioa larrialdi-botoia zapaltzen bada</string>
|
||||||
<string name="purge_setting_title">Ezabatu kontua</string>
|
<string name="purge_setting_title">Ezabatu kontua</string>
|
||||||
@@ -440,4 +445,17 @@
|
|||||||
<string name="lock_unlock_password">Erabili pasahitza</string>
|
<string name="lock_unlock_password">Erabili pasahitza</string>
|
||||||
<string name="lock_is_locked">Briar blokeatuta dago</string>
|
<string name="lock_is_locked">Briar blokeatuta dago</string>
|
||||||
<string name="lock_tap_to_unlock">Sakatu desblokeatzeko</string>
|
<string name="lock_tap_to_unlock">Sakatu desblokeatzeko</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_alice">Arantza</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_bob">Jokin</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_carol">Maitane</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<string name="screenshot_message_1">Kaixo Jokin!</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<string name="screenshot_message_2">Kaixo Arantza, eskerrik asko Briar ezagutzera emateagatik!</string>
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
|
<string name="screenshot_message_3">Ez horregatik, ea gustuko duzun 😀</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -136,6 +136,12 @@
|
|||||||
<string name="contact_added_toast">مخاطب اضافه شد: %s</string>
|
<string name="contact_added_toast">مخاطب اضافه شد: %s</string>
|
||||||
<string name="contact_already_exists">مخاطب %s از قبل وجود دارد</string>
|
<string name="contact_already_exists">مخاطب %s از قبل وجود دارد</string>
|
||||||
<string name="qr_code_invalid">کد QR نامعتبر می باشد</string>
|
<string name="qr_code_invalid">کد QR نامعتبر می باشد</string>
|
||||||
|
<string name="qr_code_too_old">کد QR که شما اسکن کرده اید متعلق به یک نسخه قدیمی از %s می باشد.
|
||||||
|
|
||||||
|
لطفا از مخاطب خود بخواهید تا به آخرین نسخه آپگرید کرده و دوباره تلاش کنید.</string>
|
||||||
|
<string name="qr_code_too_new">کد QR که شما اسکن کرده اید متعلق به یک نسخه جدید از %s می باشد.
|
||||||
|
|
||||||
|
لطفا به آخرین نسخه آپگرید کرده و دوباره تلاش کنید.</string>
|
||||||
<string name="camera_error">خطای دوربین</string>
|
<string name="camera_error">خطای دوربین</string>
|
||||||
<string name="connecting_to_device">اتصال به دستگاهu2026\</string>
|
<string name="connecting_to_device">اتصال به دستگاهu2026\</string>
|
||||||
<string name="authenticating_with_device">تصدیق سازی با دستگاه u2026\</string>
|
<string name="authenticating_with_device">تصدیق سازی با دستگاه u2026\</string>
|
||||||
@@ -367,8 +373,10 @@
|
|||||||
<string name="tor_mobile_data_title">استفاده از داده موبایل</string>
|
<string name="tor_mobile_data_title">استفاده از داده موبایل</string>
|
||||||
<!--Settings Security and Panic-->
|
<!--Settings Security and Panic-->
|
||||||
<string name="security_settings_title">امنیت</string>
|
<string name="security_settings_title">امنیت</string>
|
||||||
|
<string name="pref_lock_title">قفل برنامه</string>
|
||||||
<string name="pref_lock_summary">استفاده از قفل صفحه دستگاه به منظور محافظت از Briar (برایر) در هنگام استفاده از آن</string>
|
<string name="pref_lock_summary">استفاده از قفل صفحه دستگاه به منظور محافظت از Briar (برایر) در هنگام استفاده از آن</string>
|
||||||
<string name="pref_lock_disabled_summary">برای استفاده از این ویژگی، قفل صفحه را برای دستگاه خود برپا کنید</string>
|
<string name="pref_lock_disabled_summary">برای استفاده از این ویژگی، قفل صفحه را برای دستگاه خود برپا کنید</string>
|
||||||
|
<string name="pref_lock_timeout_title">اتمام وقت عدم فعالیت قفل صفحه</string>
|
||||||
<!--The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour-->
|
<!--The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour-->
|
||||||
<string name="pref_lock_timeout_summary">زمانی که از Briar (برایر) استفاده نمی شود، به صورت خودکار بعد از %s آن را قفل کن</string>
|
<string name="pref_lock_timeout_summary">زمانی که از Briar (برایر) استفاده نمی شود، به صورت خودکار بعد از %s آن را قفل کن</string>
|
||||||
<!--Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s"-->
|
<!--Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s"-->
|
||||||
@@ -397,6 +405,7 @@
|
|||||||
<string name="panic_app_setting_none">هیچکدام</string>
|
<string name="panic_app_setting_none">هیچکدام</string>
|
||||||
<string name="dialog_title_connect_panic_app">تایید برنامه هراس</string>
|
<string name="dialog_title_connect_panic_app">تایید برنامه هراس</string>
|
||||||
<string name="dialog_message_connect_panic_app">آیا مطمئن هستید که میخواهید به %1$s اجازه دهید تا باعث عملیات مخرب دکمه هراس بشود؟</string>
|
<string name="dialog_message_connect_panic_app">آیا مطمئن هستید که میخواهید به %1$s اجازه دهید تا باعث عملیات مخرب دکمه هراس بشود؟</string>
|
||||||
|
<string name="panic_setting_destructive_action">فعالیت های مخرب</string>
|
||||||
<string name="panic_setting_signout_title">خروج</string>
|
<string name="panic_setting_signout_title">خروج</string>
|
||||||
<string name="panic_setting_signout_summary">در صورت کلیک بر روی کلید هراس از Briar (برایر) خارج شو</string>
|
<string name="panic_setting_signout_summary">در صورت کلیک بر روی کلید هراس از Briar (برایر) خارج شو</string>
|
||||||
<string name="purge_setting_title">حذف حساب کاربری</string>
|
<string name="purge_setting_title">حذف حساب کاربری</string>
|
||||||
@@ -475,4 +484,17 @@
|
|||||||
<string name="lock_unlock_password">از رمز عبور استفاده کنید</string>
|
<string name="lock_unlock_password">از رمز عبور استفاده کنید</string>
|
||||||
<string name="lock_is_locked">Briar (برایر) قفل می باشد</string>
|
<string name="lock_is_locked">Briar (برایر) قفل می باشد</string>
|
||||||
<string name="lock_tap_to_unlock">برای آنلاک کردن کلیک کنید</string>
|
<string name="lock_tap_to_unlock">برای آنلاک کردن کلیک کنید</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_alice">آلیس</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_bob">باب</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_carol">کارول</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<string name="screenshot_message_1">هی باب!</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<string name="screenshot_message_2">هی آلیس! ممنون از اینکه درباره Briar به من گفتی!</string>
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
|
<string name="screenshot_message_3">خواهش میکنم، امیدوارم ازش خوشت بیاد 😀</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -440,4 +440,11 @@
|
|||||||
<string name="lock_unlock_password">Käytä salasanaa</string>
|
<string name="lock_unlock_password">Käytä salasanaa</string>
|
||||||
<string name="lock_is_locked">Briar on lukittu</string>
|
<string name="lock_is_locked">Briar on lukittu</string>
|
||||||
<string name="lock_tap_to_unlock">Napauta avataksesi lukitus</string>
|
<string name="lock_tap_to_unlock">Napauta avataksesi lukitus</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
<string name="download_briar_button">Télécharger Briar 1.0</string>
|
<string name="download_briar_button">Télécharger Briar 1.0</string>
|
||||||
<string name="startup_open_database">Déchiffrement de la base de données…</string>
|
<string name="startup_open_database">Déchiffrement de la base de données…</string>
|
||||||
<string name="startup_migrate_database">Mise à niveau de la base de données…</string>
|
<string name="startup_migrate_database">Mise à niveau de la base de données…</string>
|
||||||
|
<string name="startup_compact_database">Compactage de la base de données…</string>
|
||||||
<!--Navigation Drawer-->
|
<!--Navigation Drawer-->
|
||||||
<string name="nav_drawer_open_description">Ouvrir le tiroir de navigation</string>
|
<string name="nav_drawer_open_description">Ouvrir le tiroir de navigation</string>
|
||||||
<string name="nav_drawer_close_description">Fermer le tiroir de navigation</string>
|
<string name="nav_drawer_close_description">Fermer le tiroir de navigation</string>
|
||||||
@@ -129,6 +130,8 @@
|
|||||||
<string name="contact_added_toast">Contact ajouté : %s</string>
|
<string name="contact_added_toast">Contact ajouté : %s</string>
|
||||||
<string name="contact_already_exists">Le contact %s existe déjà</string>
|
<string name="contact_already_exists">Le contact %s existe déjà</string>
|
||||||
<string name="qr_code_invalid">Le code QR est invalide</string>
|
<string name="qr_code_invalid">Le code QR est invalide</string>
|
||||||
|
<string name="qr_code_too_old">Le code QR que vous avez lu provient d’une version plus ancienne de %s.\n\nVeuillez demander à votre contact de passer à la version la plus récente, puis ressayez.</string>
|
||||||
|
<string name="qr_code_too_new">Le code QR que vous avez lu provient d’une version plus récente de %s.\n\nVeuillez passer à la version la plus récente, puis ressayez.</string>
|
||||||
<string name="camera_error">Erreur de la caméra</string>
|
<string name="camera_error">Erreur de la caméra</string>
|
||||||
<string name="connecting_to_device">Connexion à l’appareil\u2026</string>
|
<string name="connecting_to_device">Connexion à l’appareil\u2026</string>
|
||||||
<string name="authenticating_with_device">Autentification avec l’appareil\u2026</string>
|
<string name="authenticating_with_device">Autentification avec l’appareil\u2026</string>
|
||||||
@@ -370,6 +373,7 @@
|
|||||||
<string name="panic_app_setting_none">Aucune</string>
|
<string name="panic_app_setting_none">Aucune</string>
|
||||||
<string name="dialog_title_connect_panic_app">Confirmer l’application d’urgence</string>
|
<string name="dialog_title_connect_panic_app">Confirmer l’application d’urgence</string>
|
||||||
<string name="dialog_message_connect_panic_app">Voulez-vous vraiment autoriser %1$s à déclencher les actions destructrices du bouton d’urgence ?</string>
|
<string name="dialog_message_connect_panic_app">Voulez-vous vraiment autoriser %1$s à déclencher les actions destructrices du bouton d’urgence ?</string>
|
||||||
|
<string name="panic_setting_destructive_action">Actions destructrices</string>
|
||||||
<string name="panic_setting_signout_title">Déconnexion</string>
|
<string name="panic_setting_signout_title">Déconnexion</string>
|
||||||
<string name="panic_setting_signout_summary">Se déconnecter de Briar si l’on appuie sur un bouton d’urgence</string>
|
<string name="panic_setting_signout_summary">Se déconnecter de Briar si l’on appuie sur un bouton d’urgence</string>
|
||||||
<string name="purge_setting_title">Supprimer le compte</string>
|
<string name="purge_setting_title">Supprimer le compte</string>
|
||||||
@@ -442,4 +446,17 @@
|
|||||||
<string name="lock_unlock_password">Utiliser un mot de passe</string>
|
<string name="lock_unlock_password">Utiliser un mot de passe</string>
|
||||||
<string name="lock_is_locked">Briar est verrouillée</string>
|
<string name="lock_is_locked">Briar est verrouillée</string>
|
||||||
<string name="lock_tap_to_unlock">Toucher pour déverrouiller</string>
|
<string name="lock_tap_to_unlock">Toucher pour déverrouiller</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_alice">Laurence</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_bob">Thomas</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_carol">Léa</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<string name="screenshot_message_1">Bonjour, Thomas !</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<string name="screenshot_message_2">Bonjour, Laurence ! Merci de m’avoir parlé de Briar !</string>
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
|
<string name="screenshot_message_3">Pas de problème, j’espère que tu aimeras l’appli 😀</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
<string name="download_briar_button">Descargar Briar 1.0</string>
|
<string name="download_briar_button">Descargar Briar 1.0</string>
|
||||||
<string name="startup_open_database">Descifrando a Base de datos...</string>
|
<string name="startup_open_database">Descifrando a Base de datos...</string>
|
||||||
<string name="startup_migrate_database">Actualizando a Base de datos...</string>
|
<string name="startup_migrate_database">Actualizando a Base de datos...</string>
|
||||||
|
<string name="startup_compact_database">Compactando a base de datos...</string>
|
||||||
<!--Navigation Drawer-->
|
<!--Navigation Drawer-->
|
||||||
<string name="nav_drawer_open_description">Abra a gaveta de navegación</string>
|
<string name="nav_drawer_open_description">Abra a gaveta de navegación</string>
|
||||||
<string name="nav_drawer_close_description">Peche a gaveta de navegación</string>
|
<string name="nav_drawer_close_description">Peche a gaveta de navegación</string>
|
||||||
@@ -129,6 +130,8 @@
|
|||||||
<string name="contact_added_toast">Contacto engadido: %s</string>
|
<string name="contact_added_toast">Contacto engadido: %s</string>
|
||||||
<string name="contact_already_exists">O contacto %s xa existe</string>
|
<string name="contact_already_exists">O contacto %s xa existe</string>
|
||||||
<string name="qr_code_invalid">O código QR non é válido</string>
|
<string name="qr_code_invalid">O código QR non é válido</string>
|
||||||
|
<string name="qr_code_too_old">O código QR que escaneou procede de unha versión anterior de %s.\n\nPor favor, solicite ao seu contacto actualizar a nova versión e inténteo de novo.</string>
|
||||||
|
<string name="qr_code_too_new">O código QR que escaneou procede de unha nova versión de %s.\n\nPor favor, actualice a última versión e inténteo de novo.</string>
|
||||||
<string name="camera_error">Fallo na cámara</string>
|
<string name="camera_error">Fallo na cámara</string>
|
||||||
<string name="connecting_to_device">Conectando co dispositivo\u2026</string>
|
<string name="connecting_to_device">Conectando co dispositivo\u2026</string>
|
||||||
<string name="authenticating_with_device">Autenticándose co dispositivo\u2026</string>
|
<string name="authenticating_with_device">Autenticándose co dispositivo\u2026</string>
|
||||||
@@ -370,6 +373,7 @@
|
|||||||
<string name="panic_app_setting_none">Ningún</string>
|
<string name="panic_app_setting_none">Ningún</string>
|
||||||
<string name="dialog_title_connect_panic_app">Confirme a App do pánico</string>
|
<string name="dialog_title_connect_panic_app">Confirme a App do pánico</string>
|
||||||
<string name="dialog_message_connect_panic_app">Está segura de querer permitir a %1$s activar accións destrutivas do botón do pánico?</string>
|
<string name="dialog_message_connect_panic_app">Está segura de querer permitir a %1$s activar accións destrutivas do botón do pánico?</string>
|
||||||
|
<string name="panic_setting_destructive_action">Accións destructivas</string>
|
||||||
<string name="panic_setting_signout_title">Finalizar sesión</string>
|
<string name="panic_setting_signout_title">Finalizar sesión</string>
|
||||||
<string name="panic_setting_signout_summary">Desconecte de Briar si o botón do pánico se preme</string>
|
<string name="panic_setting_signout_summary">Desconecte de Briar si o botón do pánico se preme</string>
|
||||||
<string name="purge_setting_title">Eliminar conta</string>
|
<string name="purge_setting_title">Eliminar conta</string>
|
||||||
@@ -442,4 +446,17 @@
|
|||||||
<string name="lock_unlock_password">Utilizar contrasinal</string>
|
<string name="lock_unlock_password">Utilizar contrasinal</string>
|
||||||
<string name="lock_is_locked">Briar está bloqueada</string>
|
<string name="lock_is_locked">Briar está bloqueada</string>
|
||||||
<string name="lock_tap_to_unlock">Toque para desbloquear</string>
|
<string name="lock_tap_to_unlock">Toque para desbloquear</string>
|
||||||
|
<!--Screenshots-->
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_alice">Alice</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_bob">Bob</string>
|
||||||
|
<!--This is a name to be used in screenshots. Feel free to change it to a local name.-->
|
||||||
|
<string name="screenshot_carol">Carol</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Bob!-->
|
||||||
|
<string name="screenshot_message_1">Ola Bob!</string>
|
||||||
|
<!--This is a message to be used in screenshots. Please use the same translation for Alice!-->
|
||||||
|
<string name="screenshot_message_2">Ola Alice! Grazas por falarme de Briar!</string>
|
||||||
|
<!--This is a message to be used in screenshots.-->
|
||||||
|
<string name="screenshot_message_3">Sen problema, agardo sexa do teu gusto 😀</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user