Compare commits

..

1 Commits

Author SHA1 Message Date
akwizgran
b9e088b054 Upgrade onionwrapper to 0.0.3. 2023-05-17 12:47:32 +01:00
263 changed files with 2757 additions and 7893 deletions

View File

@@ -7,7 +7,6 @@ stages:
variables:
GIT_SUBMODULE_STRATEGY: recursive
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
workflow:
# when to create a CI pipeline

View File

@@ -28,11 +28,15 @@
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<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" />
</JetCodeStyleSettings>
<codeStyleSettings language="Groovy">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>

View File

@@ -1,7 +1,7 @@
# Briar
Briar is a messaging app designed for activists, journalists, and anyone else who needs a safe, easy and robust way to communicate.
Unlike traditional messaging apps, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices.
Unlike traditional messaging tools such as email, Twitter or Telegram, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices.
If the Internet's down, Briar can sync via Bluetooth or Wi-Fi, keeping information flowing in a crisis. If the Internet's up, Briar can sync via the Tor network, protecting users and their relationships from surveillance.
@@ -14,16 +14,14 @@ You can also [download the APK file](https://briarproject.org/apk) directly from
our site.
## Useful links
[Project website](https://briarproject.org/)
[briarproject.org](https://briarproject.org/)
[Source code](https://code.briarproject.org/briar/briar/tree/master)
[User manual](https://briarproject.org/manual/)
[Manual](https://briarproject.org/manual/)
[Wiki](https://code.briarproject.org/briar/briar/-/wikis/home)
[Privacy policy](https://briarproject.org/privacy)
## Reproducible builds
We provide [docker images](https://code.briarproject.org/briar/briar-reproducer#briar-reproducer)
@@ -35,5 +33,5 @@ for reproduction.
## Donate
[![Donate using Liberapay](https://briarproject.org/img/liberapay.svg)](https://liberapay.com/Briar/donate)
[![Donate using Liberapay](https://briarproject.org/img/liberapay.svg)](https://liberapay.com/Briar/donate) [![Flattr this](https://briarproject.org/img/flattr-badge-large.png "Flattr this")](https://flattr.com/t/592836/)
Bitcoin and BCH: 1NZCKkUCtJV2U2Y9hDb9uq8S7ksFCFGR6K

View File

@@ -3,8 +3,8 @@ apply plugin: 'witness'
apply from: 'witness.gradle'
android {
compileSdkVersion 34
buildToolsVersion '34.0.0'
compileSdkVersion 33
buildToolsVersion '33.0.0'
packagingOptions {
doNotStrip '**/*.so'
@@ -12,9 +12,9 @@ android {
defaultConfig {
minSdkVersion 21
targetSdkVersion 33
versionCode 10514
versionName "1.5.14"
targetSdkVersion 31
versionCode 10501
versionName "1.5.1"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -40,7 +40,7 @@ configurations {
}
dependencies {
api 'org.briarproject:dont-kill-me-lib:0.2.8'
api 'org.briarproject:dont-kill-me-lib:0.2.7'
// In theory this dependency shouldn't be needed, but without it Android Studio's linter will
// complain about unresolved symbols for bramble-api test classes in bramble-android tests,
@@ -54,7 +54,8 @@ dependencies {
implementation "org.briarproject:onionwrapper-android:$onionwrapper_version"
tor "org.briarproject:tor-android:$tor_version"
tor "org.briarproject:lyrebird-android:$lyrebird_version"
tor "org.briarproject:obfs4proxy-android:$obfs4proxy_version"
tor "org.briarproject:snowflake-android:$snowflake_version"
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"

View File

@@ -8,8 +8,10 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- The BLUETOOTH permission was supposed to be removed in API 31 but is still needed on some Xiaomi/Redmi/POCO devices running API 31 and Nubia devices running API 32/33 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- The BLUETOOTH permission was supposed to be removed in API 31 but is still needed on some Xiaomi/Redmi/POCO devices running API 31 and Nubia devices running API 32 -->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="32" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />

View File

@@ -5,7 +5,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.PowerManager;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.battery.event.BatteryEvent;
@@ -17,20 +16,12 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import androidx.annotation.RequiresApi;
import static android.content.Intent.ACTION_BATTERY_CHANGED;
import static android.content.Intent.ACTION_POWER_CONNECTED;
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
import static android.os.BatteryManager.EXTRA_PLUGGED;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED;
import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGED;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
class AndroidBatteryManager implements BatteryManager, Service {
@@ -53,7 +44,7 @@ class AndroidBatteryManager implements BatteryManager, Service {
public boolean isCharging() {
// Get the sticky intent for ACTION_BATTERY_CHANGED
IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED);
Intent i = registerReceiver(appContext, null, filter);
Intent i = appContext.registerReceiver(null, filter);
if (i == null) return false;
int status = i.getIntExtra(EXTRA_PLUGGED, 0);
return status != 0;
@@ -66,13 +57,7 @@ class AndroidBatteryManager implements BatteryManager, Service {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_POWER_CONNECTED);
filter.addAction(ACTION_POWER_DISCONNECTED);
filter.addAction(ACTION_POWER_SAVE_MODE_CHANGED);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
if (SDK_INT >= 33) {
filter.addAction(ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED);
filter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED);
}
registerReceiver(appContext, batteryReceiver, filter);
appContext.registerReceiver(batteryReceiver, filter);
}
@Override
@@ -91,33 +76,6 @@ class AndroidBatteryManager implements BatteryManager, Service {
eventBus.broadcast(new BatteryEvent(true));
else if (ACTION_POWER_DISCONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(false));
else if (SDK_INT >= 23 &&
ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action) &&
LOG.isLoggable(INFO)) {
LOG.info("Device idle mode changed to: " +
getPowerManager(ctx).isDeviceIdleMode());
} else if (SDK_INT >= 23 &&
ACTION_POWER_SAVE_MODE_CHANGED.equals(action) &&
LOG.isLoggable(INFO)) {
LOG.info("Power save mode changed to: " +
getPowerManager(ctx).isPowerSaveMode());
} else if (SDK_INT >= 33 && LOG.isLoggable(INFO) &&
ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED.equals(action)) {
PowerManager powerManager =
ctx.getSystemService(PowerManager.class);
LOG.info("Low power standby now is: " +
powerManager.isLowPowerStandbyEnabled());
} else if (SDK_INT >= 33 && LOG.isLoggable(INFO) &&
ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED.equals(action)) {
PowerManager powerManager = getPowerManager(ctx);
LOG.info("Light idle mode now is: " +
powerManager.isDeviceLightIdleMode());
}
}
}
@RequiresApi(api = 23)
private PowerManager getPowerManager(Context ctx) {
return ctx.getSystemService(PowerManager.class);
}
}

View File

@@ -55,7 +55,6 @@ import static java.util.concurrent.TimeUnit.SECONDS;
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.registerReceiver;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
@@ -104,7 +103,7 @@ class AndroidNetworkManager implements NetworkManager, Service {
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
filter.addAction(WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
registerReceiver(app, networkStateReceiver, filter);
app.registerReceiver(networkStateReceiver, filter);
}
@Override

View File

@@ -56,7 +56,6 @@ 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.hasBtConnectPermission;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@@ -113,7 +112,7 @@ class AndroidBluetoothPlugin extends
filter.addAction(ACTION_STATE_CHANGED);
filter.addAction(ACTION_SCAN_MODE_CHANGED);
receiver = new BluetoothStateReceiver();
registerReceiver(app, receiver, filter);
app.registerReceiver(receiver, filter);
}
@Override
@@ -238,7 +237,7 @@ class AndroidBluetoothPlugin extends
filter.addAction(ACTION_DISCOVERY_STARTED);
filter.addAction(ACTION_DISCOVERY_FINISHED);
filter.addAction(ACTION_FOUND);
registerReceiver(app, receiver, filter);
app.registerReceiver(receiver, filter);
try {
if (adapter.startDiscovery()) {
long now = clock.currentTimeMillis();

View File

@@ -201,7 +201,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
@Nullable
private InetAddress getIpv6AddressForInterface(InetAddress ipv4) {
try {
// We may get an NPE from getByInetAddress() on Android 11
NetworkInterface iface = NetworkInterface.getByInetAddress(ipv4);
if (iface == null) return null;
for (InetAddress addr : list(iface.getInetAddresses())) {
@@ -209,7 +208,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
}
// No suitable address
return null;
} catch (SocketException | NullPointerException e) {
} catch (SocketException e) {
logException(LOG, WARNING, e);
return null;
}

View File

@@ -31,6 +31,7 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import javax.net.SocketFactory;
import static android.os.Build.VERSION.SDK_INT;
import static org.briarproject.bramble.util.AndroidUtils.getSupportedArchitectures;
@Immutable
@@ -85,10 +86,15 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
TorWrapper tor = new AndroidTorWrapper(app, wakeLockManager,
ioExecutor, eventExecutor, architecture, torDirectory,
torSocksPort, torControlPort);
// Android versions 7.1 and newer can verify Let's Encrypt TLS certs
// signed with the IdentTrust DST Root X3 certificate. Older versions
// of Android consider the certificate to have expired at the end of
// September 2021.
boolean canVerifyLetsEncryptCerts = SDK_INT >= 25;
return new TorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory,
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, tor, callback, MAX_LATENCY,
MAX_IDLE_TIME);
MAX_IDLE_TIME, canVerifyLetsEncryptCerts);
}
}

View File

@@ -2,10 +2,7 @@ package org.briarproject.bramble.util;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Looper;
import android.provider.Settings;
@@ -24,7 +21,6 @@ import javax.annotation.Nullable;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.RECEIVER_NOT_EXPORTED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Process.myPid;
@@ -67,17 +63,10 @@ public class AndroidUtils {
return new Pair<>(address, "adapter");
}
// Return the address from settings if it's valid and not fake
if (SDK_INT < 33) {
try {
address = Settings.Secure.getString(ctx.getContentResolver(),
"bluetooth_address");
if (isValidBluetoothAddress(address)) {
return new Pair<>(address, "settings");
}
} catch (SecurityException e) {
// Some custom ROMs throw this exception on SDK_INT < 33.
// Fall through
}
address = Settings.Secure.getString(ctx.getContentResolver(),
"bluetooth_address");
if (isValidBluetoothAddress(address)) {
return new Pair<>(address, "settings");
}
// Try to get the address via reflection
address = getBluetoothAddressByReflection(adapter);
@@ -145,20 +134,4 @@ public class AndroidUtils {
}
return flags;
}
/**
* Could be replaced to a similar call in ContextCompat once we
* use and upgrade to version 1.9.0 or higher of the AndroidX Core library.
*/
@Nullable
@SuppressLint("UnspecifiedRegisterReceiverFlag") // we specify where needed
public static Intent registerReceiver(Context ctx,
@Nullable BroadcastReceiver receiver, IntentFilter filter) {
if (SDK_INT >= 33) {
return ctx.registerReceiver(receiver, filter,
RECEIVER_NOT_EXPORTED);
} else {
return ctx.registerReceiver(receiver, filter);
}
}
}

View File

@@ -1,62 +1,67 @@
dependencyVerification {
verify = [
'androidx.annotation:annotation:1.5.0:annotation-1.5.0.jar:261fb7c0210858500bab66d34354972a75166ab4182add283780b05513d6ec4a',
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'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.dagger:dagger-compiler:2.51.1:dagger-compiler-2.51.1.jar:14cf2def1c4c8cd3b977840e297b463191d537cd1c8330992ca5c0b341a641ad',
'com.google.dagger:dagger-spi:2.51.1:dagger-spi-2.51.1.jar:deb52030b92b27c5dcd76b2c0747f1cf105b60939f6073b43eb06cfe7c9ba601',
'com.google.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d',
'com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14:symbol-processing-api-1.9.20-1.0.14.jar:d0339396f40dc9eb3b3f7bc86257f93869ee23448fa31ec4a1de900c6b7ae6d7',
'com.google.errorprone:error_prone_annotations:2.23.0:error_prone_annotations-2.23.0.jar:ec6f39f068b6ff9ac323c68e28b9299f8c0a80ca512dccb1d4a70f40ac3ec054',
'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.2:failureaccess-1.0.2.jar:8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064',
'com.google.guava:guava:33.0.0-jre:guava-33.0.0-jre.jar:f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'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:dont-kill-me-lib:0.2.8:dont-kill-me-lib-0.2.8.aar:e21173e480ee3f2364c142cc14db8dc6447be91bde9e62e4985c485ea0af9126',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:lyrebird-android:0.5.0-3:lyrebird-android-0.5.0-3.jar:67e21cbbfda0b17ab9e0741ada170c606ddda4e9548a70c421aa83b907ebb714',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-android:0.1.3:onionwrapper-android-0.1.3.aar:15231f0b2ad44df8eb1dd362a989ba3f88ebdc9b02a9128daa72a8da83651bf0',
'org.briarproject:onionwrapper-core:0.1.3:onionwrapper-core-0.1.3.jar:32d08c9d81a9591e08d7e64e3569334fee21f503b00514006f2e6cbbd409d0df',
'org.briarproject:tor-android:0.4.8.14:tor-android-0.4.8.14.jar:fc7c4f5007a98132ba84534a873f101951d2d554d5da5f2031b85c277f8617a6',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.41.0:checker-qual-3.41.0.jar:2f9f245bf68e4259d610894f2406dc1f6363dc639302bd566e8272e4f4541172',
'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.7:org.jacoco.agent-0.8.7.jar:9cbcc986e0fbe821a78ff1f8f7d5216f200e5eb124e7f6837d1dc4a77b28b143',
'org.jacoco:org.jacoco.ant:0.8.7:org.jacoco.ant-0.8.7.jar:97ca96a382c3f23a44d8eb4c4e6c3742a30cb8005774a76ced0fc4806ce49605',
'org.jacoco:org.jacoco.core:0.8.7:org.jacoco.core-0.8.7.jar:ad7739b5fb5969aa1a8aead3d74ed54dc82ed012f1f10f336bd1b96e71c1a13c',
'org.jacoco:org.jacoco.report:0.8.7:org.jacoco.report-0.8.7.jar:cc89258623700a6c932592153cb528785876b6da183d5431f97efbba6f020e5b',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10:kotlin-stdlib-common-1.9.10.jar:cde3341ba18a2ba262b0b7cf6c55b20c90e8d434e42c9a13e6a3f770db965a88',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0:kotlin-stdlib-jdk7-1.9.0.jar:b7979a7aac94055f0d9f1fd3b47ce5ffe1cb6032a842ba9fbe7186f085289178',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10:kotlin-stdlib-jdk7-1.9.10.jar:ac6361bf9ad1ed382c2103d9712c47cdec166232b4903ed596e8876b0681c9b7',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0:kotlin-stdlib-jdk8-1.9.0.jar:a59fa24fdf1ffb594baecdbf0fd10010f977cea10236d487fe3464977a7377fa',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.10:kotlin-stdlib-1.9.10.jar:55e989c512b80907799f854309f3bc7782c5b3d13932442d0379d5c472711504',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.20:kotlin-stdlib-1.9.20.jar:28a35bcdff46d864f80f346a617e486284b208d17378c41900dfb1de95a90e6c',
'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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-analysis:9.1:asm-analysis-9.1.jar:81a88041b1b8beda5a8a99646098046c48709538270c49def68abff25ac3be34',
'org.ow2.asm:asm-commons:9.1:asm-commons-9.1.jar:afcb26dc1fc12c0c4a99ada670908dd82e18dfc488caf5ee92546996b470c00c',
'org.ow2.asm:asm-tree:9.1:asm-tree-9.1.jar:fd00afa49e9595d7646205b09cecb4a776a8ff0ba06f2d59b8f7bf9c704b4a73',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
]
verify = [
'androidx.annotation:annotation:1.5.0:annotation-1.5.0.jar:261fb7c0210858500bab66d34354972a75166ab4182add283780b05513d6ec4a',
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'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.dagger:dagger-compiler:2.45:dagger-compiler-2.45.jar:5617dfb994537dba5b41f3744a6dd13ec3cd99789c065e0d5c6fa9f21cf7ca25',
'com.google.dagger:dagger-producers:2.45:dagger-producers-2.45.jar:a05abb4c3ccf6bb0f056bdcb5ef973898ecf172952ab5948a824aeea6c86ecaa',
'com.google.dagger:dagger-spi:2.45:dagger-spi-2.45.jar:7cd6f0b09d88e64a9c97bc80e544ab8ac8fdee9301754413585a74cf64222b27',
'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
'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:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
'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.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'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:dont-kill-me-lib:0.2.7:dont-kill-me-lib-0.2.7.aar:8a9540941fd927e1c127096a7a9b4aa61ce2f2965d2e24f849be92f9e57213c4',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:obfs4proxy-android:0.0.14-tor2:obfs4proxy-android-0.0.14-tor2.jar:a0a93770d6760ce57d9dbd31cc7177687374e00c3361dac22ab75e3b6e0f289e',
'org.briarproject:onionwrapper-android:0.0.3:onionwrapper-android-0.0.3.aar:d761854dac454616b3e0ca099b2cd17060365ce4316afe495cc7ae86b6c81d15',
'org.briarproject:onionwrapper-core:0.0.3:onionwrapper-core-0.0.3.jar:2645dd7e4f2e73fc2ba30696aeac4c960ef8b8f405d85e529fdf8b105ef374f1',
'org.briarproject:snowflake-android:2.5.1:snowflake-android-2.5.1.jar:88ec81c17b1b6fa884d06839dec0330e328b45c89f88c970a213ce91ca8eac87',
'org.briarproject:tor-android:0.4.7.13-2:tor-android-0.4.7.13-2.jar:453fd463b234a2104edd7f0d02d0649cbb5c5efbe47a76df3828f55a3f90f8b5',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
'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.7:org.jacoco.agent-0.8.7.jar:9cbcc986e0fbe821a78ff1f8f7d5216f200e5eb124e7f6837d1dc4a77b28b143',
'org.jacoco:org.jacoco.ant:0.8.7:org.jacoco.ant-0.8.7.jar:97ca96a382c3f23a44d8eb4c4e6c3742a30cb8005774a76ced0fc4806ce49605',
'org.jacoco:org.jacoco.core:0.8.7:org.jacoco.core-0.8.7.jar:ad7739b5fb5969aa1a8aead3d74ed54dc82ed012f1f10f336bd1b96e71c1a13c',
'org.jacoco:org.jacoco.report:0.8.7:org.jacoco.report-0.8.7.jar:cc89258623700a6c932592153cb528785876b6da183d5431f97efbba6f020e5b',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0:kotlin-stdlib-common-1.8.0.jar:78ef93b59e603cc0fe51def9bd4c037b07cbace3b3b7806d1a490a42bc1f4cb2',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0:kotlin-stdlib-jdk7-1.8.0.jar:4c889d1d9803f5f2eb6c1592a6b7e62369ac7660c9eee15aba16fec059163666',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
'org.jetbrains.kotlin:kotlin-stdlib:1.8.0:kotlin-stdlib-1.8.0.jar:c77bef8774640b9fb9d6e217459ff220dae59878beb7d2e4b430506feffc654e',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
'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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-analysis:9.1:asm-analysis-9.1.jar:81a88041b1b8beda5a8a99646098046c48709538270c49def68abff25ac3be34',
'org.ow2.asm:asm-commons:9.1:asm-commons-9.1.jar:afcb26dc1fc12c0c4a99ada670908dd82e18dfc488caf5ee92546996b470c00c',
'org.ow2.asm:asm-tree:9.1:asm-tree-9.1.jar:fd00afa49e9595d7646205b09cecb4a776a8ff0ba06f2d59b8f7bf9c704b4a73',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
]
}

View File

@@ -31,12 +31,6 @@ public abstract class BdfMessageValidator implements MessageValidator {
protected final Clock clock;
protected final boolean canonical;
/**
* Transitional alternative to
* {@link #BdfMessageValidator(ClientHelper, MetadataEncoder, Clock)} that
* accepts messages in non-canonical form, for backward compatibility.
*/
@Deprecated
protected BdfMessageValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock, boolean canonical) {
this.clientHelper = clientHelper;

View File

@@ -49,15 +49,6 @@ public interface ClientHelper {
BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException,
FormatException;
/**
* Transitional alternative to
* {@link #getMessageAsList(Transaction, MessageId)} that allows the
* message to be in non-canonical form, for backward compatibility.
*
* @param canonical True if the message must be in canonical form (a
* {@link FormatException} will be thrown if it's not.
*/
@Deprecated
BdfList getMessageAsList(Transaction txn, MessageId m, boolean canonical)
throws DbException, FormatException;
@@ -118,14 +109,6 @@ public interface ClientHelper {
BdfList toList(Message m) throws FormatException;
/**
* Transitional alternative to {@link #toList(Message)} that allows the
* message to be in non-canonical form, for backward compatibility.
*
* @param canonical True if the message must be in canonical form (a
* {@link FormatException} will be thrown if it's not.
*/
@Deprecated
BdfList toList(Message m, boolean canonical) throws FormatException;
BdfList toList(Author a);

View File

@@ -54,38 +54,6 @@ public interface CryptoComponent {
KeyPair ourKeyPair, byte[]... inputs)
throws GeneralSecurityException;
/**
* Derives a shared secret from two static and two ephemeral key pairs.
* <p>
* Do not use this method for new protocols. The shared secret can be
* re-derived using the ephemeral public keys and both static private
* keys, so keys derived from the shared secret should not be used if
* forward secrecy is required. Use {@link #deriveSharedSecret(String,
* PublicKey, PublicKey, KeyPair, KeyPair, boolean, byte[]...)} instead.
* <p>
* TODO: Remove this after a reasonable migration period (added 2023-03-10).
* <p>
*
* @param label A namespaced label indicating the purpose of this shared
* secret, to prevent it from being repurposed or colliding with a shared
* secret derived for another purpose
* @param theirStaticPublicKey The static public key of the remote party
* @param theirEphemeralPublicKey The ephemeral public key of the remote
* party
* @param ourStaticKeyPair The static key pair of the local party
* @param ourEphemeralKeyPair The ephemeral key pair of the local party
* @param alice True if the local party is Alice
* @param inputs Additional inputs that will be included in the
* derivation of the shared secret
* @return The shared secret
*/
@Deprecated
SecretKey deriveSharedSecretBadly(String label,
PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey,
KeyPair ourStaticKeyPair, KeyPair ourEphemeralKeyPair,
boolean alice, byte[]... inputs)
throws GeneralSecurityException;
/**
* Derives a shared secret from two static and two ephemeral key pairs.
*

View File

@@ -10,27 +10,6 @@ import java.util.TreeMap;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
/**
* A BDF dictionary contains zero or more key-value pairs, where the keys
* are strings and the values are BDF objects, which may be primitive types
* (null, boolean, integer, float, string, raw) or nested containers (list,
* dictionary).
* <p>
* Note that a BDF integer has the same range as a Java long, while a BDF
* float has the same range as a Java double. Method names in this class
* correspond to the Java types.
* <p>
* The getX() methods throw {@link FormatException} if the specified key is
* absent, the value is null, or the value does not have the requested type.
* <p>
* The getOptionalX() methods return null if the specified key is absent or
* the value is null, or throw {@link FormatException} if the value does not
* have the requested type.
* <p>
* The getX() methods that take a default value return the default value if
* the specified key is absent or the value is null, or throw
* {@link FormatException} if the value does not have the requested type.
*/
@NotThreadSafe
public final class BdfDictionary extends TreeMap<String, Object> {
@@ -101,33 +80,12 @@ public final class BdfDictionary extends TreeMap<String, Object> {
return value == null ? defaultValue : value;
}
/**
* Returns the integer with the specified key.
* <p>
* This method should be used in preference to
* <code>getLong(key).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if there is no value at the specified key,
* or if the value is null or cannot be represented as a Java int.
*/
public Integer getInt(String key) throws FormatException {
Integer value = getOptionalInt(key);
if (value == null) throw new FormatException();
return value;
}
/**
* Returns the integer with the specified key, or null if the key is
* absent or the value is null.
* <p>
* This method should be used in preference to
* <code>getOptionalLong(key).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the value at the specified key is not null
* and cannot be represented as a Java int.
*/
@Nullable
public Integer getOptionalInt(String key) throws FormatException {
Long value = getOptionalLong(key);
@@ -138,17 +96,6 @@ public final class BdfDictionary extends TreeMap<String, Object> {
return value.intValue();
}
/**
* Returns the integer with the specified key, or the given default
* value if the key is absent or the value is null.
* <p>
* This method should be used in preference to
* <code>getLong(key, defaultValue).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the value at the specified key is not null
* and cannot be represented as a Java int.
*/
public Integer getInt(String key, Integer defaultValue)
throws FormatException {
Integer value = getOptionalInt(key);

View File

@@ -6,11 +6,6 @@ import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable;
/**
* A convenience class for building {@link BdfDictionary BdfDictionaries}
* via the {@link BdfDictionary#of(Entry[]) factory method}. Entries in
* BdfDictionaries do not have to be BdfEntries.
*/
@Immutable
@NotNullByDefault
public class BdfEntry implements Entry<String, Object>, Comparable<BdfEntry> {

View File

@@ -12,29 +12,6 @@ import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
/**
* A BDF list contains zero or more BDF objects, which may be primitive types
* (null, boolean, integer, float, string, raw) or nested containers (list,
* dictionary).
* <p>
* Note that a BDF integer has the same range as a Java long, while a BDF
* float has the same range as a Java double. Method names in this class
* correspond to the Java types.
* <p>
* The getX() methods throw {@link FormatException} if the object at the
* specified index is null or does not have the requested type.
* <p>
* The getOptionalX() methods return null if the object at the specified
* index is null, or throw {@link FormatException} if the object does not
* have the requested type.
* <p>
* The getX() methods that take a default value return the default value if
* the object at the specified index is null, or throw
* {@link FormatException} if the object does not have the requested type.
* <p>
* All of the getters throw {@link FormatException} if the specified index is
* out of range.
*/
@NotThreadSafe
public final class BdfList extends ArrayList<Object> {
@@ -105,34 +82,12 @@ public final class BdfList extends ArrayList<Object> {
return value == null ? defaultValue : value;
}
/**
* Returns the integer at the specified index.
* <p>
* This method should be used in preference to
* <code>getLong(index).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the index is out of range, or if the
* value at the specified index is null or cannot be represented as a
* Java int.
*/
public Integer getInt(int index) throws FormatException {
Integer value = getOptionalInt(index);
if (value == null) throw new FormatException();
return value;
}
/**
* Returns the integer at the specified index, or null if the object at
* the specified index is null.
* <p>
* This method should be used in preference to
* <code>getOptionalLong(index).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the index is out of range, or if the value
* at the specified index cannot be represented as a Java int.
*/
@Nullable
public Integer getOptionalInt(int index) throws FormatException {
Long value = getOptionalLong(index);
@@ -143,17 +98,6 @@ public final class BdfList extends ArrayList<Object> {
return value.intValue();
}
/**
* Returns the integer at the specified index, or the given default value
* if the object at the specified index is null.
* <p>
* This method should be used in preference to
* <code>getLong(index, defaultValue).intValue()</code> as it checks for
* overflow/underflow.
*
* @throws FormatException if the index is out of range, or if the value
* at the specified index cannot be represented as a Java int.
*/
public Integer getInt(int index, Integer defaultValue)
throws FormatException {
Integer value = getOptionalInt(index);

View File

@@ -1,178 +1,70 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
/**
* An interface for reading BDF objects from an input stream.
* <p>
* The readX() methods throw {@link FormatException} if the data is not in
* canonical form, but the hasX() and skipX() methods do not check for
* canonical form.
*/
@NotNullByDefault
public interface BdfReader {
int DEFAULT_NESTED_LIMIT = 5;
int DEFAULT_MAX_BUFFER_SIZE = 64 * 1024;
/**
* Returns true if the reader has reached the end of its input stream.
*/
boolean eof() throws IOException;
/**
* Closes the reader's input stream.
*/
void close() throws IOException;
/**
* Returns true if the next object in the input is a BDF null.
*/
boolean hasNull() throws IOException;
/**
* Reads a BDF null from the input.
*/
void readNull() throws IOException;
/**
* Skips over a BDF null.
*/
void skipNull() throws IOException;
/**
* Returns true if the next object in the input is a BDF boolean.
*/
boolean hasBoolean() throws IOException;
/**
* Reads a BDF boolean from the input and returns it.
*/
boolean readBoolean() throws IOException;
/**
* Skips over a BDF boolean.
*/
void skipBoolean() throws IOException;
/**
* Returns true if the next object in the input is a BDF integer, which
* has the same range as a Java long.
*/
boolean hasLong() throws IOException;
/**
* Reads a BDF integer from the input and returns it as a Java long.
*/
long readLong() throws IOException;
/**
* Skips over a BDF integer.
*/
void skipLong() throws IOException;
/**
* Returns true if the next object in the input is a BDF integer and the
* value would fit within the range of a Java int.
*/
boolean hasInt() throws IOException;
/**
* Reads a BDF integer from the input and returns it as a Java int.
*
* @throws FormatException if the value exceeds the range of a Java int.
*/
int readInt() throws IOException;
/**
* Skips over a BDF integer.
*
* @throws FormatException if the value exceeds the range of a Java int.
*/
void skipInt() throws IOException;
/**
* Returns true if the next object in the input is a BDF float, which has
* the same range as a Java double.
*/
boolean hasDouble() throws IOException;
/**
* Reads a BDF float from the input and returns it as a Java double.
*/
double readDouble() throws IOException;
/**
* Skips over a BDF float.
*/
void skipDouble() throws IOException;
/**
* Returns true if the next object in the input is a BDF string.
*/
boolean hasString() throws IOException;
/**
* Reads a BDF string from the input.
*
* @throws IOException If the string is not valid UTF-8.
*/
String readString() throws IOException;
/**
* Skips over a BDF string without checking whether it is valid UTF-8.
*/
void skipString() throws IOException;
/**
* Returns true if the next object in the input is a BDF raw.
*/
boolean hasRaw() throws IOException;
/**
* Reads a BDF raw from the input and returns it as a byte array.
*/
byte[] readRaw() throws IOException;
/**
* Skips over a BDF raw.
*/
void skipRaw() throws IOException;
/**
* Returns true if the next object in the input is a BDF list.
*/
boolean hasList() throws IOException;
/**
* Reads a BDF list from the input and returns it. The list's contents
* are parsed and validated.
*/
BdfList readList() throws IOException;
/**
* Skips over a BDF list. The list's contents are parsed (to determine
* their length) but not validated.
*/
void skipList() throws IOException;
/**
* Returns true if the next object in the input is a BDF dictionary.
*/
boolean hasDictionary() throws IOException;
/**
* Reads a BDF dictionary from the input and returns it. The dictionary's
* contents are parsed and validated.
*/
BdfDictionary readDictionary() throws IOException;
/**
* Skips over a BDF dictionary. The dictionary's contents are parsed
* (to determine their length) but not validated.
*/
void skipDictionary() throws IOException;
}

View File

@@ -9,12 +9,6 @@ public interface BdfReaderFactory {
BdfReader createReader(InputStream in);
/**
* Transitional alternative to {@link #createReader(InputStream)} that
* can create a reader that accepts non-canonical input, for backward
* compatibility.
*/
@Deprecated
BdfReader createReader(InputStream in, boolean canonical);
BdfReader createReader(InputStream in, int nestedLimit,

View File

@@ -1,74 +1,28 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.FormatException;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
/**
* An interface for writing BDF objects to an output stream. The BDF output
* is in canonical form, ie integers and length fields are represented using
* the minimum number of bytes and dictionary keys are unique and sorted in
* lexicographic order.
*/
public interface BdfWriter {
/**
* Flushes the writer's output stream.
*/
void flush() throws IOException;
/**
* Closes the writer's output stream.
*/
void close() throws IOException;
/**
* Writes a BDF null to the output stream.
*/
void writeNull() throws IOException;
/**
* Writes a BDF boolean to the output stream.
*/
void writeBoolean(boolean b) throws IOException;
/**
* Writes a BDF integer (which has the same range as a Java long) to the
* output stream.
*/
void writeLong(long l) throws IOException;
/**
* Writes a BDF float (which has the same range as a Java double) to the
* output stream.
*/
void writeDouble(double d) throws IOException;
/**
* Writes a BDF string (which uses UTF-8 encoding) to the output stream.
*/
void writeString(String s) throws IOException;
/**
* Writes a BDF raw to the output stream.
*/
void writeRaw(byte[] b) throws IOException;
/**
* Writes a BDF list to the output stream.
*
* @throws FormatException if the contents of the given collection cannot
* be represented as (nested) BDF objects.
*/
void writeList(Collection<?> c) throws IOException;
/**
* Writes a BDF dictionary to the output stream.
*
* @throws FormatException if the contents of the given map cannot be
* represented as (nested) BDF objects.
*/
void writeDictionary(Map<?, ?> m) throws IOException;
}

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.api.network;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@@ -28,20 +27,4 @@ public class NetworkStatus {
public boolean isIpv6Only() {
return ipv6Only;
}
@Override
public int hashCode() {
return (connected ? 1 : 0) | (wifi ? 2 : 0) | (ipv6Only ? 4 : 0);
}
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof NetworkStatus) {
NetworkStatus s = (NetworkStatus) o;
return connected == s.connected
&& wifi == s.wifi
&& ipv6Only == s.ipv6Only;
}
return false;
}
}

View File

@@ -46,7 +46,6 @@ public interface TorConstants {
/**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}.
* Currently unused, but may be worth keeping for future use.
*/
int REASON_COUNTRY_BLOCKED = 8;
}

View File

@@ -32,15 +32,8 @@ public interface RecordReader {
* 'accept' or 'ignore' predicates
*/
@Nullable
Record readRecord(RecordPredicate accept, RecordPredicate ignore)
Record readRecord(Predicate<Record> accept, Predicate<Record> ignore)
throws IOException;
void close() throws IOException;
/**
* Interface that reifies the generic interface {@code Predicate<Record>}
* for easier testing.
*/
interface RecordPredicate extends Predicate<Record> {
}
}

View File

@@ -6,7 +6,6 @@ import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Locale;
import javax.annotation.Nullable;
@@ -52,7 +51,7 @@ public class PrivacyUtils {
}
private static String scrubIpv6Address(byte[] ipv6) {
String hex = toHexString(ipv6).toLowerCase(Locale.US);
String hex = toHexString(ipv6).toLowerCase();
return hex.substring(0, 2) + "[scrubbed]" + hex.substring(30);
}

View File

@@ -1,29 +1,29 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
'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.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.22:animal-sniffer-ant-tasks-1.22.jar:3f6afeb3e09301d2d7179ed1db21e3ad8846c1e38415ad832a395138ae3f4218',
'org.codehaus.mojo:animal-sniffer:1.22:animal-sniffer-1.22.jar:f18c11a25bdd8b520b9c6a28cbb6f33007c812ab0051b6be3f0778e660aa501c',
'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.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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.3:asm-9.3.jar:1263369b59e29c943918de11d6d6152e2ec6085ce63e5710516f8c67d368e4bc',
]
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
'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.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.22:animal-sniffer-ant-tasks-1.22.jar:3f6afeb3e09301d2d7179ed1db21e3ad8846c1e38415ad832a395138ae3f4218',
'org.codehaus.mojo:animal-sniffer:1.22:animal-sniffer-1.22.jar:f18c11a25bdd8b520b9c6a28cbb6f33007c812ab0051b6be3f0778e660aa501c',
'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.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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.3:asm-9.3.jar:1263369b59e29c943918de11d6d6152e2ec6085ce63e5710516f8c67d368e4bc',
]
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactExchangeManager;
@@ -23,7 +24,6 @@ import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.api.record.RecordReaderFactory;
import org.briarproject.bramble.api.record.RecordWriter;
import org.briarproject.bramble.api.record.RecordWriterFactory;
@@ -61,12 +61,12 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
getLogger(ContactExchangeManagerImpl.class.getName());
// Accept records with current protocol version, known record type
private static final RecordPredicate ACCEPT = r ->
private static final Predicate<Record> ACCEPT = r ->
r.getProtocolVersion() == PROTOCOL_VERSION &&
isKnownRecordType(r.getRecordType());
// Ignore records with current protocol version, unknown record type
private static final RecordPredicate IGNORE = r ->
private static final Predicate<Record> IGNORE = r ->
r.getProtocolVersion() == PROTOCOL_VERSION &&
!isKnownRecordType(r.getRecordType());

View File

@@ -5,31 +5,14 @@ import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES;
interface HandshakeConstants {
/**
* The current major version of the handshake protocol.
* The current version of the handshake protocol.
*/
byte PROTOCOL_MAJOR_VERSION = 0;
byte PROTOCOL_VERSION = 0;
/**
* The current minor version of the handshake protocol.
* Label for deriving the master key.
*/
byte PROTOCOL_MINOR_VERSION = 1;
/**
* Label for deriving the master key when using the deprecated v0.0 key
* derivation method.
* <p>
* TODO: Remove this after a reasonable migration period (added 2023-03-10).
*/
@Deprecated
String MASTER_KEY_LABEL_0_0 =
"org.briarproject.bramble.handshake/MASTER_KEY";
/**
* Label for deriving the master key when using the v0.1 key derivation
* method.
*/
String MASTER_KEY_LABEL_0_1 =
"org.briarproject.bramble.handshake/MASTER_KEY_0_1";
String MASTER_KEY_LABEL = "org.briarproject.bramble.handshake/MASTER_KEY";
/**
* Label for deriving Alice's proof of ownership from the master key.

View File

@@ -13,26 +13,11 @@ interface HandshakeCrypto {
KeyPair generateEphemeralKeyPair();
/**
* Derives the master key from the given static and ephemeral keys using
* the deprecated v0.0 key derivation method.
* <p>
* TODO: Remove this after a reasonable migration period (added 2023-03-10).
* Derives the master key from the given static and ephemeral keys.
*
* @param alice Whether the local peer is Alice
*/
@Deprecated
SecretKey deriveMasterKey_0_0(PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,
KeyPair ourEphemeralKeyPair, boolean alice)
throws GeneralSecurityException;
/**
* Derives the master key from the given static and ephemeral keys using
* the v0.1 key derivation method.
*
* @param alice Whether the local peer is Alice
*/
SecretKey deriveMasterKey_0_1(PublicKey theirStaticPublicKey,
SecretKey deriveMasterKey(PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,
KeyPair ourEphemeralKeyPair, boolean alice)
throws GeneralSecurityException;

View File

@@ -13,8 +13,7 @@ import javax.inject.Inject;
import static org.briarproject.bramble.contact.HandshakeConstants.ALICE_PROOF_LABEL;
import static org.briarproject.bramble.contact.HandshakeConstants.BOB_PROOF_LABEL;
import static org.briarproject.bramble.contact.HandshakeConstants.MASTER_KEY_LABEL_0_0;
import static org.briarproject.bramble.contact.HandshakeConstants.MASTER_KEY_LABEL_0_1;
import static org.briarproject.bramble.contact.HandshakeConstants.MASTER_KEY_LABEL;
@Immutable
@NotNullByDefault
@@ -33,8 +32,7 @@ class HandshakeCryptoImpl implements HandshakeCrypto {
}
@Override
@Deprecated
public SecretKey deriveMasterKey_0_0(PublicKey theirStaticPublicKey,
public SecretKey deriveMasterKey(PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,
KeyPair ourEphemeralKeyPair, boolean alice) throws
GeneralSecurityException {
@@ -48,29 +46,9 @@ class HandshakeCryptoImpl implements HandshakeCrypto {
alice ? ourEphemeral : theirEphemeral,
alice ? theirEphemeral : ourEphemeral
};
return crypto.deriveSharedSecretBadly(MASTER_KEY_LABEL_0_0,
theirStaticPublicKey, theirEphemeralPublicKey,
ourStaticKeyPair, ourEphemeralKeyPair, alice, inputs);
}
@Override
public SecretKey deriveMasterKey_0_1(PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,
KeyPair ourEphemeralKeyPair, boolean alice) throws
GeneralSecurityException {
byte[] theirStatic = theirStaticPublicKey.getEncoded();
byte[] theirEphemeral = theirEphemeralPublicKey.getEncoded();
byte[] ourStatic = ourStaticKeyPair.getPublic().getEncoded();
byte[] ourEphemeral = ourEphemeralKeyPair.getPublic().getEncoded();
byte[][] inputs = {
alice ? ourStatic : theirStatic,
alice ? theirStatic : ourStatic,
alice ? ourEphemeral : theirEphemeral,
alice ? theirEphemeral : ourEphemeral
};
return crypto.deriveSharedSecret(MASTER_KEY_LABEL_0_1,
theirStaticPublicKey, theirEphemeralPublicKey,
ourStaticKeyPair, ourEphemeralKeyPair, alice, inputs);
return crypto.deriveSharedSecret(MASTER_KEY_LABEL, theirStaticPublicKey,
theirEphemeralPublicKey, ourStaticKeyPair, ourEphemeralKeyPair,
alice, inputs);
}
@Override

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.HandshakeManager;
import org.briarproject.bramble.api.contact.PendingContact;
@@ -11,12 +12,12 @@ import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.TransportCrypto;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.api.record.RecordReaderFactory;
import org.briarproject.bramble.api.record.RecordWriter;
import org.briarproject.bramble.api.record.RecordWriterFactory;
@@ -27,20 +28,15 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.contact.HandshakeConstants.PROOF_BYTES;
import static org.briarproject.bramble.contact.HandshakeConstants.PROTOCOL_MAJOR_VERSION;
import static org.briarproject.bramble.contact.HandshakeConstants.PROTOCOL_MINOR_VERSION;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.RECORD_TYPE_EPHEMERAL_PUBLIC_KEY;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.RECORD_TYPE_MINOR_VERSION;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.RECORD_TYPE_PROOF_OF_OWNERSHIP;
import static org.briarproject.bramble.contact.HandshakeConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.EPHEMERAL_PUBLIC_KEY;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.PROOF_OF_OWNERSHIP;
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
@Immutable
@@ -48,14 +44,12 @@ import static org.briarproject.bramble.util.ValidationUtils.checkLength;
class HandshakeManagerImpl implements HandshakeManager {
// Ignore records with current protocol version, unknown record type
private static final RecordPredicate IGNORE = r ->
r.getProtocolVersion() == PROTOCOL_MAJOR_VERSION &&
private static final Predicate<Record> IGNORE = r ->
r.getProtocolVersion() == PROTOCOL_VERSION &&
!isKnownRecordType(r.getRecordType());
private static boolean isKnownRecordType(byte type) {
return type == RECORD_TYPE_EPHEMERAL_PUBLIC_KEY ||
type == RECORD_TYPE_PROOF_OF_OWNERSHIP ||
type == RECORD_TYPE_MINOR_VERSION;
return type == EPHEMERAL_PUBLIC_KEY || type == PROOF_OF_OWNERSHIP;
}
private final TransactionManager db;
@@ -67,7 +61,7 @@ class HandshakeManagerImpl implements HandshakeManager {
private final RecordWriterFactory recordWriterFactory;
@Inject
HandshakeManagerImpl(TransactionManager db,
HandshakeManagerImpl(DatabaseComponent db,
IdentityManager identityManager,
ContactManager contactManager,
TransportCrypto transportCrypto,
@@ -101,31 +95,19 @@ class HandshakeManagerImpl implements HandshakeManager {
.createRecordWriter(out.getOutputStream());
KeyPair ourEphemeralKeyPair =
handshakeCrypto.generateEphemeralKeyPair();
Pair<Byte, PublicKey> theirMinorVersionAndKey;
PublicKey theirEphemeralPublicKey;
if (alice) {
sendMinorVersion(recordWriter);
sendPublicKey(recordWriter, ourEphemeralKeyPair.getPublic());
theirMinorVersionAndKey = receiveMinorVersionAndKey(recordReader);
theirEphemeralPublicKey = receivePublicKey(recordReader);
} else {
theirMinorVersionAndKey = receiveMinorVersionAndKey(recordReader);
sendMinorVersion(recordWriter);
theirEphemeralPublicKey = receivePublicKey(recordReader);
sendPublicKey(recordWriter, ourEphemeralKeyPair.getPublic());
}
byte theirMinorVersion = theirMinorVersionAndKey.getFirst();
PublicKey theirEphemeralPublicKey = theirMinorVersionAndKey.getSecond();
SecretKey masterKey;
try {
if (theirMinorVersion > 0) {
masterKey = handshakeCrypto.deriveMasterKey_0_1(
theirStaticPublicKey, theirEphemeralPublicKey,
ourStaticKeyPair, ourEphemeralKeyPair, alice);
} else {
// TODO: Remove this branch after a reasonable migration
// period (added 2023-03-10).
masterKey = handshakeCrypto.deriveMasterKey_0_0(
theirStaticPublicKey, theirEphemeralPublicKey,
ourStaticKeyPair, ourEphemeralKeyPair, alice);
}
masterKey = handshakeCrypto.deriveMasterKey(theirStaticPublicKey,
theirEphemeralPublicKey, ourStaticKeyPair,
ourEphemeralKeyPair, alice);
} catch (GeneralSecurityException e) {
throw new FormatException();
}
@@ -146,91 +128,34 @@ class HandshakeManagerImpl implements HandshakeManager {
}
private void sendPublicKey(RecordWriter w, PublicKey k) throws IOException {
w.writeRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_EPHEMERAL_PUBLIC_KEY, k.getEncoded()));
w.writeRecord(new Record(PROTOCOL_VERSION, EPHEMERAL_PUBLIC_KEY,
k.getEncoded()));
w.flush();
}
/**
* Receives the remote peer's protocol minor version and ephemeral public
* key.
* <p>
* In version 0.1 of the protocol, each peer sends a minor version record
* followed by an ephemeral public key record.
* <p>
* In version 0.0 of the protocol, each peer sends an ephemeral public key
* record without a preceding minor version record.
* <p>
* Therefore the remote peer's minor version must be non-zero if a minor
* version record is received, and is assumed to be zero if no minor
* version record is received.
*/
private Pair<Byte, PublicKey> receiveMinorVersionAndKey(RecordReader r)
throws IOException {
byte theirMinorVersion;
PublicKey theirEphemeralPublicKey;
// The first record can be either a minor version record or an
// ephemeral public key record
Record first = readRecord(r, asList(RECORD_TYPE_MINOR_VERSION,
RECORD_TYPE_EPHEMERAL_PUBLIC_KEY));
if (first.getRecordType() == RECORD_TYPE_MINOR_VERSION) {
// The payload must be a single byte giving the remote peer's
// protocol minor version, which must be non-zero
byte[] payload = first.getPayload();
checkLength(payload, 1);
theirMinorVersion = payload[0];
if (theirMinorVersion == 0) throw new FormatException();
// The second record must be an ephemeral public key record
Record second = readRecord(r,
singletonList(RECORD_TYPE_EPHEMERAL_PUBLIC_KEY));
theirEphemeralPublicKey = parsePublicKey(second);
} else {
// The remote peer did not send a minor version record, so the
// remote peer's protocol minor version is assumed to be zero
// TODO: Remove this branch after a reasonable migration period
// (added 2023-03-10).
theirMinorVersion = 0;
theirEphemeralPublicKey = parsePublicKey(first);
}
return new Pair<>(theirMinorVersion, theirEphemeralPublicKey);
}
private PublicKey parsePublicKey(Record rec) throws IOException {
if (rec.getRecordType() != RECORD_TYPE_EPHEMERAL_PUBLIC_KEY) {
throw new AssertionError();
}
byte[] key = rec.getPayload();
private PublicKey receivePublicKey(RecordReader r) throws IOException {
byte[] key = readRecord(r, EPHEMERAL_PUBLIC_KEY).getPayload();
checkLength(key, 1, MAX_AGREEMENT_PUBLIC_KEY_BYTES);
return new AgreementPublicKey(key);
}
private void sendProof(RecordWriter w, byte[] proof) throws IOException {
w.writeRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_PROOF_OF_OWNERSHIP, proof));
w.writeRecord(new Record(PROTOCOL_VERSION, PROOF_OF_OWNERSHIP, proof));
w.flush();
}
private byte[] receiveProof(RecordReader r) throws IOException {
Record rec = readRecord(r,
singletonList(RECORD_TYPE_PROOF_OF_OWNERSHIP));
byte[] proof = rec.getPayload();
byte[] proof = readRecord(r, PROOF_OF_OWNERSHIP).getPayload();
checkLength(proof, PROOF_BYTES, PROOF_BYTES);
return proof;
}
private void sendMinorVersion(RecordWriter w) throws IOException {
w.writeRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_MINOR_VERSION,
new byte[] {PROTOCOL_MINOR_VERSION}));
w.flush();
}
private Record readRecord(RecordReader r, List<Byte> expectedTypes)
private Record readRecord(RecordReader r, byte expectedType)
throws IOException {
// Accept records with current protocol version, expected types only
RecordPredicate accept = rec ->
rec.getProtocolVersion() == PROTOCOL_MAJOR_VERSION &&
expectedTypes.contains(rec.getRecordType());
// Accept records with current protocol version, expected type only
Predicate<Record> accept = rec ->
rec.getProtocolVersion() == PROTOCOL_VERSION &&
rec.getRecordType() == expectedType;
Record rec = r.readRecord(accept, IGNORE);
if (rec == null) throw new EOFException();
return rec;

View File

@@ -5,9 +5,7 @@ package org.briarproject.bramble.contact;
*/
interface HandshakeRecordTypes {
byte RECORD_TYPE_EPHEMERAL_PUBLIC_KEY = 0;
byte EPHEMERAL_PUBLIC_KEY = 0;
byte RECORD_TYPE_PROOF_OF_OWNERSHIP = 1;
byte RECORD_TYPE_MINOR_VERSION = 2;
byte PROOF_OF_OWNERSHIP = 1;
}

View File

@@ -34,7 +34,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Locale;
import java.util.logging.Logger;
import javax.annotation.Nullable;
@@ -223,8 +222,7 @@ class CryptoComponentImpl implements CryptoComponent {
}
@Override
@Deprecated
public SecretKey deriveSharedSecretBadly(String label,
public SecretKey deriveSharedSecret(String label,
PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey,
KeyPair ourStaticKeyPair, KeyPair ourEphemeralKeyPair,
boolean alice, byte[]... inputs) throws GeneralSecurityException {
@@ -252,35 +250,6 @@ class CryptoComponentImpl implements CryptoComponent {
return new SecretKey(hash);
}
@Override
public SecretKey deriveSharedSecret(String label,
PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey,
KeyPair ourStaticKeyPair, KeyPair ourEphemeralKeyPair,
boolean alice, byte[]... inputs) throws GeneralSecurityException {
PrivateKey ourStaticPrivateKey = ourStaticKeyPair.getPrivate();
PrivateKey ourEphemeralPrivateKey = ourEphemeralKeyPair.getPrivate();
byte[][] hashInputs = new byte[inputs.length + 3][];
// Alice ephemeral/Bob ephemeral
hashInputs[0] = performRawKeyAgreement(ourEphemeralPrivateKey,
theirEphemeralPublicKey);
// Alice static/Bob ephemeral, Bob static/Alice ephemeral
if (alice) {
hashInputs[1] = performRawKeyAgreement(ourStaticPrivateKey,
theirEphemeralPublicKey);
hashInputs[2] = performRawKeyAgreement(ourEphemeralPrivateKey,
theirStaticPublicKey);
} else {
hashInputs[1] = performRawKeyAgreement(ourEphemeralPrivateKey,
theirStaticPublicKey);
hashInputs[2] = performRawKeyAgreement(ourStaticPrivateKey,
theirEphemeralPublicKey);
}
arraycopy(inputs, 0, hashInputs, 3, inputs.length);
byte[] hash = hash(label, hashInputs);
if (hash.length != SecretKey.LENGTH) throw new IllegalStateException();
return new SecretKey(hash);
}
@Override
public byte[] sign(String label, byte[] toSign, PrivateKey privateKey)
throws GeneralSecurityException {
@@ -501,7 +470,7 @@ class CryptoComponentImpl implements CryptoComponent {
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(Locale.US);
return Base32.encode(address).toLowerCase();
}
}

View File

@@ -89,17 +89,11 @@ class H2Database extends JdbcDatabase {
try {
c = createConnection();
closeAllConnections();
LOG.info("Compacting DB");
setDirty(c, false);
s = c.createStatement();
s.execute("SHUTDOWN COMPACT");
LOG.info("Finished compacting DB");
s.close();
c.close();
// Reopen the DB to mark it as clean after compacting
c = createConnection();
setDirty(c, false);
LOG.info("Marked DB as clean");
c.close();
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
tryToClose(c, LOG, WARNING);
@@ -132,7 +126,6 @@ class H2Database extends JdbcDatabase {
closeAllConnections();
s = c.createStatement();
s.execute("SHUTDOWN COMPACT");
LOG.info("Finished compacting DB");
s.close();
c.close();
} catch (SQLException e) {

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.api.record.RecordReaderFactory;
import org.briarproject.bramble.api.record.RecordWriter;
import org.briarproject.bramble.api.record.RecordWriterFactory;
@@ -34,12 +34,12 @@ class KeyAgreementTransport {
Logger.getLogger(KeyAgreementTransport.class.getName());
// Accept records with current protocol version, known record type
private static final RecordPredicate ACCEPT = r ->
private static final Predicate<Record> ACCEPT = r ->
r.getProtocolVersion() == PROTOCOL_VERSION &&
isKnownRecordType(r.getRecordType());
// Ignore records with current protocol version, unknown record type
private static final RecordPredicate IGNORE = r ->
private static final Predicate<Record> IGNORE = r ->
r.getProtocolVersion() == PROTOCOL_VERSION &&
!isKnownRecordType(r.getRecordType());

View File

@@ -388,6 +388,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
}
// Validate the UUID
try {
//noinspection ResultOfMethodCallIgnored
UUID.fromString(uuid);
} catch (IllegalArgumentException e) {
if (LOG.isLoggable(WARNING)) LOG.warning("Invalid UUID " + uuid);

View File

@@ -75,6 +75,7 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHE
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
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.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
import static org.briarproject.bramble.util.IoUtils.tryToClose;
@@ -105,6 +106,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
private final PluginCallback callback;
private final long maxLatency;
private final int maxIdleTime;
private final boolean canVerifyLetsEncryptCerts;
private final int socketTimeout;
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -124,7 +126,8 @@ class TorPlugin implements DuplexPlugin, EventListener {
TorWrapper tor,
PluginCallback callback,
long maxLatency,
int maxIdleTime) {
int maxIdleTime,
boolean canVerifyLetsEncryptCerts) {
this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor;
this.networkManager = networkManager;
@@ -138,6 +141,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
this.callback = callback;
this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime;
this.canVerifyLetsEncryptCerts = canVerifyLetsEncryptCerts;
if (maxIdleTime > Integer.MAX_VALUE / 2) {
socketTimeout = Integer.MAX_VALUE;
} else {
@@ -293,7 +297,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
List<String> bridges = new ArrayList<>();
for (BridgeType bridgeType : bridgeTypes) {
bridges.addAll(circumventionProvider.getBridges(bridgeType,
countryCode));
countryCode, canVerifyLetsEncryptCerts));
}
tor.enableBridges(bridges);
}
@@ -487,8 +491,8 @@ class TorPlugin implements DuplexPlugin, EventListener {
boolean wifi = status.isWifi();
boolean ipv6Only = status.isIpv6Only();
String country = locationUtils.getCurrentCountry();
boolean bridgesByDefault =
circumventionProvider.shouldUseBridges(country);
boolean blocked =
circumventionProvider.isTorProbablyBlocked(country);
boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE,
DEFAULT_PREF_PLUGIN_ENABLE);
int network = settings.getInt(PREF_TOR_NETWORK,
@@ -498,6 +502,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
boolean onlyWhenCharging =
settings.getBoolean(PREF_TOR_ONLY_WHEN_CHARGING,
DEFAULT_PREF_TOR_ONLY_WHEN_CHARGING);
boolean bridgesWork = circumventionProvider.doBridgesWork(country);
boolean automatic = network == PREF_TOR_NETWORK_AUTOMATIC;
if (LOG.isLoggable(INFO)) {
@@ -527,6 +532,10 @@ class TorPlugin implements DuplexPlugin, EventListener {
LOG.info("Configured not to use mobile data");
reasonsDisabled |= REASON_MOBILE_DATA;
}
if (automatic && blocked && !bridgesWork) {
LOG.info("Country is blocked");
reasonsDisabled |= REASON_COUNTRY_BLOCKED;
}
if (reasonsDisabled != 0) {
LOG.info("Disabling network due to settings");
@@ -534,7 +543,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
LOG.info("Enabling network");
enableNetwork = true;
if (network == PREF_TOR_NETWORK_WITH_BRIDGES ||
(automatic && bridgesByDefault)) {
(automatic && bridgesWork)) {
if (ipv6Only) {
bridgeTypes = asList(MEEK, SNOWFLAKE);
} else {
@@ -621,9 +630,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
private synchronized State getState(TorState torState) {
// Treat TorState.STARTED as State.STARTING_STOPPING because it's
// only seen during startup, before TorWrapper#enableNetwork() is
// called for the first time. TorState.NOT_STARTED and
// TorState.STOPPED are mapped to State.STARTING_STOPPING because
// that's the State before we've started and after we've stopped.
// called for the first time
if (torState == TorState.NOT_STARTED ||
torState == TorState.STARTING ||
torState == TorState.STARTED ||

View File

@@ -311,7 +311,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
if (latest == null) {
merged = new TransportProperties(p);
Iterator<String> it = merged.values().iterator();
//noinspection Java8CollectionRemoveIf
while (it.hasNext()) {
if (isNullOrEmpty(it.next())) it.remove();
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.record;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.util.ByteUtils;
@@ -44,7 +45,7 @@ class RecordReaderImpl implements RecordReader {
@Nullable
@Override
public Record readRecord(RecordPredicate accept, RecordPredicate ignore)
public Record readRecord(Predicate<Record> accept, Predicate<Record> ignore)
throws IOException {
while (true) {
if (eof()) return null;

View File

@@ -1,10 +1,10 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory;
@@ -41,12 +41,12 @@ import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
class SyncRecordReaderImpl implements SyncRecordReader {
// Accept records with current protocol version, known record type
private static final RecordPredicate ACCEPT = r ->
private static final Predicate<Record> ACCEPT = r ->
r.getProtocolVersion() == PROTOCOL_VERSION &&
isKnownRecordType(r.getRecordType());
// Ignore records with current protocol version, unknown record type
private static final RecordPredicate IGNORE = r ->
private static final Predicate<Record> IGNORE = r ->
r.getProtocolVersion() == PROTOCOL_VERSION &&
!isKnownRecordType(r.getRecordType());

View File

@@ -1,316 +0,0 @@
package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.HandshakeManager.HandshakeResult;
import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.TransportCrypto;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.api.record.RecordReaderFactory;
import org.briarproject.bramble.api.record.RecordWriter;
import org.briarproject.bramble.api.record.RecordWriterFactory;
import org.briarproject.bramble.api.transport.StreamWriter;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.briarproject.bramble.test.PredicateMatcher;
import org.jmock.Expectations;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import static org.briarproject.bramble.contact.HandshakeConstants.PROOF_BYTES;
import static org.briarproject.bramble.contact.HandshakeConstants.PROTOCOL_MAJOR_VERSION;
import static org.briarproject.bramble.contact.HandshakeConstants.PROTOCOL_MINOR_VERSION;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.RECORD_TYPE_EPHEMERAL_PUBLIC_KEY;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.RECORD_TYPE_MINOR_VERSION;
import static org.briarproject.bramble.contact.HandshakeRecordTypes.RECORD_TYPE_PROOF_OF_OWNERSHIP;
import static org.briarproject.bramble.test.TestUtils.getAgreementPrivateKey;
import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey;
import static org.briarproject.bramble.test.TestUtils.getPendingContact;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class HandshakeManagerImplTest extends BrambleMockTestCase {
private final TransactionManager db =
context.mock(TransactionManager.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final ContactManager contactManager =
context.mock(ContactManager.class);
private final TransportCrypto transportCrypto =
context.mock(TransportCrypto.class);
private final HandshakeCrypto handshakeCrypto =
context.mock(HandshakeCrypto.class);
private final RecordReaderFactory recordReaderFactory =
context.mock(RecordReaderFactory.class);
private final RecordWriterFactory recordWriterFactory =
context.mock(RecordWriterFactory.class);
private final RecordReader recordReader = context.mock(RecordReader.class);
private final RecordWriter recordWriter = context.mock(RecordWriter.class);
private final StreamWriter streamWriter = context.mock(StreamWriter.class);
private final PendingContact pendingContact = getPendingContact();
private final PublicKey theirStaticPublicKey =
pendingContact.getPublicKey();
private final PublicKey ourStaticPublicKey = getAgreementPublicKey();
private final PrivateKey ourStaticPrivateKey = getAgreementPrivateKey();
private final KeyPair ourStaticKeyPair =
new KeyPair(ourStaticPublicKey, ourStaticPrivateKey);
private final PublicKey theirEphemeralPublicKey = getAgreementPublicKey();
private final PublicKey ourEphemeralPublicKey = getAgreementPublicKey();
private final PrivateKey ourEphemeralPrivateKey = getAgreementPrivateKey();
private final KeyPair ourEphemeralKeyPair =
new KeyPair(ourEphemeralPublicKey, ourEphemeralPrivateKey);
private final SecretKey masterKey = getSecretKey();
private final byte[] ourProof = getRandomBytes(PROOF_BYTES);
private final byte[] theirProof = getRandomBytes(PROOF_BYTES);
private final InputStream in = new ByteArrayInputStream(new byte[0]);
private final OutputStream out = new ByteArrayOutputStream(0);
private final HandshakeManagerImpl handshakeManager =
new HandshakeManagerImpl(db, identityManager, contactManager,
transportCrypto, handshakeCrypto, recordReaderFactory,
recordWriterFactory);
@Test
public void testHandshakeAsAliceWithPeerVersion_0_1() throws Exception {
testHandshakeWithPeerVersion_0_1(true);
}
@Test
public void testHandshakeAsBobWithPeerVersion_0_1() throws Exception {
testHandshakeWithPeerVersion_0_1(false);
}
private void testHandshakeWithPeerVersion_0_1(boolean alice)
throws Exception {
expectPrepareForHandshake(alice);
expectSendMinorVersion();
expectSendKey();
// Remote peer sends minor version, so use new key derivation
expectReceiveMinorVersion();
expectReceiveKey();
expectDeriveMasterKey_0_1(alice);
expectDeriveProof(alice);
expectSendProof();
expectReceiveProof();
expectSendEof();
expectReceiveEof();
expectVerifyOwnership(alice, true);
HandshakeResult result = handshakeManager.handshake(
pendingContact.getId(), in, streamWriter);
assertArrayEquals(masterKey.getBytes(),
result.getMasterKey().getBytes());
assertEquals(alice, result.isAlice());
}
@Test
public void testHandshakeAsAliceWithPeerVersion_0_0() throws Exception {
testHandshakeWithPeerVersion_0_0(true);
}
@Test
public void testHandshakeAsBobWithPeerVersion_0_0() throws Exception {
testHandshakeWithPeerVersion_0_0(false);
}
private void testHandshakeWithPeerVersion_0_0(boolean alice)
throws Exception {
expectPrepareForHandshake(alice);
expectSendMinorVersion();
expectSendKey();
// Remote peer does not send minor version, so use old key derivation
expectReceiveKey();
expectDeriveMasterKey_0_0(alice);
expectDeriveProof(alice);
expectSendProof();
expectReceiveProof();
expectSendEof();
expectReceiveEof();
expectVerifyOwnership(alice, true);
HandshakeResult result = handshakeManager.handshake(
pendingContact.getId(), in, streamWriter);
assertArrayEquals(masterKey.getBytes(),
result.getMasterKey().getBytes());
assertEquals(alice, result.isAlice());
}
@Test(expected = FormatException.class)
public void testProofOfOwnershipNotVerifiedAsAlice() throws Exception {
testProofOfOwnershipNotVerified(true);
}
@Test(expected = FormatException.class)
public void testProofOfOwnershipNotVerifiedAsBob() throws Exception {
testProofOfOwnershipNotVerified(false);
}
private void testProofOfOwnershipNotVerified(boolean alice)
throws Exception {
expectPrepareForHandshake(alice);
expectSendMinorVersion();
expectSendKey();
expectReceiveMinorVersion();
expectReceiveKey();
expectDeriveMasterKey_0_1(alice);
expectDeriveProof(alice);
expectSendProof();
expectReceiveProof();
expectSendEof();
expectReceiveEof();
expectVerifyOwnership(alice, false);
handshakeManager.handshake(pendingContact.getId(), in, streamWriter);
}
private void expectPrepareForHandshake(boolean alice) throws Exception {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
oneOf(contactManager).getPendingContact(txn,
pendingContact.getId());
will(returnValue(pendingContact));
oneOf(identityManager).getHandshakeKeys(txn);
will(returnValue(ourStaticKeyPair));
oneOf(transportCrypto).isAlice(theirStaticPublicKey,
ourStaticKeyPair);
will(returnValue(alice));
oneOf(recordReaderFactory).createRecordReader(in);
will(returnValue(recordReader));
oneOf(streamWriter).getOutputStream();
will(returnValue(out));
oneOf(recordWriterFactory).createRecordWriter(out);
will(returnValue(recordWriter));
oneOf(handshakeCrypto).generateEphemeralKeyPair();
will(returnValue(ourEphemeralKeyPair));
}});
}
private void expectSendMinorVersion() throws Exception {
expectWriteRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_MINOR_VERSION,
new byte[] {PROTOCOL_MINOR_VERSION}));
}
private void expectReceiveMinorVersion() throws Exception {
expectReadRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_MINOR_VERSION,
new byte[] {PROTOCOL_MINOR_VERSION}));
}
private void expectSendKey() throws Exception {
expectWriteRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_EPHEMERAL_PUBLIC_KEY,
ourEphemeralPublicKey.getEncoded()));
}
private void expectReceiveKey() throws Exception {
expectReadRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_EPHEMERAL_PUBLIC_KEY,
theirEphemeralPublicKey.getEncoded()));
}
private void expectDeriveMasterKey_0_1(boolean alice) throws Exception {
context.checking(new Expectations() {{
oneOf(handshakeCrypto).deriveMasterKey_0_1(theirStaticPublicKey,
theirEphemeralPublicKey, ourStaticKeyPair,
ourEphemeralKeyPair, alice);
will(returnValue(masterKey));
}});
}
private void expectDeriveMasterKey_0_0(boolean alice) throws Exception {
context.checking(new Expectations() {{
oneOf(handshakeCrypto).deriveMasterKey_0_0(theirStaticPublicKey,
theirEphemeralPublicKey, ourStaticKeyPair,
ourEphemeralKeyPair, alice);
will(returnValue(masterKey));
}});
}
private void expectDeriveProof(boolean alice) {
context.checking(new Expectations() {{
oneOf(handshakeCrypto).proveOwnership(masterKey, alice);
will(returnValue(ourProof));
}});
}
private void expectSendProof() throws Exception {
expectWriteRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_PROOF_OF_OWNERSHIP, ourProof));
}
private void expectReceiveProof() throws Exception {
expectReadRecord(new Record(PROTOCOL_MAJOR_VERSION,
RECORD_TYPE_PROOF_OF_OWNERSHIP, theirProof));
}
private void expectSendEof() throws Exception {
context.checking(new Expectations() {{
oneOf(streamWriter).sendEndOfStream();
}});
}
private void expectReceiveEof() throws Exception {
context.checking(new Expectations() {{
oneOf(recordReader).readRecord(with(any(RecordPredicate.class)),
with(any(RecordPredicate.class)));
will(returnValue(null));
}});
}
private void expectVerifyOwnership(boolean alice, boolean verified) {
context.checking(new Expectations() {{
oneOf(handshakeCrypto).verifyOwnership(masterKey, !alice,
theirProof);
will(returnValue(verified));
}});
}
private void expectWriteRecord(Record record) throws Exception {
context.checking(new Expectations() {{
oneOf(recordWriter).writeRecord(with(new PredicateMatcher<>(
Record.class, r -> recordEquals(record, r))));
oneOf(recordWriter).flush();
}});
}
private boolean recordEquals(Record expected, Record actual) {
return expected.getProtocolVersion() == actual.getProtocolVersion() &&
expected.getRecordType() == actual.getRecordType() &&
Arrays.equals(expected.getPayload(), actual.getPayload());
}
private void expectReadRecord(Record record) throws Exception {
context.checking(new Expectations() {{
// Test that the `accept` predicate passed to the reader would
// accept the expected record
oneOf(recordReader).readRecord(with(new PredicateMatcher<>(
RecordPredicate.class, rp -> rp.test(record))),
with(any(RecordPredicate.class)));
will(returnValue(record));
}});
}
}

View File

@@ -13,7 +13,6 @@ import org.jmock.Expectations;
import org.junit.Test;
import java.security.GeneralSecurityException;
import java.util.Locale;
import static java.lang.System.arraycopy;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.BASE32_LINK_BYTES;
@@ -175,7 +174,7 @@ public class PendingContactFactoryImplTest extends BrambleMockTestCase {
rawLink[0] = (byte) formatVersion;
byte[] publicKeyBytes = publicKey.getEncoded();
arraycopy(publicKeyBytes, 0, rawLink, 1, publicKeyBytes.length);
String base32 = Base32.encode(rawLink).toLowerCase(Locale.US);
String base32 = Base32.encode(rawLink).toLowerCase();
assertEquals(BASE32_LINK_BYTES, base32.length());
return base32;
}

View File

@@ -60,22 +60,6 @@ public class KeyAgreementTest extends BrambleTestCase {
assertArrayEquals(aShared.getBytes(), bShared.getBytes());
}
@Test
public void testDerivesStaticEphemeralSharedSecretBadly() throws Exception {
String label = getRandomString(123);
KeyPair aStatic = crypto.generateAgreementKeyPair();
KeyPair aEphemeral = crypto.generateAgreementKeyPair();
KeyPair bStatic = crypto.generateAgreementKeyPair();
KeyPair bEphemeral = crypto.generateAgreementKeyPair();
SecretKey aShared = crypto.deriveSharedSecretBadly(label,
bStatic.getPublic(), bEphemeral.getPublic(), aStatic,
aEphemeral, true, inputs);
SecretKey bShared = crypto.deriveSharedSecretBadly(label,
aStatic.getPublic(), aEphemeral.getPublic(), bStatic,
bEphemeral, false, inputs);
assertArrayEquals(aShared.getBytes(), bShared.getBytes());
}
@Test
public void testDerivesStaticEphemeralSharedSecret() throws Exception {
String label = getRandomString(123);

View File

@@ -1,45 +0,0 @@
package org.briarproject.bramble.crypto;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
import static java.util.Arrays.fill;
/**
* A fake SecureRandom implementation for testing, which returns all zeroes.
*/
public class NeitherSecureNorRandom extends SecureRandom {
private static final Provider PROVIDER =
new NeitherSecureNorRandomProvider();
public NeitherSecureNorRandom() {
super(new NeitherSecureNorRandomSpi(), PROVIDER);
}
private static class NeitherSecureNorRandomSpi extends SecureRandomSpi {
@Override
protected byte[] engineGenerateSeed(int length) {
return new byte[length];
}
@Override
protected void engineNextBytes(byte[] b) {
fill(b, (byte) 0);
}
@Override
protected void engineSetSeed(byte[] seed) {
// Thank you for your input
}
}
private static class NeitherSecureNorRandomProvider extends Provider {
private NeitherSecureNorRandomProvider() {
super("NeitherSecureNorRandom", 1.0, "Only for testing");
}
}
}

View File

@@ -1,30 +0,0 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestSecureRandomProvider;
import org.junit.Test;
import java.security.SecureRandom;
import java.util.regex.Pattern;
import static org.junit.Assert.assertTrue;
public class OnionEncodingTest extends BrambleTestCase {
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
private final CryptoComponent crypto =
new CryptoComponentImpl(new TestSecureRandomProvider(), null);
private final SecureRandom secureRandom = new SecureRandom();
@Test
public void testHostnameIsValid() {
byte[] publicKey = new byte[32];
for (int i = 0; i < 100; i++) {
secureRandom.nextBytes(publicKey);
String onion = crypto.encodeOnion(publicKey);
assertTrue(onion, ONION_V3.matcher(onion).matches());
}
}
}

View File

@@ -0,0 +1,34 @@
package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
@NotNullByDefault
class PseudoRandom {
private final Salsa20Engine cipher = new Salsa20Engine();
PseudoRandom(byte[] seed) {
// Hash the seed to produce a 32-byte key
byte[] key = new byte[32];
Digest digest = new Blake2bDigest(256);
digest.update(seed, 0, seed.length);
digest.doFinal(key, 0);
// Initialise the stream cipher with an all-zero nonce
byte[] nonce = new byte[8];
cipher.init(true, new ParametersWithIV(new KeyParameter(key), nonce));
}
byte[] nextBytes(int length) {
byte[] in = new byte[length], out = new byte[length];
cipher.processBytes(in, 0, length, out, 0);
return out;
}
}

View File

@@ -0,0 +1,46 @@
package org.briarproject.bramble.crypto;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
class PseudoSecureRandom extends SecureRandom {
private static final Provider PROVIDER = new PseudoSecureRandomProvider();
PseudoSecureRandom(byte[] seed) {
super(new PseudoSecureRandomSpi(seed), PROVIDER);
}
private static class PseudoSecureRandomSpi extends SecureRandomSpi {
private final PseudoRandom pseudoRandom;
private PseudoSecureRandomSpi(byte[] seed) {
pseudoRandom = new PseudoRandom(seed);
}
@Override
protected byte[] engineGenerateSeed(int length) {
return pseudoRandom.nextBytes(length);
}
@Override
protected void engineNextBytes(byte[] b) {
byte[] random = pseudoRandom.nextBytes(b.length);
System.arraycopy(random, 0, b, 0, b.length);
}
@Override
protected void engineSetSeed(byte[] seed) {
// Thank you for your input
}
}
private static class PseudoSecureRandomProvider extends Provider {
private PseudoSecureRandomProvider() {
super("PseudoSecureRandom", 1.0, "Only for testing");
}
}
}

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
@@ -7,22 +8,21 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.api.record.RecordReaderFactory;
import org.briarproject.bramble.api.record.RecordWriter;
import org.briarproject.bramble.api.record.RecordWriterFactory;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.CaptureArgumentAction;
import org.briarproject.bramble.test.PredicateMatcher;
import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.api.keyagreement.RecordTypes.ABORT;
import static org.briarproject.bramble.api.keyagreement.RecordTypes.CONFIRM;
@@ -52,12 +52,17 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
private final KeyAgreementConnection keyAgreementConnection =
new KeyAgreementConnection(duplexTransportConnection, transportId);
private final InputStream inputStream =
new ByteArrayInputStream(new byte[0]);
private final OutputStream outputStream = new ByteArrayOutputStream();
private final InputStream inputStream;
private final OutputStream outputStream;
private KeyAgreementTransport kat;
public KeyAgreementTransportTest() {
context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE);
inputStream = context.mock(InputStream.class);
outputStream = context.mock(OutputStream.class);
}
@Test
public void testSendKey() throws Exception {
byte[] key = getRandomBytes(123);
@@ -114,7 +119,7 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
public void testReceiveKeyThrowsExceptionIfAtEndOfStream()
throws Exception {
setup();
expectReadEof();
expectReadRecord(null);
kat.receiveKey();
}
@@ -143,7 +148,7 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
public void testReceiveConfirmThrowsExceptionIfAtEndOfStream()
throws Exception {
setup();
expectReadEof();
expectReadRecord(null);
kat.receiveConfirm();
}
@@ -204,22 +209,12 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
assertArrayEquals(expectedPayload, actual.getPayload());
}
private void expectReadRecord(Record record) throws Exception {
private void expectReadRecord(@Nullable Record record) throws Exception {
context.checking(new Expectations() {{
// Test that the `accept` predicate passed to the reader would
// accept the expected record
oneOf(recordReader).readRecord(with(new PredicateMatcher<>(
RecordPredicate.class, rp -> rp.test(record))),
with(any(RecordPredicate.class)));
//noinspection unchecked
oneOf(recordReader).readRecord(with(any(Predicate.class)),
with(any(Predicate.class)));
will(returnValue(record));
}});
}
private void expectReadEof() throws Exception {
context.checking(new Expectations() {{
oneOf(recordReader).readRecord(with(any(RecordPredicate.class)),
with(any(RecordPredicate.class)));
will(returnValue(null));
}});
}
}

View File

@@ -21,11 +21,11 @@ import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.crypto.NeitherSecureNorRandom;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.ImmediateExecutor;
import org.briarproject.bramble.test.RunAction;
import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser;
import org.junit.Test;
import java.security.SecureRandom;
@@ -55,6 +55,7 @@ public class PollerImplTest extends BrambleMockTestCase {
context.mock(TransportPropertyManager.class);
private final Clock clock = context.mock(Clock.class);
private final Cancellable cancellable = context.mock(Cancellable.class);
private final SecureRandom random;
private final Executor ioExecutor = new ImmediateExecutor();
private final TransportId transportId = getTransportId();
@@ -66,8 +67,8 @@ public class PollerImplTest extends BrambleMockTestCase {
private final PollerImpl poller;
public PollerImplTest() {
// Use a fake SecureRandom that returns all zeroes
SecureRandom random = new NeitherSecureNorRandom();
context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE);
random = context.mock(SecureRandom.class);
Executor wakefulIoExecutor = new ImmediateExecutor();
poller = new PollerImpl(ioExecutor, wakefulIoExecutor, scheduler,
connectionManager, connectionRegistry, pluginManager,
@@ -351,10 +352,12 @@ public class PollerImplTest extends BrambleMockTestCase {
// Running the polling task schedules the next polling task
oneOf(plugin).getPollingInterval();
will(returnValue(pollingInterval));
oneOf(random).nextDouble();
will(returnValue(0.5));
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(scheduler).schedule(with(any(Runnable.class)),
with(ioExecutor), with(0L),
with(ioExecutor), with((long) (pollingInterval * 0.5)),
with(MILLISECONDS));
will(returnValue(cancellable));
// Get the transport properties and connected contacts
@@ -393,10 +396,12 @@ public class PollerImplTest extends BrambleMockTestCase {
// Running the polling task schedules the next polling task
oneOf(plugin).getPollingInterval();
will(returnValue(pollingInterval));
oneOf(random).nextDouble();
will(returnValue(0.5));
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(scheduler).schedule(with(any(Runnable.class)),
with(ioExecutor), with(0L),
with(ioExecutor), with((long) (pollingInterval * 0.5)),
with(MILLISECONDS));
will(returnValue(cancellable));
// Get the transport properties and connected contacts

View File

@@ -1,9 +1,9 @@
package org.briarproject.bramble.record;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.util.ByteUtils;
import org.junit.Test;
@@ -128,12 +128,12 @@ public class RecordReaderImplTest extends BrambleTestCase {
RecordReader reader = new RecordReaderImpl(in);
// Accept records with version 0, type 0 or 1
RecordPredicate accept = r -> {
Predicate<Record> accept = r -> {
byte version = r.getProtocolVersion(), type = r.getRecordType();
return version == 0 && (type == 0 || type == 1);
};
// Ignore records with version 0, any other type
RecordPredicate ignore = r -> {
Predicate<Record> ignore = r -> {
byte version = r.getProtocolVersion(), type = r.getRecordType();
return version == 0 && !(type == 0 || type == 1);
};
@@ -183,12 +183,12 @@ public class RecordReaderImplTest extends BrambleTestCase {
RecordReader reader = new RecordReaderImpl(in);
// Accept records with version 0, type 0 or 1
RecordPredicate accept = r -> {
Predicate<Record> accept = r -> {
byte version = r.getProtocolVersion(), type = r.getRecordType();
return version == 0 && (type == 0 || type == 1);
};
// Ignore records with version 0, any other type
RecordPredicate ignore = r -> {
Predicate<Record> ignore = r -> {
byte version = r.getProtocolVersion(), type = r.getRecordType();
return version == 0 && !(type == 0 || type == 1);
};

View File

@@ -1,10 +1,10 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReader.RecordPredicate;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
@@ -24,6 +24,8 @@ import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.util.List;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
import static org.briarproject.bramble.api.sync.RecordTypes.ACK;
import static org.briarproject.bramble.api.sync.RecordTypes.MESSAGE;
@@ -184,7 +186,7 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
@Test
public void testEofReturnsTrueWhenAtEndOfStream() throws Exception {
expectReadRecord(createAck());
expectReadEof();
expectReadRecord(null);
SyncRecordReader reader =
new SyncRecordReaderImpl(messageFactory, recordReader);
@@ -210,25 +212,15 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
}});
}
private void expectReadRecord(Record record) throws Exception {
private void expectReadRecord(@Nullable Record record) throws Exception {
context.checking(new Expectations() {{
// Test that the `accept` predicate passed to the reader would
// accept the expected record
oneOf(recordReader).readRecord(with(new PredicateMatcher<>(
RecordPredicate.class, rp -> rp.test(record))),
with(any(RecordPredicate.class)));
//noinspection unchecked
oneOf(recordReader).readRecord(with(any(Predicate.class)),
with(any(Predicate.class)));
will(returnValue(record));
}});
}
private void expectReadEof() throws Exception {
context.checking(new Expectations() {{
oneOf(recordReader).readRecord(with(any(RecordPredicate.class)),
with(any(RecordPredicate.class)));
will(returnValue(null));
}});
}
private Record createMessage(int payloadLength) {
return new Record(PROTOCOL_VERSION, MESSAGE, new byte[payloadLength]);
}

View File

@@ -1,67 +1,73 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
'com.fasterxml.jackson.core:jackson-core:2.13.4:jackson-core-2.13.4.jar:4c2e043200edd9ee7ba6fc378bd5c17784a5bf2388e152d208068b51fd0839cf',
'com.fasterxml.jackson.core:jackson-databind:2.13.4:jackson-databind-2.13.4.jar:c9faff420d9e2c7e1e4711dbeebec2506a32c9942027211c5c293d8d87807eb6',
'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.dagger:dagger-compiler:2.51.1:dagger-compiler-2.51.1.jar:14cf2def1c4c8cd3b977840e297b463191d537cd1c8330992ca5c0b341a641ad',
'com.google.dagger:dagger-spi:2.51.1:dagger-spi-2.51.1.jar:deb52030b92b27c5dcd76b2c0747f1cf105b60939f6073b43eb06cfe7c9ba601',
'com.google.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d',
'com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14:symbol-processing-api-1.9.20-1.0.14.jar:d0339396f40dc9eb3b3f7bc86257f93869ee23448fa31ec4a1de900c6b7ae6d7',
'com.google.errorprone:error_prone_annotations:2.23.0:error_prone_annotations-2.23.0.jar:ec6f39f068b6ff9ac323c68e28b9299f8c0a80ca512dccb1d4a70f40ac3ec054',
'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.2:failureaccess-1.0.2.jar:8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064',
'com.google.guava:guava:33.0.0-jre:guava-33.0.0-jre.jar:f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.squareup.okhttp3:mockwebserver:4.10.0:mockwebserver-4.10.0.jar:af29da234e63159d6e0dea43bf8288eea97d71cdf1651a5ee2d6c0d0d4adbf8f',
'com.squareup.okhttp3:okhttp:4.12.0:okhttp-4.12.0.jar:b1050081b14bb7a3a7e55a4d3ef01b5dcfabc453b4573a4fc019767191d5f4e0',
'com.squareup.okio:okio-jvm:3.6.0:okio-jvm-3.6.0.jar:67543f0736fc422ae927ed0e504b98bc5e269fda0d3500579337cb713da28412',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.jodah:concurrentunit:0.4.6:concurrentunit-0.4.6.jar:760e6d4ab7801484de09da621b61141f3b2c2432949da9eb13f076e5d9a5e0a5',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.bouncycastle:bcprov-jdk15to18:1.71:bcprov-jdk15to18-1.71.jar:143aaa4a40edd5fc2a18db7900059f6c16f4d931b94b94b20f7e2238e6662886',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-core:0.1.3:onionwrapper-core-0.1.3.jar:32d08c9d81a9591e08d7e64e3569334fee21f503b00514006f2e6cbbd409d0df',
'org.briarproject:socks-socket:0.1:socks-socket-0.1.jar:e5898822d10f5390363c5dddb945891648c92cf93ba50709e07f0d173ec0eb4b',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.41.0:checker-qual-3.41.0.jar:2f9f245bf68e4259d610894f2406dc1f6363dc639302bd566e8272e4f4541172',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.22:animal-sniffer-ant-tasks-1.22.jar:3f6afeb3e09301d2d7179ed1db21e3ad8846c1e38415ad832a395138ae3f4218',
'org.codehaus.mojo:animal-sniffer:1.22:animal-sniffer-1.22.jar:f18c11a25bdd8b520b9c6a28cbb6f33007c812ab0051b6be3f0778e660aa501c',
'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.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10:kotlin-stdlib-common-1.9.10.jar:cde3341ba18a2ba262b0b7cf6c55b20c90e8d434e42c9a13e6a3f770db965a88',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0:kotlin-stdlib-jdk7-1.9.0.jar:b7979a7aac94055f0d9f1fd3b47ce5ffe1cb6032a842ba9fbe7186f085289178',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10:kotlin-stdlib-jdk7-1.9.10.jar:ac6361bf9ad1ed382c2103d9712c47cdec166232b4903ed596e8876b0681c9b7',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0:kotlin-stdlib-jdk8-1.9.0.jar:a59fa24fdf1ffb594baecdbf0fd10010f977cea10236d487fe3464977a7377fa',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10:kotlin-stdlib-jdk8-1.9.10.jar:a4c74d94d64ce1abe53760fe0389dd941f6fc558d0dab35e47c085a11ec80f28',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.10:kotlin-stdlib-1.9.10.jar:55e989c512b80907799f854309f3bc7782c5b3d13932442d0379d5c472711504',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.20:kotlin-stdlib-1.9.20.jar:28a35bcdff46d864f80f346a617e486284b208d17378c41900dfb1de95a90e6c',
'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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.3:asm-9.3.jar:1263369b59e29c943918de11d6d6152e2ec6085ce63e5710516f8c67d368e4bc',
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
]
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
'com.fasterxml.jackson.core:jackson-core:2.13.4:jackson-core-2.13.4.jar:4c2e043200edd9ee7ba6fc378bd5c17784a5bf2388e152d208068b51fd0839cf',
'com.fasterxml.jackson.core:jackson-databind:2.13.4:jackson-databind-2.13.4.jar:c9faff420d9e2c7e1e4711dbeebec2506a32c9942027211c5c293d8d87807eb6',
'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.dagger:dagger-compiler:2.45:dagger-compiler-2.45.jar:5617dfb994537dba5b41f3744a6dd13ec3cd99789c065e0d5c6fa9f21cf7ca25',
'com.google.dagger:dagger-producers:2.45:dagger-producers-2.45.jar:a05abb4c3ccf6bb0f056bdcb5ef973898ecf172952ab5948a824aeea6c86ecaa',
'com.google.dagger:dagger-spi:2.45:dagger-spi-2.45.jar:7cd6f0b09d88e64a9c97bc80e544ab8ac8fdee9301754413585a74cf64222b27',
'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
'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:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
'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.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.squareup.okhttp3:mockwebserver:4.10.0:mockwebserver-4.10.0.jar:af29da234e63159d6e0dea43bf8288eea97d71cdf1651a5ee2d6c0d0d4adbf8f',
'com.squareup.okhttp3:okhttp:4.10.0:okhttp-4.10.0.jar:7580f14fa1691206e37081ad3f92063b1603b328da0bb316f2fef02e0562e7ec',
'com.squareup.okio:okio-jvm:3.0.0:okio-jvm-3.0.0.jar:be64a0cc1f28ea9cd5c970dd7e7557af72c808d738c495b397bf897c9921e907',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.jodah:concurrentunit:0.4.6:concurrentunit-0.4.6.jar:760e6d4ab7801484de09da621b61141f3b2c2432949da9eb13f076e5d9a5e0a5',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.bouncycastle:bcprov-jdk15to18:1.71:bcprov-jdk15to18-1.71.jar:143aaa4a40edd5fc2a18db7900059f6c16f4d931b94b94b20f7e2238e6662886',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-core:0.0.3:onionwrapper-core-0.0.3.jar:2645dd7e4f2e73fc2ba30696aeac4c960ef8b8f405d85e529fdf8b105ef374f1',
'org.briarproject:socks-socket:0.1:socks-socket-0.1.jar:e5898822d10f5390363c5dddb945891648c92cf93ba50709e07f0d173ec0eb4b',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.22:animal-sniffer-ant-tasks-1.22.jar:3f6afeb3e09301d2d7179ed1db21e3ad8846c1e38415ad832a395138ae3f4218',
'org.codehaus.mojo:animal-sniffer:1.22:animal-sniffer-1.22.jar:f18c11a25bdd8b520b9c6a28cbb6f33007c812ab0051b6be3f0778e660aa501c',
'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.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20:kotlin-stdlib-common-1.6.20.jar:8da40a2520d30dcb1012176fe93d24e82d08a3e346c37e0343b0fb6f64f6be01',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31:kotlin-stdlib-jdk7-1.5.31.jar:a25bf47353ce899d843cbddee516d621a73473e7fba97f8d0301e7b4aed7c15f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10:kotlin-stdlib-jdk7-1.6.10.jar:2aedcdc6b69b33bdf5cc235bcea88e7cf6601146bb6bcdffdb312bbacd7be261',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31:kotlin-stdlib-jdk8-1.5.31.jar:b548f7767aacf029d2417e47440742bd6d3ebede19b60386e23554ce5c4c5fdc',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10:kotlin-stdlib-jdk8-1.6.10.jar:1456d82d039ea30d8485b032901f52bbf07e7cdbe8bb1f8708ad32a8574c41ce',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
'org.jetbrains.kotlin:kotlin-stdlib:1.6.20:kotlin-stdlib-1.6.20.jar:eeb51c2b67b26233fd81d0bc4f8044ec849718890905763ceffd84a31e2cb799',
'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
'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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.3:asm-9.3.jar:1263369b59e29c943918de11d6d6152e2ec6085ce63e5710516f8c67d368e4bc',
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
]
}

View File

@@ -11,7 +11,7 @@ dependencies {
implementation project(':bramble-core')
implementation fileTree(dir: 'libs', include: '*.jar')
def jna_version = '5.13.0'
def jna_version = '4.5.2'
implementation "net.java.dev.jna:jna:$jna_version"
implementation "net.java.dev.jna:jna-platform:$jna_version"
implementation "org.briarproject:onionwrapper-java:$onionwrapper_version"

View File

@@ -1,17 +0,0 @@
package org.briarproject.bramble;
import org.briarproject.bramble.network.JavaNetworkModule;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface BrambleJavaEagerSingletons {
void inject(JavaNetworkModule.EagerSingletons init);
class Helper {
public static void injectEagerSingletons(BrambleJavaEagerSingletons c) {
c.inject(new JavaNetworkModule.EagerSingletons());
}
}
}

View File

@@ -1,51 +1,33 @@
package org.briarproject.bramble.network;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.network.NetworkStatus;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.nullsafety.NotNullByDefault;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.Collections.list;
import static java.util.concurrent.TimeUnit.SECONDS;
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.LogUtils.logException;
import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces;
@NotNullByDefault
class JavaNetworkManager implements NetworkManager, Service {
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class JavaNetworkManager implements NetworkManager {
private static final Logger LOG =
getLogger(JavaNetworkManager.class.getName());
private final TaskScheduler scheduler;
private final Executor ioExecutor;
private final EventBus eventBus;
private final AtomicReference<NetworkStatus> lastStatus =
new AtomicReference<>();
@Inject
JavaNetworkManager(TaskScheduler scheduler,
@IoExecutor Executor ioExecutor,
EventBus eventBus) {
this.scheduler = scheduler;
this.ioExecutor = ioExecutor;
this.eventBus = eventBus;
JavaNetworkManager() {
}
@Override
@@ -66,29 +48,7 @@ class JavaNetworkManager implements NetworkManager, Service {
} catch (SocketException e) {
logException(LOG, WARNING, e);
}
if (LOG.isLoggable(INFO)) {
LOG.info("Connected: " + connected
+ ", has IPv4 address: " + hasIpv4
+ ", has IPv6 unicast address: " + hasIpv6Unicast);
}
return new NetworkStatus(connected, false, !hasIpv4 && hasIpv6Unicast);
}
private void broadcastNetworkStatusIfChanged() {
NetworkStatus status = getNetworkStatus();
NetworkStatus old = lastStatus.getAndSet(status);
if (!status.equals(old)) {
eventBus.broadcast(new NetworkStatusEvent(status));
}
}
@Override
public void startService() {
scheduler.scheduleWithFixedDelay(this::broadcastNetworkStatusIfChanged,
ioExecutor, 0, 10, SECONDS);
}
@Override
public void stopService() {
}
}

View File

@@ -1,9 +1,7 @@
package org.briarproject.bramble.network;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.network.NetworkManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
@@ -12,16 +10,9 @@ import dagger.Provides;
@Module
public class JavaNetworkModule {
public static class EagerSingletons {
@Inject
NetworkManager networkManager;
}
@Provides
@Singleton
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,
JavaNetworkManager networkManager) {
lifecycleManager.registerService(networkManager);
NetworkManager provideNetworkManager(JavaNetworkManager networkManager) {
return networkManager;
}
}

View File

@@ -1,84 +0,0 @@
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.event.EventExecutor;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager;
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.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.WakefulIoExecutor;
import org.briarproject.nullsafety.NotNullByDefault;
import org.briarproject.onionwrapper.CircumventionProvider;
import org.briarproject.onionwrapper.LocationUtils;
import org.briarproject.onionwrapper.MacTorWrapper;
import org.briarproject.onionwrapper.TorWrapper;
import java.io.File;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import javax.net.SocketFactory;
import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.util.OsUtils.isMac;
@Immutable
@NotNullByDefault
public class MacTorPluginFactory extends TorPluginFactory {
@Inject
MacTorPluginFactory(@IoExecutor Executor ioExecutor,
@EventExecutor Executor eventExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor,
NetworkManager networkManager,
LocationUtils locationUtils,
EventBus eventBus,
SocketFactory torSocketFactory,
BackoffFactory backoffFactory,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager,
Clock clock,
CryptoComponent crypto,
@TorDirectory File torDirectory,
@TorSocksPort int torSocksPort,
@TorControlPort int torControlPort) {
super(ioExecutor, eventExecutor, wakefulIoExecutor, networkManager,
locationUtils, eventBus, torSocketFactory, backoffFactory,
circumventionProvider, batteryManager, clock, crypto,
torDirectory, torSocksPort, torControlPort);
}
@Nullable
@Override
String getArchitectureForTorBinary() {
if (!isMac()) return null;
String arch = System.getProperty("os.arch");
if (LOG.isLoggable(INFO)) {
LOG.info("System's os.arch is " + arch);
}
if (arch.equals("x86_64")) return "x86_64";
else if (arch.equals("aarch64")) return "aarch64";
return null;
}
@Override
TorPlugin createPluginInstance(Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto, PluginCallback callback,
String architecture) {
TorWrapper tor = new MacTorWrapper(ioExecutor, eventExecutor,
architecture, torDirectory, torSocksPort, torControlPort);
return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager,
locationUtils, torSocketFactory, circumventionProvider,
batteryManager, backoff, torRendezvousCrypto, tor, callback,
MAX_LATENCY, MAX_IDLE_TIME);
}
}

View File

@@ -81,6 +81,6 @@ public class UnixTorPluginFactory extends TorPluginFactory {
return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager,
locationUtils, torSocketFactory, circumventionProvider,
batteryManager, backoff, torRendezvousCrypto, tor, callback,
MAX_LATENCY, MAX_IDLE_TIME);
MAX_LATENCY, MAX_IDLE_TIME, true);
}
}

View File

@@ -78,6 +78,6 @@ public class WindowsTorPluginFactory extends TorPluginFactory {
return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager,
locationUtils, torSocketFactory, circumventionProvider,
batteryManager, backoff, torRendezvousCrypto, tor, callback,
MAX_LATENCY, MAX_IDLE_TIME);
MAX_LATENCY, MAX_IDLE_TIME, true);
}
}

View File

@@ -16,7 +16,7 @@ public class DesktopSecureRandomModule {
@Provides
@Singleton
SecureRandomProvider provideSecureRandomProvider() {
if (isLinux()) return new UnixSecureRandomProvider();
if (isLinux() || isMac()) return new UnixSecureRandomProvider();
return () -> null; // Use system default
}
}

View File

@@ -1,48 +1,52 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'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.dagger:dagger-compiler:2.51.1:dagger-compiler-2.51.1.jar:14cf2def1c4c8cd3b977840e297b463191d537cd1c8330992ca5c0b341a641ad',
'com.google.dagger:dagger-spi:2.51.1:dagger-spi-2.51.1.jar:deb52030b92b27c5dcd76b2c0747f1cf105b60939f6073b43eb06cfe7c9ba601',
'com.google.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d',
'com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14:symbol-processing-api-1.9.20-1.0.14.jar:d0339396f40dc9eb3b3f7bc86257f93869ee23448fa31ec4a1de900c6b7ae6d7',
'com.google.errorprone:error_prone_annotations:2.23.0:error_prone_annotations-2.23.0.jar:ec6f39f068b6ff9ac323c68e28b9299f8c0a80ca512dccb1d4a70f40ac3ec054',
'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.2:failureaccess-1.0.2.jar:8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064',
'com.google.guava:guava:33.0.0-jre:guava-33.0.0-jre.jar:f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.13.0:jna-platform-5.13.0.jar:474d7b88f6e97009b6ec1d98c3024dd95c23187c65dabfbc35331bcac3d173dd',
'net.java.dev.jna:jna:5.13.0:jna-5.13.0.jar:66d4f819a062a51a1d5627bffc23fac55d1677f0e0a1feba144aabdd670a64bb',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'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:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-core:0.1.3:onionwrapper-core-0.1.3.jar:32d08c9d81a9591e08d7e64e3569334fee21f503b00514006f2e6cbbd409d0df',
'org.briarproject:onionwrapper-java:0.1.3:onionwrapper-java-0.1.3.jar:a6bc535e8ea55e567c932f23123eabd10ad53251d3a1e5648960b177e7ab209b',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.41.0:checker-qual-3.41.0.jar:2f9f245bf68e4259d610894f2406dc1f6363dc639302bd566e8272e4f4541172',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0:kotlin-stdlib-jdk7-1.9.0.jar:b7979a7aac94055f0d9f1fd3b47ce5ffe1cb6032a842ba9fbe7186f085289178',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0:kotlin-stdlib-jdk8-1.9.0.jar:a59fa24fdf1ffb594baecdbf0fd10010f977cea10236d487fe3464977a7377fa',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.20:kotlin-stdlib-1.9.20.jar:28a35bcdff46d864f80f346a617e486284b208d17378c41900dfb1de95a90e6c',
'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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
]
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'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.dagger:dagger-compiler:2.45:dagger-compiler-2.45.jar:5617dfb994537dba5b41f3744a6dd13ec3cd99789c065e0d5c6fa9f21cf7ca25',
'com.google.dagger:dagger-producers:2.45:dagger-producers-2.45.jar:a05abb4c3ccf6bb0f056bdcb5ef973898ecf172952ab5948a824aeea6c86ecaa',
'com.google.dagger:dagger-spi:2.45:dagger-spi-2.45.jar:7cd6f0b09d88e64a9c97bc80e544ab8ac8fdee9301754413585a74cf64222b27',
'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
'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:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
'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.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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:4.5.2:jna-platform-4.5.2.jar:f1d00c167d8921c6e23c626ef9f1c3ae0be473c95c68ffa012bc7ae55a87e2d6',
'net.java.dev.jna:jna:4.5.2:jna-4.5.2.jar:0c8eb7acf67261656d79005191debaba3b6bf5dd60a43735a245429381dbecff',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'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:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-core:0.0.3:onionwrapper-core-0.0.3.jar:2645dd7e4f2e73fc2ba30696aeac4c960ef8b8f405d85e529fdf8b105ef374f1',
'org.briarproject:onionwrapper-java:0.0.3:onionwrapper-java-0.0.3.jar:25e3a28010e054d7976ff05b8bfed0f25fb60e748a38aa3236451fc4339955e8',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
'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.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
]
}

View File

@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
lang_map = es_CU: es-rCU, pt_BR: pt-rBR, pt_PT: pt-rPT, nb_NO: nb, zh-Hans: zh-rCN, zh-Hant: zh-rTW
lang_map = pt_BR: pt-rBR, nb_NO: nb, zh-Hans: zh-rCN, zh-Hant: zh-rTW
[o:otf:p:briar:r:google-play-full-description]
file_filter = fastlane/metadata/android/<lang>/full_description.txt

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 320 179.99999"
xml:space="preserve"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="briar-android_tv_artwork_logo_horizontal_black.svg"
width="320"
height="180"
inkscape:export-filename="C:\Users\hughi\Downloads\briar-android_tv_artwork_logo_horizontal_black.png"
inkscape:export-xdpi="95.967941"
inkscape:export-ydpi="95.967941"><metadata
id="metadata71"><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="defs69" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1366"
inkscape:window-height="705"
id="namedview67"
showgrid="false"
inkscape:zoom="2"
inkscape:cx="215.47343"
inkscape:cy="62.929329"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Ebene_1" /><style
type="text/css"
id="style3">
.st0{display:none;fill:#87C214;}
.st1{fill:#87C214;}
.st2{display:none;fill:#FFFFFF;}
.st3{fill:#95D220;}
.st4{display:none;fill:#95D220;}
</style><rect
style="opacity:1;fill:#ffffff;fill-opacity:0.98492461;stroke:none;stroke-width:0;stroke-miterlimit:1.41420996;stroke-dasharray:none;stroke-opacity:1"
id="rect3747"
width="320"
height="180"
x="0"
y="0" /><rect
style="display:none;fill:#87c214"
id="rect11"
height="43.700001"
width="43.700001"
class="st0"
y="-82.800049"
x="47.200001" /><path
class="st2"
d="m 73.2,-130 c 9.7,0 17.7,8 17.7,17.7 V 87.4 c 0,9.7 -8,17.7 -17.7,17.7 h -8.3 c -9.7,0 -17.7,-8 -17.7,-17.7 v -199.7 c 0,-9.7 7.9,-17.7 17.6,-17.7 h 8.4 m 0,-7 h -8.3 c -13.7,0 -24.7,11.1 -24.7,24.7 V 87.4 c 0,13.6 11.1,24.7 24.7,24.7 h 8.3 c 13.6,0 24.7,-11.1 24.7,-24.7 V -112.3 C 97.8,-125.9 86.8,-137 73.2,-137 Z"
id="path17"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#87c214"
id="rect25"
height="43.700001"
width="43.700001"
class="st0"
y="14.199951"
x="144.2" /><path
class="st2"
d="m 170.2,-130 c 9.7,0 17.7,8 17.7,17.7 V 87.4 c 0,9.7 -7.9,17.7 -17.7,17.7 h -8.3 c -9.7,0 -17.7,-8 -17.7,-17.7 v -199.7 c 0,-9.7 8,-17.7 17.7,-17.7 h 8.3 m 0,-7 h -8.3 c -13.6,0 -24.7,11.1 -24.7,24.7 V 87.4 c 0,13.6 11.1,24.7 24.7,24.7 h 8.3 c 13.6,0 24.7,-11.1 24.7,-24.7 v -199.7 c -0.1,-13.6 -11.1,-24.7 -24.7,-24.7 z"
id="path29"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><g
id="g3745"
transform="matrix(0.65979376,0,0,0.65979376,0,-1020.103)"><path
inkscape:connector-curvature="0"
id="path13"
d="m 64.900391,1565 c -9.7,0 -17.701172,7.9992 -17.701172,17.6992 v 22.5 h 43.601562 v -22.5 c 0,-9.7 -7.901562,-17.6992 -17.601562,-17.6992 z m 96.999999,0 c -9.7,0 -17.70117,7.9992 -17.70117,17.6992 v 119.5 h 43.60156 v -119.5 c 0,-9.7 -7.90156,-17.6992 -17.60156,-17.6992 z m -114.701171,97.8008 v 119.5 c 0,9.7 7.901172,17.6992 17.701172,17.6992 h 8.298828 c 9.7,0 17.701172,-7.9992 17.701172,-17.6992 v -119.5 z m 97.000001,97 v 22.5 c 0,9.7 8.00117,17.6992 17.70117,17.6992 h 8.29883 c 9.7,0 17.70117,-7.9992 17.70117,-17.6992 v -22.5 z"
style="fill:#87c214" /><path
inkscape:connector-curvature="0"
id="path35"
d="M 17.699219,1612.1992 C 7.9992186,1612.1992 0,1620.1004 0,1629.9004 v 8.2988 c 0,9.7 7.8992186,17.7012 17.699219,17.7012 H 137.19922 v -43.7012 z m 177.101561,0 v 43.7012 h 22.5 c 9.7,0 17.69922,-7.9012 17.69922,-17.7012 v -8.2988 c 0,-9.8 -7.99922,-17.7012 -17.69922,-17.7012 z m -177.101561,97 C 7.9992186,1709.1992 0,1717.1004 0,1726.9004 v 8.2988 c 0,9.7 7.8992186,17.7012 17.699219,17.7012 h 22.5 v -43.7012 z m 80.101562,0 v 43.7012 H 217.30078 c 9.7,0 17.69922,-8.0012 17.69922,-17.7012 v -8.2988 c 0,-9.8 -7.99922,-17.7012 -17.69922,-17.7012 z"
style="fill:#95d220" /></g><rect
style="display:none;fill:#95d220"
id="rect37"
height="43.700001"
width="43.700001"
class="st4"
y="14.199951"
x="47.200001" /><path
class="st2"
d="m 217.3,14.2 c 9.7,0 17.7,7.9 17.7,17.7 v 8.3 c 0,9.7 -8,17.7 -17.7,17.7 H 17.7 C 8,57.9 0,49.9 0,40.2 V 31.9 C 0,22.2 7.9,14.2 17.7,14.2 h 199.6 m 0,-7 H 17.7 C 4.1,7.2 -7,18.3 -7,31.9 v 8.3 c 0,13.6 11.1,24.7 24.7,24.7 h 199.7 c 13.6,0 24.7,-11.1 24.7,-24.7 V 31.9 C 242,18.2 230.9,7.2 217.3,7.2 Z"
id="path41"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#95d220"
id="rect47"
height="43.700001"
width="43.700001"
class="st4"
y="-82.800049"
x="144.2" /><path
class="st2"
d="m 217.3,-82.8 c 9.7,0 17.7,7.9 17.7,17.7 v 8.3 c 0,9.7 -8,17.7 -17.7,17.7 H 17.7 C 8,-39.1 0,-47 0,-56.8 v -8.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 h 199.6 m 0,-7 H 17.7 c -13.6,0 -24.7,11 -24.7,24.6 v 8.3 c 0,13.6 11.1,24.7 24.7,24.7 h 199.7 c 13.6,0 24.7,-11.1 24.7,-24.7 v -8.3 C 242,-78.8 230.9,-89.8 217.3,-89.8 Z"
id="path53"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><path
inkscape:connector-curvature="0"
d="m 164.94845,130.5118 v 37.0142 h 17.3299 c 8.17094,0 12.45497,-4.0911 12.45497,-10.4911 0,-4.156 -1.91138,-7.2578 -5.73332,-8.9728 v -0.083 c 2.89934,-1.7808 4.15207,-4.0233 4.15207,-7.521 0,-5.2791 -3.62408,-9.9627 -11.26806,-9.9627 z m 35.97934,0 v 37.0142 h 4.34796 v -14.8454 l -0.45977,-0.4615 h 8.76264 c 4.87623,0 7.64484,1.7133 9.424,5.5433 l 4.61191,9.7636 h 4.87655 l -5.46909,-11.5461 c -1.18614,-2.5738 -3.0974,-4.2227 -4.81061,-4.9483 v -0.083 c 4.0196,-1.0565 7.38013,-4.6856 7.38013,-9.5024 0,-7.3236 -5.66649,-10.9515 -12.45366,-10.9515 z m 36.10959,0 v 37.0142 h 4.34922 v -37.0142 z m 25.56832,0 -16.27714,37.0142 h 4.74504 l 3.95341,-8.9069 -0.19703,-0.4619 h 20.2293 l -0.19713,0.4619 3.9535,8.9069 h 4.74491 l -16.34284,-37.0142 z m 25.82985,0 v 37.0142 h 4.34912 v -14.8454 l -0.4612,-0.4615 h 8.76406 c 4.87643,0 7.64485,1.7133 9.42429,5.5433 l 4.61186,9.7636 H 320 l -5.46903,-11.5461 c -1.18594,-2.5738 -3.09737,-4.2227 -4.81072,-4.9483 v -0.083 c 4.01975,-1.0565 7.38026,-4.6856 7.38026,-9.5024 0,-7.3236 -5.6664,-10.9515 -12.45361,-10.9515 z m -119.59919,4.0908 h 12.58636 c 4.7444,0 7.24733,1.9136 7.24733,5.8723 0,3.2982 -1.97576,5.9394 -7.24733,5.9394 h -12.58636 l 0.46124,-0.4633 v -10.8868 z m 35.97962,0 h 12.32187 c 4.48085,0 7.907,1.8468 7.97296,6.7961 0,3.9585 -3.09676,6.7292 -8.43423,6.7292 h -11.8606 l 0.45977,-0.4614 v -12.6023 z m 87.44177,0 h 12.32223 c 4.54673,0 7.97414,1.8468 7.97414,6.7961 0,3.9585 -3.09683,6.7292 -8.43417,6.7292 h -11.8622 l 0.46141,-0.4614 v -12.6023 z m -27.28106,0.4616 h 0.0674 l 1.11984,3.6954 6.52328,14.8464 0.46124,0.46 h -16.27578 l 0.46131,-0.46 6.52318,-14.8464 z m -96.14033,15.4387 h 13.44199 c 5.46934,0 7.97421,2.5073 7.97421,6.532 0,4.0908 -2.30722,6.401 -7.97421,6.401 h -13.44199 l 0.46124,-0.463 V 150.966 Z"
id="path57"
style="stroke-width:0.65979397" /></svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -16,8 +16,8 @@ def getStdout = { command, defaultValue ->
}
android {
compileSdk 34
buildToolsVersion '34.0.0'
compileSdkVersion 33
buildToolsVersion '33.0.0'
packagingOptions {
doNotStrip '**/*.so'
@@ -25,18 +25,18 @@ android {
defaultConfig {
minSdkVersion 21
targetSdkVersion 34
versionCode 10514
versionName "1.5.14"
targetSdkVersion 31
versionCode 10501
versionName "1.5.1"
applicationId "org.briarproject.briar.android"
buildConfigField "String", "TorVersion", "\"$tor_version\""
vectorDrawables.useSupportLibrary = true
buildConfigField "String", "GitHash",
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
def now = (long) (System.currentTimeMillis() / 1000)
buildConfigField "Long", "BuildTimestamp",
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L"
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L"
testInstrumentationRunner 'org.briarproject.briar.android.BriarTestRunner'
testInstrumentationRunnerArguments disableAnalytics: 'true'
}
@@ -108,15 +108,16 @@ dependencies {
implementation project(':bramble-android')
implementation project(':briar-core')
// newer versions of the libraries below require compileSdk 34
implementation 'androidx.fragment:fragment:1.6.2'
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.exifinterface:exifinterface:1.3.7'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
implementation 'androidx.lifecycle:lifecycle-livedata:2.6.2'
implementation 'androidx.fragment:fragment:1.5.5'
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.exifinterface:exifinterface:1.3.6'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-livedata:2.5.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.android.material:material:1.9.0'
// check https://github.com/material-components/material-components-android/issues/3191
// before upgrading material library
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0'
// force kotlin standard lib to latest version to prevent jetifier issues
@@ -130,7 +131,7 @@ dependencies {
implementation 'com.vanniktech:emoji-google:0.9.0' // newer versions are more work to adapt
implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.1'
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
def glideVersion = '4.16.0'
def glideVersion = '4.14.2'
implementation("com.github.bumptech.glide:glide:$glideVersion") {
exclude group: 'com.android.support'
exclude module: 'disklrucache' // when there's no disk cache, we can't accidentally use it
@@ -202,7 +203,7 @@ task verifyTranslations {
}
if (translations.size() != 0)
throw new GradleException("Translations\n" + translations.join("\n")
+ "\nhave no matching value folder")
+ "\nhave no matching value folder")
// Some devices use iw instead of he for hebrew
def hebrew_legacy = project.file("src/main/res/values-iw")

View File

@@ -1,11 +1,5 @@
Briar е приложение за обменяне на съобщения, предназначено за активисти, журналисти и всички други, които имат нужда от безопасен, лесен и стабилен начин за общуване. За разлика от другите подобни приложения, Briar не използва централен сървър - съобщенията се обменят между устройствата не потребителите. За да поддържа потока на информация по време на криза Briar използва Bluetooth, Wi-Fi или карти с памет. При наличие на интернет, Briar използва мрежата на Tor и така предпазва потребителите и техните взаимоотношения от наблюдение.
Briar е приложение за обменяне на съобщения, предназначено за активисти, журналисти и всички други, които имат нужда от безопасен, лесен и стабилен начин за общуване. За разлика от другите подобни приложения, Briar може да използва Bluetooth или Wi-Fi, за да поддържа потока на информация по време на криза. При наличие на интернет, Briar използва мрежата на Tor и така предпазва потребителите и техните взаимоотношения от наблюдение.
Приложението предлага лични съобщения, групи, форуми, а също и блогове. Вградена поддръжка на мрежата на Tor. Всичко, което правите в Briar се съхранява само на устройството ви, освен ако не решите да го споделите с други потребители.
Няма реклами и проследяване. Изходният код на приложението е достъпен за преглед от всеки и е преминал професионален одит. Всички издания на Briar могат да бъдат пресъздадени и така може да бъде проверено, че публикувания изходен код точно отговаря на публикуваното тук приложение. Разработката се извършва от малък екип с нестопанска цел.
Политика за лични данни: https://briarproject.org/privacy
Ръководство: https://briarproject.org/manual
Изходен код: https://code.briarproject.org/briar/briar
Няма реклами и проследяване. Изходният код на приложението е достъпен за преглед от всеки и е преминал професионален одит. Всички издания на Briar могат да бъдат пресъздадени и така може да бъде проверено, че публикувания изходен код отговаря на публикуваното тук приложение. Разработката се извършва от малък екип с нестопанска цел.

View File

@@ -1,11 +1,5 @@
Briar ist eine Messaging-App, die für Aktivisten, Journalisten und alle anderen entwickelt wurde, die eine sichere, einfache und robuste Möglichkeit zur Kommunikation benötigen. Im Gegensatz zu herkömmlichen Messaging-Apps verlässt sich Briar nicht auf einen zentralen Server - Nachrichten werden direkt zwischen den Geräten der Benutzer synchronisiert. Wenn das Internet nicht funktioniert, kann Briar über Bluetooth, WLAN oder Speicherkarten synchronisieren und so den Informationsaustausch in Krisenzeiten aufrechterhalten. Wenn das Internet verfügbar ist, kann Briar über das Tor-Netzwerk synchronisieren und Nutzer sowie ihre Kontakte vor Überwachung schützen.
Briar ist eine Messaging-App für Aktivisten, Journalisten und jeden, der eine sichere, einfache und robuste Art der Kommunikation benötigt. Im Gegensatz zu herkömmlichen Messaging-Apps benötigt Briar keinen zentralen Server. Nachrichten werden direkt zwischen den Geräten der Benutzer ausgetauscht. Wenn das Internet ausfällt, kann Briar diese auch über Bluetooth oder WLAN austauschen, um den Informationsaustausch in einer Krise aufrecht zu erhalten. Mit einer Internetverbindung kann Briar sich über das Tor-Netzwerk synchronisieren und schützt so die Nutzer und ihre Kontakte vor Überwachung.
Die App bietet private Nachrichten, Gruppen und Foren sowie Blogs. Unterstützung für das Tor-Netzwerk ist in die App eingebaut. Alles, was du in Briar tust, wird nur auf deinem Gerät gespeichert, es sei denn, du entscheidest dich, es mit anderen Nutzern zu teilen.
Die App bietet private Nachrichten, Gruppen und Foren sowie Blogs. Die Unterstützung für das Tor-Netzwerk ist in die App integriert. Alles, was du in Briar machst, wird nur auf deinem Gerät gespeichert, es sei denn, du entscheidest dich, es mit anderen Benutzern zu teilen.
Es gibt keine Werbung und kein Tracking. Der Quellcode der App ist vollständig offen und für jeden zur Inspektion zugänglich und wurde bereits professionell überprüft. Alle Versionen von Briar sind reproduzierbar, was es möglich macht, zu überprüfen, dass der veröffentlichte Quellcode genau mit der hier veröffentlichten App übereinstimmt. Die Entwicklung erfolgt durch ein kleines gemeinnütziges Team.
Datenschutzrichtlinien: https://briarproject.org/privacy
Benutzeranleitung: https://briarproject.org/manual
Quellcode: https://code.briarproject.org/briar/briar
Es gibt keine Werbung und kein Tracking. Der Quellcode der App ist komplett offen für jeden einsehbar und wurde bereits professionell auditiert. Alle Versionen von Briar sind reproduzierbar, so dass überprüft werden kann, ob der veröffentlichte Quellcode genau mit der hier veröffentlichten App übereinstimmt. Die Entwicklung wird von einem kleinen Non-Profit-Team durchgeführt.

View File

@@ -1,11 +1,5 @@
Briar is a messaging app designed for activists, journalists, and anyone else who needs a safe, easy and robust way to communicate. Unlike traditional messaging apps, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices. If the Internet's down, Briar can sync via Bluetooth, Wi-Fi or memory cards, keeping the information flowing in a crisis. If the Internet's up, Briar can sync via the Tor network, protecting users and their relationships from surveillance.
Briar is a messaging app designed for activists, journalists, and anyone else who needs a safe, easy and robust way to communicate. Unlike traditional messaging apps, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices. If the internet's down, Briar can sync via Bluetooth or Wi-Fi, keeping the information flowing in a crisis. If the internet's up, Briar can sync via the Tor network, protecting users and their relationships from surveillance.
The app features private messages, groups and forums as well as blogs. Support for the Tor network is built into the app. Everything you do in Briar is only stored on your device unless you decide to share it with other users.
The app features private messages, groups and forums as well as blogs. Support for Tor network is built into the app. Everything you do in Briar is only stored on your device unless you decide to share it with other users.
There are no advertisements and no tracking. The source code of the app is completely open for anyone to inspect and has already been professionally audited. All releases of Briar are reproducible, making it possible to verify that the published source code exactly matches the app published here. Development is done by a small non-profit team.
Privacy policy: https://briarproject.org/privacy
User manual: https://briarproject.org/manual
Source code: https://code.briarproject.org/briar/briar
There are no advertisements and no tracking. The source code of the app is completely open for anyone to inspect and has already been professionally audited. All releases of Briar are reproducible, making it possible to verify that the published source code matches exactly the app published here. Development is done by a small non-profit team.

View File

@@ -1,11 +1,5 @@
Briar este o aplicație de mesagerie concepută pentru activiști, jurnaliști și oricine altcineva care are nevoie de o modalitate sigură, ușoară și robustă de a comunica. Spre deosebire de aplicațiile de mesagerie tradiționale, Briar nu se bazează pe un server central, ci mesajele sunt sincronizate direct între dispozitivele utilizatorilor. Dacă nu este disponibilă o conexiune la internet, Briar poate realiza sincronizarea mesajelor prin Bluetooth, Wi-Fi sau carduri de memorie, permițând schimbul de informații într-o situație de criză. Când se reface conexiunea la internet, Briar poate realiza sincronizarea prin intermediul rețelei Tor, asigurând protecția utilizatorilor și a relațiilor lor împotriva supravegherii.
Briar este o aplicație de mesagerie concepută pentru activiști, jurnaliști și oricine altcineva care are nevoie de o modalitate sigură, ușoară și robustă de a comunica. Spre deosebire de aplicațiile de mesagerie tradiționale, Briar nu se bazează pe un server central, ci mesajele sunt sincronizate direct între dispozitivele utilizatorilor. Dacă nu este disponibilă o conexiune la internet, Briar poate realiza sincronizarea mesajelor prin Bluetooth sau Wi-Fi, permițând schimbul de informații într-o situație de criză. Când se reface conexiunea la internet, Briar poate realiza sincronizarea prin intermediul rețelei Tor, asigurând protecția utilizatorilor și a relațiilor lor împotriva supravegherii.
Aplicația oferă mesaje private, grupuri și forumuri, precum și bloguri. Suportul pentru rețeaua Tor este integrat în aplicație. Tot ceea ce faceți în Briar se stochează doar pe dispozitivul dvs., cu excepția cazului în care decideți partajarea cu alți utilizatori.
Nu există reclame și nici urmărire. Codul sursă al aplicației este complet deschis pentru a fi inspectat de oricine și a fost deja auditat de specialiști. Toate versiunile Briar sunt reproductibile, ceea ce face posibilă verificarea potrivirii exacte a codului sursă publicat cu aplicația publicată aici. Dezvoltarea este realizată de o mică echipă non-profit.
Politica de intimitate: https://briarproject.org/privacy
Manualul de utilizare: https://briarproject.org/manual
Codul sursă: https://code.briarproject.org/briar/briar
Nu există reclame și nici urmărire. Codul sursă al aplicației este complet deschis pentru a fi inspectat de oricine și a fost deja auditat de specialiști. Toate versiunile Briar sunt reproductibile, ceea ce face posibilă verificarea potrivirii exacte a codului sursă publicat cu aplicația publicată aici. Dezvoltarea este realizată de o mică echipă non-profit.

View File

@@ -1,11 +1,5 @@
Briar je aplikácia na zasielanie správ určená pre aktivistov, novinárov a všetkých, ktorí potrebujú bezpečný, jednoduchý a spoľahlivý spôsob komunikácie. Na rozdiel od tradičných aplikácií na zasielanie správ, Briar sa nespolieha na centrálny server - správy sa synchronizujú priamo medzi zariadeniami používateľov. V prípade výpadku internetu sa Briar dokáže synchronizovať cez Bluetooth, Wi-Fi alebo pamäťové karty, čím udržiava tok informácií aj v krízových situáciách. Ak je internet v prevádzke, Briar sa môže synchronizovať prostredníctvom siete Tor, čím chráni používateľov a ich vzťahy pred sledovaním.
Briar je aplikácia na zasielanie správ určená pre aktivistov, novinárov a všetkých, ktorí potrebujú bezpečný, jednoduchý a spoľahlivý spôsob komunikácie. Na rozdiel od tradičných aplikácií na zasielanie správ, Briar sa nespolieha na centrálny server - správy sa synchronizujú priamo medzi zariadeniami používateľov. Ak vypadne internet, Briar sa dokáže synchronizovať cez Bluetooth alebo Wi-Fi, čím udržiava tok informácií aj v krízových situáciách. Ak internet funguje, Briar sa môže synchronizovať cez sieť Tor, čím chráni používateľov a ich vzťahy pred sledovaním.
Aplikácia poskytuje súkromné správy, skupiny a fóra, ako aj blogy. V aplikácii je zabudovaná podpora siete Tor. Všetko, čo robíte v aplikácii Briar, sa ukladá len vo vašom zariadení, pokiaľ sa to nerozhodnete zdieľať s ostatnými používateľmi.
Nie sú tu žiadne reklamy ani sledovanie. Zdrojový kód aplikácie je úplne otvorený, aby si ho mohol ktokoľvek pozrieť, a už bol profesionálne skontrolovaný. Všetky vydania aplikácie Briar sú reprodukovateľné, čo umožňuje overiť, či sa zverejnený zdrojový kód presne zhoduje s touto zverejnenou aplikáciou. Vývoj vykonáva malý neziskový tím.
Zásady ochrany osobných údajov: https://briarproject.org/privacy
Používateľská príručka: https://briarproject.org/manual
Zdrojový kód: https://code.briarproject.org/briar/briar
Nie sú tu žiadne reklamy ani sledovanie. Zdrojový kód aplikácie je úplne otvorený, aby si ho mohol ktokoľvek pozrieť a už bol profesionálne skontrolovaný. Všetky vydania aplikácie Briar sú reprodukovateľné, čo umožňuje overiť, či sa zverejnený zdrojový kód presne zhoduje s tu zverejnenou aplikáciou. Vývoj aplikácie vykonáva malý neziskový tím.

View File

@@ -1,11 +1,5 @@
Briar është një aplikacion për shkëmbim mesazhesh, i konceptuar për veprimtarë, gazetarë, dhe cilido tjetër që ka nevojë për një mënyrë të sigurt, të lehtë dhe të fuqishme komunikimi. Ndryshe nga aplikacionet tradicionale, Briar-i nuk bazohet në një shërbyes qendror - mesazhet njëkohësohen drejtpërdrejt mes pajisjeve të përdoruesve. Nëse ska Internet, Briar-i mund të bëjë njëkohësimin me Bluetooth, Wi-Fi, ose karta kujtese, duke mbajtur kështu rrjedhën e informacioneve në rast krizash. Nëse ka Internet, Briar-i mund të bëjë njëkohësimet përmes rrjetit Tor, duke i mbrojtur përdoruesit dhe marrëdhëniet e tyre nga survejimi.
Briar është një aplikacion për shkëmbim mesazhesh, i konceptuar për veprimtarë, gazetarë, dhe cilido tjetër që ka nevojë për një mënyrë të sigurt, të lehtë dhe të fuqishme komunikimi. Ndryshe nga aplikacionet tradicionale, Briar-i nuk bazohet në një shërbyes qendror - mesazhet njëkohësohen drejtpërdrejt mes pajisjeve të përdoruesve. Nëse ska internet, Briar-i mund të bëjë njëkohësimin me Bluetooth ose Wi-Fi, duke mbajtur kështu rrjedhën e informacioneve në rast krizash. Nëse ka Internet, Briar-i mund të bëjë njëkohësimet përmes rrjetit Tor, duke i mbrojtur përdoruesit dhe marrëdhëniet e tyre nga survejimi.
Aplikacioni lejon mesazhe, grupe dhe forume private, si edhe blogje. Rrjeti Tor mbulohet së brendshmi nga aplikacioni. Gjithçka që bëni në Briar depozitohet vetëm në pajisjen tuaj, veç në vendosshi ta ndani me përdorues të tjerë.
Ska reklama dhe as gjurmim. Kodi burim i aplikacionit është plotësisht i lirë që ta inspektojë cilido dhe është shqyrtuar tashmë profesionalisht. Krejt hedhjet në qarkullim të Briar-it janë të riprodhueshme, duke bërë të mundur të verifikohet se kodi burim i bërë publik përputhet saktësisht me aplikacionin e publikuar këtu. Zhvillimi bëhet nga një ekip i vogël jofitimprurës.
Rregulla privatësie: https://briarproject.org/privacy
Doracak përdoruesi: https://briarproject.org/manual
Kod burim: https://code.briarproject.org/briar/briar
Ska reklama dhe as gjurmim. Kodi burim i aplikacionit është plotësisht i lirë që ta inspektojë cilido dhe është shqyrtuar tashmë profesionalisht. Krejt hedhjet në qarkullim të Briar-it janë të riprodhueshme, duke bërë të mundur të verifikohet se kodi burim i bërë publik përputhet plotësisht me aplikacionin e publikuar këtu. Zhvillimi bëhet nga një ekip i vogël jofitimprurës.

View File

@@ -1,11 +1,5 @@
Briar aktivistler ve gazeteciler başta olmak üzere güvenli, kolay ve sağlam bir iletişim isteyen herkes için tasarlanmış bir ileti aktarımı sistemidir. Geleneksel ileti aktarımı sistemlerinin aksine Briar merkezi bir sunucu kullanmaz. İletiler doğrudan kullanıcıların aygıtları arasında eşleştirilir. İnternet erişimi yoksa Briar iletileri Bluetooth veya Wi-Fi üzerinden de aktarabilir ve kriz durumlarında bilgi akışını sürdürür. İnternet erişimi varken Briar iletileri Tor ağı üzerinden aktarır. Böylece kullanıcılar ve yazıştıkları kişiler izlenmekten korunmuş olur.
Briar aktivistler ve gazeteciler başta olmak üzere güvenli, kolay ve sağlam bir iletişim isteyen herkes için tasarlanmış bir ileti sistemidir. Geleneksel ileti sistemlerinin aksine Briar merkezi bir sunucu kullanmaz, iletiler doğrudan kullanıcıların aygıtları arasında eşleştirilir. Briar, eğer İnternet yoksa Bluetooth veya Wi-Fi aracılığıyla da iletileri iletebilir, böylece kriz durumlarında bilgi akışını sürdürür. İnternet varken Briar Tor ağı aracılığıyla iletim sağlar, böylece kullanıcıları ve ilkilerini gözetimden korumuş olur.
Bu uygulamada özel iletiler, gruplar, forumlar ve günlük özellikleri bulunur. Tor ağı desteği uygulama ile bütünleştirilmiştir. Briar üzerinde yaptığınız her şey, siz başka kullanıcılarla paylaşmayı seçmediğiniz sürece, yalnızca kendi aygıtınızda tutulur.
Bu uygulama özel iletiler, gruplar ve forumlarla birlikte blog özelliklerine sahiptir. Tor ağı desteği uygulamada gömülüdür. Briar üzerinde yaptığınız her şey, siz başka kullanıcılarla paylaşmayı seçmediğiniz sürece, sadece kendi aygıtınızda saklanır.
Reklam yok, izleme yok. Uygulamanın kaynak kodu, incelemek isteyen herkese açıktır ve profesyonel uzmanlar tarafından da denetlenmiştir. Tüm Briar sürümleri yeniden üretilebilir. Böylece yayınlanmış kaynak kodunun, burada yayınlanan uygulamayla bire bir aynı olduğu doğrulanabilir. Uygulama kâr amacı gütmeyen küçük bir ekip tarafından geliştirilmektedir.
Gizlilik ilkesi: https://briarproject.org/privacy
Kullanım rehberi: https://briarproject.org/manual
Kaynak kodu: https://code.briarproject.org/briar/briar
Ne reklam var, ne de sizi izleme. Uygulamanın kaynak kodu, incelemek isteyen herkese tamamen ıktır ve zaten profesyonel olarak da denetlenmiştir. Briar'ın tüm sürümleri yeniden üretilebilir, böylece yayınlanan kaynak kodun, burada yayınlanan uygulamayla tam olarak eşlendiğini doğrulamak mümkündür. Uygulama kâr amacı gütmeyen küçük bir ekip tarafından geliştirilmektedir.

View File

@@ -1 +1 @@
Güvenli ileti gönderimi, her yerde.
Güvenli mesajlaşma, nerede olursa olsun.

View File

@@ -12,14 +12,13 @@
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission
android:name="android.permission.NEARBY_WIFI_DEVICES"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="31" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@@ -31,24 +30,16 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission-sdk-23
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="32" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" />
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission
android:name="android.permission.HIDE_OVERLAY_WINDOWS"
tools:targetApi="31" />
<application
android:name="org.briarproject.briar.android.BriarApplicationImpl"
android:allowBackup="false"
android:banner="@mipmap/tv_banner"
android:dataExtractionRules="@xml/backup_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher_round"
@@ -70,8 +61,7 @@
<service
android:name="org.briarproject.briar.android.BriarService"
android:exported="false"
android:foregroundServiceType="connectedDevice|dataSync">
android:exported="false">
<intent-filter>
<action android:name="org.briarproject.briar.android.BriarService" />
</intent-filter>
@@ -112,12 +102,12 @@
<activity
android:name="org.briarproject.briar.android.login.StartupActivity"
android:exported="false"
android:theme="@style/BriarTheme.NoActionBar" />
android:label="@string/app_name" />
<activity
android:name="org.briarproject.briar.android.account.SetupActivity"
android:exported="false"
android:theme="@style/BriarTheme.NoActionBar" />
android:label="@string/setup_title" />
<activity
android:name="org.briarproject.briar.android.splash.SplashScreenActivity"
@@ -128,6 +118,7 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>

View File

@@ -27,7 +27,7 @@ class BriarAccountManager extends AndroidAccountManager {
super.deleteAccount();
Localizer.reinitialize();
UiUtils.setTheme(appContext,
appContext.getString(R.string.pref_theme_system_value));
appContext.getString(R.string.pref_theme_light_value));
}
}
}

View File

@@ -33,7 +33,6 @@ import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
import static org.briarproject.briar.android.settings.DisplayFragment.PREF_THEME;
public class BriarApplicationImpl extends Application
implements BriarApplication {
@@ -110,11 +109,11 @@ public class BriarApplicationImpl extends Application
}
private void setTheme(Context ctx, SharedPreferences prefs) {
String theme = prefs.getString(PREF_THEME, null);
String theme = prefs.getString("pref_key_theme", null);
if (theme == null) {
// set default value
theme = getString(R.string.pref_theme_system_value);
prefs.edit().putString(PREF_THEME, theme).apply();
theme = getString(R.string.pref_theme_light_value);
prefs.edit().putString("pref_key_theme", theme).apply();
}
// set theme
UiUtils.setTheme(ctx, theme);

View File

@@ -22,7 +22,6 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.briar.R;
import org.briarproject.briar.android.logout.HideUiActivity;
import org.briarproject.briar.api.android.AndroidNotificationManager;
@@ -175,8 +174,7 @@ public class BriarService extends Service {
filter.addAction(ACTION_SHUTDOWN);
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF");
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF");
AndroidUtils.registerReceiver(getApplicationContext(), receiver,
filter);
registerReceiver(receiver, filter);
}, "LifecycleStartup");
}
@@ -217,14 +215,17 @@ public class BriarService extends Service {
@Override
public void onDestroy() {
super.onDestroy();
LOG.info("Destroyed");
// Stop the lifecycle, if not already stopped
shutdown(false);
stopForeground(true);
if (receiver != null) {
getApplicationContext().unregisterReceiver(receiver);
}
// Hold a wake lock during shutdown
wakeLockManager.runWakefully(() -> {
super.onDestroy();
LOG.info("Destroyed");
stopForeground(true);
if (receiver != null) unregisterReceiver(receiver);
// Stop the services in a background thread
wakeLockManager.executeWakefully(() -> {
if (started) lifecycleManager.stopServices();
}, "LifecycleShutdown");
}, "LifecycleShutdown");
}
@Override
@@ -294,8 +295,8 @@ public class BriarService extends Service {
private void shutdownFromBackground() {
// Hold a wake lock during shutdown
wakeLockManager.runWakefully(() -> {
// Begin lifecycle shutdown
shutdown(true);
// Stop the service
stopSelf();
// Hide the UI
hideUi();
// Wait for shutdown to complete, then exit
@@ -330,18 +331,8 @@ public class BriarService extends Service {
/**
* Starts the shutdown process.
*/
public void shutdown(boolean stopAndroidService) {
// Hold a wake lock during shutdown
wakeLockManager.runWakefully(() -> {
// Stop the lifecycle services in a background thread,
// then stop this Android service if needed
wakeLockManager.executeWakefully(() -> {
if (started) lifecycleManager.stopServices();
if (stopAndroidService) {
androidExecutor.runOnUiThread(() -> stopSelf());
}
}, "LifecycleShutdown");
}, "LifecycleShutdown");
public void shutdown() {
stopSelf(); // This will call onDestroy()
}
public class BriarBinder extends Binder {

View File

@@ -7,27 +7,17 @@ import android.content.IntentFilter;
import android.os.PowerManager;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.briar.api.android.DozeWatchdog;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import androidx.annotation.RequiresApi;
import static android.content.Context.POWER_SERVICE;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
class DozeWatchdogImpl implements DozeWatchdog, Service {
private static final Logger LOG =
getLogger(DozeWatchdogImpl.class.getName());
private final Context appContext;
private final AtomicBoolean dozed = new AtomicBoolean(false);
private final BroadcastReceiver receiver = new DozeBroadcastReceiver();
@@ -42,18 +32,14 @@ class DozeWatchdogImpl implements DozeWatchdog, Service {
}
@Override
public void startService() {
public void startService() throws ServiceException {
if (SDK_INT < 23) return;
IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED);
if (SDK_INT >= 33) {
filter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED);
filter.addAction(ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED);
}
registerReceiver(appContext, receiver, filter);
appContext.registerReceiver(receiver, filter);
}
@Override
public void stopService() {
public void stopService() throws ServiceException {
if (SDK_INT < 23) return;
appContext.unregisterReceiver(receiver);
}
@@ -63,33 +49,9 @@ class DozeWatchdogImpl implements DozeWatchdog, Service {
@Override
public void onReceive(Context context, Intent intent) {
if (SDK_INT < 23) return;
String action = intent.getAction();
PowerManager pm =
(PowerManager) appContext.getSystemService(POWER_SERVICE);
if (ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
if (pm.isDeviceIdleMode()) dozed.set(true);
} else if (SDK_INT >= 33) {
onReceive33(action, pm);
}
}
@RequiresApi(33)
private void onReceive33(String action, PowerManager pm) {
if (ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED.equals(action)) {
if (pm.isLowPowerStandbyEnabled()) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("System is in low power standby mode");
}
dozed.set(true);
}
} else if (ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED.equals(action)) {
if (pm.isDeviceLightIdleMode()) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("System is in light idle mode");
}
dozed.set(true);
}
}
if (pm.isDeviceIdleMode()) dozed.set(true);
}
}
}

View File

@@ -49,7 +49,6 @@ import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.GET_SIGNATURES;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
@@ -208,7 +207,7 @@ class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
filter.addAction(ACTION_PACKAGE_REPLACED);
filter.addDataScheme("package");
receiver = new PackageBroadcastReceiver();
registerReceiver(app, receiver, filter);
app.registerReceiver(receiver, filter);
cachedApps = null;
});
}

View File

@@ -18,9 +18,7 @@ import javax.annotation.Nullable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.setError;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -40,27 +38,19 @@ public class AuthorNameFragment extends SetupFragment {
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
requireActivity().setTitle(getString(R.string.setup_title));
View v = inflater.inflate(R.layout.fragment_setup_author_name,
container, false);
authorNameWrapper = v.findViewById(R.id.nickname_entry_wrapper);
authorNameInput = v.findViewById(R.id.nickname_entry);
Button infoButton = v.findViewById(R.id.info_button);
nextButton = v.findViewById(R.id.next);
authorNameInput.addTextChangedListener(this);
infoButton.setOnClickListener(view ->
showOnboardingDialog(requireContext(), getHelpText()));
nextButton.setOnClickListener(this);
return v;
}
@Override
public void onStart() {
super.onStart();
hideViewOnSmallScreen(requireView().findViewById(R.id.logo));
}
@Override
public String getUniqueTag() {
return TAG;

View File

@@ -1,7 +1,6 @@
package org.briarproject.briar.android.account;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -9,7 +8,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.briarproject.briar.R;
import org.briarproject.briar.android.account.PowerView.OnCheckedChangedListener;
@@ -20,10 +18,8 @@ import androidx.annotation.Nullable;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.android.dontkillmelib.DozeUtils.getDozeWhitelistingIntent;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@MethodsNotNullByDefault
@@ -80,12 +76,6 @@ public class DozeFragment extends SetupFragment
return v;
}
@Override
public void onStart() {
super.onStart();
hideViewOnSmallScreen(requireView().findViewById(R.id.logo));
}
@Override
public String getUniqueTag() {
return TAG;
@@ -123,12 +113,7 @@ public class DozeFragment extends SetupFragment
private void askForDozeWhitelisting() {
if (getContext() == null) return;
Intent i = getDozeWhitelistingIntent(getContext());
try {
startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
} catch (ActivityNotFoundException e) {
Toast.makeText(requireContext(),
R.string.error_start_activity, LENGTH_LONG).show();
}
startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
}
@Override

View File

@@ -14,7 +14,6 @@ import androidx.annotation.UiThread;
import static org.briarproject.android.dontkillmelib.HuaweiUtils.getHuaweiProtectedAppsIntent;
import static org.briarproject.android.dontkillmelib.HuaweiUtils.protectedAppsNeedsToBeShown;
import static org.briarproject.briar.android.util.UiUtils.tryToStartActivity;
@UiThread
@NotNullByDefault
@@ -50,7 +49,7 @@ class HuaweiProtectedAppsView extends PowerView {
@Override
protected void onButtonClick() {
tryToStartActivity(getContext(), getHuaweiProtectedAppsIntent());
getContext().startActivity(getHuaweiProtectedAppsIntent());
setChecked(true);
}
}

View File

@@ -19,21 +19,12 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.annotation.Nullable;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static androidx.core.content.ContextCompat.checkSelfPermission;
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.setError;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -47,10 +38,6 @@ public class SetPasswordFragment extends SetupFragment {
private StrengthMeter strengthMeter;
private Button nextButton;
private final ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new RequestPermission(), isGranted ->
setPassword());
public static SetPasswordFragment newInstance() {
return new SetPasswordFragment();
}
@@ -59,6 +46,7 @@ public class SetPasswordFragment extends SetupFragment {
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
requireActivity().setTitle(getString(R.string.setup_password_intro));
View v = inflater.inflate(R.layout.fragment_setup_password, container,
false);
@@ -68,18 +56,17 @@ public class SetPasswordFragment extends SetupFragment {
passwordConfirmationWrapper =
v.findViewById(R.id.password_confirm_wrapper);
passwordConfirmation = v.findViewById(R.id.password_confirm);
Button infoButton = v.findViewById(R.id.info_button);
nextButton = v.findViewById(R.id.next);
ProgressBar progressBar = v.findViewById(R.id.progress);
passwordEntry.addTextChangedListener(this);
passwordConfirmation.addTextChangedListener(this);
infoButton.setOnClickListener(view ->
showOnboardingDialog(requireContext(), getHelpText()));
nextButton.setOnClickListener(this);
if (!viewModel.needToShowDozeFragment()) {
nextButton.setText(R.string.create_account_button);
int options = passwordConfirmation.getImeOptions();
passwordConfirmation.setImeOptions(options | IME_ACTION_DONE);
}
viewModel.getIsCreatingAccount()
@@ -96,12 +83,6 @@ public class SetPasswordFragment extends SetupFragment {
return v;
}
@Override
public void onStart() {
super.onStart();
hideViewOnSmallScreen(requireView().findViewById(R.id.logo));
}
@Override
public String getUniqueTag() {
return TAG;
@@ -118,27 +99,17 @@ public class SetPasswordFragment extends SetupFragment {
String password2 = passwordConfirmation.getText().toString();
boolean passwordsMatch = password1.equals(password2);
strengthMeter.setVisibility(!password1.isEmpty() ? VISIBLE : INVISIBLE);
strengthMeter
.setVisibility(password1.length() > 0 ? VISIBLE : INVISIBLE);
float strength = viewModel.estimatePasswordStrength(password1);
strengthMeter.setStrength(strength);
boolean strongEnough = strength >= QUITE_WEAK;
if (!password1.isEmpty()) {
if (strength >= STRONG) {
passwordEntryWrapper.setHelperText(
getString(R.string.password_strong));
} else if (strength >= QUITE_WEAK) {
passwordEntryWrapper.setHelperText(
getString(R.string.password_quite_strong));
} else {
passwordEntryWrapper.setHelperTextEnabled(false);
}
}
setError(passwordEntryWrapper, getString(R.string.password_too_weak),
!password1.isEmpty() && !strongEnough);
password1.length() > 0 && !strongEnough);
setError(passwordConfirmationWrapper,
getString(R.string.passwords_do_not_match),
!password2.isEmpty() && !passwordsMatch);
password2.length() > 0 && !passwordsMatch);
boolean enabled = passwordsMatch && strongEnough;
nextButton.setEnabled(enabled);
@@ -150,18 +121,6 @@ public class SetPasswordFragment extends SetupFragment {
IBinder token = passwordEntry.getWindowToken();
Object o = requireContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
if (SDK_INT >= 33 &&
checkSelfPermission(requireContext(), POST_NOTIFICATIONS) !=
PERMISSION_GRANTED) {
// this calls setPassword() when it returns
requestPermissionLauncher.launch(POST_NOTIFICATIONS);
} else {
setPassword();
}
}
private void setPassword() {
viewModel.setPassword(passwordEntry.getText().toString());
}
}

View File

@@ -36,7 +36,7 @@ public class SetupActivity extends BaseActivity
@Inject
ViewModelProvider.Factory viewModelFactory;
private SetupViewModel viewModel;
SetupViewModel viewModel;
@Override
public void injectActivity(ActivityComponent component) {
@@ -71,16 +71,16 @@ public class SetupActivity extends BaseActivity
}
}
private void showPasswordFragment() {
void showPasswordFragment() {
showNextFragment(SetPasswordFragment.newInstance());
}
@TargetApi(23)
private void showDozeFragment() {
void showDozeFragment() {
showNextFragment(DozeFragment.newInstance());
}
private void showApp() {
void showApp() {
Intent i = new Intent(this, ENTRY_ACTIVITY);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME |
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_CLEAR_TOP);

View File

@@ -1,8 +1,6 @@
package org.briarproject.briar.android.account;
import android.annotation.SuppressLint;
import android.app.KeyguardManager;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
@@ -30,7 +28,6 @@ import static android.hardware.biometrics.BiometricPrompt.BIOMETRIC_ERROR_CANCEL
import static android.hardware.biometrics.BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED;
import static android.os.Build.VERSION.SDK_INT;
import static android.view.View.INVISIBLE;
import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_KEYGUARD_UNLOCK;
import static org.briarproject.briar.android.util.UiUtils.hasKeyguardLock;
import static org.briarproject.briar.android.util.UiUtils.hasUsableFingerprint;
@@ -114,7 +111,6 @@ public class UnlockActivity extends BaseActivity {
}
@Override
@SuppressLint("MissingSuperCall")
public void onBackPressed() {
moveTaskToBack(true);
}
@@ -195,12 +191,7 @@ public class UnlockActivity extends BaseActivity {
unlock();
} else {
keyguardShown = true;
try {
startActivityForResult(intent, REQUEST_KEYGUARD_UNLOCK);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.error_start_activity, LENGTH_LONG)
.show();
}
startActivityForResult(intent, REQUEST_KEYGUARD_UNLOCK);
overridePendingTransition(0, 0);
}
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.account;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Toast;
@@ -61,12 +60,12 @@ class XiaomiLockAppsView extends PowerView {
getContext().startActivity(getXiaomiLockAppsIntent());
setChecked(true);
return;
} catch (SecurityException | ActivityNotFoundException e) {
} catch (SecurityException e) {
logException(LOG, WARNING, e);
Toast.makeText(getContext(),
R.string.dnkm_xiaomi_lock_apps_error_toast,
LENGTH_LONG).show();
}
Toast.makeText(getContext(),
R.string.dnkm_xiaomi_lock_apps_error_toast,
LENGTH_LONG).show();
// Let the user continue with setup
setChecked(true);
}

View File

@@ -101,8 +101,6 @@ public abstract class BaseActivity extends AppCompatActivity
// unlock screen is shown.
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
if (SDK_INT >= 31) getWindow().setHideOverlayWindows(true);
for (ActivityLifecycleController alc : lifecycleControllers) {
alc.onActivityCreate(this);
}

View File

@@ -1,13 +1,9 @@
package org.briarproject.briar.android.activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.transition.Transition;
import android.view.Window;
import android.widget.CheckBox;
import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.Wakeful;
@@ -38,12 +34,9 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Build.VERSION.SDK_INT;
import static android.widget.Toast.LENGTH_LONG;
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.android.dontkillmelib.DozeUtils.getDozeWhitelistingIntent;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_UNLOCK;
@@ -179,20 +172,14 @@ public abstract class BriarActivity extends BaseActivity {
}
protected void showDozeDialog(@StringRes int message) {
MaterialAlertDialogBuilder b =
new MaterialAlertDialogBuilder(this, R.style.BriarDialogTheme);
AlertDialog.Builder b =
new AlertDialog.Builder(this, R.style.BriarDialogTheme);
b.setMessage(message);
b.setView(R.layout.checkbox);
b.setPositiveButton(R.string.fix,
(dialog, which) -> {
Intent i = getDozeWhitelistingIntent(BriarActivity.this);
try {
startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
} catch (ActivityNotFoundException e) {
logException(LOG, WARNING, e);
Toast.makeText(this, R.string.error_start_activity,
LENGTH_LONG).show();
}
startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
dialog.dismiss();
});
b.setNegativeButton(R.string.cancel,

View File

@@ -10,8 +10,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
@@ -29,6 +27,7 @@ import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView.LayoutManager;
@@ -221,8 +220,8 @@ public class BlogFragment extends BaseFragment
}
private void showDeleteDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
requireContext(), R.style.BriarDialogTheme);
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.blogs_remove_blog));
builder.setMessage(
getString(R.string.blogs_remove_blog_dialog_message));

View File

@@ -4,8 +4,6 @@ import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BaseActivity;
@@ -15,6 +13,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
@@ -52,8 +51,8 @@ public class RssFeedDeleteFeedDialogFragment extends DialogFragment {
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
GroupId groupId = new GroupId(
requireNonNull(requireArguments().getByteArray(GROUP_ID)));
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
requireActivity(), R.style.BriarDialogTheme);
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity(),
R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.blogs_rss_remove_feed));
builder.setMessage(
getString(R.string.blogs_rss_remove_feed_dialog_message));

View File

@@ -4,8 +4,6 @@ import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
@@ -14,6 +12,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
@@ -48,8 +47,8 @@ public class RssFeedImportFailedDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(requireActivity(),
AlertDialog.Builder builder =
new AlertDialog.Builder(requireActivity(),
R.style.BriarDialogTheme);
builder.setMessage(R.string.blogs_rss_feeds_import_error);
builder.setNegativeButton(R.string.cancel, null);

View File

@@ -88,7 +88,6 @@ 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.INACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactPermissionManager.areEssentialPermissionsGranted;
@@ -209,7 +208,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
eventBus.addListener(this);
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
registerReceiver(getApplication(), bluetoothReceiver, filter);
getApplication().registerReceiver(bluetoothReceiver, filter);
}
@Override

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.contact.add.remote;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.os.Bundle;
@@ -21,7 +20,6 @@ import org.briarproject.briar.android.view.InfoView;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import javax.annotation.Nullable;
@@ -31,12 +29,8 @@ import androidx.core.app.ShareCompat.IntentBuilder;
import androidx.lifecycle.ViewModelProvider;
import static android.content.Context.CLIPBOARD_SERVICE;
import static android.widget.Toast.LENGTH_LONG;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.LINK_REGEX;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.observeOnce;
@@ -45,7 +39,6 @@ import static org.briarproject.briar.android.util.UiUtils.observeOnce;
public class LinkExchangeFragment extends BaseFragment {
private static final String TAG = LinkExchangeFragment.class.getName();
private static final Logger LOG = getLogger(TAG);
@Inject
ViewModelProvider.Factory viewModelFactory;
@@ -123,18 +116,11 @@ public class LinkExchangeFragment extends BaseFragment {
copyButton.setEnabled(true);
Button shareButton = v.findViewById(R.id.shareButton);
shareButton.setOnClickListener(view -> {
try {
shareButton.setOnClickListener(view ->
IntentBuilder.from(requireActivity())
.setText(link)
.setType("text/plain")
.startChooser();
} catch (ActivityNotFoundException e) {
logException(LOG, WARNING, e);
Toast.makeText(requireContext(),
R.string.error_start_activity, LENGTH_LONG).show();
}
});
.startChooser());
shareButton.setEnabled(true);
InfoView infoText = v.findViewById(R.id.infoView);

View File

@@ -55,7 +55,6 @@ public class NicknameFragment extends BaseFragment {
private TextInputLayout contactNameLayout;
private TextInputEditText contactNameInput;
private BriarButton addButton;
@Override
public String getUniqueTag() {
@@ -92,7 +91,7 @@ public class NicknameFragment extends BaseFragment {
contactNameLayout = v.findViewById(R.id.contactNameLayout);
contactNameInput = v.findViewById(R.id.contactNameInput);
addButton = v.findViewById(R.id.addButton);
BriarButton addButton = v.findViewById(R.id.addButton);
addButton.setOnClickListener(view -> onAddButtonClicked());
return v;
@@ -113,7 +112,7 @@ public class NicknameFragment extends BaseFragment {
@Nullable
private String getNicknameOrNull() {
Editable text = contactNameInput.getText();
if (text == null || text.toString().trim().isEmpty()) {
if (text == null || text.toString().trim().length() == 0) {
contactNameLayout.setError(getString(R.string.nickname_missing));
contactNameInput.requestFocus();
return null;
@@ -130,10 +129,7 @@ public class NicknameFragment extends BaseFragment {
private void onAddButtonClicked() {
String name = getNicknameOrNull();
if (name == null) { // invalid nickname
addButton.reset();
return;
}
if (name == null) return; // invalid nickname
LifecycleOwner owner = getViewLifecycleOwner();
viewModel.getAddContactResult().observe(owner, result -> {

View File

@@ -4,7 +4,6 @@ import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.view.MenuItem;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import org.briarproject.bramble.api.contact.PendingContactId;
@@ -22,6 +21,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -110,7 +110,7 @@ public class PendingContactListActivity extends BriarActivity
// show warning dialog
OnClickListener removeListener = (dialog, which) ->
removePendingContact(item.getPendingContact().getId());
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(
AlertDialog.Builder builder = new AlertDialog.Builder(
PendingContactListActivity.this, R.style.BriarDialogTheme);
builder.setTitle(
getString(R.string.dialog_title_remove_pending_contact));

View File

@@ -147,7 +147,7 @@ public class BriarControllerImpl implements BriarController {
service.waitForStartup();
// Shut down the service and wait for it to shut down
LOG.info("Shutting down service");
service.shutdown(true);
service.shutdown();
service.waitForShutdown();
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting for service");

View File

@@ -19,7 +19,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import org.briarproject.bramble.api.FeatureFlags;
@@ -102,6 +101,7 @@ import javax.inject.Inject;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.ActionMenuView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
@@ -812,8 +812,8 @@ public class ConversationActivity extends BriarActivity
}
private void askToDeleteAllMessages() {
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this, R.style.BriarDialogTheme);
AlertDialog.Builder builder =
new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_delete_all_messages));
builder.setMessage(
getString(R.string.dialog_message_delete_all_messages));
@@ -892,8 +892,8 @@ public class ConversationActivity extends BriarActivity
}
String msg = join(fails, "\n\n");
// show dialog
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this, R.style.BriarDialogTheme);
AlertDialog.Builder builder =
new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(
getString(R.string.dialog_title_not_all_messages_deleted));
builder.setMessage(msg);
@@ -904,8 +904,8 @@ public class ConversationActivity extends BriarActivity
private void askToRemoveContact() {
DialogInterface.OnClickListener okListener =
(dialog, which) -> removeContact();
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(ConversationActivity.this,
AlertDialog.Builder builder =
new AlertDialog.Builder(ConversationActivity.this,
R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_delete_contact));
builder.setMessage(

View File

@@ -7,8 +7,6 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.sharing.ForumSharingStatusActivity;
@@ -22,6 +20,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;
@@ -129,7 +128,7 @@ public class ForumActivity extends
private void showUnsubscribeDialog() {
OnClickListener okListener = (dialog, which) -> viewModel.deleteForum();
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this,
AlertDialog.Builder builder = new AlertDialog.Builder(this,
R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_leave_forum));
builder.setMessage(getString(R.string.dialog_message_leave_forum));

View File

@@ -13,18 +13,15 @@ import androidx.recyclerview.widget.ListAdapter;
@NotNullByDefault
class ForumListAdapter extends ListAdapter<ForumListItem, ForumViewHolder> {
private final ForumListViewModel viewModel;
ForumListAdapter(ForumListViewModel viewModel) {
ForumListAdapter() {
super(new ForumListCallback());
this.viewModel = viewModel;
}
@Override
public ForumViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_item_forum, parent, false);
return new ForumViewHolder(v, viewModel);
return new ForumViewHolder(v);
}
@Override

View File

@@ -40,7 +40,7 @@ public class ForumListFragment extends BaseFragment implements
private ForumListViewModel viewModel;
private BriarRecyclerView list;
private Snackbar snackbar;
private ForumListAdapter adapter;
private final ForumListAdapter adapter = new ForumListAdapter();
@Inject
ViewModelProvider.Factory viewModelFactory;
@@ -54,7 +54,6 @@ public class ForumListFragment extends BaseFragment implements
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(ForumListViewModel.class);
adapter = new ForumListAdapter(viewModel);
}
@Nullable

View File

@@ -1,7 +1,6 @@
package org.briarproject.briar.android.forum;
import android.app.Application;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
@@ -16,7 +15,6 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.R;
import org.briarproject.briar.android.viewmodel.DbViewModel;
import org.briarproject.briar.android.viewmodel.LiveResult;
import org.briarproject.briar.api.android.AndroidNotificationManager;
@@ -42,7 +40,6 @@ import androidx.annotation.UiThread;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@@ -183,17 +180,4 @@ class ForumListViewModel extends DbViewModel implements EventListener {
return numInvitations;
}
void deleteForum(GroupId groupId) {
runOnDbThread(() -> {
try {
Forum f = forumManager.getForum(groupId);
forumManager.removeForum(f);
androidExecutor.runOnUiThread(() -> Toast
.makeText(getApplication(), R.string.forum_left_toast,
LENGTH_SHORT).show());
} catch (DbException e) {
handleException(e);
}
});
}
}

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