Compare commits

..

10 Commits

Author SHA1 Message Date
Ivana
543eda68b2 Update feature_request 2021-08-25 10:33:28 +00:00
Ivana
5033febaed Update feature_request 2021-08-25 10:12:57 +00:00
Ivana
c13b40ec2e Add new file 2021-08-25 10:12:08 +00:00
Ivana
b74f635ba7 Update bug_report.md 2021-08-24 09:23:02 +00:00
Ivana
5a6c1cc0e9 Update bug_report.md 2021-08-24 09:22:39 +00:00
Ivana
a45669a750 Update bug_report.md 2021-08-24 09:21:19 +00:00
Ivana
5dd183ce47 Update bug_report.md 2021-08-24 09:19:54 +00:00
Ivana
32d121566e Add new file - contains bug_report description template 2021-08-24 08:47:16 +00:00
Ivana
c76da20620 Add new directory issue_templates 2021-08-24 08:24:46 +00:00
Ivana
9b1d6d936e Add new directory 2021-08-24 08:16:11 +00:00
202 changed files with 1781 additions and 4830 deletions

0
.gitlab/.gitkeep Normal file
View File

View File

View File

@@ -0,0 +1,35 @@
# Summary
(Briefly describe the bug encontered)
# Steps to reproduce
(Please list the steps you performed when you encountered the bug)
-
-
-
# How often does it happen?
(Every time, Sometimes, It happened only once)
# What did you expect to happen
(Describe the app behaviour that you expected to happen)
# What actually happened?
(Describe what actually happened)
* What version of Briar app do you have installed? [Please fill in]
* Did you send the feedback from your device? [Yes/No]
* Your device manufacturer: [Please fill in]
* Your device model: [Please fill in]
* Android version: [Please fill in]

View File

@@ -0,0 +1,15 @@
# Are you requesting a new feature or an improvement to an existing feature?
# Brief description of the new or improved feature you would like to see in the Briar app
# Please describe in detail what you would like to do in Briar app, for which a new or improved feature is required?
* Does the absence of this feature prevent you from using the Briar app for certain activities? What are those activities?
* Would your use of Briar app increase with this new feature?

View File

@@ -31,6 +31,15 @@
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value />
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
@@ -188,9 +197,9 @@
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
<option name="ENUM_CONSTANTS_WRAP" value="1" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -1,32 +1,21 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":briar-android:testOfficialDebugUnitTest" />
<option value=":briar-android:testScreenshotDebugUnitTest" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<configuration default="false" name="All tests" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.briar-android" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-android" />
<method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="GradleRunConfiguration" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="GradleRunConfiguration" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="GradleRunConfiguration" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="GradleRunConfiguration" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-api" run_configuration_type="GradleRunConfiguration" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="GradleRunConfiguration" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-headless" run_configuration_type="GradleRunConfiguration" />
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" 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 briar-api" 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-headless" run_configuration_type="AndroidJUnit" />
</method>
</configuration>
</component>

View File

@@ -1,23 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-android" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":bramble-android:testDebugUnitTest" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-android" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-api" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":bramble-api:animalSnifferMain" />
<option value=":bramble-api:animalSnifferTest" />
<option value=":bramble-api:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-api" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-core" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":bramble-core:animalSnifferMain" />
<option value=":bramble-core:animalSnifferTest" />
<option value=":bramble-core:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,23 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-java" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":bramble-java:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-java" />
<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="-ea -Djava.library.path=libs" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,24 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-android" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":briar-android:testOfficialDebugUnitTest" />
<option value=":briar-android:testScreenshotDebugUnitTest" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.briar-android" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-api" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":briar-api:animalSnifferMain" />
<option value=":briar-api:animalSnifferTest" />
<option value=":briar-api:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in briar-api" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.briar-api" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-api" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-core" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":briar-core:animalSnifferMain" />
<option value=":briar-core:animalSnifferTest" />
<option value=":briar-core:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.briar-core" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,23 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-headless" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":briar-headless:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="All tests in briar-headless" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.briar-headless" />
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-headless" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,28 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="BridgeTest" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--tests &quot;org.briarproject.bramble.plugin.tor.BridgeTest&quot;" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value=":bramble-java:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
<configuration default="false" name="BridgeTest" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true">
<module name="briar.bramble-java" />
<useClassPathOnly />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.briarproject.bramble.plugin.tor.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="org.briarproject.bramble.plugin.tor" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<envs>
<env name="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
</envs>
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="org.briarproject.bramble.db" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.db.H2DatabasePerformanceTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="org.briarproject.bramble.db" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.db.HyperSqlDatabasePerformanceTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -15,8 +15,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionCode 10401
versionName "1.4.1"
versionCode 10306
versionName "1.3.6"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -42,8 +42,8 @@ configurations {
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
tor "org.briarproject:tor-android:$tor_version"
tor "org.briarproject:obfs4proxy-android:$obfs4proxy_version@zip"
tor 'org.briarproject:tor-android:0.3.5.15'
tor 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a@zip'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"

View File

@@ -5,15 +5,12 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -26,18 +23,14 @@ import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.getPersistentLogDir;
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.logFileOrDir;
class AndroidAccountManager extends AccountManagerImpl
implements AccountManager {
private static final Logger LOG =
getLogger(AndroidAccountManager.class.getName());
Logger.getLogger(AndroidAccountManager.class.getName());
/**
* Directories that shouldn't be deleted when deleting the user's account.
@@ -47,22 +40,13 @@ class AndroidAccountManager extends AccountManagerImpl
protected final Context appContext;
private final SharedPreferences prefs;
private final PersistentLogManager logManager;
private final FeatureFlags featureFlags;
@Inject
AndroidAccountManager(
DatabaseConfig databaseConfig,
CryptoComponent crypto,
IdentityManager identityManager,
SharedPreferences prefs,
PersistentLogManager logManager,
FeatureFlags featureFlags,
Application app) {
AndroidAccountManager(DatabaseConfig databaseConfig,
CryptoComponent crypto, IdentityManager identityManager,
SharedPreferences prefs, Application app) {
super(databaseConfig, crypto, identityManager);
this.prefs = prefs;
this.logManager = logManager;
this.featureFlags = featureFlags;
appContext = app.getApplicationContext();
}
@@ -90,9 +74,6 @@ class AndroidAccountManager extends AccountManagerImpl
LOG.info("Contents of account directory after deleting:");
logFileOrDir(LOG, INFO, getDataDir());
}
if (featureFlags.shouldEnablePersistentLogs()) {
replacePersistentLogger();
}
}
}
@@ -153,13 +134,4 @@ class AndroidAccountManager extends AccountManagerImpl
private void addIfNotNull(Set<File> files, @Nullable File file) {
if (file != null) files.add(file);
}
private void replacePersistentLogger() {
File logDir = getPersistentLogDir(appContext);
try {
logManager.addLogHandler(logDir, getLogger(""));
} catch (IOException e) {
logException(LOG, WARNING, e);
}
}
}

View File

@@ -70,14 +70,12 @@ class AndroidTorPlugin extends TorPlugin {
String architecture,
long maxLatency,
int maxIdleTime,
File torDirectory,
int torSocksPort,
int torControlPort) {
File torDirectory) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture, maxLatency,
maxIdleTime, torDirectory, torSocksPort, torControlPort);
maxIdleTime, torDirectory);
this.app = app;
wakeLock = wakeLockManager.createWakeLock("TorPlugin");
String nativeLibDir = app.getApplicationInfo().nativeLibraryDir;

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.plugin.tor;
import android.app.Application;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager;
@@ -12,9 +11,7 @@ import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
@@ -59,9 +56,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
private final AndroidWakeLockManager wakeLockManager;
private final Clock clock;
private final File torDirectory;
private int torSocksPort;
private int torControlPort;
private final CryptoComponent crypto;
@Inject
AndroidTorPluginFactory(@IoExecutor Executor ioExecutor,
@@ -77,10 +71,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
BatteryManager batteryManager,
AndroidWakeLockManager wakeLockManager,
Clock clock,
@TorDirectory File torDirectory,
@TorSocksPort int torSocksPort,
@TorControlPort int torControlPort,
CryptoComponent crypto) {
@TorDirectory File torDirectory) {
this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor;
this.app = app;
@@ -95,9 +86,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
this.wakeLockManager = wakeLockManager;
this.clock = clock;
this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort;
this.crypto = crypto;
}
@Override
@@ -139,15 +127,13 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto =
new TorRendezvousCryptoImpl(crypto);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor,
wakefulIoExecutor, app, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, wakeLockManager,
backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort,
torControlPort);
MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -111,14 +111,10 @@ public class AndroidUtils {
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
}
public static File getTemporaryLogFile(Context ctx) {
public static File getLogcatFile(Context ctx) {
return new File(ctx.getFilesDir(), STORED_LOGCAT);
}
public static File getPersistentLogDir(Context ctx) {
return ctx.getDir("log", MODE_PRIVATE);
}
/**
* Returns an array of supported content types for image attachments.
*/

View File

@@ -4,11 +4,9 @@ import android.app.Application;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.jmock.lib.legacy.ClassImposteriser;
@@ -17,9 +15,7 @@ import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.util.logging.Logger;
import static android.content.Context.MODE_PRIVATE;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
@@ -31,10 +27,6 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
context.mock(SharedPreferences.class, "prefs");
private final SharedPreferences defaultPrefs =
context.mock(SharedPreferences.class, "defaultPrefs");
private final PersistentLogManager logManager =
context.mock(PersistentLogManager.class);
private final FeatureFlags featureFlags =
context.mock(FeatureFlags.class);
private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
@@ -48,7 +40,6 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key");
private final File dbDir = new File(testDir, "db");
private final File logDir = new File(testDir, "log");
private AndroidAccountManager accountManager;
@@ -70,7 +61,7 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(app));
}});
accountManager = new AndroidAccountManager(databaseConfig, crypto,
identityManager, prefs, logManager, featureFlags, app) {
identityManager, prefs, app) {
@Override
SharedPreferences getDefaultSharedPreferences() {
return defaultPrefs;
@@ -118,17 +109,10 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(cacheDir));
oneOf(app).getExternalCacheDir();
will(returnValue(externalCacheDir));
oneOf(featureFlags).shouldEnablePersistentLogs();
will(returnValue(true));
oneOf(app).getDir("log", MODE_PRIVATE);
will(returnValue(logDir));
oneOf(logManager).addLogHandler(with(logDir),
with(any(Logger.class)));
}});
assertTrue(dbDir.mkdirs());
assertTrue(keyDir.mkdirs());
assertTrue(logDir.mkdirs());
assertTrue(codeCacheDir.mkdirs());
assertTrue(codeCacheFile.createNewFile());
assertTrue(libDir.mkdirs());
@@ -146,7 +130,6 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertFalse(dbDir.exists());
assertFalse(keyDir.exists());
assertFalse(logDir.exists());
assertTrue(codeCacheDir.exists());
assertTrue(codeCacheFile.exists());
assertTrue(libDir.exists());

View File

@@ -1,50 +1,50 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.android.tools.analytics-library:protos:30.0.3:protos-30.0.3.jar:f62b89dcd9de719c6a7b7e15fb1dd20e45b57222e675cf633607bd0ed6bca7e7',
'com.android.tools.analytics-library:shared:30.0.3:shared-30.0.3.jar:05aa9ba3cc890354108521fdf99802565aae5dd6ca44a6ac8bb8d594d1c1cd15',
'com.android.tools.analytics-library:tracker:30.0.3:tracker-30.0.3.jar:5d0ef35bf6733e96210b5085a2a202152921bf834d345959dce1ca3369b528df',
'com.android.tools.analytics-library:protos:27.1.3:protos-27.1.3.jar:0d9e6cff60b318baac250b6f5bb076a8161103338bf2749cdf1db8a5a13a1f12',
'com.android.tools.analytics-library:shared:27.1.3:shared-27.1.3.jar:10d2a51d8f89ff4ac849888e5a9c60b10e879c30d78545ec1da4d3df7bd56ae4',
'com.android.tools.analytics-library:tracker:27.1.3:tracker-27.1.3.jar:589b355a2ba796cbc0a2b2295737de6661f078262e5f87cd6f540b8d011e5ebb',
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
'com.android.tools.build:apksig:7.0.3:apksig-7.0.3.jar:012337a2803c9a30dfc41dcbc6450686ee9e5f582549f7f126479f743a343ec9',
'com.android.tools.build:apkzlib:7.0.3:apkzlib-7.0.3.jar:b31e53174c92db83c5cc6e7dac6734ea4e907a72e452c2bf1818dfd082c59397',
'com.android.tools.build:builder-model:7.0.3:builder-model-7.0.3.jar:483f99d7494a5bed027e1e8d29111384cf535d4842f0be5a79805bd44bb68d4e',
'com.android.tools.build:builder-test-api:7.0.3:builder-test-api-7.0.3.jar:f6de4bc2cef545e8367bf82d7c733829c7be3b0b3b8b09fd8c58f2150e59ab46',
'com.android.tools.build:builder:7.0.3:builder-7.0.3.jar:c6952da0094b094c2ba0fe84c675622097c5d9b9f9beb53485b860320540cf1d',
'com.android.tools.build:manifest-merger:30.0.3:manifest-merger-30.0.3.jar:72b346ba6318b4b6260e6e49df4bea5da2e12329ab6c2beb2269c49a9f51f178',
'com.android.tools.ddms:ddmlib:30.0.3:ddmlib-30.0.3.jar:7a914a68ab93393657297234e2f37b22410ae9a433cba692ce8c727c9607e3bb',
'com.android.tools.external.com-intellij:intellij-core:30.0.3:intellij-core-30.0.3.jar:1ebe858d3f58eeaa8c06507f8ac0f1c7051e6c61f35a70f3c3967d5734d3abc5',
'com.android.tools.external.com-intellij:kotlin-compiler:30.0.3:kotlin-compiler-30.0.3.jar:ed00e441f427cb4e0d418287b9da30b12b7f735f9af32e6b5d3dc960b6a742fc',
'com.android.tools.external.org-jetbrains:uast:30.0.3:uast-30.0.3.jar:a77801bee6ff509910e459525c9c34d7f04b066ade123547f16f1917548eadea',
'com.android.tools.layoutlib:layoutlib-api:30.0.3:layoutlib-api-30.0.3.jar:4caa87e9ca2e11315f650d576cd59fec1793373bc3fca3f6d53c029e7534e7c4',
'com.android.tools.lint:lint-api:30.0.3:lint-api-30.0.3.jar:bcecbd2f752a6560096a9029a47d1de6bd788a51bab505c5ebfba6a18524b983',
'com.android.tools.lint:lint-checks:30.0.3:lint-checks-30.0.3.jar:25a7cd42dc3ad502337f131fb8b7e873c53301db0a67b1c64dd4ae7a8eb66cec',
'com.android.tools.lint:lint-gradle:30.0.3:lint-gradle-30.0.3.jar:94544d6147a809bf2fd3440e51f28a4e42e547d74aab53eefd74938cdad42c26',
'com.android.tools.lint:lint-model:30.0.3:lint-model-30.0.3.jar:0b940a7f575c2ff5cbd038260f41dde686a93c672213881ead3ce8af3513b396',
'com.android.tools.lint:lint:30.0.3:lint-30.0.3.jar:ee4f11001e0c7e3b776e0d67399ad354b19b0f168822ec2b7db47c0910ed227d',
'com.android.tools:annotations:30.0.3:annotations-30.0.3.jar:5c1944982fda8555855c4f5422fabf0dc8e2306e1f5460e9ad82dae71316bc31',
'com.android.tools:common:30.0.3:common-30.0.3.jar:8751efaaf2c2ddd1f0a37526c794347def6a3057ca9fc510307c13a6cf0d036f',
'com.android.tools:dvlib:30.0.3:dvlib-30.0.3.jar:5affafcec390041e5afd64cb924153f5e474db47ee8ccc2f555b495083141233',
'com.android.tools:repository:30.0.3:repository-30.0.3.jar:0a40c6f16c506903ce2c609affd8228aceda73a69d93dfa42d4f02b8491449f6',
'com.android.tools:sdk-common:30.0.3:sdk-common-30.0.3.jar:b45570a380360236ffee0f6bb593d66b673bad3834dfe0d6c9871fa7188ee0eb',
'com.android.tools:sdklib:30.0.3:sdklib-30.0.3.jar:7088f20a414fab170a21e457825e14ebe099f753558e02c8acc12c67eb412162',
'com.android:signflinger:7.0.3:signflinger-7.0.3.jar:903a4536db3e96b4e1e1dc1e400eb0b91bf7866d9b39cd7ec94d75dde158f152',
'com.android:zipflinger:7.0.3:zipflinger-7.0.3.jar:fd209c960a3eff7a339e6fcba07d5e9ef4604d1633c69ab2df987460d9804140',
'com.beust:jcommander:1.78:jcommander-1.78.jar:7891debb84b5f83e9bd57593ebece3399abbe0fd938cf306b3534c57913b9615',
'com.github.javaparser:javaparser-core:3.17.0:javaparser-core-3.17.0.jar:23f5c982e1c7771423d37d52c774e8d2e80fd7ea7305ebe448797a96f67e6fca',
'com.android.tools.build:apksig:4.1.3:apksig-4.1.3.jar:a851980c678ff7a6785388b9a9e8cc094788ce3c4a985ad2b19c2028fd3c631a',
'com.android.tools.build:apkzlib:4.1.3:apkzlib-4.1.3.jar:475903065e7e83a8c1ba78d267c97a54dc5a04d768b535093850423d7b11f2c8',
'com.android.tools.build:builder-model:4.1.3:builder-model-4.1.3.jar:2624a1436c3ab39dd91d3ecf9409a594b0f89ea5cab255f2e9ff11f5ee03d274',
'com.android.tools.build:builder-test-api:4.1.3:builder-test-api-4.1.3.jar:3d2af66726b06b53b8d6d497efcee39ff9f77eb2f8d2cce38b31502383a40d2c',
'com.android.tools.build:builder:4.1.3:builder-4.1.3.jar:a40426cd6d68f6a722ef4950058c075e4547025e8c2fd78e732ad89f15176f84',
'com.android.tools.build:gradle-api:4.1.3:gradle-api-4.1.3.jar:11b1fb9de658bdcf9290b1c1517060d0c4d93f2b27975934989ca4ac890bc077',
'com.android.tools.build:manifest-merger:27.1.3:manifest-merger-27.1.3.jar:ce8d4009b1f1584777a7ffa1da3b0551dc316bc8e08112e442c352af70f46f2d',
'com.android.tools.ddms:ddmlib:27.1.3:ddmlib-27.1.3.jar:8f76e8236d2b9eebf26378746dad025c4c7c056a02e133dae4ddef47b283c710',
'com.android.tools.external.com-intellij:intellij-core:27.1.3:intellij-core-27.1.3.jar:652814fa099b4746fb6f10e19718e476952e8b5bac24e17d914f90650ad21808',
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.3:kotlin-compiler-27.1.3.jar:8d7a78d5efd213c5e467e42bd205582aad73ffc77ee5dc18eb1361c9af72f125',
'com.android.tools.external.org-jetbrains:uast:27.1.3:uast-27.1.3.jar:aea53944a1ac6a05f12297b55290e8cbecfe54c4166260cfba4405823bfe1c78',
'com.android.tools.layoutlib:layoutlib-api:27.1.3:layoutlib-api-27.1.3.jar:23875ce0a8429f33a4e86cc358f658faa0ba9c576f5f05760e544b453d67d04b',
'com.android.tools.lint:lint-api:27.1.3:lint-api-27.1.3.jar:97666be32bcadacd944416ea334a9575ef8f4ad0c8f333151491ff4a7df43e1c',
'com.android.tools.lint:lint-checks:27.1.3:lint-checks-27.1.3.jar:b2d71ae84a31490fe9ff26c706163fe245b2aea98e3eb747214c1085df444708',
'com.android.tools.lint:lint-gradle-api:27.1.3:lint-gradle-api-27.1.3.jar:e54131c287a2954e6ed78a3351e5e10e35a1da2f09ac443bf44b705c71b63a4d',
'com.android.tools.lint:lint-gradle:27.1.3:lint-gradle-27.1.3.jar:6a79e48943649d63665db7b17dbaff7af93e94ab9b15072f1a4d90486294ee9f',
'com.android.tools.lint:lint-model:27.1.3:lint-model-27.1.3.jar:acb9e792db7000e38e3c3ca21a9b14f2de6549d7a3fc92a97ffba3d06345e5bf',
'com.android.tools.lint:lint:27.1.3:lint-27.1.3.jar:5a2e69d0901a3a476a5b2d5001de755868113145f5f6aa557750cfad5389a44b',
'com.android.tools:annotations:27.1.3:annotations-27.1.3.jar:904dd771883496d5dfc86619ab2555968ea4e8a29d7a5f4f7cae6fbf5429f8f5',
'com.android.tools:common:27.1.3:common-27.1.3.jar:17ab4728e3ea50f047dd5937f0faf35f2c5416962ed74891057087ddc328bf96',
'com.android.tools:dvlib:27.1.3:dvlib-27.1.3.jar:cead1c0c356cbe43e6855b0330fe09ef4bec2c72e22bdb4c6e7cf7e6b1dfbc37',
'com.android.tools:repository:27.1.3:repository-27.1.3.jar:99de1a178855b56b8cd91a56296f1e0a9399c445e6acc51f1d2927947cc472cb',
'com.android.tools:sdk-common:27.1.3:sdk-common-27.1.3.jar:b591e2aa0f1be600795f5c9e2bf81cba9b052bee452fc86c3362b5dd9e427a14',
'com.android.tools:sdklib:27.1.3:sdklib-27.1.3.jar:ad6c08a45fe2904d05656bdddf9f623fa5c1d16bbd7b8d6a270a0734136ae02e',
'com.android:signflinger:4.1.3:signflinger-4.1.3.jar:f3103b55ccdc8dd9ee2517eb26af93b904d41303726594372d0df59d51156e5c',
'com.android:zipflinger:4.1.3:zipflinger-4.1.3.jar:48569896c0497268308a8014c66eb0f2bace2b9e2fc9390f3012823fb86387d5',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
'com.google.errorprone:error_prone_annotations:2.3.4:error_prone_annotations-2.3.4.jar:baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c',
'com.google.errorprone:error_prone_annotations:2.3.2:error_prone_annotations-2.3.2.jar:357cd6cfb067c969226c442451502aee13800a24e950fdfde77bcdb4565a668d',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
'com.google.guava:guava:30.1-jre:guava-30.1-jre.jar:e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa',
'com.google.guava:guava:28.1-jre:guava-28.1-jre.jar:30beb8b8527bd07c6e747e77f1a92122c2f29d57ce347461a4a55eb26e382da4',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
@@ -54,108 +54,63 @@ dependencyVerification {
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
'com.thoughtworks.qdox:qdox:1.12.1:qdox-1.12.1.jar:21fba22f830e9268f07cf4ab2d99e8181abbdcb0cb91ee0228eb3cb918dcdd1d',
'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
'commons-io:commons-io:2.4:commons-io-2.4.jar:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581',
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
'info.picocli:picocli:4.5.2:picocli-4.5.2.jar:b4395e9a67932616efd2245d984bf5fcd453c2c5049558c3ce959ac2af4d3fac',
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'jline:jline:2.14.6:jline-2.14.6.jar:97d1acaac82409be42e622d7a54d3ae9d08517e8aefdea3d2ba9791150c2f02d',
'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.apache.ant:ant-antlr:1.10.9:ant-antlr-1.10.9.jar:7623dc9d0f20ea713290c6bf1a23f4c059447aef7ff9f5b2be75960f3f028d2e',
'org.apache.ant:ant-junit:1.10.9:ant-junit-1.10.9.jar:960bdc8827954d62206ba42d0a68a7ee4476175ba47bb113e17e77cce7394630',
'org.apache.ant:ant-launcher:1.10.9:ant-launcher-1.10.9.jar:fcce891f57f3be72149ff96ac2a80574165b3e0839866b95d24528f3027d50c1',
'org.apache.ant:ant:1.10.9:ant-1.10.9.jar:0715478af585ea80a18985613ebecdc7922122d45b2c3c970ff9b352cddb75fc',
'org.apache.commons:commons-compress:1.20:commons-compress-1.20.jar:0aeb625c948c697ea7b205156e112363b59ed5e2551212cd4e460bdb72c7c06e',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7',
'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd',
'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e',
'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.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82',
'org.briarproject:tor-android:0.3.5.17:tor-android-0.3.5.17.jar:1888afc10a26b93d00a010ea27bf0b1b162a6d524688b08b98d70d14dc363b54',
'org.briarproject:tor-android:0.3.5.15:tor-android-0.3.5.15.jar:560c5070166300b396cb2f28d82d9f639ee1fb5479096a3cef67da56d39937ad',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.checkerframework:checker-qual:3.5.0:checker-qual-3.5.0.jar:729990b3f18a95606fc2573836b6958bcdb44cb52bfbd1b7aa9c339cff35a5a4',
'org.codehaus.groovy:groovy-ant:3.0.7:groovy-ant-3.0.7.jar:6ed2ba82813d128f7050c24142e87b3dc2ad8b504786280eb03e81f0cf6a5793',
'org.codehaus.groovy:groovy-astbuilder:3.0.7:groovy-astbuilder-3.0.7.jar:b290451eb1583666e906c41f7d14747b4cc96363c99c478b244634fd5dfc9013',
'org.codehaus.groovy:groovy-cli-picocli:3.0.7:groovy-cli-picocli-3.0.7.jar:71b4bd11fb30a9c7b5618e22122c9c5141958fb27f4dcf0068b6f715088f6916',
'org.codehaus.groovy:groovy-console:3.0.7:groovy-console-3.0.7.jar:0541b358b6b8e5363215026736168fccfec1d91bac678d066fa77349eeeaa5dd',
'org.codehaus.groovy:groovy-datetime:3.0.7:groovy-datetime-3.0.7.jar:b9823d14b1a4f94236ae2f8a471701aab17e093e1b33402b91550b5c8dd88f04',
'org.codehaus.groovy:groovy-docgenerator:3.0.7:groovy-docgenerator-3.0.7.jar:bf53f7a11c9eb1e278e1b8ed2714c741bcf781235c803ad3ba1555f2614573f3',
'org.codehaus.groovy:groovy-groovydoc:3.0.7:groovy-groovydoc-3.0.7.jar:86b24dfc23c005066ab83927cdb54177f06c9531773f2e2d2ecc9a131f7c2677',
'org.codehaus.groovy:groovy-groovysh:3.0.7:groovy-groovysh-3.0.7.jar:5c40e78cbc09726aedd1c75fab112d245d665d6294870f9119e6cd3013ed14ab',
'org.codehaus.groovy:groovy-jmx:3.0.7:groovy-jmx-3.0.7.jar:0a89f3007884eb156751937d93382038b83d39c7c2f0ab156ebf251a7251f2ab',
'org.codehaus.groovy:groovy-json:3.0.7:groovy-json-3.0.7.jar:df1f0ee475e3fc93a6a0d17548294e160cca5de6d9d36817a7be1fbe650de03b',
'org.codehaus.groovy:groovy-jsr223:3.0.7:groovy-jsr223-3.0.7.jar:1dbd969595332416193baa660fbb45743d19696eaa25fe98e591a2739e13517e',
'org.codehaus.groovy:groovy-macro:3.0.7:groovy-macro-3.0.7.jar:c6cc06df526b39e2c359e2435f0071594c5a1c7babafaa6c184fdd8fa931531f',
'org.codehaus.groovy:groovy-nio:3.0.7:groovy-nio-3.0.7.jar:db54c577882b294cd8c975ec5451596441baf54781319c61627dca0e0c2361ef',
'org.codehaus.groovy:groovy-servlet:3.0.7:groovy-servlet-3.0.7.jar:5b6a909bf501c209adfb6205b9e740649609074455fd979bf9da4853e6ff9a39',
'org.codehaus.groovy:groovy-sql:3.0.7:groovy-sql-3.0.7.jar:252bb6c74e1a9f41756ad4fbd3b0d2eddc93bb61109961dd1952a37bf2d57a64',
'org.codehaus.groovy:groovy-swing:3.0.7:groovy-swing-3.0.7.jar:bd942032d9328d54c6679c49a41f6caa0d4a0039ebe598493b8a647730d98cff',
'org.codehaus.groovy:groovy-templates:3.0.7:groovy-templates-3.0.7.jar:f119e07f650ef186ae5a4b944f9e30915b14311bad47c94a6b32de8d4f69bc80',
'org.codehaus.groovy:groovy-test-junit5:3.0.7:groovy-test-junit5-3.0.7.jar:c16eeea07b8e396891e266d7ba9388b24ac804237ffdd9a792b0d08969bad014',
'org.codehaus.groovy:groovy-test:3.0.7:groovy-test-3.0.7.jar:f71afd7c25d43017f89ea47e6de6daec971d159047dae083c1513a8422d44b90',
'org.codehaus.groovy:groovy-testng:3.0.7:groovy-testng-3.0.7.jar:713d5f2231bbb5712aefd362151b9ffd884aeb7ef2e773315cc54259cbdd063d',
'org.codehaus.groovy:groovy-xml:3.0.7:groovy-xml-3.0.7.jar:8a62e7c9ddece3e82676c4bef2f2c100f459602cd1fb6a14e94187bf863e97ff',
'org.codehaus.groovy:groovy:3.0.7:groovy-3.0.7.jar:51d1777e8dd1f00e60ea56e00d8a354ff5aab1f00fc8464ae8d39d71867e401f',
'org.checkerframework:checker-qual:2.8.1:checker-qual-2.8.1.jar:9103499008bcecd4e948da29b17864abb64304e15706444ae209d17ebe0575df',
'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d',
'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jacoco:org.jacoco.agent:0.8.3:org.jacoco.agent-0.8.3.jar:522deb254ee16a04cc8341cc8f335f5cb7232982994d961b9cf3a0454709209f',
'org.jacoco:org.jacoco.ant:0.8.3:org.jacoco.ant-0.8.3.jar:735844e1ae15f9b875b42a27ac5cb61cc26e106d9e839e5d1c6756709b424ce0',
'org.jacoco:org.jacoco.core:0.8.3:org.jacoco.core-0.8.3.jar:0818437bc060a0c7cc798148f22b713702aae2771aba104444407697d578f1ea',
'org.jacoco:org.jacoco.report:0.8.3:org.jacoco.report-0.8.3.jar:aae08fa4ff043c807b8876cdb2d8705eb8449a55efce461baa6c09da245088c1',
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
'org.jetbrains.kotlin:kotlin-reflect:1.4.32:kotlin-reflect-1.4.32.jar:dbf19e9cdaa9c3c170f3f6f6ce3922f38dfc1d7fa1cab5b7c23a19da8b5eec5b',
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32:kotlin-stdlib-common-1.4.32.jar:e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32:kotlin-stdlib-jdk7-1.4.32.jar:5f801e75ca27d8791c14b07943c608da27620d910a8093022af57f543d5d98b6',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32:kotlin-stdlib-jdk8-1.4.32.jar:adc43e54757b106e0cd7b3b7aa257dff471b61efdabe067fc02b2f57e2396262',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.32:kotlin-stdlib-1.4.32.jar:13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.junit.jupiter:junit-jupiter-api:5.7.0:junit-jupiter-api-5.7.0.jar:b03f78e0daeed2d77a0af9bcd662b4cdb9693f7ee72e01a539b508b84c63d182',
'org.junit.jupiter:junit-jupiter-engine:5.7.0:junit-jupiter-engine-5.7.0.jar:dfa26af94644ac2612dde6625852fcb550a0d21caa243257de54cba738ba87af',
'org.junit.platform:junit-platform-commons:1.7.0:junit-platform-commons-1.7.0.jar:5330ee87cc7586e6e25175a34e9251624ff12ff525269d3415d0b4ca519b6fea',
'org.junit.platform:junit-platform-engine:1.7.0:junit-platform-engine-1.7.0.jar:75f21a20dc594afdc875736725b408cec6d0344874d29f34b2dd3075500236f2',
'org.junit.platform:junit-platform-launcher:1.7.0:junit-platform-launcher-1.7.0.jar:fbdc748fde4c4279fe1d3c607447cb3b7ccd45d7338fc574f8a894ddf2d16818',
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.opentest4j:opentest4j:1.2.0:opentest4j-1.2.0.jar:58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2',
'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c',
'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.testng:testng:7.3.0:testng-7.3.0.jar:63727488f9717d57f0d0a0fee5a1fc10a2be9cfcff2ec3a7187656d663c0774e',
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
]
}

View File

@@ -11,5 +11,9 @@ public interface FeatureFlags {
boolean shouldEnableDisappearingMessages();
boolean shouldEnablePersistentLogs();
boolean shouldEnableConnectViaBluetooth();
boolean shouldEnableTransferData();
boolean shouldEnableShareAppViaOfflineHotspot();
}

View File

@@ -1,16 +1,8 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Hashtable;
import java.util.Map;
import javax.annotation.Nullable;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@NotNullByDefault
public abstract class StringMap extends Hashtable<String, String> {
protected StringMap(Map<String, String> m) {
@@ -60,19 +52,4 @@ public abstract class StringMap extends Hashtable<String, String> {
public void putLong(String key, long value) {
put(key, String.valueOf(value));
}
@Nullable
public byte[] getBytes(String key) {
String s = get(key);
if (s == null) return null;
try {
return fromHexString(s);
} catch (IllegalArgumentException e) {
return null;
}
}
public void putBytes(String key, byte[] value) {
put(key, toHexString(value));
}
}

View File

@@ -128,7 +128,7 @@ public interface ClientHelper {
* group.
*/
ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException;
throws DbException, FormatException;
/**
* Stores the given contact ID in the group metadata of the given contact

View File

@@ -170,11 +170,4 @@ public interface CryptoComponent {
* length. The line terminator is CRLF.
*/
String asciiArmour(byte[] b, int lineLength);
/**
* Encode the onion/hidden service address given its public key. As
* specified here: https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt?id=29245fd5#n2135
*/
String encodeOnionAddress(byte[] publicKey);
}

View File

@@ -1,46 +0,0 @@
package org.briarproject.bramble.api.logging;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.logging.Handler;
import java.util.logging.Logger;
@NotNullByDefault
public interface PersistentLogManager {
/**
* The namespace of the (@link Settings) where the log key is stored.
*/
String LOG_SETTINGS_NAMESPACE = "log";
/**
* The {@link Settings} key under which the log key is stored.
*/
String LOG_KEY_KEY = "logKey";
/**
* Creates and returns a persistent log handler that stores its logs in
* the given directory.
*/
Handler createLogHandler(File dir) throws IOException;
/**
* Creates a persistent log handler that stores its logs in the given
* directory and adds the handler to the given logger, replacing any
* existing persistent log handler.
*/
void addLogHandler(File dir, Logger logger) throws IOException;
/**
* Returns a {@link Scanner} for reading the persistent log entries stored
* in the given directory.
*
* @param old True if the previous session's log should be loaded, or false
* if the current session's log should be loaded
*/
Scanner getPersistentLog(File dir, boolean old) throws IOException;
}

View File

@@ -1,32 +0,0 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class MailboxProperties {
private final String onionAddress, authToken;
private final boolean owner;
public MailboxProperties(String onionAddress, String authToken,
boolean owner) {
this.onionAddress = onionAddress;
this.authToken = authToken;
this.owner = owner;
}
public String getOnionAddress() {
return onionAddress;
}
public String getAuthToken() {
return authToken;
}
public boolean isOwner() {
return owner;
}
}

View File

@@ -1,26 +0,0 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface MailboxSettingsManager {
@Nullable
MailboxProperties getOwnMailboxProperties(Transaction txn)
throws DbException;
void setOwnMailboxProperties(Transaction txn, MailboxProperties p)
throws DbException;
MailboxStatus getOwnMailboxStatus(Transaction txn) throws DbException;
void recordSuccessfulConnection(Transaction txn, long now)
throws DbException;
void recordFailedConnectionAttempt(Transaction txn, long now)
throws DbException;
}

View File

@@ -1,59 +0,0 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class MailboxStatus {
private final long lastAttempt, lastSuccess;
private final int attemptsSinceSuccess;
public MailboxStatus(long lastAttempt, long lastSuccess,
int attemptsSinceSuccess) {
this.lastAttempt = lastAttempt;
this.lastSuccess = lastSuccess;
this.attemptsSinceSuccess = attemptsSinceSuccess;
}
/**
* Returns the time of the last attempt to connect to the mailbox, in
* milliseconds since the Unix epoch, or -1 if no attempt has been made.
* <p>
* If an attempt is in progress and has not yet succeeded or failed then
* this method returns the time of the previous attempt, or -1 if the
* current attempt is the first.
*/
public long getTimeOfLastAttempt() {
return lastAttempt;
}
/**
* Returns the time of the last successful attempt to connect to the
* mailbox, in milliseconds since the Unix epoch, or -1 if no attempt has
* succeeded.
* <p>
* If the last attempt was successful then this method returns the same
* value as {@link #getTimeOfLastAttempt()}. If an attempt is in progress
* and has not yet succeeded or failed then this method returns the time
* of the previous successful connection, or -1 if no attempt has
* succeeded.
*/
public long getTimeOfLastSuccess() {
return lastSuccess;
}
/**
* Returns the number of attempts to connect to the mailbox that have
* failed since the last attempt succeeded, or the number of attempts that
* have been made, if no attempt has ever succeeded.
* <p>
* If an attempt is in progress and has not yet succeeded or failed then
* it is not included in this count.
*/
public int getAttemptsSinceSuccess() {
return attemptsSinceSuccess;
}
}

View File

@@ -1,14 +1,17 @@
package org.briarproject.bramble.api.plugin;
import static java.util.concurrent.TimeUnit.DAYS;
public interface TorConstants {
TransportId ID = new TransportId("org.briarproject.bramble.tor");
// Transport properties
String PROP_ONION_V2 = "onion";
String PROP_ONION_V3 = "onion3";
int DEFAULT_SOCKS_PORT = 59050;
int DEFAULT_CONTROL_PORT = 59051;
int SOCKS_PORT = 59050;
int CONTROL_PORT = 59051;
int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds
int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds
@@ -18,7 +21,14 @@ public interface TorConstants {
String PREF_TOR_PORT = "port";
String PREF_TOR_MOBILE = "useMobileData";
String PREF_TOR_ONLY_WHEN_CHARGING = "onlyWhenCharging";
String HS_PRIVATE_KEY_V2 = "onionPrivKey";
String HS_PRIVATE_KEY_V3 = "onionPrivKey3";
String HS_V3_CREATED = "onionPrivKey3Created";
/**
* How long to publish a v3 hidden service before retiring the v2 service.
*/
long V3_MIGRATION_PERIOD_MS = DAYS.toMillis(180);
// Values for PREF_TOR_NETWORK
int PREF_TOR_NETWORK_AUTOMATIC = 0;

View File

@@ -1,20 +0,0 @@
package org.briarproject.bramble.api.plugin;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the control port for the Tor plugin.
*/
@Qualifier
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface TorControlPort {
}

View File

@@ -1,20 +0,0 @@
package org.briarproject.bramble.api.plugin;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the socks port for the Tor plugin.
*/
@Qualifier
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface TorSocksPort {
}

View File

@@ -8,24 +8,11 @@ import java.io.File;
@NotNullByDefault
public interface DevConfig {
/**
* Returns the public key for encrypting feedback and crash reports.
*/
PublicKey getDevPublicKey();
/**
* Returns the onion address for submitting feedback and crash reports.
*/
String getDevOnionAddress();
/**
* Returns the directory for storing unsent feedback and crash reports.
*/
File getReportDir();
/**
* Returns the temporary file for passing the encrypted app log from the
* main process to the crash reporter process.
*/
File getTemporaryLogFile();
File getLogcatFile();
}

View File

@@ -22,11 +22,4 @@ public interface SettingsManager {
* namespace.
*/
void mergeSettings(Settings s, String namespace) throws DbException;
/**
* Merges the given settings with any existing settings in the given
* namespace.
*/
void mergeSettings(Transaction txn, Settings s, String namespace)
throws DbException;
}

View File

@@ -1,10 +1,7 @@
package org.briarproject.bramble.util;
import java.io.File;
import java.util.Collection;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
@@ -60,13 +57,4 @@ public class LogUtils {
String type) {
logger.log(level, type + " " + f.getAbsolutePath() + " " + f.length());
}
public static String formatLog(Formatter formatter,
Collection<LogRecord> logRecords) {
StringBuilder sb = new StringBuilder();
for (LogRecord record : logRecords) {
sb.append(formatter.format(record)).append('\n');
}
return sb.toString();
}
}

View File

@@ -1,17 +1,12 @@
package org.briarproject.bramble.test;
import org.jmock.Mockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.junit.After;
public abstract class BrambleMockTestCase extends BrambleTestCase {
protected final Mockery context = new Mockery();
public BrambleMockTestCase() {
context.setThreadingPolicy(new Synchroniser());
}
@After
public void checkExpectations() {
context.assertIsSatisfied();

View File

@@ -14,8 +14,6 @@ import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.io.IoModule;
import org.briarproject.bramble.keyagreement.KeyAgreementModule;
import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.logging.LoggingModule;
import org.briarproject.bramble.mailbox.MailboxModule;
import org.briarproject.bramble.plugin.PluginModule;
import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.record.RecordModule;
@@ -45,8 +43,6 @@ import dagger.Module;
IoModule.class,
KeyAgreementModule.class,
LifecycleModule.class,
LoggingModule.class,
MailboxModule.class,
PluginModule.class,
PropertiesModule.class,
RecordModule.class,

View File

@@ -7,7 +7,6 @@ import net.i2p.crypto.eddsa.KeyPairGenerator;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.briarproject.bramble.api.crypto.AgreementPrivateKey;
import org.briarproject.bramble.api.crypto.AgreementPublicKey;
import org.briarproject.bramble.api.crypto.CryptoComponent;
@@ -22,13 +21,11 @@ import org.briarproject.bramble.api.crypto.SignaturePrivateKey;
import org.briarproject.bramble.api.crypto.SignaturePublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.Base32;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
@@ -61,8 +58,6 @@ class CryptoComponentImpl implements CryptoComponent {
private static final int PBKDF_SALT_BYTES = 32; // 256 bits
private static final byte PBKDF_FORMAT_SCRYPT = 0;
private static final byte PBKDF_FORMAT_SCRYPT_STRENGTHENED = 1;
private static final byte ONION_HS_PROTOCOL_VERSION = 3;
private static final int ONION_CHECKSUM_BYTES = 2;
private final SecureRandom secureRandom;
private final PasswordBasedKdf passwordBasedKdf;
@@ -447,21 +442,4 @@ class CryptoComponentImpl implements CryptoComponent {
public String asciiArmour(byte[] b, int lineLength) {
return AsciiArmour.wrap(b, lineLength);
}
@Override
public String encodeOnionAddress(byte[] publicKey) {
Digest digest = new SHA3Digest(256);
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
digest.update(label, 0, label.length);
digest.update(publicKey, 0, publicKey.length);
digest.update(ONION_HS_PROTOCOL_VERSION);
byte[] checksum = new byte[digest.getDigestSize()];
digest.doFinal(checksum, 0);
byte[] address = new byte[publicKey.length + ONION_CHECKSUM_BYTES + 1];
arraycopy(publicKey, 0, address, 0, publicKey.length);
arraycopy(checksum, 0, address, publicKey.length, ONION_CHECKSUM_BYTES);
address[address.length - 1] = ONION_HS_PROTOCOL_VERSION;
return Base32.encode(address).toLowerCase();
}
}

View File

@@ -1,44 +0,0 @@
package org.briarproject.bramble.logging;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.system.TaskScheduler;
import java.io.OutputStream;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
class FlushingStreamHandler extends StreamHandler {
private static final int FLUSH_DELAY_MS = 5_000;
private final TaskScheduler scheduler;
private final Executor ioExecutor;
private final AtomicBoolean flushScheduled = new AtomicBoolean(false);
FlushingStreamHandler(TaskScheduler scheduler,
Executor ioExecutor, OutputStream out, Formatter formatter) {
super(out, formatter);
this.scheduler = scheduler;
this.ioExecutor = ioExecutor;
}
@Override
public void publish(LogRecord record) {
super.publish(record);
if (!flushScheduled.getAndSet(true)) {
scheduler.schedule(this::scheduledFlush, ioExecutor,
FLUSH_DELAY_MS, MILLISECONDS);
}
}
@IoExecutor
private void scheduledFlush() {
flushScheduled.set(false);
flush();
}
}

View File

@@ -1,29 +0,0 @@
package org.briarproject.bramble.logging;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import java.util.logging.Formatter;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class LoggingModule {
@Provides
Formatter provideFormatter() {
return new BriefLogFormatter();
}
@Provides
@Singleton
PersistentLogManager providePersistentLogManager(
LifecycleManager lifecycleManager,
PersistentLogManagerImpl persistentLogManager) {
lifecycleManager.registerOpenDatabaseHook(persistentLogManager);
return persistentLogManager;
}
}

View File

@@ -1,176 +0,0 @@
package org.briarproject.bramble.logging;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.api.transport.StreamReaderFactory;
import org.briarproject.bramble.api.transport.StreamWriter;
import org.briarproject.bramble.api.transport.StreamWriterFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
class PersistentLogManagerImpl implements PersistentLogManager,
OpenDatabaseHook {
private static final Logger LOG =
getLogger(PersistentLogManagerImpl.class.getName());
private static final String LOG_FILE = "briar.log";
private static final String OLD_LOG_FILE = "briar.log.old";
private final TaskScheduler scheduler;
private final Executor ioExecutor;
private final ShutdownManager shutdownManager;
private final DatabaseComponent db;
private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory;
private final Formatter formatter;
private final SecretKey logKey;
private final AtomicReference<Integer> shutdownHookHandle =
new AtomicReference<>();
@Nullable
private volatile SecretKey oldLogKey = null;
@Inject
PersistentLogManagerImpl(
TaskScheduler scheduler,
@IoExecutor Executor ioExecutor,
ShutdownManager shutdownManager,
DatabaseComponent db,
StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory,
Formatter formatter,
CryptoComponent crypto) {
this.scheduler = scheduler;
this.ioExecutor = ioExecutor;
this.shutdownManager = shutdownManager;
this.db = db;
this.streamReaderFactory = streamReaderFactory;
this.streamWriterFactory = streamWriterFactory;
this.formatter = formatter;
logKey = crypto.generateSecretKey();
}
@Override
public void onDatabaseOpened(Transaction txn) throws DbException {
Settings s = db.getSettings(txn, LOG_SETTINGS_NAMESPACE);
// Load the old log key, if any
byte[] oldKeyBytes = s.getBytes(LOG_KEY_KEY);
if (oldKeyBytes != null && oldKeyBytes.length == SecretKey.LENGTH) {
LOG.info("Loaded old log key");
oldLogKey = new SecretKey(oldKeyBytes);
}
// Store the current log key
s.putBytes(LOG_KEY_KEY, logKey.getBytes());
db.mergeSettings(txn, s, LOG_SETTINGS_NAMESPACE);
}
@Override
public Handler createLogHandler(File dir) throws IOException {
File logFile = new File(dir, LOG_FILE);
File oldLogFile = new File(dir, OLD_LOG_FILE);
if (oldLogFile.exists() && !oldLogFile.delete())
LOG.warning("Failed to delete old log file");
if (logFile.exists() && !logFile.renameTo(oldLogFile))
LOG.warning("Failed to rename log file");
try {
OutputStream out = new FileOutputStream(logFile);
StreamWriter writer =
streamWriterFactory.createLogStreamWriter(out, logKey);
StreamHandler handler = new FlushingStreamHandler(scheduler,
ioExecutor, writer.getOutputStream(), formatter);
// Flush the log and terminate the stream at shutdown
Runnable shutdownHook = () -> {
LOG.info("Shutting down");
handler.flush();
try {
writer.sendEndOfStream();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
};
int handle = shutdownManager.addShutdownHook(shutdownHook);
// If a previous handler registered a shutdown hook, remove it
Integer oldHandle = shutdownHookHandle.getAndSet(handle);
if (oldHandle != null) {
shutdownManager.removeShutdownHook(oldHandle);
}
return handler;
} catch (SecurityException e) {
throw new IOException(e);
}
}
@Override
public void addLogHandler(File dir, Logger logger) throws IOException {
for (Handler h : logger.getHandlers()) {
if (h instanceof FlushingStreamHandler) logger.removeHandler(h);
}
logger.addHandler(createLogHandler(dir));
}
@Override
public Scanner getPersistentLog(File dir, boolean old)
throws IOException {
if (old) {
SecretKey oldLogKey = this.oldLogKey;
if (oldLogKey == null) {
LOG.info("Old log key has not been loaded");
return emptyScanner();
}
return getPersistentLog(new File(dir, OLD_LOG_FILE), oldLogKey);
} else {
return getPersistentLog(new File(dir, LOG_FILE), logKey);
}
}
private Scanner getPersistentLog(File logFile, SecretKey key)
throws IOException {
if (logFile.exists()) {
LOG.info("Reading log file");
InputStream in = new FileInputStream(logFile);
return new Scanner(streamReaderFactory.createLogStreamReader(in,
key));
} else {
LOG.info("Log file does not exist");
return emptyScanner();
}
}
private Scanner emptyScanner() {
return new Scanner(new ByteArrayInputStream(new byte[0]));
}
}

View File

@@ -1,16 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import dagger.Module;
import dagger.Provides;
@Module
public class MailboxModule {
@Provides
MailboxSettingsManager provideMailboxSettingsManager(
MailboxSettingsManagerImpl mailboxSettingsManager) {
return mailboxSettingsManager;
}
}

View File

@@ -1,86 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@Immutable
@NotNullByDefault
class MailboxSettingsManagerImpl implements MailboxSettingsManager {
// Package access for testing
static final String SETTINGS_NAMESPACE = "mailbox";
static final String SETTINGS_KEY_ONION = "onion";
static final String SETTINGS_KEY_TOKEN = "token";
static final String SETTINGS_KEY_LAST_ATTEMPT = "lastAttempt";
static final String SETTINGS_KEY_LAST_SUCCESS = "lastSuccess";
static final String SETTINGS_KEY_ATTEMPTS = "attempts";
private final SettingsManager settingsManager;
@Inject
MailboxSettingsManagerImpl(SettingsManager settingsManager) {
this.settingsManager = settingsManager;
}
@Override
public MailboxProperties getOwnMailboxProperties(Transaction txn)
throws DbException {
Settings s = settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
String onion = s.get(SETTINGS_KEY_ONION);
String token = s.get(SETTINGS_KEY_TOKEN);
if (isNullOrEmpty(onion) || isNullOrEmpty(token)) return null;
return new MailboxProperties(onion, token, true);
}
@Override
public void setOwnMailboxProperties(Transaction txn, MailboxProperties p)
throws DbException {
Settings s = new Settings();
s.put(SETTINGS_KEY_ONION, p.getOnionAddress());
s.put(SETTINGS_KEY_TOKEN, p.getAuthToken());
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
}
@Override
public MailboxStatus getOwnMailboxStatus(Transaction txn)
throws DbException {
Settings s = settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
long lastAttempt = s.getLong(SETTINGS_KEY_LAST_ATTEMPT, -1);
long lastSuccess = s.getLong(SETTINGS_KEY_LAST_SUCCESS, -1);
int attempts = s.getInt(SETTINGS_KEY_ATTEMPTS, 0);
return new MailboxStatus(lastAttempt, lastSuccess, attempts);
}
@Override
public void recordSuccessfulConnection(Transaction txn, long now)
throws DbException {
Settings s = new Settings();
s.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
s.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
s.putInt(SETTINGS_KEY_ATTEMPTS, 0);
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
}
@Override
public void recordFailedConnectionAttempt(Transaction txn, long now)
throws DbException {
Settings oldSettings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
int attempts = oldSettings.getInt(SETTINGS_KEY_ATTEMPTS, 0);
Settings newSettings = new Settings();
newSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
newSettings.putInt(SETTINGS_KEY_ATTEMPTS, attempts + 1);
settingsManager.mergeSettings(txn, newSettings, SETTINGS_NAMESPACE);
}
}

View File

@@ -34,7 +34,6 @@ import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
@@ -45,7 +44,6 @@ import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -70,16 +68,20 @@ import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_PLUGIN_ENABLE;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_MOBILE;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_NETWORK;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_ONLY_WHEN_CHARGING;
import static org.briarproject.bramble.api.plugin.TorConstants.HS_PRIVATE_KEY_V2;
import static org.briarproject.bramble.api.plugin.TorConstants.HS_PRIVATE_KEY_V3;
import static org.briarproject.bramble.api.plugin.TorConstants.HS_V3_CREATED;
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
@@ -88,10 +90,12 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
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.api.plugin.TorConstants.REASON_BATTERY;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
import static org.briarproject.bramble.api.plugin.TorConstants.V3_MIGRATION_PERIOD_MS;
import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
import static org.briarproject.bramble.util.IoUtils.copyAndClose;
import static org.briarproject.bramble.util.IoUtils.tryToClose;
@@ -111,6 +115,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final String OWNER = "__OwningControllerProcess";
private static final int COOKIE_TIMEOUT_MS = 3000;
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
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, wakefulIoExecutor;
@@ -127,11 +132,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final CircumventionProvider circumventionProvider;
private final ResourceProvider resourceProvider;
private final long maxLatency;
private final int maxIdleTime;
private final int socketTimeout;
private final int maxIdleTime, socketTimeout;
private final File torDirectory, geoIpFile, configFile;
private final int torSocksPort;
private final int torControlPort;
private final File doneFile, cookieFile;
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -160,9 +162,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
String architecture,
long maxLatency,
int maxIdleTime,
File torDirectory,
int torSocksPort,
int torControlPort) {
File torDirectory) {
this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor;
this.networkManager = networkManager;
@@ -182,8 +182,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
socketTimeout = Integer.MAX_VALUE;
else socketTimeout = maxIdleTime * 2;
this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort;
geoIpFile = new File(torDirectory, "geoip");
configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done");
@@ -279,7 +277,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
throw new PluginException();
}
//noinspection BusyWait
Thread.sleep(COOKIE_POLLING_INTERVAL_MS);
}
LOG.info("Auth cookie created");
@@ -290,7 +287,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
try {
// Open a control connection and authenticate using the cookie file
controlSocket = new Socket("127.0.0.1", torControlPort);
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed
@@ -393,24 +390,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return zin;
}
private static void append(StringBuilder strb, String name, int value) {
strb.append(name);
strb.append(" ");
strb.append(value);
strb.append("\n");
}
private InputStream getConfigInputStream() {
StringBuilder strb = new StringBuilder();
append(strb, "ControlPort", torControlPort);
append(strb, "CookieAuthentication", 1);
append(strb, "DisableNetwork", 1);
append(strb, "RunAsDaemon", 1);
append(strb, "SafeSocks", 1);
append(strb, "SocksPort", torSocksPort);
//noinspection CharsetObjectCanBeUsed
return new ByteArrayInputStream(
strb.toString().getBytes(Charset.forName("UTF-8")));
ClassLoader cl = getClass().getClassLoader();
return requireNonNull(cl.getResourceAsStream("torrc"));
}
private void listFiles(File f) {
@@ -475,10 +457,54 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void publishHiddenService(String port) {
if (!state.isTorRunning()) return;
// TODO: Remove support for v2 hidden services after a reasonable
// migration period (migration started 2020-06-30)
String privKey2 = settings.get(HS_PRIVATE_KEY_V2);
String privKey3 = settings.get(HS_PRIVATE_KEY_V3);
String v3Created = settings.get(HS_V3_CREATED);
// Publish a v2 hidden service if we've already created one, and
// either we've never published a v3 hidden service or we're still
// in the migration period since first publishing it
if (!isNullOrEmpty(privKey2)) {
long now = clock.currentTimeMillis();
long then = v3Created == null ? now : Long.parseLong(v3Created);
if (now - then >= V3_MIGRATION_PERIOD_MS) retireV2HiddenService();
else publishV2HiddenService(port, privKey2);
}
publishV3HiddenService(port, privKey3);
}
private void publishV2HiddenService(String port, String privKey) {
LOG.info("Creating v2 hidden service");
Map<Integer, String> portLines = singletonMap(80, "127.0.0.1:" + port);
Map<String, String> response;
try {
response = controlConnection.addOnion(privKey, portLines);
} catch (IOException e) {
logException(LOG, WARNING, e);
return;
}
if (!response.containsKey(HS_ADDRESS)) {
LOG.warning("Tor did not return a hidden service address");
return;
}
String onion2 = response.get(HS_ADDRESS);
if (LOG.isLoggable(INFO)) {
LOG.info("V2 hidden service " + scrubOnion(onion2));
}
// The hostname has already been published and the private key stored
}
private void retireV2HiddenService() {
LOG.info("Retiring v2 hidden service");
TransportProperties p = new TransportProperties();
p.put(PROP_ONION_V2, "");
callback.mergeLocalProperties(p);
Settings s = new Settings();
s.put(HS_PRIVATE_KEY_V2, "");
callback.mergeSettings(s);
}
private void publishV3HiddenService(String port, @Nullable String privKey) {
LOG.info("Creating v3 hidden service");
Map<Integer, String> portLines = singletonMap(80, "127.0.0.1:" + port);
@@ -515,6 +541,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
// Save the hidden service's private key for next time
Settings s = new Settings();
s.put(HS_PRIVATE_KEY_V3, response.get(HS_PRIVKEY));
s.put(HS_V3_CREATED, String.valueOf(clock.currentTimeMillis()));
callback.mergeSettings(s);
}
}
@@ -621,30 +648,49 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public DuplexTransportConnection createConnection(TransportProperties p) {
if (getState() != ACTIVE) return null;
// TODO: Remove support for v2 hidden services after a reasonable
// migration period (migration started 2020-06-30)
String bestOnion = null, version = null;
String onion2 = p.get(PROP_ONION_V2);
String onion3 = p.get(PROP_ONION_V3);
if (onion3 != null && !ONION_V3.matcher(onion3).matches()) {
// Don't scrub the address so we can find the problem
if (LOG.isLoggable(INFO)) {
LOG.info("Invalid v3 hostname: " + onion3);
if (!isNullOrEmpty(onion2)) {
if (ONION_V2.matcher(onion2).matches()) {
bestOnion = onion2;
version = "v2";
} else {
// Don't scrub the address so we can find the problem
if (LOG.isLoggable(INFO))
LOG.info("Invalid v2 hostname: " + onion2);
}
onion3 = null;
}
if (onion3 == null) return null;
if (!isNullOrEmpty(onion3)) {
if (ONION_V3.matcher(onion3).matches()) {
bestOnion = onion3;
version = "v3";
} 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;
try {
if (LOG.isLoggable(INFO)) {
LOG.info("Connecting to v3 " + scrubOnion(onion3));
LOG.info("Connecting to " + version + " "
+ scrubOnion(bestOnion));
}
s = torSocketFactory.createSocket(onion3 + ".onion", 80);
s = torSocketFactory.createSocket(bestOnion + ".onion", 80);
s.setSoTimeout(socketTimeout);
if (LOG.isLoggable(INFO)) {
LOG.info("Connected to v3 " + scrubOnion(onion3));
LOG.info("Connected to " + version + " "
+ scrubOnion(bestOnion));
}
return new TorTransportConnection(this, s);
} catch (IOException e) {
if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to v3 "
+ scrubOnion(onion3) + ": " + e.toString());
LOG.info("Could not connect to " + version + " "
+ scrubOnion(bestOnion) + ": " + e.toString());
}
tryToClose(s, LOG, WARNING);
return null;
@@ -938,17 +984,17 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Nullable
private ServerSocket serverSocket = null;
private synchronized void setStarted() {
synchronized void setStarted() {
started = true;
callback.pluginStateChanged(getState());
}
private synchronized boolean isTorRunning() {
synchronized boolean isTorRunning() {
return started && !stopped;
}
@Nullable
private synchronized ServerSocket setStopped() {
synchronized ServerSocket setStopped() {
stopped = true;
ServerSocket ss = serverSocket;
serverSocket = null;
@@ -956,44 +1002,44 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return ss;
}
private synchronized void setBootstrapped() {
synchronized void setBootstrapped() {
bootstrapped = true;
callback.pluginStateChanged(getState());
}
private synchronized boolean getAndSetCircuitBuilt() {
synchronized boolean getAndSetCircuitBuilt() {
boolean firstCircuit = !circuitBuilt;
circuitBuilt = true;
callback.pluginStateChanged(getState());
return firstCircuit;
}
private synchronized void enableNetwork(boolean enable) {
synchronized void enableNetwork(boolean enable) {
networkInitialised = true;
networkEnabled = enable;
if (!enable) circuitBuilt = false;
callback.pluginStateChanged(getState());
}
private synchronized void setReasonsDisabled(int reasonsDisabled) {
synchronized void setReasonsDisabled(int reasonsDisabled) {
settingsChecked = true;
this.reasonsDisabled = reasonsDisabled;
callback.pluginStateChanged(getState());
}
// Doesn't affect getState()
private synchronized boolean setServerSocket(ServerSocket ss) {
synchronized boolean setServerSocket(ServerSocket ss) {
if (stopped || serverSocket != null) return false;
serverSocket = ss;
return true;
}
// Doesn't affect getState()
private synchronized void clearServerSocket(ServerSocket ss) {
synchronized void clearServerSocket(ServerSocket ss) {
if (serverSocket == ss) serverSocket = null;
}
private synchronized State getState() {
synchronized State getState() {
if (!started || stopped || !settingsChecked) {
return STARTING_STOPPING;
}
@@ -1003,7 +1049,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return bootstrapped && circuitBuilt ? ACTIVE : ENABLING;
}
private synchronized int getReasonsDisabled() {
synchronized int getReasonsDisabled() {
return getState() == DISABLED ? reasonsDisabled : 0;
}
}

View File

@@ -4,26 +4,39 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.util.encoders.Base64;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.util.Base32;
import java.nio.charset.Charset;
class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
import static java.lang.System.arraycopy;
public class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
private static final EdDSANamedCurveSpec CURVE_SPEC =
EdDSANamedCurveTable.getByName("Ed25519");
private final CryptoComponent crypto;
TorRendezvousCryptoImpl(CryptoComponent crypto) {
this.crypto = crypto;
}
private static final byte HS_PROTOCOL_VERSION = 3;
private static final int CHECKSUM_BYTES = 2;
@Override
public String getOnionAddress(byte[] seed) {
EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC);
return crypto.encodeOnionAddress(spec.getA().toByteArray());
byte[] publicKey = spec.getA().toByteArray();
Digest digest = new SHA3Digest(256);
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
digest.update(label, 0, label.length);
digest.update(publicKey, 0, publicKey.length);
digest.update(HS_PROTOCOL_VERSION);
byte[] checksum = new byte[digest.getDigestSize()];
digest.doFinal(checksum, 0);
byte[] address = new byte[publicKey.length + CHECKSUM_BYTES + 1];
arraycopy(publicKey, 0, address, 0, publicKey.length);
arraycopy(checksum, 0, address, publicKey.length, CHECKSUM_BYTES);
address[address.length - 1] = HS_PROTOCOL_VERSION;
return Base32.encode(address).toLowerCase();
}
@Override

View File

@@ -37,10 +37,4 @@ class SettingsManagerImpl implements SettingsManager {
public void mergeSettings(Settings s, String namespace) throws DbException {
db.transaction(false, txn -> db.mergeSettings(txn, s, namespace));
}
@Override
public void mergeSettings(Transaction txn, Settings s, String namespace)
throws DbException {
db.mergeSettings(txn, s, namespace);
}
}

View File

@@ -1,7 +1,5 @@
package org.briarproject.bramble.socks;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import java.net.InetSocketAddress;
import javax.net.SocketFactory;
@@ -11,14 +9,15 @@ import dagger.Provides;
import static org.briarproject.bramble.api.plugin.TorConstants.CONNECT_TO_PROXY_TIMEOUT;
import static org.briarproject.bramble.api.plugin.TorConstants.EXTRA_SOCKET_TIMEOUT;
import static org.briarproject.bramble.api.plugin.TorConstants.SOCKS_PORT;
@Module
public class SocksModule {
@Provides
SocketFactory provideTorSocketFactory(@TorSocksPort int torSocksPort) {
SocketFactory provideTorSocketFactory() {
InetSocketAddress proxy = new InetSocketAddress("127.0.0.1",
torSocksPort);
SOCKS_PORT);
return new SocksSocketFactory(proxy, CONNECT_TO_PROXY_TIMEOUT,
EXTRA_SOCKET_TIMEOUT);
}

View File

@@ -0,0 +1,6 @@
ControlPort 59051
CookieAuthentication 1
DisableNetwork 1
RunAsDaemon 1
SafeSocks 1
SocksPort 59050

View File

@@ -24,10 +24,11 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
@@ -52,8 +53,9 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class ClientHelperImplTest extends BrambleMockTestCase {
public class ClientHelperImplTest extends BrambleTestCase {
private final Mockery context = new Mockery();
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final MessageFactory messageFactory =
context.mock(MessageFactory.class);
@@ -98,6 +100,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}});
clientHelper.addLocalMessage(message, dictionary, shared);
context.assertIsSatisfied();
}
@Test
@@ -109,6 +112,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}});
clientHelper.createMessage(groupId, timestamp, list);
context.assertIsSatisfied();
}
@Test
@@ -123,6 +127,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}});
clientHelper.getMessageAsList(messageId);
context.assertIsSatisfied();
}
@Test
@@ -139,6 +144,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertEquals(dictionary,
clientHelper.getGroupMetadataAsDictionary(groupId));
context.assertIsSatisfied();
}
@Test
@@ -155,6 +161,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertEquals(dictionary,
clientHelper.getMessageMetadataAsDictionary(messageId));
context.assertIsSatisfied();
}
@Test
@@ -172,6 +179,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}});
assertEquals(map, clientHelper.getMessageMetadataAsDictionary(groupId));
context.assertIsSatisfied();
}
@Test
@@ -196,6 +204,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertEquals(map,
clientHelper.getMessageMetadataAsDictionary(groupId, query));
context.assertIsSatisfied();
}
@Test
@@ -210,6 +219,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}});
clientHelper.mergeGroupMetadata(groupId, dictionary);
context.assertIsSatisfied();
}
@Test
@@ -224,6 +234,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}});
clientHelper.mergeMessageMetadata(messageId, dictionary);
context.assertIsSatisfied();
}
@Test
@@ -231,6 +242,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
byte[] bytes = expectToByteArray(list);
assertArrayEquals(bytes, clientHelper.toByteArray(list));
context.assertIsSatisfied();
}
@Test
@@ -238,6 +250,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
expectToList(true);
assertEquals(list, clientHelper.toList(getRandomBytes(123)));
context.assertIsSatisfied();
}
@Test
@@ -249,6 +262,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
fail();
} catch (FormatException e) {
// expected
context.assertIsSatisfied();
}
}
@@ -265,6 +279,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertArrayEquals(signature,
clientHelper.sign(label, list, privateKey));
context.assertIsSatisfied();
}
@Test
@@ -280,6 +295,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}});
clientHelper.verifySignature(signature, label, list, publicKey);
context.assertIsSatisfied();
}
@Test
@@ -299,6 +315,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
fail();
} catch (GeneralSecurityException e) {
// expected
context.assertIsSatisfied();
}
}

View File

@@ -12,7 +12,6 @@ import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations;
import org.jmock.auto.Mock;
import org.jmock.integration.junit4.JUnitRuleMockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Rule;
import org.junit.Test;
@@ -36,7 +35,6 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
public JUnitRuleMockery context = new JUnitRuleMockery() {{
// So we can mock concrete classes like KeyAgreementTransport
setImposteriser(ClassImposteriser.INSTANCE);
setThreadingPolicy(new Synchroniser());
}};
private final PublicKey alicePubKey = getAgreementPublicKey();

View File

@@ -1,169 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.Test;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_ATTEMPTS;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_ATTEMPT;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_SUCCESS;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_ONION;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_TOKEN;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_NAMESPACE;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
private final SettingsManager settingsManager =
context.mock(SettingsManager.class);
private final MailboxSettingsManager manager =
new MailboxSettingsManagerImpl(settingsManager);
private final String onion = getRandomString(64);
private final String token = getRandomString(64);
private final long now = System.currentTimeMillis();
private final long lastAttempt = now - 1234;
private final long lastSuccess = now - 2345;
private final int attempts = 123;
@Test
public void testReturnsNullPropertiesIfSettingsAreEmpty() throws Exception {
Transaction txn = new Transaction(null, true);
Settings emptySettings = new Settings();
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(emptySettings));
}});
assertNull(manager.getOwnMailboxProperties(txn));
}
@Test
public void testReturnsProperties() throws Exception {
Transaction txn = new Transaction(null, true);
Settings settings = new Settings();
settings.put(SETTINGS_KEY_ONION, onion);
settings.put(SETTINGS_KEY_TOKEN, token);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(settings));
}});
MailboxProperties properties = manager.getOwnMailboxProperties(txn);
assertNotNull(properties);
assertEquals(onion, properties.getOnionAddress());
assertEquals(token, properties.getAuthToken());
assertTrue(properties.isOwner());
}
@Test
public void testStoresProperties() throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.put(SETTINGS_KEY_ONION, onion);
expectedSettings.put(SETTINGS_KEY_TOKEN, token);
MailboxProperties properties =
new MailboxProperties(onion, token, true);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.setOwnMailboxProperties(txn, properties);
}
@Test
public void testReturnsDefaultStatusIfSettingsAreEmpty() throws Exception {
Transaction txn = new Transaction(null, true);
Settings emptySettings = new Settings();
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(emptySettings));
}});
MailboxStatus status = manager.getOwnMailboxStatus(txn);
assertEquals(-1, status.getTimeOfLastAttempt());
assertEquals(-1, status.getTimeOfLastSuccess());
assertEquals(0, status.getAttemptsSinceSuccess());
}
@Test
public void testReturnsStatus() throws Exception {
Transaction txn = new Transaction(null, true);
Settings settings = new Settings();
settings.putLong(SETTINGS_KEY_LAST_ATTEMPT, lastAttempt);
settings.putLong(SETTINGS_KEY_LAST_SUCCESS, lastSuccess);
settings.putInt(SETTINGS_KEY_ATTEMPTS, attempts);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(settings));
}});
MailboxStatus status = manager.getOwnMailboxStatus(txn);
assertEquals(lastAttempt, status.getTimeOfLastAttempt());
assertEquals(lastSuccess, status.getTimeOfLastSuccess());
assertEquals(attempts, status.getAttemptsSinceSuccess());
}
@Test
public void testRecordsSuccess() throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
expectedSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, 0);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.recordSuccessfulConnection(txn, now);
}
@Test
public void testRecordsFailureOnFirstAttempt() throws Exception {
testRecordsFailure(new Settings(), 0);
}
@Test
public void testRecordsFailureOnLaterAttempt() throws Exception {
Settings oldSettings = new Settings();
oldSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, lastAttempt);
oldSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, lastSuccess);
oldSettings.putInt(SETTINGS_KEY_ATTEMPTS, attempts);
testRecordsFailure(oldSettings, attempts);
}
private void testRecordsFailure(Settings oldSettings, int oldAttempts)
throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, oldAttempts + 1);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(oldSettings));
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.recordFailedConnectionAttempt(txn, now);
}
}

View File

@@ -12,8 +12,10 @@ import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.junit.Test;
import java.util.Arrays;
@@ -22,10 +24,13 @@ import java.util.concurrent.Executors;
import static org.briarproject.bramble.test.TestUtils.getTransportId;
public class PluginManagerImplTest extends BrambleMockTestCase {
public class PluginManagerImplTest extends BrambleTestCase {
@Test
public void testStartAndStop() throws Exception {
Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser());
}};
Executor ioExecutor = Executors.newSingleThreadExecutor();
EventBus eventBus = context.mock(EventBus.class);
PluginConfig pluginConfig = context.mock(PluginConfig.class);
@@ -111,5 +116,7 @@ public class PluginManagerImplTest extends BrambleMockTestCase {
// Two plugins should be started and stopped
p.startService();
p.stopService();
context.assertIsSatisfied();
}
}

View File

@@ -26,7 +26,17 @@ public class TestFeatureFlagModule {
}
@Override
public boolean shouldEnablePersistentLogs() {
public boolean shouldEnableConnectViaBluetooth() {
return true;
}
@Override
public boolean shouldEnableTransferData() {
return true;
}
@Override
public boolean shouldEnableShareAppViaOfflineHotspot() {
return true;
}
};

View File

@@ -1,17 +1,19 @@
package org.briarproject.bramble.transport;
import org.briarproject.bramble.api.crypto.StreamDecrypter;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
import static org.junit.Assert.assertEquals;
public class StreamReaderImplTest extends BrambleMockTestCase {
public class StreamReaderImplTest extends BrambleTestCase {
@Test
public void testEmptyFramesAreSkipped() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -28,11 +30,13 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
assertEquals(0, r.read()); // Read another byte
assertEquals(-1, r.read()); // Skip the second empty frame, reach EOF
assertEquals(-1, r.read()); // Still at EOF
context.assertIsSatisfied();
r.close();
}
@Test
public void testEmptyFramesAreSkippedWithBuffer() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -52,11 +56,13 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
assertEquals(-1, r.read(buf));
// Still at EOF
assertEquals(-1, r.read(buf));
context.assertIsSatisfied();
r.close();
}
@Test
public void testMultipleReadsPerFrame() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -72,11 +78,13 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
assertEquals(MAX_PAYLOAD_LENGTH / 2, r.read(buf));
// Reach EOF
assertEquals(-1, r.read(buf, 0, buf.length));
context.assertIsSatisfied();
r.close();
}
@Test
public void testMultipleReadsPerFrameWithOffsets() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -94,6 +102,7 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
MAX_PAYLOAD_LENGTH / 2));
// Reach EOF
assertEquals(-1, r.read(buf, 0, buf.length));
context.assertIsSatisfied();
r.close();
}
}

View File

@@ -1,17 +1,19 @@
package org.briarproject.bramble.transport;
import org.briarproject.bramble.api.crypto.StreamEncrypter;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
import static org.junit.Assert.assertEquals;
public class StreamWriterImplTest extends BrambleMockTestCase {
public class StreamWriterImplTest extends BrambleTestCase {
@Test
public void testCloseWithoutWritingWritesFinalFrame() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
context.checking(new Expectations() {{
// Write an empty final frame
@@ -22,11 +24,13 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
}});
StreamWriterImpl w = new StreamWriterImpl(encrypter);
w.close();
context.assertIsSatisfied();
}
@Test
public void testFlushWithoutBufferedDataWritesFrameAndFlushes()
throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{
@@ -47,11 +51,13 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush();
}});
w.close();
context.assertIsSatisfied();
}
@Test
public void testFlushWithBufferedDataWritesFrameAndFlushes()
throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{
@@ -73,10 +79,12 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush();
}});
w.close();
context.assertIsSatisfied();
}
@Test
public void testSingleByteWritesWriteFullFrame() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{
@@ -95,10 +103,12 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush();
}});
w.close();
context.assertIsSatisfied();
}
@Test
public void testMultiByteWritesWriteFullFrames() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{
@@ -124,10 +134,12 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush();
}});
w.close();
context.assertIsSatisfied();
}
@Test
public void testLargeMultiByteWriteWritesFullFrames() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{
@@ -145,5 +157,6 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
w.write(b);
// There should be one byte left in the buffer
w.close();
context.assertIsSatisfied();
}
}

View File

@@ -17,8 +17,8 @@ dependencies {
def jna_version = '4.5.2'
implementation "net.java.dev.jna:jna:$jna_version"
implementation "net.java.dev.jna:jna-platform:$jna_version"
tor "org.briarproject:tor:$tor_version"
tor "org.briarproject:obfs4proxy:$obfs4proxy_version@zip"
tor 'org.briarproject:tor:0.3.5.15'
tor 'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a@zip'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"

View File

@@ -35,15 +35,12 @@ abstract class JavaTorPlugin extends TorPlugin {
String architecture,
long maxLatency,
int maxIdleTime,
File torDirectory,
int torSocksPort,
int torControlPort) {
File torDirectory) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory, torSocksPort,
torControlPort);
maxLatency, maxIdleTime, torDirectory);
}
@Override

View File

@@ -35,15 +35,12 @@ class UnixTorPlugin extends JavaTorPlugin {
String architecture,
long maxLatency,
int maxIdleTime,
File torDirectory,
int torSocksPort,
int torControlPort) {
File torDirectory) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory, torSocksPort,
torControlPort);
maxLatency, maxIdleTime, torDirectory);
}
@Override

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager;
@@ -10,9 +9,7 @@ import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
@@ -57,9 +54,6 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
private final BatteryManager batteryManager;
private final Clock clock;
private final File torDirectory;
private int torSocksPort;
private int torControlPort;
private final CryptoComponent crypto;
@Inject
UnixTorPluginFactory(@IoExecutor Executor ioExecutor,
@@ -73,10 +67,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
CircumventionProvider circumventionProvider,
BatteryManager batteryManager,
Clock clock,
@TorDirectory File torDirectory,
@TorSocksPort int torSocksPort,
@TorControlPort int torControlPort,
CryptoComponent crypto) {
@TorDirectory File torDirectory) {
this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor;
this.networkManager = networkManager;
@@ -89,9 +80,6 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
this.batteryManager = batteryManager;
this.clock = clock;
this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort;
this.crypto = crypto;
}
@Override
@@ -132,14 +120,12 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto =
new TorRendezvousCryptoImpl(crypto);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory, clock,
resourceProvider, circumventionProvider, batteryManager,
backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort,
torControlPort);
MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager;
@@ -37,8 +36,6 @@ import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_SOCKS_PORT;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
@@ -89,8 +86,6 @@ public class BridgeTest extends BrambleTestCase {
BackoffFactory backoffFactory;
@Inject
Clock clock;
@Inject
CryptoComponent crypto;
private final File torDir = getTestDirectory();
private final String bridge;
@@ -144,8 +139,7 @@ public class BridgeTest extends BrambleTestCase {
factory = new UnixTorPluginFactory(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, eventBus, torSocketFactory,
backoffFactory, resourceProvider, bridgeProvider,
batteryManager, clock, torDir, DEFAULT_SOCKS_PORT,
DEFAULT_CONTROL_PORT, crypto);
batteryManager, clock, torDir);
}
@After

View File

@@ -25,7 +25,7 @@ dependencyVerification {
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a:obfs4proxy-0.0.12-dev-40245c4a.zip:172029e7058b3a83ac93ac4991a44bf76e16ce8d46f558f5836d57da3cb3a766',
'org.briarproject:tor:0.3.5.17:tor-0.3.5.17.jar:ce0e1f4d8f14878e61b23a35a452bc0f2a8e3117ced5a74773cd78475fa7af39',
'org.briarproject:tor:0.3.5.15:tor-0.3.5.15.jar:2ff5b5a3b5eaa97d699629ad24ba9584b3199d0ffdb1ea7d8a02de3016b80e7a',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',

View File

@@ -1,28 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="500" height="175" viewBox="0 0 500 175"
id="svg2" version="1.1" sodipodi:docname="bluetooth.svg" inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="892"
id="namedview10"
showgrid="false"
inkscape:zoom="0.93337848"
inkscape:cx="-49.861215"
inkscape:cy="137.66042"
inkscape:window-x="0"
inkscape:window-y="144"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="499.24374"
height="175.49413"
viewBox="0 0 499.24373 175.49413"
id="svg2"
version="1.1">
<defs
id="defs4" />
<metadata
@@ -39,23 +26,22 @@
</metadata>
<path
id="path4201"
d="m 459.80937,167.15983 -4.32657,-4.3343 -7.06956,-2.42737 c -3.88825,-1.33505 -8.72285,-2.99587 -10.74354,-3.6907 l -3.674,-1.26333 3.524,-0.1726 c 8.24183,-0.40367 12.98778,-4.00671 14.33634,-10.88389 0.79628,-4.06078 1.12887,-17.29805 0.83016,-33.04122 -0.15338,-8.08375 -0.16617,-15.41641 -0.0284,-16.29481 0.13775,-0.8784 0.53527,-2.42011 0.88339,-3.42602 1.22247,-3.53243 0.33996,-11.90828 -1.8577,-17.63146 -0.34848,-0.9075 -1.93434,-4.215 -3.52415,-7.35 -4.15849,-8.2003 -4.50458,-8.94188 -4.89292,-10.4841 -0.45865,-1.82145 -0.21161,-5.43531 0.4625,-6.7659 0.66625,-1.31505 2.15695,-2.91616 3.24622,-3.48662 1.29885,-0.68024 2.61568,0.12202 4.6864,2.85512 3.42153,4.51599 14.00135,19.44095 15.73191,22.19301 3.74551,5.95636 5.95558,11.16496 7.9722,18.78849 0.6547,2.475 1.88525,6.9975 2.73456,10.05 0.84931,3.0525 2.71404,10.15792 4.14385,15.78983 l 2.59964,10.23983 4.65,5.19319 c 2.5575,2.85626 5.7975,6.46371 7.2,8.01657 1.4025,1.55286 2.55,2.97543 2.55,3.16127 0,0.33546 -34.49955,29.29931 -34.89913,29.29931 -0.11475,0 -2.15559,-1.95044 -4.5352,-4.3343 z M 365.9443,150.77206 c -1.25762,-0.62844 -2.20557,-1.3788 -2.91402,-2.30663 -2.08931,-2.73629 -1.95034,2.36868 -1.86433,-68.48249 l 0.0777,-64.03881 0.66066,-1.23494 c 1.0152,-1.89767 1.99201,-2.91087 3.73952,-3.87887 l 1.59982,-0.88619 37.78387,-0.0796 c 42.45592,-0.0894 39.40239,-0.2483 42.11646,2.19188 0.87544,0.78709 1.75715,1.95946 2.18393,2.90385 0.71264,1.57698 0.71613,1.63839 0.80561,14.20405 l 0.0899,12.62022 -1.79817,-0.13007 c -1.42577,-0.10313 -2.08143,0.007 -3.16601,0.5321 -2.01294,0.97445 -3.93993,2.89871 -5.11476,5.10753 l -1.03717,1.95 -0.007,-12.825 -0.007,-12.825 h -33.6 -33.6 v 51.3 51.3 h 33.59873 33.59874 l 0.0763,-34.425 c 0.073,-32.96021 0.0982,-34.36117 0.59098,-32.925 0.28309,0.825 1.80562,3.9975 3.3834,7.05 5.49252,10.62624 5.40494,9.86009 5.39597,47.20335 -0.007,27.62122 -0.12358,29.95084 -1.66204,33.10906 -1.07144,2.19949 -2.71143,3.71042 -5.05823,4.66019 l -1.67381,0.6774 -36.1677,0.0797 -36.16769,0.0797 -1.864,-0.93145 z m 42.39939,-5.03813 c 2.87119,-1.30885 4.45771,-3.6784 4.43003,-6.61652 -0.0388,-4.11587 -3.1088,-7.22328 -7.1364,-7.22328 -2.11956,0 -3.56727,0.60889 -5.16364,2.17177 -2.24518,2.19807 -2.75398,5.43897 -1.30101,8.28704 0.71312,1.39782 2.52137,3.00905 3.96214,3.53045 1.49707,0.54176 3.84003,0.47454 5.20888,-0.14946 z"
style="fill:#000000;stroke:none" />
d="m 459.80937,171.15983 -4.32657,-4.3343 -7.06956,-2.42737 c -3.88825,-1.33505 -8.72285,-2.99587 -10.74354,-3.6907 l -3.674,-1.26333 3.524,-0.1726 c 8.24183,-0.40367 12.98778,-4.00671 14.33634,-10.88389 0.79628,-4.06078 1.12887,-17.29805 0.83016,-33.04122 -0.15338,-8.08375 -0.16617,-15.41641 -0.0284,-16.29481 0.13775,-0.8784 0.53527,-2.42011 0.88339,-3.42602 1.22247,-3.53243 0.33996,-11.90828 -1.8577,-17.63146 -0.34848,-0.9075 -1.93434,-4.215 -3.52415,-7.35 -4.15849,-8.2003 -4.50458,-8.94188 -4.89292,-10.4841 -0.45865,-1.82145 -0.21161,-5.43531 0.4625,-6.7659 0.66625,-1.31505 2.15695,-2.91616 3.24622,-3.48662 1.29885,-0.68024 2.61568,0.12202 4.6864,2.85512 3.42153,4.51599 14.00135,19.44095 15.73191,22.19301 3.74551,5.95636 5.95558,11.16496 7.9722,18.78849 0.6547,2.475 1.88525,6.9975 2.73456,10.05 0.84931,3.0525 2.71404,10.15792 4.14385,15.78983 l 2.59964,10.23983 4.65,5.19319 c 2.5575,2.85626 5.7975,6.46371 7.2,8.01657 1.4025,1.55286 2.55,2.97543 2.55,3.16127 0,0.33546 -34.49955,29.29931 -34.89913,29.29931 -0.11475,0 -2.15559,-1.95044 -4.5352,-4.3343 z M 365.9443,154.77206 c -1.25762,-0.62844 -2.20557,-1.3788 -2.91402,-2.30663 -2.08931,-2.73629 -1.95034,2.36868 -1.86433,-68.48249 l 0.0777,-64.03881 0.66066,-1.23494 c 1.0152,-1.89767 1.99201,-2.91087 3.73952,-3.87887 l 1.59982,-0.88619 37.78387,-0.0796 c 42.45592,-0.0894 39.40239,-0.2483 42.11646,2.19188 0.87544,0.78709 1.75715,1.95946 2.18393,2.90385 0.71264,1.57698 0.71613,1.63839 0.80561,14.20405 l 0.0899,12.62022 -1.79817,-0.13007 c -1.42577,-0.10313 -2.08143,0.007 -3.16601,0.5321 -2.01294,0.97445 -3.93993,2.89871 -5.11476,5.10753 l -1.03717,1.95 -0.007,-12.825 -0.007,-12.825 -33.6,0 -33.6,0 0,51.3 0,51.3 33.59873,0 33.59874,0 0.0763,-34.425 c 0.073,-32.96021 0.0982,-34.36117 0.59098,-32.925 0.28309,0.825 1.80562,3.9975 3.3834,7.05 5.49252,10.62624 5.40494,9.86009 5.39597,47.20335 -0.007,27.62122 -0.12358,29.95084 -1.66204,33.10906 -1.07144,2.19949 -2.71143,3.71042 -5.05823,4.66019 l -1.67381,0.6774 -36.1677,0.0797 -36.16769,0.0797 -1.864,-0.93145 z m 42.39939,-5.03813 c 2.87119,-1.30885 4.45771,-3.6784 4.43003,-6.61652 -0.0388,-4.11587 -3.1088,-7.22328 -7.1364,-7.22328 -2.11956,0 -3.56727,0.60889 -5.16364,2.17177 -2.24518,2.19807 -2.75398,5.43897 -1.30101,8.28704 0.71312,1.39782 2.52137,3.00905 3.96214,3.53045 1.49707,0.54176 3.84003,0.47454 5.20888,-0.14946 z"
style="fill:#000000" />
<path
id="path4201-1"
d="m 39.434334,167.15983 4.32657,-4.3343 7.06956,-2.42737 c 3.88825,-1.33505 8.72285,-2.99587 10.74354,-3.6907 l 3.674,-1.26333 -3.524,-0.1726 c -8.24183,-0.40367 -12.98778,-4.00671 -14.33634,-10.88389 -0.79628,-4.06078 -1.12887,-17.29805 -0.83016,-33.04122 0.15338,-8.08375 0.16617,-15.41641 0.0284,-16.29481 -0.13775,-0.8784 -0.53527,-2.42011 -0.88339,-3.42602 -1.22247,-3.53243 -0.33996,-11.90828 1.8577,-17.63146 0.34848,-0.9075 1.93434,-4.215 3.52415,-7.35 4.15849,-8.2003 4.50458,-8.94188 4.89292,-10.4841 0.45865,-1.82145 0.21161,-5.43531 -0.4625,-6.7659 -0.66625,-1.31505 -2.15695,-2.91616 -3.24622,-3.48662 -1.29885,-0.68024 -2.61568,0.12202 -4.6864,2.85512 -3.42153,4.51599 -14.00135,19.44095 -15.73191,22.19301 -3.74551,5.95636 -5.955584,11.16496 -7.972204,18.78849 -0.6547,2.475 -1.88525,6.9975 -2.73456,10.05 -0.84931,3.0525 -2.71404,10.15792 -4.14385,15.78983 L 14.4,125.82379 9.75,131.01698 c -2.5575,2.85626 -5.7975,6.46371 -7.2,8.01657 -1.4025,1.55286 -2.55,2.97543 -2.55,3.16127 0,0.33546 34.499554,29.29931 34.899134,29.29931 0.11475,0 2.15559,-1.95044 4.53519,-4.3343 z m 93.865056,-16.38777 c 1.25762,-0.62844 2.20557,-1.3788 2.91402,-2.30663 2.08931,-2.73629 1.95034,2.36868 1.86433,-68.48249 l -0.0777,-64.03881 -0.66066,-1.23494 c -1.0152,-1.89767 -1.99201,-2.91087 -3.73952,-3.87887 L 132.00004,9.94413 94.216184,9.86453 c -42.45592,-0.0894 -39.40239,-0.2483 -42.11646,2.19188 -0.87544,0.78709 -1.75715,1.95946 -2.18393,2.90385 -0.71264,1.57698 -0.71613,1.63839 -0.80561,14.20405 l -0.0899,12.62022 1.79817,-0.13007 c 1.42577,-0.10313 2.08143,0.007 3.16601,0.5321 2.01294,0.97445 3.93993,2.89871 5.11476,5.10753 l 1.03717,1.95 0.007,-12.825 0.007,-12.825 h 33.6 33.599986 v 51.3 51.3 H 93.751664 60.152924 l -0.0763,-34.425 c -0.073,-32.96021 -0.0982,-34.36117 -0.59098,-32.925 -0.28309,0.825 -1.80562,3.9975 -3.3834,7.05 -5.49252,10.62624 -5.40494,9.86009 -5.39597,47.20335 0.007,27.62122 0.12358,29.95084 1.66204,33.10906 1.07144,2.19949 2.71143,3.71042 5.05823,4.66019 l 1.67381,0.6774 36.1677,0.0797 36.167676,0.0797 1.864,-0.93145 z m -42.399376,-5.03813 c -2.87119,-1.30885 -4.45771,-3.6784 -4.43003,-6.61652 0.0388,-4.11587 3.1088,-7.22328 7.1364,-7.22328 2.11956,0 3.56727,0.60889 5.16364,2.17177 2.245176,2.19807 2.753976,5.43897 1.301006,8.28704 -0.713116,1.39782 -2.521366,3.00905 -3.962136,3.53045 -1.49707,0.54176 -3.84003,0.47454 -5.20888,-0.14946 z"
style="fill:#000000;stroke:none" />
d="m 39.434334,171.15983 4.32657,-4.3343 7.06956,-2.42737 c 3.88825,-1.33505 8.72285,-2.99587 10.74354,-3.6907 l 3.674,-1.26333 -3.524,-0.1726 c -8.24183,-0.40367 -12.98778,-4.00671 -14.33634,-10.88389 -0.79628,-4.06078 -1.12887,-17.29805 -0.83016,-33.04122 0.15338,-8.08375 0.16617,-15.41641 0.0284,-16.29481 -0.13775,-0.8784 -0.53527,-2.42011 -0.88339,-3.42602 -1.22247,-3.53243 -0.33996,-11.90828 1.8577,-17.63146 0.34848,-0.9075 1.93434,-4.215 3.52415,-7.35 4.15849,-8.2003 4.50458,-8.94188 4.89292,-10.4841 0.45865,-1.82145 0.21161,-5.43531 -0.4625,-6.7659 -0.66625,-1.31505 -2.15695,-2.91616 -3.24622,-3.48662 -1.29885,-0.68024 -2.61568,0.12202 -4.6864,2.85512 -3.42153,4.51599 -14.00135,19.44095 -15.73191,22.19301 -3.74551,5.95636 -5.955584,11.16496 -7.972204,18.78849 -0.6547,2.475 -1.88525,6.9975 -2.73456,10.05 -0.84931,3.0525 -2.71404,10.15792 -4.14385,15.78983 L 14.4,129.82379 9.75,135.01698 c -2.5575,2.85626 -5.7975,6.46371 -7.2,8.01657 -1.4025,1.55286 -2.55,2.97543 -2.55,3.16127 0,0.33546 34.499554,29.29931 34.899134,29.29931 0.11475,0 2.15559,-1.95044 4.53519,-4.3343 z m 93.865056,-16.38777 c 1.25762,-0.62844 2.20557,-1.3788 2.91402,-2.30663 2.08931,-2.73629 1.95034,2.36868 1.86433,-68.48249 l -0.0777,-64.03881 -0.66066,-1.23494 c -1.0152,-1.89767 -1.99201,-2.91087 -3.73952,-3.87887 l -1.59982,-0.88619 -37.783856,-0.0796 c -42.45592,-0.0894 -39.40239,-0.2483 -42.11646,2.19188 -0.87544,0.78709 -1.75715,1.95946 -2.18393,2.90385 -0.71264,1.57698 -0.71613,1.63839 -0.80561,14.20405 l -0.0899,12.62022 1.79817,-0.13007 c 1.42577,-0.10313 2.08143,0.007 3.16601,0.5321 2.01294,0.97445 3.93993,2.89871 5.11476,5.10753 l 1.03717,1.95 0.007,-12.825 0.007,-12.825 33.6,0 33.599986,0 0,51.3 0,51.3 -33.598716,0 -33.59874,0 -0.0763,-34.425 c -0.073,-32.96021 -0.0982,-34.36117 -0.59098,-32.925 -0.28309,0.825 -1.80562,3.9975 -3.3834,7.05 -5.49252,10.62624 -5.40494,9.86009 -5.39597,47.20335 0.007,27.62122 0.12358,29.95084 1.66204,33.10906 1.07144,2.19949 2.71143,3.71042 5.05823,4.66019 l 1.67381,0.6774 36.1677,0.0797 36.167676,0.0797 1.864,-0.93145 z m -42.399376,-5.03813 c -2.87119,-1.30885 -4.45771,-3.6784 -4.43003,-6.61652 0.0388,-4.11587 3.1088,-7.22328 7.1364,-7.22328 2.11956,0 3.56727,0.60889 5.16364,2.17177 2.245176,2.19807 2.753976,5.43897 1.301006,8.28704 -0.713116,1.39782 -2.521366,3.00905 -3.962136,3.53045 -1.49707,0.54176 -3.84003,0.47454 -5.20888,-0.14946 z"
style="fill:#000000" />
<path
id="rect4270"
d="m 247.25369,71.97921 h 4.73637 c 13.16497,0 23.76348,10.598514 23.76348,23.763485 v 32.174615 c 0,13.16497 -10.59851,23.76348 -23.76348,23.76348 h -4.73637 c -13.16497,0 -23.76349,-10.59851 -23.76349,-23.76348 V 95.742695 c 0,-13.164971 10.59852,-23.763485 23.76349,-23.763485 z"
style="fill:#0a3d91;stroke:none" />
d="m 247.25369,75.97921 4.73637,0 c 13.16497,0 23.76348,10.598514 23.76348,23.763485 l 0,32.174615 c 0,13.16497 -10.59851,23.76348 -23.76348,23.76348 l -4.73637,0 c -13.16497,0 -23.76349,-10.59851 -23.76349,-23.76348 l 0,-32.174615 c 0,-13.164971 10.59852,-23.763485 23.76349,-23.763485 z"
style="fill:#0a3d91" />
<path
id="path4272"
d="m 236.31105,102.92749 24.90674,25.07007 -12.00423,14.53574 0,-51.936691 12.00423,13.882451 -24.90674,24.41678"
style="fill:none;stroke:#ffffff;stroke-width:4.32805729" />
<path
id="path4844"
d="m 143.67921,23.5571 c -1.59043,2.623831 0.18153,5.574737 2.78461,6.642714 2.69504,1.572445 6.1706,4.987176 9.14793,2.232151 2.23313,-2.039515 0.60129,-5.727894 -2.04109,-6.67035 -3.06433,-1.676733 -6.55172,-5.514807 -9.89145,-2.204515 z M 351.7046,23.12937 c -2.76779,1.960623 -7.06819,2.694997 -8.37782,6.042717 -0.64195,2.73095 1.93572,4.99255 4.58419,4.426453 3.2021,-1.637914 7.05658,-2.8424 9.17849,-5.94769 0.56931,-2.60435 -1.49324,-5.35066 -4.26769,-4.745697 -0.41558,-0.107679 -0.76003,0.03505 -1.11717,0.224217 z m -26.76172,13.17187 c -2.93431,1.708015 -7.32039,1.922759 -8.93076,5.153004 -0.90775,2.654328 1.43202,5.159236 4.12365,4.861044 3.35587,-1.304271 7.31954,-2.112696 9.73662,-5.002268 0.81368,-2.537666 -0.97658,-5.469583 -3.79644,-5.128908 -0.4035,-0.14574 -0.75969,-0.03824 -1.13307,0.117128 z m -155.23633,2.46289 c -1.21948,2.711869 0.75683,5.460507 3.4437,6.14538 2.85847,1.080772 6.66937,4.11785 9.31224,1.23392 2.3151,-2.03652 0.33929,-5.835383 -2.40983,-6.41823 -3.32833,-1.175814 -7.38479,-4.713633 -10.34611,-0.96107 z m 127.27344,7.61719 c -3.12289,1.309174 -7.49226,0.970678 -9.49244,3.970097 -1.23184,2.518748 0.7727,5.298264 3.48037,5.339749 3.48706,-0.907308 7.56742,-1.1128 10.30314,-3.739116 1.11397,-2.422222 -0.31199,-5.546068 -3.1516,-5.551016 -0.3827,-0.195662 -0.75023,-0.126964 -1.13947,-0.01971 z m -97.49023,1.54492 c -2.22858,1.461838 -2.68005,4.865948 -0.27553,6.376909 2.5869,1.470583 5.91459,1.954941 8.83971,2.495346 2.78485,0.332188 4.74603,-2.479173 3.89118,-5.048668 -2.04264,-3.279676 -6.47206,-2.73364 -9.71704,-4.089227 -0.91277,0.08855 -1.82555,0.177093 -2.73832,0.26564 z m 68.51367,4.50782 c -3.27623,0.788856 -7.46081,-0.187875 -9.93635,2.381992 -1.64972,2.268076 -0.15709,5.353662 2.50432,5.86185 3.61172,-0.292365 7.71764,0.09072 10.84009,-2.093962 1.46245,-2.227649 0.52336,-5.531725 -2.28478,-5.959415 -0.34949,-0.249225 -0.72211,-0.239347 -1.12328,-0.190465 z m -39.44922,1.41796 c -1.93309,1.83595 -1.76537,5.266611 0.87081,6.321491 2.80857,0.988807 6.17065,0.846733 9.1444,0.861366 2.79909,-0.172766 4.22635,-3.289835 2.92376,-5.664738 -2.60365,-2.851635 -6.84699,-1.541752 -10.29251,-2.269899 -0.88215,0.250593 -1.76431,0.501187 -2.64646,0.75178 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0a3d91;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.55;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:7.55, 22.65;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
d="m 252.50083,112.08988 11.6563,-11.45156 -17.12592,-19.790888 0.0193,25.792048 -9.14185,-9.24454 -3.12531,3.09064 11.5214,11.58063 -11.49773,11.30756 c 3.03061,3.05593 0,0 3.03061,3.05593 l 9.18921,-8.97308 c 0.0443,4.73517 0.004,27.16515 0.004,27.16515 l 17.10224,-20.77257 z m -1.07721,-19.570428 6.79869,7.863838 -6.79869,6.63278 z m -0.0237,40.027828 0.0237,-15.39623 6.89338,6.9879 z"
id="path1536"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.254891"
sodipodi:nodetypes="ccccccccccccccccccccc" />
d="m 143.67921,27.5571 c -1.59043,2.623831 0.18153,5.574737 2.78461,6.642714 2.69504,1.572445 6.1706,4.987176 9.14793,2.232151 2.23313,-2.039515 0.60129,-5.727894 -2.04109,-6.67035 -3.06433,-1.676733 -6.55172,-5.514807 -9.89145,-2.204515 z M 351.7046,27.12937 c -2.76779,1.960623 -7.06819,2.694997 -8.37782,6.042717 -0.64195,2.73095 1.93572,4.99255 4.58419,4.426453 3.2021,-1.637914 7.05658,-2.8424 9.17849,-5.94769 0.56931,-2.60435 -1.49324,-5.35066 -4.26769,-4.745697 -0.41558,-0.107679 -0.76003,0.03505 -1.11717,0.224217 z m -26.76172,13.17187 c -2.93431,1.708015 -7.32039,1.922759 -8.93076,5.153004 -0.90775,2.654328 1.43202,5.159236 4.12365,4.861044 3.35587,-1.304271 7.31954,-2.112696 9.73662,-5.002268 0.81368,-2.537666 -0.97658,-5.469583 -3.79644,-5.128908 -0.4035,-0.14574 -0.75969,-0.03824 -1.13307,0.117128 z m -155.23633,2.46289 c -1.21948,2.711869 0.75683,5.460507 3.4437,6.14538 2.85847,1.080772 6.66937,4.11785 9.31224,1.23392 2.3151,-2.03652 0.33929,-5.835383 -2.40983,-6.41823 -3.32833,-1.175814 -7.38479,-4.713633 -10.34611,-0.96107 z m 127.27344,7.61719 c -3.12289,1.309174 -7.49226,0.970678 -9.49244,3.970097 -1.23184,2.518748 0.7727,5.298264 3.48037,5.339749 3.48706,-0.907308 7.56742,-1.1128 10.30314,-3.739116 1.11397,-2.422222 -0.31199,-5.546068 -3.1516,-5.551016 -0.3827,-0.195662 -0.75023,-0.126964 -1.13947,-0.01971 z m -97.49023,1.54492 c -2.22858,1.461838 -2.68005,4.865948 -0.27553,6.376909 2.5869,1.470583 5.91459,1.954941 8.83971,2.495346 2.78485,0.332188 4.74603,-2.479173 3.89118,-5.048668 -2.04264,-3.279676 -6.47206,-2.73364 -9.71704,-4.089227 -0.91277,0.08855 -1.82555,0.177093 -2.73832,0.26564 z m 68.51367,4.50782 c -3.27623,0.788856 -7.46081,-0.187875 -9.93635,2.381992 -1.64972,2.268076 -0.15709,5.353662 2.50432,5.86185 3.61172,-0.292365 7.71764,0.09072 10.84009,-2.093962 1.46245,-2.227649 0.52336,-5.531725 -2.28478,-5.959415 -0.34949,-0.249225 -0.72211,-0.239347 -1.12328,-0.190465 z m -39.44922,1.41796 c -1.93309,1.83595 -1.76537,5.266611 0.87081,6.321491 2.80857,0.988807 6.17065,0.846733 9.1444,0.861366 2.79909,-0.172766 4.22635,-3.289835 2.92376,-5.664738 -2.60365,-2.851635 -6.84699,-1.541752 -10.29251,-2.269899 -0.88215,0.250593 -1.76431,0.501187 -2.64646,0.75178 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0a3d91;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.55000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:7.55, 22.65;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -1,83 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="256" height="204"
viewBox="0 0 256 204" fill="none" version="1.1" id="svg42" sodipodi:docname="share_app.svg"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<metadata id="metadata48">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs46" />
<sodipodi:namedview pagecolor="#000000" bordercolor="#666666" borderopacity="1"
objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="964"
id="namedview44" showgrid="false" inkscape:zoom="2.4705882" inkscape:cx="123.34752"
inkscape:cy="83.759737" inkscape:window-x="1920" inkscape:window-y="72"
inkscape:window-maximized="0" inkscape:current-layer="svg42" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M41.583 100.841H22.1807V102.841H52.7503V136.663H54.7503V102.841H68.0341C70.9241 102.841 73.267 105.184 73.267 108.074C73.267 112.068 76.5053 115.307 80.4999 115.307H92.727V113.307H80.4999C77.6098 113.307 75.267 110.964 75.267 108.074C75.267 104.079 72.0287 100.841 68.0341 100.841H43.583V63.6593H41.583V100.841Z"
fill="#657D99" id="path2" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M122.611 86.0596V46.2531H124.611V86.0596H122.611Z" fill="#657D99" id="path4" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M119.754 179.928L119.754 142.682L121.754 142.682L121.754 179.928L119.754 179.928Z"
fill="#657D99" id="path6" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M195.251 100.841V86.5962H193.251V113.826H148.362V115.826H194.251C198.125 115.826 201.301 118.969 201.301 122.826V127.044H203.301V122.826C203.301 118.186 199.75 114.378 195.251 113.881V102.841H233.052V100.841H195.251Z"
fill="#657D99" id="path8" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M32.1213 57.4112L32.8875 55.5637C33.5961 55.8576 34.3747 56.0208 35.1966 56.0208H37.0795V58.0208H35.1966C34.1072 58.0208 33.0686 57.804 32.1213 57.4112ZM48.3769 58.0208V56.0208H50.2598C51.0816 56.0208 51.8602 55.8576 52.5689 55.5637L53.335 57.4112C52.3877 57.804 51.3491 58.0208 50.2598 58.0208H48.3769ZM58.2935 36.8067H56.2935V34.9238C56.2935 34.102 56.1303 33.3234 55.8364 32.6147L57.6839 31.8486C58.0767 32.7959 58.2935 33.8345 58.2935 34.9238V36.8067ZM37.0795 26.8901H35.1966C34.1072 26.8901 33.0686 27.1069 32.1213 27.4997L32.8875 29.3472C33.5961 29.0533 34.3747 28.8901 35.1966 28.8901H37.0795V26.8901ZM27.1628 48.1042H29.1628V49.9871C29.1628 50.8089 29.326 51.5875 29.6199 52.2962L27.7724 53.0623C27.3796 52.115 27.1628 51.0764 27.1628 49.9871V48.1042ZM27.1628 44.3384H29.1628V40.5725H27.1628V44.3384ZM27.1628 36.8067H29.1628V34.9238C29.1628 34.102 29.326 33.3234 29.6199 32.6147L27.7724 31.8486C27.3796 32.7959 27.1628 33.8345 27.1628 34.9238V36.8067ZM40.8453 26.8901V28.8901H44.6111V26.8901H40.8453ZM48.3769 26.8901V28.8901H50.2598C51.0816 28.8901 51.8602 29.0533 52.5689 29.3472L53.335 27.4997C52.3877 27.1069 51.3491 26.8901 50.2598 26.8901H48.3769ZM58.2935 40.5725H56.2935V44.3383H58.2935V40.5725ZM58.2935 48.1042H56.2935V49.9871C56.2935 50.8089 56.1303 51.5875 55.8364 52.2962L57.6839 53.0623C58.0767 52.115 58.2935 51.0764 58.2935 49.9871V48.1042ZM44.6111 58.0208V56.0208H40.8453V58.0208H44.6111Z"
fill="#657D99" id="path10" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M112.487 40.4256L112.875 38.4636C113.41 38.5694 113.964 38.6251 114.533 38.6251H116.99V40.6251H114.533C113.833 40.6251 113.149 40.5565 112.487 40.4256ZM131.733 40.6251V38.6251H134.191C134.76 38.6251 135.314 38.5694 135.848 38.4636L136.237 40.4256C135.575 40.5565 134.891 40.6251 134.191 40.6251H131.733ZM140.016 38.8593L138.903 37.1973C139.829 36.5774 140.627 35.7797 141.247 34.8536L142.909 35.9663C142.143 37.1095 141.159 38.0939 140.016 38.8593ZM144.674 12.9411H142.674V10.4839C142.674 9.91475 142.619 9.36059 142.513 8.82599L144.475 8.43785C144.606 9.0996 144.674 9.78374 144.674 10.4839V12.9411ZM142.909 4.65889L141.247 5.77152C140.627 4.84548 139.829 4.04776 138.903 3.42779L140.016 1.76585C141.159 2.53126 142.143 3.5156 142.909 4.65889ZM116.99 0H114.533C113.833 0 113.149 0.0686375 112.487 0.199551L112.875 2.16153C113.41 2.05577 113.964 2 114.533 2H116.99V0ZM108.708 1.76585L109.821 3.42779C108.895 4.04776 108.097 4.84548 107.477 5.77152L105.815 4.65888C106.581 3.5156 107.565 2.53126 108.708 1.76585ZM104.049 27.6841H106.049V30.1412C106.049 30.7104 106.105 31.2645 106.211 31.7992L104.249 32.1873C104.118 31.5255 104.049 30.8414 104.049 30.1412V27.6841ZM105.815 35.9663L107.477 34.8536C108.097 35.7797 108.895 36.5774 109.821 37.1973L108.708 38.8593C107.565 38.0939 106.581 37.1095 105.815 35.9663ZM104.049 22.7697H106.049V17.8554H104.049V22.7697ZM104.049 12.9411H106.049V10.4839C106.049 9.91475 106.105 9.36059 106.211 8.82598L104.249 8.43785C104.118 9.09959 104.049 9.78374 104.049 10.4839V12.9411ZM121.905 0V2H126.819V0H121.905ZM131.733 0V2H134.191C134.76 2 135.314 2.05577 135.848 2.16153L136.237 0.199552C135.575 0.0686377 134.891 0 134.191 0H131.733ZM144.674 17.8554H142.674V22.7697H144.674V17.8554ZM144.674 27.6841H142.674V30.1412C142.674 30.7104 142.619 31.2645 142.513 31.7992L144.475 32.1873C144.606 31.5255 144.674 30.8414 144.674 30.1412V27.6841ZM126.819 40.6251V38.6251H121.905V40.6251H126.819Z"
fill="#657D99" id="path12" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M183.397 81.9904L184.163 80.1429C184.902 80.4493 185.714 80.6194 186.57 80.6194H188.513V82.6194H186.57C185.446 82.6194 184.375 82.3957 183.397 81.9904ZM200.171 82.6194V80.6194H202.114C202.97 80.6194 203.782 80.4493 204.521 80.1429L205.287 81.9904C204.309 82.3957 203.238 82.6194 202.114 82.6194H200.171ZM210.403 60.7295H208.403V58.7866C208.403 57.9301 208.233 57.1184 207.927 56.3795L209.774 55.6134C210.18 56.5908 210.403 57.6626 210.403 58.7866V60.7295ZM188.513 50.4969H186.57C185.446 50.4969 184.375 50.7207 183.397 51.126L184.163 52.9734C184.902 52.667 185.714 52.4969 186.57 52.4969H188.513V50.4969ZM178.281 72.3869H180.281V74.3297C180.281 75.1863 180.451 75.998 180.757 76.7368L178.91 77.5029C178.504 76.5255 178.281 75.4538 178.281 74.3297V72.3869ZM178.281 68.5011H180.281V64.6153H178.281V68.5011ZM178.281 60.7295H180.281V58.7866C180.281 57.9301 180.451 57.1184 180.757 56.3795L178.91 55.6134C178.504 56.5908 178.281 57.6626 178.281 58.7866V60.7295ZM192.399 50.4969V52.4969H196.285V50.4969H192.399ZM200.171 50.4969V52.4969H202.114C202.97 52.4969 203.782 52.667 204.521 52.9734L205.287 51.126C204.309 50.7207 203.238 50.4969 202.114 50.4969H200.171ZM210.403 64.6153H208.403V68.5011H210.403V64.6153ZM210.403 72.3869H208.403V74.3297C208.403 75.1863 208.233 75.998 207.927 76.7368L209.774 77.5029C210.18 76.5255 210.403 75.4538 210.403 74.3297V72.3869ZM196.285 82.6194V80.6194H192.399V82.6194H196.285Z"
fill="#657D99" id="path14" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M188.271 180.562L188.659 178.6C189.316 178.73 189.996 178.798 190.694 178.798H192.633V180.798H190.694C189.865 180.798 189.055 180.717 188.271 180.562ZM212.029 180.798V178.798H213.968C214.666 178.798 215.346 178.73 216.003 178.6L216.391 180.562C215.607 180.717 214.797 180.798 213.968 180.798H212.029ZM220.865 178.708L219.753 177.046C220.889 176.285 221.868 175.306 222.629 174.17L224.291 175.282C223.384 176.636 222.219 177.801 220.865 178.708ZM226.381 147.05H224.381V145.111C224.381 144.413 224.313 143.733 224.183 143.077L226.145 142.688C226.3 143.472 226.381 144.282 226.381 145.111V147.05ZM224.291 138.214L222.629 139.327C221.868 138.19 220.889 137.211 219.753 136.451L220.865 134.789C222.219 135.695 223.384 136.86 224.291 138.214ZM192.633 132.698H190.694C189.865 132.698 189.055 132.779 188.271 132.934L188.659 134.896C189.316 134.766 189.996 134.698 190.694 134.698H192.633V132.698ZM183.797 134.789L184.91 136.451C183.773 137.211 182.794 138.19 182.033 139.327L180.372 138.214C181.278 136.86 182.443 135.695 183.797 134.789ZM178.281 166.446H180.281V168.385C180.281 169.083 180.349 169.763 180.479 170.42L178.517 170.808C178.362 170.024 178.281 169.214 178.281 168.385V166.446ZM180.372 175.282L182.033 174.17C182.794 175.306 183.773 176.285 184.91 177.046L183.797 178.708C182.443 177.801 181.278 176.636 180.372 175.282ZM178.281 162.567H180.281V158.688H178.281V162.567ZM178.281 154.809H180.281V150.93H178.281V154.809ZM178.281 147.05H180.281V145.111C180.281 144.413 180.349 143.733 180.479 143.077L178.517 142.688C178.362 143.472 178.281 144.282 178.281 145.111V147.05ZM196.512 132.698V134.698H200.392V132.698H196.512ZM204.271 132.698V134.698H208.15V132.698H204.271ZM212.029 132.698V134.698H213.968C214.666 134.698 215.346 134.766 216.003 134.896L216.391 132.934C215.607 132.779 214.797 132.698 213.968 132.698H212.029ZM226.381 150.93H224.381V154.809H226.381V150.93ZM226.381 158.688H224.381V162.567H226.381V158.688ZM226.381 166.446H224.381V168.385C224.381 169.083 224.313 169.763 224.183 170.42L226.145 170.808C226.3 170.024 226.381 169.214 226.381 168.385V166.446ZM208.15 180.798V178.798H204.271V180.798H208.15ZM200.392 180.798V178.798H196.512V180.798H200.392Z"
fill="#657D99" id="path16" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M40.3891 175.457L41.1552 173.609C41.9338 173.932 42.7892 174.111 43.6915 174.111H45.7134V176.111H43.6915C42.5217 176.111 41.4063 175.878 40.3891 175.457ZM57.8451 176.111V174.111H59.8671C60.7693 174.111 61.6247 173.932 62.4033 173.609L63.1694 175.457C62.1522 175.878 61.0368 176.111 59.8671 176.111H57.8451ZM68.4941 153.33H66.4941V151.309C66.4941 150.406 66.3149 149.551 65.992 148.772L67.8395 148.006C68.2613 149.023 68.4941 150.139 68.4941 151.309V153.33ZM45.7134 142.682H43.6915C42.5217 142.682 41.4063 142.914 40.3891 143.336L41.1552 145.184C41.9338 144.861 42.7892 144.682 43.6915 144.682H45.7134V142.682ZM35.0645 165.462H37.0645V167.484C37.0645 168.386 37.2437 169.242 37.5665 170.02L35.7191 170.786C35.2973 169.769 35.0645 168.654 35.0645 167.484V165.462ZM35.0645 161.418H37.0645V157.374H35.0645V161.418ZM35.0645 153.33H37.0645V151.309C37.0645 150.406 37.2437 149.551 37.5665 148.772L35.7191 148.006C35.2973 149.023 35.0645 150.139 35.0645 151.309V153.33ZM49.7573 142.682V144.682H53.8012V142.682H49.7573ZM57.8451 142.682V144.682H59.8671C60.7693 144.682 61.6247 144.861 62.4033 145.184L63.1694 143.336C62.1522 142.914 61.0368 142.682 59.8671 142.682H57.8451ZM68.4941 157.374H66.4941V161.418H68.4941V157.374ZM68.4941 165.462H66.4941V167.484C66.4941 168.386 66.3149 169.242 65.992 170.02L67.8395 170.786C68.2613 169.769 68.4941 168.654 68.4941 167.484V165.462ZM53.8012 176.111V174.111H49.7573V176.111H53.8012Z"
fill="#657D99" id="path18" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M2.84 110.802L3.60611 108.954C3.91005 109.081 4.24493 109.151 4.60133 109.151H6.75821V111.151H4.60133C3.97743 111.151 3.38253 111.027 2.84 110.802ZM11.072 111.151V109.151H13.2288C13.5852 109.151 13.9201 109.081 14.2241 108.954L14.9902 110.802C14.4476 111.027 13.8527 111.151 13.2288 111.151H11.072ZM17.8302 100.079H15.8302V97.9223C15.8302 97.5659 15.7596 97.231 15.6336 96.927L17.481 96.1609C17.706 96.7035 17.8302 97.2984 17.8302 97.9223V100.079ZM6.75821 93.3209H4.60133C3.97743 93.3209 3.38253 93.4451 2.84 93.6701L3.60611 95.5175C3.91005 95.3915 4.24493 95.3209 4.60133 95.3209H6.75821V93.3209ZM0 104.393H2V106.55C2 106.906 2.07056 107.241 2.1966 107.545L0.349152 108.311C0.124172 107.769 0 107.174 0 106.55V104.393ZM0 100.079H2V97.9223C2 97.5659 2.07056 97.231 2.1966 96.927L0.349152 96.1609C0.124172 96.7035 0 97.2984 0 97.9223V100.079ZM11.072 93.3209V95.3209H13.2288C13.5852 95.3209 13.9201 95.3915 14.2241 95.5175L14.9902 93.6701C14.4476 93.4451 13.8527 93.3209 13.2288 93.3209H11.072ZM17.8302 104.393H15.8302V106.55C15.8302 106.906 15.7596 107.241 15.6336 107.545L17.481 108.311C17.706 107.769 17.8302 107.174 17.8302 106.55V104.393Z"
fill="#657D99" id="path20" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M114.745 202.969L115.511 201.122C115.815 201.248 116.149 201.318 116.506 201.318H118.663V203.318H116.506C115.882 203.318 115.287 203.194 114.745 202.969ZM122.977 203.318V201.318H125.133C125.49 201.318 125.825 201.248 126.129 201.122L126.895 202.969C126.352 203.194 125.757 203.318 125.133 203.318H122.977ZM129.735 192.246H127.735V190.09C127.735 189.733 127.664 189.398 127.538 189.094L129.386 188.328C129.611 188.871 129.735 189.466 129.735 190.09V192.246ZM118.663 185.488H116.506C115.882 185.488 115.287 185.612 114.745 185.837L115.511 187.685C115.815 187.559 116.149 187.488 116.506 187.488H118.663V185.488ZM111.905 196.56H113.905V198.717C113.905 199.074 113.975 199.408 114.101 199.712L112.254 200.478C112.029 199.936 111.905 199.341 111.905 198.717V196.56ZM111.905 192.246H113.905V190.09C113.905 189.733 113.975 189.398 114.101 189.094L112.254 188.328C112.029 188.871 111.905 189.466 111.905 190.09V192.246ZM122.977 185.488V187.488H125.133C125.49 187.488 125.825 187.559 126.129 187.685L126.895 185.837C126.352 185.612 125.757 185.488 125.133 185.488H122.977ZM129.735 196.56H127.735V198.717C127.735 199.074 127.664 199.408 127.538 199.712L129.386 200.478C129.611 199.936 129.735 199.341 129.735 198.717V196.56Z"
fill="#657D99" id="path22" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M240.444 110.802L241.21 108.954C241.514 109.081 241.849 109.151 242.205 109.151H244.362V111.151H242.205C241.581 111.151 240.987 111.027 240.444 110.802ZM248.676 111.151V109.151H250.833C251.189 109.151 251.524 109.081 251.828 108.954L252.594 110.802C252.052 111.027 251.457 111.151 250.833 111.151H248.676ZM255.434 100.079H253.434V97.9223C253.434 97.5659 253.364 97.231 253.238 96.927L255.085 96.1609C255.31 96.7035 255.434 97.2984 255.434 97.9223V100.079ZM244.362 93.3209H242.205C241.581 93.3209 240.987 93.4451 240.444 93.6701L241.21 95.5175C241.514 95.3915 241.849 95.3209 242.205 95.3209H244.362V93.3209ZM237.604 104.393H239.604V106.55C239.604 106.906 239.675 107.241 239.801 107.545L237.953 108.311C237.728 107.769 237.604 107.174 237.604 106.55V104.393ZM237.604 100.079H239.604V97.9223C239.604 97.5659 239.675 97.231 239.801 96.927L237.953 96.1609C237.728 96.7035 237.604 97.2984 237.604 97.9223V100.079ZM248.676 93.3209V95.3209H250.833C251.189 95.3209 251.524 95.3915 251.828 95.5175L252.594 93.6701C252.052 93.4451 251.457 93.3209 250.833 93.3209H248.676ZM255.434 104.393H253.434V106.55C253.434 106.906 253.364 107.241 253.238 107.545L255.085 108.311C255.31 107.769 255.434 107.174 255.434 106.55V104.393Z"
fill="#657D99" id="path24" />
<path
d="M108.75 109.808V129.511C108.75 131.11 110.052 132.429 111.668 132.429H113.036C114.636 132.429 115.955 131.11 115.955 129.511V109.808H108.75V109.808Z"
fill="#87C214" id="path26" />
<path
d="M115.938 100.312V96.6023C115.938 95.003 114.636 93.684 113.036 93.684H111.668C110.069 93.684 108.75 95.003 108.75 96.6023V100.312H115.938V100.312Z"
fill="#87C214" id="path28" />
<path
d="M131.931 116.305V96.6023C131.931 95.003 130.628 93.684 129.029 93.684H127.66C126.061 93.684 124.742 95.003 124.742 96.6023V116.305H131.931V116.305Z"
fill="#87C214" id="path30" />
<path
d="M124.742 125.801V129.511C124.742 131.11 126.061 132.429 127.66 132.429H129.029C130.628 132.429 131.947 131.11 131.947 129.511V125.801H124.742Z"
fill="#87C214" id="path32" />
<path
d="M107.595 117.459H103.886C102.286 117.459 100.967 118.761 100.967 120.377V121.746C100.967 123.345 102.27 124.664 103.886 124.664H107.595V117.459Z"
fill="#95D220" id="path34" />
<path
d="M136.795 117.459H117.092V124.664H136.795C138.394 124.664 139.713 123.345 139.713 121.746V120.377C139.713 118.761 138.394 117.459 136.795 117.459Z"
fill="#95D220" id="path36" />
<path
d="M123.588 101.466H103.886C102.286 101.466 100.967 102.769 100.967 104.385V105.753C100.967 107.352 102.27 108.671 103.886 108.671H123.588V101.466Z"
fill="#95D220" id="path38" />
<path
d="M136.795 101.466H133.085V108.671H136.795C138.394 108.671 139.713 107.369 139.713 105.753V104.384C139.713 102.769 138.394 101.466 136.795 101.466Z"
fill="#95D220" id="path40" />
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -26,8 +26,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionCode 10401
versionName "1.4.1"
versionCode 10306
versionName "1.3.6"
applicationId "org.briarproject.briar.android"
vectorDrawables.useSupportLibrary = true

View File

@@ -462,17 +462,6 @@
android:label="@string/hotspot_title"
android:theme="@style/BriarTheme" />
<activity
android:name=".android.contact.connect.ConnectViaBluetoothActivity"
android:exported="false"
android:label="@string/connect_via_bluetooth_title"
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity"
android:theme="@style/BriarTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
</activity>
</application>
<queries>

View File

@@ -3,11 +3,9 @@ package org.briarproject.bramble.account;
import android.app.Application;
import android.content.SharedPreferences;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import org.briarproject.briar.R;
import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.util.UiUtils;
@@ -17,16 +15,10 @@ import javax.inject.Inject;
class BriarAccountManager extends AndroidAccountManager {
@Inject
BriarAccountManager(
DatabaseConfig databaseConfig,
CryptoComponent crypto,
IdentityManager identityManager,
SharedPreferences prefs,
PersistentLogManager logManager,
FeatureFlags featureFlags,
BriarAccountManager(DatabaseConfig databaseConfig, CryptoComponent crypto,
IdentityManager identityManager, SharedPreferences prefs,
Application app) {
super(databaseConfig, crypto, identityManager, prefs, logManager,
featureFlags, app);
super(databaseConfig, crypto, identityManager, prefs, app);
}
@Override

View File

@@ -22,7 +22,6 @@ import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
import org.briarproject.bramble.api.keyagreement.PayloadParser;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
@@ -36,7 +35,6 @@ import org.briarproject.briar.BriarCoreEagerSingletons;
import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.attachment.AttachmentModule;
import org.briarproject.briar.android.attachment.media.MediaModule;
import org.briarproject.briar.android.contact.connect.BluetoothIntroFragment;
import org.briarproject.briar.android.conversation.glide.BriarModelLoader;
import org.briarproject.briar.android.hotspot.AbstractTabsFragment;
import org.briarproject.briar.android.hotspot.FallbackFragment;
@@ -79,7 +77,6 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager
import org.briarproject.briar.api.test.TestDataCreator;
import java.util.concurrent.Executor;
import java.util.logging.Formatter;
import javax.inject.Singleton;
@@ -206,10 +203,6 @@ public interface AndroidComponent
AutoDeleteManager autoDeleteManager();
PersistentLogManager persistentLogManager();
Formatter formatter();
void inject(SignInReminderReceiver briarService);
void inject(BriarService briarService);
@@ -243,6 +236,4 @@ public interface AndroidComponent
void inject(SendFragment sendFragment);
void inject(ReceiveFragment receiveFragment);
void inject(BluetoothIntroFragment bluetoothIntroFragment);
}

View File

@@ -18,9 +18,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BluetoothConstants;
import org.briarproject.bramble.api.plugin.LanTcpConstants;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
@@ -37,13 +35,11 @@ import org.briarproject.briar.android.account.SetupModule;
import org.briarproject.briar.android.blog.BlogModule;
import org.briarproject.briar.android.contact.ContactListModule;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactModule;
import org.briarproject.briar.android.contact.connect.ConnectViaBluetoothModule;
import org.briarproject.briar.android.forum.ForumModule;
import org.briarproject.briar.android.hotspot.HotspotModule;
import org.briarproject.briar.android.introduction.IntroductionModule;
import org.briarproject.briar.android.logging.LoggingModule;
import org.briarproject.briar.android.login.LoginModule;
import org.briarproject.briar.android.mailbox.MailboxModule;
import org.briarproject.briar.android.navdrawer.NavDrawerModule;
import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule;
import org.briarproject.briar.android.privategroup.list.GroupListModule;
@@ -77,8 +73,6 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_SOCKS_PORT;
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
@@ -95,7 +89,6 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
DevReportModule.class,
ContactListModule.class,
IntroductionModule.class,
ConnectViaBluetoothModule.class,
// below need to be within same scope as ViewModelProvider.Factory
BlogModule.class,
ForumModule.class,
@@ -104,7 +97,6 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
SharingModule.class,
HotspotModule.class,
TransferDataModule.class,
MailboxModule.class,
})
public class AppModule {
@@ -161,28 +153,6 @@ public class AppModule {
return app.getDir("tor", MODE_PRIVATE);
}
@Provides
@Singleton
@TorSocksPort
int provideTorSocksPort() {
if (!IS_DEBUG_BUILD) {
return DEFAULT_SOCKS_PORT;
} else {
return DEFAULT_SOCKS_PORT + 2;
}
}
@Provides
@Singleton
@TorControlPort
int provideTorControlPort() {
if (!IS_DEBUG_BUILD) {
return DEFAULT_CONTROL_PORT;
} else {
return DEFAULT_CONTROL_PORT + 2;
}
}
@Provides
@Singleton
PluginConfig providePluginConfig(AndroidBluetoothPluginFactory bluetooth,
@@ -199,8 +169,11 @@ public class AppModule {
@Override
public Collection<SimplexPluginFactory> getSimplexFactories() {
if (SDK_INT >= 19) return singletonList(drive);
else return emptyList();
if (SDK_INT >= 19 && featureFlags.shouldEnableTransferData()) {
return singletonList(drive);
} else {
return emptyList();
}
}
@Override
@@ -245,9 +218,8 @@ public class AppModule {
}
@Override
public File getTemporaryLogFile() {
return AndroidUtils
.getTemporaryLogFile(app.getApplicationContext());
public File getLogcatFile() {
return AndroidUtils.getLogcatFile(app.getApplicationContext());
}
};
return devConfig;
@@ -340,7 +312,17 @@ public class AppModule {
}
@Override
public boolean shouldEnablePersistentLogs() {
public boolean shouldEnableConnectViaBluetooth() {
return IS_DEBUG_BUILD;
}
@Override
public boolean shouldEnableTransferData() {
return IS_DEBUG_BUILD;
}
@Override
public boolean shouldEnableShareAppViaOfflineHotspot() {
return IS_DEBUG_BUILD;
}
};

View File

@@ -17,14 +17,11 @@ import com.vanniktech.emoji.google.GoogleEmojiProvider;
import org.briarproject.bramble.BrambleAndroidEagerSingletons;
import org.briarproject.bramble.BrambleAppComponent;
import org.briarproject.bramble.BrambleCoreEagerSingletons;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import org.briarproject.briar.BriarCoreEagerSingletons;
import org.briarproject.briar.R;
import org.briarproject.briar.android.logging.CachingLogHandler;
import org.briarproject.briar.android.util.UiUtils;
import java.io.File;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.logging.Handler;
import java.util.logging.Logger;
@@ -34,10 +31,7 @@ import androidx.annotation.NonNull;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.getPersistentLogDir;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
public class BriarApplicationImpl extends Application
@@ -87,17 +81,6 @@ public class BriarApplicationImpl extends Application
rootLogger.addHandler(logHandler);
rootLogger.setLevel(IS_DEBUG_BUILD ? FINE : INFO);
if (applicationComponent.featureFlags().shouldEnablePersistentLogs()) {
PersistentLogManager logManager =
applicationComponent.persistentLogManager();
File logDir = getPersistentLogDir(this);
try {
rootLogger.addHandler(logManager.createLogHandler(logDir));
} catch (IOException e) {
logException(LOG, WARNING, e);
}
}
LOG.info("Created");
EmojiManager.install(new GoogleEmojiProvider());

View File

@@ -28,8 +28,8 @@ import org.briarproject.briar.android.contact.add.remote.AddContactActivity;
import org.briarproject.briar.android.contact.add.remote.LinkExchangeFragment;
import org.briarproject.briar.android.contact.add.remote.NicknameFragment;
import org.briarproject.briar.android.contact.add.remote.PendingContactListActivity;
import org.briarproject.briar.android.contact.connect.ConnectViaBluetoothActivity;
import org.briarproject.briar.android.conversation.AliasDialogFragment;
import org.briarproject.briar.android.conversation.BluetoothConnecterDialogFragment;
import org.briarproject.briar.android.conversation.ConversationActivity;
import org.briarproject.briar.android.conversation.ConversationSettingsDialog;
import org.briarproject.briar.android.conversation.ImageActivity;
@@ -238,6 +238,9 @@ public interface ActivityComponent {
void inject(ConversationSettingsDialog dialog);
void inject(
BluetoothConnecterDialogFragment bluetoothConnecterDialogFragment);
void inject(RssFeedImportFragment fragment);
void inject(RssFeedManageFragment fragment);
@@ -245,6 +248,4 @@ public interface ActivityComponent {
void inject(RssFeedImportFailedDialogFragment fragment);
void inject(RssFeedDeleteFeedDialogFragment fragment);
void inject(ConnectViaBluetoothActivity connectViaBluetoothActivity);
}

View File

@@ -40,10 +40,10 @@ public class ContactListItem extends ContactItem
item.unread, item.timestamp);
}
ContactListItem(ContactListItem item, long timestamp, boolean read) {
ContactListItem(ContactListItem item, ConversationMessageHeader h) {
this(item.getContact(), item.getAuthorInfo(), item.isConnected(), false,
read ? item.unread : item.unread + 1,
Math.max(timestamp, item.timestamp));
h.isRead() ? item.unread : item.unread + 1,
Math.max(h.getTimestamp(), item.timestamp));
}
/**

View File

@@ -28,7 +28,6 @@ import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.conversation.ConversationManager;
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
import org.briarproject.briar.api.conversation.event.ConversationMessageReceivedEvent;
import org.briarproject.briar.api.conversation.event.ConversationMessageTrackedEvent;
import org.briarproject.briar.api.identity.AuthorInfo;
import org.briarproject.briar.api.identity.AuthorManager;
@@ -132,14 +131,13 @@ public class ContactsViewModel extends DbViewModel implements EventListener {
} else if (e instanceof ContactRemovedEvent) {
LOG.info("Contact removed, removing item");
removeItem(((ContactRemovedEvent) e).getContactId());
} else if (e instanceof ConversationMessageTrackedEvent) {
LOG.info("Conversation message tracked, updating item");
ConversationMessageTrackedEvent p =
(ConversationMessageTrackedEvent) e;
long timestamp = p.getTimestamp();
boolean read = p.getRead();
updateItem(p.getContactId(),
item -> new ContactListItem(item, timestamp, read), true);
} else if (e instanceof ConversationMessageReceivedEvent) {
LOG.info("Conversation message received, updating item");
ConversationMessageReceivedEvent<?> p =
(ConversationMessageReceivedEvent<?>) e;
ConversationMessageHeader h = p.getMessageHeader();
updateItem(p.getContactId(), item -> new ContactListItem(item, h),
true);
} else if (e instanceof AvatarUpdatedEvent) {
AvatarUpdatedEvent a = (AvatarUpdatedEvent) e;
updateItem(a.getContactId(), item -> new ContactListItem(item,

View File

@@ -20,8 +20,6 @@ import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgre
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.QrCodeScanned;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.qrcode.CameraException;
import org.briarproject.briar.android.qrcode.CameraView;
import org.briarproject.briar.android.view.QrCodeView;
import java.util.logging.Logger;

View File

@@ -53,8 +53,7 @@ import org.briarproject.briar.android.contact.add.nearby.AddContactState.Contact
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementListening;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementStarted;
import org.briarproject.briar.android.contact.add.nearby.AddContactState.KeyAgreementWaiting;
import org.briarproject.briar.android.qrcode.QrCodeDecoder;
import org.briarproject.briar.android.qrcode.QrCodeUtils;
import org.briarproject.briar.android.util.QrCodeUtils;
import org.briarproject.briar.android.viewmodel.LiveEvent;
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;

View File

@@ -1,8 +1,8 @@
package org.briarproject.briar.android.qrcode;
package org.briarproject.briar.android.contact.add.nearby;
import java.io.IOException;
public class CameraException extends IOException {
class CameraException extends IOException {
CameraException(String message) {
super(message);

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.qrcode;
package org.briarproject.briar.android.contact.add.nearby;
import android.content.Context;
import android.hardware.Camera;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.qrcode;
package org.briarproject.briar.android.contact.add.nearby;
import android.hardware.Camera;
@@ -7,7 +7,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import androidx.annotation.UiThread;
@NotNullByDefault
public interface PreviewConsumer {
interface PreviewConsumer {
@UiThread
void start(Camera camera, int cameraIndex);

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.qrcode;
package org.briarproject.briar.android.contact.add.nearby;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
@@ -32,7 +32,7 @@ import static java.util.logging.Logger.getLogger;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
private static final Logger LOG = getLogger(QrCodeDecoder.class.getName());
@@ -44,7 +44,7 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
private Camera camera = null;
private int cameraIndex = 0;
public QrCodeDecoder(AndroidExecutor androidExecutor,
QrCodeDecoder(AndroidExecutor androidExecutor,
@IoExecutor Executor ioExecutor, ResultCallback callback) {
this.androidExecutor = androidExecutor;
this.ioExecutor = ioExecutor;
@@ -127,7 +127,7 @@ public class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
}
@NotNullByDefault
public interface ResultCallback {
interface ResultCallback {
@IoExecutor
void onQrCodeDecoded(Result result);
}

View File

@@ -1,87 +0,0 @@
package org.briarproject.briar.android.contact.connect;
import android.app.Activity;
import android.content.Context;
import org.briarproject.briar.R;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.os.Build.VERSION.SDK_INT;
import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener;
import static org.briarproject.briar.android.util.UiUtils.isLocationEnabled;
import static org.briarproject.briar.android.util.UiUtils.showLocationDialog;
class BluetoothConditionManager {
private enum Permission {
UNKNOWN, GRANTED, SHOW_RATIONALE, PERMANENTLY_DENIED
}
private Permission locationPermission = Permission.UNKNOWN;
/**
* Call this when the using activity or fragment starts,
* because permissions might have changed while it was stopped.
*/
void reset() {
locationPermission = Permission.UNKNOWN;
}
@UiThread
void onLocationPermissionResult(Activity activity,
@Nullable Boolean result) {
if (result != null && result) {
locationPermission = Permission.GRANTED;
} else if (shouldShowRequestPermissionRationale(activity,
ACCESS_FINE_LOCATION)) {
locationPermission = Permission.SHOW_RATIONALE;
} else {
locationPermission = Permission.PERMANENTLY_DENIED;
}
}
boolean areRequirementsFulfilled(Context ctx,
ActivityResultLauncher<String> permissionRequest,
Runnable onLocationDenied) {
boolean permissionGranted =
SDK_INT < 23 || locationPermission == Permission.GRANTED;
boolean locationEnabled = isLocationEnabled(ctx);
if (permissionGranted && locationEnabled) return true;
if (locationPermission == Permission.PERMANENTLY_DENIED) {
showDenialDialog(ctx, onLocationDenied);
} else if (locationPermission == Permission.SHOW_RATIONALE) {
showRationale(ctx, permissionRequest);
} else if (!locationEnabled) {
showLocationDialog(ctx);
}
return false;
}
private void showDenialDialog(Context ctx, Runnable onLocationDenied) {
new AlertDialog.Builder(ctx, R.style.BriarDialogTheme)
.setTitle(R.string.permission_location_title)
.setMessage(R.string.permission_location_denied_body)
.setPositiveButton(R.string.ok, getGoToSettingsListener(ctx))
.setNegativeButton(R.string.cancel, (v, d) ->
onLocationDenied.run())
.show();
}
private void showRationale(Context ctx,
ActivityResultLauncher<String> permissionRequest) {
new AlertDialog.Builder(ctx, R.style.BriarDialogTheme)
.setTitle(R.string.permission_location_title)
.setMessage(R.string.permission_location_request_body)
.setPositiveButton(R.string.ok, (dialog, which) ->
permissionRequest.launch(ACCESS_FINE_LOCATION))
.show();
}
}

View File

@@ -1,109 +0,0 @@
package org.briarproject.briar.android.contact.connect;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.util.ActivityLaunchers.RequestBluetoothDiscoverable;
import javax.inject.Inject;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class BluetoothIntroFragment extends Fragment {
final static String TAG = BluetoothIntroFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private final BluetoothConditionManager conditionManager =
new BluetoothConditionManager();
private ConnectViaBluetoothViewModel viewModel;
private final ActivityResultLauncher<Integer> bluetoothDiscoverableRequest =
registerForActivityResult(new RequestBluetoothDiscoverable(),
this::onBluetoothDiscoverable);
private final ActivityResultLauncher<String> permissionRequest =
registerForActivityResult(new RequestPermission(),
this::onPermissionRequestResult);
@Override
public void onAttach(Context context) {
super.onAttach(context);
getAndroidComponent(requireContext()).inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(ConnectViaBluetoothViewModel.class);
}
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater
.inflate(R.layout.fragment_bluetooth_intro, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
Button startButton = view.findViewById(R.id.startButton);
startButton.setOnClickListener(this::onStartClicked);
}
@Override
public void onStart() {
super.onStart();
conditionManager.reset();
}
private void onStartClicked(View v) {
if (viewModel.shouldStartFlow()) {
// The dialog starts a permission request which comes back as true
// if the permission is already granted.
// So we can use the request as a generic entry point
// to the whole flow.
permissionRequest.launch(ACCESS_FINE_LOCATION);
}
}
private void onPermissionRequestResult(@Nullable Boolean result) {
Activity a = requireActivity();
// update permission result in BluetoothConnecter
conditionManager.onLocationPermissionResult(a, result);
// what to do when the user denies granting the location permission
Runnable onLocationPermissionDenied = () -> Toast.makeText(
requireContext(),
R.string.connect_via_bluetooth_no_location_permission,
LENGTH_LONG).show();
// if requirements are fulfilled, request Bluetooth discoverability
if (conditionManager.areRequirementsFulfilled(a, permissionRequest,
onLocationPermissionDenied)) {
bluetoothDiscoverableRequest.launch(120); // for 2min
}
}
private void onBluetoothDiscoverable(@Nullable Boolean result) {
if (result != null && result) {
viewModel.onBluetoothDiscoverable();
}
}
}

View File

@@ -1,29 +0,0 @@
package org.briarproject.briar.android.contact.connect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class BluetoothProgressFragment extends Fragment {
final static String TAG = BluetoothProgressFragment.class.getName();
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater
.inflate(R.layout.fragment_bluetooth_progress, container, false);
}
}

View File

@@ -1,98 +0,0 @@
package org.briarproject.briar.android.contact.connect;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.Objects.requireNonNull;
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
import static org.briarproject.briar.android.util.UiUtils.showFragment;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ConnectViaBluetoothActivity extends BriarActivity {
@Inject
ViewModelProvider.Factory viewModelFactory;
private ConnectViaBluetoothViewModel viewModel;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(ConnectViaBluetoothViewModel.class);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = requireNonNull(getIntent());
int contactId = intent.getIntExtra(CONTACT_ID, -1);
if (contactId == -1) throw new IllegalArgumentException("ContactId");
viewModel.setContactId(new ContactId(contactId));
setContentView(R.layout.activity_fragment_container);
viewModel.getState().observeEvent(this, this::onStateChanged);
if (savedInstanceState == null) {
Fragment f = new BluetoothIntroFragment();
String tag = BluetoothIntroFragment.TAG;
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, f, tag)
.commitNow();
}
}
@Override
public void onStart() {
super.onStart();
viewModel.reset();
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void onStateChanged(ConnectViaBluetoothState state) {
if (state instanceof ConnectViaBluetoothState.Connecting) {
Fragment f = new BluetoothProgressFragment();
String tag = BluetoothProgressFragment.TAG;
showFragment(getSupportFragmentManager(), f, tag, false);
} else if (state instanceof ConnectViaBluetoothState.Success) {
Toast.makeText(this, R.string.connect_via_bluetooth_success,
LENGTH_LONG).show();
supportFinishAfterTransition();
} else if (state instanceof ConnectViaBluetoothState.Error) {
Toast.makeText(this,
((ConnectViaBluetoothState.Error) state).errorRes,
LENGTH_LONG).show();
supportFinishAfterTransition();
} else throw new AssertionError();
}
}

View File

@@ -1,19 +0,0 @@
package org.briarproject.briar.android.contact.connect;
import org.briarproject.briar.android.viewmodel.ViewModelKey;
import androidx.lifecycle.ViewModel;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public abstract class ConnectViaBluetoothModule {
@Binds
@IntoMap
@ViewModelKey(ConnectViaBluetoothViewModel.class)
abstract ViewModel bindContactListViewModel(
ConnectViaBluetoothViewModel connectViaBluetoothViewModel);
}

View File

@@ -1,23 +0,0 @@
package org.briarproject.briar.android.contact.connect;
import androidx.annotation.StringRes;
abstract class ConnectViaBluetoothState {
static class Connecting extends ConnectViaBluetoothState {
}
static class Success extends ConnectViaBluetoothState {
}
static class Error extends ConnectViaBluetoothState {
@StringRes
final int errorRes;
Error(@StringRes int errorRes) {
this.errorRes = errorRes;
}
}
}

View File

@@ -1,20 +1,19 @@
package org.briarproject.briar.android.contact.connect;
package org.briarproject.briar.android.conversation;
import android.app.Activity;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.widget.Toast;
import org.briarproject.bramble.api.connection.ConnectionManager;
import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
@@ -22,22 +21,23 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.plugin.bluetooth.BluetoothPlugin;
import org.briarproject.briar.R;
import org.briarproject.briar.android.contact.connect.ConnectViaBluetoothState.Connecting;
import org.briarproject.briar.android.contact.connect.ConnectViaBluetoothState.Success;
import org.briarproject.briar.android.viewmodel.DbViewModel;
import org.briarproject.briar.android.viewmodel.LiveEvent;
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
import org.briarproject.briar.android.contact.ContactItem;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import static java.util.Objects.requireNonNull;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.os.Build.VERSION.SDK_INT;
import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
@@ -46,50 +46,48 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener;
import static org.briarproject.briar.android.util.UiUtils.isLocationEnabled;
import static org.briarproject.briar.android.util.UiUtils.showLocationDialog;
@UiThread
@NotNullByDefault
class ConnectViaBluetoothViewModel extends DbViewModel implements
EventListener {
class BluetoothConnecter implements EventListener {
private final Logger LOG =
getLogger(ConnectViaBluetoothViewModel.class.getName());
private final Logger LOG = getLogger(BluetoothConnecter.class.getName());
private final long BT_ACTIVE_TIMEOUT = SECONDS.toMillis(5);
private enum Permission {
UNKNOWN, GRANTED, SHOW_RATIONALE, PERMANENTLY_DENIED
}
private final Application app;
private final PluginManager pluginManager;
private final Executor ioExecutor;
private final AndroidExecutor androidExecutor;
private final ConnectionRegistry connectionRegistry;
@Nullable
private final BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
private final EventBus eventBus;
private final TransportPropertyManager transportPropertyManager;
private final ConnectionManager connectionManager;
@Nullable
private volatile BluetoothPlugin bluetoothPlugin;
@Nullable
private Permission locationPermission = Permission.UNKNOWN;
private ContactId contactId = null;
private final MutableLiveEvent<ConnectViaBluetoothState> state =
new MutableLiveEvent<>();
@Inject
ConnectViaBluetoothViewModel(
Application app,
@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager,
TransactionManager db,
AndroidExecutor androidExecutor,
BluetoothConnecter(Application app,
PluginManager pluginManager,
@IoExecutor Executor ioExecutor,
AndroidExecutor androidExecutor,
ConnectionRegistry connectionRegistry,
EventBus eventBus,
TransportPropertyManager transportPropertyManager,
ConnectionManager connectionManager) {
super(app, dbExecutor, lifecycleManager, db, androidExecutor);
this.app = app;
this.pluginManager = pluginManager;
this.ioExecutor = ioExecutor;
this.androidExecutor = androidExecutor;
this.bluetoothPlugin = (BluetoothPlugin) pluginManager.getPlugin(ID);
this.connectionRegistry = connectionRegistry;
this.eventBus = eventBus;
@@ -97,22 +95,20 @@ class ConnectViaBluetoothViewModel extends DbViewModel implements
this.connectionManager = connectionManager;
}
@Override
protected void onCleared() {
stopConnecting();
boolean isConnectedViaBluetooth(ContactId contactId) {
return connectionRegistry.isConnected(contactId, ID);
}
boolean isDiscovering() {
return bluetoothPlugin.isDiscovering();
}
/**
* Set this as soon as it becomes available.
*/
void setContactId(ContactId contactId) {
this.contactId = contactId;
}
/**
* Call this when the using activity or fragment starts.
* Call this when the using activity or fragment starts,
* because permissions might have changed while it was stopped.
*/
void reset() {
locationPermission = Permission.UNKNOWN;
// When this class is instantiated before we are logged in
// (like when returning to a killed activity), bluetoothPlugin would be
// null and we consider bluetooth not supported. So reset here.
@@ -120,52 +116,94 @@ class ConnectViaBluetoothViewModel extends DbViewModel implements
}
@UiThread
boolean shouldStartFlow() {
if (isBluetoothNotSupported()) {
state.setEvent(new ConnectViaBluetoothState.Error(
R.string.bt_plugin_status_inactive));
return false;
} else if (isConnectedViaBluetooth()) {
state.setEvent(new Success());
return false;
} else if (isDiscovering()) {
state.setEvent(new ConnectViaBluetoothState.Error(
R.string.connect_via_bluetooth_already_discovering));
return false;
void onLocationPermissionResult(Activity activity,
@Nullable Boolean result) {
if (result != null && result) {
locationPermission = Permission.GRANTED;
} else if (shouldShowRequestPermissionRationale(activity,
ACCESS_FINE_LOCATION)) {
locationPermission = Permission.SHOW_RATIONALE;
} else {
locationPermission = Permission.PERMANENTLY_DENIED;
}
return true;
}
private boolean isBluetoothNotSupported() {
boolean isBluetoothNotSupported() {
return bt == null || bluetoothPlugin == null;
}
private boolean isDiscovering() {
// we should not be calling this if isBluetoothNotSupported() is true
return requireNonNull(bluetoothPlugin).isDiscovering();
boolean areRequirementsFulfilled(Context ctx,
ActivityResultLauncher<String> permissionRequest,
Runnable onLocationDenied) {
boolean permissionGranted =
SDK_INT < 23 || locationPermission == Permission.GRANTED;
boolean locationEnabled = isLocationEnabled(ctx);
if (permissionGranted && locationEnabled) return true;
if (locationPermission == Permission.PERMANENTLY_DENIED) {
showDenialDialog(ctx, onLocationDenied);
} else if (locationPermission == Permission.SHOW_RATIONALE) {
showRationale(ctx, permissionRequest);
} else if (!locationEnabled) {
showLocationDialog(ctx);
}
return false;
}
private boolean isConnectedViaBluetooth() {
return connectionRegistry.isConnected(requireNonNull(contactId), ID);
private void showDenialDialog(Context ctx, Runnable onLocationDenied) {
new AlertDialog.Builder(ctx, R.style.BriarDialogTheme)
.setTitle(R.string.permission_location_title)
.setMessage(R.string.permission_location_denied_body)
.setPositiveButton(R.string.ok, getGoToSettingsListener(ctx))
.setNegativeButton(R.string.cancel, (v, d) ->
onLocationDenied.run())
.show();
}
private void showRationale(Context ctx,
ActivityResultLauncher<String> permissionRequest) {
new AlertDialog.Builder(ctx, R.style.BriarDialogTheme)
.setTitle(R.string.permission_location_title)
.setMessage(R.string.permission_location_request_body)
.setPositiveButton(R.string.ok, (dialog, which) ->
permissionRequest.launch(ACCESS_FINE_LOCATION))
.show();
}
@UiThread
void onBluetoothDiscoverable() {
ContactId contactId = requireNonNull(this.contactId);
BluetoothPlugin bluetoothPlugin = requireNonNull(this.bluetoothPlugin);
void onBluetoothDiscoverable(ContactItem contact) {
contactId = contact.getContact().getId();
connect();
}
state.setEvent(new Connecting());
@UiThread
@Override
public void eventOccurred(@NonNull Event e) {
if (e instanceof ConnectionOpenedEvent) {
ConnectionOpenedEvent c = (ConnectionOpenedEvent) e;
if (c.getContactId().equals(contactId) && c.isIncoming() &&
c.getTransportId() == ID) {
if (bluetoothPlugin != null) {
bluetoothPlugin.stopDiscoverAndConnect();
}
LOG.info("Contact connected to us");
showToast(R.string.toast_connect_via_bluetooth_success);
}
}
}
private void connect() {
bluetoothPlugin.disablePolling();
pluginManager.setPluginEnabled(ID, true);
ioExecutor.execute(() -> {
try {
if (!waitForBluetoothActive()) {
state.postEvent(new ConnectViaBluetoothState.Error(
R.string.bt_plugin_status_inactive));
showToast(R.string.bt_plugin_status_inactive);
LOG.warning("Bluetooth plugin didn't become active");
return;
}
showToast(R.string.toast_connect_via_bluetooth_start);
eventBus.addListener(this);
try {
String uuid = null;
@@ -188,7 +226,7 @@ class ConnectViaBluetoothViewModel extends DbViewModel implements
LOG.info("Could connect, handling connection");
connectionManager
.manageOutgoingConnection(contactId, ID, conn);
state.postEvent(new Success());
showToast(R.string.toast_connect_via_bluetooth_success);
}
} finally {
eventBus.removeListener(this);
@@ -199,23 +237,8 @@ class ConnectViaBluetoothViewModel extends DbViewModel implements
});
}
@UiThread
@Override
public void eventOccurred(@NonNull Event e) {
if (e instanceof ConnectionOpenedEvent) {
ConnectionOpenedEvent c = (ConnectionOpenedEvent) e;
if (c.getContactId().equals(contactId) && c.isIncoming() &&
c.getTransportId() == ID) {
stopConnecting();
LOG.info("Contact connected to us");
state.postEvent(new Success());
}
}
}
@IoExecutor
private boolean waitForBluetoothActive() {
BluetoothPlugin bluetoothPlugin = requireNonNull(this.bluetoothPlugin);
long left = BT_ACTIVE_TIMEOUT;
final long sleep = 250;
try {
@@ -241,9 +264,9 @@ class ConnectViaBluetoothViewModel extends DbViewModel implements
final long sleep = 250;
try {
while (left > 0) {
if (isConnectedViaBluetooth()) {
if (isConnectedViaBluetooth(contactId)) {
LOG.info("Failed to connect, but contact connected");
// no success state needed here, as it gets shown when
// no Toast needed here, as it gets shown when
// ConnectionOpenedEvent is received
return;
}
@@ -254,19 +277,13 @@ class ConnectViaBluetoothViewModel extends DbViewModel implements
Thread.currentThread().interrupt();
}
LOG.warning("Failed to connect");
state.postEvent(new ConnectViaBluetoothState.Error(
R.string.connect_via_bluetooth_error));
showToast(R.string.toast_connect_via_bluetooth_error);
}
private void stopConnecting() {
BluetoothPlugin bluetoothPlugin = this.bluetoothPlugin;
if (bluetoothPlugin != null) {
bluetoothPlugin.stopDiscoverAndConnect();
}
}
LiveEvent<ConnectViaBluetoothState> getState() {
return state;
private void showToast(@StringRes int res) {
androidExecutor.runOnUiThread(() ->
Toast.makeText(app, res, Toast.LENGTH_LONG).show()
);
}
}

View File

@@ -0,0 +1,151 @@
package org.briarproject.briar.android.conversation;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.contact.ContactItem;
import org.briarproject.briar.android.util.ActivityLaunchers.RequestBluetoothDiscoverable;
import javax.inject.Inject;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.content.DialogInterface.BUTTON_POSITIVE;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.Objects.requireNonNull;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class BluetoothConnecterDialogFragment extends DialogFragment {
final static String TAG = BluetoothConnecterDialogFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private ConversationViewModel viewModel;
private BluetoothConnecter bluetoothConnecter;
private final ActivityResultLauncher<Integer> bluetoothDiscoverableRequest =
registerForActivityResult(new RequestBluetoothDiscoverable(),
this::onBluetoothDiscoverable);
private final ActivityResultLauncher<String> permissionRequest =
registerForActivityResult(new RequestPermission(),
this::onPermissionRequestResult);
@Override
public void onAttach(Context ctx) {
super.onAttach(ctx);
((BaseActivity) requireActivity()).getActivityComponent().inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(ConversationViewModel.class);
bluetoothConnecter = viewModel.getBluetoothConnecter();
}
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Context ctx = requireContext();
return new AlertDialog.Builder(ctx, R.style.BriarDialogTheme)
.setTitle(R.string.dialog_title_connect_via_bluetooth)
.setMessage(R.string.dialog_message_connect_via_bluetooth)
// actual listener gets set in onResume()
.setPositiveButton(R.string.start, null)
.setNegativeButton(R.string.cancel, null)
.setCancelable(false) // keep it open until dismissed
.create();
}
@Override
public void onStart() {
super.onStart();
bluetoothConnecter.reset();
if (bluetoothConnecter.isBluetoothNotSupported()) {
showToast(R.string.toast_connect_via_bluetooth_error);
dismiss();
return;
}
// MenuItem only gets enabled after contactItem has loaded
ContactItem contact =
requireNonNull(viewModel.getContactItem().getValue());
ContactId contactId = contact.getContact().getId();
if (bluetoothConnecter.isConnectedViaBluetooth(contactId)) {
showToast(R.string.toast_connect_via_bluetooth_success);
dismiss();
return;
}
if (bluetoothConnecter.isDiscovering()) {
showToast(R.string.toast_connect_via_bluetooth_already_discovering);
dismiss();
}
}
@Override
public void onResume() {
super.onResume();
// Set the click listener for the START button here
// to prevent it from automatically dismissing the dialog.
// The dialog is shown in onStart(), so we set the listener here later.
AlertDialog dialog = (AlertDialog) getDialog();
Button positiveButton = dialog.getButton(BUTTON_POSITIVE);
positiveButton.setOnClickListener(this::onStartClicked);
}
private void onStartClicked(View v) {
// The dialog starts a permission request which comes back as true
// if the permission is already granted.
// So we can use the request as a generic entry point to the whole flow.
permissionRequest.launch(ACCESS_FINE_LOCATION);
}
private void onPermissionRequestResult(@Nullable Boolean result) {
Activity a = requireActivity();
// update permission result in BluetoothConnecter
bluetoothConnecter.onLocationPermissionResult(a, result);
// what to do when the user denies granting the location permission
Runnable onLocationPermissionDenied = () -> {
Toast.makeText(requireContext(),
R.string.toast_connect_via_bluetooth_no_location_permission,
LENGTH_LONG).show();
dismiss();
};
// if requirements are fulfilled, request Bluetooth discoverability
if (bluetoothConnecter.areRequirementsFulfilled(a, permissionRequest,
onLocationPermissionDenied)) {
bluetoothDiscoverableRequest.launch(120); // for 2min
}
}
private void onBluetoothDiscoverable(@Nullable Boolean result) {
if (result != null && result) {
// MenuItem only gets enabled after contactItem has loaded
ContactItem contact =
requireNonNull(viewModel.getContactItem().getValue());
bluetoothConnecter.onBluetoothDiscoverable(contact);
dismiss();
} else {
showToast(R.string.toast_connect_via_bluetooth_not_discoverable);
}
}
private void showToast(@StringRes int stringRes) {
Toast.makeText(requireContext(), stringRes, LENGTH_LONG).show();
}
}

View File

@@ -48,7 +48,6 @@ import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.attachment.AttachmentItem;
import org.briarproject.briar.android.attachment.AttachmentRetriever;
import org.briarproject.briar.android.blog.BlogActivity;
import org.briarproject.briar.android.contact.connect.ConnectViaBluetoothActivity;
import org.briarproject.briar.android.conversation.ConversationVisitor.AttachmentCache;
import org.briarproject.briar.android.conversation.ConversationVisitor.TextCache;
import org.briarproject.briar.android.forum.ForumActivity;
@@ -105,6 +104,7 @@ import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
@@ -379,8 +379,11 @@ public class ConversationActivity extends BriarActivity
this::showIntroductionOnboarding);
}
});
if (!featureFlags.shouldEnableConnectViaBluetooth()) {
menu.findItem(R.id.action_connect_via_bluetooth).setVisible(false);
}
// Transfer Data feature only supported on API 19+
if (SDK_INT >= 19) {
if (SDK_INT >= 19 && featureFlags.shouldEnableTransferData()) {
menu.findItem(R.id.action_transfer_data).setVisible(true);
}
// enable alias and bluetooth action once available
@@ -419,9 +422,9 @@ public class ConversationActivity extends BriarActivity
onAutoDeleteTimerNoticeClicked();
return true;
} else if (itemId == R.id.action_connect_via_bluetooth) {
Intent intent = new Intent(this, ConnectViaBluetoothActivity.class);
intent.putExtra(CONTACT_ID, contactId.getInt());
startActivity(intent);
FragmentManager fm = getSupportFragmentManager();
new BluetoothConnecterDialogFragment().show(fm,
BluetoothConnecterDialogFragment.TAG);
return true;
} else if (itemId == R.id.action_transfer_data) {
Intent intent = new Intent(this, RemovableDriveActivity.class);

View File

@@ -101,6 +101,7 @@ public class ConversationViewModel extends DbViewModel
private final AttachmentCreator attachmentCreator;
private final AutoDeleteManager autoDeleteManager;
private final ConversationManager conversationManager;
private final BluetoothConnecter bluetoothConnecter;
@Nullable
private ContactId contactId = null;
@@ -139,7 +140,8 @@ public class ConversationViewModel extends DbViewModel
AttachmentRetriever attachmentRetriever,
AttachmentCreator attachmentCreator,
AutoDeleteManager autoDeleteManager,
ConversationManager conversationManager) {
ConversationManager conversationManager,
BluetoothConnecter bluetoothConnecter) {
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
this.db = db;
this.eventBus = eventBus;
@@ -152,6 +154,7 @@ public class ConversationViewModel extends DbViewModel
this.attachmentCreator = attachmentCreator;
this.autoDeleteManager = autoDeleteManager;
this.conversationManager = conversationManager;
this.bluetoothConnecter = bluetoothConnecter;
messagingGroupId = map(contactItem, c ->
messagingManager.getContactGroup(c.getContact()).getId());
eventBus.addListener(this);
@@ -411,6 +414,10 @@ public class ConversationViewModel extends DbViewModel
return attachmentRetriever;
}
BluetoothConnecter getBluetoothConnecter() {
return bluetoothConnecter;
}
LiveData<ContactItem> getContactItem() {
return contactItem;
}

View File

@@ -25,7 +25,6 @@ import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.Fragment;
import static android.view.View.FOCUS_DOWN;
import static android.view.View.GONE;
/**
* A fragment to be used at the end of a user flow
@@ -82,12 +81,7 @@ public class FinalFragment extends Fragment {
int color = getResources().getColor(args.getInt(ARG_ICON_TINT));
ColorStateList tint = ColorStateList.valueOf(color);
ImageViewCompat.setImageTintList(iconView, tint);
int textRes = args.getInt(ARG_TEXT);
if (textRes == 0) {
textView.setVisibility(GONE);
} else {
textView.setText(textRes);
}
textView.setText(args.getInt(ARG_TEXT));
buttonView.setOnClickListener(view -> onBackButtonPressed());

View File

@@ -24,7 +24,7 @@ import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.R;
import org.briarproject.briar.android.hotspot.HotspotState.NetworkConfig;
import org.briarproject.briar.android.qrcode.QrCodeUtils;
import org.briarproject.briar.android.util.QrCodeUtils;
import java.security.SecureRandom;
import java.util.concurrent.Executor;
@@ -52,7 +52,6 @@ import static java.util.Objects.requireNonNull;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.qrcode.QrCodeUtils.HOTSPOT_QRCODE_FACTOR;
import static org.briarproject.briar.android.util.UiUtils.handleException;
@MethodsNotNullByDefault
@@ -335,8 +334,7 @@ class HotspotManager {
ioExecutor.execute(() -> {
String content = createWifiLoginString(group.getNetworkName(),
group.getPassphrase());
Bitmap qrCode = QrCodeUtils.createQrCode(
(int) (dm.heightPixels * HOTSPOT_QRCODE_FACTOR), content);
Bitmap qrCode = QrCodeUtils.createQrCode(dm, content);
NetworkConfig config = new NetworkConfig(group.getNetworkName(),
group.getPassphrase(), qrCode);
listener.onHotspotStarted(config);
@@ -439,8 +437,9 @@ class HotspotManager {
return "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;";
}
// exclude chars that are easy to confuse: 0 (O), 5 (S), 1 l (I)
private static final String chars = "2346789abcdefghijkmnopqrstuvwxyz";
// exclude chars that are easy to confuse: 0 O, 5 S, 1 l I
private static final String chars =
"2346789ABCDEFGHJKLMNPQRTUVWXYZabcdefghijkmnopqrstuvwxyz";
private String getRandomString(int length) {
char[] c = new char[length];

View File

@@ -8,7 +8,7 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.android.hotspot.HotspotState.WebsiteConfig;
import org.briarproject.briar.android.qrcode.QrCodeUtils;
import org.briarproject.briar.android.util.QrCodeUtils;
import java.io.IOException;
import java.net.InetAddress;
@@ -27,7 +27,6 @@ import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces;
import static org.briarproject.briar.android.hotspot.WebServer.PORT;
import static org.briarproject.briar.android.qrcode.QrCodeUtils.HOTSPOT_QRCODE_FACTOR;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -84,8 +83,7 @@ class WebServerManager {
}
url = "http://" + address.getHostAddress() + ":" + PORT;
}
Bitmap qrCode = QrCodeUtils.createQrCode(
(int) (dm.heightPixels * HOTSPOT_QRCODE_FACTOR), url);
Bitmap qrCode = QrCodeUtils.createQrCode(dm, url);
listener.onWebServerStarted(new WebsiteConfig(url, qrCode));
}

View File

@@ -1,9 +1,10 @@
package org.briarproject.bramble.logging;
package org.briarproject.briar.android.logging;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.Formatter;
@@ -17,6 +18,16 @@ import static java.util.Locale.US;
@NotNullByDefault
public class BriefLogFormatter extends Formatter {
public static String formatLog(Formatter formatter,
Collection<LogRecord> logRecords) {
StringBuilder sb = new StringBuilder();
for (LogRecord record : logRecords) {
String formatted = formatter.format(record);
sb.append(formatted).append('\n');
}
return sb.toString();
}
private final Object lock = new Object();
private final DateFormat dateFormat; // Locking: lock
private final Date date; // Locking: lock

View File

@@ -8,9 +8,8 @@ import androidx.annotation.Nullable;
@NotNullByDefault
public interface LogDecrypter {
/**
* Returns decrypted log records from
* {@link AndroidUtils#getTemporaryLogFile} or null if there was an error
* reading the logs.
* Returns decrypted log records from {@link AndroidUtils#getLogcatFile}
* or null if there was an error reading the logs.
*/
@Nullable
String decryptLogs(@Nullable byte[] logKey);

View File

@@ -41,7 +41,7 @@ class LogDecrypterImpl implements LogDecrypter {
public String decryptLogs(@Nullable byte[] logKey) {
if (logKey == null) return null;
SecretKey key = new SecretKey(logKey);
File logFile = devConfig.getTemporaryLogFile();
File logFile = devConfig.getLogcatFile();
try (InputStream in = new FileInputStream(logFile)) {
InputStream reader =
streamReaderFactory.createLogStreamReader(in, key);

View File

@@ -8,7 +8,7 @@ import androidx.annotation.Nullable;
@NotNullByDefault
public interface LogEncrypter {
/**
* Writes encrypted log records to {@link AndroidUtils#getTemporaryLogFile}
* Writes encrypted log records to {@link AndroidUtils#getLogcatFile}
* and returns the encryption key if everything went fine.
*/
@Nullable

View File

@@ -33,19 +33,16 @@ class LogEncrypterImpl implements LogEncrypter {
private final DevConfig devConfig;
private final CachingLogHandler logHandler;
private final Formatter formatter;
private final CryptoComponent crypto;
private final StreamWriterFactory streamWriterFactory;
@Inject
LogEncrypterImpl(DevConfig devConfig,
CachingLogHandler logHandler,
Formatter formatter,
CryptoComponent crypto,
StreamWriterFactory streamWriterFactory) {
this.devConfig = devConfig;
this.logHandler = logHandler;
this.formatter = formatter;
this.crypto = crypto;
this.streamWriterFactory = streamWriterFactory;
}
@@ -54,7 +51,7 @@ class LogEncrypterImpl implements LogEncrypter {
@Override
public byte[] encryptLogs() {
SecretKey logKey = crypto.generateSecretKey();
File logFile = devConfig.getTemporaryLogFile();
File logFile = devConfig.getLogcatFile();
try (OutputStream out = new FileOutputStream(logFile)) {
StreamWriter streamWriter =
streamWriterFactory.createLogStreamWriter(out, logKey);
@@ -70,8 +67,10 @@ class LogEncrypterImpl implements LogEncrypter {
}
private void writeLogString(Writer writer) throws IOException {
Formatter formatter = new BriefLogFormatter();
for (LogRecord record : logHandler.getRecentLogRecords()) {
writer.append(formatter.format(record)).append('\n');
String formatted = formatter.format(record);
writer.append(formatted).append('\n');
}
}

View File

@@ -1,19 +0,0 @@
package org.briarproject.briar.android.mailbox;
import org.briarproject.briar.android.viewmodel.ViewModelKey;
import androidx.lifecycle.ViewModel;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public interface MailboxModule {
@Binds
@IntoMap
@ViewModelKey(MailboxPairViewModel.class)
ViewModel bindMailboxViewModel(
MailboxPairViewModel mailboxPairViewModel);
}

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